2. 스프링을 이용한 리액티브 프로그래밍 - 기본 개념
관찰자(Observer) 패턴
- 이벤트를 발생시키는 역할(주체Subject), 이벤트를 수신하는 역할(객체, 즉 관찰자Observer)의 두가지 핵심 요소가 존재
- Observer는 Subject에 등록되고 Subject로부터 알림을 수신
Java의 내장 클래스인 Observable, Observer는 java9 부터 deprecated 되었다.
- interface가 아니라 class로 구현되어 있어서 이미 다른 클래스를 상속받은 클래스가 Observable을 상속할 수 없어서 재사용성에 제약이 생긴다.
- Observable의 핵심 메소드 중 하나인 setChanged() 메소드가 protected로 정의되어 있어서 사용하려면 상속받은 서브클래스만 해당 메소드를 호출할 수 있다.
- Observable의 알림은 순서를 보장할 수 없고 상태 변경 역시 1:1로 일치하지 않아서 멀티 스레드 환경에서 thread-safe 하지 않다.
- Serializable을 구현하지 않기 때문에 Observable을 상속받은 서브클래스도 직렬화할 수 없다.
발행-구독 패턴
스프링 프레임워크는 이벤트처리를 위해 @EventListener
어노테이션과 이벤트 발행을 위한 ApplicationEventPublisher
클래스를 제공한다.
관찰자 패턴과의 차이점은 게시자와 구독자 사이에 간접적인 이벤트 채널(=메시지 브로커 or 이벤트 버스)
을 제공하여 구독자는 이벤트 채널은 알고 있지만 게시자가 누구인지는 신경쓰지 않는다.
SseEmitter
를 사용하면 스프링 프레임워크를 브로커를 사용하여 발행-구독 패턴을 구현할 수 있다.
다만 로직을 구현함에 있어 스프링의 내부 메커니즘을 사용했고 이는 프레임워크의 변경으로 인해 프로그램의 안정성을 보장할 수 없는 단점이 있다.
리액티브 프레임워크 RxJava
자바 플랫폼에서 리액티브 프로그래밍을 위한 표준 라이브러리는 RxJava 1.x 였고 현재(2021 기준)는 2.x를 지나 3.x까지 출시되었다.
RxJava
라이브러리는 **Reactive Extensions(혹은 ReactiveX)**의 자바 구현체로 종종 관찰자 패턴, 반복자 패턴 및 함수형 프로그래밍의 조합으로 정의된다.
RxJava의 기본적인 Observer 인터페이스는 아래와 같이 설계할 수 있다.
1 | public interface RxObserver<T> { |
RxJava에서 아래와 같이 주기적으로 비동기 이벤트 시퀀스를 생성할 경우 이벤트가 생성되는 것과 별개의 스레드에서 사용되기 때문에 메인 스레드가 종료되지 않도록 sleep()을 쓰거나 다른
방법으로 종료를 지연시킬 수 있다.
1 | Observable.interval(1, TimeUnit.SECONDS) |
마블 다이어그램
RxJava는 연산자를 통해 스트림의 원소를 조정하거나 구조 자체를 변경할 수 있다. 연산자가 복잡한 변환을 수행할 경우 이를 시각적으로 표현하여 그 동작을 효과적으로 설명하기 위한 목적으로 마블 다이어그램(marble diagram)
이 발명됐다.
- 위아래 실선(ㅡ>) : Observable의 시간흐름(Timeline)을 의미한다.
- 각 도형(○,□) : Observable에서 발행하는 데이터로 발행될때마다
onNext
메서드가 호출된다. - 파이프(
|
) : 데이터 발행을 모두 완료했다는 의미로onCompleted
메서드가 호출된다. - 위에서 아래로 점선(—>) : 함수의 입력,출력을 의미한다.
- 가운데 박스 : 함수를 의미하며 입력된 값에 어떤 변환작업을 하는지 나타내고 있다.
- 엑스(
X
) : 함수에서 입력된 값을 처리하는 중 에러가 발생하거나 비정상적으로 종료되었음을 의미하며onError
메서드가 호출된다.
RxJava와 관련된 모든 연산자는 이러한 마블다이어그램으로 표현되고 있으니 익숙해질 필요가 있다.
2. 스프링을 이용한 리액티브 프로그래밍 - 기본 개념
https://yoo0926.github.io/2021/11/28/book/spring5-reactive/2/