리액티브 프로그래밍의 중요성
- 빅데이터: 기가 바이트의 데이터 → 페타 바이트 단위의 데이터
- 다양한 환경: 모바일 디바이스에서 부터 클라우드 기반 클러스터에 이르기까지 다양한 환경에 애플리케이션이 배포됨
- 사용자 패턴: 사용자는 1년 내내 항상 서비스를 이용할 수 있으며, 밀리초 단위의 응답시간을 기대함
리액티브 프로그래밍: 다양한 시스템과 소스에서 들어오는 데이터 항목 스트림을 비동기적으로 처리하고 합쳐서 해결함
17.1 리액티브 매니패스토
리액티브 애플리케이션과 시스템 개발의 핵심 원칙을 공식적으로 정의함
- 반응성(responsive): 빠르고 일정하고 예상가능한 반응 시간을 제공함
- 회복성(resilient): 장애가 발생해도 시스템은 반응해야 함
- 탄력성(elastic): 애플리케이션에 작업 부하가 심해지면 자동으로 컴포넌트에 할당된 자원 수를 늘림
- 메시지 주도(Messge-driven): 비동기 메시지를 전달해 컴포넌트끼리의 통신이 이루어짐. 회복성과 탄력성을 지원하려면 시스템을 구성하는 컴포넌트의 경계를 명확하게 정의해향함.
- 회복성: 장애를 메시지로 처리
- 탄력성: 주고받은 메시지 수를 감시하고 메시지 양에 따라 적절하게 리소스를 할당
17.1.1 애플리케이션 수준의 리액티브 (리액티브 애플리케이션)
- 주요 기능 비동기로 작업을 수행
- 이벤트 스트림을 블록하지 않고 비동기로처리하는 것이 멀티코어 CPU의 사용률을 극대화할 수 있음
- 리액티브 프레임워크 & 라이브러리는 스레드를 이벤트 루프 등과 공유하고, 처리할 이벤트를 관리함. 비동기 애플리케이션 구현의 추상 수준을 높일 수 있으므로 동기 블록, 경쟁 조건, 데드락 같은 저 수준의 멀티스레드 문제를 직접 처리하지 않아도 됨
- 스레드를 다시 쪼개는 종류의 기술을 사용할 때 메인 이벤트 루프 안에서 동작을 블록하지 않아야 함
- RxJava, Akka와 같은 리액티브 프레임워크는 별도로 지정된 스레드 풀에서 블록 동작을 실행시켜 문제를 해결함.메인 풀의 모든 스레드는 방해받지 않고 실행되므로 모든 CPU 코어가 가장 최적의 상황에서 동작할 수 있음. CPU 관련 작업과 I/O 관련 작업을 분리하면 더 정밀하게 풀의 크기를 설정할 수 있고, 두 타입의 작업의 성능을 관찰할 수 있음

