13. 시간을 다루는 마법 (비동기 처리)/13.3 약속을 지키는 Promise

13.3.1 Promise - 미래의 약속을 담는 편리한 도구

thejavascript4kids 2025. 7. 18. 04:13

📘 13.3.1 Promise - 미래의 약속을 담는 편리한 도구

약속이라는 이름의 새로운 시작

안녕하세요, 여러분. 오늘은 정말 신나는 여행을 시작할 거예요. 지금까지 콜백 지옥에서 탈출하는 방법들을 함께 찾아왔는데, 이제 놀라운 해결책을 만나볼 시간이에요. 바로 Promise라는 아름다운 도구입니다.

Promise는 마치 "나중에 결과를 꼭 알려드릴게요"라는 정중한 약속 편지 같아서, 복잡한 비동기 작업을 훨씬 더 깔끔하고 이해하기 쉽게 만들어줄 수 있어요.

🧠 새로운 단어들과 친해지기

단어 의미
Promise 미래에 완료될 작업의 결과를 나타내는 특별한 도구예요
Pending 아직 작업이 완료되지 않은 "기다리는 중" 상태예요
Fulfilled 작업이 성공적으로 완료된 "성공!" 상태예요
Rejected 작업이 실패한 "실패했어요" 상태예요

✨ Promise가 뭔지 알아보기

Promise는 비동기 작업의 최종 완료나 실패를 나타내는 특별한 도구입니다. 콜백 함수의 문제점들을 해결하기 위해 만들어진 현대적인 해결책이에요.

Promise의 가장 중요한 특징은 세 가지 상태를 가진다는 것입니다:

  • Pending: 아직 기다리는 중
  • Fulfilled: 성공적으로 완료됨
  • Rejected: 아쉽게 실패함

중요한 규칙: 한 번 상태가 결정되면 절대 바뀌지 않아요! 성공이면 계속 성공이고, 실패면 계속 실패예요.

온라인 쇼핑 주문 이야기

Promise를 이해하기 위해 하나의 이야기를 들려드릴게요.

여러분이 정말 갖고 싶던 새로운 게임을 온라인으로 주문했다고 생각해보세요. 주문을 완료하면 "주문 확인서"를 받게 되잖아요? 이 확인서가 바로 Promise와 같은 역할을 해요.

  • 처음: "배송 준비 중"이라고 나와요 → Pending 상태
  • 성공: "배송 완료!"가 되면 → Fulfilled 상태
  • 실패: "배송 실패"가 되면 → Rejected 상태

한 번 "배송 완료"나 "배송 실패"로 상태가 바뀌면, 다시는 바뀌지 않아요. Promise도 마찬가지예요!

🎯 왜 Promise를 배워야 할까요?

  1. 웹사이트의 많은 코드를 이해하기 위해서예요
  2. 복잡한 비동기 처리의 원리를 배우면서 자바스크립트를 깊이 이해할 수 있어요
  3. 다음에 배울 async/await가 얼마나 훌륭한지 알 수 있어요

⚙️ Promise 사용법 배우기

Promise 만들기:

let myPromise = new Promise(function(resolve, reject) {
    // 여기서 비동기 작업을 해요
    if (작업이_성공했다면) {
        resolve(결과값); // 성공!
    } else {
        reject(오류정보); // 실패!
    }
});

Promise 사용하기:

myPromise
    .then(function(결과) {
        console.log("와! 성공했어요:", 결과);
    })
    .catch(function(오류) {
        console.log("아이고, 실패했네요:", 오류);
    });

🧪 예제로 익혀보기

🔹 예제 1: 가장 기본적인 Promise 만들어보기

// 2초 후에 성공하는 간단한 Promise
let myFirstPromise = new Promise(function(resolve, reject) {
    console.log("작업을 시작합니다...");

    setTimeout(function() {
        resolve("와! 작업이 성공적으로 완료되었어요!");
    }, 2000);
});

// Promise의 결과 처리하기
myFirstPromise
    .then(function(성공메시지) {
        console.log("🎉 좋은 소식:", 성공메시지);
    })
    .catch(function(실패메시지) {
        console.log("😢 아쉬운 소식:", 실패메시지);
    });

console.log("다른 일들도 계속 할 수 있어요!");

🔹 예제 2: 성공과 실패를 모두 다루는 Promise

// 주사위 게임 Promise
let diceGamePromise = new Promise(function(resolve, reject) {
    console.log("🎲 주사위를 굴리고 있어요...");

    setTimeout(function() {
        let diceNumber = Math.floor(Math.random() * 6) + 1;
        console.log("주사위 결과:", diceNumber);

        if (diceNumber >= 4) {
            resolve("🎉 축하해요! " + diceNumber + "이 나왔어요. 이겼습니다!");
        } else {
            reject("😅 아쉽네요! " + diceNumber + "이 나왔어요. 졌어요.");
        }
    }, 1000);
});

