포스트

(Day 43) (GoF) 프록시 패턴과 원격 메서드 호출

Review

Socket

Socket을 이용하여 클라이언트/서버 애플리케이션을 만들기

  • Socket에 입출력 스트림을 연결하여 데이터 송수신하기
  • 인터페이스의 활용
    • 변수도 객체도 전부 인터페이스를 타입으로 쓴다. 그 인터페이스의 규칙에 따라 만든 것을 쓰겠다는 의미로, 코드의 유연성을 높이려는 목적이다.
    • 이렇게 되면 DI(Defendency Injection)를 할 수 있다. 어떤 객체던 핸들러에 주입해 줄 수 있다. 핸들러에 범용성이 부여된다.
    • 구현체를 무엇을 끼워 넣는지 자유가 생겼다. 그 자유가 없으면 무엇을 조립하느냐에 따라 다른 부분도 다 변경해줘야 했을 것이다.

Study

개선

기능추가: Client와 순차적으로 연결됨

서버가 클라이언트의 요청을 처리하고, quit 문자열을 요청으로 받은 경우 해당 연결을 종료하고 다음 연결을 받도록 코드를 변경

문제점

클라이언트 1명만 접속할 수 있으며, 접속한 클라이언트가 연결을 해제한 다음에 다음 클라이언트가 연결이 가능함.

프록시 패턴

모르는 사이에 GoF의 프록시 패턴을 적용했다.

개념

<<Caller»인 Clientr가 인터페이스를 통해 메서드를 호출하면, 실제 작업을 수행하는 객체가 아닌, 대행자(Proxy가 대행인 이라는 뜻이다.)를 통해서 호출하는 형태라면 프록시 패턴을 사용하는 것이다.

목적(이유)

Proxy를 이용하여 간접적으로 객체를 사용하는 이유는 무엇인가? 직접 사용하면 복잡한 코드를 작성해야 하는 경우 객체 사용에 대한 복잡한 코드를 캡슐화하려는 것이 목적이고 사용하는 이유이다.


예시

DAO가 그러한 예시가 된다. DAO는 Proxy이면서 Real로도 사용된다. ClientApp 은 ServerApp과 요청/응답을 반복하는데, 이 Request/Rsponse를 반복하려면 복잡한 코드가 발생한다. 요청 및 응답을 처리하기 위해 ClientApp 및 ServerApp 에서 동시에 DAO를 사용하는 경우를 생각해보자.

예를 들면 BoardDaoImpl (네트워크를 위한 DAO 구현체) 가 있다. 이 DAO는 JSON파일을 읽고 쓴다. (직접 만든 DAO이다.)

만약에 DAO가 없었다면? 아래와 같은 부분이 캡슐화되지 않고 드러났을 것이다.

  1. 서버 소켓 연결
  2. 입출력 스트림 연결
  3. 요청 데이터를 JSON으로 변환(Serialization)
  4. 변환한 데이터를 전송
  5. 응답 데이터를 수신
  6. JSON 데이터를 객체로 변환(Deserialization)

ClientApp에서 서버쪽의 DAO를 호출하기 위한 복잡한 코드를 캡슐화했다. 그 복잡한 코드는 위의 1~6까지의 내용을 처리하기 위한 코드다.

RMI (Remote Method Invocation)

원격에 존재하는 코드(ex. Method)를 호출하는 이유가 무엇인가? 다른 사람과 동시에 뭔가를 처리하지 않는, 개인용의 프로그램이라면 원격에 있는 코드를 굳이 호출하지 않아도 될 것이다. (네트워크에 연결되어서 사용되는 기능이 없는 경우) 그런데 기업용으로 사용하는 프로그램이라면, 동시에 여러 사람의 요청을 처리해야할 필요도 있을 것이며, 그를 위해 개인용 프로그램보다 더 많은 리소스를 요구하게 될 것이다. (더 높은 성능의 시스템이 요구될 것이다.)

분산 컴퓨팅

일반적으로 개인용 프로그램(메모장이나 워드, 포토샵 등등..)을 실행한다면 1대의 PC만 있으면 충분하겠지만, 적게는 수십에서 많게는 수천만의 클라이언트의 요청을 처리하는 기업용 프로그램은 그 리소스를 1대의 컴퓨터에서 처리하는게 현실적으로 불가능해진다. 그래서 그 요청을 여러대의 컴퓨터로 분산하여 처리하려는 움직임이 발생했으며, 이는 분산 컴퓨팅 기술의 발전으로 이어진다. (선택이 아니라 필수적인 기술..)

