13. 시간을 다루는 마법 (비동기 처리)/13.4 더 쉽게! async & await

13.4.3 Promise vs async/await - 두 가지 방법 비교해보기

thejavascript4kids 2025. 7. 19. 05:16

📘 13.4.3 Promise vs async/await - 두 가지 방법 비교해보기

여러분과 함께 걸어온 이 길이 참 멀고도 아름다웠습니다. 지금까지 우리는 정말 아름다운 여행을 해왔지요. Promise라는 약속 방법과 async/await라는 기다리기 방법을 각각 배워보면서, 순서가 있는 일들을 어떻게 처리하는지 알아봤습니다.

오늘은 이 두 가지 방법을 나란히 놓고 차분히 비교해볼 시간입니다. 마치 같은 목적지로 가는 두 개의 서로 다른 길을 비교해서 어떤 길이 더 아름다운지, 어떤 길이 더 편안한지 알아보는 것과 같습니다. 두 방법 모두 같은 목표를 향해 걸어가지만, 걸어가는 방식이 조금씩 다릅니다.

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

Promise와 async/await를 비교하면서 알아둘 단어들을 자연스럽게 풀어서 설명해드리겠습니다.

단어 쉬운 설명
비교 분석 두 가지 방법을 나란히 놓고 어떤 점이 다른지, 어떤 게 더 좋은지 살펴보는 거예요.
코드 스타일 코드를 쓰는 방식이나 모양을 말해요. 마치 글씨체처럼 각자 다른 특징이 있어요.
읽기 쉬움 코드를 봤을 때 다른 사람도 쉽게 이해할 수 있는 정도를 말해요.
편의 문법 어려운 기능을 더 쉽고 간단하게 사용할 수 있게 해주는 특별한 문법이에요.

async/await는 Promise의 "편의 문법"이라고 불립니다. 마치 무거운 짐을 들 때 바퀴 달린 가방을 사용하는 것처럼, Promise를 더 쉽고 편하게 사용할 수 있게 도와주는 도구입니다.

✨ Promise와 async/await는 어떻게 다를까요?

Promise와 async/await는 본질적으로 같은 일을 하는 두 가지 다른 방법입니다. 마치 "안녕하세요"와 "안녕"이 같은 마음을 전하지만 다른 표현인 것처럼, 둘 다 순서가 있는 일을 처리하고 결과를 안전하게 다루는 것이 목적입니다.

Promise 방식연결고리 스타일을 따릅니다. .then().then().catch() 형태로 마치 사슬처럼 연결해서 사용하는 방식이지요. 각 단계를 별도의 함수로 처리해서 연결고리로 만드는 방법입니다.

async/await 방식차례대로 하기 스타일을 따릅니다. 일반적인 코드처럼 위에서 아래로 순서대로 실행되는 것처럼 보이게 만드는 방식입니다. 마치 평소에 우리가 말하는 순서대로 코드를 쓸 수 있게 해줍니다.

가장 중요한 점은 async/await가 Promise를 없애는 게 아니라는 것입니다. async/await는 속에서 Promise를 사용하면서 더 쉬운 문법을 제공하는 것입니다. 마치 자동차와 자동변속기의 관계와 같습니다. 자동변속기가 수동변속기를 더 쉽게 사용할 수 있게 해주는 것처럼 말이지요.

선택하는 기준은 상황과 개인 취향, 그리고 팀에서 사용하는 스타일에 따라 달라집니다. 중요한 것은 어떤 방법을 선택하든 일관되게 사용하는 것입니다.

따뜻한 비유: 두 가지 다른 요리 순서

Promise와 async/await를 더 쉽게 이해하기 위해 '요리하는 두 가지 다른 방법'에 비유해보겠습니다.

목적지는 같지만 순서를 정하는 방법이 다른 두 가지 요리 방식이 있습니다.

Promise 방식 (레시피 카드 방법):
"1번 카드: 재료 준비하기 → 완료되면 2번 카드 보기 → 2번 카드: 볶기 시작 → 완료되면 3번 카드 보기 → 3번 카드: 그릇에 담기"

