Load my friends of Facebook with RxJava

WindSekirun (wind.seo)·2022년 4월 26일
0

이 글은 기존 운영했던 WordPress 블로그인 PyxisPub: Development Life (pyxispub.uzuki.live) 에서 가져온 글 입니다. 모든 글을 가져오지는 않으며, 작성 시점과 현재 시점에는 차이가 많이 존재합니다.

작성 시점: 2018-07-16

도입

SNS를 연동하는 앱을 개발하다 보면, 가끔 '친구 목록' 을 불러와서 처리하는 기획이 있다.

Facebook SDK 내부의 GraphRequest 클래스 내부에는 여러 메서드가 있는데, 기본적으로 로그인을 했을 때 나 자신의 정보를 불러오는 newMeRequest 메서드나 글을 올리는 newPostRequest 메서드도 있다.

여기에는 나 자신의 친구 목록을 불러오는 newMyFriendsRequest 메서드도 있는데, 이 메서드를 이용하여 나 자신의 친구 목록을 불러오는 기능을 만들 수 있다.

이 글에서는 newMyFriendsRequest 사용과 함께 Async Callback 를 RxJava 의 Observable로 발행하는 방법을 다뤄보려 한다.

기본 코드

GraphRequest.newMyFriendsRequest 의 파라미터는 총 2개인데, 첫 번째 파라미터인 accessToken 은 Facebook API에 접근하기 위한 엑세스 토큰이고, 두 번째 파라미터인 callback 는 GraphJSONArrayCallback 타입으로 JSONArray 형태로 콜백을 받기 위한 인터페이스이다. 즉, Request 로 요청하면 그 결과가 GraphJSONArrayCallback.onCompleted 에 오는 것이다.

따라서 기본적으로 해줘야 할 것은 GraphJSONArrayCallback 에 대한 지역변수를 만들고, 이를 이용해 Request 클래스를 만들어 Asynchronous 방식으로 요청하는 것이다.

그에 대한 기본 코드는 다음과 같다.

private void getFriendsInfo() {
    GraphRequest.GraphJSONArrayCallback callback1 = (array, response) -> {
        
    };

    GraphRequest request = GraphRequest.newMyFriendsRequest(AccessToken.getCurrentAccessToken(), callback1);
    Bundle parameters = new Bundle();
    parameters.putString("fields", "id, name, email, gender, birthday, picture, first_name");
    request.setParameters(parameters);
    request.executeAsync();
}

여기에 간단한 콜백 방식을 붙이면 다음과 같다.

private void getFriendsInfo(F1 listener) {
GraphRequest.GraphJSONArrayCallback callback1 = (array, response) -> {
if (array == null) {
listener.invoke(false);
return;
}

    listener.invoke(true);
};

GraphRequest request = GraphRequest.newMyFriendsRequest(AccessToken.getCurrentAccessToken(), callback1);
Bundle parameters = new Bundle();
parameters.putString("fields", "id, name, email, gender, birthday, picture, first_name");
request.setParameters(parameters);
request.executeAsync();

}

이렇게 사용해도 별 문제가 없지만, RxJava 를 도입함으로서 Callback hell 를 최소화시키고 새로 구현한 RxSocialLogin 와도 잘 통합하기 위하여 Async Callback 방식을 RxJava 의 Observable 로 바꾸려 한다.

RxJava 의 도입

RxJava 도입을 위해서는 기존의 콜백 방식에서 Observable 로의 전환이 필요한데, Observable 는 비동기 데이터 스트림 (Asynchronous Data Stream) 에 기반한 방식으로 동기/비동기 방식을 별개로 처리하는 기존 방식 보다는 연속적인 흐르는 데이터 스트림으로 동기/비동기 방식을 처리하는 것이다.

따라서 Callback 를 Observable 로 변환해야 하는데, 여기에서 가장 흔히 사용되는 것은 Observable.create 메서드이다. 이 메서드는 ObservableOnSubscribe 라는 인터페이스를 파라미터로 받는데, 이 인터페이스는 ObservableEmitter 인터페이스를 파라미터로 가지고 있어, onNext, onError, onComplete 를 발행할 수 있게 해준다.

onNext, onError, onComplete 는 그 이름 대로 역할이 있는데, onNext 는 스트림에 데이터를 발행하기 위해, onError 는 스트림에 에러를 발행하고 스트림을 종료하기 위해, onComplete 는 모든 작업이 끝나 스트림을 종료하려 할 때 사용한다. onError 는 onNext 와 달리 onComplete 를 명시적으로 호출할 필요가 없다.

Observable.create 는 Observable 라는 클래스를 반환하는데, 이 Observable 를 가지고 리액티브 연산자를 활용하여 최종적으로 Subscribe 를 하면 Subscribe 한 곳에 데이터가 들어오는 형식이다.

예를 들어, 이런 방식이다.

// due to limitation, divide chain into two group
// see https://github.com/WindSekirun/RxSocialLogin#limitations
Disposable disposable = RxSocialLogin.facebook(facebookLogin)
        .subscribeOn(AndroidSchedulers.mainThread())
        .subscribe(resultItem -> FacebookUtils.newMyFriendsRequest()
                .flatMap(data -> mSettingRepository.updateMemberFriendList(mActionMemNo, encodeList(data)))
                .subscribe(data -> loadData(), EMPTY_ERROR), EMPTY_ERROR);

addDisposable(disposable);

이제 위 기본 코드를 RxJava 방식으로 변경하면 다음과 같다.

public static Observable<List<Boolean>> newMyFriendsRequest() {
    return Observable.create(emitter -> {
        GraphRequest.GraphJSONArrayCallback callback1 = (array, response) -> {
            if (array == null) {
                emitter.onError(new Exception("no friends list"));
                emitter.onComplete();
                return;
            }

            emitter.onNext(true);
            emitter.onComplete();
        };

        GraphRequest request = GraphRequest.newMyFriendsRequest(AccessToken.getCurrentAccessToken(), callback1);
        Bundle parameters = new Bundle();
        parameters.putString("fields", "id, name, email, gender, birthday, picture, first_name");
        request.setParameters(parameters);
        request.executeAsync();
    });
}

마무리

이전부터 리액티브 프로그래밍이 좋다고 계속 들어왔지만, 쉽게 도입할 생각이 안 들었기도 했다. 하지만 이번 프로젝트를 진행하면서 RxJava 를 적극적으로 도입하니, 겁 먹을 필요가 없다고 느껴졌다. 기존에 Stream 을 적극적으로 사용해서 익숙해진 것일지도 모르겠다.

이제 나름대로 MVVM + DataBinding + Dagger + Kotlin + RxJava stack 를 가지게 된 셈인데, 좀 더 공부해서 함수형 프로그래밍 까지 잘 활용할 수 있게 노력해야 겠다고 생각했다.

profile
Android Developer @kakaobank

0개의 댓글