[73일차]리액티브 프로그래밍

유태형·2022년 8월 10일
0

코드스테이츠

목록 보기
73/77

오늘의 목표

  1. 리액티브 정의
  2. 리액티브 스트림즈
  3. 리액티브 프로그래밍 구조



내용

리액티브 정의

리액티브 프로그래밍이란 클라이언트의 요청에 반응을 잘 하는 프로그래밍을 의미 합니다. 리액티브(Reactive)는 반응을 잘하는 인데 살짝 모호해서 리액션(Reaction)이 좋은 으로 조금 다르게 해석 하는 것도 개념에 새기는 좋은 방법입니다.



리액티브 시스템

리액티브한 그러니까 클라이언트의 요청에 반응을 잘하는 시스템이 리액티브 시스템 입니다.
(쓰레드의 Non-Blocking과 관련)

리액티브 시스템은 여러 특징들이 존재합니다.

  • MEANS : 리액티브 시스템에서 사용하는 커뮤니케이션 수단
    • Message Driven : 리액티브 시스템에서 메세지 기반 통신을 통해 시스템간 느슨한 결합
  • FORM : 메세지 기반 통신을 통해 어떤 특성을 가지는 구조로 형성되는지 의미
    • Elastic : 클라이언트의 요청 용량에 상관없이 일정한 응답성을 유지
    • Resilient : 시스템 일부가 장애가 생기더라도 응답성을 유지
  • VALUE : 리액티브 시스템의 핵심 가치
    • Responsive : 리액티브 시스템은 클라이언트의 요청에 즉각적으로 응답
    • Maintainable : 즉각적인 응답이 지속 가능해야 함
    • Extensible : 클라이언트의 요청에 대한 처리량을 자동으로 확장하고 축소


리액티브 프로그래밍

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

  1. 리액티브 프로그래밍은 선언형 프로그래밍 방식을 사용하는 모델입니다.
  2. 리액티브 프로그래밍에서 지속적으로 데이터가 입력으로 들어오고, 데이터가 지속적으로 발생하는 것 자체를 데이터에 변경이 발생함을 의미합니다.
  3. 지속적으로 발생하는 데이터를 하나의 데이터 플로우로 정의하고 데이터를 자동으로 전달합니다.



리액티브 스트림즈

리액티브 스트림즈(Reactive Streams)는 리액티브 프로그래밍을 위한 표준 사양(Specification)입니다.

다른 표준사양들과 마찬가지로 일반적으로 인터페이스로 정의합니다.

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

Publisher 인터페이스는 데이터를 내보내는(emit)하는 역할을 수행하는 주체입니다.
Publishersubscribe() 추상 메서드를 포함하며, Publisher가 데이터를 내보내는 프로세스를 시작합니다.
subscribe()는 구독의 의미를 가집니다.
SubscriberPublisher로 부터 emit된 데이터를 소비하는 주체입니다.

public interface Subscriber<T> {
	public void onSubscribe(Subscription s);
    public void onNext(T t);
    public void onError(Throwable t);
    public void onComplete();
}
  • onSubscribe(Subscription e) : 구독이 시작되는 시점에 호출됩니다. Publisher에게 요청할 데이터의 갯수를 지정하거나 구독 해지 처리가 가능합니다.
  • onNext(T t) : Publisher가 emit시 호출되며 emit된 데이터를 전달 받아 소비할 수 있습니다.
  • onError(Throwable t) : Subscriber에게 전달되는 과정에서 에러가 발생한 경우 호출됩니다.
  • onComplete() : emit하는 과정이 모두 정상적으로 완료 된 경우 호출됩니다. 수행후 해야할 작업이 있다면 onComplete()내에서 수행 가능합니다.
public interface Subscriptoin {
	public void request(long n);
    public void cancel();
}

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

  • request(long n) : emit하는 데이터의 개수를 요청합니다.
  • cancel() : 구독을 해지합니다. 더이상 publisher로부터 데이터를 emit받지 않습니다.
public interface Processor<T,R> extends Subscriber<T>, Publisher<R> {

}

Processor인터페이스는 Subscriber인터페이스와 Publisher인터페이스를 상속받고 별도의 추상 메서드는 없습니다.



리엑티브 스트림즈 구현체

구현체설명
Project Reactor리액티브 스트림즈를 구현한 대표적인 구현체로써 Spring과 가장 궁합이 잘맞고 Spring5의 리액티브 스택에 포함되어 있습니다.
RxJava.NET 기반의 리액티브 라이브러리를 넷플릭스에서 Java언어로 포팅한 리액티브 확장 라이브러리 입니다. 2.0버전 부터 리액티브 스트림즈 표준 사양을 준수합니다.
Java Flow APIJava 9부터 지원하고 있으며, 리액티브 표준 사양을 Java안에 포함시킨 구조입니다. 밴더들이 스트림즈를 구현할 수 있도록 SPI역할을 수행합니다.

