본문 바로가기
프로그래밍/Angular

[RxJS / angular] 22. concatMap 이해하기 (옵저버블 매핑 + concat )

by 신나요 2022. 8. 12.

옵저버블은 또다시 옵저버블을 방출할 수 있습니다.  옵저버블을 방출하는 옵저버블을 다룰 때는 고차 매핑 연산자를 사용하는 것이 좋습니다. 고차 매핑 연산자에 대해 더 알고 싶은 분은 지난 포스트를 참고해 주세요.
이번 포스트에서는 고차 매핑 연산자인 catcatMap에 대해 자세히 알아보도록 하겠습니다.


concatMap 이란?

concatMap은 고차 매핑과 concat(연결)작업을 동시에 한다고 생각하면 이해하기 편합니다. 여기서 말하는 고차 매핑은 옵저버블에서 방출된 옵저버블을 구독해서 처리하는 과정이라고 생각해주세요.

concatMap 연산자는 방출된 각 항목을 우리가 제공하는 함수에 정의된 대로 새로운 내부 옵저버블 항목으로 변환합니다. 외부 옵저버블에서 방출된 각 항목을 각각 내부에 정의된 처리에 의해 옵저버블 항목에 매핑합니다. concatMap에서 기억해야 할 점은 직렬 처리로 이뤄진다는 점입니다. 직렬 처리를 한다는 의미는 일이 동시에 진행되지 않고 하나의 흐름으로 순서대로 처리됨을 의미하는대요. concatMap은 각 내부 옵저버블에서 방출된 항목은 출력 스트림에 순서대로 연결됩니다.

 

뭔가 말로 풀어 설명하면 어려운데 코드를 보면 훨씬 이해가 편합니다.  아래 예제에서는 문자열을 방출하는 옵저버블을 생성하기 위해 of 생성자 함수를 사용하고 있습니다.

파이프 처리에서 concatMap 연산자를 통해 각 문자열을 ID로 사용해 http.get 통신의 url로 데이터를 검색하게 됩니다. 우리가 잘 알고 있듯이 http.get은 옵저버블 리턴하고 이 옵저버블은 구독하기 전까지 아무 일도 하지 않습니다. 하지만 여기서 concatMap을 사용하고 있으므로 자동으로 방출한 옵저버블을 구독해줍니다. 마블 다이어그램에서 처리 순서를 생각해 보면 더욱 명확해집니다.

 

concatMap 마블 다이어그램으로 이해하기

위에서 다룬 예제를 마블 다이어 그램으로 단계별로 그려보겠습니다. 마블 다이어그램에서 concatMap은 옵저버블을 구독하고 새로운 출력 옵저버블을 생성합니다.

of('id1', 'id2')로 생성되는 소스 옵저버블은 id1과 id2라는 두 개의 문자열을 방출하고 값이 버퍼링됩니다. 생성 함수를 사용하기 때문에 of로 생성되는 외부 옵저버블은 complete 됩니다.

 

'id1'이 소스 옵저버블에서 방출되면 매핑 함수가 실행되어 새로운 내부 옵저버블을 생성합니다.

그런 다음 옵저버블을 구독하고 내보낸 문자열을 id로 사용하여 get 요청이 발행됩니다. 이제 concatMap은 get의 응답을 기다립니다.

 

response가 반환되면 이 내부 옵저버블에서 방출된 데이터가 출력 옵저버블에 연결되고 내부 옵저버블이 complete됩니다.

두 번째로 방출된 문자열 'id2'는 이전 옵저버블이 완료될 때까지 처리되지 않습니다.

 

이제 다음으로 매핑 함수는 새로운 내부 옵저버블 생성을 실행합니다. 그리고 같은 처리를 반복하게 됩니다.

옵저버블을 구독하고 get 요청이 발행됩니다. concatMap은 다시 응답을 기다리고 응답이 반환되면 내부 옵저버블에서 방출된 데이터가 출력 옵저버블에 연결(concat)되고 내부 옵저버블이 complete 됩니다. 결과적으로 데이터는 순서대로 출력 스트림으로 방출됩니다.

 

concatMap 쉽게 기억하기

cotcatMap연산자가 하는 일을 쉽게 기억하기 위해서 릴레이 경주와 연관 지어서 생각해보세요. 주자는 순서대로 대기열에 있으며 각 팀에서 한 번에 한 명의 주자가 달리게 됩니다. 다음 주자가 달리기 위해서는 선행 주자가 달리기를 완료해야 합니다. 따라서 주자의 순서는 유지됩니다. concatMap도 이전 옵저버블이 완료되지 않으면 다음 옵저버블의 로직이 실행되지 않습니다. 이제 concatMap의 처리 흐름이 잘 생각나지 않을 때 릴레이 경기를 생각해 주세요.

 

concatMap 정리

공식적으로 concatMap은 변환 연산자(transformation operator)입니다. concatMap 연산자는 옵저버블을 구독하고 출력 옵저버블을 생성합니다. 항목이 방출되면 대기열에 추가됩니다. 첫 번째 방출된 항목은 지정한 함수에서 새로운 내부 옵저버블에 매핑됩니다. 그리고 이 내부 옵저버블을 구독하고 complete 될 때까지 기다립니다. 마지막으로 내부 옵저버블에서 방출된 값을 출력 옵저버블에 연결합니다. 내부 옵저버블이 complete 되면 대기열의 다음 항목을 처리합니다.

concatMap을 사용하면 이전 옵저버블이 완료될 때까지 기다리게 되므로 항목을 순서대로 처리할 수 있습니다. 따라서 데이터를 순서대로 검색할 필요가 있는 경우 concatMap 사용을 고려해 볼 수 있습니다.


여기까지 수고하셨습니다. 

댓글