TIL [JS / Node] 비동기

13030 단어 비동기비동기



비동기적 실행

위의 두 사진은 네이버의 화면 한 부분을 캡쳐한 것이다. '오늘 읽을만한 글'이라는 주제에는 여러가지의 태그가 있다. 여기서 한 태그를 선택했을 때, '오늘 읽을만한 글'이라는 주제를 벗어난 곳까지 모두 로딩이 된다고 하면 어떤 점이 이득이라고 할 수 있을까? 아마 어떤 점도 이득이라고 생각이 들지 않을 것이다. 더 오랜 시간이 걸릴 것이기 때문이다. 이렇게 컴포넌트 단위로 웹 페이지가 동작하게 하는 것을 비동기적 실행이라고 한다.
여러개의 동작을 수행할 때 어떤 동작을 마친 시점이 다른 동작이 시작되는 시점이 되는 것을 동기적 실행이라고 한다. 즉 비동기적 실행이라는 말은 여러 개의 동작이 동시다발적으로 수행이 된다는 것이다.

Callback

그런데 만약 3개의 동작을 순서대로 실행을 시키고 싶은데 비동기적으로 실행이 된다면 그 순서를 원하는대로 조정할 수가 있을까? 이렇게 순서를 제어하고 싶은 경우에 Callback 함수를 사용할 수가 있다.

const 비동기 = () => {
  동작(1);
  동작(2);
  동작(3);
}

const 비동기 = () => {
  동작(1, () => {
  	동작(2, () => {
      		동작(3, () => {})
    	})
  })
}

첫 번째 코드를 비동기적으로 수행했을 때, 동작 1을 먼저 수행시키고 싶다하더라도 2나 3의 수행시간이 짧다면 짧은 동작이 먼저 수행이 될 것이다.
하지만 두 번째 코드처럼 콜백함수를 지정하여 다음에 실행될 함수를 제어해준다면 순서를 원하는대로 조정할 수가 있다. 그런데 여기서 제어해야하는 동작의 순서가 50개, 100개로 늘어난다고 해보자. 아무리 들여쓰기가 잘 된 코드라 하지만 가독성이 좋다고 느껴질까? 아니다. 이 때문에 등장한 방식이 Promise이다.

Promise

Promise는 일종의 클래스라고 생각하면 쉽다. Promise 안에는 동작을 다룰 수 있는 resolve, reject 메서드가 존재하고 이를 통해 위의 Callback 함수를 사용한 비동기에서의 Callback hell에서 벗어난 코딩을 할 수가 있다.

const 동작 = (param) => {
  return new Promise((resolve, reject) => {
    // 이것저것 동작
    resolve();
  }
}
                     
const 비동기 = () => {
    동작(1)
    .then((res) => {
      return 동작(2)
    })
    .then((res2) => {
      return 동작(3)
    })
  }

이렇게 어떤 동작을 Promise로 리턴을 받아주고 여러 동작들을 순차적으로 시행하면 Promise를 리턴하는 동작(1)을 .then의 인자로 받아서 함수를 이어갈 수 있다. 이렇게 리턴을 해주며 Promise를 이어가는 구조를 Promise Chaining이라고 하며 가독성을 높이기 위해 Chain을 잘 구성하는 것이 좋다. 만약 return 없이 코드를 이어간다면 Promise를 쓰더라도 Callback과 마찬가지로 가독성을 망치는 Promise hell 현상이 나타날 것이다.

Async await

ES7에 나타난 문법 중 하나로 async await 라는 것이 있다. 이것은 사실 Promise와 거의 동일한데 한번 살펴보자.

function 동작1() {
  return new Promise((resolve, reject) => {
    이것저것(() => { resolve()}
  })
}
                     
function 동작2() {
  return new Promise((resolve, reject) => {
    이것저것(() => { resolve()}
  })
}
                     
function 동작3() {
  return new Promise((resolve, reject) => {
    이것저것(() => { resolve()}
  })
}
                     
const 비동기 = async () => {
    const= await 동작1();
    무언가 동작();
    
    const= await 동작2();
    무언가 동작();
    
    const= await 동작3();
    무언가 동작();
  }

여기서는 함수를 정의하여 Promise를 리턴하는 것까지는 동일하지만, async라는 키워드를 통해 인자를 받아주어야 하고 일반 함수처럼 사용하지만 await라는 키워드를 함께 사용하여야 한다. 이렇게 하면 순서대로 동작을 제어할 수가 있다.

비동기 요청의 대표적인 사례로는 네트워크 요청이 있고 네트워크를 통해 이루어지는 요청은 형태가 다양한데 그중 URL로 요청하는 경우가 가장 흔하다. URL로 요청하게 해주는 API가 fetch API이다.

좋은 웹페이지 즐겨찾기