SlideShare a Scribd company logo
안드로이드 동시성 프로그래밍 - 
RxJava를 활용한 Functional 
Reactive Programming 
최정열 / Sivaworks / 라 스칼라 코딩단䯽 
조현태 / 라 스칼라 코딩단 / waynejo1024@gmail.com
RxJAVA?!
RxJava란? 
Excel䯽 
- 각 항목에 변화가 있으면 자동으로 감지해서 값을 갱신해준다.䯽 
A 
B 
C 
1 2 
10 20 
30 = A1+A2
RxJava란? 
Event Three䯽 
- 각각의 서로 다른 이벤트 소스들을 묶어서 하나의 흐름을 만들어 내는 도구䯽 
각종 센서 이벤트 
네트워크 정보 
사용자 입력 
원하는 결과의 스트림
RxJava - Observable, Observer란? 
Observable - 관측 가능한 값의 흐름를 나타내는 객체 (생산자)䯽 
Observer - 값의 흐름를 받는 객체 (소비자)䯽 
Observable Observer 
Button 
Click String 
Network 
Byte[] 
Keyboard 
Text View 
Alert 
Image View 
Input Text 
Error 
Image 
String 
Visibility 
Image 
Event
RxJava - Observable, Observer란? 
Observable - 관측 가능한 값의 흐름를 나타내는 객체 (생산자)䯽 
- subscribe 함수를 통해 구독이 가능하며, 구독자에게 값을 흐름을 알려준다.䯽 
Observer - 값의 흐름를 받는 객체 (소비자)䯽 
- Observable의 값의 흐름에 따라 onNext, onError, onCompelete를 호출 받는다.䯽 
OnNext OnComplete 
OnError
RxJava - Observable, Observer란? 
eventSource.subscribe((event)-> { 
// observer 
} 
}); 
Observable 
Observer
RxJava - map 
키보드 입력값 출력 시나리오䯽 
- 키를 입력하면 TextView에 출력하는 시나리오 
EditText 
Function 
TextView 
Text B 
fun(x) 
TextB-1 
Text C 
fun(x) 
TextC-1 
Text A 
fun(x) 
TextA-1
RxJava - map 
map䯽 
- 전달되는 값에 함수를 적용해서 새로운 값을 만들어냄 䯽 
eventSource.map((value) -> fun(value)) 
fun(x) 
Value1 Value2
RxJava - map 
map䯽 
- 전달되는 값에 함수를 적용해서 새로운 값을 만들어냄 䯽 
buttonClick 
.map((value) -> {return fly(value);}) 
.subscribe(); 
buttonClick.setOnClickListener( 
(v) -> {value.fly();} 
);
RxJava - flatMap 
키보드 입력값 출력 시나리오䯽 
- 키를 입력하면 추천 검색어를 서버에서 받아와 출력하는 시나리오 
EditText 
Async Function 
TextView 
fun(x) 
TextA-1 
Text A 
fun(x) 
TextB-1 
Text B 
fun(x) 
TextC-1 
Text C
RxJava - flatMap 
flatmap䯽 
- 미래에 0개 ~ n개의 결과를 반환하는 함수를 적용한다.䯽 
eventSource.flatMap((value) -> {return longlongFunc(value);}) 
.subscribe((Result) -> { 
// show result. 
}); 
Observable
RxJava - flatMap 
flatmap䯽 
- 이벤트 결과가 아닌 다른 값을 사용할 수 있습니다.䯽 
confirmBtnClickEvent.flatMap((value) -> { 
return userId.flatMap((userId) -> { 
return login(userId); 
}); 
}).subscribe((Result) -> { 
// show result. 
}); 
Push 
Pull
RxJava - flatMap 
flatmap䯽 
- 순차적으로 비동기 작업을 요청할 수 있다.䯽 
confirmBtnClickEvent.flatMap((value) -> { 
return startupEngine(); 
}).flatMap((value) -> { 
return setupWings(); 
}).flatMap((value) -> { 
return takeOff(); 
}).subscribe((Result) -> { 
// show result. 
});
이벤트 합성
RxJava - combineLatest, merge 
combineLatest䯽 
- Observable 들의 이벤트들 중 가장 최신 이벤트 값을 합성해서 사용한다.䯽 
Observable.combineLatest( 
(altitude, latitude, longitude) -> { 
getDirection(altitude, latitude, longitude); 
} 
);
RxJava - combineLatest, merge 
combineLatest䯽 
- Observable 들의 중 가장 최신의 이벤트 값을 합성한다.䯽 
색상 combineLatest( ) 
1 
모양 
결과 
2 
2 
3 
4 
3 4
RxJava - combineLatest, merge 
모형 비행기 예제 시나리오䯽 
• 사용자가 ‘take off’ 버튼을 누르면䯽 
- 비동기로 엔진을 켠다.䯽 
- 엔진이 켜지면 비동기로 속도와 고도를 각각 동시에 높인다.䯽 
- 속도와 고도가 모두 높아지고 1초뒤에 Status 창에 “GREEN” 이라고 출력한다.䯽 
사용자가 다른 버튼을 누른경우, 현재 진행중인 비동기 작업까지만 처리하고 더이상의 이전 작업은 처리하지 않는다. 
• 사용자가 ‘landing’ 버튼을 누르면䯽 
- 속도와 고도를 각각 동시에 낮춘다.䯽 
- 속도와 고도가 각각 낮아지면 엔진을 멈춘다.䯽 
- 엔진이 멈추고 1초뒤에 Status 창에 “RED” 라고 출력한다.䯽
RxJava - combineLatest, merge 
switchMap䯽 
- Observable 에서 매 이벤트마다 새로운 Observable을 적용하여 사용한다.䯽 
remoteControl switchMap( ) 
altitude 
engine 
On 
Off 
landing 
On 
On Off
RxJava - combineLatest, merge 
switchMap䯽 
- Observable 에서 매 이벤트마다 새로운 Observable을 적용하여 사용한다.䯽 
receivedEvent.switchMap(remoteEventType -> { 
switch (remoteEventType) { 
case LANDING: 
return Observable.zip( 
setupAltitude(0), setupSpeed(0), (event1, event2) -> null) 
.flatMap(event -> setupEngine(0)); 
case TAKE_OFF: 
return setupEngine(100).flatMap( 
event -> Observable.zip( 
setupAltitude(100), setupSpeed(100), (event1, event2) -> null) 
); 
}
Thread 관리
RxJava - Scheduler 
이미지 다운로드 시나리오䯽 
- 버튼을 클릭하면 이미지를 다운받아 표시하는 예제 
UI Thread 
IO Thread 
UI Thread 
Click 
Image 
Image
RxJava - Scheduler 
subscribeOn - 비동기 결과값을 가져오는 쓰레드를 결정한다 䯽 
observeOn - 결과 값을 처리할 쓰레드를 결정한다. 
ClickEvents.flatMap((event) -> 
asyncDownloadImage(params).subscribeOn(Schedulers.io()); 
) 
.observeOn(AndroidSchedulers.mainThread()) 
.subscribe((image) -> { 
// show result. 
});
RxJava - Scheduler 
observeOn䯽 
- 결과 값을 처리할 쓰레드를 결정한다. 
Event 
observeOn(MainThreadScheduler) 
Thread 
Main Thread
RxJava - Scheduler 
subscribeOn䯽 
- 비동기 결과값을 가져오는 쓰레드를 결정한다. 
subscribeOn(IOThreadScheduler) 
IO Thread 
Event 
IO Thread
RxJava - Scheduler 
- 단일 쓰레드에서 이벤트 관리 䯽 
Observable<Action0> request = // 요청 리스트 
.observeOn(Schedulers.from(Executors.newSingleThreadExecutor()) 
.subscribe(Action0::call); 
Task 요청 
쓰레드 지정 
Single Thread 
Task Task Task 
Task Task 
Thread 1 Thread 2
시간 관리
RxJava - Time 
예제) delay䯽 
- 시간 지연 기능䯽 
// 입력된 Text를 1초 후에 보여줍니다. 
inputText.delay(1, TimeUnit.SECONDS) 
.subscribe(new SetTextAction(textView));
RxJava - Time 
delay䯽 
- 모든 이벤트를 주어진 시간만큼 지연한다.䯽 
1 2 3 
Observer 
1 2 3 
delay( )
RxJava - Time 
throttleFirst䯽 
- 한 이벤트 후의 일정 시간만큼의 이벤트를 무시한다.䯽 
Observer 
3 5 
throttleFirst( ) 
1 
1 
3 
5 
2 4
RxJava - Time 
throttleWithTimeout䯽 
- 일정 시간만큼의 이벤트가 없는 경우에 가장 마지막 이벤트를 전달한다.䯽 
Observer 
1 2 3 4 
1 4 
throttleWithTimeout( )
예외 관리
RxJava - Error Handling 
retry䯽 
- 실패한 경우 자동으로 재시도 합니다.䯽 
GetDataFromNetwork() 
.subscribeOn(Schedulers.io()) 
.observeOn(AndroidSchedulers.mainThread()()) 
.subscribe( 
(img) -> {showImage(img);}, 
(e) -> {showError(e);}, 
() -> {showComplete();} 
) 
1 
Observer 
1 X 
Error Handling
RxJava - Error Handling 
retry䯽 
- 실패한 경우 자동으로 재시도 합니다.䯽 
GetDataFromNetwork() 
.subscribeOn(Schedulers.io()) 
.retry() 
Observer 
retry() 
1 X 
1 
3 
3
RxJava - Error Handling 
retry(int n)䯽 
- 실패한 경우 자동으로 n회 재시도 합니다.䯽 
GetDataFromNetwork() 
.subscribeOn(Schedulers.io()) 
.retry(1) 
Observer 
retry(1) 
1 X 
1 
2 X 
2 
X
RxJava - Error Handling 
retryWhen(Observable)䯽 
- 실패한 경우 자동으로 재시도 합니다.䯽 
Observer 
// 3초마다 재시도 
return observable.delay(3, TimeUnit.SECONDS); 
retryWhen() 
GetDataFromNetwork() 
1 X 
1 
3 
.subscribeOn(Schedulers.io()) 
.retryWhen((observable) -> 
3 
{ 
}) 
delay(3, SECODS)
RxJava - Map? FlatMap? 
Map을 사용해야할지, FlatMap을 사용해야 할지 구분이 힘들다면?䯽 
- 기능이 실패했을때, 다시 작업을 시작하거나 작업을 취소할 범위로 구분䯽 
click func save 
map() map() 
retry()
RxJava - Map? FlatMap? 
Map을 사용해야할지, FlatMap을 사용해야 할지 구분이 힘들다면?䯽 
- 기능이 실패했을때, 다시 작업을 시작하거나 작업을 취소할 범위로 구분䯽 
click func save 
map() flatMap() 
retry()
MVVM With RxJava
RxJava - MVVM 
Loading Indicator 예제䯽 
버튼을 클릭하면 다운로드가 완료될 때까지 Loading indicator를 표시한다.䯽 
// 버튼 클릭 이벤트 
Observable<Void> btnClickEvent = … 
Observable.merge( 
btnClickEvent.map((event) -> true), 
btnClickEvent.flatMap((event)-> 
downloadFunction().subscribeOn(Schedulers.io()) 
).map((event) -> false).observeOn(AndroidSchedulers.main()) 
.subscribe((isVisible) -> { 
v.setVisibility(isVisible ? View.VISIBLE : View.GONE); 
)} 
View Model 
View
RxJava - MVVM 
Model View 
User Info 
String String 
Login Info 
String 
Profile Image 
Text View 
Alert 
Image View 
Input Text 
Error 
Image 
Image 
Visibility 
Image 
Event 
View Model 
운영체제에䯽 
의존적 
운영체제에䯽 
독립적
RxJava - MVVM 
Model View 
User Info 
String String 
Login Info 
String 
Profile Image 
Text View 
Alert 
Image View 
Input Text 
Error 
Image 
Image 
Visibility 
Image 
Event 
View Model 
테스트 불가 
능 코드 
테스트 가능 
코드 
연결 코드
테스트가 어려운 부분 - Thread 
public class SchedulerManager { 
private static Scheduler main = AndroidSchedulers.mainThread(); 
private static Scheduler io = Schedulers.io(); 
public static Scheduler main() { 
return main; 
} 
public static Scheduler io() { 
return io; 
} 
} 
기본적으로는 상황에 맞는 
Scheduler를 할당해준다.
테스트가 어려운 부분 - Thread 
@Override 
protected void setUp() throws Exception { 
super.setUp(); 
testScheduler = Schedulers.test(); 
SchedulerManager.setMain(testScheduler); 
SchedulerManager.setIO(testScheduler); 
} 
테스트시에는, 테스트를 위한 
Scheduler를 지정한다.
테스트가 어려운 부분 - Thread 
ArrayList<String> testResults = new ArrayList<>(); 
remoteAirplaneModel.statusText.subscribe(testResults::add); 
mainActivityModel.takeoffBtn.emit(); 
assertEquals(1, testResults.size()); 
testScheduler.advanceTimeBy(2, TimeUnit.SECONDS); 
assertEquals(2, testResults.size());
테스트가 어려운 부분 - Thread 
Thread 1 testScheduler.advanceTimeBy(2, TimeUnit.SECONDS) 
Event Event 
테스트시의 단일 쓰레드 흐름 
Thread 2 
ArrayList<String> testResults = new ArrayList<>(); 
remoteAirplaneModel.statusText.subscribe(testResults::add); 
mainActivityModel.takeoffBtn.emit(); 
assertEquals(1, testResults.size()); 
testScheduler.advanceTimeBy(2, TimeUnit.SECONDS); 
assertEquals(2, testResults.size());
주의 사항
RxJava - 실수하기 쉬운 Memory 관리 
Observable -> Observer 사이의 연산은 Subscribe 횟수 만큼 반복䯽 
- 함수에 side effect가 존재하면 결과가 예측과 다를 수 있습니다..䯽 
source 
Custom 
Action1 
Function 
Custom 
Action2
RxJava - 실수하기 쉬운 Memory 관리 
Observable -> Observer 사이의 연산은 Subscribe 횟수 만큼 반복䯽 
- 함수에 side effect가 존재하면 결과가 예측과 다를 수 있습니다..䯽 
Observable<Integer> o = Observable.from(Arrays.asList(0, 1, 2, 3, 4)); 
Observable<Integer> sumObservable = o.map(new Func1<Integer, Integer>() 
int sum = 0; 
@Override 
public Integer call(Integer integer) { 
sum += integer; 
return sum; 
} 
}); 
sumObservable.subscribe(System.out::println); 
sumObservable.subscribe(System.out::println); 
0 
1 
3 
6 
10 
10 
11 
13 
16 
20
RxJava - 실수하기 쉬운 Memory 관리 
cache()䯽 
- 계산 결과를 cache 하여 반복 계산을 방지합니다.䯽 
source 
Custom 
Action1 
Function 
Custom 
Action2 
cache 
Relplay 
Subject
RxJava - 실수하기 쉬운 Memory 관리 
Observable -> Observer 사이의 연산은 Subscribe 횟수 만큼 반복䯽 
- 함수에 side effect가 존재하면 결과가 예측과 다를 수 있습니다..䯽 
Observable<Integer> o = Observable.from(Arrays.asList(0, 1, 2, 3, 4)); 
Observable<Integer> sumObservable = o.map(new Func1<Integer, Integer>() 
int sum = 0; 
@Override 
public Integer call(Integer integer) { 
sum += integer; 
return sum; 
} 
}).cache(); 
sumObservable.subscribe(System.out::println); 
sumObservable.subscribe(System.out::println); 
0 
1 
3 
6 
10 
0 
1 
3 
6 
10
RxJava - 실수하기 쉬운 Memory 관리 
cache(n)䯽 
- 계산 결과를 n개만 cache 하여 반복 계산을 방지합니다.䯽 
source 
Custom 
Action1 
Function 
Custom 
Action2 
cache(n) 
Relplay 
Subject(n)
RxJava - 실수하기 쉬운 Memory 관리 
onCreate / onDestroy䯽 
- onCreate에서 subscribe되고 onCompelete가 불리지 않는 경우 영원히 메모리에 존재 
하게 됩니다.䯽 
Subscription subscribe; 
@Override 
protected void onCreate(Bundle savedInstanceState) { 
subscribe = observable.subscribe(new Action1<T>() { 
@Override 
public void call(T aT) { 
// 부모 Activity Reference “this$0” 
} 
}); 
} 
@Override 
protected void onDestroy() { 
subscribe.unsubscribe(); 
}
RxJava - 실수하기 쉬운 Memory 관리 
onCreate / onDestroy䯽 
- onCreate에서 subscribe되고 onCompelete가 불리지 않는 경우 영원히 메모리에 존재 
하게 됩니다.䯽 
observable Subscription 
Activity 
or 
View 
subscribe() new Action1()
결론
왜 Reactive Programming 인가? 
프로그램의 일관성을 유지하는 통일된 방식이 필요䯽 
- Event, Thread, 시간, Exception을 처리하기에는 Callback은 조합이 어렵다.䯽 
- 그러므로 개개인이 각각의 방식으로 조합하여 복잡성이 증대된다.䯽 
통일된 방식으로 Event, Thread, Time, Exception을 처리할 수 있는 방법을 제공 
단순 객체지향으로는 큰 프로그램을 만들기 어렵다.䯽 
- 객체지향은 내부의 상세한 구현을 숨긴다.䯽 
- 이로인해 잘 만들지 않으면 기대와 다른 동작들로 인해 복잡도가 증가한다.䯽 
- 이를 해결하기 위해 객체가 객체를 감싸고 또다시 감싸는 등의 문제가 발생한다.䯽 
외부에 제공할 수 있는 읽기 전용의 Observable을 제공하며 내용을 감추지 않아도 됨
왜 Reactive Programming 인가? 
보다 테스트하기 쉬운 구조가 필요하다.䯽 
- 일반적인 구현에서는 가장 내부 깊은 곳에 View, Activity 등이 존재한다.䯽 
- 이로 인해 테스트에서 View를 제거하지 못해 테스트가 힘들어진다.䯽 
MVVM의 구조를 활용하여 OS 종속적인 부분을 최대한 배제하고 테스트할 수 있음
감사합니다.

More Related Content

What's hot

7가지 동시성 모델 - 데이터 병렬성
7가지 동시성 모델 - 데이터 병렬성7가지 동시성 모델 - 데이터 병렬성
7가지 동시성 모델 - 데이터 병렬성
HyeonSeok Choi
 
자바8 스트림 API 소개
자바8 스트림 API 소개자바8 스트림 API 소개
자바8 스트림 API 소개
beom kyun choi
 
EcmaScript6(2015) Overview
EcmaScript6(2015) OverviewEcmaScript6(2015) Overview
EcmaScript6(2015) Overview
yongwoo Jeon
 
Java mentoring of samsung scsc 2
Java mentoring of samsung scsc   2Java mentoring of samsung scsc   2
Java mentoring of samsung scsc 2
도현 김
 
Rx java intro
Rx java introRx java intro
Rx java intro
Young-Hyuk Yoo
 
UML distilled 1장 스터디 발표 자료
UML distilled 1장 스터디 발표 자료UML distilled 1장 스터디 발표 자료
UML distilled 1장 스터디 발표 자료
beom kyun choi
 
Ji 개발 리뷰 (신림프로그래머)
Ji 개발 리뷰 (신림프로그래머)Ji 개발 리뷰 (신림프로그래머)
Ji 개발 리뷰 (신림프로그래머)
beom kyun choi
 
스위프트 성능 이해하기
스위프트 성능 이해하기스위프트 성능 이해하기
스위프트 성능 이해하기
Yongha Yoo
 
[D2 오픈세미나]5.robolectric 안드로이드 테스팅
[D2 오픈세미나]5.robolectric 안드로이드 테스팅[D2 오픈세미나]5.robolectric 안드로이드 테스팅
[D2 오픈세미나]5.robolectric 안드로이드 테스팅
NAVER D2
 
GKAC 2015 Apr. - Android Looper
GKAC 2015 Apr. - Android LooperGKAC 2015 Apr. - Android Looper
GKAC 2015 Apr. - Android Looper
GDG Korea
 
자바8 람다식 소개
자바8 람다식 소개자바8 람다식 소개
자바8 람다식 소개
beom kyun choi
 
MVP 패턴 소개
MVP 패턴 소개MVP 패턴 소개
MVP 패턴 소개
beom kyun choi
 
함수적 사고 2장
함수적 사고 2장함수적 사고 2장
함수적 사고 2장
HyeonSeok Choi
 
자바8 람다 나머지 공개
자바8 람다 나머지 공개자바8 람다 나머지 공개
자바8 람다 나머지 공개
Sungchul Park
 
7가지 동시성 모델 - 3장. 함수형 프로그래밍
7가지 동시성 모델 - 3장. 함수형 프로그래밍7가지 동시성 모델 - 3장. 함수형 프로그래밍
7가지 동시성 모델 - 3장. 함수형 프로그래밍
Hyunsoo Jung
 
모델링 연습 리뷰
모델링 연습 리뷰모델링 연습 리뷰
모델링 연습 리뷰
beom kyun choi
 
7가지 동시성 모델 4장
7가지 동시성 모델 4장7가지 동시성 모델 4장
7가지 동시성 모델 4장
HyeonSeok Choi
 
java 8 람다식 소개와 의미 고찰
java 8 람다식 소개와 의미 고찰java 8 람다식 소개와 의미 고찰
java 8 람다식 소개와 의미 고찰
Sungchul Park
 

What's hot (18)

7가지 동시성 모델 - 데이터 병렬성
7가지 동시성 모델 - 데이터 병렬성7가지 동시성 모델 - 데이터 병렬성
7가지 동시성 모델 - 데이터 병렬성
 
자바8 스트림 API 소개
자바8 스트림 API 소개자바8 스트림 API 소개
자바8 스트림 API 소개
 
EcmaScript6(2015) Overview
EcmaScript6(2015) OverviewEcmaScript6(2015) Overview
EcmaScript6(2015) Overview
 
Java mentoring of samsung scsc 2
Java mentoring of samsung scsc   2Java mentoring of samsung scsc   2
Java mentoring of samsung scsc 2
 
Rx java intro
Rx java introRx java intro
Rx java intro
 
UML distilled 1장 스터디 발표 자료
UML distilled 1장 스터디 발표 자료UML distilled 1장 스터디 발표 자료
UML distilled 1장 스터디 발표 자료
 
Ji 개발 리뷰 (신림프로그래머)
Ji 개발 리뷰 (신림프로그래머)Ji 개발 리뷰 (신림프로그래머)
Ji 개발 리뷰 (신림프로그래머)
 
스위프트 성능 이해하기
스위프트 성능 이해하기스위프트 성능 이해하기
스위프트 성능 이해하기
 
[D2 오픈세미나]5.robolectric 안드로이드 테스팅
[D2 오픈세미나]5.robolectric 안드로이드 테스팅[D2 오픈세미나]5.robolectric 안드로이드 테스팅
[D2 오픈세미나]5.robolectric 안드로이드 테스팅
 
GKAC 2015 Apr. - Android Looper
GKAC 2015 Apr. - Android LooperGKAC 2015 Apr. - Android Looper
GKAC 2015 Apr. - Android Looper
 
자바8 람다식 소개
자바8 람다식 소개자바8 람다식 소개
자바8 람다식 소개
 
MVP 패턴 소개
MVP 패턴 소개MVP 패턴 소개
MVP 패턴 소개
 
함수적 사고 2장
함수적 사고 2장함수적 사고 2장
함수적 사고 2장
 
자바8 람다 나머지 공개
자바8 람다 나머지 공개자바8 람다 나머지 공개
자바8 람다 나머지 공개
 
7가지 동시성 모델 - 3장. 함수형 프로그래밍
7가지 동시성 모델 - 3장. 함수형 프로그래밍7가지 동시성 모델 - 3장. 함수형 프로그래밍
7가지 동시성 모델 - 3장. 함수형 프로그래밍
 
모델링 연습 리뷰
모델링 연습 리뷰모델링 연습 리뷰
모델링 연습 리뷰
 
7가지 동시성 모델 4장
7가지 동시성 모델 4장7가지 동시성 모델 4장
7가지 동시성 모델 4장
 
java 8 람다식 소개와 의미 고찰
java 8 람다식 소개와 의미 고찰java 8 람다식 소개와 의미 고찰
java 8 람다식 소개와 의미 고찰
 

Similar to GDG 2014 - RxJava를 활용한 Functional Reactive Programming

GKAC 2014 Nov. - RxJava를 활용한 Functional Reactive Programming
GKAC 2014 Nov. - RxJava를 활용한 Functional Reactive ProgrammingGKAC 2014 Nov. - RxJava를 활용한 Functional Reactive Programming
GKAC 2014 Nov. - RxJava를 활용한 Functional Reactive Programming
GDG Korea
 
ReactiveX의 이해
ReactiveX의 이해ReactiveX의 이해
ReactiveX의 이해
성태 임
 
React Hooks 마법. 그리고 깔끔한 사용기
React Hooks 마법. 그리고 깔끔한 사용기React Hooks 마법. 그리고 깔끔한 사용기
React Hooks 마법. 그리고 깔끔한 사용기
NAVER SHOPPING
 
웹 사이트 시각화 및 성능 관리
웹 사이트 시각화 및 성능 관리웹 사이트 시각화 및 성능 관리
웹 사이트 시각화 및 성능 관리
mosaicnet
 
Side Effect in Compose (Android Jetpack)
Side Effect in Compose (Android Jetpack)Side Effect in Compose (Android Jetpack)
Side Effect in Compose (Android Jetpack)
SSLEE14
 
Redux
ReduxRedux
RLCode와 A3C 쉽고 깊게 이해하기
RLCode와 A3C 쉽고 깊게 이해하기RLCode와 A3C 쉽고 깊게 이해하기
RLCode와 A3C 쉽고 깊게 이해하기
Woong won Lee
 
04.실행환경 실습교재(화면처리)
04.실행환경 실습교재(화면처리)04.실행환경 실습교재(화면처리)
04.실행환경 실습교재(화면처리)
Hankyo
 
[NDC17] Unreal.js - 자바스크립트로 쉽고 빠른 UE4 개발하기
[NDC17] Unreal.js - 자바스크립트로 쉽고 빠른 UE4 개발하기[NDC17] Unreal.js - 자바스크립트로 쉽고 빠른 UE4 개발하기
[NDC17] Unreal.js - 자바스크립트로 쉽고 빠른 UE4 개발하기
현철 조
 
[오픈소스컨설팅] 스카우터 사용자 가이드 2020
[오픈소스컨설팅] 스카우터 사용자 가이드 2020[오픈소스컨설팅] 스카우터 사용자 가이드 2020
[오픈소스컨설팅] 스카우터 사용자 가이드 2020
Ji-Woong Choi
 
Re frame
Re frameRe frame
Re frame
Sang-Kyu Park
 
20140122 techdays mini 앱 개발 세미나(3) - 센서활용 앱 개발
20140122 techdays mini  앱 개발 세미나(3) - 센서활용 앱 개발20140122 techdays mini  앱 개발 세미나(3) - 센서활용 앱 개발
20140122 techdays mini 앱 개발 세미나(3) - 센서활용 앱 개발
영욱 김
 
Prometheus Project Journey
Prometheus Project JourneyPrometheus Project Journey
Prometheus Project Journey
Jinwoong Kim
 
Java stream v0.1
Java stream v0.1Java stream v0.1
Java stream v0.1
Hyosang Hong
 
Java stream v0.1
Java stream v0.1Java stream v0.1
Java stream v0.1
Hyosang Hong
 
Online service 계층별 성능 모니터링 방안
Online service 계층별 성능 모니터링 방안Online service 계층별 성능 모니터링 방안
Online service 계층별 성능 모니터링 방안
중선 곽
 
React 실무활용 이야기
React 실무활용 이야기React 실무활용 이야기
React 실무활용 이야기
철민 배
 
Half sync/Half Async
Half sync/Half AsyncHalf sync/Half Async
Half sync/Half Asyncscor7910
 
Surface flingerservice(서피스 상태 변경 jb)
Surface flingerservice(서피스 상태 변경 jb)Surface flingerservice(서피스 상태 변경 jb)
Surface flingerservice(서피스 상태 변경 jb)fefe7270
 
[ES6] 10. Generator
[ES6] 10. Generator[ES6] 10. Generator
[ES6] 10. Generator
Han JaeYeab
 

Similar to GDG 2014 - RxJava를 활용한 Functional Reactive Programming (20)

GKAC 2014 Nov. - RxJava를 활용한 Functional Reactive Programming
GKAC 2014 Nov. - RxJava를 활용한 Functional Reactive ProgrammingGKAC 2014 Nov. - RxJava를 활용한 Functional Reactive Programming
GKAC 2014 Nov. - RxJava를 활용한 Functional Reactive Programming
 
ReactiveX의 이해
ReactiveX의 이해ReactiveX의 이해
ReactiveX의 이해
 
React Hooks 마법. 그리고 깔끔한 사용기
React Hooks 마법. 그리고 깔끔한 사용기React Hooks 마법. 그리고 깔끔한 사용기
React Hooks 마법. 그리고 깔끔한 사용기
 
웹 사이트 시각화 및 성능 관리
웹 사이트 시각화 및 성능 관리웹 사이트 시각화 및 성능 관리
웹 사이트 시각화 및 성능 관리
 
Side Effect in Compose (Android Jetpack)
Side Effect in Compose (Android Jetpack)Side Effect in Compose (Android Jetpack)
Side Effect in Compose (Android Jetpack)
 
Redux
ReduxRedux
Redux
 
RLCode와 A3C 쉽고 깊게 이해하기
RLCode와 A3C 쉽고 깊게 이해하기RLCode와 A3C 쉽고 깊게 이해하기
RLCode와 A3C 쉽고 깊게 이해하기
 
04.실행환경 실습교재(화면처리)
04.실행환경 실습교재(화면처리)04.실행환경 실습교재(화면처리)
04.실행환경 실습교재(화면처리)
 
[NDC17] Unreal.js - 자바스크립트로 쉽고 빠른 UE4 개발하기
[NDC17] Unreal.js - 자바스크립트로 쉽고 빠른 UE4 개발하기[NDC17] Unreal.js - 자바스크립트로 쉽고 빠른 UE4 개발하기
[NDC17] Unreal.js - 자바스크립트로 쉽고 빠른 UE4 개발하기
 
[오픈소스컨설팅] 스카우터 사용자 가이드 2020
[오픈소스컨설팅] 스카우터 사용자 가이드 2020[오픈소스컨설팅] 스카우터 사용자 가이드 2020
[오픈소스컨설팅] 스카우터 사용자 가이드 2020
 
Re frame
Re frameRe frame
Re frame
 
20140122 techdays mini 앱 개발 세미나(3) - 센서활용 앱 개발
20140122 techdays mini  앱 개발 세미나(3) - 센서활용 앱 개발20140122 techdays mini  앱 개발 세미나(3) - 센서활용 앱 개발
20140122 techdays mini 앱 개발 세미나(3) - 센서활용 앱 개발
 
Prometheus Project Journey
Prometheus Project JourneyPrometheus Project Journey
Prometheus Project Journey
 
Java stream v0.1
Java stream v0.1Java stream v0.1
Java stream v0.1
 
Java stream v0.1
Java stream v0.1Java stream v0.1
Java stream v0.1
 
Online service 계층별 성능 모니터링 방안
Online service 계층별 성능 모니터링 방안Online service 계층별 성능 모니터링 방안
Online service 계층별 성능 모니터링 방안
 
React 실무활용 이야기
React 실무활용 이야기React 실무활용 이야기
React 실무활용 이야기
 
Half sync/Half Async
Half sync/Half AsyncHalf sync/Half Async
Half sync/Half Async
 
Surface flingerservice(서피스 상태 변경 jb)
Surface flingerservice(서피스 상태 변경 jb)Surface flingerservice(서피스 상태 변경 jb)
Surface flingerservice(서피스 상태 변경 jb)
 
[ES6] 10. Generator
[ES6] 10. Generator[ES6] 10. Generator
[ES6] 10. Generator
 

GDG 2014 - RxJava를 활용한 Functional Reactive Programming

  • 1. 안드로이드 동시성 프로그래밍 - RxJava를 활용한 Functional Reactive Programming 최정열 / Sivaworks / 라 스칼라 코딩단䯽 조현태 / 라 스칼라 코딩단 / waynejo1024@gmail.com
  • 3. RxJava란? Excel䯽 - 각 항목에 변화가 있으면 자동으로 감지해서 값을 갱신해준다.䯽 A B C 1 2 10 20 30 = A1+A2
  • 4. RxJava란? Event Three䯽 - 각각의 서로 다른 이벤트 소스들을 묶어서 하나의 흐름을 만들어 내는 도구䯽 각종 센서 이벤트 네트워크 정보 사용자 입력 원하는 결과의 스트림
  • 5. RxJava - Observable, Observer란? Observable - 관측 가능한 값의 흐름를 나타내는 객체 (생산자)䯽 Observer - 값의 흐름를 받는 객체 (소비자)䯽 Observable Observer Button Click String Network Byte[] Keyboard Text View Alert Image View Input Text Error Image String Visibility Image Event
  • 6. RxJava - Observable, Observer란? Observable - 관측 가능한 값의 흐름를 나타내는 객체 (생산자)䯽 - subscribe 함수를 통해 구독이 가능하며, 구독자에게 값을 흐름을 알려준다.䯽 Observer - 값의 흐름를 받는 객체 (소비자)䯽 - Observable의 값의 흐름에 따라 onNext, onError, onCompelete를 호출 받는다.䯽 OnNext OnComplete OnError
  • 7. RxJava - Observable, Observer란? eventSource.subscribe((event)-> { // observer } }); Observable Observer
  • 8. RxJava - map 키보드 입력값 출력 시나리오䯽 - 키를 입력하면 TextView에 출력하는 시나리오 EditText Function TextView Text B fun(x) TextB-1 Text C fun(x) TextC-1 Text A fun(x) TextA-1
  • 9. RxJava - map map䯽 - 전달되는 값에 함수를 적용해서 새로운 값을 만들어냄 䯽 eventSource.map((value) -> fun(value)) fun(x) Value1 Value2
  • 10. RxJava - map map䯽 - 전달되는 값에 함수를 적용해서 새로운 값을 만들어냄 䯽 buttonClick .map((value) -> {return fly(value);}) .subscribe(); buttonClick.setOnClickListener( (v) -> {value.fly();} );
  • 11. RxJava - flatMap 키보드 입력값 출력 시나리오䯽 - 키를 입력하면 추천 검색어를 서버에서 받아와 출력하는 시나리오 EditText Async Function TextView fun(x) TextA-1 Text A fun(x) TextB-1 Text B fun(x) TextC-1 Text C
  • 12. RxJava - flatMap flatmap䯽 - 미래에 0개 ~ n개의 결과를 반환하는 함수를 적용한다.䯽 eventSource.flatMap((value) -> {return longlongFunc(value);}) .subscribe((Result) -> { // show result. }); Observable
  • 13. RxJava - flatMap flatmap䯽 - 이벤트 결과가 아닌 다른 값을 사용할 수 있습니다.䯽 confirmBtnClickEvent.flatMap((value) -> { return userId.flatMap((userId) -> { return login(userId); }); }).subscribe((Result) -> { // show result. }); Push Pull
  • 14. RxJava - flatMap flatmap䯽 - 순차적으로 비동기 작업을 요청할 수 있다.䯽 confirmBtnClickEvent.flatMap((value) -> { return startupEngine(); }).flatMap((value) -> { return setupWings(); }).flatMap((value) -> { return takeOff(); }).subscribe((Result) -> { // show result. });
  • 16. RxJava - combineLatest, merge combineLatest䯽 - Observable 들의 이벤트들 중 가장 최신 이벤트 값을 합성해서 사용한다.䯽 Observable.combineLatest( (altitude, latitude, longitude) -> { getDirection(altitude, latitude, longitude); } );
  • 17. RxJava - combineLatest, merge combineLatest䯽 - Observable 들의 중 가장 최신의 이벤트 값을 합성한다.䯽 색상 combineLatest( ) 1 모양 결과 2 2 3 4 3 4
  • 18. RxJava - combineLatest, merge 모형 비행기 예제 시나리오䯽 • 사용자가 ‘take off’ 버튼을 누르면䯽 - 비동기로 엔진을 켠다.䯽 - 엔진이 켜지면 비동기로 속도와 고도를 각각 동시에 높인다.䯽 - 속도와 고도가 모두 높아지고 1초뒤에 Status 창에 “GREEN” 이라고 출력한다.䯽 사용자가 다른 버튼을 누른경우, 현재 진행중인 비동기 작업까지만 처리하고 더이상의 이전 작업은 처리하지 않는다. • 사용자가 ‘landing’ 버튼을 누르면䯽 - 속도와 고도를 각각 동시에 낮춘다.䯽 - 속도와 고도가 각각 낮아지면 엔진을 멈춘다.䯽 - 엔진이 멈추고 1초뒤에 Status 창에 “RED” 라고 출력한다.䯽
  • 19. RxJava - combineLatest, merge switchMap䯽 - Observable 에서 매 이벤트마다 새로운 Observable을 적용하여 사용한다.䯽 remoteControl switchMap( ) altitude engine On Off landing On On Off
  • 20. RxJava - combineLatest, merge switchMap䯽 - Observable 에서 매 이벤트마다 새로운 Observable을 적용하여 사용한다.䯽 receivedEvent.switchMap(remoteEventType -> { switch (remoteEventType) { case LANDING: return Observable.zip( setupAltitude(0), setupSpeed(0), (event1, event2) -> null) .flatMap(event -> setupEngine(0)); case TAKE_OFF: return setupEngine(100).flatMap( event -> Observable.zip( setupAltitude(100), setupSpeed(100), (event1, event2) -> null) ); }
  • 22. RxJava - Scheduler 이미지 다운로드 시나리오䯽 - 버튼을 클릭하면 이미지를 다운받아 표시하는 예제 UI Thread IO Thread UI Thread Click Image Image
  • 23. RxJava - Scheduler subscribeOn - 비동기 결과값을 가져오는 쓰레드를 결정한다 䯽 observeOn - 결과 값을 처리할 쓰레드를 결정한다. ClickEvents.flatMap((event) -> asyncDownloadImage(params).subscribeOn(Schedulers.io()); ) .observeOn(AndroidSchedulers.mainThread()) .subscribe((image) -> { // show result. });
  • 24. RxJava - Scheduler observeOn䯽 - 결과 값을 처리할 쓰레드를 결정한다. Event observeOn(MainThreadScheduler) Thread Main Thread
  • 25. RxJava - Scheduler subscribeOn䯽 - 비동기 결과값을 가져오는 쓰레드를 결정한다. subscribeOn(IOThreadScheduler) IO Thread Event IO Thread
  • 26. RxJava - Scheduler - 단일 쓰레드에서 이벤트 관리 䯽 Observable<Action0> request = // 요청 리스트 .observeOn(Schedulers.from(Executors.newSingleThreadExecutor()) .subscribe(Action0::call); Task 요청 쓰레드 지정 Single Thread Task Task Task Task Task Thread 1 Thread 2
  • 28. RxJava - Time 예제) delay䯽 - 시간 지연 기능䯽 // 입력된 Text를 1초 후에 보여줍니다. inputText.delay(1, TimeUnit.SECONDS) .subscribe(new SetTextAction(textView));
  • 29. RxJava - Time delay䯽 - 모든 이벤트를 주어진 시간만큼 지연한다.䯽 1 2 3 Observer 1 2 3 delay( )
  • 30. RxJava - Time throttleFirst䯽 - 한 이벤트 후의 일정 시간만큼의 이벤트를 무시한다.䯽 Observer 3 5 throttleFirst( ) 1 1 3 5 2 4
  • 31. RxJava - Time throttleWithTimeout䯽 - 일정 시간만큼의 이벤트가 없는 경우에 가장 마지막 이벤트를 전달한다.䯽 Observer 1 2 3 4 1 4 throttleWithTimeout( )
  • 33. RxJava - Error Handling retry䯽 - 실패한 경우 자동으로 재시도 합니다.䯽 GetDataFromNetwork() .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()()) .subscribe( (img) -> {showImage(img);}, (e) -> {showError(e);}, () -> {showComplete();} ) 1 Observer 1 X Error Handling
  • 34. RxJava - Error Handling retry䯽 - 실패한 경우 자동으로 재시도 합니다.䯽 GetDataFromNetwork() .subscribeOn(Schedulers.io()) .retry() Observer retry() 1 X 1 3 3
  • 35. RxJava - Error Handling retry(int n)䯽 - 실패한 경우 자동으로 n회 재시도 합니다.䯽 GetDataFromNetwork() .subscribeOn(Schedulers.io()) .retry(1) Observer retry(1) 1 X 1 2 X 2 X
  • 36. RxJava - Error Handling retryWhen(Observable)䯽 - 실패한 경우 자동으로 재시도 합니다.䯽 Observer // 3초마다 재시도 return observable.delay(3, TimeUnit.SECONDS); retryWhen() GetDataFromNetwork() 1 X 1 3 .subscribeOn(Schedulers.io()) .retryWhen((observable) -> 3 { }) delay(3, SECODS)
  • 37. RxJava - Map? FlatMap? Map을 사용해야할지, FlatMap을 사용해야 할지 구분이 힘들다면?䯽 - 기능이 실패했을때, 다시 작업을 시작하거나 작업을 취소할 범위로 구분䯽 click func save map() map() retry()
  • 38. RxJava - Map? FlatMap? Map을 사용해야할지, FlatMap을 사용해야 할지 구분이 힘들다면?䯽 - 기능이 실패했을때, 다시 작업을 시작하거나 작업을 취소할 범위로 구분䯽 click func save map() flatMap() retry()
  • 40. RxJava - MVVM Loading Indicator 예제䯽 버튼을 클릭하면 다운로드가 완료될 때까지 Loading indicator를 표시한다.䯽 // 버튼 클릭 이벤트 Observable<Void> btnClickEvent = … Observable.merge( btnClickEvent.map((event) -> true), btnClickEvent.flatMap((event)-> downloadFunction().subscribeOn(Schedulers.io()) ).map((event) -> false).observeOn(AndroidSchedulers.main()) .subscribe((isVisible) -> { v.setVisibility(isVisible ? View.VISIBLE : View.GONE); )} View Model View
  • 41. RxJava - MVVM Model View User Info String String Login Info String Profile Image Text View Alert Image View Input Text Error Image Image Visibility Image Event View Model 운영체제에䯽 의존적 운영체제에䯽 독립적
  • 42. RxJava - MVVM Model View User Info String String Login Info String Profile Image Text View Alert Image View Input Text Error Image Image Visibility Image Event View Model 테스트 불가 능 코드 테스트 가능 코드 연결 코드
  • 43. 테스트가 어려운 부분 - Thread public class SchedulerManager { private static Scheduler main = AndroidSchedulers.mainThread(); private static Scheduler io = Schedulers.io(); public static Scheduler main() { return main; } public static Scheduler io() { return io; } } 기본적으로는 상황에 맞는 Scheduler를 할당해준다.
  • 44. 테스트가 어려운 부분 - Thread @Override protected void setUp() throws Exception { super.setUp(); testScheduler = Schedulers.test(); SchedulerManager.setMain(testScheduler); SchedulerManager.setIO(testScheduler); } 테스트시에는, 테스트를 위한 Scheduler를 지정한다.
  • 45. 테스트가 어려운 부분 - Thread ArrayList<String> testResults = new ArrayList<>(); remoteAirplaneModel.statusText.subscribe(testResults::add); mainActivityModel.takeoffBtn.emit(); assertEquals(1, testResults.size()); testScheduler.advanceTimeBy(2, TimeUnit.SECONDS); assertEquals(2, testResults.size());
  • 46. 테스트가 어려운 부분 - Thread Thread 1 testScheduler.advanceTimeBy(2, TimeUnit.SECONDS) Event Event 테스트시의 단일 쓰레드 흐름 Thread 2 ArrayList<String> testResults = new ArrayList<>(); remoteAirplaneModel.statusText.subscribe(testResults::add); mainActivityModel.takeoffBtn.emit(); assertEquals(1, testResults.size()); testScheduler.advanceTimeBy(2, TimeUnit.SECONDS); assertEquals(2, testResults.size());
  • 48. RxJava - 실수하기 쉬운 Memory 관리 Observable -> Observer 사이의 연산은 Subscribe 횟수 만큼 반복䯽 - 함수에 side effect가 존재하면 결과가 예측과 다를 수 있습니다..䯽 source Custom Action1 Function Custom Action2
  • 49. RxJava - 실수하기 쉬운 Memory 관리 Observable -> Observer 사이의 연산은 Subscribe 횟수 만큼 반복䯽 - 함수에 side effect가 존재하면 결과가 예측과 다를 수 있습니다..䯽 Observable<Integer> o = Observable.from(Arrays.asList(0, 1, 2, 3, 4)); Observable<Integer> sumObservable = o.map(new Func1<Integer, Integer>() int sum = 0; @Override public Integer call(Integer integer) { sum += integer; return sum; } }); sumObservable.subscribe(System.out::println); sumObservable.subscribe(System.out::println); 0 1 3 6 10 10 11 13 16 20
  • 50. RxJava - 실수하기 쉬운 Memory 관리 cache()䯽 - 계산 결과를 cache 하여 반복 계산을 방지합니다.䯽 source Custom Action1 Function Custom Action2 cache Relplay Subject
  • 51. RxJava - 실수하기 쉬운 Memory 관리 Observable -> Observer 사이의 연산은 Subscribe 횟수 만큼 반복䯽 - 함수에 side effect가 존재하면 결과가 예측과 다를 수 있습니다..䯽 Observable<Integer> o = Observable.from(Arrays.asList(0, 1, 2, 3, 4)); Observable<Integer> sumObservable = o.map(new Func1<Integer, Integer>() int sum = 0; @Override public Integer call(Integer integer) { sum += integer; return sum; } }).cache(); sumObservable.subscribe(System.out::println); sumObservable.subscribe(System.out::println); 0 1 3 6 10 0 1 3 6 10
  • 52. RxJava - 실수하기 쉬운 Memory 관리 cache(n)䯽 - 계산 결과를 n개만 cache 하여 반복 계산을 방지합니다.䯽 source Custom Action1 Function Custom Action2 cache(n) Relplay Subject(n)
  • 53. RxJava - 실수하기 쉬운 Memory 관리 onCreate / onDestroy䯽 - onCreate에서 subscribe되고 onCompelete가 불리지 않는 경우 영원히 메모리에 존재 하게 됩니다.䯽 Subscription subscribe; @Override protected void onCreate(Bundle savedInstanceState) { subscribe = observable.subscribe(new Action1<T>() { @Override public void call(T aT) { // 부모 Activity Reference “this$0” } }); } @Override protected void onDestroy() { subscribe.unsubscribe(); }
  • 54. RxJava - 실수하기 쉬운 Memory 관리 onCreate / onDestroy䯽 - onCreate에서 subscribe되고 onCompelete가 불리지 않는 경우 영원히 메모리에 존재 하게 됩니다.䯽 observable Subscription Activity or View subscribe() new Action1()
  • 56. 왜 Reactive Programming 인가? 프로그램의 일관성을 유지하는 통일된 방식이 필요䯽 - Event, Thread, 시간, Exception을 처리하기에는 Callback은 조합이 어렵다.䯽 - 그러므로 개개인이 각각의 방식으로 조합하여 복잡성이 증대된다.䯽 통일된 방식으로 Event, Thread, Time, Exception을 처리할 수 있는 방법을 제공 단순 객체지향으로는 큰 프로그램을 만들기 어렵다.䯽 - 객체지향은 내부의 상세한 구현을 숨긴다.䯽 - 이로인해 잘 만들지 않으면 기대와 다른 동작들로 인해 복잡도가 증가한다.䯽 - 이를 해결하기 위해 객체가 객체를 감싸고 또다시 감싸는 등의 문제가 발생한다.䯽 외부에 제공할 수 있는 읽기 전용의 Observable을 제공하며 내용을 감추지 않아도 됨
  • 57. 왜 Reactive Programming 인가? 보다 테스트하기 쉬운 구조가 필요하다.䯽 - 일반적인 구현에서는 가장 내부 깊은 곳에 View, Activity 등이 존재한다.䯽 - 이로 인해 테스트에서 View를 제거하지 못해 테스트가 힘들어진다.䯽 MVVM의 구조를 활용하여 OS 종속적인 부분을 최대한 배제하고 테스트할 수 있음