
Blocking I/O와 Non-Blocking I/O는 시스템의 성능과 효율성을 결정짓는 중요한 개념입니다. 특히, Spring WebFlux는 Non-Blocking I/O를 기반으로 설계되어 대량의 요청을 효율적으로 처리할 수 있도록 돕습니다. 이 글에서는 두 방식의 차이점과 활용 방안을 살펴보겠습니다.
1. Blocking I/O란?
Blocking I/O는 요청 스레드가 I/O 작업이 완료될 때까지 대기하는 방식입니다. 이는 간단하고 직관적이지만, 대량의 요청을 처리할 때 다음과 같은 문제를 야기합니다:
- 스레드 대기: 하나의 요청이 완료될 때까지 다른 요청은 대기 상태에 놓입니다.
- 컨텍스트 스위칭 비용: 다수의 스레드가 생성되면, CPU가 작업 전환에 많은 시간을 소비하게 됩니다.
- 자원 낭비: 유휴 상태의 스레드가 많아지면서 메모리와 CPU 자원이 비효율적으로 사용됩니다.
코드 예제: Blocking I/O
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class BlockingIOExample {
public static void main(String[] args) {
long startTime = System.currentTimeMillis();
for (int i = 0; i < 3; i++) {
readFile();
}
long endTime = System.currentTimeMillis();
System.out.println("총 소요 시간: " + (endTime - startTime) + "ms");
}
public static void readFile() {
try (BufferedReader br = new BufferedReader(new FileReader("example.txt"))) {
String line;
while ((line = br.readLine()) != null) {
// 파일 읽기 작업
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
특징: 파일 읽기가 순차적으로 진행되며, 모든 작업이 완료될 때까지 다른 요청은 대기합니다.
2. Non-Blocking I/O란?
Non-Blocking I/O는 I/O 작업 중에도 스레드가 차단되지 않고 다른 작업을 수행할 수 있는 방식입니다. 이는 적은 수의 스레드로도 많은 요청을 처리할 수 있어 효율적입니다.
주요 특징
- 요청 스레드 차단 없음: 작업이 완료될 때까지 기다리지 않고 다른 작업을 처리합니다.
- 효율적인 자원 사용: 적은 수의 스레드로도 높은 동시성을 지원합니다.
- 전 과정 Non-Blocking: 모든 요소가 Non-Blocking으로 동작해야 최대 효과를 발휘합니다.
코드 예제: Non-Blocking I/O
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.concurrent.CompletableFuture;
public class NonBlockingIOExample {
public static void main(String[] args) {
long startTime = System.currentTimeMillis();
CompletableFuture<Void> future1 = CompletableFuture.runAsync(NonBlockingIOExample::readFile);
CompletableFuture<Void> future2 = CompletableFuture.runAsync(NonBlockingIOExample::readFile);
CompletableFuture<Void> future3 = CompletableFuture.runAsync(NonBlockingIOExample::readFile);
CompletableFuture<Void> allOf = CompletableFuture.allOf(future1, future2, future3);
allOf.join(); // 모든 작업이 완료될 때까지 기다림
long endTime = System.currentTimeMillis();
System.out.println("총 소요 시간: " + (endTime - startTime) + "ms");
}
public static void readFile() {
try {
Files.lines(Paths.get("example.txt")).forEach(System.out::println);
} catch (IOException e) {
e.printStackTrace();
}
}
}
특징: 비동기 처리를 통해 여러 파일 읽기 작업이 동시에 진행됩니다.
3. Spring WebFlux와 Non-Blocking I/O
Spring WebFlux는 Non-Blocking I/O를 기반으로 설계된 프레임워크로, 다음과 같은 상황에서 효과적입니다:
- 대량의 요청 트래픽 처리
- 하나의 스레드로 다수의 요청을 처리하여 서버 자원을 효율적으로 활용합니다.
- 마이크로서비스 아키텍처
- 서비스 간 비동기 통신을 통해 응답 속도를 향상시킵니다.
- 실시간 데이터 스트리밍
- 지속적으로 데이터가 발생하는 환경에서 높은 성능을 제공합니다.
4. Non-Blocking I/O 도입 시 주의점
Non-Blocking I/O는 장점이 많지만, 다음과 같은 단점도 고려해야 합니다:
- 복잡한 코드 구조
- 비동기 프로그래밍 패턴(콜백, 프라미스 등)은 코드 가독성을 떨어뜨릴 수 있습니다.
- 디버깅 어려움
- 순차적이지 않은 실행 흐름으로 인해 오류 원인을 파악하기 어렵습니다.
- 기존 시스템과 호환성 문제
- 기존 Blocking 기반 시스템에서 전환하려면 많은 리팩토링이 필요합니다.
- CPU 바운드 작업에서 성능 저하 가능성
- CPU 중심 작업에서는 Non-Blocking 방식의 이점이 줄어듭니다.
결론
Blocking I/O와 Non-Blocking I/O는 각각의 장단점이 있으며, 시스템 요구사항에 따라 적합한 방식을 선택해야 합니다. Spring WebFlux와 같은 Non-Blocking 프레임워크는 특히 대량 요청 처리나 실시간 스트리밍 환경에서 큰 효과를 발휘합니다. 그러나 복잡한 코드 구조와 러닝 커브를 고려하여 도입 여부를 신중히 결정해야 합니다.
앞으로 고민할 점
- 기존 Blocking 기반 시스템을 어떻게 점진적으로 전환할 것인가?
- 비동기 프로그래밍 패턴에서 디버깅과 유지보수를 어떻게 개선할 것인가?
- CPU 바운드 작업과 혼합된 환경에서 최적화를 어떻게 이룰 것인가?
필요한 상황에 적합한 기술을 선택하는 것이 가장 중요한 전략입니다.
[WebFlux] Blocking I/O, Non-Blocking I/O
Blocking I/O 정의 Blocking I/O는 하나의 요청에 여러 스레드가 동작할 때, 특정 스레드가 I/O 작...
blog.naver.com
[WebFlux 심층 분석] 리액티브 스트림즈 컴포넌트 구현 및 Kafka와의 비교
리액티브 스트림즈는 비동기적이고 Non-Blocking 방식의 데이터 처리를 위한 표준입니다. 이 글에서는 리액티브 스트림즈의 주요 컴포넌트 구현과 Apache Kafka와의 차이점을 살펴보겠습니다. 리액티
hoosfa.tistory.com
'IT기술 > webflux (reactor)' 카테고리의 다른 글
| Spring WebFlux와 리액티브 프로그래밍의 기초: 함수형 인터페이스부터 함수 디스크립터까지 (2) | 2025.03.26 |
|---|---|
| 리액티브 스트림즈(Reactive Streams) 핵심 정리 (1) | 2025.03.23 |
| [WebFlux 심층 분석] 리액티브 스트림즈 컴포넌트 구현 및 Kafka와의 비교 (0) | 2025.03.21 |
| [WebFlux 심층 분석] 리액티브 스트림즈의 핵심 개념과 구현 전략 (0) | 2025.03.20 |
| [WebFlux 완전 정복] 리액티브 시스템과 리액티브 프로그래밍의 핵심 개념 및 구현 전략 (0) | 2025.03.19 |