솔직히, 3Chapter 밖에 공부를 하지 않았지만, 이번챕터에서 가장 넓은 Insight(통찰력)을 얻은듯 하다.
네티는 우리가 기술과 아키텍처라고 광범위하게 이야기하는 두 관심 영역의 문제를 모두 해결한다.
-
자바 NIO 기반의 비동기식 이벤트 기반 구현을 이용해 고부하 조건에서도 애플리케이션 성능과 확장성을 보장한다.
-
네티는 애플리케이션 논리를 네트워크 레이어로부터 분리하는 다양한 설계 패턴을 활용해 코드의 테스트 용이성, 모듈성, 재사용성을 극대화해 개발을 간소화 한다.
1. Channel, EventLoop, ChannelFuture
-
Channel : 소켓 (왜 굳이 소켓을 Channel로 한번 감싼걸까..? 사용하기 편하게 하기 위해서인가.. 공부를 지속하다보면 알게되겠지..)
-
EventLoop : 제어흐름, 멀티스레딩, 동시성 제어
-
ChannelFuture : 비동기 알림
1.1 Channel 인터페이스
기본 입출력 작업(bind(), connect(), read(), write())은 기본 네트워크 전송에서 제공하는 기본형을 제공한다. 자바 기반 네트워크에서 기본 구조는 Socket 클래스인데 네티의 Channel 인터페이스는 Socket으로 직접 작업할 때의 복잡성을 크게 완화시켜주는 API를 제공한다.
1.2 EventLoop 인터페이스
EventLoop는 연결의 주명주기중 발생하는 이벤트를 처리하는 네티의 핵심 추상화를 정의한다.
다음은 Channel, EventLoop, Thread, EventLoopGroup 간의 관계를 개략적으로 보여준다.
-
한 EventLoopGroup은 하나 이상의 EventLoop를 포함한다.
-
한 EventLoop는 수명주기 동안 한 Thread로 바인딩 된다.
-
한 EventLoop에서 처리되는 모든 입출력 이벤트는 해당 전용 Thread에서 처리된다.
-
한 Channel은 수명주기 동안 한 EventLoop에 등록할 수 있다.
-
한 EventLoop를 하나 이상의 Channel로 할당할 수 있다.
1.3 ChannelFuture 인터페이스
네티의 모든 입출력 작업은 비동기적이고, 이 때문에 결과를 확인 하는 방법이 필요한데, 이러한 기능을 ChannelFuture 인터페이스가 제공한다. 이 인터페이스의 addListener() 메서드는 작업이 완료되면 알림을 받을 ChannelFutureListener 하나를 등록한다.
2 ChannelHandler와 ChannelPipeline
데이터 흐름을 관리하고, 애플리케이션의 처리 논리를 실행하는 컴포넌트
2.1 ChannelHandler 인터페이스
애플리케이션 개발자의 관점에서 네티의 핵심 컴포넌트는 인바운드와 아웃바운드 데이터의 처리에 적용되는 모든 애플리케이션 논리의 컨테이너 역할을 하는 ChannelHandler다. ChannelHandler는 데이터를 다른 포멧으로 변환하거나 작업중 발생한 예외를 처리하는 등의 작업을 할 수 있다.
2.2 ChannelPipeline 인터페이스
ChannelPIpelin은 ChannelHandler 체인을 위한 컨테이너를 제공하며, 체인상에서 인바운드와 아웃바운드를 전파하는 API를 정의한다.
-
ChannelInitializer 구현은 ServerBootstrap에 등록된다.
-
ChannelInitailizer.initChannel()이 호출되면 ChannelInitializer가 ChannelHandler의 커스텀 집합을 파이프라인에 설치한다.
-
ChannelInitializer는 ChannelPipeline에서 자신을 제거한다.
파이프라인을 통해 이벤트를 이용하는 역할은 애플리케이션의 부트스트랩 단계나 초기화 중에 설치된 ChannelHandler가 담당한다. 이들 객체는 이벤트를 수신하고, 구현된 처리 논리를 실행하며, 체인상의 다음 핸들러로 데이터를 전달한다.
실행되는 순서는 추가된 순서에 의해 결정된다. 실제로 ChannelPIpeline이라고 말할 때는 이러한 ChannelHandler의 정렬된 배치 전체를 의미한다.
인바운드 : 서버에서 클라이언트로
아웃바운드 : 클라이언트에서 서버로
네티는 ChannelInboundHandler와 ChannelOutboundHandler 의 구현을 구분하며 핸들러간의 데이터 전달이 동일한 방향으로 수행되도록 보장한다.
네티에서 메시지를 보내는 데는 Channel에 직접 기록하거나 ChannelHandler와 연결된 ChanelHandlerContext 객체에 기록하는 두 가지 방법이 있다. 전자의 방법은 ChannelPipeline의 뒤쪽에서 시작하며, 후자의 방법은 메시지가 ChannelPipeline의 다음 핸들러에서 시작한다.
2.3 ChannelHandler에 대한 고찰
ChannelHandler에는 다양한 종류가 있으며 각 기능은 상위 클래스가 무엇인지에 따라 많이 좌우된다. 네티는 애플리케이션의 논리를 쉽게 개발할 수 있게 어댑터 클래스 형태로 여러 기본 핸들러의 구현을 제공한다.
파이프라인의 각 ChannelHandler는 이벤트 체인의 다음 핸들러로 전달해야 하는데, 이러한 어댑터 클래스는 이 작업을 자동으로 해주므로 특수한 동작이 필요한 메소드와 이벤트만 재정의할 수 있다.
2.4 인코더와 디코더
네티로 메시지를 전송하거나 수신할 떄는 데이터를 변환해야 한다. 인바운드 메시지는 바이트에서 다른 포멧으로 변환되는 디코딩을 거친다. 아웃바운드 메시지는 반대로 현재 포멧에서 바이트로 인코딩해야 한다. 이러한 두가지 변환이 필요한 이유는 네트워크 데이터는 반드시 연속된 바이트여야 하기 떄문이다.
채널 핸들러를 쉽게 만들수 있게 어댑터 클래스가 있는 것처럼 네티가 제공하는 모든 인코더/디코더 클래스는 ChannelInboundHandler나 ChannelOutboundHandler를 구현한다.
2.5 SimpleChannelInboundHandler 추상클래스
애플리케이션에서는 디코딩된 메시지를 수신하고 이러한 메시지를 처리하는 핸들러를 많이 사용하는데, 이러할 경우 SimpleInboundClass<T>를 확장하면 되며 여기서 T는 처리할 메시지의 자바 형식이다.
3 부트스트랩
네티의 부트스트랩 클래스는 프로세스를 지정된 포트로 바인딩하거나 프로세스를 지정된 호스트의 지정된 포트에서 실행중인 다른 호스트로 연결하는 등의 일을 하는 애플리케이션의 네트워크 데이터를 구성하는 컨테이너를 제공한다.
움,, 프로세스간 연결을 지원하는 클랠스로 이해하도록 하겠다. 응?? 그러면 Socket이 네티에서 Channel의 개념이라고 하고 Socket도 프로세스간 연결(?)을 나타내는 것으로 이해하고 있었는데 뭐가 다른거뇨 ㅠ 모르겠다 다음 챕터부터 심화 개념이 나오니깐 넘어가도록 한다)
구분 |
BootStrap |
ServerBootstrap |
네트워크 기능 |
원격 호스트와 포트로 연결 |
로컬포트로 바인딩 |
EventLoopGroup수 |
1 |
2 |
차이점
-
서버는 연결요청을 수신하므로 ServerBootstrap을, 클라이언트는 원격피어로 연결하므로 ServerBootstrap을 이용
-
서버는 각기 다른 Channel 두개의 집합을 가진다. 첫번째집합은 로컬포트로 바인딩된 서버 자체의 수신 소켓인 ServerChannel, 두번째 집합은 서버가 수락된 연결마다 하나씩 들어오는 클라이언트 연결을 처리하기 위해 생성된 모든 Channel이다.
ServerChannel에 연결된 EventLoop그룹은 연결 요청에 대해 Channel 생성의 역할을, 수락된 두번쨰 EventLoopGroup이 해당 Channel에 EventLoop를 할당한다.
뭔가 큰그림은 잡히는데,, 아리송한 부분이 많다... 계속 공부해가면서 꺠닫도록 하쟈;; 특히 Selectotr를 사용하면 Socket의 읽기 쓰기를 단일스레드로 처리 가능한 것으로 보이는데,, 이는 자바 nio를 공부해야 할것,,
'IT > Netty' 카테고리의 다른 글
네티에서 제공하는 웹소켓관련 기능을 이용한 웹 채팅 구현 (0) | 2020.12.05 |
---|---|
네티 단위테스트를 위한 EmbeddedChannel (0) | 2020.12.03 |
네티의 전송 (0) | 2020.11.29 |
Netty로 echo서버 만들기 (0) | 2020.11.23 |