denny 2025. 4. 2. 11:34

Netty에서는 LZ4를 공식적으로 지원하는 Lz4FrameEncoderLz4FrameDecoder 클래스를 제공해.
이를 사용하면 MMORPG 서버에서 실시간 패킷 압축을 쉽게 적용할 수 있어.


📌 Netty에서 LZ4 압축 적용 예제

Netty 서버와 클라이언트 모두 LZ4 압축을 적용하는 핸들러를 추가해야 해.

1️⃣ Maven 또는 Gradle에 Netty LZ4 추가

Maven:

<dependency>
    <groupId>io.netty</groupId>
    <artifactId>netty-codec-compression</artifactId>
    <version>4.1.104.Final</version>
</dependency>

Gradle:

implementation 'io.netty:netty-codec-compression:4.1.104.Final'

2️⃣ Netty 서버 코드 (LZ4 적용)

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.compression.Lz4FrameDecoder;
import io.netty.handler.codec.compression.Lz4FrameEncoder;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.util.CharsetUtil;

public class Lz4NettyServer {
    public static void main(String[] args) throws Exception {
        EventLoopGroup bossGroup = new NioEventLoopGroup(1);
        EventLoopGroup workerGroup = new NioEventLoopGroup();

        try {
            ServerBootstrap b = new ServerBootstrap();
            b.group(bossGroup, workerGroup)
             .channel(NioServerSocketChannel.class)
             .childHandler(new ChannelInitializer<SocketChannel>() {
                 @Override
                 protected void initChannel(SocketChannel ch) {
                     ChannelPipeline p = ch.pipeline();
                     
                     // LZ4 압축/해제 핸들러 추가
                     p.addLast(new Lz4FrameEncoder());
                     p.addLast(new Lz4FrameDecoder());

                     // 문자열 인코딩/디코딩
                     p.addLast(new StringDecoder(CharsetUtil.UTF_8));
                     p.addLast(new StringEncoder(CharsetUtil.UTF_8));

                     // 비즈니스 로직 핸들러
                     p.addLast(new SimpleChannelInboundHandler<String>() {
                         @Override
                         protected void channelRead0(ChannelHandlerContext ctx, String msg) {
                             System.out.println("Received: " + msg);
                             ctx.writeAndFlush("Server Response: " + msg);
                         }
                     });
                 }
             });

            ChannelFuture f = b.bind(8080).sync();
            System.out.println("Netty LZ4 Server started on port 8080");
            f.channel().closeFuture().sync();
        } finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }
}

3️⃣ Netty 클라이언트 코드 (LZ4 적용)

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.compression.Lz4FrameDecoder;
import io.netty.handler.codec.compression.Lz4FrameEncoder;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.util.CharsetUtil;

public class Lz4NettyClient {
    public static void main(String[] args) throws Exception {
        EventLoopGroup group = new NioEventLoopGroup();
        
        try {
            Bootstrap b = new Bootstrap();
            b.group(group)
             .channel(NioSocketChannel.class)
             .handler(new ChannelInitializer<SocketChannel>() {
                 @Override
                 protected void initChannel(SocketChannel ch) {
                     ChannelPipeline p = ch.pipeline();

                     // LZ4 압축/해제 핸들러 추가
                     p.addLast(new Lz4FrameEncoder());
                     p.addLast(new Lz4FrameDecoder());

                     // 문자열 인코딩/디코딩
                     p.addLast(new StringDecoder(CharsetUtil.UTF_8));
                     p.addLast(new StringEncoder(CharsetUtil.UTF_8));

                     // 클라이언트 응답 핸들러
                     p.addLast(new SimpleChannelInboundHandler<String>() {
                         @Override
                         protected void channelRead0(ChannelHandlerContext ctx, String msg) {
                             System.out.println("Server says: " + msg);
                         }

                         @Override
                         public void channelActive(ChannelHandlerContext ctx) {
                             ctx.writeAndFlush("Hello, Server! This is LZ4 compressed.");
                         }
                     });
                 }
             });

            ChannelFuture f = b.connect("localhost", 8080).sync();
            f.channel().closeFuture().sync();
        } finally {
            group.shutdownGracefully();
        }
    }
}

🔥 결과 확인

  1. 서버 실행: Lz4NettyServer 실행
  2. 클라이언트 실행: Lz4NettyClient 실행
  3. 콘솔 출력 예시:
  4. Server says: Server Response: Hello, Server! This is LZ4 compressed. Received: Hello, Server! This is LZ4 compressed.

💡 LZ4 압축이 MMORPG 서버에서 좋은 이유

빠른 속도 → 실시간 패킷 압축에 적합
낮은 CPU 사용량 → 서버 성능 유지 가능
간단한 Netty 적용 → Lz4FrameEncoder / Lz4FrameDecoder 추가하면 끝

Netty에서 공식 지원하는 만큼 MMORPG 서버에서 패킷 압축을 적용할 때 매우 좋은 선택이야.
이 방식으로 적용하면 MMORPG 서버에서 네트워크 트래픽 절감 + 빠른 처리가 가능해질 거야. 🚀

지금 서버 프로젝트에서 Netty를 쓰고 있어? 아니면 다른 프레임워크야? 😊