728x90
상황
- Node.js 프레임워크로 돌아가는 서버
- WebRTC 구축을 위해 MediaSoup을 사용
- 통신을 위해 socket.io 를 사용하고 있다.
문제점
- socket.io 에서, 클라이언트에서 이벤트를 emit 하면 callback으로 응답을 주는 API의 경우
- callback으로 응답 된 데이터를 바로 다음에 사용해되는 경우
- callback이 호출될때까지 대기해야함 → 즉 순서가 보장되어야한다.
시도한 방법
0. 고전적인 방법 : Callback Hell
- callback안에 다음으로 실행할 코드를 적으면 되긴하지만 콜백지옥을 불러오고 싶지는 않음
- 심미적으로 불편
1. 단순하게 동기로 받아오기
- (socket.on의 람다 식이 callback의 listener)
- 소비 시점에 따라 res가 할당 되어 있을지, emptyString인지 랜덤이다.
- 비동기적 처리의 필요성을 느낌
2. async - await를 활용하여 deferred 객체로 대기한다.
- await 하더라도 소비하는 시점이 callback 오기 전인 경우가 있었다.
- 따라서 deferred 객체는 소비 시점에서 초기화되지 못했다.
- lateinit property deferred has not been intialized
3. Flow를 활용하여 시도
- 비슷하게 flow로 시도하여 collect로 소비할려고 시도
- 마찬가지로 flow 또한 collect하는 시점에 초기화 되지 못했다.
- 소비 시점 또한 비동기 적이여야 할 것같다.
4. Channel로 미리 객체를 정의해보자
- 2,3번의 경우 소비 시점에 객체가 초기화 되지 않았었다.
- 그렇다면 아예 비동기 pipeline을 미리 만들고 데이터를 보낸다면?
- 데이터 생산 전에 channel을 미리 초기화하고 소비
- → 되는거 같은데 왔다리 갔다리 한다.
5. suspendCoroutine 로 callback이 호출될 때 까지 정지
- suspendCoroutine 또는 suspendCancellableCoroutine 을 사용하면 scope안의 코드가 실행되지만 인자로 전달되는 객체를 통해 값이 resume 될 때까지 suspend한다.
- 즉 callback이 호출되어 resume 될때까지 대기하게 된다.
- 서버가 응답이 없다면 영원히 suspend할 것이기에 suspendCancellableCoroutine 과 withTimeOut 을 사용하여 시간 제한을 두고, 예외처리하여 exception을 throw 한다.
- 코드 depth가 너무 길어지고 가독성이 좋지 않아 suspendCancellableCoroutine 과 withTimeOut 를 동시에 사용할 수 있는 util function을 작성
- 같은 코드이지만 훨씬 깔끔해보인다.
아직 궁금하다
- 결국 마지막 방법은 받아올때까지 suspend한다는 것인데 병렬적으로 실행하고 소비 시점에만 await하는 방법은 없을까?
- suspendCoroutine 은 단발성 데이터인데 만약 callback이 데이터의 시퀀스로 들어온다면?
- callbackFlow? (channel로 구현되고 있는듯함)
728x90
'Android > Issue Handling' 카테고리의 다른 글
💡 launchIn(Scope) vs Scope.launch 의 차이 | flow terminal operation (1) | 2022.08.20 |
---|