[Section 4] 리액티브 프로그래밍

Kim·2022년 11월 29일
0

Boot Camp

목록 보기
57/64

이전까지 학습하며 만들어 본 애플리케이션은 명령형 프로그래밍 방식을 사용했다. 명령형 프로그래밍 방식은 전통적인 개발 방식이다.
반면에 리액티브 프로그래밍은 전통적인 명령형 프로그래밍 방식과 달리 선언형 프로그래밍 방식을 사용한다.

리액티브(Reactive)란, 일반적으로 '반응하는' 으로 해석할 수 있다.

리액티브에 대한 의미를 가장 쉽게 이해할 수 있는 단어는 리액션이다.
다른 사람의 이야기를 듣고 바로바로 반응을 하는 사람을 흔히 리액션이 좋은 사람이라고 부르듯이, 리액티브 시스템도 마찬가지다.


Reactive System

리액티브 시스템이란, 반응을 잘 하는 시스템이다.
여기서의 반응은 리액티브 시스템을 이용하는 클라이언트의 요청에 반응하는 것이다. 즉, 클라이언트의 요청에 반응을 잘 하는 시스템이 리액티브 시스템인 것이다.

리액티브 시스템 관점에서의 반응은 쓰레드의 Non-Blocking과 관련이 있다.
리액티브 시스템은 클라이언트의 요청에 대한 응답 대기 시간을 최소화 할 수 있도록 요청 쓰레드가 차단되지 않게(Non-Blocking) 함으로써 클라이언트에게 즉각적으로 반응하도록 구성된 시스템이라 할 수 있다.

특징

이 그림은 리액티브 시스템의 설계 원칙을 표현한 것이다. 용어를 토대로 시스템의 특징을 살펴보자.

  • VALUE
    리액티브 시스템의 핵심 가치가 무엇인지를 표현하는 영역이다.
    Responsive - 리액티브 시스템은 클라이언트 요청에 즉각적으로 응답할 수 있어야 함을 의미한다.
    Maintainable - 클라이언트의 요청에 대한 즉각적인 응답이 지속 가능해야 함을 의미한다.
    Extensible - 클라이언트 요청에 대한 처리량을 자동으로 확장 및 축소할 수 있어야 함을 의미한다.

  • FORM
    메시지 기반 통신을 통해 시스템이 어떤 특성을 갖는 구조로 형성되는지를 의미한다.
    Elastic - 시스템으로 들어오는 요청량이 적던 많던 상관 없이 일정한 응답성을 유지한다.
    Resilient - 시스템의 일부분에 장애가 발생해도 응답성을 유지한다.

  • MEANS
    리액티브 시스템에서 사용하는 커뮤니케이션 수단이다.
    Message Driven - 리액티브 시스템에서는 메시지 기반 통신을 통해 여러 시스템 간에 느슨한 결합을 유지한다.


Reactive Programming

리액티브 프로그래밍이란, 리액티브 시스템에서 사용되는 프로그래밍 모델을 의미한다.
리액티브 시스템에서의 메시지 기반 통신(Message Driven)은 Non-Blocking 통신과 유기적인 관계를 맺고 있으며, 리액티브 프로그래밍은 Non-Blocking 통신을 위한 프로그래밍 모델이다.

특징

리액티브 프로그래밍은 선언형 프로그래밍 방식을 사용하는 대표적인 프로그래밍 모델이다.

data streams는 지속적으로 데이터가 입력으로 들어올 수 있음을 의미한다. 리액티브 프로그래밍에서는 데이터가 지속적으로 발생하는 것 자체가 데이터에 어떤 변경이 발생함을 의미하며, 변경 자체를 이벤트로 간주하고 이벤트가 발생할 때마다 데이터를 계속 전달한다.
지속적으로 발생하는 데이터를 하나의 데이터 플로우로 보고 데이터를 자동으로 전달한다는 말과 같다.


Reactive Streams

JPA와 JDBC API의 공통점을 생각해보면 리액티브 스트림즈가 의미하는 것을 바로 알 수 있을 것이다.
JPA는 Java 진영에서 사용하는 ORM 기술의 표준 사양 또는 명세이고, JDBC는 Java 애플리케이션에서 DB에 액세스 하기 위한 표준 사양 또는 명세이다.

리액티브 스트림즈는 리액티브 프로그래밍을 위한 표준 사양 또는 명세이다.
Java에서는 어떤 기술의 표준 사양을 코드로 정의할 경우, 일반적으로 Java의 인터페이스(interface)로 정의한다.

리액티브 스트림즈 컴포넌트

Publisher

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

Publisher 인터페이스는 데이터 소스로부터 데이터를 내보내는 역할을 한다.
subscribe() 메서드는 Publisher가 내보내는 데이터를 수신할지 여부를 결정하는 구독의 의미이다. 일반적으로 subscribe()가 호출되지 않으면 Publisher가 데이터를 내보내는 프로세스는 시작되지 않는다.

Publisher가 데이터를 내보내는 것을 emit이라 표현한다.

