태임쓰의 개발블로그

[RxJava2] #1. 리액티브 프로그래밍과 RxJava 본문

Rx/RxJava

[RxJava2] #1. 리액티브 프로그래밍과 RxJava

태임태임 2018. 9. 8. 22:02

1. 리액티브 프로그래밍과 RxJava

1.1 리액티브 프로그래밍이란?

자바 언어와 리액티브 프로그래밍은 대략 두 가지 관계가 있다고 정리 할 수 있음.

  • 기존 pull 방식의 프로그래밍 개념을 push 방식의 프로그래밍 개념으로 바꾼다.

    • 예를 들어, 전국 매장의 매출액 정보를 실시간으로 집계한다고 할 때, 기존에는 각 매장의 변화 상황을 데이터베이스에서 가져(pull)와야한다. 하지만, 리액티브 프로그래밍서는 데이터의 변화가 발생했을 때 변경이 발생한 곳에서 새로운 데이터를 보내(push 방식)준다.

  • 함수형 프로그래밍의 지원을 받는다.

    • 우리가 아는 콜백이나 옵서버 패턴을 넘어 RxJava기반의 리액티브 프로그래밍이 되려면 함수형 프로그래밍이 필요

    • 콜백이나 옵서퍼 패턴은 옵서버가 1개이거나 단일 스레드 환경에서는 문제가 없지만 멀티 스레드 환경에서는 많은 주의가 필요하다. (대표적 예 : 데드락, 동기화 문제)

    • 함수형 프로그램은 부수 효과가 없다. (부수효과: 같은 자원에 여러 스레드가 경쟁조건에 빠지게 되었을 때 예측할 수 없는 잘못된 결과가 나오는 현상.)

      • 한 두 개의 스레드가 있을 때는 정상 동작하다가 수십 수백 개의 스레드가 동시에 단일 자원에 접근하면 계산 결과가 꼬이고 디버깅하다가 매우 어렵다.

    • 함수형 프로그래밍은 부수 효과가 없는 순수 함수를 지향한다. 따라서, 멀티스레드 환경에서도 안전하다.

  • 한마디로, “함수형 프로그래밍 도구를 활용한 비동기 프로그래밍”


1.2 RxJava 만든 이유

넷플릭스에서 RxJava를 만들게 된 핵심적인 이유 3가지

  1. 동시성을 적극적으로 끌어안을 필요가 있다. (Embrance Concurrency)

    자바가 동시성 처리를 하는 데 번거로움이 있다. 이를 해결하려고 넷플릭스는 클라이언트의 요청을 처리하는 서비스 계층에서 동시성을 적극적으로 끌어안았다. 클라이언트의 요청을 처리할 때 다수의 비동기 실행 흐름(스레드 등)을 생성하고 그것의 결과를 취합하여 최종 리턴하는 방식으로 내부 로직을 변경했다.

  2. 자바 Future를 조합하기 어렵다는 점을 해결해야 한다. (Java Futures are Expensive to Compose)

    2013년 당시 자바 8에서 제공하는 CompletableFuture 같은 클래스가 제공되지 않았기 때문이다. 그래서 비동기 흐름을 조합할 방법이 거의 없었다. RxJava에서는 이를 해결하려고 비동기 흐름을 조합할 수 있는 방법을 제공한다. RxJava에서는 조함하는 실행 단위를 리액티브 연산자라고 한다.

  3. 콜백 방식의 문제점을 개선해야 한다. (Callbacks Have Their Own Problems)

    콜백이 콜백을 부르는 콜백 지옥 상황이 코드의 가독성을 떨어뜨리고 문제 발생 시 디버깅을 어렵게 만든다.

    비동기 방식으로 동작하는 가장 대표적인 프로그래밍 패턴은 콜백이다. 그래서 RxJava는 콜백을 사용하지 않는 방향으로 설계하여 이를 해결했다.

리액티브 프로그래밍은 비동기 연산을 필터링, 변환, 조합하여 위 세가지 핵심이유를 해결할 수 있다.


1.3 RxJava 맛보기

Observable.just("Hello", "RxJava2")
  .subscribe(System.out::println);
  • Observable 클래스 : 리액티브 프로그래밍이 Observable에서 시작

  • just() 함수 : 가장 단순한 Observable 선언 방식.

  • subscribe() 함수 : Observable을 구독. Observable은 subscribe() 함수를 호출해야 비로소 변화한 데이터를 구독자에게 발행한다.

    • just()함수만 호출하면 데이터를 발행하지 않음.

  • 반드시 데이터를 수신할 구독자가 subscribe()를 호출해야 Observable에서 데이터가 발행된다.

  • System.out::println

    • data -> System.out.println(data)


1.4 RxJava 소개, 특징

  • RxJava는 함수형 프로그래밍

    • 함수형 프로그래밍은 부수효과가 없는 순수 함수를 지향하므로 스레드에 안전하다.

  • 자바는 함수형 언어가 아니므로 RxJava 라이브러리는 순수 함수로 작성된 리액티브 연산자를 제공.

    • 이 리액티브 연산자 덕분에 RxJava는 리액티브 프로그래밍이 되는 것

    • 리액티브 연산자를 활용하면 목적을 달성할 수 있는 도구인 ‘함수형 프로그래밍’ 방식으로 ‘스레드에 안전한 비동기 프로그램’을 작성할 수 있음

  • RxJava가 어려운 이유

    • 함수형 연산자를 어떻게 호출해야 하는지 모르기 때문

    • “RxJava는 안드로이드 개발자 사이에서 가장 화제다. 유일한 단점은 처음에 배우기 어렵다는 것이다.”

  • 권장하는 학습순서

  1. Observable 클래스 명확하게 이해 (특히 뜨거운(Hot) Observable과 차가운(Cold) Observable의 개념을 꼭 이해해야 함)

  2. 간단한 예제로 map(), filter(), reduce, flatMap() 함수의 사용법을 익힙니다.

  3. 생성 연산자, 결합 연산자, 변환 연산자 등 카테고리별 주요 함수를 공부

  4. 스케줄러의 의미를 배우고 subscribeOn()과 observeOn() 함수의 차이를 알아둡니다.

​5. 그 밖의 디버깅, 흐름 제어 함수를 익힙니다.

2장(Observable) => 3장(map-filter-reduce) => 4장(주요 연산자) => 5장(RxJava 때문에 달라지는 비동기 프로그래밍, 스케줄러) => 6장(RxAndroid) => 7장(디버깅, 예외처리)

  • 자바 8을 사용하지 않아도 됨. 자바 8에서 제공하는 Consumer, Predicate, Function과 같은 함수형 인터페이스를 자체 구현했으므로 자바 6 이상이면 동작.

    • But, 8의 람다 표현식과 함수 레퍼런스를 활용하는 코드는 가독성을 좋게함. (람다식 & 함수 레퍼런스 공부)


1.5 마블 다이어그램

  • 마블 다이어그램은 RxJava를 이해하는 핵심 도구

  • RxJava는 마블 다이어그램으로 배운다고 해도 과언이 아니다.



Reference


Comments