Post

[Netty] 네티란?

Netty?


Desktop View

네티는 자바 네트워크 프레임워크로서 자바환경에서 네트워크 프로그래밍을 손쉽게 할 수 있게 해주며 고성능, 고안정성의 프로그램을 만들 수 있게 해줍니다.

네트워크 어플리케이션을 그냥 자바의 소켓 프로그래밍을 통해 구현하는 것에 비해 네티의 추상화로 인해 얼마나 편하고 간결하게 자바 네트워크 프로그래밍을 할 수 있는지를 보여줍니다.

1
2
3
4
5
Client ---------------------------------------------------------Server

 Outbound        ----->  Send    (몇시에요?) ---------->         Inbound

 Inbound         <--- (오후 8) Response <-----------         Outbound

Netty? ⇒ 비동기 + 논블로킹 + 이벤트기반

동기/비동기? 블로킹/논블로킹?


동기와 비동기 개념과 블로킹과 논블로킹은 혼용하여 사용하는 경우가 있지만 엄연히 서로 다른 개념입니다.

흔히 ‘동기’ == ‘블로킹’, ‘비동기’ == ‘논블로킹’으로 헷갈리기도 합니다. 하지만 실제로는 두 개념은 서로 크게 연관관계가 없는 별개의 개념입니다.

동기/비동기


Desktop View

출처: https://deveric.tistory.com/99

동기 작업이란 작업을 수행하는 두 개 이상의 주체가 서로 동시에 수행하거나, 동시에 끝나거나, 끝나는 동시에 시작할 때를 의미합니다. 시작과 종료를 동시에 하거나, 하나의 작업이 끝나는 동시에 다른 주체가 작업을 시작하면 이는 동기 작업이라고 볼 수 있습니다.

비동기 작업두 주체가 서로의 시작, 종료 시간과는 관계 없이 별도의 수행 시작/종료 시간을 가지고 있을 때를 뜻합니다. 서로 다른 주체가 하는 작업이 자신의 작업 시작, 종료 시간과는 관계가 없을 때 비동기라고 부를 수 있습니다.

블로킹/논블로킹


블로킹과 논블로킹은 다른 작업을 수행하는 주체를 어떻게 상대하는지가 중요합니다. 자신의 작업을 하다가 다른 작업 주체가 하는 작업의 시작부터 끝까지 기다렸다가 다시 자신의 작업을 시작한다면 이는 블로킹이고, 다른 주체의 작업과 관계없이 자신의 작업을 계속한다면 이를 논블로킹이라고 할 수 있습니다.

스레드 A가 어떤 작업을 하는 다른 대상을 호출하고, 그 대상이 가져온 결과물을 받아 다시 작업을 재개하고 있습니다. 예를 들자면 Java에서 JDBC를 사용하여 DB에 질의를 날리고 결과를 받아오는 작업을 블로킹 작업이라고 부를 수 있습니다. 이와 반대로 다른 주체에게 작업을 요청하고 그 결과를 받을 때까지 기다리지 않으며 자신의 작업을 한다면 이를 논블로킹이라고 할 수 있습니다.

Desktop View

동기/비동기 + 블로킹/논블로킹 조합


Desktop View

비동기, 논블로킹 조합

‘다른 작업과 시작, 종료 시간을 맞추지 말 것’, ’다른 작업의 주체가 작업하는동안 기다리지 말 것’ 을 만족하는 비동기, 논블로킹 조합은 자원이 충분하다면 효율이 좋은 조합입니다. 자신의 작업이 멈추지도 않고, 다른 주체가 하는 작업의 결과가 나왔을 때 콜백을 설정하기도 합니다. 다른 주체에게 작업을 맡겨놓고 자신이 하던 일을 계속할 수 있기 때문에 해야 할 작업이 대규모이고, 동기가 필요하지 않을 때 효과적입니다.

  • 대규모 사용자에게 푸시메세지 전송
  • 다양한 외부 API를 한번에 호출할 때

이벤트 기반 프로그래밍


이벤트를 정의해두고 이벤트가 발생했을 때 실행될 코드를 준비합니다.

논블로킹 소켓의 Selector 를 사용한 I/O 이벤트 감지 및 처리도 이벤트 기반 프로그램의 한 종류입니다.

이벤트 기반 네트워크 프로그래밍


이벤트를 발생시키는 객체와 발생될 이벤트 종류를 정의해야 합니다.

네트워크 프로그램에서 이벤트 발생 주체는 ‘소켓’ 이며, 이벤트 종류는 소켓연결, 데이터 송수신 입니다.

Desktop View

이벤트 핸들러 == 데이터 핸들러

네티는 데이터를 소켓으로 접근하기 위해 채널에 직접 쓰기/읽기 하지 않고 데이터 핸들러를 통해 작업합니다.

  • 서버 코드를 클라이언트에서도 재사용 가능
  • 이벤트에 따라 로직 분리 -> 깔끔
  • 네티의 이벤트 핸들러는 에러 이벤트도 같이 정의 -> 에러처리 부담 낮아짐

ChannelPipeline


채널 파이프라인은 Netty 애플리케이션의 핵심이다. 각 TCP 연결에 해당하는 SocketChannel은 ChannelPipeline을 가지고 있다. 채널 파이프라인은 ChannelHandler 인스턴스의 리스트이다. 각 ChannelHandler 인스턴스들은 SocketChannel 쪽으로 데이터를 넘기거나, SocketChannel 쪽에서 데이터를 얻어온다.

Desktop View

출처: https://hbase.tistory.com/116

소켓을 통해서 SocketChannel에 들어온 데이터는 ChannelInboundHandler 체인을 거치면서 애플리케이션으로 넘어온다. 반대로 애플리케이션이 소켓을 통해 저송하려는 데이터는 ChannelOutboundHandler체인을 거치면서 처리된 후 소켓으로 넘어간다.

이 체인을 이용해서 애플리케이션이 네트워크 통신을 할 때 적당한 처리를 먼저 할 수 있다. 예를 들어 네트워크를 통해 객체를 전송하는 경우, 객체를 Netty로 넘겨주면 Channel 핸들러 체인 안쪽에서 객체를 직렬화(Serialize)하고, 필요한 경우 압축하고, 소켓을 통해 좀 더 작은 단위로 바이트 배열을 전송하는 과정을 거치게 할 수 있다.

이런 과정은 한번 Netty 프레임워크에 구현해 놓으면, 애플리케이션 개발자는 그냥 객체를 write()하는 동작만으로 전송이 가능하다.

This post is licensed under CC BY 4.0 by the author.

Comments powered by Disqus.