Async Await

0_CyberLover_0·2022년 4월 6일
0

Node.JS # 03

목록 보기
7/19

callback의 장점은 에러들을 바로 볼수 있다는거다.

추가적인 코드 없이 에러들을 바로 불러 올수 있다. 바로 이렇게 해볼 수 있다.

export const home = (req, res) => {
  console.log("Start");
  Video.find({}, (error, videos) => {
    if (error) {
      return res.render("server-error");
    }
    return res.render("home", { pageTitle: "Home", videos: [] });
  });
  console.log("I finish first");
};
if (error){
   return res.render("server-error");
    }

이렇게 해줄수가 있다. 하지만 callback을 좋아하지 않는 이유는

function안에 function을 작성하는 걸 싫어 하기 때문이다.

뭔가 세련된 코드 처럼 안 느껴진다. (필자는 아직 왜 그런지 이유는 잘 모르겠다.)

그래서 promise를 사용할 거다. promisecallback의 최신 버전이라고 생각하면 된다.

promise를 사용하면 장황한 코드를 쓸 필요가 없다.

import Video from "../models/Video";
Video.find({}, (error, videos) => {});

export const home = (req, res) => {
  return res.render("home", { pageTitle: "Home", videos: [] });
};
Video.find({}, (error, videos) => {});

callback 과 비교 할수 있도록 이 코드는 남겨둘거다. 저 부분이 callback의 코드이다.

그리고 promise는 이렇게 생겼다.

import Video from "../models/Video";

// Video.find({}, (error, videos) => {});

export const home = async (req, res) => {
  console.log("I Start");
  const videos = await Video.find({});
  console.log("I finish");
  console.log(videos);
  return res.render("home", { pageTitle: "Home", videos: [] });
};

결과를 확인하기 위해 console.log()을 중간 중간에 넣어 주었다. 어떤 차이가 있는지 보여줘야 해서

// Video.find({}, (error, videos) => {});

주석 처리 하였다.

현재는 awitasync에 대해 몰라도 상관없다. callback과의 차이를 이해하는 것이 중요하다.

서버를 재시작하고 새로고침을 하고 터미널을 확인해 보면

I Start
I finish
[]
GET / 304 184.973 ms - -

보다시피 모든 코드가 순서대로 실행되고 있다.

I Start가 출력되고, 비디오를 찾고, I Finish 그리고 array를 출력한다.

저 과정이 끝나면 render가 실행된다.

callback과의 차이점은 awaitfind 앞에 적으면 findcallback을 필요로 하지 않는다는걸 안다.

그렇기에 find는 찾아낸 비디오를 바로 출력해 주는거다. find operation의 결과 값으로 말이다.

callback과 느낌이 조금 다르다.

에러를 출력하기 위해서는 try catch문을 사용해야 한다.

export const home = async (req, res) => {
  try{
  console.log("Start");
  const videos = await Video.find({});
  console.log("finish");
  console.log(videos);
  return res.render("home", { pageTitle: "Home", videos: [] });
  } catch{
    return res.reder("server-error")
  }
};

말 그대로 무엇인가를 try하고 에러가 있다면 그 에러들을 catch 하게 해준다.

그 다음 res.render를 통해 오류들을 출력 해준다.

단순한 예시이다.

만약 이걸 javascript 방식으로 사용한다면 이렇게 적어야 한다.

Video.find({}, (error, videos) => {
  if(error){
    return res.reder("server-error")
  }
  return res.render("home", { pageTitle: "Home", videos: [] });
});

이렇게 적는 건 코드를 비교하기 위함이다. 만약 callback 방식으로 하게 되면 이렇게 해야 한다.

export const home = async (req, res) => {
  try {
    const videos = await Video.find({});
    return res.render("home", { pageTitle: "Home", videos: [] });
  } catch {
    return res.reder("server-error");
  }
};

이건 promise 방식이다. promisetrycatch를 사용한다는 건 알겠는데

