오늘은 리액티브 프로그래밍에 대해 공부해보는 날이다.
아마 깊은 내용은 다루지 않고, 간단한 지식들만 공부 할 것 같다.

image

우리는 Spring MVC 기반의 애플리케이션을 사용하고있는데
최신 기술로 Spring Reactive가 나와서 후에 어떻게
바뀔지는 아무도 모르니 Spring MVC 이해를 마친 후
해당 기술에 대해 깊게 공부해볼 필요가 있을 것 같다.


리액티브 프로그래밍이란?

기존의 명령형 프로그래밍 방식과 달리 선언형 프로그래밍 방식을 사용한다.
클라이언트의 요청에 반응을 잘하는 시스템을 의미한다.
리액티브 시스템 관점에서의 반응은 쓰레드의 Non-Blocking과 관련이 있다.
클라이언트의 요청에 대한 대기 시간을 최소화 할 수 있도록
요청 쓰레드가 차단되지 않게 함으로써, 클라이언트에게 즉각적으로
반응하도록 구성된 시스템이라고 볼 수 있다.

리액티브 시스템의 특징을 알아보자

image

1). MEANS
-. 리액티브 시스템에서 사용하는 커뮤니케이션 수단

  • Message Driven
    -. 리액티브 시스템에서는 메세지 기반 통신을 통해 여러 시스템 간에 느슨한 결합을 유지한다.

2). FORM
-. 메세지 기반 통신을 통해 리액티브 시스템이 어떤 특성을 가지는 구조로 형성되는지를 의미

  • Elastic
    -. 시스템으로 들어오는 요청량이 적거나 많거나에 상관없이 일정한 응답성을 유지하는 것
  • Resillient
    -. 시스템의 일부분에 장애가 발생하더라도 응답성을 유지하는 것

3). VALUE
-. 리액티브 시스템의 핵심 가치가 무엇인지를 표현하는 영역

  • Responsive
    -. 리액티브 시스템은 클라이언트의 요청에 즉각적으로 응답할 수 있어야함을 의미
  • Maintainable
    -. 클라이언트의 요청에 대한 즉각적인 응답이 지속가능해야함을 의미
  • Extensible
    -. 클라이언트의 요청에 대한 처리량을 자동으로 확장하고 축소할 수 있어야함을 의미


리액티브 스트림즈란?

리액티브 프로그래밍을 위한 표준사양이다.
리액티브 스트림즈에서 사양으로 정의된 구성요소를 알아보자

1). Publisher 인터페이스

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

-. 데이터 소스로 부터 데이터를 내보내는(emit) 역할을 한다.
-. subscribe();추상 메서드를 포함하고 있고, 매개변수로 전달되는 Subscriberrk
Publisher로부터 내보내진 데이터를 소비하는 역할을 한다.


2). Subscriber 인터페이스

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

-. Publisher로 부터 내보내진 데이터를 소비하는 역할을 한다.

-. onSubscribe(Subscription s);

  • 구독이 시작되는 시점에 호출됨.
  • Pusblisher에게 요청할 데이터의 개수를 지정하거나 구독해지 처리가 가능

-. onNext(T t)

  • Publisher가 데이터를 emit할 때 호출됨
  • emti된 데이터를 전달 받아서 소비할 수 있다.

-. onError(Throwable t)

  • Publisher로부터 emit된 데이터가 Subscriber에게 전달되는 과정에서
    에러가 발생할 경우에 호출된다.

-. onComplete()

  • Publisher가 데이터를 emit하는 과정이 종료될 경우 호출됨
  • emit이 정상적으로 완료된 후, 처리해야 될 작업이 있다면 해당 메서드 내에서 수행할 수 있다.


3). Subscription 인터페이스

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

-. Subscriber의 구독 자체를 표현한 인터페이스이다. -. request(long n)

  • Publisher가 emit하는 데이터의 개수를 요청

-. cancel()

  • 구독을 해지하는 역할을한다. 구독해지가 발생하면 Publisher는 더이상 데이터를 Emit하지 않는다.


4). Processor 인터페이스

public interface Processor<T, R> extends Subscriber<T>, Publisher<R> {
}

-. 별도로 구현해야 되는 추상메서드는 없다.
-. Publisher와 Subscriber의 역할을 동시에 할 수 있는 특징을 가지고 있다.


5). 구현체들

  • Project Reactor
  • RxJava
  • Java Flow API

코드로 알아보기

public class ReactiveExample {
    public static void main(String[] args) {
        // Publisher의 역할
        Mono<String> mono = Mono.just("Hello, Reactive");

        // Subscriber의 역할
        mono.subscribe(message -> System.out.println(message));
    }
}

// 출력
Hello, Reactive

리액티브 스트림즈 구현체인 Project Reactor을 통해 출력하고 있는 모습이다.
Mono의 역할이 Publisher의 역할이고
Subscriber는 Publisher가 emit한 데이터를 전달 받아서
소비하는 역할이라고 위에서 공부했었다.

Subscriber 역할을 하는 것은 mono.subscribe(); 메서드이고
내부에 정의된 람다 표현식을 사용하고 있다.

기존에 우리가 사용했던 Stream과 동일하게 메서드 체인형식으로 구성도 가능하다.

public class ReactiveExample {
    public static void main(String[] args) {
        Mono
            .just("Hello, Reactive")
            .subscribe(message -> System.out.println(message));
    }
}
// 출력
Hello, Reactive

다른 형식의 예제를 알아보자

public class ReactiveGlossaryExample {
    public static void main(String[] args) {
        Flux
            .fromIterable(List.of(1, 3, 6, 7, 8, 11))
            .filter(number -> number > 4 && (number % 2 == 0))
            .reduce((n1, n2) -> n1 + n2)
            .subscribe(System.out::println);

    }
}
// 출력
14

Publisher -> Flux가 Pusblisher 이다.

Emit -> Flux가 데이터를 내보내는 것을 가르킴

Subscriber -> Flux가 emit한 데이터를 전달 받아서 소비하는 주체
즉, System.out::println 부분이 Subscriber에 해당한다.

Subscribe -> subscribe 메서드를 호출하면 구독을 하는 것이다.

Signal -> Publisher가 발생시키는 이벤트를 의미한다.

Operator -> 어떤 동작을 수행하는 메서드를 의미한다.
fromIterable(), filter(), reduce()등 하나하나들 Operator이라 한다.

Sequence -> Operator 체인으로 표현되는 데이터의 흐름을 의미한다.
해당 코드에선 코드자체를 하나의 Sequence라고 보면된다.

Upstream -> Operator 기준으로 위쪽 Sequence 일부를 Upstream이라함
Downstream -> Operator 기준으로 아래쪽 Sequence 일부를 Downstream이라함




오늘의 커피량: ☕️ ☕️
오늘의 점심: 제육볶음, 김치찌개, 밥