hsunny study blog

RxJS를 이용하여 HTTP 통신 개선하기 본문

programming/RxJS

RxJS를 이용하여 HTTP 통신 개선하기

헤써니 2019. 5. 27. 23:39

개발 중인 IONIC 앱에서는 Angular에서 제공하는 HttpClientModule을 이용하여 서버와 통신하고 있습니다.

 

HttpClientModuleAngular 4.3.0 버전에 추가되었습니다. 
Angular에서 제공하는 HTTP 모듈은 RxJS Observable 객체를 기반으로 만들어졌습니다. RxJS이지만 RxJS의 장점들을 이용하지 못하고 단순히 결과를 받는 데에만 이용하고 있었습니다.

이 부분에 대해 어떻게 개선해나갔는지 내용을 공유합니다.

 

기존

 

이런 생각을 시작으로 코드를 개선해나갔습니다.

- 통신에 실패하는 이유를 timeout으로만 두어도 될까
- http 응답에 따라 처리를 다르게 주는 것이 괜찮을 것 같다!


첫 번째 개선

개선한 것

- 서버에 보낼 최종 데이터를 세팅하는 부분을 provider로 옮겼습니다.  
※   getValue()로 얻는 값은 provider를 사용하는 모든 곳에서 별도로 받아서 옮기고 파라미터로 받아왔습니다. 중복을 피하기 위해 provider 내에서 한 번만 세팅할 수 있도록 했습니다.   
getValue() ← 포스팅을 위해 변경한 이름  
- 흐름(Stream)을 이어나갔습니다.   
※ 위에 언급한 getValue()는 Promise 함수입니다. 따라서 데이터가 제대로 세팅될 수 있도록 then() 이후에 서버에 보낼 데이터를 세팅하고, 세팅한 값을 return 했습니다. HTTP통신에 이용하기 위하여, Promise를 Observable로 변경하기 위해 from() operator로 묶었습니다.    
- 개선하려고 했던 내용(위에서 말한 생각들)을 개선했습니다.
retry() operator로 서버통신에 실패했을 경우에 대한 처리를 보완했습니다.   

mergeMap(): settingData$에서 받은 데이터를 받아 통신에 보내기 위해 사용
retry(): 통신에 실패했을 경우 3번 다시 시도하도록 함
catchError(): error.status에 따라 처리를 다르게 해주기 위해 넣음. 503이 아닌 경우는 재시도 없이 끝내도록 함

개선했지만 부족해보인다..

- 시간을 두고 재시도하는 게 좋을 것 같다.   
※ retry() operator 통신에러가 발생하면 지체 없이 바로 재시도를 했습니다. 서버 지연의 경우 시간을 두고 재시도하는 것이 더 적합할 것 같았습니다. (시간 지나고 재시도했을 때 될 수도 있으니!)
- 503도 에러는 맞다.
※ error.status가 503인 경우는 에러를 던지지 않게 짰지만, 생각해보면 재시도했는데 계속 503이면 이것도 이용이 불가능한 상태이기 때문에 에러를 내보내 줘야 한다고 생각했습니다.

 


두 번째 개선

개선한 것

- retry() operator retryWhen() operator로 변경했습니다.   
retry() operator는 단순히 재시도가 가능했지만 retryWhen() operator는 더 유연했습니다. retryWhen은 subscription을 받아서 다시 제어할 수 있었습니다. 따라서 더 유연한 작업을 위해 변경했습니다.   
- 지연시간을 추가했습니다.  
※ 첫 번째 개선 때 고민하던 부분을 해소하기 위해 delay() operator를 이용하여 take() operator로 통신을 재시도하기 전에 지연시간을 주었습니다.   
- 모든 시도마다 통신을 실패했을 때, 에러를 던지는 것으로 변경했습니다.   
take() operator로 재시도를 하지만, 설정한 재시도가 끝났을 경우 어떻게 처리할지 고민했습니다. tap() operator 매 재시도 때마다 실행되는 곳이기 때문에 이 함수를 응용했습니다. retryWhen() operator 에러가 발생했을 경우에만 들어오는 점을 함께 생각했습니다.   
 countRetry라는 변수를 두고 tap() 안에서 카운팅 되도록 했습니다. 모든 재시도가 끝났는데도 에러라면 if (countRetry ===5) 조건으로 들어옵니다. 이 경우에 tap()으로 전달받은 데이터를 throw 시켜서 subscribeonError()로 잡히도록 했습니다. 

retryWhen(): 좀 더 유연한 통신 재시도를 위해 사용 [흐름 자체를 파라미터로 받음]
delay(): 시간을 지연시키기 위해 사용 [*delay(1500) : 1.5초 지연]
take(): 원하는 만큼 다시 실행하기 위해서 사용 [*take(4) : 4번 재시도]
tap(): 흐름을 제어하기 위해서 사용 [ex.503이 아닌 경우 재시도 안 하고 끝내기]

포스팅에 사용한 함수명, 변수명은 포스팅용입니다. 실무에 사용한 이름은 아닙니다.
"어떻게" RxJS를 활용했는지에 대해서 봐주시면 됩니다! 

 

읽어주셔서 감사합니다 :)  

 

내용에 잘못된 부분이 있다면 댓글 부탁드립니다!


참고 사이트

https://angular.io/guide/http

 

Angular

 

angular.io

https://han41858.tistory.com/39

 

Angular v.4.3.0에 추가된 HttpClientModule

2017년 7월 10일에 발표된 Angular v.4.3.0 버전에 HttpClientModule이 추가되었습니다. Angular에는 원래 @angular/http 패키지로 제공하던 HttpModule이 있었지만, 이번에 추가된 HttpClientModule을 사용하면..

han41858.tistory.com

https://stackoverflow.com/questions/44979131/rxjs-retry-with-delay-function

 

Rxjs Retry with Delay function

I am trying to use retry with delay function, I expect function will call after 1000ms delay, but it doesnot, what can be error here? look at console output, it is same time 16:22:48. I expect th...

stackoverflow.com

 

'programming > RxJS' 카테고리의 다른 글

toPromise? firstValueFrom? lastValueFrom?  (0) 2023.02.04
forkjoin 마이그레이션  (0) 2021.07.09
fromEvent()  (0) 2019.07.20
데이터 가공해서 출력하기 (pluck operator)  (0) 2019.07.12