[node.js] async JS

Ian·2020년 8월 10일
0

Server side

목록 보기
1/1

1. sync, async

  • sync : 동기처리, 요청(request)를 받고 그 받은 응답을 처리하기 전까지 다른 것을 실행할 수 없다

  • async : 비동기처리, 요청을 받고 그 요청을 처리하는 과정 도중에도 다른 요청들을 받을 수 있다

  • async 의 대표적인 예시로 유튜브가 있다, 유튜브에서 우리가 어떤 영상을 누르고 난 뒤에 영상을 로딩하는 도중에도 다른 작업들을 할 수 있는 것은 async style 로 유튜브를 구현했기 때문이다.

  • 만약 sync style 로 유튜브를 구현했다면 우리는 영상 로딩이 완료되기 전까지는 아무 것도 할 수가 없을 것이다.

  • async 를 사용하는 이유? :
    언제 요청에 대한 응답을 줄 지 모르는데 마냥 기다릴 수만은 없는 상황에서 응답이 오기 전까지 다른 일들을 진행하기 위해서이다.

  • 굳이 일상생활 속에서 예시를 들자면, 면접의 합격/불합격 결과가 나오기 전까지 아무 것도 하지 않는 것이 동기적인 삶이고, 면접의 합격/불합격 결과가 나오기 전까지도 내가 할 수 있는 일을 하는 것이 비동기적인 삶이라고 하면 될까?

2. async handling

2-1. why we need to handling async?

async style 로 짜기 위해선 순서의 제어가 필요하다. 비동기적으로 들어오는 요청들이라고 해서 무작위하게 다 받아버리면 소위 말해 일이 꼬인다. 그 일들에도 엄연히 순서가 있는 것이다.
그러나, 이 '순서가 있어야 한다' 라는 말을 프로그래밍으로만 놓고 보면 잘 납득이 가지 않았다. 그래서 곰곰히 생각해 본 끝에 우리의 일상 속에서 동기, 무작위한 비동기, 그리고 어느정도 순서를 지킨 비동기의 예시를 들어보려고 한다.

일상 속 예시는 우리가 좋아하는 힐링이다.

오늘 하루가 너무 힘든 나머지 나는 힐링을 하기로 했다. 샤워를 마친 다음, 전기포트에 뜨거운 물을 팔팔 끓여 야식으로 컵라면을 먹으려고 한다. 넷플릭스에 볼 만한 게 뭐가 있는지 한 번 훑어보고, 괜찮은 게 있으면 그걸 정주행 할 예정이다.

이를 동기적으로 실행한다면 :

샤워를 한다 → 전기포트에 물을 올려 끓인다 → 물이 다 끓으면 라면에 부어 3분동안 기다린다 → 라면을 다 먹고 넷플릭스를 본다

라는 순서로 실행할 수 있을 것이다. 그렇지만 우리는 조금 더 효율적으로 힐링을 하고 싶을 것이다.

샤워를 하러 들어가기 전, 전기포트에 먼저 물을 올려 놓는다 → 샤워를 한다 → 샤워를 마치고 나와서 라면에 물을 붓는다 → 라면이 익을 때까지 넷플릭스를 슥 훑어보면서 뭐가 재밌는지 본다 → 라면이 다 익으면 일단 먹으면서 넷플릭스에 볼 만한 게 있는지 찾아보다가, 볼 만한 걸 찾으면 정주행을 시작한다

아주 1분 1초도 허투루 쓰지 않는 체계적인 힐링이다. 비동기적(다른 일을 하는 도중 요청을 받아 실행하고 있기 때문에)이면서도, 일련의 순서가 존재한다. 프로그래밍으로 보면 잘 제어된 비동기적 흐름이라고 할 수 있겠다.

그러나, 비동기를 체계적으로 고려하지 않고 실행해버린다면 조금 더 비효율적인 상황이 벌어질 수도 있다. 나름 현실적이면서도 충분히 벌어질 법한 최악의 상황을 고려해 볼까?

