Promise와 Callback

이진혁·2022년 6월 8일
0

Promise

Promise란 자바스크립트 비동기 처리에서 사용되는 객체이다.
싱글스레드인 자바스크립트에서 비동기 처리를 위해 사용한 Callback 함수의 에러/예외처리의 어려움, 중첩으로 인한 복잡도 증가 라는 단점을 해결하기 위해 프로미스 객체를 ES6에서 언어적 차원으로 지원한다.

Promise를 사용한 비동기 처리

function async() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve("1초 후 실행");
    }, 1000);
  })
}

async().then(res => {
  console.log(res);
});

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

async 함수를 실행하면 1초 후 첫 번째 인자에 "1초 후 실행"이 들어간 resolve가 실행이 된다.

이 인자는 .then의 첫번째 인자는 함수이고, 이 함수의 첫 번째 인자로 받아서 콘솔에 찍히게 된다.

Callback

Callback이란 다른 함수가 실행을 끝낸 뒤 실행(call back)되는 함수(나중에 호출되는 함수)를 말한다. 다시 말해 코드를 통해 명시적으로 호출되는 함수가 아니라, 함수를 등록해놓은 후 어떤 이벤트가 발생했을 때 호출하는 함수를 말한다. 파라미터로 함수를 전달받아, 함수의 내부에서 실행된다.

Callback을 사용한 비동기 처리

function async(callback) {
  setTimeout(() => {
    callback("1초 후 실행");
  }, 1000);
}

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

async 함수는 첫번째 인자로 callback을 받고, callback이 실행 될 때 첫 번째 인자를 console에 출력한다.

callback이 실행되는 시점은 async함수 안에 있는 setTimeout으로 인해서 1초 후에 실행이 된다.

callback이 실행이 되면서 첫 번째 인자로 "1초 후 실행"이 들어가고, 콘솔에 "1초 후 실행"이 나타난다.

이렇게 callback을 통해서 어떠한 비동기 로직이 끝났을 때 callback 함수를 실행시킴으로써 비동기 작업이 완료 되었을 때 callback에서 작성한 어떠한 행동을 실행할 수 있게 된다.

Promiese와 Callback의 차이점

callback을 사용하면 비동기 로직의 결과값을 처리하기 위해서는 callback안에서만 처리를 해야하고, 콜백 밖에서는 비동기에서 온 값을 알 수가 없다. 하지만 promise를 사용하면 비동기에에서 온 값이 promise 객체에 저장되기 때문에 코드 작성이 용이해지며 일명 Callback 지옥을 피할 수 있다.

또한, Promise 클래스는 비동기 처리만을 위해 만들어졌기 때문에 클래스에 resolve나 reject 함수들이 잘 정의되어 있고 이를 잘 활용하기만 하면 되지만, callback pattern은 자유도가 높지만 template이 존재하지 않기 때문에 코드가 복잡해지고 에러 처리 같은 작업들이 어렵다.

아래의 예시를 살펴보자.

function async(callback) {
  let result;
    
  setTimeout(() => {
    result = callback("결과값");
  },1000);
    
  return result;
}

let b = async((res) => {
  return res;
})

만약 async 함수에서 비동기가 끝난 후의 값을 가지고 싶어서 위처럼 코드를 썼다면, b를 1초 후, 100초 후에 찍어도 undefined만 나오게 된다. 하지만 아래와 같이 Promise 객체를 이용하면

let p = new Promise((res, rej) => {
    setTimeout(() => {
      res("a")
    }, 1000)
    
})

let result = p.then(res => {
  return res;
})

console.log(result) // Promise {<fulfilled>: "a"}

result.then(res => {
    console.log(res); // "a"
})

Promise를 사용하게 되면 Promise 객체에 비동기가 처리된 결과값이 저장됩니다. Callback의 경우 매번 비동기를 실행해야지 그 값을 사용할 수 있지만 프로미스는 .then 메소드를 통해서 저장되어 있는 값을 원하는 때에 사용할 수 있다.

아래는 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

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

하지만 Promise를 사용하면 아래와 같이 .then을 통해 코드의 깊이가 깊어지지 않고, 이해하기도 쉽다.

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

출처

profile
개발 === 99%의 노력과 1%의 기도

0개의 댓글