- 리액티브 프로그래밍을 이해한다.
- Spring WebFlux 내부 동작 방식을 이해한다.
리액티브 프로그래밍#
리액티브 프로그래밍#
- 비동기 이벤트 처리와 데이터 스트림에 대한 아이디어를 기반으로 한다.
- 비동기 이벤트 처리는 다른 이벤트 처리를 차단하지 않는다는 것을 의미한다.
- 이벤트 큐와 병렬 이벤트 처리를 도입하여 성능과 확장성을 향상시킨다.
- 기본적으로 리액티브 프로그래밍은 3가지 구성요소를 가진 옵저버 패턴이다.(RxJava 기준)
Observable: 데이터 스트림을 표현한다. 한 스레드에서 다른 스레드로 전달할 수 있는 데이터를 담는다.Observer: Observable이 방출하는 데이터 스트림을 소비한다. Observable이 데이터를 방출할 때마다 데이터를 통해 작업을 수행하거나 예외를 던진다.Scheduler: Observable과 Observer가 어떤 스레드에서 실행해야할지 알려주는 구성요소다.
리액티브 스트림#
- 위 3가지 구성요소를 가진 방식에는 문제점이 있다.
Observable에 발생 시키는 이벤트의 수나 타이밍을 제어할 수 없기 때문에, 예측할 수 없는 부하를 관리할 수 없다.
- 리액티브 스트림은 non-blocking backpressure를 사용해서 위 문제를 해결한 표준을 제공한다.
- 리액티브 스트림은 4개의 인터페이스인
Publisher, Subscriber, Subscription, Processor로 요약할 수 있다. Publisher는 하나의 Subscription당 하나의 Subscriber에 발행하는 데이터는 생성한다.Publisher 인터페이스에는 Subscriber가 Publisher를 구독 신청할 수 있는 subscribe() 메서드 한 개가 선언되어 있다.Subscriber가 구독 신청되면 Publisher로부터 이벤트를 수신할 수 있다.Subscriber가 수신할 첫 번째 이벤트는 onSubsribe() 호출을 통해 이루어진다.Publisher가 onSubsribe()를 호출할 때 이 메서드의 인자로 Subscription 객체를 Subscriber에 전달한다.Subscriber는 Subscription 객체를 통해서 구독을 관리할 수 있다.
Subscriber는 Subscription의 request()를 호출하여 전송되는 데이터를 요청하거나, 또는 더 이상 데이터를 수신하지 않고 취소한다는 것을 나타내기 위해 cancel()을 호출할 수 있다.request()를 호출할 때 Subscriber는 받고자 하는 데이터 항목 수를 나타내는 long 타입의 값을 인자로 전달한다. 바로 이것이 _백 프레셔_이며, Subscriber가 처리할 수 있는 것보다 더 많은 데이터를 Publisher가 전송하는 것을 막아준다.- 요청된 수의 데이터를
Publisher가 전송한 후에 Subscriber는 다시 request()를 호출하여 더 많은 요청을 할 수 있다. 
Subscriber의 데이터 요청이 완료되면 데이터가 스트림을 통해 전달되기 시작한다. 이 때 onNext() 메서드가 호출되어 Publisher가 전송하는 데이터가 Subscriber에게 전달되며, 만일 에러가 생길 떄는 onError()가 호출된다.Publisher에서 전송할 데이터가 없고 더 이상의 데이터를 생성하지 않는다면 Publisher가 onComplete()를 호출하여 작업이 끝났다고 Subscriber에게 알려준다.Processor 인터페이스는 Subscriber 인터페이스와 Publisher 인터페이스를 결합한 것이다.Subscriber 역할로 Processor는 데이터를 수신하고 처리한다. 그다음에 역할을 바꾸어 Publisher 역할로 처리 결과를 자신의 Subscriber 들에게 발행한다.
- 리액티브 스트림의 구현체로 RxJava, Reactor 등이 존재한다.
- Reactor의
Flux, Mono가 Publisher 인터페이스의 구현체다.
Spring Webflux#
사용법#
- Spring Webflux는 2가지 방식으로 API를 제공하고 있다.
- 어노테이션 기반 컨트롤러: Spring MVC에서 제공하는 어노테이션을 사용을 지원.
- 람다 기반: 함수형 프로그래밍 지원.
내부 동작#
HttpHandler#
HttpHandler: HTTP 요청을 논블록킹, 리액티브 스트림 백프레셔로 처리해주는 낮은 레벨의 인터페이스- Reator Netty, Undertow, Tomcat, Jetty 등 리액티브 스트림 웹 서버를 지원하기 위한 어댑터 클래스도 지원해주고 있다.
WebHandler#
WebHandler: 어노테이션 기반 컨트롤러, 람다 기반 요청 처리를 지원하기 위한 높은 레벨의 핸들러- Spring WebFlux에서는 Spring MVC와 비슷하게 프론트 컨트롤러 패턴으로 설계되어,
WebHandler의 구현체인 DispatcherHandler를 제공한다. DispatcherHandler는 DispatcherServlet과 비슷하게 동작한다.- 요청이 들어오면
HandlerMapping이 적절한 핸들러를 찾는다. - 핸들러가 발견되면 적잘한
HandlerAdapter를 통해 실행하고, 반환 값은 HandlerResult로 노출된다. HandlerResult는 응답에 직접 쓰거나 렌더링할 뷰를 사용하여 처리하기 위해 적절한 HandlerReseulthandler에 제공된다.
DispatcherHandler는 DispatcherServlet과 다르게 정체 과정이 리액티브 스트림으로 처리된다.
스레드 동작 방식#
- WebFlux 서버는 기본적으로 서버를 실행하기 위한 하나의 스레드와 요청 처리를 위한 여러 개의 다른 스레드(일반적으로 CPU 코어 수 만큼)로 동작한다.
- 만약, 외부 서버 호출이나 DB 조회같은 오래동안 블로킹되는 API를 호출해야되는 경우
publishOn을 사용해서 다른 스레드풀에서 실행되도록 할 수 있다.
참고 자료#
comments powered by