비동기 처리 with 자바스크립트

강종연·2021년 5월 9일
0

Javascript

목록 보기
1/1
post-thumbnail

사실 프론트엔드 쪽을 공부하다보면 여러 키워드가 고정적으로 나온다. 마치 그 단어들이 이 공부의 방향을 결정해주는 듯하게 한다. 오늘은 그 다양한 키워드 중 하나인 비동기 처리에 대해서 알아보고 자바스크립트안에서 어떻게 작동하는지 보고자 한다.

비동기처리란?

이 단어를 이해하기 위해선 동기적인 처리부터 알아야할 것이다.

동기적 처리 란 요청받은 태스크들을 순차적으로 실행되며 현재 작업이 수행중이면 다음 작업은 이 작업이 끝날때 까지 대기하는 방식이다.(직렬적으로 수행)

function f1() {
  console.log("f1");
  f2();
}

function f2() {
  console.log("f2");
  f3();
}

function f3() {
  console.log("f3");
}

f1();
//f1 -> f2 -> f3

이런 방식으로 시행이 되었을 때 한 태스크가 오래걸리면 뒤의 작업들은 계속해서 쌓이게 되고 병목현상(태스크가 적체되는 현상)이 발생하기 쉽다. 이 단점을 보완하고자 나온 개념이 비동기처리이다.

비동기 처리란 현재 진행중인 태스트가 끝난 상태가 아니라도 대기하지않고 다음 작업을 실행하는 방식이다.(병렬적으로 수행)

function f1() {
  console.log("f1");
  f2();
}

function f2() {
  setTimeout(function () {
    console.log("f2");
  }, 0);

  f3();
}

function f3() {
  console.log("f3");
}

f1();
//f1 -> f3 -> f2

함수가 실행이 되면 Call Stack이란 곳에 차곡차곡 쌓이고 완료가 되면 차례대로 pop된다.

위의 코드를 설명하면 f1이 Call Stack에 쌓이고 f2가 Call Stack에 쌓인다. f2안에서 setTimeout(콜백함수, 비동기처리 함수)이 호출되면 지정된 시간만큼 기다리다가 Event Queue란 곳으로 넘어간다. 그리고 Call Stack이 비어졌을 때 Call Stack으로 이동되어 실행된다.

서버에서 데이터를 가져올 일이 많은 웹 프로젝트에서 한번의 서버요청이 오래걸린다면 뒤의 작업들은 작업중단이 되니 이 얼마나 어이없는 일인가!

자바스크립트에서 비동기 처리 방식

JS에서는 이 비동기처리를 위한 방식이 여러가지가 있지만 최근에 가장 많이 언급이 되는 Promiseasync & await에 대해서 설명을 하겠다.

Promise

Promise는 비동기 처리를 위해 콜백 함수의 단점을 보완한 ES6에 도입된 기능이다.
Promise는 resolve와 reject function을 파라미터로 같은 excutor 라는 함수를 받는다. 이 함수는 작업의 성공 및 실패 유무에 따라서 다른 처리를 해준다.

Promise는 생성되고 종료될 때 까지

  • Pending: 성공 및 실패 전의 초기상태
  • Fulfilled: 작업이 성공했을 때 상태
  • Rejected: 작업이 실패하거나 오류상태

위의 3가지 상태로 구성되어 있다.

상태에 따라 excutor함수에서 파라미터로 받은 resolve함수는 성공했을 때 (Fulfilled), reject함수는 실패했을 때 (Rejected) 호출이 된다.

//new Promise => Pending 상태
const promiseEx = new Promise((resolve, reject) => {
  setTimeout(() => {
    //성공했을 때
    resolve(101);

    //실패했을 때
    reject("error");
  }, 1000);
});

//성공했을 경우 101, 실패했을 경우 error
promiseEx.then((res) => console.log(res)).catch((err) => console.log(err));

위와 같이 new Promise로 생성된 인스턴스 객체(promiseEx)는 호출 시 then(성공)과 catch(실패) 메서드를 주로 쓴다.

async & await

async, await은 가장 최근에 나온 Promise를 기반으로 한 비동기 처리 문법으로 콜백 함수와 Promise의 단점을 보완하고자 나왔다.
단, async, await은 Promise를 대체하는 것이 아니라 Promise를 사용하지만 then, catch 메서드를 쓰지 않고 더욱 동기스럽게 표현한다.

특징:

  • await은 async가 붙은 함수 안에서만 사용이 가능하다.
  • async가 붙은 함수는 항상 성공한 Promise(Resolved Promise)를 반환한다.
  • await은 new Promise로 생성된 인스턴스 객체 앞에 붙어 Promise가 시행될 때까지 대기한다.
    (Promise가 시행되길 기다리는 동안에도 다른 작업을 할 수 있기에 비동기 처리가 가능하다)
async function f1() {
  try {
    //response 와 user에서 각각의 promise가 시행될 때까지 대기.
    const response = await fetch("http://abcd.com");
    const user = await response.json();
  } catch (e) {
    //에러처리는 try, catch문을 통해 잡음
    console.log(e);
  }
}

f1();

이로써 then과 catch를 쓰는 것 보다는 훨씬 동기적인 행위 처럼 보이면서 직관적으로 수행상태를 판단할 수 있다.

글을 마무리 하며

JS 및 React를 공부하면서 비동기 처리를 왜 해야하는지 정확하게 어떻게 해야하는지를 제대로 잡지 않고 넘어갔었다. 이제야 어떤 부분에서 비동기 처리를 해야하고 어떻게 써야하는지 감이 잡히기 시작했다.

이 비동기 처리도 무조건 한다고 좋아할 것이 아니라 적체현상이 벌어지지 않도록 하기 위한 용도에만 사용하도록 하자.

profile
TypeScript, Next.js를 좋아하는 프론트엔드 개발자입니다:)

0개의 댓글