Netty의 네트워크 통신 과정에서 각 컴포넌트가 어떤 단계에서 어떤 역할을 하는지 상세히 설명하겠습니다.
전체 프로세스 개요
Netty의 네트워크 통신은 크게 다음 단계로 진행됩니다:
- 서버 초기화 및 바인딩
- 클라이언트 연결 수락
- 데이터 수신 처리 (인바운드)
- 데이터 송신 처리 (아웃바운드)
- 연결 종료
1. 서버 초기화 및 바인딩 단계
ServerBootstrap
- 역할: 서버 설정의 중앙 집중화
- 수행 작업:
- EventLoopGroup 설정 (Boss와 Worker 그룹)
- 서버 채널 클래스 지정 (NioServerSocketChannel)
- 채널 옵션 설정 (SO_BACKLOG, SO_REUSEADDR 등)
- 초기 ChannelHandler 등록
ServerBootstrap bootstrap = new ServerBootstrap()
.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer<SocketChannel>() {
// 새로운 연결마다 파이프라인 설정
});
Boss EventLoopGroup
- 역할: 새로운 클라이언트 연결 수락 전담
- 수행 작업:
- 서버 소켓에서 Accept 이벤트 감지
- 새로운 클라이언트 채널 생성
- Worker EventLoop에 채널 등록
2. 클라이언트 연결 수락 단계
ServerSocketChannel (서버 채널)
- 역할: 클라이언트 연결을 받아들이는 서버 소켓 추상화
- 수행 작업:
- 포트 바인딩
- 클라이언트 연결 대기
- 새로운 SocketChannel 생성
SocketChannel (클라이언트 채널)
- 역할: 개별 클라이언트와의 통신 채널
- 수행 작업:
- Worker EventLoop에 등록
- ChannelPipeline 초기화
- 읽기/쓰기 이벤트 처리 준비
Worker EventLoopGroup
- 역할: 실제 I/O 작업 처리
- 수행 작업:
- 등록된 채널들의 I/O 이벤트 감지
- 채널별 ChannelHandler 호출
- 하나의 EventLoop는 여러 채널 담당 가능
3. 데이터 수신 처리 (인바운드) 단계
EventLoop
- 역할: I/O 이벤트 감지 및 처리 조율
- 수행 작업:
- Selector를 통해 읽기 이벤트 감지
- 해당 채널의 파이프라인에 이벤트 전달
- 순차적 이벤트 처리 보장
ChannelPipeline
- 역할: 인바운드 이벤트의 처리 흐름 관리
- 수행 작업:
- Head에서 Tail 방향으로 이벤트 전파
- 각 핸들러에 순차적으로 이벤트 전달
- 핸들러 체인 관리
ByteBuf
- 역할: 네트워크에서 수신한 바이트 데이터 저장
- 수행 작업:
- 소켓에서 읽은 원시 바이트 데이터 저장
- 읽기/쓰기 인덱스를 통한 효율적 데이터 접근
- 메모리 풀링을 통한 성능 최적화
ChannelInboundHandler (순서대로 실행)
1. ByteToMessageDecoder (디코더)
- 역할: 바이트 스트림을 의미있는 메시지 객체로 변환
- 수행 작업:
ByteBuf → 프로토콜별 메시지 객체 예: HTTP 요청, JSON 객체, 커스텀 프로토콜 메시지
2. MessageToMessageDecoder (추가 디코딩)
- 역할: 1차 디코딩된 메시지를 더 상위 레벨 객체로 변환
- 수행 작업:
기본 메시지 객체 → 비즈니스 로직용 객체 예: JSON 문자열 → POJO 객체
3. Business Logic Handler
- 역할: 실제 비즈니스 로직 처리
- 수행 작업:
- 메시지 검증
- 비즈니스 로직 실행
- 응답 메시지 생성
- 다음 핸들러로 응답 전달
4. 데이터 송신 처리 (아웃바운드) 단계
ChannelPipeline
- 역할: 아웃바운드 이벤트의 처리 흐름 관리
- 수행 작업:
- Tail에서 Head 방향으로 이벤트 전파 (인바운드와 반대)
- 각 아웃바운드 핸들러에 순차적으로 이벤트 전달
ChannelOutboundHandler (역순으로 실행)
1. Business Logic Handler
- 역할: 응답 메시지 생성 및 전송 시작
- 수행 작업:
ctx.writeAndFlush(responseMessage);
2. MessageToMessageEncoder
- 역할: 고수준 객체를 중간 형태로 변환
- 수행 작업:
비즈니스 객체 → 프로토콜 메시지 예: POJO 객체 → JSON 문자열
3. MessageToByteEncoder
- 역할: 메시지 객체를 바이트 스트림으로 변환
- 수행 작업:
프로토콜 메시지 → ByteBuf 예: HTTP 응답 → 바이트 배열
Channel
- 역할: 실제 네트워크 소켓으로 데이터 전송
- 수행 작업:
- ByteBuf의 데이터를 소켓에 쓰기
- 운영체제의 송신 버퍼로 데이터 전달
5. 연결 종료 단계
EventLoop
- 역할: 연결 종료 이벤트 감지 및 처리
- 수행 작업:
- 소켓 연결 끊김 감지
- channelInactive 이벤트 발생
ChannelHandler
- 역할: 정리 작업 수행
- 수행 작업:
- 리소스 해제
- 연결 상태 업데이트
- 로깅 및 모니터링
ByteBuf
- 역할: 메모리 정리
- 수행 작업:
- 참조 카운트 감소
- 메모리 풀로 반환 또는 GC 대상화
컴포넌트 간 상호작용 흐름
[클라이언트 연결]
↓
[Boss EventLoop] → 연결 수락 → [Worker EventLoop에 채널 등록]
↓
[Worker EventLoop] → I/O 이벤트 감지
↓
[ChannelPipeline] → 이벤트 전파
↓
[ByteToMessageDecoder] → 바이트를 메시지로 변환
↓
[Business Handler] → 비즈니스 로직 처리
↓
[MessageToByteEncoder] → 메시지를 바이트로 변환
↓
[Channel] → 네트워크로 응답 전송
핵심 특징
- 이벤트 기반: 모든 작업이 이벤트 발생과 처리로 진행
- 비동기 처리: I/O 작업이 블로킹되지 않음
- 파이프라인 패턴: 처리 단계가 체인으로 연결
- 스레드 안전성: 각 채널은 하나의 EventLoop에서만 처리
- 메모리 효율성: ByteBuf 풀링과 참조 카운팅으로 최적화
이러한 구조를 통해 Netty는 높은 성능과 확장성을 제공하면서도 복잡한 네트워크 프로그래밍을 단순화합니다.
'Netty' 카테고리의 다른 글
| Netty Framework 이해하기 (5부): Spring Framework와의 통합 (0) | 2025.05.25 |
|---|---|
| Netty Framework 이해하기 (4부): 성능 최적화와 모니터링 (0) | 2025.05.25 |
| Netty Framework 이해하기 (3부): WebSocket 프로토콜과 실시간 통신 (3) | 2025.05.24 |
| Netty Framework 이해하기 (2부): 핵심 컴포넌트 심층 분석 (0) | 2025.05.24 |
| Netty Framework 이해하기 (1부): 비동기 네트워크 프로그래밍의 기초 (1) | 2025.05.23 |