아래 두 코드의 차이는 무엇일까?
// fun updateConfigs(): Completable
// fun getMyConfig(): String
// 1번 코드
updateConfigs().andThen(
Single.just(getMyConfig())
)
// 2번 코드
updateConfigs().andThen(
Single.create { emitter ->
emitter.onSuccess(getMyConfig())
}
)
1번 코드는 업데이트 전 config를 반환하고 2번 코드는 업데이트 후 config를 반환한다.
RxJava 구현을 살펴보면 다음과 같다.
public static <T> Single<T> just(final T item)
public static <T> Single<T> create(SingleOnSubscribe<T> source)
Single.just
는 값을 계산한 뒤 넘기고, Single.create
는 함수를 넘긴 후 나중에 함수를 실행(계산)한다.
의도한 동작은 updateConfigs()
에서 설정 값을 업데이트한 후, andThen
에서 업데이트 된 값인 getMyConfig()
를 반환하는 것이었다. 즉, 2번 코드가 의도한 대로 동작한다.
생각
이렇게 놓고 보면 기본적인 내용이고 별거 아닌 것 같은데, 이 코드가 포함된 부분을 한 4명이서 봤는데도 아무도 문제점을 깨닫지 못했다. 다른 문제를 디버깅 하던 중 andThen
안에 로그를 찍어보기 위해 Single.just
대신 Single.create
로 '임시로' 바꿔서 로그를 찍어본 것이었는데, 호출되는 순서가 아예 달라져서 알게 되었다.
왜 놓쳤을까?
팀원들과 '우리는 어쩌다 이런 기본적인 걸 놓치게 되었는지' 얘기해보았다.
Single.just
는 그냥Single.create
에서 값 하나 내보내고 complete 한 거랑 똑같지 않나? 코드 짧은게 보기 편하지~'라고 안일하게 넘겼다.- Rx를 Rx 답게 쓰지 못했다. 값을 '받아서' Single.just로 넘기는게 아니라 어딘가에 상태를 업데이트 한 후 사용하려고 했다. (사이드 이펙트를 배제하지 못했다)
어떻게 해결할 수 있을까?
이런저런 얘기를 했지만 결론은 '리팩토링이 필요하다'였다.
문제는 2015년에 만들어진 레거시 프로젝트에 기능이 얹히고 얹히다 보니, 이번에 문제가 된 '설정 가져오기' 같이 상대적으로 프로젝트 초창기에 만들어진 기본적인 기능들은 리팩토링이 엄두도 안날 만큼 여기저기에서 사용되고 있다는 것이다. 공개 API와 엮인 부분도 있어서 더 까다롭다.
요즘 리팩토링을 어떻게 해야할지 고민이 많은데, 숙제가 하나 더 늘어난 기분이다.
2023.02.07 추가
defer
도 있었다. 근데 defer
+Single.just
이나 Single.create
쓰는거나 가독성 측면에서는 비슷해보인다.
updateConfigs().andThen(
Single.defer {
Single.just(getMyConfig())
}
)
'개발 > 기타' 카테고리의 다른 글
git add commit push 한 번에 하기 (0) | 2020.04.23 |
---|---|
adb로 안드로이드 기본 카메라 무음 설정(안드로이드 10 까지 적용 가능) (8) | 2020.03.03 |
티스토리 코드 하이라이트(highlight.js, line number, 폰트 적용하기) (2) | 2020.01.22 |