본문 바로가기
백엔드/Node.js

async와 await

by hyunji00pj 2024. 11. 7.

async와 await

 

기존에 콜백과 Promise로 구현한 코드를 async/await로 변환하여 코드를 간결하고 읽기 쉽게 만들 수 있다

 

1. getBanana, getApple, getOrange 함수 정의

먼저, 각 과일을 가져오는 함수들을 정의합니다.

 

function getBanana(){
    return new Promise((resolve)=> { // 새로운 Promise 생성
        setTimeout(()=>{ // 1초 후 실행
            resolve('🍌') // '🍌' 반환
        }, 1000) // 1000ms = 1초
    })
}

function getApple(){
    return new Promise((resolve)=> { // 새로운 Promise 생성
        setTimeout(()=>{ // 3초 후 실행
            resolve('🍎') // '🍎' 반환
        }, 3000) // 3000ms = 3초
    })
}

function getOrange(){
    return Promise.reject(new Error('오렌지 없음')) // 에러를 즉시 반환하는 Promise 생성
}

 

함수 설명

  • getBanana: 1초 후에 바나나(🍌)를 반환하는 Promise를 생성합니다.
  • getApple: 3초 후에 사과(🍎)를 반환하는 Promise를 생성합니다.
  • getOrange: 에러(오렌지 없음)를 발생시키는 Promise를 즉시 반환하여, 비동기 작업에서 오류 처리를 테스트할 수 있도록 합니다.

이러한 함수들을 통해 비동기 작업의 처리 흐름을 이해할 수 있다.

 

2. async와 await로 비동기 함수 구현

이제 async와 await을 사용하여 비동기 작업을 순차적으로 처리하는 fetchFruits 함수를 만들어 보겠다.

async function fetchFruits() {
    const banana = await getBanana() // getBanana()가 완료될 때까지 대기
    const apple = await getApple()   // getApple()이 완료될 때까지 대기
    return [banana, apple]           // 결과 배열을 반환
}
fetchFruits().then((fruits) => console.log(fruits))

fetchFruits 함수 설명

  1. async 키워드: fetchFruits 함수 앞에 async를 붙여 비동기 함수로 정의합니다.
    • async 함수는 항상 Promise를 반환하며, 내부에서 비동기 작업을 await 키워드와 함께 사용할 수 있습니다.
  2. await getBanana(): await 키워드는 getBanana()가 완료될 때까지 기다린 후 다음 줄로 넘어갑니다.
    • getBanana가 1초 후에 🍌를 반환하므로, banana 변수에는 🍌가 할당됩니다.
  3. await getApple(): getApple()이 완료될 때까지 기다립니다.
    • getApple은 3초 후에 🍎를 반환하므로, apple 변수에는 🍎가 할당됩니다.
  4. return [banana, apple]: 배열 [banana, apple]을 반환하여, 최종적으로 ['🍌', '🍎']가 반환됩니다.

3. fetchFruits().then((fruits) => console.log(fruits))

  • fetchFruits는 async 함수이므로 Promise를 반환하며, then을 통해 결과값을 받습니다.
['🍌', '🍎']

코드의 핵심 포인트

  • 비동기 코드의 가독성 개선: async와 await은 비동기 작업을 동기적인 코드 스타일로 작성하게 해줍니다. 코드가 직관적이며, 기존의 콜백 방식보다 이해하기 쉽습니다.
  • 순차적 처리: await 키워드는 각 비동기 작업이 순차적으로 실행되도록 합니다. 각 await 구문은 해당 작업이 완료된 후에 다음 코드로 진행합니다.
  • 오류 처리의 단순화: try...catch 구문과 함께 사용하면 오류 처리를 직관적으로 구현할 수 있습니다. getOrange 함수의 에러 처리를 추가할 때 유용합니다.

예제 확장: try...catch로 오류 처리 추가

getOrange 함수의 오류를 처리하는 확장 예제입니다.

async function fetchFruits() {
    try {
        const banana = await getBanana()
        const apple = await getApple()
        const orange = await getOrange() // 오류 발생 부분
        return [banana, apple, orange]
    } catch (error) {
        console.error('에러 발생:', error.message)
    }
}
fetchFruits().then((fruits) => console.log(fruits))

오류 발생 시: getOrange()에서 에러가 발생하면 catch 블록이 실행되어 "에러 발생: 오렌지 없음" 메시지가 출력됩니다.

 

전체 코드

// 1초 후에 바나나 이모지('🍌')를 반환하는 Promise를 생성하는 함수
function getBanana() {
    return new Promise((resolve) => { // 새로운 Promise 생성
        setTimeout(() => { // 1초 후 실행
            resolve('🍌'); // '🍌'를 반환하며 Promise 이행
        }, 1000); // 1000ms(1초)
    });
}

// 3초 후에 사과 이모지('🍎')를 반환하는 Promise를 생성하는 함수
function getApple() {
    return new Promise((resolve) => { // 새로운 Promise 생성
        setTimeout(() => { // 3초 후 실행
            resolve('🍎'); // '🍎'를 반환하며 Promise 이행
        }, 3000); // 3000ms(3초)
    });
}

// 즉시 에러를 발생시키는 Promise를 반환하는 함수
function getOrange() {
    return Promise.reject(new Error('오렌지 없음')); // '오렌지 없음' 에러로 Promise 거부
}

// async와 await을 사용하여 바나나와 사과를 순차적으로 가져오는 비동기 함수
async function fetchFruits() {
    const banana = await getBanana(); // getBanana()가 완료될 때까지 대기, '🍌'를 반환받아 banana에 저장
    const apple = await getApple(); // getApple()이 완료될 때까지 대기, '🍎'를 반환받아 apple에 저장
    return [banana, apple]; // [바나나, 사과] 배열을 반환
}

// fetchFruits 함수를 호출하고 결과가 반환되면 콘솔에 출력
fetchFruits().then((fruits) => console.log(fruits)); // ['🍌', '🍎'] 출력

 

'백엔드 > Node.js' 카테고리의 다른 글

Node.js 프로젝트 시작하기: 효율적인 파일 구조와 라우팅 관리  (20) 2024.11.13
package.json 파일 생성 및 설정 방법  (0) 2024.11.13
fetch  (2) 2024.11.09
Node.js  (2) 2024.11.08
Promise  (0) 2024.11.07