gyunam.blog

[weekly] [nb] 웹 개발 시작하기(4)

프로미스(promise)의 3가지 상태에 대해 설명해 주세요.

약속(promise)

javascript 에서 비동기 프로그래밍을 보다 편하고 직관적이게 하기 위해 만든 기능이다.

es6(2015) 공식 표준화

javascript 로 비동기 작업을 많이 하게 되면서, 공통된 표준 문법으로 비동기 작업을 할 수 있도록 규정했다.

이때 아래의 조건을 충족할 수 있도록 여러 프로그래밍 언어에서 개념을 차용해왔다.

  1. 비동기 작업을 값 처럼 사용
  2. 중첩이 아니라 체이닝(chaining) 으로 흐름 작성
  3. 에러 처리 통합

e 언어

공식적으로 promise 라는 용어와 개념이 명확하게 사용된 언어는 e 언어(1990년대 중반)다.

상품 택배 배송

promise 의 과정은 대단히 단순하다.

우리가 쿠팡에서 물건을 샀을 때 택배로 배송오는 걸 생각하면 편하다.

deleivery-product.mjs 코드


// deleivery-product.mjs
export function deliverProduct(isAddressCorrect = true) {
  return new Promise((resolve, reject) => {
    console.log("배송 중 : 택배 집하소 도착(pending)")

    setTimeout(() => {
      if (isAddressCorrect) {
        resolve("배송 성공 : 택배 도착(fulfilled)")
      } else {
        reject("배송 실패 : 주소 오류(rejected)")
      }
    }, 1000)
  })
}

index.js 코드


// index.js
import { deliverProduct } from './delivery-product.mjs'

console.log("택배 배송 시작")

async function trackProduct() {
  try {
    const result = await deliverProduct(true)
    console.log("성공:", result)
  } catch (error) {
    console.error("실패:", error)
  }
}

trackProduct()

배송 시작


console.log("택배 배송 시작")

쿠팡이 주문을 받고 택배 배송을 시작했다.

대기(pending)

아직 배송 중이기 때문에 해당 배송이 성공이었는지, 실패였는지 알 수 없다.


return new Promise((resolve, reject) => {
  console.log("배송 중 : 택배 집하소 도착(pending)")
  // ...
})

쿠팡에서 물건을 택배 집하소에 가져다 두었다.

이제 쿠팡맨들이 각자 담당한 지점에 따라서 이 물건을 가지고 배송을 이어갈 것이다.

성공(fulfilled)

주소가 정확하게 입력이 되었다면 배송은 문제없이 진행될 것이다.


setTimeout(() => {
  if (isAddressCorrect) {
    resolve("배송 성공 : 택배 도착(fulfilled)")
  } // ...
}, 1000)

promise 에서는 이 성공한 결과를 resolve() 에 담아서 보낼 수 있다.

아까 상기한 1. 비동기 작업을 값 처럼 사용 의 경우가 바로 이것이다.

실패(rejected)

하지만 배송 주소가 잘못 입력되었을 경우 물건은 다른 주소에 배송된다.

쿠팡 입장에서는 적힌 주소대로 보낸 것이긴 하지만, 어쨋든 우리 입장에서는 택배가 배송오지 못했다.


setTimeout(() => {
  //...
  else {
    reject("배송 실패 : 주소 오류(rejected)")
  }
}, 1000)

이때 javascript 는 reject() 에 담아서 오류를 보낸다.

async, await

직관적인 단어 비동기(async) 기다림(await) 을 사용해서 비동기 프로그래밍이 가능하다.


async function example() {
  try{
    const result = await something()
    console.log(result)
  } catch(error){}
}

표준으로 정립된 문법에서는 await 는 반드시 async 가 사용된 함수 안에서 사용되어야 한다.

간혹 그냥 .js 파일 안에서 바로 쓰는 경우가 있는데, 그 경우엔 동작은 한다.

하위호환성 과 여러가지 이유로 가능은 하게 해둔 것인데, 의도치 않은 버그가 생길 수 있다. 그리고 그것에 관해서는 프로그래머 본인의 책임일 뿐이다.

그래서 무조건 await 는 async 로 감싸진 함수에서 꼭 쓸 것.

try, catch

async 함수를 만들 때는 try {} catch(){} 를 항상 셋트로 사용하자.


async function example() {
  try{
    console.log('good')
  } catch(error){
    console.error('bad : ${error}')
  }
}

express 를 사용하다보면 수없이 api 요청과 응답을 받는데 이때 마다 에러를 확인하기가 편하다.

async 를 사용할 때는 그냥 항상 기본값으로 쓴다는 생각으로 쓰자.

마무리

promise 를 객체로 만들어서 쓰는 것은 처음 해봤다.

기존에 만들어져 있는 기능들을 가져와서 쓸 때 async, await 를 많이 썼는데, 이번에 Promise 객체로 setTimeOut 을 감싸서 사용하니까 어떻게 써먹는지 이해가 되었다.

setTimeOut 은 Promise 객체가 아니라서 Promise 로 감싸면 await 로 딜레이를 줄 수 있다.

그런데 실무에서 이 setTimeOut 을 쓸지는 잘 모르겠다.

굳이 쓴다면 의도적으로 응답 시간을 넘겨서 timeout 을 테스트하는 정도..?