• 모닥위키모닥위키
  • 모닥위키
위키
  • 임의문서
  • 주간인기
  • 문서
  • 시리즈
    AAAdddvvveeerrrtttiiissseeemmmeeennntttAdvertisement

    © 2025 modak.wiki All rights reserved.

      프로미스

      Chapter 25 - Promises

      컴퓨터/IT학습
      lu

      luasenvy (luasenvy)

      CC BY 4.0 국제규약

      Promise

      프로미스는 후에 실행할 작업을 등록할 수 있다. 콜백함수와 동일한 구조를 가지고 있는데 그도 그럴것이 콜백헬을 대처하기 위해 제안된 기능이다. 이해를 위해서는 콜백에 대해 먼저 짚고 넘어가야 한다.

      콜백함수

      const asyncFn = (callback) => {
        // 5초 후 원하는 작업이 완료되면 콜백함수 호출
        setTimeout(() => callback(10), 5 * 1000);
      }
      
      // 비동기 함수를 호출하면서 완료 이후에 작동할 함수를 미리 제공
      asyncFn((result) => {
        console.info(`Async Function Has Returned. ${result}`);
      })
      

      비동기 동작의 시점 문제를 해결하기 위한 방법으로 작업이 완료된 이후에 동작할 함수를 미리 제공하는 방법이다.

      콜백헬

      asyncFn(() => {
        asyncFn(() => {
          asyncFn(()=> {
            asyncFn(()=> {
              // ...
            })
          })
        })
      })
      

      비동기 작업을 합리적으로 처리할 수 있는 방안이지만 비동기 작업 이후에 다시 비동기 작업을 해야하는 경우 등 콜백함수를 활용하는 구간이 많아지면 가독성이 아주 떨어져 유지보수가 힘들어진다.

      위 예시는 원리만 표현해서 그렇지 여러 작업들이 끼어들고 에러처리를 하는 등 점점 그 모양새가 맛이 가기 시작하면 처다보기도 싫어진다. 프로세스 순서를 쫓아가는건 기본이고 내부에서 다루는 데이터 구조가 트리처럼 조금이라도 복잡하다면 손을 놓기 십상이다. 이름에서 볼 수 있듯이 말 그대로 지옥을 경험할 수 있다.

      어디 그뿐이겠는가? 스코프에 대한 이해도 필요하고 클로저나 호이스팅 같은 현상도 고려해야 한다. 사실상 유지보수는 못 한다고 봐야하며 개발자가 도망가 아무도 이해하지 못해 결국 뒤짚어 엎는 수순을 밟는게 일반적이다.

      const asyncFn = () => new Promise((resolve, reject) => {
        setTimeout(() => resolve(Math.trunc((Math.random() * 500))), Math.trunc((Math.random() * 10000)))
      });
      
      asyncFn()
        .then((res) => asyncFn())
        .then((res) => asyncFn())
        .then((res) => asyncFn())
        .then((res) => asyncFn())
        .then((res) => asyncFn())
        .catch(err => console.error(err))
        .finally(() => console.info("run finally"))
      

      콜백 방식의 몸체를 Promise의 인자로 만들어 넘겨주고 callback 함수를 호출하는 대신 Promise가 지원하는 resolve() 함수로 전달하도록 변경하였다. 함수의 반환값은 new Promise()를 통해 생성된 Promise 인스턴스가 되도록 변경했다.

      Promise를 사용하면 기존의 콜백헬을 직렬화 할 수 있다. callback 함수를 호출하는 대신 Promise가 지원해주는 resolve() 함수로 반환값을 리턴하면 .then() 콜백에서 사용할 수 있다. 중간에 에러가 발생하여 throw 되거나 reject() 함수로 에러를 전달하면 .then()의 유무와 개수에 관게없이 .catch()로 작업이 전달된다. finally()는 오류 유무와 관계없이 마지막에 한 번 실행된다. .then() 함수에서 다시 Promise 인스턴스를 반환하면 비동기처리가 완료되고 난 후 다시 .then()으로 처리할 수도 있다.

      asyncFn()
        .then((res) => {
          asyncFn()
            .then((res) => {
              asyncFn()
                .then( /* ... */ )
            })
        })
      

      좀 웃긴 예제이긴 한데 오류없이 동작한다. 프로미스를 활용하면서 실무를 하다보면 콜백을 통해 문법적 우회를 시도하는 일이 생기고는 한다. 그러면 위 같은 어처구니 없는 경우도 분명 발생한다. 이럴때는 '이렇게 하면 되네?' 가 아니라 '내가 뭘 잘못했나?'를 고려해보자. 콜백헬을 굳이 프로미스까지 이어올 필요는 없다. Promise를 올바르게 사용하도록 하자.

      초판: 2024. 08. 20. 11:59:08

      © 2024 이 문서는 "CC BY 4.0 국제규약" 라이선스로 배포 되었습니다. 모든 권리는 저자에게 있습니다.

      프로미스

      Promise
      콜백함수