비동기 / node.js

왕지호·2022년 11월 23일
0

오늘은 비동기 호출과 node.js를 알아보자!

비동기의 경우 콜백 함수가 중요하다! 콜백을 잠깐 복습해보자.

비동기 호출

  • 다른 함수(A)의 전달인자(argument)로 넘겨주는 함수(B)
  • parameter를 넘겨받는 함수(A)는 callback 함수(B)를 필요에 따라 즉시 실행(synchronously)할 수 있고, 아니면 나중에 (asynchronously) 실행할 수 있다
function B(){
  console.log("called at the back!");
}
function A(callback) {
	callback(); //callback === B
}
A(B);

호출 할 때는 Bloking, Non-Blocking이 있다.
그렇다면 그 둘의 차이는 무엇일까?

커피 주문으로 예를 들어보자.
만약 커피 주문을 하는데 커피 주문 시스템이 동기적으로 되면 어떻게 될까?


이런식으로 주문 시스템이 작동될 것이다.
이런 시스템의 단점은 무엇일까?
4번을 보면 손님 2는 손님 1이 아메리카노를 전달받을 때까지 주문도 하지 못하고 대기열에 머물러 있어야 할 것이다.

그렇다면 이 경우를 어떻게 효율적이게 만들어야 할까?

바로 비동기적으로 주문을 받으면 된다!

여기서 손님 1의 주문과 손님 2의 주문을 비동기적으로 처리하면 된다!
비동기적으로 만들면 손님 1의 요청과 손님 2의 요청과 응답을 blocking 하지 않는다.

위의 사진처럼 callback을 사용하면 된다.

그럼 여기서 동기적으로 주문을 받은 경우와 비동기적으로 받은 주문의 코드를 비교해보자!

동기적

비동기 함수

그럼 비동기의 주요 사례는 무엇이 있을까?
DOM Element의 이벤트 핸들러

  • 마우스, 키보드 입력(click, keydown 등)
  • 페이지 로딩 (DOMContentLoaded 등)

타이머

  • 타이머 API (setTimeout 등)
  • 애니메이션 API (requestAnimationFrame)

서버의 지원 요쳥 및 응답

  • fetch API
  • AJAX (XHR)

이제 비동기를 자바스크립트에서 어떻게 사용하는지 알아보자!

비동기를 자바스크립트에서 사용하는 방법은 대표적으로 4가지 방법이 있다

1. Why Async
2. Callback
3. Promise
4. async await

일단, 동기적으로 작동하는 경우 클라이언트에서 요청이 오면 서버에서 처리를 하고 그동안 클라이언트는 reponse가 올 때까지 기다리게 된다. 그 다음 서버에서 다 처리가 되면 그제서야 클라이언트가 다시 실행된다.

비동기적의 경우 동기적인 경우와 다르게 클라이엔트에서 요청을 하면 서버에서 그 요청을 처리하는 시간에 남은 일을 계속 하고 그 와중에 서버에서 다 처리가 되어서 요청이 돌아오는 경우에도 클라이언트에서 그 요청을 가지고 일을 한다.

아래의 이미지들을 참고하자!


그렇다면 javascript는 자동적으로 비동기적으로 처리가 될까?
아니다. 바로 Node.js를 사용해야 한다!
javascipt는 single thread인 반면, Node.js는 비동기적으로 작동되고 thread 없이 디자인되었다.

그럼... 다시 돌아가서 4가지 대표적인 방법에 집중해보자!


1. why Async?

  • Async가 좋은 것은 알겠는데 만약 비동기적인 환경에서 순서를 제어하고 싶을때는 어떻게 할까?

예를 들어서 Math.random으로 랜덤하게 순서가 노출된다고 가정해보자. 이 경우를 어떻게 순서대로 노출시킬 수 있을까?

  • 바로 callback 함수를 사용하면 된다!

    콜백을 사용하면 위의 이미지처럼 순서대로 나온다. settimeout의 콜백을 실행해주기 때문이다.

흠... 그런 쉬운 방법이! 그럼 콜백을 계속 사용하면 되겠다!
... 애석하게도 콜백을 계속 사용하게 되면 코드가 복잡해지고 수정하기 힘든 콜백지옥이 일어난다.

  • 이런식으로 코드를 작성하게 되면 나중에 코드를 수정할 때 관리하기 어렵다.

흠... 그렇다면 콜백 지옥을 피하려면 어떻게해야할까?
바로... Promise를 사용하면 된다!

2. Promise

프로미스를 사용하려면 2가지가 필요하다.
next action으로 가게 해주는 resolve(),
error를 핸들하는 reject()를 사용해야 한다.

아래의 이미지처럼 사용하면 된다.

만약 프로미스 chain의 callback을 deal 하고싶을 때는 then과 catch를 사용해야 한다.

Promise.prototype.then은 메서드 체이닝이 가능하다. Promise.prototype.then은 사실 다음과 같이 두 개의 콜백 함수를 받을 수 있다.

Promise.prototype.then(onFulfilled, onRejected)

두번째 파라미터에는 에러가 났을 경우의 콜백 함수를 적어주면 Promise.prototype.catch와 같은 역할을 할 수 있다.

Promise.prototype.catch의 경우 Promise.prototype.then을 사용하다가 맨 마지막에 catch 를 사용해서 오류를 핸들시킨다.

흠.. 그럼 계속 then이랑 catch를 사용해야 할까?
아니다! async 와 await를 사용해도 동일하게 작동된다.

async는 는 자동으로 promise 같이 만들어준다.
await는 처리가 끝날때까지 기다려준다. 그렇기 때문에 시간을 다르게 설정하면 시간이 누적되어서 늦게 처리가 된다.

주의할 점이 있다!
node 버전이 낮을 경우 사용하지 못한다. 그리고 await을 사용하려면 async를 무조건 같이 사용해야 한다.


마지막으로 유용한 promise API 2개를 더 알아보자!

1. all API

  • promise가 여러개 있다고 하면 모든 promise들을 병렬적으로 모아준다.

2. race API

  • promise 중에서 가장 먼저 수행되는 것을 전달한다.
profile
개발 공부하는 코린이!

0개의 댓글