이전에 Controller
부분에서 @PostConstruct
어노테이션을 활용하여 Thread를 생성하여 돌리고 서버를 따로 구동하는 형태로 작성하였는데, Bean
등록을 하거나 @Component
어노테이션을 활용해서 등록하고 사용해보는 예제를 확인해보겠습니다.
Bean등록을 통한 설정
servlet-context.xml
<!-- Netty Server 등록 -->
<beans:bean id="nettyServer" class="package명.NettyServer" name="nettyServer"/>
정의한 NettyServer class파일을 등록하여 사용하면 됩니다.
@Component 어노테이션을 통한 설정
@Component
public class NettyServer {
private static final Logger logger = Logger.getLogger(NettyServer.class);
private final int SERVER_PORT = 15500;
private final TestService testService;
@Autowired
public NettyServer(TestService testService) {
this.testService = testService;
}
private int SERVER_PORT;
private ServerBootstrap sbs = new ServerBootstrap();
private EventLoopGroup bossGroup;
private EventLoopGroup workerGroup;
@PostConstruct
public void run() {
logger.info(" ============================= Netty Server Start ============================= ");
bossGroup = new NioEventLoopGroup(20);
workerGroup = new NioEventLoopGroup(20);
sbs.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.option(ChannelOption.SO_TIMEOUT, 5 * 1000)
.childOption(ChannelOption.SO_TIMEOUT, 5 * 1000)
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
// 응답없는 read상태 확인하는 Handler
ch.pipeline().addLast("idleStateHandler", new IdleStateHandler(5, 0, 0)); //아이들 상태
// 메시지 송신, 수신, 응답없는 이벤트등을 처리할 Handler
ch.pipeline().addLast("socketServerHandler", new NettyServerHandler(testService) ); //직접 동작 할 핸들러
}
});
doConnect();
}
private void doConnect() {
//서버는 Listen상태로 기다려야하는데, 톰캣이 Timeout이 발생함
//이를 방지하기 위해 Thread로 처리한다.
new Thread(new Runnable() {
@Override
public void run() {
try {
ChannelFuture future = sbs.bind(SERVER_PORT).sync();
future.channel().closeFuture().sync();
} catch (InterruptedException e) {
logger.error("InterruptedException", e);
}
}
}).start();
}
@PreDestroy
public void serverDestroy() throws InterruptedException {
logger.info("================ Netty BootStrapServer Destroy() ================");
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
sbs.group().shutdownGracefully();
}
}
xml
설정이 어렵다면 작성한 class
를 Bean
으로 등록해주는 @Component
어노테이션을 활용하면 보다 쉽게 설정이 가능합니다.
추가해주시고 service
, dao
등 설정이 필요한 부분은 생성자를 통해 주입해줍니다.
이후 @PostConstruct
어노테이션을 활용하여 ServerBootStrap
옵션을 설정하고 구동을 해줍니다.
doConnect()
함수에서 쓰레드를 생성하고 특정 포트로 바인딩하도록 설정하였는데, @PostConstruct
는 해당 함수가 끝날때까지 대기하도록 설계되어 있는데, 해당부분에서 Netty 서버는 Listen상태로 계속 기다리고 있게됩니다.
톰캣입장에서는 구동 완료되는 시간이 Timeout설정이 되어 있는데 Timeout시간이 될때까지 설정이 끝나질 않으니 Timeout 에러가 발생하게 됩니다. 이부분을 막기위해 Thread를 통해 별도로 구성을 했습니다.
마무리
아직 스프링부트 프로젝트를 제대로 해볼 일이 없어서 아직도 Legacy만 쓰고 있는데, xml의 설정이 늘 어렵고 복잡하며 헷갈린것 같습니다. 이번 글에서 주의할 점은 xml에서 Bean등록을 했다면 Component 어노테이션은 지워야하고, Component 어노테이션으로 등록을 했다면 xml에서 Bean등록을 삭제해주시면 됩니다. 둘 다 설정하여도 동작은 하겠지만 2중으로 등록되면서 오류가 발생할 수 있습니다.
'WEB > Spring' 카테고리의 다른 글
SpringBoot - 외부 프로퍼티 적용하기(application.properties) (0) | 2021.01.12 |
---|---|
SpringBoot - 인터셉터(Interceptor) 적용하기 (0) | 2021.01.08 |
Spring - 자바소스에서 프로퍼티(properties) 파일 읽기 (0) | 2020.12.10 |
Spring - 스프링에서 NettyServer 동작 후 종료시 바인딩 현상 (0) | 2020.11.25 |
Spring - 스프링 프로젝트에서 netty사용하기 (7) | 2020.09.22 |