분산 컴퓨팅의 예시

분산 컴퓨팅이라 하면 하둡과 같은 솔루션이 먼저 떠오를 수도 있다. 그러한 경우 뿐만 아니라 부하가 어느정도 걸릴 수 있는 기업용 시스템은 대부분 분산컴퓨팅을 지원한다. 업무관리시스템을 생각해보자. 시스템마다 차이는 있겠지만 대부분 아래와 같은 모듈들을 가지고 있을 것이다. (기업이 조금만 커지거나, 시스템을 따로 구축하는 경우 아래 기능들이 개별적인 시스템이 되는 경우도 많지만 일단 공부를 위한 가정!!)

  1. 회계관리
  2. 인사관리
  3. 재고관리
  4. 고객관리
  5. 제조관리

이 기능들은 서로 연동도 되어야 한다. 이 관리시스템을 1대의 컴퓨터로만 처리한다면, 시스템이 처리할 수 있는 성능의 한계가 요청이 조금만 늘어도 빠르게 느껴질 것이다.

그래서 기능들을 여러 대의 컴퓨터로 분산시켜서 처리한다. 이렇게 되면 다른 컴퓨터에서 실행되는 App의 메서드를 호출하는 기술이 필요해진다. 그래서 RMI가 등장한다. 다른 (컴퓨터에서 실행되고 있는) 프로세스의 코드(ex.메서드)를 실행할 수 있게 된 것이다.

추가로 공부할 만한 내용이 있어서 아래에 링크한다. https://drcode-devblog.tistory.com/287

  • 앱과 앱간의 메모리를 직접 접근하는 것은 당연히 불가능하다. 한 컴퓨터 안에서 실행되는 두 프로세스에 대해서도 그렇다.
    • 그건 OS의 영역인데 OS는 그것을 보안상 허락해주지 않을 것이다. DOS 초기에는 다른 프로세스의 메모리를 읽어오거나 변경하는 것이 가능했고 그로 인한 보안 위험이 아주아주 컸다.
    • 그래서 다른 프로세스의 변수나 메서드를 접근할 수 없을 것이다.
  • 그래서 로컬에서 실행되는 프로세스가, 리모트에서 실행되는 다른 프로세스의 코드(메서드 등)을 실행하려면 RMI를 알아야 한다. (Local/Remote는 같은 컴퓨터라고 해도 프로세스가 다르면 사용되는 말이다. Remote Process, Local Process)
  • Local computer / Remote computer 라고 명시하지 않으면 같은 Process인지의 여부만으로 Remote/Local를 구분하는 것이다.

이전에는 이를 위해 EJB 같은 기술들을 썼는데 이제는 Restful API를 기반으로 이 요구사항을 해결하는 중이다.

리모트 코드 호출에 대한 역사

  1. RPC (Remote Procedure Call) 절차적 프로그래밍 언어(C, Pascal)에서 자주 사용된 기술 https://en.wikipedia.org/wiki/Remote_procedure_call

  2. RMI (Remote Method Invocation) 객체지향프로그래밍(OOP)의 언어(C++, Java)에서 자주 사용된 기술 특히, 이기종 플랫폼간에서 RMI를 구현하기 위한 CORBA(Comman Object Request Broker Architecture)가 등장했다. CORBA를 포함하는 RMI에서는 모두 Client - Stub ↔ Skeleton - Serivce Object 형태를 보인다.

  • EJB(Enterprise Java Bean)가 RMI - WebService 사이에 있는데 요즘은 잘 쓰지 않는다.
  1. Web Service skel은 서비스 객체를 가지고 있다. WSDL(XML 형식 등): 서비스 객체가 제공하는 메서드 정보를 담고 있다.

CORBA와 웹서비스의 차이점

Stub을 로컬에서 자동으로 생성한다는 것이다. 서비스 객체를 만드는 개발자가 stub을 제공하는 것이다. 서버측 개발자가 제공하는 stub 객체를 클라이언트 개발자는 받아와서 쓰기만 한다. WSDL(Web Service Description Language)을 보고 로컬의 IDE가 자동으로 생성한다. 서버에서 Stub을 제공하지 않고 WSDL을 제공한다.

적용의 예시

