728x90
Java에서 소켓을 구현할 때 비동기로 작동하는지 여부는 "어떤 API를 사용하느냐"에 따라 달라집니다. Java는 역사적으로 이 문제를 해결하기 위해 세 가지 방식을 발전시켜 왔습니다.
1. Java의 세 가지 방식
① 전통적인 방식 (BIO: Blocking I/O)
처음 Java가 나왔을 때의 방식입니다. java.net.ServerSocket을 사용합니다.
- 특징: 데이터가 올 때까지 스레드가 멈춰(Blocking) 있습니다.
- 문제점: 연결이 1,000개면 스레드도 1,000개가 필요합니다. 스레드가 너무 많아지면 메모리가 부족해지고 성능이 급격히 떨어집니다. (비유: 손님 한 명당 점원 한 명이 붙어서 아무것도 못 하고 기다리는 식당)
② 현대적인 방식 (NIO: Non-blocking I/O) — 비동기적 처리
Java 1.4부터 도입된 java.nio 패키지입니다.
- 특징: 소켓 연결은 계속 유지되지만, 데이터가 왔을 때만 스레드가 반응합니다.
- 핵심 요소: Selector라는 관리자가 여러 소켓을 관찰하다가, 패킷이 도착한 소켓만 골라 처리합니다.
- Node.js와의 유사성: Express(Node.js)의 이벤트 기반 방식과 가장 유사하게 동작합니다.
③ 비동기 방식 (AIO: Asynchronous I/O)
Java 7부터 도입되었습니다. AsynchronousServerSocketChannel을 사용합니다.
- 특징: I/O 작업이 완료되면 운영체제가 프로그램에게 "다 끝났어!"라고 알려줍니다(Callback). 가장 진보된 비동기 방식입니다.
2. Java 코드 예시 (Blocking vs Non-blocking)
[전통적인 Blocking 방식]
보통 한 클라이언트당 스레드 하나를 새로 만들어 비동기처럼 보이게 흉내를 냅니다.
ServerSocket server = new ServerSocket(8080);
while(true) {
Socket socket = server.accept(); // 여기서 멈춤(Blocking)
// 새로운 스레드를 생성하여 비동기처럼 처리
new Thread(() -> {
// 데이터 읽기/쓰기
}).start();
}
[현대적인 NIO 방식 (Netty 라이브러리 등)]
실무에서 Java로 고성능 소켓 서버를 만들 때는 Netty라는 라이브러리를 거의 표준처럼 사용합니다. Netty는 내부적으로 NIO를 사용하여 매우 효율적인 비동기 처리를 지원합니다.
3. Node.js(Express) vs Java의 결정적 차이
- Node.js: 태생부터 싱글 스레드 + 비동기입니다. 개발자가 딱히 설정하지 않아도 소켓 통신이 비동기로 흘러갑니다.
- Java: 기본은 멀티 스레드 + 동기(Blocking) 중심이었으나, NIO와 AIO를 통해 강력한 비동기 기능을 제공합니다. 대규모 기업용 시스템에서는 Java의 멀티 스레드 비동기 처리가 더 안정적일 때가 많습니다.
요약
"Java에서도 비동기로 작동하나요?"에 대한 답은 "네, 하지만 그렇게 짜야만(NIO/AIO 사용) 합니다."입니다. 전통적인 방식으로 짜면 동기식으로 작동하여 서버 성능에 한계가 올 수 있습니다.
728x90
'기술 학습' 카테고리의 다른 글
| Claude를 백엔드 API 개발에 효율적으로 활용하는 완벽 가이드 (0) | 2026.02.10 |
|---|---|
| Java에서는 비동기 대신 가상 스레드 (0) | 2026.02.09 |
| 소켓(socket)은 비동기로 작동 (0) | 2026.02.09 |
| express로 socket 사용 방법 (0) | 2026.02.09 |
| 소켓(Socket)과 패킷(Packet)의 관계 (0) | 2026.02.09 |