이 방식은 각 단계가 카드로 연결되어 있습니다. 각 카드에서 다음 카드로 넘어가는 명확한 연결 구조를 가지고 있지요. 전체 요리 과정을 한눈에 볼 수 있고, 각 단계를 따로따로 관리할 수 있습니다.

async/await 방식 (요리책 읽기 방법):
"재료를 준비한다 → 준비가 끝날 때까지 조용히 기다린다 → 볶기를 시작한다 → 볶기가 끝날 때까지 조용히 기다린다 → 그릇에 정성스럽게 담는다"

이 방식은 하나의 연속된 요리 과정처럼 느껴집니다. 카드를 넘길 필요 없이 처음부터 끝까지 자연스럽게 이어지지요. 요리하는 사람 입장에서는 매우 쉽고 이해하기 좋은 방법입니다.

두 방법 모두 같은 요리를 만들지만, 요리하는 경험과 느낌이 달라집니다. Promise와 async/await도 이와 똑같은 관계입니다.

🎯 두 방법을 비교하는 이유

Promise와 async/await를 비교하는 것이 왜 중요할까요? 여러 실용적인 이유들이 있습니다.

첫 번째는 상황에 맞는 최적의 선택을 하기 위해서입니다. 마치 짧은 거리는 걸어가고 먼 거리는 차를 타는 것처럼, 각 상황에 가장 적합한 방법을 선택할 수 있어야 합니다.

두 번째는 기존 코드를 이해하고 바꾸기위해서입니다. 인터넷에는 Promise로 만들어진 코드가 정말 많이 있어서, 이를 이해하고 필요하면 async/await로 바꿀 수 있어야 합니다. 또는 그 반대의 경우도 마찬가지입니다.

세 번째는 팀에서 함께 일하기위해서입니다. 다른 사람들과 함께 프로그래밍을 할 때 어떤 스타일을 사용할지 정하고, 서로의 코드를 이해할 수 있어야 합니다.

네 번째는 더 좋은 코드 만들기위해서입니다. 각 방법의 장점과 단점을 알고 있으면 더 읽기 쉽고 고치기 좋은 코드를 만들 수 있습니다.

마지막으로 더 깊이 배우기위해서입니다. 비교를 통해 각 방법의 특징을 더 명확하게 이해하고, 순서가 있는 프로그래밍의 전체적인 그림을 그릴 수 있게 됩니다.

⚙️ 기본 사용법 비교하기

두 방법의 기본 사용법을 직접 비교해보겠습니다. 같은 일을 하는 코드를 두 가지 방식으로 만들어보겠습니다.

같은 일을 하는 두 가지 방법:

// Promise 방식 - 사슬고리 스타일
function promiseStyle() {
    return firstTask()
        .then(function(result1) {
            console.log("1단계 완료:", result1);
            return secondTask(result1);
        })
        .then(function(result2) {
            console.log("2단계 완료:", result2);
            return thirdTask(result2);
        })
        .catch(function(error) {
            console.log("문제가 생겼어요:", error);
            return "문제를 해결했어요";
        });
}

// async/await 방식 - 차례대로 하기 스타일
async function asyncAwaitStyle() {
    try {
        let result1 = await firstTask();
        console.log("1단계 완료:", result1);

        let result2 = await secondTask(result1);
        console.log("2단계 완료:", result2);

        let result3 = await thirdTask(result2);
        return result3;
    } catch (error) {
        console.log("문제가 생겼어요:", error);
        return "문제를 해결했어요";
    }
}

주요 차이점:

  • Promise: .then() 사슬고리로 연결, .catch()로 문제 처리
  • async/await: await 키워드로 기다림, try/catch로 문제 처리

공통점:

  • 둘 다 같은 결과를 만들어냄
  • 둘 다 순서가 있는 일을 차례대로 처리
  • 둘 다 문제를 안전하게 처리

🧪 예제로 익혀보기

실제 예제를 통해 두 방법의 차이점과 특징을 자세히 비교해보겠습니다.

🔹 예제 1: 같은 작업을 두 가지 방식으로 구현하기

이번 예제에서는 학생 정보를 조회하는 같은 작업을 두 가지 방식으로 구현해보겠습니다.

