본문 바로가기

개발/Spring

#2) Spring WebFlux(리액티브 프로그래밍 특징, 리액티브 스트림즈)

리액티브 프로그래밍 특징

1. 선언형 프로그래밍

    - 명령형 프로그래밍 vs 선언형 프로그래밍

        : 간단하게 요약하자면

          명령형 프로그래밍 방식은 실행할 동작을 구체적으로 명시하는 방식

          선언형 프로그래밍은 실행할 동작을 구체적으로 명시하는게 아닌 목표만 선언하는 방식

 

 

2. 코드 구성

    - Publisher : 입력으로 들어오는 데이터를 제공하는 역할

    - Subscriber : Publisher가 제공하는 데이터를 사용하는 주체

    - Data Source : Publisher의 입력으로 전달되는 데이터

    - Operator : Publisher와 Subscriber 사이에서 데이터를 적절하게 가공 처리하는 담당

 

 

리액티브 스트림즈

리액티브한 코드 구성을 용이하게 해주는 라이브러리를 어떻게 구현할지 정의해 놓은 별도의 표준 사양

- 데이터 스트림을 비동기-논블록킹인 방식으로 처리하기 위한 리액티브 라이브러리의 표준 사양

- 종류 : RxJava, Reactor, Akka Streams, Java9 Flow API

- Spring Framework와 가장 궁합이 잘 맞는건 Reactor!

 

1. 구성요소

    - Publisher : 데이터를 생성하고 통지(발행, 게시, 방출)하는 역할을 한다.

    - Subscriber : 통지된 데이터를 전달받아 처리하는 역할

    - Subscription : Publisher에 요청할 데이터의 개수를 지정하고, 데이터의 구독을 취소하는 역할

    - Processor : Publisher와 Subscriber의 기능을 모두 가진다.

                           즉 Subscriber로서 다른 Publisher를 구독할 수 있고

                           Publisher로서 다른 Subscriber가 구독할 수 있다.

 

 

Publisher와  Subscriber 간의 데이터가 전달되는 동작 과정

 

*Subscriber가 Subscription.request를 통해 데이터의 요청 개수를 지정하는 이유 : Publisher와 Subscriber는 각각 다른 스레드에서 비동기적으로 상호작용하는 경우가 대부분이므로 Publisher가 데이터를 통지하는 속도가 Subscriber에서 데이터를 처리하는 속도보다 빠르면 처리를 기다리는 데이터가 쌓이게되고 시스템 부하가 커지는 결과를 초래할 수 있기 때문이다.

 

1-1 Publisher

 

Publisher 인터페이스

public interface Publisher<T> {
    public void subscribe(Subscriber<? super T> s);
}

 

subscribe : 파라미터로 전달받은 Subscriber를 등록하는 역할을 한다.

 

 

1-2 Subscriber

public interface Subscriber<T> {
    public void onSubscribe(Subscription s);
    public void onNext(T t);
    public void onError(Throwable t);
    public void onComplete();
}

 

onSubscribe : 구독 시작 시점에 어떤 처리를 하는 역할. Publisher에게 요청할 데이터 수를 지정하거나 구독을 해지한다.

onNext : Publisher가 통지한 데이터를 처리한다.

onError : Publisher가 데이터 통지를 위한 처리 과정에서 에러가 발생하면 처리한다.

onComplete : Publisher가 데이터 통지를 완료하면 호출된다. 데이터 통지가 완료될 경우 후처리를 해야한다면 onComplete에 처리 코드를 작성하면 된다.

 

1-3 Subscription

public interface Subscription {
    public void request(long n);
    public void cancel();
}

 

request : Publisher에게 데이터 수를 요청한다.

cancel : 구독을 해지한다.

 

1-4 Processor 인터페이스는 별도로 구현해야 하는 메서드가 없다. Subscriber 혹은 Publisher 인터페이스를 상속한다.

 

 

2. 리액티브 스트림즈 관련 용어

 

2-1 Signal

Publisher와 Subscriber간에 주고받는 상호작용을 signal이라고 한다.

즉 리액티브 스트림즈 인터페이스에 있는 메서드들을 Signal이라고 표현한다.

 

2-2 Demand

Publisher가 아직 Subscriber에게 전달하지 않은 Subscriber가 요청한 데이터를 말한다.

 

2-3 Emit

Publisher가 데이터를 전달하기 위해 onNext Signal을 Subscriber에게 보내는 것을 데이터를 emit한다라고 표현한다.

 

2-4 Upstream/Downstream

현재 호출한 메서드에서 반환된 Flux의 위치에서 자신보다 더 상위에 있는 Flux는 Upstream, 하위에 있으면 Downstream이 된다.

 

2-5 Sequence

Publisher가 emit하는 데이터의 연속적인 흐름을 정의해 놓은 것 자체를 의미한다. Operator 체인 형태로 정의되며

예를 들어 Flux를 통해 데이터를 생성, emit 후 filter 메서드를 통해 필터링 하고 map 메서드를 통해 변환하는 과정 자체를 말한다.

 

2-6 Operator

우리말로 연산자로 해석하며 just, filter, map 같은 메서드를 말한다.

 

 

3. 리액티브 스트림즈 구현체

 

3-1 RxJava

넷플릭스에서 .NET 환경의 리액티브 확장 라이브러리를 Java로 포팅하여 만든 대표적인 리액티브 확장 라이브러리

2.0 버전부터 리액티브 스트림즈 사양을 지원하기 시작했다. 이전 버전과 차이점은 Backpressure를 지원하냐 마냐이다.

 

3-2 Project Reactor

줄여서 Reactor라고 하며 Spring Framwork 팀에서 주도적으로 개발한 리액티브 스트림즈 구현체이다. Spring 5 버전부터 리액티브 스택에 포함되어 Java 리액티브 프로그래밍의 핵심이 된다. WebFlux 기반의 리액티브 어플리케이션을 만드려면 충분히 이해해야 한다.

 

3-3 Akka Streams

Akka는 JVM상에서의 동시성과 분산 어플리케이션을 단순화해주는 오픈소스 툴킷이고 Actor 모델을 적극적으로 사용하는 기술이다.

Actor들은 서로 독립적이고 메시지로만 통신한다. Akka 툴킷 위에 리액티브 스트림즈를 구현한 것이 Akka Streams이다. Akka Streams API는 리액티브 스트림즈 구현체는 아니고 Akka를 사용하는 최종 사용자에게 제공되는 API이므로 리액티브 스트림즈와 구분되어야 한다. 

 

3-4 Java Flow API

Java 9버전부터 Flow API를 사용하여 리액티브 스트림즈를 지원한다. 다른 구현체들과 차이점은 스트림즈를 구현한 구현체가 아니고 리액티브 스트림즈의 표준 사양이 SPI로써 Java API에 정의되어 있다.

반응형