Javascript - Promise 비동기 처리

2025. 9. 25. 12:35·Frontend/Javascript

JavaScript로 개발하다 보면 Promise는 피할 수 없는 존재다. 하지만 처음 접하면 "이게 뭔데?" 싶은 게 사실이다.

오늘은 Promise의 기본 개념부터 실전 활용까지 정리해봤다.

동기 vs 비동기, 카페 예시로 이해하기

동기 처리를 카페에 비유하면 이렇다. 첫 번째 손님이 주문하고 커피 받을 때까지 뒤의 모든 손님이 대기한다. 비효율적이다.

 

비동기 처리는 다르다. 주문받고 진동벨 주고 다음 손님 받는다. 커피 완성되면 진동벨로 알려준다. 훨씬 효율적이다.

웹 개발도 마찬가지다. API 호출 결과를 기다리느라 화면이 멈추면 사용자 경험이 최악이 된다.

 

Promise가 뭔가?

Promise는 JavaScript에서 비동기 작업을 다루는 객체다. 작업 상태에 따라 3가지 상태를 가진다.

  • Pending (대기): 아직 결과 안 나옴
  • Fulfilled (이행): 작업 성공
  • Rejected (거부): 작업 실패

Promise의 생명주기를 보면 이렇다:

  1. Promise 생성 → Pending 상태로 시작
  2. 작업 성공 → Fulfilled 상태, .then() 실행
  3. 작업 실패 → Rejected 상태, .catch() 실행
  4. 체이닝 → 다음 Promise로 연결 가능

 

기본 사용법

// Promise 생성
const promise = new Promise((resolve, reject) => {
  setTimeout(() => {
    let success = true;
    
    if (success) {
      resolve("작업 성공!"); 
    } else {
      reject("작업 실패...");
    }
  }, 2000);
});

// Promise 사용
promise
  .then((message) => {
    console.log(message); // 성공 시 실행
  })
  .catch((error) => {
    console.log(error); // 실패 시 실행
  });

처음엔 이 문법이 어색하게 느껴졌는데, 익숙해지면 콜백 지옥보다 훨씬 깔끔하다.

 

Async/Await로 더 깔끔하게

ES8부터 추가된 async/await는 Promise를 동기 코드처럼 작성할 수 있게 해준다. 가독성이 확실히 좋아진다.

 
async function fetchData() {
  try {
    const response = await fetch('/api/data');
    const data = await response.json();
    console.log(data);
  } catch (error) {
    console.error('Error:', error);
  }
}
  • async 함수: 항상 Promise 반환
  • await: Promise 완료까지 대기
  • try/catch: 에러 처리

실무에서는 대부분 async/await 방식을 쓴다. Promise 체인보다 직관적이기 때문이다.

 

 

Promise 활용

Promise Chaining

여러 비동기 작업을 순차적으로 처리할 때 사용한다.

fetchData('/api/data')
  .then(response => processResponse(response))
  .then(processedData => displayData(processedData))
  .catch(error => handleError(error));

 

Async/Await로 변환하면

async function getData() {
  try {
    const response = await fetchData('/api/data');
    const processedData = await processResponse(response);
    displayData(processedData);
  } catch (error) {
    handleError(error);
  }
}

훨씬 읽기 쉽다. 

 

Promise 정적 메서드

Promise.all vs Promise.allSettled

- Promise.all: 모든 Promise가 성공해야 성공

const requests = [
  fetch('/api/data1'),
  fetch('/api/data2'),
  fetch('/api/data3')
];

Promise.all(requests)
  .then(responses => Promise.all(responses.map(res => res.json())))
  .then(([data1, data2, data3]) => {
    // 모든 데이터 성공적으로 받았을 때
    renderAllData(data1, data2, data3);
  })
  .catch(error => {
    // 하나라도 실패하면 여기로
    console.error('API 호출 실패:', error);
  });

문제점: 하나만 실패해도 전체 실패 처리된다.

 

 

- Promise.allSettled: 성공/실패 상관없이 모든 결과 반환

 
Promise.allSettled(requests)
  .then(results => {
    results.forEach(result => {
      if (result.status === 'fulfilled') {
        console.log('성공:', result.value);
      } else {
        console.error('실패:', result.reason);
      }
    });
  });

실무에서는 allSettled를 더 많이 쓴다. 일부 실패해도 나머지는 정상 처리할 수 있기 때문이다.

 

Promise.race vs Promise.any

- Promise.race: 가장 빨리 완료된 결과 반환 (성공/실패 무관)

Promise.race([
  fetch('/server1/data'),
  fetch('/server2/data')
])
  .then(result => {
    console.log('가장 빠른 응답:', result);
  })
  .catch(error => {
    console.error('가장 빠른 실패:', error);
  });

 

 

- Promise.any: 가장 빨리 성공한 결과 반환

Promise.any([
  fetch('/server1/data'),
  fetch('/server2/data')
])
  .then(result => {
    console.log('첫 번째 성공:', result);
  })
  .catch(error => {
    // 모든 요청이 실패했을 때만 실행
    console.error('모든 요청 실패:', error);
  });

실무 활용: CDN 서버 여러 개 중 가장 빠른 곳에서 데이터 받을 때 유용하다.

 

 

정리

  1. Promise는 비동기 작업의 상태를 관리하는 객체
  2. async/await가 가독성 면에서 더 우수
  3. Promise.all: 모든 작업 성공 필요
  4. Promise.allSettled: 부분 실패 허용
  5. Promise.race: 속도 우선
  6. Promise.any: 성공 우선

예전엔 콜백 함수로 비동기를 처리했는데, Promise 도입 후 코드가 훨씬 깔끔해졌다. 특히 async/await 문법은 비동기 코드를 동기처럼 읽을 수 있게 해서 유지보수성이 향상됐다.

실무에서는 API 호출, 파일 업로드, 이미지 로딩 등 거의 모든 비동기 작업에서 Promise를 사용한다. 그러므로 이번에 제대로 알아두자.

 

참조

  • MDN Promise
  • MDN AggregateError: erros
  • https://kkirtigoel01.medium.com/promises-in-javascript-js-27baf0e506b5
  • https://velog.io/@jeong011010/%EB%8F%99%EA%B8%B0-%EB%B9%84%EB%8F%99%EA%B8%B0%EC%97%90-%EB%8C%80%ED%95%B4-%EC%95%8C%EC%95%84%EB%B3%B4ja

 

'Frontend > Javascript' 카테고리의 다른 글

JavaScript - JavaScript의 복사, 비교, 그리고 Immer  (0) 2025.11.05
JavaScript - 프로토타입과 상속  (0) 2025.09.29
Javascript - 이벤트 루프  (0) 2025.09.26
'Frontend/Javascript' 카테고리의 다른 글
  • JavaScript - JavaScript의 복사, 비교, 그리고 Immer
  • JavaScript - 프로토타입과 상속
  • Javascript - 이벤트 루프
qkrdkwl9090
qkrdkwl9090
6년차 프론트엔드 개발자 Tony(박동현)입니다.
  • qkrdkwl9090
    Tony - Blog
    qkrdkwl9090
  • 전체
    오늘
    어제
    • 분류 전체보기 (59)
      • Frontend (24)
        • React (2)
        • Three.js (1)
        • Javascript (4)
        • R&D (7)
        • 번역글 (9)
      • IT (18)
      • 일상 (6)
        • 장소 (1)
        • 맛집 (3)
      • 경제 (11)
  • 링크

    • Github
    • Linkedin
  • 인기 글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.5
qkrdkwl9090
Javascript - Promise 비동기 처리
상단으로

티스토리툴바