// 결과 처리
diceGamePromise
    .then(function(승리메시지) {
        console.log("🏆 승리:", 승리메시지);
    })
    .catch(function(패배메시지) {
        console.log("💪 패배:", 패배메시지);
    });

🔹 예제 3: 실용적인 사용자 정보 처리 Promise

// 사용자 정보를 가져오는 함수
function fetchUserInfo(userId) {
    return new Promise(function(resolve, reject) {
        console.log("사용자 ID " + userId + "의 정보를 불러오고 있어요...");

        setTimeout(function() {
            if (userId > 0 && userId <= 100) {
                // 올바른 사용자 ID인 경우
                let userInfo = {
                    id: userId,
                    name: "학생" + userId,
                    email: "student" + userId + "@school.com",
                    age: 10 + (userId % 8)
                };
                resolve(userInfo);
            } else {
                // 잘못된 사용자 ID인 경우
                reject("사용자 ID " + userId + "는 존재하지 않아요.");
            }
        }, 1500);
    });
}

// 함수 사용해보기
fetchUserInfo(25)
    .then(function(user) {
        console.log("📋 사용자 정보를 성공적으로 가져왔어요:");
        console.log("이름: " + user.name);
        console.log("이메일: " + user.email);
        console.log("나이: " + user.age + "세");
    })
    .catch(function(error) {
        console.log("❌ 문제가 발생했어요: " + error);
    });

// 잘못된 ID로도 테스트해보기
fetchUserInfo(150)
    .then(function(user) {
        console.log("사용자 정보:", user);
    })
    .catch(function(error) {
        console.log("❌ 예상된 문제: " + error);
    });

🔄 Promise 사용 과정 정리하기

  1. Promise 만들기: new Promise()로 새로운 Promise 생성 (Pending 상태)
  2. 비동기 작업 수행: Promise 안에서 실제 작업 진행
  3. 상태 결정: 성공 시 resolve(), 실패 시 reject() 호출
  4. 결과 처리: .then()으로 성공, .catch()로 실패 처리
  5. 완료: 상태가 결정되면 더 이상 바뀌지 않음

🧠 자주 하는 실수와 주의할 점

❌ 실수 1: resolve나 reject를 호출하지 않기

// 잘못된 예시 - Promise가 영원히 Pending 상태
let badPromise = new Promise(function(resolve, reject) {
    console.log("작업을 시작해요...");
    // resolve나 reject를 호출하지 않았어요!
});

// 올바른 예시
let goodPromise = new Promise(function(resolve, reject) {
    console.log("작업을 시작해요...");
    setTimeout(function() {
        resolve("작업 완료!");
    }, 1000);
});

❌ 실수 2: Promise를 만들고 결과를 처리하지 않기

// 문제가 될 수 있는 예시
let promise = new Promise(function(resolve, reject) {
    setTimeout(function() {
        resolve("작업 완료");
    }, 1000);
});
// .then()이나 .catch()로 결과를 처리하지 않았어요!

// 올바른 예시
promise
    .then(function(result) {
        console.log("결과:", result);
    })
    .catch(function(error) {
        console.log("오류:", error);
    });

❌ 실수 3: resolve와 reject를 둘 다 호출하려고 시도하기

// 잘못된 예시 - 첫 번째만 유효해요
let confusedPromise = new Promise(function(resolve, reject) {
    resolve("성공!");
    reject("실패!"); // 이 줄은 무시돼요
});

// 올바른 예시 - 조건에 따라 하나만 호출
let goodPromise = new Promise(function(resolve, reject) {
    let success = Math.random() > 0.5;
    if (success) {
        resolve("성공!");
    } else {
        reject("실패!");
    }
});

✏️ 연습문제로 개념 다지기

천천히, 마치 새로운 언어를 배우듯 차분하게 문제를 풀어보세요. Promise는 우리에게 비동기 코딩의 새로운 가능성을 열어주는 열쇠같은 존재예요.

Ex1) 3초 후에 "안녕하세요!"라는 메시지를 전달하는 Promise 만들기

let greetingPromise = new Promise(function(resolve, reject) {
    setTimeout(function() {
        resolve("안녕하세요!");
    }, 3000);
});

greetingPromise
    .then(function(message) {
        console.log("받은 메시지:", message);
    })
    .catch(function(error) {
        console.log("오류:", error);
    });

