아래의 책을 정리했습니다.
https://product.kyobobook.co.kr/detail/S000201399476
스프링으로 시작하는 리액티브 프로그래밍 | 황정식 - 교보문고
스프링으로 시작하는 리액티브 프로그래밍 | *리액티브 프로그래밍의 기본기를 확실하게 다진다*리액티브 프로그래밍은 적은 컴퓨팅 파워로 대량의 요청 트래픽을 효과적으로 처리할 수 있는
product.kyobobook.co.kr
Blocking I/O
데이터베이스를 조회하거나 추가하는 작업, 다른 웹 애플리케이션으로 네트워크 통신을 하는 작업, 파일에서 데이터를 읽어오거나 기록하는 작업을 I/O 작업이라고 합니다.
Blocking I/O는 하나의 스레드가 I/O에 의해서 차단되어 대기하는 것을 말합니다.
(예시)
클라이언트와 도서 데이터를 제공하는 두대의 API 서버가 있습니다. 도서 정보를 조회하기 위한 요청을 보내면 API 서버는 클라이언트 요청에 맞는 도서 데이터를 제공합니다. 본사 API 서버에서는 더 많은 정보가 필요하여 지점 API 서버에 추가적인 요청을 보냅니다. 이 때 본사 API 서버에서 실행된 스레드는 차단되고 지점 API 서버의 스레드가 응답을 반환하기 전까지 대기하게 됩니다.
Blocking I/O 방식의 문제를 보완하기 위해 멀티스레딩 기법으로 시간을 효율적으로 사용할 수 있습니다.
그러나 이 방법 또한, 컨텍스트 스위칭으로 인한 스레드 전환 비용이 발생합니다. 컨텍스트 스위칭을 하는 과정에서 프로세스의 정보를 PCB에 저장, reload하는 시간 동안 CPU가 다른 작업을 하지 못하기 때문입니다.
그리고 새로운 스레드가 실행되면 JVM에서 해당 스레드에 대한 스택 영역을 할당하기에 과다한 메모리 사용으로 오버헤드가 발생할 수 있습니다.
또한, 스레드 풀에서 응답 지연이 발생할 수 있습니다. Spring boot 톰캣에서는 서블릿 컨테이너를 내장하고 컨테이너는 사용자의 요청을 처리하기 위해 스레드 풀을 사용합니다. 대량의 요청 발생 시에 스레드 풀에 사용 가능한 유휴 스레드가 없을 경우, 사용 가능한 스레드 확보 전까지 응답 지연이 발생합니다.
Non-Blocking I/O
Non-Blocking I/O는 Blocking I/O와 반대로 스레드가 차단되지 않습니다.
그렇기에 하나의 스레드로 많은 수의 요청을 처리할 수 있습니다. 그러나 스레드 내부에 CPU를 많이 사용하는 작업이 포함된 경우 성능에 악영향을 줄 수 있습니다. 또한, 사용자의 요청, 응답 과정이 모두 Non-Blocking 방식이어야 이점을 발휘할 수 있습니다.
Spring Framework에서 Blocking I/O, Non-Blocking I/O
평상 시에 사용하던 기술은 Spring MVC 기반의 Blocking I/O 방식입니다. 그러나 스마트폰, 태블릿 등 휴대기기와 IOT 기술의 발전으로 Blocking I/O 방식의 애플리케이션이 감당하기 어려움 트래픽이 발생하는 상황이 많아지면서 Spring MVC 의 대안으로 Spring WebFlux가 등장했습니다.
Spring WebFlux는 Netty 같은 비동기 Non-Blocking I/O 기반의 서버 엔진을 사용하여 적은 수의 스레드로 많은 수의 요청을 처리하기 때문에 CPU와 메모리를 효율적으로 관리할 수 있습니다.
Spring MVC는 RestTemplate을 사용해 요청 전송 후, 받은 도서 정보를 ResponseEntity 클래스를 사용하여 반환했다면, Spring WebFlux는 WebClient를 사용해서 요청을 전송한 후, 응답으로 받은 도서 정보를 Mono 타입으로 바꾸어 최종적으로 Mono 타입의 객체를 반환합니다.
@ResponseState(HttpStatus.OK)
@GetMapping("/{book-id}")
public Mono<Book> getBook(@PathVariable("book-id") long bookId) {
URI getBookUri = UriComponentsBuider.fromUri(baseUri)
.path("/{book-id}")
.build()
.expand(bookId)
.encode()
.toUri();
return WebClient.create()
.get()
.uri(getBookUri)
.retrieve()
.bodyToMono(Book.class);
}
Non-Blocking I/O 방식의 통신이 적합한 환경
학습 난이도와 리액티브 프로그래밍 경험이 있는 개발 인력을 확보하는 것이 어려워 당장 높은 성능을 위해 도입한 기술이 발목을 잡을 수 있습니다.
그래서 대량의 요청 트래픽이 발생하는 시스템이나 마이크로 서비스 기반 시스템, 스트리밍 또는 실시간 시스템에서 WebFlux 기술 도입을 고려해볼 수 있습니다.
'🍀spring' 카테고리의 다른 글
[Spring] Project Reactor - Cold & Hot Sequence, Backpressure (1) | 2025.03.11 |
---|---|
[Spring] Project Reactor - Reactor와 마블 다이어그램 (1) | 2025.03.10 |
[Spring] 리액티브 프로그래밍 - 리액티브 스트림즈 (0) | 2025.03.02 |