await는 왜 사용 할까? awaitdatabase를 기다려 준다.

이전 파트에서 이런 코드를 본적이 있을 것이다.

console.log("Start")
Video.find({}, (error, videos) => {
  if(error){
    return res.reder("server-error")
  }
  return res.render("home", { pageTitle: "Home", videos: [] });
});
console.log("Finished")

여기서 Start, finished 그 다음에 videos를 출력했다.

왜냐하면 javascript는 기다리는 기능이 원래 없었다.

그저 위에서 아래로 순서대로 코드를 읽어냈었다.

하지만 작업별로 실행되는 시간이 달라 순서가 다르게 나왔고 그래서 callback이란 해결책을 썼다.

callback 어떤 동작이 끝나면 특정 function을 부르도록 만들어졌다.

왜냐하면 javascript는 기다리는 기능이 없기 때문이다.

그저 위에서 아래로 순서대로 코드를 읽는다.

하지만 이 모든건 await가 쓰이면서 달라졌다.

await만 있다면 javascript는 계속 기다려준다. database에게 결과값을 받을 때까지이다.

그리고 asyncawaitcallback보다 최신 기술이다.

asyncawait의 최대 장점은 직관적이라는 거다.

왜냐하면 javascript가 어디서 어떻게 기다리는지 바로 알 수 있기 때문이다.

callback 에서는 Start, Finished 다음에 videos를 출력해준다.

하지만 promise의 경우에는 순서대로 위에서 아래로 코드가 실행 된다.

이 작은 차이가 엄청 큰거다. 왜냐하면 이렇게 하면 코드를 읽을때 정말 이해하기가 편하다.

코드를 읽다가 awit를 보면 바로 이 생각을 하면 된다.

javascript가 무엇인가를 기다리고 있다.

코딩 규칙상 awaitfunction안에서만 사용이 가능하다.

해당 functionasynchronous(비동기)일 때만 가능하다.

그렇기에 async를 적어주는 거다. 규칙이다.

오류들을 다뤄 보도록 하자

callback의 경우 어디 무엇이 오는지 모든 건 명확한데 promise는 아직 명확하지 않다.

두가지 옵션이 있다. 첫번째는 try를 사용하는 것인데 이 방법은 res.render를 실행하다

    const videos = await Video.find({});
    return res.render("home", { pageTitle: "Home", videos: [] });

에러 발생 시, 이 코드로 넘어가서 실행시키는 거다.

    return res.reder("server-error");

에러를 인식하는 것이 catch의 기능이다.

다시 한번 짚고 넘어 가자면 예를 들어 database가 꺼졌거나, 연결이 끊겼거나, 사람이 포화 상태거나,

어떤 에러가 발생하든 javascriptawait 내 출력 값을 출력 안 하고 아래 에러 출력 코드를 실행 시키는 거다.

이것이 가능 한 것도 await가 있기 때문이다.

계속 말하지만 이 operationawait가 있는 코드에 오류가 있다면

await가 있는 코드는 출력 되지 않는다. 바로 에러 출력 코드가 발생 할 거다.

참고로 에러 메세지는 이 코드를 통해 받을 수 있다.

export const home = async (req, res) => {
  try {
    const videos = await Video.find({});
    return res.render("home", { pageTitle: "Home", videos: [] });
  } catch (error) {
    return res.reder("server-error", { error });
  }
};

그리고 필요하다면 오류 메세지를 추가 해줄수도 있다.

하지만 지금은 그렇게 하지 않을 거다. 일단 에러에 대해서는 여기까지만 다루도록 한다.

export const home = async (req, res) => {
  const videos = await Video.find({});
  return res.render("home", { pageTitle: "Home", videos: [] });
};

이렇게 만 작성을 해준다. promise가 확실히 callback보다 훨씬 보기에도 더 좋다.

profile
꿈꾸는 개발자

0개의 댓글