[JavaScript]비동기(Asynchronous)

hyemini·2022년 8월 25일

비동기(Asynchronous)란?

위 그림(a)를 보시면..!한 손님의 주문한 커피가 나오고 나서야 다른 손님이 커피를 주문할 수 있습니다! 첫 번째 손님의 커피 주문 완료 시점과 두 번째 손님의 커피 주문 시작 시점이 같습니다! 이렇게 시작 시점과 완료 시점이 같은 상황을 "동기적(synchronous)이다!" 라고 합니다 :) 딱 봐도 효율적이지 못해 보이죵? 그래서 Node.js를 비동기적(asynchronous)으로 작동하는 런타임으로 개발하게 됩니다 🤭


Blocking vs Non-blocking


전화문자
하던 일을 멈추고 받아야 한다 (blocking)확인 후, 나중에 답장할 수 있다 (non-blocking)
요청에 대한 결과가 동시에 일어난다 (synchronous)요청에 대한 결과가 동시에 일어나지 않는다 (asynchronous)

쉽게 예시를 들자면..! Blocking은 전화라고 할 수 있습니다 :) 현재 하고 있던 작업에 대해 Blocking이 일어납니다! 그리고 요청에 대한 응답이 바로바로 이루어집니다 :) Non-blocking은 문자라고 할 수 있습니다! 요청에 대한 결과가 동시에 일어나지 않습니다 (비동기적임)


  • 동기

콘솔창을 보시면..! 동기일 때..매우 비효율적으로 실행되는 것을 볼 수 있습니다!


  • 비동기

비동기는 요청을 blocking 없이 전부 다 받습니다!

요청을 전부 다 받고..! 콜백이 나중에 실행됩니다 :)


  • 비동기의 주요 사례
  1. DOM Element의 이벤트 핸들러
    -마우스, 키보드 입력 (click, keydown 등)
    -페이지 로딩 (DOMContentLoaded 등)
  2. 타이머
    -타이머 API (setTimeout 등)
    -애니메이션 API (requestAnimationFrame)
  3. 서버에 자원 요청 및 응답
    -fetch API
    -AJAX (XHR)

  • 동기와 비동기의 차이!

동기일 때와 비동기일 때 차이가 확연히 보여집니다!

유튜브 동영상 화면이 로딩 걸렸을 때..! 다른 컴포넌트는 조작이 가능하죠? (초록색 애들) 이런 것이 비동기적이라고 합니다 😮


Callback

그래서 순서를 제어하고 싶을 때는 어떻게 하나요??
예시 코드를 볼까요?! (코드 출처는 코드스테이츠!)

const printString = (string) => {
  setTimeout(
    () => {
      console.log(string)
    }, 
    Math.floor(Math.random() * 100) + 1
  )
}

const printAll = () => {
  printString("A")
  printString("B")
  printString("C")
}
printAll() // what do you expect?

이렇게 하면..! 콘솔창에 A/B/C가 순서대로 뜰까요?? No!
순서를 제어하고 싶을 때!!! Callback 함수를 이용합니다 🤭


const printString = (string, callback) => {
  setTimeout(
    () => {
      console.log(string)
      callback()
    }, 
    Math.floor(Math.random() * 100) + 1
  )
}
const printAll = () => {
  printString("A", () => {
    printString("B", () => {
      printString("C", () => {})
    })
  })
}
printAll() // now what do you expect?

위에는 스트링만 받았는데...이번에는 콜백도 받쥬??
A를 실행할 때..! 콜백을 받아서 넘깁니다! 그리고 B로 가고, C로 갑니다!
콘솔창에 출력해 보면..! 콜백으로 인하여...A/B/C가 순서대로 뜨는 걸 확인할 수 있습니다 🤭

즉..!!!! 순서를 제어하고 싶을 때는 Callback을 이용 🤗


Promise

콜백은 참으로..고마운 존재인데..! 함수가 많이 존재할 경우..계속 밀려나게 되어서..! Callback Hell (콜백 지옥)이 발생합니다 ㅠㅠ
(요렇게)

하쥐만..!! Promise를 통해...콜백을 핸들링할 수 있습니다!

const printString = (string) => {
  return new Promise((resolve, reject) => {
    setTimeout(
      () => {
        console.log(string)
        resolve()
      }, 
      Math.floor(Math.random() * 100) + 1
    )
  })
}

const printAll = () => {
  printString("A")
  .then(() => {
      return printString("B")
    })
  .then(() => {
      return printString("C")
    })
}
printAll()

프로미스를 어떻게 사용하냐..!
이번에는 콜백을 인자로 받지 않습니다! 대신..!! 새로운 프로미스 인스턴스를 리턴합니다!

보면 printString("A")에서 콜백을 인자로 받는 것이 아닌..!!
.then으로 이어나갈 수 있습니다! 👍
.then은 printString("A")가 끝나면 return printString("B")를 실행하라는 것입니다 :)

프로미스를 사용하면..! 어디서 에러가 나더라도! .catch()로 마지막에 에러 잡을 수 있습니다 ㅎㅎ


async/await

요즘은 promise 대신에...async/await 얘네도 쓰입니다!

async 함수 표현하고서..! await로 비동기 함수들을 마치 동기적인 프로그램인 것처럼 쓸 수 있습니다 :)

const one = await gotoCodestates()

이렇게 그냥 일반 함수처럼 사용하고 있습니다! 대신 앞에 await를 붙이고..! 표현 자체는 그냥 일반 함수인데...이러면 순서가 제어가 될까요??

콘솔에 찍어보면..!! 순서가 제어됩니다 🤭
심지어...100밀리초를 위에서부터 500밀리초 / 300밀리초 / 200밀리초로 바꿔도! 제어가 됩니다 ㅎㅎ

실제로 돌아가는 건..프로미스와 동일하게 돌아가지만! 표현 자체를 동기적으로 쓸 수 있어서..훨씬 코드 가독성이 높아집니다 :) 😎


✔️ 정리

👏 자바스크립트가 왜 비동기적으로 돌아가야 하는지!
👏 비동기적으로 돌아가는 자바스크릅티를 제어하는 방법은?
👏 콜백보다 쉽고 편하게 비동기 함수들을 처리하는 방법은?
👏 프로미스를 일반 함수처럼 쓸 수 있는 방법은?


Retrospect 🧐

이벤트 루프를 공부했어서 이해하기 훨씬 수월했다! 꺄륵 😄

0개의 댓글