드디어 JS가 비동기처리를 어떻게 하는지 찾았기 때문에 연장선상에 있는 이 내용들을 적을 수 있게 됐다.
바로 비동기 처리를 할 수 있게 만든 Callback 함수, Promise, async await에 대한 내용이다.
콜백함수란 다른 함수에 파라미터로 넘겨지는 함수를 이야기한다.
또 특정한 시점에 호출되는 함수를 이야기한다.
원하는 코드가 종료될 때 콜백함수를 실행하는 것을 구현할 수 있어서 비동기처리로 많이 사용했다.
하지만 콜백함수를 여러개 붙이면서 문제가 발생했는데, 그것이 콜백지옥이라 불리는 문제다.
불러오고, 불러오고, 불러오고, 불러오고......
그래서 사람들은 이것을 해결하기 위해 2015년 ES6으로 Promise, anync await라는 것을 도입했다.
프로미스는 비동기 처리에서 사용되는 객체다.
작업이 모두 완성이 되기 전까지는 어떠한 것이 들어있는지 확인할 수 없고,
어떤 방식이던간에 종료가 되었을 경우에 확인을 할 수 있다.
프로미스의 흐름도는 아래와 같다. (MDN에서 긁어왔다)
위를 기반으로 설명을 하면 프로미스는 3개의 상태가 존재한다.
툭하면 보는 것이 팬딩인데 작업이 완료 되기전에 호출을 해서 보는 것이다(보통 await 안걸어놔서 뜬다...)
아래 코드처럼 new Promise를 선언하여 사용할 수 있다.
위의 코드는 이미지 업로드 로직에 들어가있는 코드인데
정상적으로 스토리지에 이미지가 업로드가 될 경우 resolve를 통하여
버켓이름 + 파일이름.webp를 받을 수 있고
업로드가 되지 않았을 경우에는 reject를 통하여
에러 메세지를 받을 수 있다.
그리고 then catch finally 라는 3가지 메소드가 존재한다.
Try Catch 구문을 사용해봤다면 사용해봤을 메소드들일 것이다.
Promise.then
프로미스에서 제일 기본이 되는 메소드인데, 프로미스가 이행이 되거나, 거부가 되었을 때 확인을 할 수 있다.
VSC의 Promise.then의 설명, 읽어보면 onfulfilled와 onrejected를 확인할 수 있다.
첫번째로 사용되는 인자는 이행된 상태의 값
두번째로 사용되는 인자는 실패했을 때의 에러메세지인 것을 볼 수 있다.
Promise.catch
오직 에러만을 확인하고 싶을때 사용할 수 있다.
VSC의 Promise.catch 설명, 읽어보면 onrejected만 있는 것을 확인할 수 있다.
Promise.finally
프로미스가 이행이 되었는지, 실패가 되었는지 관계 없이 결과를 확인하기 위해 사용한다.
VSC의 Promise.finally의 설명, 읽어보면 위의 두개와는 다르게 onfinally에는 인수가 없는 것을 볼 수 있다.
3개의 메소드를 총 정리해서 보면 이러한 형식임을 확인할 수 있다.
그럼 이제 마지막으로 async await을 확인해볼 수 있는 자격이 생겼다!
async await는 다소 복잡해보이는 프로미스를 편하게 만들어낼 수 있다.
사용법은 매우매우매우 간단하다.
함수 맨 앞에 async를 붙여주면 항상 프로미스를 반환한다.
이렇게 손쉽게 프로미스 객체를 생성할 수 있게 된다.
async 함수를 사용하면 무조건 프로미스를 반환하게 되는데,
프로미스가 아니였다면 프로미스로 감싸서 반환을 해준다.
그리고 제일 중요한 것은 async 함수 내부에서는 await을 사용할 수 있게 된다.
물론 고차함수인 filter, map, reduce의 경우에도 사용할 수 있는데 콜백 위치에 붙여주면 사용할 수 있다.
await은 영단어의 뜻처럼 프로미스가 처리가 될 때까지 기다린 후 결과가 나오면 반환을 해준다.
위의 코드를 잠깐 보면 DB에 값을 insert(추가)하는 과정이다.
상식적으로 DB에 무언가를 추가를 하려면 생성되는 시간이 필요하다고 생각을 하게 되는데
추가가 되기 전에 다음 명령어로 넘어가면 문제가 생기게 된다.
그래서 생성이 될 때까지 기다려주기 위하여 await을 사용한 것이다.
TypeORM 특성상 문법에 await이 없으면 안돌아가는데 같은 맥락인 것 같으니...
await는 2가지 특징을 가지고 있다.
이렇게 비동기를 할 수 있게 만들어준 3가지를 다뤄봤다.
한번에 여러개의 반복문을 돌릴 수 있는 Promise.all 이라는 것도 존재하는데, 이것은 추후에 포스팅을 할 예정이다.
끝!