본문 바로가기
개발자 면접 질문

[개발자 면접 질문 #1] Promise와 Callback의 차이를 설명해주세요.

by Whiimsy 2022. 5. 24.

자바스크립트에서 비동기를 처리할 때 사용되는 Callback과 Promise의 차이를 알아보자!


🍖 Callback을 사용한 비동기 처리

자바스크립트에는 setTimeout() 이라는 대표적인 내장 비동기 함수가 있다. setTimeout()은 두 개의 매개 변수를 받는데, 첫번째는 실행할 작업 내용을 담은 콜백 함수이고, 두 번째는 이 콜백 함수를 수행하기 전에 기다리는 밀리초 단위 시간이다. 즉, setTimeout() 함수는 두번째 인자로 들어온 시간만큼 기다린 후에 첫 번째 인자로 들어온 콜백 함수를 실행한다.

function async(callback) {
  setTimeout(() => {
    callback("waited 1 sec.");
  }, 1000);
}

async(function (msg) {
  console.log(msg);
});

 

따라서 위 코드를 실행하면 1초 뒤에 "waited 1 sec."이 콘솔에 찍힌다. 이렇게 어떠한 비동기 로직이 완료되었을 때 callback 함수를 실행시킴으로써 callback에서 작성한 어떠한 행동을 실행할 수 있게 된다.

🍖 Promise를 사용한 비동기 처리

Promise 객체는 new 키워드와 함수를 인자로 받는 생성자를 통해서 생성할 수 있다. 여기서 인자로 받는 함수는 reslove reject라는 2개의 파라미터를 가진다.

function async(key) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      if (key === true) resolve("waited 1 sec.");
      else reject(new Error("Error!"))
    }, 1000);
  })
}

async(true)
  .then((result) => { console.log(result); })
  .catch((error) => { console.log(error); });

 

Promise를 사용하면 resolve는 성공했을 때, reject는 에러가 발생했을 때 첫 번째 인자로 어떠한 값을 넘길 수 있다. resolve는 .then의 첫 번째 인자로, reject는 .catch의 첫 번째 인자로 들어간다.

async 함수에 true를 넣어 실행하면 1초 후,

resolve의 "waited 1 sec."이 .then의 첫 번째 인자로 전달되어 "waited 1 sec."이 콘솔에 찍히고,

false를 넣어 실행하면 1초 후,

reject의 new Error("Error!")가 .catch의 첫 번째 인자로 전달되어 "Error: Error! at ..."가 콘솔에 찍힌다.

🍖 Callback과 Promise의 차이점

비동기 처리 결과 값 저장 및 사용

function async(id, callback) {
  setTimeout(function () {
    console.log("waited 1 sec.");
    const user = {
      id: id,
      name: "User" + id,
      email: id + "@test.com",
    };
    callback(user);
  }, 1000);
}

async(1, function (user) {
  console.log("user:", user);
});

// waited 1 sec.
// user: {id: 1, name: "User1", email: "1@test.com"}

 

async() 함수의 2번째 인자로 결과값을 이용해서 실행될 로직을 넘겼고, setTimeout() 함수는 1초 후에 이 콜백 함수를 호출하게 했다. 이와 같이 Callback을 사용해 비동기 처리를 할 때는 결괏값을 리턴 받으려고 하지 말고, 결괏값을 통해 처리할 로직을 콜백 함수로 넘기는 스타일로 코딩을 해줘야 예상된 결과를 얻을 수 있다.

하지만 자바스크립트 프로젝트가 점점 더 복잡해지면서 최근에는 콜백 함수를 인자로 넘겨서 비동기 처리를 하는 스타일을 피하는 추세이다. 콜백 함수를 중첩해서 사용하게 되면 계속해서 코드를 들여 쓰기 해야 하고 그러다 보면 코드 가독성이 현저하게 떨어지게 되기 때문이다. (콜백 지옥..)

가독성

비동기 로직의 결과를 다음 비동기로 전달해 실행해야 할 때, 가독성이 매우 안 좋아지고 코드 작성도 힘들어진다.

function async(result, callback) {
  setTimeout(() => {
    callback(result, function (result) {
      console.log(result);
    });
  }, 1000);
}

async(0, function (res, callback) {
  callback(res)
  async(res + 1, function (res, callback) {
    callback(res)
    async(res + 1, function (res, callback) {
      callback(res)
    });
  });
});

// 0
// 1
// 2

 

위 코드를 Promise를 사용한 비동기 처리로 바꾸어 작성해보면,

 

function async(result) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      console.log(result);
      resolve(result);
    }, 1000)
  });
}

async(0).then(res => {
  return async(res + 1);
}).then(res => {
  return async(res + 1);
})

// 0
// 1
// 2

 

보다 더 간결하고 이해하기 쉬운 것을 알 수 있다!

 

 

🐱‍👤 참고 :

https://www.daleseo.com/js-async-callback/
https://www.daleseo.com/js-async-promise/

https://jcon.tistory.com/189