본문 바로가기
프로그래밍/Netty Encoder & Decoder

Netty Decoder with VS Code (1)

by Flow.X 2022. 1. 6.
728x90

Netty에는 다양한 Codec이 있다.

그걸 사용하면 왠만한 모든것들을 다 처리할수가 있을정도로 잘 되어 있다.
그중 Decoder에 대해 살펴보자

Decoder들은 아래 3개를 상속받아서 구현되어 있고,  자기만의 Decoder, Encoder를 만들수도 있다.

 

ByteToMessageDecoder

여기에서 기본적으로 지원하는 디코더를 볼수 있다. 

 

ByteBuf를 내가 원하는 메시지 형태로 변경할 수 있다.
대부분 처음 수신될때 ByteBuf로 수신되기 때문에 pipeline 제일 앞쪽에 배치가 된다.

 

카페를 예를들면 

우리나라 말로 한다고 한들 팔도 사투리가 다 들어올 것이다.
그럼 팔도 사투리들을 ByteBuf로 생각하고 종업원은 경상도 사람인데 (channelHandler로 보고) 미리 경상도로 바꿔 줬으면 좋겠다라고 하면 이렇게 배치될것 같다.

channel.pipeline.addLast(new 팔도사투리를경상도사투리로());
channel.pipeline.addLast(new 경상도종업원이처리()); // 주문처리

팔도사투리를_경상도사투리로() 코드를 보면

ByteBuf형태의 msg를 받아서 경상도 사투리로 리턴되서 나온다

여기서 중요한점은 decode는 반드시 있어야 하는 함수이다.

public class 팔도사투리를_경상도사투리로() extends ByteToMessageDecoder<ByteBuf>{
    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf msg, List<Object> out) throws Exception {
        out.add(경상도사투리로(msg)); //경상도 사투리로 변환
    }
}

 

MessageToMessageDecoder

Bytebuf가 아닌 메시지를 다른 메시지로 변환할 수 있다.
여기에서 기본적으로 제공되는 디코더를 볼수 있다


다시 카페를 예로 들면, 종업원이 경상도인데 마산 사람이야.. 근데 손님은 경상도 사람인디 대구사람이네..

pipeline은 이렇게 구성되고

channel.pipeline.addLast(new 팔도사투리를_경상도사투리로());  // bytebuf -> 경상도사투리 (message)
channel.pipeline.addLast(new 대구사투리를_마산사투리로()); // 대구사투리면(message) -> 마산으로 (message)
channel.pipeline.addLast(new 마산종업원이처리()); // 주문처리

대구사투리를_마산사투리로는 이렇게 처리되겠지

public class 대구사투리를_경상도사투리로() extends ByteToMessageDecoder<경상도사투리>{
    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf msg, List<Object> out) throws Exception {
        if(msg instanceof 대구사투리){
            out.add(대구사투리를_마산사투리로(msg)); //마산사투리로 변환
        }
    }
}

 

ReplayingDecoder

ByteToMessageDecoder를 상속받아서 만들어진 Decoder로 ByteToMessageDecoder를 좀더 편하게 사용하기 위해 만들어졌다.
카페에 손님이 왔는데 이 손님이 말을 더듬어서 어디 사투리인지 모를 때 내가 알아들을 만큼 말할때까지 기다릴때 사용하면 될것같다.

public class 기다리자말끝날때까지() extends ReplyingDecoder<ByteBuf>{
    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf msg, List<Object> out) throws Exception {
        out.add(엔터키칠때까지읽자(msg));
    }
}

 

그런데 ReplayingDecoder 는 성능상에 문제를 발생시킬수도 있기 때문에 checkpoint를 사용해야 한다고 한다.
알아들을때까지에 대한 부분을 기다리기 때문인듯하다.

 

ReplayingDecoder에 checkpoint()를 넣자 

public class 기다리자말끝날때까지() extends ReplyingDecoder<ByteBuf>{

    Enum 손님말 {"말할단어수","한말"}

    int length =0;

    public 기다리자말끝날때까지(){
       checkpoint(손님말.말할단어수); // 고객 인사를 기다린다.
    }
    
    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf msg, List<Object> out) throws Exception {
      switch (state()) {
        case 손님말.말할단어수:
          length = buf.readInt(); // 고객이 말할 단어수를 읽을때까지 기다름
          checkpoint(손님말.한말); // 다음꺼는 고객이 한말이 말할단어수만큼 오겠군
          break.
        case 손님말.한말:
          ByteBuf frame = buf.readBytes(length); // 고객이 말할단어수만큼 읽는다
          checkpoint(손님말.말할단어수); //다음은 말할 단어수니깐 그걸로 초기화
          out.add(frame);
          break;
        default:
          throw new Error("Shouldn't reach here.");
     }
   }
}

 

만약 ByteToMessageDecoder 를 사용하게 된다면 아래처럼 구현될것 이다.(적당한가.. 나중에 다시보자)

public class 팔도사투리를_경상도사투리로() extends ByteToMessageDecoder<ByteBuf>{
   @Override
   protected void decode(ChannelHandlerContext ctx, ByteBuf msg, List<Object> out) throws Exception {
      if not (msg instanceof 팔도사투리 ) { // 알아 들을때까지 대기
         return;
      }
      out.add(msg);
   }
}

 

728x90

'프로그래밍 > Netty Encoder & Decoder' 카테고리의 다른 글

Netty Encoder with VSCode (1)  (0) 2022.01.10
Netty Encoder & Decoder  (0) 2022.01.10
Netty Decoder with VSCode (2)  (0) 2022.01.07
Netty Encoder with VSCode  (0) 2022.01.06