JavaScript를 배울 때 가장 어려운 내용 중 하나가 동기와 비동기, Promise와 async await 문법이 아닐까 싶다.
오늘 수업 중 fetch()함수를 사용해 외부 서버에서 데이터를 불러오는 법과 Promise 객체에 대해 훑고 지나갔다.
복습 겸 예습으로 Promise에 대해 정리해보고자 한다.

mdn에 있는 Promise 설명은 다음과 같다.

Promise 는 프로미스가 생성된 시점에는 알려지지 않았을 수도 있는 값을 위한 대리자로, 비동기 연산이 종료된 이후에 결과 값과 실패 사유를 처리하기 위한 처리기를 연결할 수 있습니다. 프로미스를 사용하면 비동기 메서드에서 마치 동기 메서드처럼 값을 반환할 수 있습니다. 다만 최종 결과를 반환하는 것이 아니고, 미래의 어떤 시점에 결과를 제공하겠다는 '프로미스(promise)'를 반환합니다.

처음 설명을 보면 이게 무슨 소리인가 이해하기 어렵다.
간단히 요약하면 Promise는 비동기 작업의 최종 완료(또는 실패)와 그 결과값을 나타내는 객체 다.

짧게 요약해도 무슨 말인지 이해하기 어렵다면 이것만 기억하자.
Promise는 콜백 지옥(callback hell)에 빠지는 사고를 방지할 수 있는 문법이다.

Promise는 셋 중 하나의 상태를 가진다.

  • 대기(pending): 이행하지도, 거부하지도 않은 초기 상태
  • 이행(fulfilled): 연산이 성공적으로 완료됨
  • 거부(rejected): 연산이 실패함

대기 중인 프로미스는 값과 함께 이행할 수도, 어떤 이유(오류)로 인해 거부될 수도 있습니다. 이행이나 거부될 때, 프로미스의 then 메서드에 의해 대기열(큐)에 추가된 처리기들이 호출됩니다. 이미 이행했거나 거부된 프로미스에 처리기를 연결해도 호출되므로, 비동기 연산과 처리기 연결 사이에 경합 조건은 없습니다.


프로미스가 이행되거나 거부되었지만 보류 중이 아닌 경우, 프로미스가 확정된 것으로 간주합니다.

또한 프로미스와 함께 resolved라는 용어가 사용되는 것을 볼 수 있는데, 이는 프로미스가 다른 프로미스의 최종 상태와 일치하도록 "settled"되거나 "locked-in"되어 더 이상 해결하거나 거부해도 아무런 효과가 없음을 의미합니다.
"resolved" 프로미스는 종종 "fulfilled" 프로미스와 동일하지만, 해결된 프로미스도 보류 중이거나 거부될 수 있습니다.

다음 예제를 보자

new Promise((resolveOuter) => {
  resolveOuter(
    new Promise((resolveInner) => {
      setTimeout(resolveInner, 1000);
    }),
  );
});

이 프로미스는 생성될 때 resolveOuter가 동기적으로 호출되기 때문에 이미 해결되었지만, 다른 프로미스와 함께 해결되므로 1초 후 내부 프로미스가 이행될 때까지는 이행되지 않습니다. 실제로 "resolution"은 종종 백그라운드에서 이루어지며 관찰할 수 없으며, 이행 또는 거부 여부만 확인할 수 있습니다.

프로미스 연결

Promise.prototype.then(), Promise.prototype.catch() 및 Promise.prototype.finally() 메서드는 정착된 프로미스와 추가 작업을 연결하는 데 사용됩니다. 이러한 메서드는 프로미스를 반환하므로 연쇄적으로 연결할 수 있습니다.

.then() 메서드는 최대 두 개의 인수를 받습니다. 첫 번째 인수는 프로미스의 이행된 경우에 대한 콜백 함수이고, 두 번째 인수는 거부된 경우에 대한 콜백 함수입니다. 각 .then()은 새로 생성된 프로미스 객체를 반환하며, 선택적으로 연쇄에 사용할 수 있습니다. 다음은 예제입니다.

const myPromise = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve("foo");
  }, 300);
});

myPromise
  .then(handleFulfilledA, handleRejectedA)
  .then(handleFulfilledB, handleRejectedB)
  .then(handleFulfilledC, handleRejectedC);

We will use the following terminology: initial promise is the promise on which then is called; new promise is the promise returned by then. The two callbacks passed to then are called fulfillment handler and rejection handler, respectively.

The settled state of the initial promise determines which handler to execute.

  • If the initial promise is fulfilled, the fulfillment handler is called with the fulfillment value.
  • If the initial promise is rejected, the rejection handler is called with the rejection reason.

한글 번역 보다 영어를 읽는 게 더 이해가는 마법...

대충 해석하면 .then(완료 핸들러, 거부 핸들러)
이렇게 두 가지 인자를 받는다.
.then((result) => {
console.log("성공:", result);
})
처럼 then()에 하나의 함수만 들어가는 경우가 있는데 이때는 들어있는 하나의 함수가 완료 핸들러다.

사실 아직도 이해하기 어렵고, 공부할 내용이 남았다.
아래 예제 코드와 결과를 마지막으로 글을 마무리하려고 한다.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>

<script>
  // Promise 생성
  const fetchData = url => {
    return new Promise((resolve, reject) => {
      fetch(url)
      .then(response => {
        if(!response.ok) {
          throw new Error(`HTTP error! Status: ${response.status}`);
        }
        console.log('response.json()반환');
        return response.json();
      })
      .then(data => resolve(data))
      .catch(error => reject(error));
    });
  };

  // Promise 사용
  fetchData('https://jsonplaceholder.typicode.com/users')
  .then(data => {
    console.log('데이터 수신 성공:', data);
    return fetchData(`https://jsonplaceholder.typicode.com/users/${data[0].id}/posts`);
  })
  .then(posts => {
    console.log('첫 번째 사용자의 게시물:', posts);
  })
  .catch(error => {
    console.error('오류 발생:', error);
  })
  .finally(() => {
    console.log('작업 완료 (성공 또는 실패)');
  })
</script>
</body>
</html>

공식 문서도 좋지만 직접 코드를 따라 치고 결과를 확인하는 게 학습에는 효과적이다.

예제코드에서 fetchData를 실행 후, then()메서드 두 가지가 순차대로 실행된 것을 확인할 수 있다.
이처럼 Promise는 완료 시점에 맞춰 처리해야 할 작업(정확히는 비동기 작업이 끝났을 때) 다음 나중에 할 작업을 정해주는 도구라고 말할 수 있겠다.



참고 사이트 https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Promise https://www.youtube.com/watch?v=RvYYCGs45L4
profile
개발자 지망생. 일단 하고보자

0개의 댓글