RxJavaRxReactive Extension의 줄임말 으로써 리액티브 스트림즈를 구현한 별도의 구혀네가 존재한다는 의미로 다양한 프로그래밍 언어에서 Reactive Extension 라이브러리를 제공하고 있습니다.(ex)RxJS,RxAndroid,RxKotlin,RxPython,RxScala,...)




리액티브 프로그래밍 구조

리액티브 프로그래밍의 대표적인 특징은 선언형 프로그래밍방식을 사용합니다.

기존의 방식은 명령형 프로그래밍 방식for문,if문등으로 명령의 흐름을 제어 하였다면 선언형 프로그래밍방식은 스트림(Stream)방식으로 .filter().map().sum(). 체인형태의 내부적으로 처리하는 방식입니다.

public class 리엑티브예시1 {
	public static void main(String[] args){
    	Mono<String> mono = Mono.just("데이터");
        
        mono.subscribe(message -> System.out.println(message));
    }
}
  • Mono : 스프링은 Publisher로써 0또는 1개의 데이터를 발생시킬 수 있는 Mono를 지원합니다.
  • Mono.just("데이터") : 데이터를 받아들이는 메서드 입니다.
  • Mono.subscrbe() : Publisher인터페이스의 subscirbe()추상메서드를 구현한 것입니다. publishermono에 있는 데이터를 subscriber에게 emit합니다.
  • message -> System.out.println(message) : 람다 표현식으로 구성된 subscriber입니다. publisher로 부터 데이터를 emit받아 소비합니다.
public class 리액티브예시2 {
	public static void main(String[] args) {
    	Mono.just("데이터")
        	.subscribe(message -> System.out.println(message));
    }
}

리액티브 프로그래밍의 대표적인 특징은 선언형 프로그래밍방식을 사용한다고 하였습니다. 그러므로 체인 형태로 표현이 가능합니다.

public class 리액티브예시3 {
	public static void main(String[] args) {
    	Flux
        	.fromIterable(List.of(1,5,6,7,8,9,10))
            .filter(number -> number > 4 && (number % 2 == 0))
            .reduce((total, n) -> total + n)
            .subscribe(System.out::println);
    }
}
  • Flux : 스프링은 publisher로써 0개 이상의 데이터를 발생시킬 수 있는 Flux를 지원합니다.
  • Flux.fromIterable(Interable) : 이터러블한 데이터들로 부터 데이터를 받아들입니다.
  • filter() : 스트림의 filter와 동일한 역할을 합니다. 해당 조건에 만족하는 데이터들만 남깁니다.
  • reduce() : 최종 결과를 연산합니다. 첫번째 파라미터로는 이전까지 요소들의 연산 결과이고 두번째 파라미터는 현재의 요소입니다.
  • subscribe() : publisher 의 데이터를 subscirber로 emit 합니다.
  • System.out::println : 메서드 레퍼런스로 구성된 subscriber입니다. emit된 데이터를 소비하는 주체입니다.
역할코드
PublisherFlux
데이터List.of(1,5,6,7,8,9,10)
EmitPublisher가 Subscriber에게 데이터를 보내는 행위
SubscriberSystem.out::println
Subscribe.subscribe()
SignalPublisher가 발생시키는 이벤트이며, 데이터를 하나씩 emit하는 것을 이벤트가 발생하는 것으로 간주하여 다른 컴포넌트에 전달하는것을 Signal을 전송한다고 표현합니다.
Operator동작을 수행하는 메서드. fromIterable(),filter(),reduce()
SequenceOperator로 구성된 체인코드
UpstreamSequence 상에서 Operator 보다 먼저 처리되는 Operator들. fromIterable()은 filter()의 Upstream
DownstreamSequence 상에서 Operator 보다 나중에 처리되는 Operator들. reduce()는 filter()의 Downstream



후기

Reactive는 프론트엔드 쪽에서 많이 들어봐서 프론트엔드에 국한되는 줄 알았으니 백엔드에서도 사용하는 프로그래밍 기법인 것을 처음 알게 되어 놀랐습니다. 기존에 스트림에 대해 관심을 가지고 코딩테스트 문제 풀때 자주 적용해 보았던게 이해하는 데 큰 도움이 되었습니다. 자세히 배우면 어떤 것들이 나올 지 기대 됩니다.




GitHub

https://github.com/ds02168/CodeStates_Spring/tree/main/section4-week3-TUR

profile
오늘도 내일도 화이팅!

0개의 댓글