17.1.2 시스템 수준의 리액티브 (리액티브 시스템)
- 리액티브 시스템
- 여러 애플리케이션이 하나의 일관적인, 회복 가능한 플랫폼을 구성할 수 있게 함
- 애플리케이션들 중 하나가 실패해도 전체 시스템은 계속 운영될 수 있도록 도와주는 소프트웨어 아키텍쳐
- 애플리케이션을 조립하고 상호소통을 조절함. 메시지 주도가 특징임
- 리액티브 어플리케이션
- 리액티브 시스템을 구현한 어플리케이션
- 비교적 짧은 시간 도안만 유지되는 데이터 스트림에 기반한 연산을 수행하며 보통 이벤트 주도로 분류됨.
- 메시지는 정의된 목적지 하나를 향하는 반면, 이벤트는 관련 이벤트를 관찰하도록 등록한 컴포넌트가 수신한다는 점이 다름.
리액티브 시스템
- 고립&비결합(회복성): 수신자와 발신자가 수신 메시지와 발신 메시지를 결합하지 않도록 이 메시지들을 비동기로 처리해야 함. 각 컴포넌트를 완전히 고립하려면 이들을 결합되지 않도록 해야함. 이를 통해 시스템이 장애와 높은 부하에서도 반응성을 유지할 수 있음
- 위치 투명성(탄력성): 리액티브 시스템의 컴포넌트들이 물리적인 위치에 대한 정보를 알 필요 없이 서로 통신할 수 있음. 즉, 어떤 컴포넌트가 다른 컴포넌트에게 메시지를 보낼 때, 그 컴포넌트가 물리적으로 어디에 위치해 있는지 몰라도 메시지를 보낼 수 있어야 함. 시스템의 위치 정보가 추상화되어 있기 때문에 시스템을 쉽게 복제할 수 있으며 현재 작업 부하에 따라 자동으로 애플리케이션을 확장할 수 있음
17.2 리액티브 스트림과 플로 API
- 리액티브 프로그래밍: 리액티브 스트림을 사용하는 프로그래밍
- 리액티브 스트림: 잠재적으로 무한한 비동기 데이터를 순서대로 그리고 블록하지 않는 역압력을 전재해 처리하는 표준 기술
- 역압력
- 목적지 스트림에서 처리할 수 있는 양보다 소스 스트림에서 생성되는 양이 더 많을 때 발생.
- 소스 스트림에서는 목적지 스트림으로 더 이상 데이터를 전송하지 않음
- 시스템 전체에서 과부하가 발생하는 것을 방지할 수 있음
17.2.1 Flow 클래스 소개
java9의 java.util.concurrent.Flow
Pub-Sub 모델을 지원할 수 있도록 인터페이스를 제공함
- Publisher
- 함수형 인터페이스
- 항목 발행
- Subscriber의 요구사항에 따라 역압력 기법에 의해 이벤트 제공 속도가 제한됨
- Subscriber
- Publisher가 발행한 이벤트 리스너
- 한 개씩 또는 한 번에 여러 항목을 소비
- Subscription
- Publisher와 Subscriber 사이의 제어 흐름, 역압력을 관리
- Processor
Publisher & Subscriber
@FunctionalInterface
public interface Publisher<T>{
void subscribe(Subscriber<? super T> s);
}
public interface Subscriber<T>{
void onSubscribe(Subscription s);
void onNext(T t);
void onError(Throwable t);
void onComplete();
}
- 순서를 지켜야함
- onSubscribe onNext* (onError | onComplete)?
- onSubscribe → onNext 0~무한번 → 끝나려면 onError or onComplete 중 하나로 끝나기
- Subscriber가 Publisher에 자신을 등록할 때, Publisher는 onSubscribe 메서드를 호출해서 Subscription 객체를 전달함
Subscription
public interface Subscription{
void request(long n);
void cancel();
}
- Subscription 인터페이스는 메서드 두 개를 정의함
- request(long n): Publisher에게 n개의 이벤트를 처리할 준비가 되었음을 알림
- cancel(): Subscription을 취소함. Publisher에게 더 이상 이벤트를 받지 않음을 통지함
- Publisher는 반드시 Subscription의 request 메서드에 정의된 개수 이하의 요소만 Subscriber에게 전달해야 함
- Subscriber는 요소를 받아 처리할 수 있음을 Publisher에 알려야 함 (역압력)
- Pub-Sub은 정확하게 Subscrption을 공유해야하며 각각이 고유한 역할을 수행해야 함

Processor
public interface Processor<T,R> extends Subscriber<T>, Publisher<R> {
}
- Processor interface
- 리액티브 스트림에서 처리하는 이벤트의 변환 단계를 나타냄
- Processor가 에러를 수신하면 이로부터 회복하거나 즉시 onError 신호로 모든 Subscriber에게 에러를 전파할 수 있음
- Subscriber가 Subscription을 취소하면 Processor는 자신의 업스트림 Subscription도 취소하므로 취소 신호를 전파해야함
'백엔드 > 모던자바인액션' 카테고리의 다른 글
17.3 리액티브 라이브러리 RxJava 사용하기 (0) | 2023.04.14 |
---|---|
ch17.2.3 Flow 라이브러리 예제 (0) | 2023.04.13 |
ch16. CompletableFuture: 안정적 비동기 프로그래밍 (0) | 2023.04.04 |
ch15. CompletableFuture와 리액티브 프로그래밍 컨셉의 기초 (0) | 2023.03.23 |
[ch4] 스트림 소개 (0) | 2022.09.19 |
댓글