// 학생 정보를 가져오는 Promise 함수
function getStudentInfo(studentId) {
    return new Promise(function(resolve, reject) {
        console.log("📋 학생 ID " + studentId + " 조회 중...");
        setTimeout(function() {
            if (studentId > 0 && studentId <= 100) {
                resolve({
                    id: studentId,
                    name: "김학생",
                    grade: "5학년"
                });
            } else {
                reject("그런 학생은 없어요");
            }
        }, 1000);
    });
}

// 학생 성적을 가져오는 Promise 함수
function getStudentGrade(student) {
    return new Promise(function(resolve) {
        console.log("📊 " + student.name + " 성적 조회 중...");
        setTimeout(function() {
            resolve({
                student: student,
                math: 85,
                korean: 92,
                average: 88.5
            });
        }, 1000);
    });
}

// Promise 방식 - 사슬고리로 연결
function getCompleteInfoWithPromise(studentId) {
    console.log("🎯 Promise 방식으로 정보 조회 시작");

    return getStudentInfo(studentId)
        .then(function(studentInfo) {
            console.log("✅ 학생 정보:", studentInfo.name);
            return getStudentGrade(studentInfo);
        })
        .then(function(gradeInfo) {
            console.log("✅ 성적 정보 완료");
            return {
                name: gradeInfo.student.name,
                grade: gradeInfo.student.grade,
                average: gradeInfo.average
            };
        })
        .catch(function(error) {
            console.log("❌ Promise 문제:", error);
            return { error: "정보 조회 실패" };
        });
}

// async/await 방식 - 차례대로 처리
async function getCompleteInfoWithAsync(studentId) {
    console.log("🎯 async/await 방식으로 정보 조회 시작");

    try {
        let studentInfo = await getStudentInfo(studentId);
        console.log("✅ 학생 정보:", studentInfo.name);

        let gradeInfo = await getStudentGrade(studentInfo);
        console.log("✅ 성적 정보 완료");

        return {
            name: gradeInfo.student.name,
            grade: gradeInfo.student.grade,
            average: gradeInfo.average
        };
    } catch (error) {
        console.log("❌ async/await 문제:", error);
        return { error: "정보 조회 실패" };
    }
}

// 두 방법 모두 실행해서 비교
getCompleteInfoWithPromise(25);
getCompleteInfoWithAsync(25);

이 예제를 비교해보면, Promise 방식은 각 단계가 .then()으로 연결되어 있고, async/await 방식은 일반 코드처럼 순서대로 작성되어 있습니다. 결과는 똑같지만 코드를 읽는 느낌이 완전히 다르지요. async/await 버전이 더 자연스럽고 이해하기 쉽다는 것을 느낄 수 있습니다.

🔹 예제 2: 복잡한 조건이 포함된 비교

조건에 따라 다른 작업을 해야 하는 복잡한 상황에서 두 방법의 차이를 비교해보겠습니다.

// 시험 점수에 따라 다른 처리를 하는 함수들
function getExamScore() {
    return Promise.resolve(Math.floor(Math.random() * 100) + 1);
}

function processHighScore(score) {
    return Promise.resolve("🏆 우수상: " + score + "점");
}

function processLowScore(score) {
    return Promise.resolve("💪 격려: " + score + "점, 다음엔 더 잘할 거예요!");
}

// Promise 방식 - 조건문이 복잡해짐
function processScoreWithPromise() {
    console.log("🎯 Promise 방식으로 점수 처리");

    return getExamScore()
        .then(function(score) {
            console.log("📊 받은 점수:", score);

            if (score >= 80) {
                return processHighScore(score);
            } else {
                return processLowScore(score);
            }
        })
        .then(function(result) {
            console.log("✅ Promise 처리 결과:", result);
            return result;
        })
        .catch(function(error) {
            console.log("❌ Promise 문제:", error);
            return "처리 실패";
        });
}

// async/await 방식 - 조건문이 자연스러움
async function processScoreWithAsync() {
    console.log("🎯 async/await 방식으로 점수 처리");

    try {
        let score = await getExamScore();
        console.log("📊 받은 점수:", score);

        let result;
        if (score >= 80) {
            result = await processHighScore(score);
        } else {
            result = await processLowScore(score);
        }

        console.log("✅ async/await 처리 결과:", result);
        return result;
    } catch (error) {
        console.log("❌ async/await 문제:", error);
        return "처리 실패";
    }
}