샤워를 하기 전, 넷플릭스를 훑어보면서 전기포트에 물을 올린다 → 넷플릭스를 아무리 찾아봐도 재밌는 게 나오질 않아 계속해서 보다보니 벌써 시간이 40분이 지났다 → 이미 포트에 올린 물은 팔팔 끓었다가 식어버린 상황이다 → 시간이 지나서 촉박해진 마음에 바로 씻으러 들어간다 → 나와보니 물은 더 차갑게 식어있었다, 라면에 물을 다시 올리는 걸 까먹었던 것이다 → 라면에 물을 올리고 또 넷플릭스를 찾아본다 → 이번엔 놓치지 않고 물이 끓었을 때 잽싸게 라면에 물을 붓는다 → 라면에 물을 붓고 기다리던 도중 재밌는 게 나와서 조금만 보려고 했더니 벌써 1시간이 지나가 버렸다, '아 맞다...' 하고 라면을 보지만, 라면은 불어터져 있었다

비동기 처리를 중점으로 하여, 프로그래밍의 관점에서 짚어보자.

일단은 넷플릭스를 찾아보면서 물이 식어버린 상황부터 시작이다. 넷플릭스에서 재미있는 게 언제 나올지도 모르는데 주구장창 찾고 있던 것인가?
요청에 대한 응답이 언제 올지도 모르는 상황에서는 다른 할 수 있는 일을 하면서 응답을 기다리는 것이 더욱 효율적인데, 그러지 못 했다.

또 라면이 다 익을 때까지 잠깐 보다가 라면을 먹으면서 넷플릭스를 보든가, 라면을 다 먹고 넷플릭스를 보든가 해도 되는 상황에서 넷플릭스를 보다가 라면이 결국 팅팅 불어버렸다.
비슷하게 요청(넷플릭스 시청 시작)에 대한 응답(넷플릭스 시청 끝)이 상당히 늦게 오게 될 상황에서 요청을 걸어놓고 응답이 올 때까지 주구장창 보다가 그만 힐링의 소중한 요소 중 하나인 야식을 잃어버린 상황을 초래했다.

무시무시한 예시(?)를 보면서 느끼는 것처럼, 비동기의 순서 처리(async handling)은 이리도 중요하다.

2-2. then, how we can handle this?

async 를 제어하는 방법은 별도로 존재하며, 이를 알아야 한다. 왜냐면, 선언된 순서에 따라 코드가 실행되는 것을 보장할 수 없기 때문 이다.

function getUp() {
  setTimeout(() => {
    console.log('get up')}, 10)
}

function shower() {
   setTimeout(() => {
    console.log('take a shower')}, 30)
}

function haveBreakfast() {
  setTimeout(() => {
    console.log('have a breakfast')}, 5)
}

function dailyRoutine() {
  getUp();
  shower();
  haveBreakfast();
}

dailyRoutine();

우리의 일상생활을 setTimeout 을 통해 옮겨놓은 코드다.

대략 console 에 찍히는 것이 상황이고, 옆에 있는 integer 가 소요되는 시간이라고 생각해보자. 예상대로라면, 코드라인 순서대로 get up → shower → have a meal 가 콘솔에 쫘르륵 찍혀야 될텐데, 그렇지 않다.

have a breakfast
get up
take a shower

그렇다. 모든 request 를 일단은 전부 받아버리고, delay 가 적은 순서대로 실행을 해버린다. 우리는 10ms 뒤에 get up 이, 30ms 뒤에 take shower 가, 그리고 5ms 뒤에 have a breakfast 가 console 에 찍히길 바랬는데, 우리가 바란 것과는 너무나도 다른 결과가 나온다.

그렇기 때문에 효율적인 async 작업들의 순서를 고려하기 이전, 일단은 async handling 을 어떻게 해야할까 부터 알아야 한다. JS 에서 존재하는 대표적인 방법은 세 가지다.

  • callback
  • Promise
  • async / await

(다음편에 계속)


오늘의 공부일지 후기 : 평일에 쓰는 건 공부한 것만 간단하게 작성하고, 주말에 진득하게 해당 과정들을 통복습한다는 느낌으로 엮어내서 작성해야겠다. 서론이 너무 길었던 거 같다.

profile
правда и красота, truth and beauty

0개의 댓글