nodeJS

[nestJS]배열의 비동기처리 병렬적으로 실행하기

변기원 2023. 1. 8. 19:12

nest 기초강의에서 이미지를 s3버킷에 업로드하고 그 결과를 리턴 받는 함수를 만들었다.

awsService의 uploadFileToS3 메소드를 실행시키고 폴더명과 해당 파일객체를 보낸다.

그럼 s3에 putObject 메소드를 실행해서 해당 파일객체를 저장하고 필요한 정보가 있는 객체를 리턴해준다.

기초 강의에서는 이미지를 1장만 업로드했기 때문에 async await을 사용해서 해당 메서드만 비동기처리를 해주면 된다.

 

이 함수를 그대로 쓰면 되는데,

우리 서비스는 한번에 최대 5장의 이미지까지 받을 예정이다.

files 객체를 프론트엔드로부터 전달받아서 콘솔에 찍어보면

이렇게 배열에 file객체가 총5개 들어가 있다.

files배열에 map메서드를 사용해서 전부 하나씩 순회하면서 uploadFileToS3 함수를 실행시켜 준다.

딱 봐도 제대로 안되게 생겼다. s3에 올리고 응답을 받기 위해서는 시간이 필요한데,

자바스크립트 Array.prototype.map()은 동기적으로 실행되어 promise pending상태만 리턴한다.

결과값: [ Promise { <pending> }, Promise { <pending> } ]

콜백함수를 async로 만들어서 비동기처리결과를 기다리게 해 볼까?

똑같다.  await 은 프로미스 객체를 실행하고 돌려주지만, 프로미스 배열에는 그렇게 작동하지 않는다.

Promise.all을 사용하면 iterable 하게 주어진 모든 프로미스가 이행되고 나서 매개변수로 제공한 프로미스 각각의 이행값을 배열로 반환한다고 한다. 오! 배열요소의 순서는 매개변수에 지정한 순서를 유지한다고 한다.

Promise.all()의 매개변수로 아까 받았던 이터러블한 프로미스들, [ Promise { }, Promise { } ]를 반환했던 것을 넣어준다.

이렇게 하면 각 프로미스를 병렬적으로 처리할 수 있어서 최종적으로 결과를 받는 시간도 빨라진다.

 

* 어떤 분의 블로그에서 Promise.all이 반환순서를 지키지 않는다고 reduce를 쓰셨던 방식도 있습니다.

(출처: https://crmrelease.tistory.com/99)

리듀스를 사용하면 병렬적으로 비동기처리를 하면서도 반환순서를 지킬 수 있어서 좋다고 하셨는데

내가 결과적으로 필요한 것은 순서대로 받은 이미지의 s3 url이 필요하고

Promise.all()이 결과적으로 반환하는 배열도 결국 매개변수의 순서대로 반환된다고 하니

나는 Promise.all()을 사용하는 것으로 결정.