Ex2) 숫자를 입력받아서 짝수면 성공, 홀수면 실패하는 Promise 함수

function checkEvenNumber(number) {
    return new Promise(function(resolve, reject) {
        setTimeout(function() {
            if (number % 2 === 0) {
                resolve(number + "은 짝수예요!");
            } else {
                reject(number + "은 홀수예요!");
            }
        }, 1000);
    });
}

// 테스트해보기
checkEvenNumber(6)
    .then(function(result) {
        console.log("성공:", result);
    })
    .catch(function(error) {
        console.log("실패:", error);
    });

🤔 심화 문제로 실력 확인하기

Q1. Promise의 세 가지 상태는 무엇이고, 각각 언제 발생하나요?

정답: Pending(기다리는 중), Fulfilled(성공 완료), Rejected(실패)

해설: Pending은 Promise가 생성되어 아직 완료되지 않은 초기 상태예요. Fulfilled는 resolve()가 호출되어 성공한 상태이고, Rejected는 reject()가 호출되어 실패한 상태예요. 한 번 결정되면 절대 바뀌지 않아요.

Q2. Promise가 콜백 함수보다 좋은 이유를 세 가지 말해보세요.

정답:

  1. 콜백 지옥을 해결해서 코드가 더 읽기 쉬워져요
  2. 오류 처리가 .catch()로 통일되어 더 간단해져요
  3. 여러 비동기 작업을 체이닝으로 연결할 수 있어요

Q3. 다음 코드의 출력 순서를 예측해보세요.

console.log("1");
let promise = new Promise(function(resolve) {
    console.log("2");
    resolve("3");
});
promise.then(function(result) {
    console.log(result);
});
console.log("4");

정답: "1" → "2" → "4" → "3"

해설: Promise 생성자는 즉시 실행되므로 "1", "2"가 순서대로 출력돼요. 그다음 "4"가 출력되고, 마지막에 .then()이 비동기적으로 실행되어 "3"이 출력돼요.

🔙 지난 시간 복습하기 (13.2.3 - 함수 나누기)

복습 문제 1: 함수 나누기의 가장 큰 장점은?

A) 코드 실행 속도가 빨라짐
B) 코드를 읽고 이해하기 쉬워짐
C) 메모리 사용량이 줄어듦
D) 인터넷 속도가 빨라짐

정답: B) 코드를 읽고 이해하기 쉬워짐

복습 문제 2: 가장 좋은 함수 이름은?

A) doSomething()
B) func1()
C) calculateScore()
D) process()

정답: C) calculateScore()

Promise는 현대 자바스크립트에서 비동기 처리의 핵심이 되는 중요한 도구예요. 다음 시간에는 Promise를 더 효과적으로 사용하는 방법들을 배워보겠습니다!

✅ 학습 완료 체크리스트

학습 내용 이해했나요?
Promise의 기본 개념
Promise의 3가지 상태
Promise 만들기와 사용하기
자주 하는 실수들
실전 예제 만들기

🎯 추가 연습 문제들

추가 문제 1. 3초 후에 "안녕하세요!"를 반환하는 Promise

let greetingPromise = new Promise(function(resolve, reject) {
    setTimeout(function() {
        resolve("안녕하세요!");
    }, 3000);
});

greetingPromise
    .then(function(message) {
        console.log(message);
    })
    .catch(function(error) {
        console.log("에러:", error);
    });

추가 문제 2. 숫자 체크 Promise

function checkNumber(num) {
    return new Promise(function(resolve, reject) {
        setTimeout(function() {
            if (num % 2 === 0) {
                resolve(num + "은 짝수입니다!");
            } else {
                reject(num + "은 홀수입니다!");
            }
        }, 1000);
    });
}

checkNumber(4)
    .then(function(result) {
        console.log("성공:", result);
    })
    .catch(function(error) {
        console.log("실패:", error);
    });

📂 마무리 정보

오늘 배운 Promise가 여러분의 자바스크립트 지식에 잘 저장되었나요? 다음 시간에는 Promise를 더 효과적으로 사용하는 방법들을 배워볼 예정이에요!


🚀 더 체계적인 JavaScript 학습을 원하신다면?
이 포스팅에서 다룬 내용을 실제로 실습해보세요!
무료 JavaScript 학습 플랫폼에서 단계별 학습과 실시간 코드 실행을 통해
더욱 효과적이고 재미있게 학습하실 수 있습니다.
📝 실시간 코드 실행 📊 학습 진도 관리 👥 체계적 커리큘럼
📚 171개 체계적 학습레슨 · 📋 855개 4지선다 연습문제 · 🆓 완전 무료 · ⚡ 즉시 시작