reactive android application architecture
TRANSCRIPT
Reactive Android Application Architecture
GDE Android 정승욱
발표자 소개
● 정승욱
● Google Developer Expert Android (2016)● TossLab - JANDI, Android 개발자● 블로그 : https://medium.com/@jsuch2362
FB : https://www.facebook.com/steve.SU.JGithub : https://github.com/ZeroBrainSlack : @nobrain_steve (http://gdgkr.slack.com)
● 기여 : Robolectric-Gradle, Socket.io-java-client 등● Android 기술 및 애자일 스크럼 활동 등 블로그 포스팅
Reactive 가 트렌드가 되었나?
데이터 변화에 대한 지금의 모습
수정 요청
수정 결과 전달
일반적인 케이스
EventBus 를 통해 사용자의 정보가 바뀌었다는 신호를 보냄
OnActivityResult 또는 LifeCycle 콜백을 이용해서 갱신을 함
데이터를 가져올 때는 저장소를 통해서 재접근
일반적인 케이스의 문제점
EventBus 를 통해 사용자의 정보가 바뀌었다는 신호를 보냄
Domain 과 상관없는 다수의 이벤트들과의 관리 문제
OnActivityResult 또는 LifeCycle 콜백을 이용해서 갱신을 함
복잡한 Stack 및 콜백 관리, 불필요한 Refresh 동작
데이터를 가져올 때는 저장소를 통해서 재접근
Query 나 데이터에 대한 재접근 요구
데이터의 변화를 스스로 알고 대응한다면?
Reactive Programming
Reactive Programming?
Reactive Programming
데이터 흐름과 변화에 대한 전달 을 기반으로 하는 프로그래밍 패러다임
“In computing, reactive programming is a programming paradigm oriented around data flows and the propagation of change”
wikipidiahttps://en.wikipedia.org/wiki/Reactive_programming
Reactive Programming
데이터 흐름과 변화에 대한 전달 을 기반으로 하는 프로그래밍 패러다임
“In computing, reactive programming is a programming paradigm oriented around data flows and the propagation of change”
wikipidiahttps://en.wikipedia.org/wiki/Reactive_programming
데이터의 흐름데이터의 변화를 전달
데이터의 흐름데이터의 변화를 전달
데이터의 흐름
데이터의 흐름
A
B
C
D
Listindex
데이터의 흐름
A
B
C
D
Listindex
데이터 변경
데이터 가공
가
A
데이터의 흐름
B
C
D
Listindex
데이터 변경
가
가
최종 처리
데이터 처리
A
데이터 가공
A
데이터의 흐름
B
C
D
Listindex
데이터 변경
나
나
최종 처리
데이터 처리
데이터 가공
B
데이터의 흐름
C
D
Listindex
데이터 변경
다
다
최종 처리
데이터 처리
데이터 가공
C
데이터의 흐름
D
Listindex
데이터 변경
라
라
최종 처리
데이터 처리
데이터 가공
D
데이터의 흐름List
index
데이터 변경 최종 처리
데이터의 흐름List
index
데이터 변경 최종 처리
D
B
C
A
모든 처리가 끝나면흐름 종료
데이터의 흐름↓
Stream 처리 or API
RxJava로 보는 Stream 처리
데이터의 흐름List
D
B
C
AObservable.just("A", "B", "C", "D");
데이터의 흐름
D
데이터 변경
라
데이터 가공
Observable.just("A", "B", "C", "D")
.map(charater -> new Data());
데이터의 흐름
라
최종 처리
데이터 처리
Observable.just("A", "B", "C", "D")
.map(charater -> new Data())
.subscribe(data -> {
doSome();
});
데이터의 변화 전달
데이터의 변화 전달
B
데이터 모니터
데이터의 변화 전달
B
데이터 변경
나
데이터 가공
B
데이터 모니터
데이터 감지
데이터의 변화 전달
B
데이터 변경
나
나
최종 처리
데이터 처리
데이터 가공
B
데이터 모니터
데이터 감지
데이터의 변화 전달
B
데이터 변경
나
나
최종 처리
데이터 처리
데이터 가공
B
데이터 모니터
데이터 감지
데이터의 변화 전달
B
데이터 모니터
Data.set(B’)
B’
데이터의 변화 전달
B`
데이터 변경
나`
데이터 가공
B
데이터 모니터
B’
데이터 변화
Data.set(B’)
데이터의 변화 전달
B`
데이터 변경
나`
나`
최종 처리
데이터 처리
데이터 가공
B
데이터 모니터
B’
데이터 변화
Data.set(B’)
데이터의 변화 전달
B`
데이터 변경
나`
나`
최종 처리
데이터 처리
데이터 가공
B
데이터 모니터
B’
데이터 변화
Data.set(B’)
데이터의 변화가 없으면 흐름이 시작되지 않는다.
데이터의 변화 감지↓
Observer 또는 Repository
Reactive 의 형태↓
Stream 처리를 통한 데이터 전달Observer 감시를 통한 변화 전달
Reactive 를 위해 고려해야 할 것
Reactive 를 위해 고려해야 할 것
● Reative 정보는 무엇이 될 것인가?
● 어떻게 Reactive 정보를 전달 할 것인가?
● Reactive 관리는 어떻게 할 것인가?
Reactive 를 위해 고려해야 할 것
● Reative 정보는 무엇이 될 것인가?
● 어떻게 Reactive 정보를 전달 할 것인가?
● Reactive 관리는 어떻게 할 것인가?
RxJava 를 이용 예시로 본 고려사항
RxBinding 예시
RxBinding
Android 의 View 상태 변화를 RxJava 를 이용해서 전달해주는 라이브러리
ex)
View 의 Click, TouchViewPager 의 PageChange 등
RxBinding - TextView.onTextChanged
EditText name;
RxTextView.textChanges(name)
.subscribe(text -> {
// do something
});
RxBinding - TextView.onTextChanged
EditText name;
RxTextView.textChanges(name)
.subscribe(text -> {
// do something
}); Reactive 감지 : Text 가 변경될 때
RxBinding - TextView.onTextChanged
EditText name;
RxTextView.textChanges(name)
.subscribe(text -> {
// do something
});Reactive 대상 : EditText 내의 Text
RxBinding - TextView.onTextChanged
EditText name;
RxTextView.textChanges(name)
.subscribe(text -> {
// do something
});RxBinding 내부의
RxViewTextOnSubscribe 클래스가 EditText 를 관리함.
그림으로 보는 RxBinding
최종 처리
데이터 처리
text
데이터 모니터
text’
데이터 변화
onTextChangedtext’
BehaviorSubject 예시
RxJava 의 Subject
외부에서 데이터를 비동기적으로 전달할 수 있도록 제공된 Interface
AsyncSubject - 연결이 완료된 시점의 마지막 정보 전달PublishSubject - 연결이 시작된 시점부터 정보 전달BahaviorSubject - 연결이 시작 직전에 마지막 정보부터 전달ReplaySubject - 연결이 시작되기 전 일정 구간의 정보를 모두 전달
BehaviorSubject
Subject subject = BehaviorSubject.create("default");
subject.distinctUntilchanged()
.subscribe(text -> {
// do something
});
subject.onNext("modified");
BehaviorSubject
Subject subject = BehaviorSubject.create("default");
subject.distinctUntilchanged()
.subscribe(text -> {
// do something
});
subject.onNext("modified");
Reactive 관리 : BehaviorSubject 내에서 관리
BehaviorSubject
Subject subject = BehaviorSubject.create("default");
subject.distinctUntilchanged()
.subscribe(text -> {
// do something
});
subject.onNext("modified");
Reactive 감지 : String 정보가 변경될 때
Reactive 변화 요인
BehaviorSubject
Subject subject = BehaviorSubject.create("default");
subject.distinctUntilchanged()
.subscribe(text -> {
// do something
});
subject.onNext("modified");
Reactive 대상 : String 형 객체
Advanced Reactive From Data
Reactive 대상 정의
↓객체 정의
Reactive 전달↓
RxJava 를 이용한 전달
전달에 용이한 객체로 전환
일반적인 데이터 관리
● 관리하지 않는다.
Activity 네트워크 요청 View.setXXX
일반적인 데이터 관리
● 관리하지 않는다.
● Activity 등에 일회성 저장
Activity 네트워크 요청 View.setXXXActivity 저장
일반적인 데이터 관리
● 관리하지 않는다.
● Activity 등에 일회성 저장
● Singleton, Database 에 저장
Activity 네트워크 요청 View.setXXXDB 저장
일반적인 데이터 관리
● 관리하지 않는다.
● Activity 등에 일회성 저장
● Singleton, Database 에 저장
Activity 네트워크 요청 View.setXXXDB 저장
Singleton, Database 의 변화
Database 의 변화 전달
Sqlite : ContentObserver 를 제공
Realm : RealmChangeListener 제공
데이터의 Create/Update/Delete 에 따라로직이나 View 의 정보가 변경된다
Database 의 변화
Sqlite : ContentObserver 를 제공
Realm : RealmChangeListener 제공
하지만 Data 의 Create/Update/Delete 상태를 제공하지 않는다.
데이터의 변화는 이미 외부에서 결정됨
public T insert(T t);
public int update(T t);
public int delete(T t);
예상 가능 Transaction ↓
이벤트에 정의하고 전달 가능
public class Result<T> {
T data; // 변화된 데이터
// 데이터 반영 상태
boolean added() {};
boolean updated() {};
boolean deleted() {};
}
public class Result<T> {
T data; // 변화된 데이터
// 데이터 반영 상태
boolean added() {};
boolean updated() {};
boolean deleted() {};
}
public class Result<T> {
T data; // 변화된 데이터
// 데이터 반영 상태
boolean added() {};
boolean updated() {};
boolean deleted() {};
}
데이터의 전달
1개의 도메인에 대해 N 곳에서 처리↓
Reactive 관리
N 곳에서 동시에 등록/해제 할 수 있는
인터페이스 필요
class DataObserver { // Singleton Class
Map<Object, List<Listener>> register;
Subject notifier;
// 데이터 감시 등록
void <T> register(Object invoker, Class klass, Listener listener);
// 데이터 감시 해제
void unregister(Object invoker);
// 데이터 변화 주입
void update(Result result);
}
등록/해제 방법
등록/해제 방법public class MainActivity {
public void onCreate() {
DataObserver.register(this,
Data.class,
result -> doSome());
}
public void onDestroy() {
DataObserver.unregister(this);
}
}
등록/해제 방법public class MainActivity {
public void onCreate() {
DataObserver.register(this,
Data.class,
result -> doSome());
}
public void onDestroy() {
DataObserver.unregister(this);
}
}
등록
해제
등록/해제 방법public class MainActivity {
public void onCreate() {
DataObserver.register(this,
Data.class,
result -> doSome());
}
public void onDestroy() {
DataObserver.unregister(this);
}
}
데이터 변화를 감지할 객체 정의
등록/해제 방법public class MainActivity {
public void onCreate() {
DataObserver.register(this,
Data.class,
result -> doSome());
}
public void onDestroy() {
DataObserver.unregister(this);
}
}
콜백 정의
실제 화면상의 모습
User.class
User.class사용자의 정보가 바뀐다면?
User 객체의 변화에만 반응
Database
DataObserver
NavigationDrawer ProfileView
ProfileLoader ProfileLoader
ProfileBinder ProfileBinder
Database
DataObserver
NavigationDrawer ProfileView
ProfileLoader ProfileLoader
User 감시 User 감시
ProfileBinder ProfileBinder
NavigationDrawer ProfileView
Database
DataObserver
NavigationDrawer ProfileView
ProfileLoader
ProfileBinder ProfileBinder
ProfileLoaderUser 로드 후 바인딩
NavigationDrawer ProfileView
사용자가 User 정보를 변경
Database
DataObserver
NavigationDrawer ProfileView
ProfileLoader ProfileLoader
ProfileBinder ProfileBinderUser 정보 갱신
NavigationDrawer ProfileView
User 정보 갱신
Database
DataObserver
NavigationDrawer ProfileView
ProfileLoader ProfileLoader
ProfileBinder ProfileBinder
NavigationDrawer ProfileView
Database 가 DataObserver 에게 갱신을 알림
User 정보 갱신
Database
DataObserver
NavigationDrawer ProfileView
ProfileLoader ProfileLoader
ProfileBinder ProfileBinder
NavigationDrawer ProfileView
User 정보 갱신
Database
DataObserver
NavigationDrawer ProfileView
ProfileLoader ProfileLoader
ProfileBinder ProfileBinder
NavigationDrawer ProfileView
User 정보 갱신
Database
DataObserver
NavigationDrawer ProfileView
ProfileLoader ProfileLoader
ProfileBinder ProfileBinder
NavigationDrawer ProfileView
기존 과의 차이
Data 에만 반응함
LifeCycle 등의 특정 콜백 으로부터 해방
Transactional Operator 에 대한 정확한 추정이 가능
결론
결론
객체 에 대한 공통된 정의
객체 을 이용해서 관리 할 수 있는 Observer 정의
객체 처리에 맞도록 리스너 정의
주의 사항
주의 사항객체 의 지나친 포괄/세분화는 중복적인 처리를 가져올 수 있음.
ex) ChatList (전체 채팅 리스트)1개의 뱃지만 바뀌는 updated 동작에 대해 전체의 갱신
객체 반응시 의존적 관계에 대한 Scope/처리 정의 필요
ex) User 는 Team / AccessInfo 에 의존적Team 정보가 없는 경우, 다른 Team 정보로 변경되는 경우
Q&A
워크샵 시작~!