// 두 방법 실행
processScoreWithPromise();
processScoreWithAsync();

이 예제에서는 async/await의 장점이 더욱 명확하게 드러납니다. 조건문이 들어가면 Promise 사슬고리는 복잡해지지만, async/await는 일반적인 if문처럼 자연스럽게 작성할 수 있습니다. 특히 복잡한 로직이 들어갈수록 async/await의 읽기 쉬움 장점이 더 커집니다.

🔹 예제 3: 문제 처리 방식 비교

두 방법에서 문제를 처리하는 방식을 직접 비교해보겠습니다.

// 때로는 실패하는 작업 함수들
function riskyTask1() {
    return new Promise(function(resolve, reject) {
        setTimeout(function() {
            if (Math.random() > 0.3) {
                resolve("1단계 성공");
            } else {
                reject("1단계 실패");
            }
        }, 1000);
    });
}

function riskyTask2() {
    return new Promise(function(resolve, reject) {
        setTimeout(function() {
            if (Math.random() > 0.3) {
                resolve("2단계 성공");
            } else {
                reject("2단계 실패");
            }
        }, 1000);
    });
}

// Promise 방식 - 문제 처리
function handleErrorsWithPromise() {
    console.log("🎯 Promise 문제 처리 시작");

    return riskyTask1()
        .then(function(result1) {
            console.log("✅", result1);
            return riskyTask2();
        })
        .then(function(result2) {
            console.log("✅", result2);
            return "Promise 모든 작업 성공";
        })
        .catch(function(error) {
            console.log("❌ Promise에서 문제 잡음:", error);
            return "Promise 문제 해결됨";
        })
        .finally(function() {
            console.log("🔧 Promise 정리 작업");
        });
}

// async/await 방식 - 문제 처리
async function handleErrorsWithAsync() {
    console.log("🎯 async/await 문제 처리 시작");

    try {
        let result1 = await riskyTask1();
        console.log("✅", result1);

        let result2 = await riskyTask2();
        console.log("✅", result2);

        return "async/await 모든 작업 성공";
    } catch (error) {
        console.log("❌ async/await에서 문제 잡음:", error);
        return "async/await 문제 해결됨";
    } finally {
        console.log("🔧 async/await 정리 작업");
    }
}

// 두 방법 실행
handleErrorsWithPromise();
handleErrorsWithAsync();

문제 처리 측면에서는 async/await가 더 직관적입니다. try/catch는 다른 프로그래밍 언어에서도 흔히 사용하는 패턴이라서 익숙하고, 어느 줄에서 문제가 발생했는지 파악하기도 쉽습니다. Promise의 .catch()도 좋지만, 복잡한 로직에서는 async/await의 try/catch가 더 명확합니다.

🔄 장단점 비교하기

지금까지 살펴본 내용을 바탕으로 두 방법의 장점과 단점을 정리해보겠습니다.

Promise 방식의 좋은 점:

  • 함수를 연결해서 사용하는 스타일에 익숙한 사람에게 자연스럽습니다
  • 간단한 데이터 변환에서는 사슬고리가 더 간결할 수 있습니다
  • Promise.all(), Promise.race() 같은 특별한 기능과 잘 어울립니다
  • 각 단계를 독립적인 함수로 나누기 쉽습니다

Promise 방식의 아쉬운 점:

  • 복잡한 로직에서는 읽기가 어려워집니다
  • 조건문이나 반복문과 함께 사용하기 어렵습니다
  • 문제 처리가 여러 곳에 흩어질 수 있어서 관리가 복잡합니다

async/await 방식의 좋은 점:

  • 차례대로 진행되어서 읽고 이해하기 쉽습니다
  • 조건문, 반복문과 자연스럽게 결합됩니다
  • try/catch로 통합 문제 처리가 가능합니다
  • 디버깅할 때 코드 흐름을 따라가기 쉽습니다

async/await 방식의 아쉬운 점:

  • Promise의 기본 개념을 이해해야 사용할 수 있습니다
  • 병렬 처리할 때 주의가 필요합니다 (모든 await가 차례대로 실행됨)
  • 함수 전체에 async를 붙여야 해서 함수의 성격이 바뀝니다

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

