티스토리 뷰

개발

리액티브 시스템, 프로그래밍에 대해

달리는개발자 2018. 2. 12. 00:35
LIGHTBEND CTO이자 쉽게 리액티브 분산 시스템을 만들 수 있는 akka라는 툴킷을 만든 Jonas Bonér와 Viktor Klang가 기고한 글 리액티브 프로그래밍 Vs 리액티브 시스템(원문 : Reactive programming vs. Reactive systems) 을 먼저 읽는게 도움이 많이 됩니다.

리액티브 시스템(Reactive System)
리액티브는 일련의 설계 원칙이고 리액티브 시스템은 "리액티브 선언문"에 정의된 바와 같이 오늘날 응용프로그램들이 마주한 증가하는 요구사항(밀리초의 빠른 응답, 100% 가동률 등등)들을 충족할 수 있도록 잘 준비된 현대적 시스템을 구축하기 위한 일련의 아키텍쳐 설계 원칙들입니다.
리액티브 선언문에서는 응답성이 좋고 장애가 발생하더라도 응답을 유지하는 회복성, 작업량이 변화하면 그에 맞게 할당된 자원을 변화시키는 탄력성이 있고 느슨한 결합, 위치 투명성을 위한 메시지기반으로 동작하는 시스템이라 정의합니다.

리액티브 프로그래밍(Reactive Programming)
논블럭킹, 비동기의 이벤트 중심형이며 제어흐름보다는 데이터흐름에 중점을 둔 개발방법입니다.
또한 iterator design pattern과도 비교가 되는데 iterator가 pull 기반이라면 reactive streams는 push 기반입니다.
명령형이 아닌 선언형 프로그래밍인데 위키백과에 보면 선언형 프로그래밍은 다음과 같이 나와 있습니다.


명령형 프로그램은 알고리즘을 명시하고 목표는 명시하지 않는 데 반해 선언형 프로그램은 목표를 명시하고 알고리즘을 명시하지 않는 것이다.



Springframework5에서 Spring WebFlux라는 것을 통해 reative programming으로 웹어플리케이션 만들 수 있도록 지원합니다.

Springframework5 reactive stack vs servlet stack

스프링프레임워크 개발자이자 스프링 부트를 만든 Phil Webb 이란 분의 SpringOne Platform 2017 동영상인데 19분 정도에 reactive stack 과 servlet stack을 왜 선택해야 하느냐? 라는 질문의 답이 있습니다.

우선 영상을 보시면 이해가 쉬울 것 같습니다.

블럭킹과 서블릿에 대한 이해는 스레드를 수영장의 레인으로 생각해서 각각의 레인은 외부 요청을 처리하기 위한 프로세스나 스레드의 시작과 끝이라고 가정합니다. 

일반적인 블럭킹 방식에서는 느린 요청이 오면 어플리케이션 성능 저하가 일어나고 해당 부분을 제거하기 위해서 스레드를 추가하는 방법을 사용하는데 이 부분은 자원 사용으로 인해 비용 문제가 발생합니다.

논블럭킹 방식에서는 요청 후에 해당 스레드가 대기하지 않기 때문에 더 효율적입니다.

spring webflux


Project Reactor 문서의 리액티브 프로그래밍 소개

현대 어플리케이션에서 성능은 주요한 관심사이다.

성능의 향상을 위해서 더 많은 쓰레드와 하드웨어 자원을 사용해서 병렬화하거나 자원을 좀 더 효율화하는 방법을 찾는다.


대개 자바 개발자들이 블럭킹 코드를 사용하고 병목이 생기면 쓰레드를 늘린다.

블로킹 코드는 데이터베이스 요청이나 네트워크를 통한 호출 시 데이터를 기다리는 동안 유휴상태로 있기 때문에 낭비이다.

병렬화는 묘책, 특효약(silver bullet)이 아니다.

하드웨어를 최대로 사용하기 위해서 필요하지만 자원 낭비와 복잡해지는 문제가 있다.


자원 효율화를 위해서 비동기 프로그래밍을 한다.

주로 자바에서는 Callbacks과 Futures를 사용한다.


