프로젝트/도서구매사이트

1027 비동기 처리 방식 종류 - promise, async/await

thinktank911 2025. 10. 26. 01:18

주문하기 전체 flow 

  • delivery(배송정보) ➡️ orders(주문정보) ➡️ orderedBook(주문한 책)
  • 배송정보 저장 후 insertId를 delivery_id로 받아 주문정보에 넣어줘야 하는데 에러남
    ➡️ conn.query() 안 delivery_id보다 괄호 밖 delivery_id 가 먼저 찍힘
    ➡️ conn.query()가 비동기 함수

노드js 비동기

논블로킹 I/O

  • 한명이 일을 하는데, 요리를 순차적으로 하지 않고 중간에 비는 시간이 있으면, 다른 요리를 한다.

비동기 처리 방식

  • 비동기 발생
    • 실행되는 코드가 기다려야 하는 시간이 생긴다는 의미
    • 이전 시간이 오래 걸리면, 안 기다려주고 (알아서 하라 그러고) 다음 코드를 무작정 실행함.
      ex> setTimeOut(), setInterval(), query()
  • 비동기 처리
    • 비동기 필요없을 때 이전 코드들의 시간을 다 기다려준다.
    • 순서를 맞춰서 코드를 실행해주겠다
  • 비동기 프로그래밍의 종류
    1. 콜백 함수 : 할 일 다 하고, 이거 실행해줘(= 순서 맞춰서 이걸 뒤에 실행해달라고)
    2. promise(resolve, reject)
    3. then & catch
    4. (es2017이후 버전) promise => async & await

Promise 객체

  • Promise 객체는 매개변수로 함수를 받는다.
    ➡️  resove : 성공, reject : 실패
  • resolve, reject는 .then()의 매개변수와 연관
  • then & catch : promise의 기본 메서드
    ➡️  promise가 일 다 하고(=약속 다 지키고) 호출해야하는 함수 
    ➡️  첫번째 매개변수 : resolve 결과
    ➡️  두번째 매개변수 : reject 에러
// Promise "객체" : 약속을 지키는 친구

// 객체 생성 = 친구 소환
// 매개변수로 함수 받음
// resove : 성공, reject : 실패
let promise = new Promise((resolve, reject)=>{
    // executor : 이 친구가 할 일

    setTimeout(() => resolve("완료!") , 3000);
    // 일을 다 하면 무조건 콜백함수 resolve() or reject() 둘 중 하나 호출
    // 할 일을 성공적으로 하면 resolve(결과), 
    // 실패하면 reject(에러)

});    
                                
// promise의 기본 메서드: promise가 일 다 하고(=약속 다 지키고) 호출해야하는 함수 
// 첫번째 매개변수 : resolve 결과
// 두번째 매개변수 : reject 에러
promise.then(
    (res)=>{
        console.log(res);
    },
    (err)=>{});

promise 체이닝

  • promise-chain-demo.js
// 비동기 처리 "Promise (Chaining)"
let promise = new Promise((resolve, reject)=>{
    setTimeout(() => resolve("완료") , 3000);
}).then(
    (res)=>{
        console.log(res);
        return res + "!!!!!";
    },
    (err)=>{}
).then(
    (res)=>{
        console.log(res);
        return res + "!!!!!";
    },
    (err)=>{}
).then(
    (res)=>{
        console.log(res);
        
    },
    (err)=>{}
)

async/await

  • async-await : Promise 객체를 좀 더 쉽고 편하게 사용 문법. 즉, 비동기 처리가 쉽다!
  • async : Promise 객체 반환하는 기능
    ➡️ 만약 반환값이 Promise가 아니면, Promise.resolve()로 감싼다.
// async-await : Promise 객체를 좀 더 쉽고 편하게 사용 문법
// 즉, 비동기 처리가 쉽다!

// async 함수
// ___ function f(){} : 일반 함수
// async function f(){} : async 함수
async function f() {
    // return Promise.resolve(7);   
    return 7;   
    // async 함수는 무조건 Promise 객체를 반환
    // async의 첫번째 기능
    // 만약 반환값이 Promise가 아니면, Promise.resolve()로 감싼다.
}

f().then(
    (res) => {
        console.log("promise resolve: ", res);
    },
    (err) => {
        console.log("promise reject: ", err);
    }
)
  • await
    • await은 async 함수 안에서만 동작
    • Promise 객체.then() 메소드를 좀 더 쉽게 사용할 수 있는 방법
    • async의 두번째 기능: Promise 객체가 일이 끝날 때까지 기다릴 수 있는 공간 제공
// async-await : Promise 객체를 좀 더 쉽고 편하게 사용 문법
// 즉, 비동기 처리가 쉽다!

// await은 async 함수 안에서만 동작
// Promise 객체.then() 메소드를 좀 더 쉽게 사용할 수 있는 방법
// async의 두번째 기능
// Promise 객체가 일이 끝날 때까지 기다릴 수 있는 공간 제공
async function f() {   
    // promise 객체 한 개당 => query 하나
    let promise1 = new Promise((resolve, reject) => {
        setTimeout(()=> resolve("첫번째 쿼리"), 3000);
    });

    let result1 = await promise1;
    // promise 객체가 일 다 할때까지 기다려줌
    console.log(result1);

    // promise 객체 한 개당 => query 하나
    let promise2 = new Promise((resolve, reject) => {
        setTimeout(()=> resolve("두번째 쿼리 with " + result1), 3000);
    });

    let result2 = await promise2;
    console.log(result2);

    // promise 객체 한 개당 => query 하나
    let promise3 = new Promise((resolve, reject) => {
        setTimeout(()=> resolve("세번째 쿼리 with " + result2), 3000);
    });

    let result3 = await promise3;
    console.log(result3);
};

f();

delivery_id 받아오기

  • conn.query(sql, values) 앞에 await  붙였을 때 promise 객체로 인식이 안된다.
  • mariadb.js의 connection 함수를 async/await으로 감싸기 ➡️ mariadb.js의 conn을 받아줄 경우 async/await이 제대로 안 먹히는 경우 발생
// mysql 모듈 소환
const mysql = require('mysql2/promise');  // 쿼리를 promise로 감싸기

// DB와 연결 통로 생성
const connection = async () => {
  const conn = await mysql.createConnection({
    host: '127.0.0.1',
    port: '3307',
    user: 'root',
    password: 'root',
    database: 'Bookshop',
    dateStrings: true,    // 날짜 형식대로 표기
  });

  return conn;
}

 

  • OrderController에 직접 dbConnection을 셋팅한다.
// const conn = require('../mariadb')  // db 모듈 가져오기
const mysql = require('mysql2/promise');  // 쿼리를 promise로 감싸기

const {StatusCodes} = require('http-status-codes');     // status code 모듈

// 주문하기
const order = async (req, res)=>{
    const conn = await mysql.createConnection({
        host: '127.0.0.1',
        port: '3307',
        user: 'root',
        password: 'root',
        database: 'Bookshop',
        dateStrings: true,    // 날짜 형식대로 표기
      });