PG(Payment Gateway)사 시스템을 적용하는 경우에 해당 PG사의 메서드를 콜해야 할 것이다. 그런 웹서비스를 만드려면, 해당 PG사가 제공해주는 Stub을 가져와서 Handler로 처리하게 될 것이다. 그래서 클라이언트 개발자라면, 붙이려는 시스템의 서버 개발자가 만든 Stub을 사용하게 될 것이다. (이니시스 등..)

다른 예시로는 SNS 계정을 통해 다른 서비스에 로그인하는 경우가 있다.

반대로, 다른 시스템들이 사용하는 시스템을 위한 개발을 하는 경우 Stub, Skeleton, Remote Object를 위한 개발을 하게 될 것이다.

Stub의 단점

언어에 종속된다! 자바 스텁, C++ 스텁…

Restful Service의 등장

Rest=Represent 서비스 객체와 클라이언트 사이에 웹 서버가 개입한다. 요청과 응답을 HTTP를 통해서 하는 것이다!! 현대의 대부분의 서비스는 Restful Service이다.

클라이언트 —HTTP(요청/응답)— **웹서버** —위임/리턴— 서비스 객체

  1. 클라이언트측에 stub 역할을 하는 객체가 필요없다.
  2. 언어에 상관없이 HTTP 통신에 맞춰서 서비스 객체를 이용한다.
    • 이기종 플랫폼 간 리모트 프로세스의 코드에 대한 상호 호출이 가능하다.
    • 이기종 플랫폼: OS, Programming Language
  3. 전송 데이터 포맷은 XML, json 을 주로 사용한다. HTTP를 통해 처리할 수 있다면 어떤 포맷이던 가능하다.

나중에 아래 웹서버에 스프링부트 프레임워크가 적용될 것이다. 클라이언트 —HTTP(요청/응답)— **웹서버** —(위임/리턴)— 서비스 객체

myApp 41. 공통기능을 서브프로젝트로 분리하기

  • 클라이언트와 서버에서 공통으로 사용하는 코드를 별도의 프로젝트로 분리함
    • myapp-common 프로젝트 생성하여 공통코드를 별도 패키지로 분리한다.
  • 분리하는 경우 settings.gradle 빌드 스크립트 파일에도 알려줘야 한다.
    • 포함할 경로(프로젝트)를 include('경로명')으로 알려줘야 한다.
    • 해당 프로젝트를 빌드시에 사용할 다른 프로젝트는 build.gradle에 implements 한다고 알려줘야 한다.
      • IDE에서 자동으로 gradle 설정에 따라 Auto-import 지원되는 경우라면 상관없는데,

my-app common

공통으로 사용하는 코드들은? 서버와 클라이언트에서 둘 다 사용하는 코드들은? vo 클래스, DAO의 인터페이스들이 그 대상이 된다.

app-api

app-server 프로젝트에서 제공하는 DAO 객체의 stub을 둔다.


그래서 현재 client/server/api/common 으로 4가지로 쪼개졌다.

요약

오늘 배운 것들은 무엇인가?

  1. 원격 메서드 호출 메커니즘과 관련 용어를 배웠다.
  2. 원격 메서드 호출의 발전사를 배웠다.
    • RPC, RMI, CORBA, WebService, RESTful
  3. Gradle 빌드 도구로 여러 프로젝트를 다루는 방법

내일은 DAO Proxy Object를 자동으로 생성하는 방법을 배워볼 것이다. 지금 보면 Board, Assignment, Member 즉 VO별로 DAO를 두고 있다. 그런데 거의 유사하다. VO마다 가지고 있는 정보가 다르기 때문에 그렇다. 인터페이스를 구현하는 클래스를 자동으로 만드는 방법을 배울 것이다. 스프링 부트 프레임워크나 마이바티스에서도 이렇게 자동으로 구현클래스를 생성해준다. 그것을 java에서 어떻게 하는지 배워 볼 것이다. 그러면 인터페이스만 있으면 구현 클래스를 만드는, Stub Auto Generator를 만드는 방법을 알게 되는 것이다.

그 외

직업훈련업과 취업시장

직업훈련업계는 취업시장이 얼어붙었을수록 불탄다. 지금 직업훈련업계가 불타고 있다. 그럼 나중에 취업할 때 경쟁이 아주 심할 것이다. 기술면접에서 튀어야 뽑힌다. rmf 기술면접에서 튀려면 그 용어를 직접 말로 써보고, 글로 써봐야 한다. restful, method invocation이 나와야 한다는 것이다. 그래서 블로그도 하고 서로 물어보기도 하고 그래야 한다.

이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.