두 방법을 비교할 때 자주 하는 실수들을 미리 알아두면 더 현명한 선택을 할 수 있습니다.

❌ 실수 1: 두 방식을 섞어서 사용하기

// 혼란스러운 예시 - 일관성이 없음
async function confusingMix() {
    let result1 = await firstTask();

    // 갑자기 Promise 사슬고리 사용
    return secondTask(result1)
        .then(function(result2) {
            return result2.toUpperCase();
        })
        .catch(function(error) {
            return "문제 처리";
        });
}

// 일관된 예시 - async/await로 통일
async function consistentAsync() {
    try {
        let result1 = await firstTask();
        let result2 = await secondTask(result1);
        return result2.toUpperCase();
    } catch (error) {
        return "문제 처리";
    }
}

하나의 함수에서는 하나의 스타일로 일관되게 작성하는 것이 좋습니다. 섞어서 사용하면 코드를 읽는 사람이 혼란스러워할 수 있습니다.

❌ 실수 2: async/await가 무조건 더 좋다고 생각하기

// 간단한 경우에는 Promise가 더 간결할 수 있음
// Promise 방식
function simpleConversion(data) {
    return getData(data).then(result => result.toUpperCase());
}

// async/await 방식 (오히려 더 복잡)
async function notSoSimpleConversion(data) {
    let result = await getData(data);
    return result.toUpperCase();
}

간단한 변환이나 처리에서는 Promise 사슬고리가 더 간결하고 적절할 수 있습니다. 상황에 따라 선택하는 것이 중요합니다.

❌ 실수 3: Promise를 모르고 async/await만 사용하려고 하기

// Promise 기본 원리를 모르면 async/await도 제대로 사용하기 어려움
// async/await는 Promise 위에 만들어진 문법이므로 Promise 이해가 필수

async/await는 Promise를 없애는 것이 아니라 Promise를 더 쉽게 사용하게 해주는 도구입니다. Promise의 기본 개념을 이해하고 사용해야 합니다.

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

연습문제를 시작하기 전에 잠시 마음을 가다듬어보겠습니다. 지금까지 Promise와 async/await라는 두 가지 다른 길을 걸어보면서, 같은 목적지로 가는 서로 다른 여행법을 경험했습니다. 어떤 길이 더 아름다운지, 어떤 길이 더 편안한지는 상황과 개인의 취향에 따라 다를 수 있습니다. 이제 그 경험을 바탕으로 연습을 해보겠습니다.

Ex1) Promise 코드를 async/await로 바꿔보자

// 원본 Promise 코드
function getWeatherInfo() {
    return getLocation()
        .then(function(location) {
            console.log("위치:", location);
            return getWeather(location);
        })
        .then(function(weather) {
            console.log("날씨:", weather);
            return weather.temperature;
        })
        .catch(function(error) {
            console.log("문제:", error);
            return "날씨 정보 없음";
        });
}

// 바꾼 async/await 코드
async function getWeatherInfoAsync() {
    try {
        let location = await getLocation(); // 위치 정보를 기다려요
        console.log("위치:", location);

        let weather = await getWeather(location); // 날씨 정보를 기다려요
        console.log("날씨:", weather);

        return weather.temperature; // 온도를 돌려줘요
    } catch (error) {
        console.log("문제:", error); // 문제가 생기면 여기서 처리해요
        return "날씨 정보 없음";
    }
}

Ex2) async/await 코드를 Promise로 바꿔보자

// 원본 async/await 코드
async function processOrder() {
    try {
        let order = await createOrder();
        let payment = await processPayment(order);
        let delivery = await scheduleDelivery(payment);
        return delivery;
    } catch (error) {
        return "주문 처리 실패";
    }
}

// 바꾼 Promise 코드
function processOrderPromise() {
    return createOrder() // 주문을 만들어요
        .then(function(order) {
            return processPayment(order); // 결제를 처리해요
        })
        .then(function(payment) {
            return scheduleDelivery(payment); // 배송을 예약해요
        })
        .then(function(delivery) {
            return delivery; // 배송 정보를 돌려줘요
        })
        .catch(function(error) {
            return "주문 처리 실패"; // 문제가 생기면 여기서 처리해요
        });
}