Example Of Callback Hell 



userService.getFavorites(userId, new Callback>() { 
  public void onSuccess(List list) { 
    if (list.isEmpty()) { 
      suggestionService.getSuggestions(new Callback>() {
        public void onSuccess(List list) { 
          UiUtils.submitOnUiThread(() -> { 
            list.stream()
                .limit(5)
                .forEach(uiList::show); 
            });
        }

        public void onError(Throwable error) { 
          UiUtils.errorPopup(error);
        }
      });
    } else {
      list.stream() 
          .limit(5)
          .forEach(favId -> favoriteService.getDetails(favId, 
            new Callback() {
              public void onSuccess(Favorite details) {
                UiUtils.submitOnUiThread(() -> uiList.show(details));
              }

              public void onError(Throwable error) {
                UiUtils.errorPopup(error);
              }
            }
          ));
    }
  }

  public void onError(Throwable error) {
    UiUtils.errorPopup(error);
  }
});



Callback Code와 같은 Reactor Code


userService.getFavorites(userId) 
           .flatMap(favoriteService::getDetails) 
           .switchIfEmpty(suggestionService.getSuggestions()) 
           .take(5) 
           .publishOn(UiUtils.uiThreadScheduler()) 
           .subscribe(uiList::show, UiUtils::errorPopup); 


Timeout과 Fallback이 있는 Reactor Code


userService.getFavorites(userId)
           .timeout(Duration.ofMillis(800)) 
           .onErrorResume(cacheService.cachedFavoritesFor(userId)) 
           .flatMap(favoriteService::getDetails) 
           .switchIfEmpty(suggestionService.getSuggestions())
           .take(5)
           .publishOn(UiUtils.uiThreadScheduler())
           .subscribe(uiList::show, UiUtils::errorPopup);




리액티브 프로그래밍을 하기 위한 여러 기술들

Reactive Streams : 단순 API, 직접 구현해야 됨. JDK9에서 java.util.concurrent.Flow로 통합됨.

RxJava : 넷플릭스에서 만듬.

Reactor : 피보탈에서 만들고 spring 5에서 사용.

Spring Framework 5.0 : 내부적으로 reactor를 사용.

Ratpack : 고성능 HTTP 어플리케이션을 만들기 위한 라이브러리 집합.

Akka : Scala나 java로 Actor pattern을 사용해서 어플리케이션을 만들 수 있는 toolkit


결론

무조건 리액티브 프로그래밍을 해야된다라기보다 좀 더 자원효율적이고 성능이 좋은 어플리케이션을 만들 때 중요하다라고 생각하는게 맞을 것 같습니다.
Springframework 5 FAQ를 보면 블록킹JDBC, JPA API를 사용하거나 논블럭킹 프로그래밍에 대한 이점이 없으면 그냥 Spring MVC를 사용하면 되다고 합니다.
그 외에 RestTemplate을 대체할 WebClient를 사용해서 혼합한 방식을 사용하는 것도 고려해 볼만 합니다.
youtube에 리액티브 시스템이나 프로그래밍에 대한 동영상이 많은데 특히 josh long 의 라이브코딩 영상이 도움이 많이 됩니다. ^^

참고

리액티브 프로그래밍 Vs 리액티브 시스템

Reactive programming vs. Reactive systems

https://www.reactivemanifesto.org/ko

https://docs.spring.io/spring/docs/5.0.0.BUILD-SNAPSHOT/spring-framework-reference/html/web-reactive.html

https://dzone.com/articles/reactive-programming-with-spring-5

https://projectreactor.io/docs/core/release/reference/#_blocking_can_be_wasteful


spring blog

https://spring.io/blog/2016/02/09/reactive-spring

https://spring.io/blog/2016/04/19/understanding-reactive-types

https://spring.io/blog/2016/06/07/notes-on-reactive-programming-part-i-the-reactive-landscape

https://spring.io/blog/2016/06/13/notes-on-reactive-programming-part-ii-writing-some-code

https://spring.io/blog/2016/07/28/reactive-programming-with-spring-5-0-m1

반응형
댓글
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함