본문 바로가기

프로그래머스 풀스택 데브코스/데브코스 TIL

웹 풀사이클 데브코스 TIL 38일차

논 블로킹 I/O

비동기식 I/O 처리
전날의 강의에서 발생했던 문제는 이 비동기식 처리 때문에 발생한 일이다.
노드 js 한테는 순서가 의미가 없다. 그렇다면 여태까지는 왜 문제가 없었을까?

Node.js 비동기 처리 방식

  • 비동기 발생 : 실행되는 코드가 기다려야 하는 시간이 생긴다는 뜻. 이전 시간이 오래걸리면 안 기다려주고 다음코드를 무작정 실행
    ex) setTimeOut(), setInterval(), query()
  • 비동기 처리 : 비동기가 필요 없을 때가 있는데 이런 부분은 처리해주어야 한다. 이전 코드들의 시간을 다 기다려 준다. 순서를 맞춰서 코드를 실행해 주겠다

비동기 처리

  1. 콜백 함수 : 함수 할일 다하고 이걸 실행해줘(= 순서 맞춰서 이걸 뒤에 실행해 줘)
  2. Promise(resolve, reject)
  3. then & catch
  4. async & await : ES2017 버전 promise

Promise

Promise 객체는 동기적으로 처리가 가능하게 해준다. 아래는 활용 예시이다.


// Promise 객체 : 약속을 지킨다.
let promise = new Promise(function(resolve, reject) { // 매개변수로 함수를 받는다.
    //excutor : 얘가 할 일

    setTimeout(() => resolve("완료") ,3000);

    // 일을 다하면 무조건 콜백함수 resolve() 또는 reject() 둘 중 하나는 호출
    //할일을 성공적으로 하면 resolve(결과)
    // 실패하면 reject(에러)

});

//promise의 기본 메서드 : promise가 일 다 하고 호출해야하는 함수
promise.then(
    function(result){
        console.log(result);
}, 
function(error){

});

Promise 는 객체이다. Promise 객체에는 매개변수로 함수가 들어가는데 이 함수의 매개변수로 resolve와 reject가 들어간다. 이 두 함수는 각각 일이 성공했을 때, 실패했을 때 사용한다. 결과를 담고, promise의 메서드 중 하나인 then 을 호출하면 성공했을 경우 첫번째 매개변수, 실패했을 경우 두번재 매개변수를 부른다.

Promise chain

위의 예시에서는 두가지 연산만 작동하였다. 하지만 우리는 세 개 이상의 연산을 요구할 수도 있다. 그럴 때는 then 문을 이어 붙여서 promise chain을 만들 수 있다.

let promise = new Promise(function(resolve, reject) {
    setTimeout(() => resolve("완료") ,3000);

}).then(
    function(result){
        console.log(result);
        return result + "!!!!";
}, 
function(error){

}).then(
    function(result){
        console.log(result);
        return result + "!!!!";
}, 
function(error){

}).then(
    function(result){
        console.log(result);
})

단 이어지기 위해서는 앞의 then 에서 return으로 값을 반환해주어야 한다.

Async

Async 는 Promise 객체를 편하게 사용할 수 있게 해주는 방식이다.

// async-await : Promise 객체를 좀 더 쉽게 사용하는 문법
// 쉽게 비동기 처리가 가능

//async 함수
// _____ function f() {} : 일반 함수
// async function f() {} : async 함수

async function f() {
    return 7; // Promise 객체를 반환 중 Promise.resolve(7);
    //async 함수는 무조건 Promise 객체를 반환
    // 만약 반환값이 Promise가 아니면, Promise.resolve() 로 감쌈
}

f().then(
    function(result) {
        console.log("promise resolve : ", result);
    },
    function(error) {
        console.log("promise reject : ", error);
    }
)

함수 앞에 async 키워드를 붙여 사용하며 이 함수에서는 무조건 Promise 객체가 반환된다.

Await

그렇다면 Await는 어떤것일까

//await 은 async 함수 안에서만 동작!
//await이 Promise 객체.then() 이 메소드를 좀 더 쉽게 사용할 수 있는 방법
//async의 두번째 기능
//Promise 객체가 일이 끝날 때까지 기다릴 수 있는 공간을 제공

async function f() {

    let promise = new Promise(function(resolve, reject){
        setTimeout(() => resolve("완료"), 3000);
    });
    let result = await promise;
    //promise 객체가 일 다 할 때까지 기다려줌
    console.log(result);
}

f();

await은 asnyc 함수 안에서만 동작한다. promise 객체가 일을 다 할 때까지 기다려준다. 이를 이용해 then 처리를 함수 안에서 한번에 해줄 수 있다.

await을 사용하면서 3개 이상의 promise를 실행하려면 어떻게 해야할끼?

async function f() {

    //promise 객체 한개당 => query 하나
    let promise1 = new Promise(function(resolve, reject){
        setTimeout(() => resolve("첫번째쿼리"), 3000);
    });
    let result1 = await promise1;
    //promise 객체가 일 다 할 때까지 기다려줌
    console.log(result1);

    let promise2 = new Promise(function(resolve, reject){
        setTimeout(() => resolve("두번째 쿼리 with" + result1), 3000);
    });

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

    let promise3 = new Promise(function(resolve, reject){
        setTimeout(() => resolve("세번째 쿼리 with" + result2), 3000);
    });

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

}

f();

Promise 객체를 여러개 생성하고 각각 await로 기다려주면 깔끔하게 해결된다.

Mysql Promise 적용

위에서 학습한데로 쿼리문들을 Promise 객체로 감싸줘도 제대로 작동한다. 하지만 mysql에서는 더 간단한 방법을 제공한다.
mariadb.js 에서 모듈을 가져올때 추가해 주면된다.

const mariadb = require('mysql2/promise');

const connection = async() => {
  const conn = await mariadb.createConnection({
    host: process.env.DB_HOST,
    user: process.env.DB_USER,
    password: process.env.DB_PASSWORD,
    database: process.env.DB_DATABASE,
    dateStrings : true
  });

  return conn;
}

promise 키워드를 추가해주면 작동할 것 같지만 실제로는 잘 작동하지 않는데 npm 에서 제공하는 공식 문서를 보고 방법을 알아보도록 하겠다.

const mariadb = require('mysql2/promise');

const conn = await mariadb.createConnection({
        host: process.env.DB_HOST,
        user: process.env.DB_USER,
        password: process.env.DB_PASSWORD,
        database: process.env.DB_DATABASE,
        dateStrings : true
    })

let [results] = await conn.execute(sql, values);

후기

자바스크립트의 비동기 처리와 이를 데이터베이스에서 적용하는 법에 대해서 알아보았다.

키워드: 프로그래머스 데브코스, 국비지원교육, 코딩부트캠프