Ex3) 간단한 유저 정보 조회 함수를 두 가지 방식으로 만들어보자

// 사용자 정보를 가져오는 기본 함수
function getUserData(userId) {
    return new Promise(function(resolve, reject) {
        setTimeout(function() {
            if (userId > 0) {
                resolve({ id: userId, name: "사용자" + userId });
            } else {
                reject("잘못된 사용자 ID");
            }
        }, 1000);
    });
}

// Promise 방식
function getUserInfoPromise(userId) {
    return getUserData(userId)
        .then(function(user) {
            console.log("Promise 방식:", user.name);
            return user;
        })
        .catch(function(error) {
            console.log("Promise 오류:", error);
            return { id: 0, name: "기본 사용자" };
        });
}

// async/await 방식
async function getUserInfoAsync(userId) {
    try {
        let user = await getUserData(userId);
        console.log("async/await 방식:", user.name);
        return user;
    } catch (error) {
        console.log("async/await 오류:", error);
        return { id: 0, name: "기본 사용자" };
    }
}

// 두 방법 모두 테스트
getUserInfoPromise(5);
getUserInfoAsync(5);

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

기본 연습을 마쳤다면, 조금 더 깊이 있는 문제들을 통해 두 방법의 이해를 확인해보겠습니다.

Q1. Promise와 async/await의 관계를 설명해보세요.

정답: async/await는 Promise를 없애는 새로운 기술이 아니라, Promise를 더 쉽고 직관적으로 사용할 수 있게 해주는 편의 문법입니다. 안에서는 여전히 Promise를 사용하며, 복잡한 Promise 사슬고리를 차례대로 하는 코드처럼 작성할 수 있게 해줍니다.

해설: 마치 자동차의 수동변속기와 자동변속기의 관계와 같습니다. 자동변속기가 수동변속기를 완전히 없애는 것이 아니라, 더 쉽게 사용할 수 있게 해주는 것처럼, async/await도 Promise를 더 쉽게 사용할 수 있게 해주는 도구입니다.

Q2. 언제 Promise를 사용하고 언제 async/await를 사용하는 것이 좋나요?

정답: 간단한 데이터 변환이나 함수를 연결하는 스타일을 선호할 때는 Promise를, 복잡한 차례대로 처리나 조건문이 많이 포함된 로직에서는 async/await를 사용하는 것이 좋습니다. 가장 중요한 것은 팀 내에서 일관성을 유지하는 것입니다.

해설: 상황에 따른 선택이 중요합니다. 마치 짧은 거리는 걸어가고 먼 거리는 차를 타는 것처럼, 각 상황에 맞는 최적의 방법을 선택하면 됩니다.

Q3. 다음 두 코드의 성능 차이가 있을까요?

// Promise 버전
getData().then(result => result.toUpperCase());

// async/await 버전
async function processData() {
    let result = await getData();
    return result.toUpperCase();
}

정답: 성능상 의미 있는 차이는 거의 없습니다. async/await는 안에서 Promise를 사용하므로 동일한 방식으로 동작합니다. 차이가 있다면 코드의 읽기 쉬움과 고치기 쉬움 측면입니다.

해설: 두 방법 모두 같은 엔진을 사용하는 자동차와 같습니다. 겉모습은 다르지만 성능은 비슷합니다. 선택의 기준은 성능이 아니라 사용하기 편한 정도나 상황에 맞는 적합성입니다.

🔙 지난 시간 복습하기

13.4.2에서 배운 async/await의 에러 처리를 복습해볼까요?

복습 문제 1: try/catch의 실행 순서를 설명하고 간단한 예제를 만들어보세요.

정답:

async function errorHandlingExample() {
    try {
        console.log("1. try 블록 시작");
        let result = await riskyOperation();
        console.log("2. 성공 시에만 실행:", result);
        return result;
    } catch (error) {
        console.log("3. 에러 발생 시 실행:", error);
        return "에러 처리됨";
    } finally {
        console.log("4. 항상 마지막에 실행됨");
    }
}

errorHandlingExample();

