TIL028 | 자바스크립트 비동기

김태규·2021년 9월 12일
1
post-thumbnail

1. 동기와 비동기

  • 동기(synchronous) 란 코드가 순차적으로 실행되는 것을 의미하고, 어떤 코드의 연산이 진행 중이라면 다음 작업은 대기하게 된다.
console.log(1);
console.log(2);
console.log(3);   // 콘솔창에 순차적으로 1,2,3 이 출력된다.
  • 비동기(asynchronous) 란 특정 코드의 연산이 끝날 때까지 코드의 실행을 멈추지 않고 다음 코드를 먼저 실행하는 것을 의미한다.
console.log('Hello');        // #1

setTimeout(function() {
	console.log('Bye');  // #2
}, 3000);

console.log('Hello Again');  // #3
  • setTimeout은 web API로 특정 시간이 지난 후에 콜백함수를 실행시킨다.

  • 비동기 처리에 대한 이해가 없는 상태에서 위 코드를 보면 #1, #2, #3 의 순서로 출력할 거라고 생각되지만, setTimeout()은 비동기적으로 실행되기 때문에 setTimeout()을 실행하고 나서 바로 다음 코드인 console.log('Hello Again')으로 넘어가게 된다. 따라서, ‘Hello’, ‘Hello Again’를 먼저 출력하고 3초가 지나면 ‘Bye’가 출력된다. 결국 #1, #3, #2의 순서로 출력된다.

  • ‘Hello’ 출력
    ‘Hello Again’ 출력
    3초 있다가 ‘Bye’ 출력


2. Callback

콜백 함수란 다른 함수의 인자로 이용되는 함수이며 어떤 이벤트에 의해 호출되는 함수이다. 콜백 함수를 사용하면 특정 로직이 끝났을 때 원하는 동작을 실행시킬 수 있다.

function printWithDelay(callback, sec){
  setTimeout(callback, sec*1000)
}
printWithDelay(()=>console.log("async callback"), 2)
console.log("hello")

"hello"가 먼저 출력이 되고 2초 뒤에 "async callback"이 출력이 된다.

하지만 이러한 콜백 함수를 비동기적으로 연속적으로 사용하다보면 콜백 지옥이라는 문제점이 발생하게 된다.


3. Promise

Promise 는 자바스크립트에서 제공하는 비동기를 간편하게 처리할 수 있도록 도와주는 객체이다. Promise 는 정해진 기능을 수행한 후에 기능이 성공적으로 수행되었다면 성공했다는 메세지와 함께 결과값을 전달해주고, 기능을 수행하지 못 했을 경우에는 에러 메세지를 전달해준다.

const myPromise = new Promise((resolve, reject)=>{
  console.log("doning some heavy work: network, read files")
  setTimeout(()=>{
    resolve('김코딩');
  }, 2000);
})
  • Promise 는 클래스이기 때문에 new 라는 키워드를 사용하여 객체를 생성할 수 있다.
  • 두가지 콜백 함수를 인자로 받는데, 기능을 정상적으로 수행했을 때 데이터를 전달해주는 resolve 콜백 함수와 기능 수행 중에 문제가 생겼을 때 불러올 reject 콜백 함수가 있다.
  • Promise 는 만들어지는 순간 내부의 코드가 실행된다.
  • 위의 코드가 정상적으로 수행되면 '김코딩' 이라는 데이터를 2초 후에 전달하게 된다.

Promise 를 만든 후에 사용하고 싶다면 then, catch, finally 등과 함께 사용할 수 있다.

myPromise.then(value=>{
  console.log(value) // resolve 가 있다면 '김코딩' 출력 
})
.catch(error=>{
  console.log(error) // reject에 있는 'this is error msg' 출력
})
.finally(()=>{
  console.log('finally!!')
})
  • then 은 Promise 가 정상적으로 수행되었을 때 value 로 resolve 콜백 함수에서 전달된 데이터가 들어오게 된다.
  • catch 는 Promise 가 수행 중에 문제가 생겼을 때 reject 콜백 함수에서 전달된 에러가 들어오게 된다.
  • finally 는 Promise 의 성공/실패 여부와 상관없이 무조건 호출되기 때문에 마지막에 특정 기능을 수행하고 싶을 때 사용한다.

4. async/await

async/await 는 비동기를 동기식으로 코드를 순서대로 작성하는 것처럼 간편하게 작성할 수 있도록 도와준다. async/await 는 새로운 문법이 아니고, 기존에 존재하던 문법(Promise) 에 사용자가 조금 더 편하게 사용할 수 있도록 API를 제공해준다. 이렇게 문법적인 기능은 그대로 유지하되, 코드를 작성하는 사람 입장에서 혹은 그 코드를 다시 읽는 사람의 입장에서 편의성이 높은 프로그래밍 문법을 Syntactic Sugar 라고 부른다.

promise를 사용할 경우에 callback처럼 chaining이 일어나는 것은 마찬가지이다. 따라서 콜백 지옥의 문제가 어느정도 나타날 수 있다는 것이다. 하지만 async await을 사용하면 promise를 '깔끔한 스타일'로 작성할 수 있다. 그러나 무조건 async/await이 절대적으로 좋은 방법은 아니고 상황에 따라 적절한 것을 선택하면 된다.

function goWork(time1, timeStartWork) {   // Promise
  return wakeUp(time1)
    .then(time2 => tackSubway(time2))
    .then(time3 => takeOffSubway(time3))
    .then(time4 => arriveWork(time4))
    .then(arrivalTime => {
      if (arrivalTime > timeStartWork) {
        fire()
      }
    })
}


async function goWork(time1, timeStartWork) {  // async/await
  const time2 = await wakeUp(time1)
  const time3 = await takeSubway(time2)
  const time4 = await takeOffSubway(time3)
  const arrivalTime = await arriveWork(time4)
  if (arrivalTime > timeStartWork) {
    fire()
  }
}
  • async/await 을 사용하려면 우선 사용할 함수 앞에 async라는 키워드를 붙여 사용해야 하며 선언된 async 함수 안에서만 await 키워드를 사용할 수 있다.
  • 주의할 점이 있다면 await 뒷부분이 반드시 promise 를 반환해야 한다는 것과 async function 자체도 promise 를 반환한다는 것이다.
  • async/await 을 사용할 때는 예외처리를 try-catch 로 한다.

references

https://www.youtube.com/watch?v=s1vpVCrT8f4&ab_channel=%EB%93%9C%EB%A6%BC%EC%BD%94%EB%94%A9by%EC%97%98%EB%A6%AC
https://joshua1988.github.io/web-development/javascript/promise-for-beginners/
https://velog.io/@open_h/javascriptasync#async-await
https://velog.io/@jhyunk218/%EB%B9%84%EB%8F%99%EA%B8%B0
https://blueshw.github.io/2018/02/27/async-await/

0개의 댓글