2 minute read

콜백 함수

자바스크립트는 비동기 처리를 위한 패턴으로 콜백 함수라는 것을 사용한다.

하지만, 전통적인 콜백 함수는 ‘콜백 지옥’ 으로 인해서 가독성도 나쁘고,

비동기 처리 중 발생한 에러를 처리하기가 곤란하며, 여러 개의 비동기 처리를

한번에 처리하기도 어렵다.

(콜백 함수의 콜백 지옥)

콜백 지옥

콜백 지옥이란, 비동기 로직을 처리할 때

콜백 함수를 계속해서 사용하게 될 때 발생하게 되는 문제이다.

// XMLHttpsRequest를 이용한 GET 요청 비동기 함수
const get = url => {
  const xhr = new XMLHttpRequest();
  xhr.open('GET', url);
  xhr.send();

  xhr.onload = () => {
    if (xhr.status === 200) {
      callback(JSON.parse(xhr.response));
    } else {
      console.error(`${xhr.status} ${xhr.statusText}`);
    }
  };
};

const url = 'https://skagns211.com';

// id가 1인 post를 획득
get(`${url}/posts/1`, ({ userId }) => {
  console.log(userId); // 1
  // userId를 이용해 userInfo를 획득
  get(`${url}/users/${userId}`, (userInfo) => {
    console.log(userInfo); // {id: 1, name: "nam hun", age: 30, ...}
  }
});

위 예제에서 GET요청을 통해 서버로부터 받은 응답을 이용해 또 다시 GET 요청을 한다.

이게 반복되면, 콜백 지옥이 발생한다.

전형적인 콜백 지옥의 예제를 보자.

get("/step1", (a) => {
  get(`/step2/${a}`, (b) => {
    get(`/step3/${b}`, (c) => {
      get(`/step4/${c}`, (d) => {
        get(`/step5/${d}`, (e) => {
          get(`/step6/${e}`, (f) => {
            get(`/step7/${f}`, (g) => {
              get(`/step8/${g}`, (h) => {
                get(`/step9/${h}`, (i) => {
                  get(`/step10/${i}`, (j) => {
                    console.log(j);
                  });
                });
              });
            });
          });
        });
      });
    });
  });
});

프로미스

// 프로미스 생성
const promise = new Promise(resolve, reject) => {
  if (//비동기 처리 성공) {
    resolve('result');
  } else { // 비동기 처리 실패
    reject('err');
}

기본적인 프로미스 포맷이다.

Promise 생성자 함수가 인수로 전달받은 콜백 함수 내부에서 비동기 처리를 수행하고,

비동기 처리가 성공하면 인수로 전달받은 resolve함수를 호출,

비동기 처리가 실패하면 reject 함수를 호출한다.

이 때 비동기 처리가 성공한 상태를 fulfilled, 실패한 상태를 rejected라고 한다.

fulfilled, rejected 상태에 따라 후속 과정을 진행해야 하는데,

then, catch, finally 메소드를 이용해 진행한다.

  • then

then 메소드는 2개의 콜백 함수를 인수로 전달받는다.

  • 첫번째 콜백 함수는 프로미스가 fullfilled (성공) 상태가 되면 호출된다. 비동기 처리 결과를 인수로 전달받는다.
  • 두번째 콜백 함수는 프로미스가 rejected (실패) 상태가 되면 호출된다. 프로미스의 에러를 인수로 전달받는다.

즉, 첫번째 콜백 함수는 비동기 처리가 성공했을 때 호출,

두번째 콜백 함수는 비동기 처리가 실패했을 때 호출되는 콜백 함수이다.

new Promise((resolve) => resolve("fulfilled")).then(
  (v) => console.log(v),
  (e) => console.error(e)
); // fulfilled
  • catch

catch 메소드는 then과 동일하게 동작한다.

프로미스가 rejected 상태인 경우에만 호출된다.

new Promise((_, reject) => reject(new Error("rejected"))).catch((e) =>
  console.log(e)
); // Error: rejected`

콜백 함수와 프로미스의 차이

  • 콜백 함수는 비동기 처리의 결과를 콜백 함수 내부에서만 처리가 가능하고,

콜백 함수 밖에서는 결과의 값을 알 수 없다.

(콜백 함수 내부에서 외부의 변수 값을 바꿀 수도 없다)

  • 프로미스는 비동기 처리의 결과가 프로미스 객체에 저장되므로 결과의 값을 알 수 있다.

Updated: