본문 바로가기
프로그래밍/javascript

Promise

by freeelifee 2025. 4. 14.
728x90

Promise는 자바스크립트에서 비동기 작업을 보다 구조적으로 관리하기 위해 도입된 객체입니다. 자세히 살펴보면, 비동기 작업을 처리하기 위한 상태비동기 로직의 흐름을 제어하는 메서드 체인으로 구성됩니다. 여기에서 각 개념과 특징을 깊이 설명하겠습니다.

1. Promise의 정의와 역할

Promise는 비동기 작업의 현재 상태를 표현하고, 작업이 완료되었을 때 (성공 또는 실패) 처리할 로직을 연결할 수 있는 객체입니다. 콜백 방식과 달리, Promise를 사용하면 가독성을 유지하면서 명확하게 작업 흐름을 제어할 수 있습니다.

콜백 방식의 문제점

// 콜백 기반의 비동기 작업
function getData(callback) {
    setTimeout(() => {
        callback(null, "데이터 가져옴");
    }, 1000);
}

getData((error, result) => {
    if (error) {
        console.error(error);
    } else {
        console.log(result);
    }
});

위와 같은 코드는 콜백이 중첩되면서 복잡해지는 콜백 헬(Callback Hell)을 야기합니다.

Promise를 사용한 해결

Promise를 활용하면 중첩된 콜백 구조를 메서드 체인으로 단순화할 수 있습니다.

2. Promise의 상태

Promise는 불변 상태를 가지고 있어 다음 단계를 명확히 구분할 수 있습니다:

  • Pending: 비동기 작업이 진행 중이며 아직 결과가 없는 상태.
  • Fulfilled: 작업이 성공적으로 완료되어 결과 값을 얻은 상태.
  • Rejected: 작업이 실패하거나 에러가 발생한 상태.

Promise는 항상 Pending에서 시작하며, 작업 완료 시 Fulfilled 또는 Rejected 상태로 전환되며 한 번 변하면 더 이상 변경되지 않습니다(불변성).

3. Promise의 구조

Promise는 생성자로 만들며, 내부적으로 두 개의 콜백 함수를 받습니다:

  • resolve: 작업이 성공했을 때 호출.
  • reject: 작업이 실패했을 때 호출.
특징 resolve reject
상태 변경 Promise를 Fulfilled 상태로 바꿈 Promise를 Rejected 상태로 바꿈
전달 값 작업이 성공했을 때 결과 값을 전달 작업이 실패했을 때 에러 이유를 전달
연결 메서드 .then() 메서드에서 결과 처리 .catch() 메서드에서 에러 처리

예제: 간단한 Promise 생성

const myPromise = new Promise((resolve, reject) => {
    const success = true; // 작업 성공 여부
    if (success) {
        resolve("작업이 성공했습니다!");
    } else {
        reject("작업이 실패했습니다.");
    }
});

myPromise
    .then(result => {
        console.log(result); // "작업이 성공했습니다!" 출력
    })
    .catch(error => {
        console.error(error); // 실패 시 에러 메시지 출력
    });

4. Promise의 메서드

Promise 객체는 비동기 작업의 상태를 관리하고 후속 작업을 처리하기 위한 다양한 메서드를 제공합니다.

4.1 then

Promise가 성공했을 때 실행할 콜백을 연결합니다.

const promise = new Promise((resolve, reject) => {
    setTimeout(() => resolve("성공적으로 완료!"), 1000);
});

promise.then(result => {
    console.log(result); // 출력: "성공적으로 완료!"
});

4.2 catch

Promise가 실패했을 때 실행할 콜백을 연결합니다.

const promise = new Promise((resolve, reject) => {
    setTimeout(() => reject("작업 실패!"), 1000);
});

promise.catch(error => {
    console.error(error); // 출력: "작업 실패!"
});

4.3 finally

성공 또는 실패 여부와 관계없이 항상 실행되는 코드를 연결합니다.

const promise = new Promise((resolve, reject) => {
    setTimeout(() => resolve("완료!"), 1000);
});

promise
    .then(result => console.log(result))
    .finally(() => console.log("Promise가 종료되었습니다."));

5. Promise의 활용 사례

Promise는 주로 비동기 API 호출, 파일 읽기/쓰기, 타이머 등을 처리하는 데 사용됩니다.

예제: 비동기 API 호출

function fetchData() {
    return new Promise((resolve, reject) => {
        const success = true; // 가상의 성공 여부
        setTimeout(() => {
            if (success) {
                resolve("데이터를 성공적으로 가져왔습니다!");
            } else {
                reject("데이터 가져오기 실패!");
            }
        }, 2000); // 2초 후 실행
    });
}

// 사용 예제
fetchData()
    .then(data => console.log(data))
    .catch(error => console.error(error));

6. Promise의 병렬 처리

여러 개의 비동기 작업을 동시에 처리할 때는 Promise.all 또는 Promise.race를 사용할 수 있습니다.

Promise.all: 모든 작업이 완료되면 결과를 배열로 반환합니다.

const promise1 = new Promise(resolve => setTimeout(() => resolve("첫 번째 완료"), 1000));
const promise2 = new Promise(resolve => setTimeout(() => resolve("두 번째 완료"), 2000));

Promise.all([promise1, promise2]).then(results => {
    console.log(results); // ["첫 번째 완료", "두 번째 완료"]
});

Promise.race: 가장 먼저 완료된 작업의 결과를 반환합니다.

const promise1 = new Promise(resolve => setTimeout(() => resolve("첫 번째 완료"), 1000));
const promise2 = new Promise(resolve => setTimeout(() => resolve("두 번째 완료"), 2000));

Promise.race([promise1, promise2]).then(result => {
    console.log(result); // "첫 번째 완료"
});

7. Promise를 왜 사용하는가?

Promise는 비동기 작업 처리에서 다음과 같은 이점을 제공합니다:

  • 가독성 향상: 콜백 헬을 피하고 코드를 체인 방식으로 구성.
  • 에러 처리 통합: 모든 에러를 catch에서 관리 가능.
  • 병렬 처리 가능: 여러 작업을 동시에 수행할 수 있는 유연한 메커니즘.

Promise는 자바스크립트에서 비동기 작업을 효율적으로 처리하는 핵심적인 도구입니다.

728x90