해설: try 블록이 먼저 실행되고, 에러가 발생하면 즉시 catch 블록으로 이동합니다. 에러가 없으면 catch는 건너뛰고, finally는 어떤 경우든 항상 실행됩니다.

복습 문제 2: async/await에서 try/catch를 사용하는 장점 2가지를 설명해보세요.

정답: 1) 여러 개의 await를 하나의 try/catch로 처리할 수 있어서 에러 처리가 간결해집니다. 2) Promise의 .catch()보다 더 직관적이고 일반적인 프로그래밍 언어의 에러 처리 방식과 같아서 이해하기 쉽습니다.

해설: try/catch는 통합 에러 처리와 직관적인 문법이라는 두 가지 큰 장점을 가지고 있습니다. 이 덕분에 복잡한 비동기 작업에서도 안전하고 읽기 쉬운 코드를 작성할 수 있습니다.

지금까지 Promise와 async/await를 비교해보면서 각각의 특징과 장단점을 알아봤습니다. 두 방법 모두 같은 목적을 가지고 있지만 사용하는 방식이 다르다는 것을 이해했습니다. 중요한 것은 상황에 맞는 적절한 선택과 일관성 있는 사용입니다. 다음 시간에는 여러 Promise를 동시에 처리하는 고급 기법들을 배워보겠습니다.

✅ 학습 완료 체크리스트

이번 시간에 배운 내용들을 모두 이해했는지 확인해보세요!

학습 내용 이해했나요?
Promise와 async/await의 차이점
두 방법의 장단점
상황에 맞는 선택 기준
자주 하는 실수들
실전 예제 이해

🎯 추가 연습 문제들

조금 더 연습하고 싶은 분들을 위한 추가 문제들입니다!

추가 문제 1. 다음 Promise 코드를 async/await로 변환해보세요.

// 원본 Promise 코드
function promiseVersion() {
    return getData(1)
        .then(function(data) {
            console.log("데이터:", data);
            return data.toUpperCase();
        })
        .catch(function(error) {
            console.log("에러:", error);
            return "기본값";
        });
}

// 답:
async function asyncVersion() {
    try {
        let data = await getData(1);
        console.log("데이터:", data);
        return data.toUpperCase();
    } catch (error) {
        console.log("에러:", error);
        return "기본값";
    }
}

추가 문제 2. 다음 async/await 코드를 Promise로 변환해보세요.

// 원본 async/await 코드
async function asyncVersion() {
    try {
        let step1 = await firstStep();
        let step2 = await secondStep(step1);
        return step2;
    } catch (error) {
        return "실패";
    }
}

// 답:
function promiseVersion() {
    return firstStep()
        .then(function(step1) {
            return secondStep(step1);
        })
        .then(function(step2) {
            return step2;
        })
        .catch(function(error) {
            return "실패";
        });
}

추가 문제 3. 두 방식의 장단점을 각각 2가지씩 말해보세요.

// 답:
// Promise 장점:
// 1. 함수형 프로그래밍 스타일
// 2. 간단한 변환에서는 더 간결함

// Promise 단점:
// 1. 복잡한 체이닝에서 가독성 떨어짐
// 2. 에러 처리가 분산될 수 있음

// async/await 장점:
// 1. 순차적이라 읽기 쉬움
// 2. try/catch로 통합 에러 처리

// async/await 단점:
// 1. 병렬 처리에서 주의 필요
// 2. Promise 이해가 선행되어야 함

추가 문제 4. 언제 Promise를 사용하고 언제 async/await를 사용하는 것이 좋나요?

: 간단한 체이닝이나 함수형 스타일을 원할 때는 Promise를, 복잡한 순차 처리나 읽기 쉬운 코드를 원할 때는 async/await를 사용하는 것이 좋습니다. 가장 중요한 것은 팀 내에서 일관성을 유지하는 것입니다.

📂 마무리 정보

오늘 배운 13.4.3 내용이 여러분의 자바스크립트 지식에 자연스럽게 스며들었나요? 다음 시간에는 더 재미있는 내용으로 만나겠습니다!

기억할 점: 오늘 배운 내용을 꼭 연습해보시고, 궁금한 점이 있으면 언제든 다시 돌아와서 읽어보세요.


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