자바스크립트 비동기(Promise)

한장희·2025년 9월 11일

JavaScript

목록 보기
1/2

Promise란?

  • Promise란 비동기 작업이 완료되면 값을 알려주는 객체
  • 작업이 완료되면 값을 알려줄 것을 '약속'함
  • 일단 Promise를 돌려주고 나중에 작업이 완료되면 결과값을 Promise에 채워 넣어줌
  • Promise는 3가지 상태를 가진다.
    • 비동기 작업의 결과를 기다리고 있을 때는 Pending
    • 비동기 작업이 성공적으로 완료됬을 때는 Fulfilled
    • 비동기 작업이 실패했을 때는 Rejected

리퀘스트를 보내고 리스폰스를 파싱해서 결과를 출력하는 코드

  1. 콜백 기반

    getEmployees((response) => {
        json(response, (data) => {
            console.log(data);
        })
    })
  2. Promise 기반

    const response = await fetch('...');
    const data = await response.json();
    cosnole.log(data);

    Promise 기반을 쓰면 가독성이 더 좋아지고, 콜백 헬을 벗어날 수 있다.

Promise 객체를 다루는 방법

1. .then() 메소드 + 콜백

 fetch('')
	.then((response) => response.json())
	.then((data) => console.log(data))
	.catch((error) => console.log("error"))
	.finally(() => console.log("finish"))

console.log('나 먼저 실행됨')

then은 Promise객체의 메소드이고 Promise를 리턴한다. then 메소드는 앞선 비동기 작업이 완료되면 콜백함수를 실행해준다. then은 Promise를 리턴하기 때문에 then 뒤에 바로 then을 또 붙일 수 있다. 이렇게 Promise뒤에 메소드를 계속 연결해서 쓰는 것을 프로미스 체인(Promise Chain)이라고 한다.

함수의 동작 원리
fetch 함수가 URL로 리퀘스트를 보내고 곧바로 Pending상태의 Promise를 리턴하고 이어서 then 메소드들도 Pending상태의 Promise를 바로 리턴한다. 아직 콜백함수는 실행되지 않았다. 이후 리퀘스트가 완료되어 리스폰스가 돌아오면 Promise가 Fullfilled가 되고, 이렇게 Fullilled 상태가 되었을 때만 then 메소드에 등록된 콜백이 실행된다. 콜백함수는 첫번째 파라미터로 이전 Promise의 결과 값을 가지고 실행이 된다. 콜백함수가 Promise를 리턴하면 then 메소드가 리턴한 Promise는 콜백함수가 리턴한 Promise와 동일한 상태와 결과 값을 가지게 된다. 콜백함수가 평범한 값을 리턴하면 then 메소드가 리턴한 Promise는 Fullilled 상태가 되고 콜백함수의 리턴값을 결과 값으로 갖게 된다.

프로미스 체인에서는 비동기 작업을 기다리는 동안에 다른 코드를 먼저 실행한다. 그래서 "나 먼저 실행됨"이 콘솔에 먼저 찍힌다

오류처리

catch 메소드는 이전 Promise가 Rejected 상태가 되야지 Promise 결과 값을 가지고 콜백을 실행한다. 오류가 어디서 나든 Rejected 상태가 계속 전파 되는 원리 덕분에 catch 메소드가 오류를 처리할 수 있다. 콜백이 Promise를 리턴하면 catch 메소드가 리턴하는 Promise도 동일한 상태와 결과 값을 가지고, 콜백이 일반 값을 리턴하면 Promise는 Fullfilled 상태가 되고 리턴 값을 결과 값으로 갖게 된다.
finally 메소드는 앞선 Promise 상태가 Fullfilled 또는 Rejected 상태가 되면 등록된 콜백을 실행한다.

2. async와 await 문법

  const response = await fetch('...');
  const data = await response.json();
  cosnole.log(data);

fetch함수는 Promise를 리턴한다. 함수 앞에 await를 써주면 Promise가 Fullfilled 또는 Rejected 상태가 될 때까지 기다리고 값을 할당해준다. await을 쓰지 않으면 Promise가 pending인 상태를 바로 할당해주기 때문에 await을 써줘야한다. 비동기 작업이 성공해서 Fullfilled 상태가 되면 Promise의 결과 값을 꺼내서 리턴해 준다. 데이터 파싱 함수인 json()도 Promise를 리턴하기 때문에 await을 써준다.

코드 실행 순서

  async function print() {
      try{
          const response = await fetch('');
          const data = await response.json();
          console.log(data);
      } catch(error) {
          console.log("error")
      } finally {
          console.log("finish")
      }
  }

  print();
  console.log('나 먼저 실행됨')

async 함수 안에서 await를 쓰면 Promise가 Fullfilled가 될 때까지 기다리는 동안은 다시 함수 바깥으로 나가서 나머지 코드를 모두 실행한다. 그래서 콘솔에는 "나 먼저 실행됨"이 먼저 찍힌다.
이후 Promise함수가 Fullfilled 상태가 되면 다시 함수 body로 돌아와 코드를 이어서 실행한다.

async 함수는 항상 Promise 객체를 리턴한다. 따라서 async 함수의 반환 값을 할당 받으려면 함수앞에 await를 앞에 써주어야한다.

오류처리

Promise 기반 코드에서 오류를 처리하려면 try catch 문을 사용하면 된다.
비동기 상태를 처리하는 동안에 오류가나면 Promise는 Rejected 상태가 되고 발생한 오류를 결과 값으로 가지게 된다. 이때 Promise 앞에 await이 있으면 Promise의 결과 값인 오류를 throw해주는데, try문 안에서 오류를 throw해주기 때문에 catch에서 오류를 잡아서 처리해준다. 이후 비동기 작업이 성공하던지 실패하던지 관계없이 항상 마지막에 finally에 있는 코드를 실행하고 함수가 종료된다.

profile
발전하는 프론트엔드 개발자입니다!

0개의 댓글