Subscriber

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

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

  • onSubscribe(Subscription s) : 구독이 시작되는 시점에 호출된다. onSubscribe() 내에서 Publisher에게 요청할 데이터의 개수를 지정하거나 구독 해지 처리를 할 수 있다.

  • onNext(T t) : Publisher가 데이터를 emit 할 때 호출된다. emit된 데이터를 전달 받아서 소비할 수 있다.

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

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

Subscription

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

Subscription 인터페이스는 Subscriber의 구독 자체를 표현한 인터페이스이다.

  • request(long n) : Publihser가 emit하는 데이터의 개수를 요청한다.

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

Processor

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

Processor 인터페이스는 Subscriber 인터페이스와 Publisher 인터페이스를 상속하고 있어, Publisher와 Subscriber의 역할을 동시에 할 수 있는 특징을 가지고 있다. 별도로 구현해야 할 추상 메서드는 없다.

리액티브 스트림즈 구현체

🔅 Project Reactor
Project Reactor(Reactor로도 불림)는 리액티브 스트림즈를 구현한 대표적인 구현체이다. Spring과 궁합이 가장 잘 맞는 구현체이다.
Reactor는 Spring 5의 리액티브 스택에 포함되어 있으며 Sprig Reactive Application 구현에 있어 핵심적인 역할을 담당한다.

🔅 RxJava
RxJava는 .NET 기반의 리액티브 라이브러리를 넷플릭스에서 Java 언어로 포팅한 JVM 기반의 리액티브 확장 라이브러리이다.
2.0부터 리액티브 스트림즈 표준 사양을 준수하고 있으며 이 전 버전의 컴포넌트와 함께 혼용되어 사용되고 있다.

🔅 Java Flow API
Java 9부터 리액티브 스트림즈를 지원한다.
Flow API는 리액티브 스트림즈를 구현한 구현체가 아닌, 리액티브 스트림즈 표준 사양을 Java 안에 포함을 시킨 구조라고 할 수 있다.

다양한 벤더들이 JDBC API를 구현한 드라이버를 제공할 수 있게 SPI 역할을 하듯이, Flow API 또한 리액티브 스트림즈 사양을 구현한 여러 구현제에 대한 SPI 역할을 한다고 보면 된다.

🔅 기타 리액티브 확장(Reactive Extension)
RxJava의 Rx는 Reactive Extension의 약어이다.

특정 언어에서 리액티브 스트림즈를 구현한 별도의 구현체가 존재한다는 의미이다. 다양한 프로그래밍 언어에서 리액티브 스트림즈를 구현한 리액티브 확장(Reactive Extension) 라이브러리를 제공한다.
대표적인 리액티브 확장 라이브러리는 RxJava가 있다.


🔑Key Summary

  • 리액티브 시스템은 클라이언트의 요청에 반응을 잘하는 시스템을 의미한다.

  • 리액티브 프로그래밍은 리액티브 시스템에서 사용되는 프로그래밍 모델이다.

  • 리액티브 스트림즈는 리액티브 프로그래밍을 위한 표준 사양 또는 명세이다.

  • 리액티브 스트림즈 컴포넌트
    ✔ Publisher
    ✔ Subscriber
    ✔ Subscription
    ✔ Processor

  • 리액티브 스트림즈 구현체
    ✔ Project Reactor
    ✔ RxJava
    ✔ Java Flow API
    ✔ 기타 리액티브 확장(Reactive Extension)

  • 명령형 프로그래밍 방식은 실행 로직을 작성한 코드대로 실행이 된다.

  • 선언형 프로그래밍 방식은 실행할 코드만 선언하며, 순차적으로 실행되지 않는다.
    실행 로직의 일부만 람다 표현식으로 전달하며 전달 받은 람다 표현식을 기반으로 Operation 메서드 내부에서 전체 로직을 실행한다.

  • 리액티브 프로그래밍 용어
    Publisher : 데이터를 내보내는 주체이다.
    Emit : Publisher가 데이터를 내보내는 것을 의미한다.
    Subscriber : Publisher가 emit한 데이터를 전달 받아 소비하는 주체이다.
    Subscribe : 구독을 의미한다. 메서드를 호출하면 구독을 하는 것이다.
    Signal : Publisher가 발생시키는 이벤트를 의미한다.
    데이터를 emit하는 자체를 이벤트가 발생하는 것으로 간주하며, 이벤트 발생을 다른 컴포넌트에게 전달하는 것을 Signal을 전송한다고 표현한다.
    Operator : 리액티브 프로그래밍에서 어떤 동작을 수행하는 메서드이다.
    Sequence : Operator 체인으로 표현되는 데이터의 흐름을 의미한다.
    Operator 체인으로 작성된 코드 자체를 하나의 Sequence라고 생각하면 된다.
    Upstream & Downstream : Sequence 상의 특정 Operator를 기준으로, 위쪽은 Upstream, 아래쪽은 Downstream이라고 표현한다.


참고 자료

📄 The Reactive Manifesto
reactive-streams-jvm

📄 declarative programming

0개의 댓글