본문으로 바로가기

리액티브 프로그래밍 개념정리(1)

category SPRING/리액티브 프로그래밍 2024. 5. 9. 17:05
728x90
반응형
SMALL

리액티브 프로그래밍을 하면서 나오는 개념들을 정리하자

함수형 인터페이스란?

  • 추상메서드가 하나인 것

함수형 프로그래밍에서는 함수를 일급 시민으로 취급한다.

  • 일급 시민은 함수를 값으로 취급한다는 고급진 표현이다. 어떤 함수 호출시 함수 자체를 파라미터로 전달할 수 있음
  • 람다 표현식, 메서드 래퍼런스은 함수형 인터페이스의 추상메서드를 간결하게 표현하기 위해 사용한다.

Reactor란?

  • Spring framework 팀의 주도 하에 개발된 리액티브 스트림즈의 구현체, 리액티브 프로그래밍을 위한 라이브러리라고도 말할 수 있다.

Hot과 Cold의 의미

  • Hot swap은 컴퓨터의 시스템이 전원이 켜져 있는 상태에서 디스크 등의 장치를 교체할 경우 시스템을 재시작하지 않고서 바로 장치를 인식하는 것
  • Hot deploy는 서버를 재시작하지 않고서 소프트웨어의 변경사항을 반영할 수 있는 기능
  • 리액티브 프로그래밍에서는 Hot은 무언가 새로 시작하지 않는것, Cold는 새로 시작하는 것

build.gradle

dependencies {
    implementation 'io.projectreactor:reactor-core:3.4.13'
}

스터디 코드

public class TestMain {

    public static void main(String[] args) throws InterruptedException {
        hot시퀀스1();

    }

    public static void 기본flux사용법(){
        Flux<String> seq = Flux.just("hello", "yjy");
        seq.map(String::toLowerCase)
                .subscribe(System.out::println);
    }

    // 데이터를 emit하진 않지만, 작업이 끝났음을 알리고, 후처리 하고 싶을때
    public static void monoByempty(){
        Mono.empty()
                .subscribe(
                        none -> System.out.println("emitted onNext signal"),
                        error -> {},
                        () -> System.out.print("# emitted onComplete signal")
                );
    }

    public static void flux활용(){
        Flux.fromArray(new Integer[]{3,6,7,9})
                .filter(num -> num>6)
                .map(num -> num*2)
                .subscribe(System.out::println);
    }

    //justOrEmpty는 내부 파라미터로 null이 가능하며, null일 경우 empty 오퍼레이터를 호출
    //concatWith은 두 개의 데이터 소스만 연결 가능
    public static void flux의justOrEmpty오퍼레이션_concatWith오퍼레이션(){
        Flux<String> flux = Mono.justOrEmpty("Steve")
                .concatWith(Mono.justOrEmpty("Jobs"));

        flux.subscribe(System.out::println);
    }
    //concat은 여러개의 데이터 소스를 연결, 그러므로 Flux 타입이다.
    //collectList은 emit하는 데이터를 모아서 List 원소로 포함시킨 새로운 데이터 소스, Mono 타입이다.
    public static void flux의concat오퍼레이션_collectList오퍼레이션(){
        Flux.concat(
                Flux.just("윤", "주", "영"),
                Flux.just("김", "민", "수"),
                Flux.just("장", "성", "엽"))
                .collectList()
                .subscribe(System.out::println);
    }
    //구독이 발생할 때마다 구독 시점과 상관없이 데이터를 처음부터 끝까지 얻는다.
    //ex) 신문을 5월부터 구독했으면 1~5월 신문을 모두 볼 수 있음.
    public static void cold시퀀스(){
        Flux<String> coldFlux =
                Flux.fromIterable(Arrays.asList("윤주영", "김민수", "장성엽"))
                        .map(String::toLowerCase);

        coldFlux.subscribe(name -> System.out.println("subscribe 1 :::"+ name));
        coldFlux.subscribe(name -> System.out.println("subscribe 2 :::"+ name));
    }

    //구독이 발생된 시점 이전의 데이터는 얻지 못한다. 구독이 발생한 시점 이후의 데이터만 얻을 수 있다.
    //ex) 신문을 5월부터 구독했으면 5월 신문부터 볼 수 있음.
    public static void hot시퀀스() throws InterruptedException {
        String[] singers = {"김범수", "나얼", "박효신", "이수"};
        System.out.println("콘서트 시작");

        Flux<String> concertFlux =
                Flux.fromArray(singers)
                        .delayElements(Duration.ofSeconds(1))
                        .share(); //cold sequence를 hot sequence로 동작하게 만들어주는 operator

        concertFlux.subscribe(
                singer -> System.out.println(Thread.currentThread().getName()+" Subscriber1 watching ::: " + singer)
        );

        Thread.sleep(2000);

        concertFlux.subscribe(
                singer -> System.out.println(Thread.currentThread().getName()+" Subscriber2 watching ::: " + singer)
        );
        Thread.sleep(3000);
    }

    //cache 오퍼레이션은 Cold Sequence -> Hot Sequence 로 변경해준다. emit된 데이터를 캐시한뒤 구독이 발생할 때마다 캐시된 데이터를 전달
    //결국 동일한 데이터를 얻게 된다.
    public static void hot시퀀스1() throws InterruptedException {
        Mono<String> usedCache = getToken().cache();

        usedCache.subscribe(token -> System.out.println("sub1 ::: " + token));
        Thread.sleep(5000);
        usedCache.subscribe(token -> System.out.println("sub2 ::: " + token));
        Thread.sleep(2000);

    }

    //just는 Mono가 생성된 시점에 값이 이미 결정되어 있지만,
    //defer는 실제 구독이 발생할 때 값이 결정된다. 매번 새로운 값을 생성하거나 상태를 갱신할 수 있다.
    public static Mono<String> getToken(){
        return Mono.defer(() -> Mono.just(nowDate()));
    }

    public static String nowDate(){
        return LocalDateTime.now().toString();
    }

}
728x90
반응형
LIST

'SPRING > 리액티브 프로그래밍' 카테고리의 다른 글

리액티브 프로그래밍 개념정리(2)  (0) 2024.05.10