들어가기
여기서는 비동기 기반의 네트워크 프레임워크 구조에 대해서 다루려고 한다. Mina에 대해 깊숙히 분석하기 위한 목적도 아니다. 비동기 프레임워크에 대해 필요한 사항이나 고려사항에서 아는데로 다루고려 한다.
작성자: http://ospace.tistory.com/,2010.10.22 (ospace114@empal.com)
고려사항
비동기 기반이기 때문에 메시지 전달 처리에 대한 고려가 필요하다. 비동기 기반에 처리를 할 경우에는 이벤트가 필요하다. 네트워크 객체에서는 하위에 소켓과 상위 프로그램 간에 필요한 이벤트 종류를 파악해야 한다.
이벤트 종류
먼저 어떤 종류의 이벤트가 필요한지 파악해 보자. 일단 이벤트의 방향에 따라서 구분되야 한다. 즉, 소켓에서 프로그램 방향과 프로그램에서 소켓 방향이다.
프로그램에서 소켓 방향
- 연결 요청(connect, open)
- 수신대기(accept, bind)
- 종료(close)
- 즉시 종료
- 큐를 비우고 종료
- 메시지 전송(send, write)
소켓에서 프로그램 방향
- 전송완료(sent)
- 수신됨(received)
- 종료됨(closed)
- 연결됨(connected, opened)
- 연결수락됨(accepted)
- 에러발생(errored, exceptionRaised)
- 유효상태(idled): 일정시간 아무런 처리가 없음
프로그래에서 소켓 방향으로는 단순 메시지 호출로 처리하면 된다. 물론 중간에 큐를 두어서 비동기적으로 처리해도 되지만, 직접 소켓에 처리 요청을 할 수 도 있다. 각각 개별로 메소드를 생성하면 된다.
간단하게 인터페이스를 정의하면 다음과 같은 형태로 될 것이다. 각 메소드의 이름은 자신의 원하는 것으로 하면 된다.
interface ISession {
int open ( Address addr );
int bind ( Address addr );
int close ( boolean isNow );
int send ( String msg );
}
다음은 소켓에서 프로그램으로 보내는 이벤트이다. 이 경우는 대부분 비동기인 이벤트 형태로 구성이 된다. 이 경우는 이벤트를 받는다는 의미로 listener로 정의할 수 있다.
interface ISessionListener {
void sent ( Message msg );
void receved ( Message msg );
void closed ( int code );
void opened();
void accepted();
void errored ( int code );
void idle();
}
각 메소드의 인자는 필요하다면 더 추가할 수 있다. 예를 들어, 이벤트 발생 근원(source)가 들어갈 수 있다.
void send(Source src, Message msg);
이벤트 형식
이벤트의 종류도 객체로 사용할지 또는 값으로 사용할지에 따라서 객체 간의 인터페이스도 변경이 된다. 객체를 사용한다는 말은 상속구조의 구성을 갖는 것이며, 값을 사용하는 것은 일련의 값 나열을 정의하는 것이다.
이벤트 객체
이벤트 객체는 객체의 상속구조를 사용한 것이다. 그렇기에 객체 관계 등을 이용해서 유기적으로 처리하기 좋다.
class SocketEvent {}
class EventSent extend SocketEvent {}
class EventClosed extend SocketEvent {}
단점은 한번 작성된 이벤트는 삭제 변경이 힘들다는 것이다. 이외에 이해하는데 복잡할 것이며, 기타 다른 단점이 존재할 것이다.
이벤트 값
이벤트 값은 일반적인 값 나열이다. 단순 정수 값을 사용하기에 단순 명료하다.
enum SocketEvent { EventSent, EventClosed, ... }
이벤트 호출
이 벤트 호출할 때에 방법도 2가지 정도가 있다. 앞에서는 별도의 이벤트에 대해서 별도 메소드를 생성해서 이벤트 별로 호출이 된다. 다른 방법으로는 하나의 메소드만 만들고 인자로 이벤트 객체나 값을 넘기는 것이다. 전자는 앞에 예가 있기 때문에 여기서는 다루지 않고, 후자에 대한 예를 간단하게 보자.
interface ISessionListener {
void actionEvent ( SocketEvent event );
}
장 점은 추가적인 이벤트에 대해서 인터페이스가 변경되지 않는다. 쉽게 이벤트를 변경할 수 있다. 그러나 단점으로 이벤트 변경으로 인해 내부 코드를 수정해야 한다. 즉, 분기문이나 객체 식별로 이벤트 종류를 확인해서 일일히 처리해줘야한다. 그리고, 추가적인 인자값은 이벤트 객체이면 이벤트 객체 내에 저장해두던가, 아니면, 메소드에 인자를 추가하여 값을 넘겨줘야한다.
void actionEvent (SocketEvent event, Object a1, Object a2);
여기까지 해서 네트워크와 이벤트 처리 방법에 대해서 간략하게 살펴보았다. 다음은 네트워크 프레임워크를 유연하게 확장할 수 있는 구조에 대해서 살펴보자.
유연한 구조
Mina에서는 유연한 확장을 위해서 Chain-of-responsibility pattern을 사용하고 있다. 해당 패턴의 자세한 내용은 다음을 참고하기 바란다.
기 본적인 구조는 세션을 관리하는 최하단에 IoServicer가 있고, 최상단에는 요청에 대한 처리를 하는 핸들러인 IoHandler가 있다. 그리고 IoService와 IoHandler간에 이벤트와 메시지에 대한 추가 작업을 위한 IoFilter가 존재한다. 즉, IoFilter에 의해서 추가적인 작업이 유연하게 구성이된다. 예를 들어, 암호화나, 인증이나, 프로토콜, 메시지 직렬화에 대한 부분도 처리 가능하다.
IoProcess는 IoService의 통신 작업을 수행하기 위한 메시지 펌프같은 역활을 한다.
여기서 중요한 것은 IoFilter이다. 여기서는 송수신에 대해서만 예제에서 다루겠다. 연결, 종료, 에러는 다루지 않는다.
Mina에서는 이들 필터간에 호출을 조금 복잡하게 사용한다. 간략하게 클래스로 정리해보았다.
위 그림은 클래스간에 관계를 표시한 것이다. 좀 복잡하다.
필터의 연속된 구조는 EntryImpl과 NextFilter 그리고 AbstratorFilterChain에 있다. 이들이 어떻게 동작하는지 정리해보았다.
필 터 중에 특화된 필터로 프로토콜이 있다. 이는 메시지만 처리하는 것이기에 송수신 메시지에 대해서만 처리하도록 하면 된다. 이미 필요한 프로토콜을 만들어 두면 편리하게 사용할 것이다. 그리고, 각 필터에서는 다음 필터를 사용할지 여부를 스스로 판단해서 호출해야 한다. 즉 Figure 4에서 4)번 호출을 할지 여부에 따라서 다음 필터가 수행될지 여부를 결정하게 된다.
IoFilterChain을 통해서 필터을 추가, 제거가 가능하므로 유연한 필터 구성을 할 수 있다는 장점이 있다.
사 실 Mina의 필터 구조가 쉽게 이해하기는 힘들다. 일단 Chain of responsibility 패턴을 알았다고 해도, 필터 간에 호출 관계를 이해하기에는 어렵다. 그런 이유 중에 하나가 EntryImpl에서 double linked list 구조로 직접 구현했기에 자료형 관리 부분도 추가되었기 때문이다. 그리고, 내부적으로 호출되는 메소드의 인자와 외부로 호출되는 메소드의 인자를 구분하려고 했기 때문인 것 같다. 어찌되었든 한번에 이해하기는 힘든 구조임에 틀림이 없다.
기타등등
Mina 에서는 전송 요청도 하나의 메시지 형태로 비동기적으로 처리하고 있다. 전송 요청 메시지는 future 패턴와 event handler를 가지고 있어서 원하는 형태로 구성이 가능하게 되었다. 당연히 이런 전송 요청을 저장할 큐가 필요할 것이고, 이를 처리할 쓰레드가 더 필요하겠다. 물론 이런 처리는 자바의 NIO가 처리 해주겠지만...
결론
여기서는 Mina의 구조를 이용하여 chain of responsibility 패턴을 사용한 유연한 확장 구조를 살펴보았다. 사실 네트워크 프레임워크의 구조는 매우 다양하게 생성할 수 있다. 여기서 사용한 패턴도 본인이 이전에 네트워크 모듈을 작성할 때에서 사용했다. 그때 뭔가 부족한 부분을 여기서 조금 채워지는 느낌이다.
그 리고 Mina 구조에 대해서도 조금 알았다하는 정도일 것이다. 자바 환경에서 네트워크 프로그래밍이 필요하다면 Mina를 선택하는 것은 좋다고 본다. 물론 프레임워크라서 구조를 어느정도 이해하고 사용하기 까지는 조금 시간이 걸릴 것이다. 거기에 NIO까지 안다면 금상첨화이겠지만, 프레임워크라는게 이런 것을 잘 포장하는 것이에 프레임워크 사용법만 알아도 충분하리라 본다.
아직 부족한 부분이 많지만, 계속 보강될 것이라고 본다. (정말 될지는...ㅡ.ㅡ;) 모두 즐프하시길. ospace.
참조
[2] Chain-of-responsibility pattern, http://ospace.springnote.com/pages/6605427
[3] [Apache Mina] 1. Mina 구조 따라잡기, http://run4dream.tistory.com/96
[4] Mina v2.0 quick start guide, http://mina.apache.org/mina-v20-quick-start-guide.html
'2.분석 및 설계' 카테고리의 다른 글
[mybatis] Mybatis 내부동작 흐름 (0) | 2022.01.26 |
---|---|
YUV 포멧 (0) | 2021.11.15 |
MFC 메시지맵 구조 (0) | 2012.07.27 |
errno같은 리턴 에러값 프레임워크 (0) | 2012.07.26 |
함수 호출과정 분석 (0) | 2011.01.12 |