본문 바로가기
개발 공부/React, React Redux

비동기 처리 (async, await)

by 느림보어른 2021. 6. 17.

문제

내가 Drello의 Board page를 설계하면서 겪었던 문제 중 하나는 바로 Board page에 접속하면 전에 생성된 Board가 뜨지 않았다.

원인

Python을 주로 사용한 내가 Drello의 Frontend를 React로 설계하면서 JavaScript를 본격적으로 사용하게 되었다. 그중 나를 가장 애먹게 만든 개념이 바로 비동기, 동기 처리이다. Python은 코드가 짜진 순으로, 즉 위에서부터 아래로 순차적으로 실행된다. 큰 데이터를 처리하는 등 실행시간이 오래 걸리는 코드가 있더라도 그 뒤에 있는 코드가 먼저 실행되는 일이 없다. 그래서 나는 모든 코드는 순차적으로 실행된다라는 고정관념이 있었다. 이로 인해 나는 위의 서술한 문제가 대체 왜 발생했는지 이해를 할 수 없었다. 그리고 JavaScript를 공부하면서 나의 문제가 비동기 처리로 인한 문제였음을 알 수 있었다.

위의 문제를 예시로 들자면, getBoardsList(), getBoardsOrder() 함수가 비동기식으로 처리되어 웹페이지가 화면에 뜨는 것보다 늦게 처리되어 state에 어떠한 data도 불러오지 않은 채로 생성된 Board가 page에 뜨지 않았다.

개념

Blocking

웹 앱이 브라우저에서 특정 코드를 실행하느라 브라우저에게 제어권을 돌려주지 않으면 브라우저는 마치 정지된 것처럼 보일 수 있다. 이러한 현상을 blocking이라고 부릅니다. 자세히 정의하자면, 사용자의 입력을 처리하느라 웹 앱이 프로세서에 대한 제어권을 브라우저에게 반환하지 않는 현상이다.

Thread

기본적으로 프로그램이 작업을 완료하는 데 사용할 수 있는 단일 프로세스이다. 각 스레드는 한 번에 하나의 작업만 수행할 수 있다.

JavaScript의 경우

자바스크립트는 기본적으로 싱글 thread이다. 그래서 순차적으로 스레드가 실행되지만 Web workers가 여러 개의 JavaScript 청크(코드 스플리팅 시 생성되는 자바스크립트 파일 조각)를 동시에 실행할 수 있도록 worker라고 불리는 별도의 스레드로 보낼 수 있다. 따라서 시간이 오래 걸리는 처리는 woker를 사용해 처리하면 blocking 발생을 막을 수 있다.

 

비동기적 실행은 코드의 처리에 효율성을 증가시킬 수 있다. 하지만 어떤 함수가 일의 처리를 위해 이전의 여러 프로세스의 결과를 return 받아야 할 경우, 이전의 프로세스가 전부 종료된 후 다음 프로세스가 실행되도록 해야 한다.

동기, 비동기

위에서 Thread의 개념과 함께 JavaScript의 동기 처리에 대한 과정을 설명했다. 여기서 잠깐 동기와 비동기에 대해 확실하게 정리하면 다음과 같다.

  장점 딘점
동기(Synchronous) 의뢰한 처리가 끝났는지 여부를 쉽게 확인할 수 있어서 구조가 간단하고 구현 난이도가 낮다. 의뢰한 처리가 끝나기까지 기다려야 하기 때문에 대기 시간을 활용할 수 없다.
비동기(Asynchronous) 의뢰한 처리가 진행되고 있는 동안 시간을 효율적으로 사용해서 병렬 처리 할 수 있다. 의뢰한 처리가 끝났는지 확인하지 않으면 모르기 때문에 불필요한 확인 처리가 늘어난다. 구조가 복잡해서 구현 난이도가 높다.
  • 동기(Synchronous)
  • 비동기(Asynchronous)

https://adrianmejia.com/asynchronous-vs-synchronous-handling-concurrency-in-javascript/

async, await

내가 JavaScript 비동기 실행 처리를 위해 사용한 것은 async, await이다.

 

async, await의 사용 목적은 async로 감싼 function 내부에 특정 함수에 await을 추가해 해당 함수가 작업을 완료할 때까지 기다리도록 유지하기 위해 사용한다. 즉, 함수 자체가 동기식으로 바뀌는 것이 아닌 특정 작업의 함수는 작업을 기다리도록 해주는 것이다.

async

async function 선언은 AsyncFunction객체를 반환하는 하나의 비동기 함수를 정의합니다. 비동기 함수는 이벤트 루프를 통해 비동기적으로 작동하는 함수로, 암시적으로 Promise를 사용하여 결과를 반환합니다.

async function으로 만들기 위하여 function() 앞에 async keyword를 추가한다.

await

await연산자는 Promise를 기다리기 위해 사용됩니다. 연산자는 async function 내부에서만 사용할 수 있습니다.

내 코드에 반영한 결과

아래의 코드 일부에서 async와 await이 쓰인 것을 확인할 수 있다.

Boards.js

async componentDidMount(){ 
        console.log("componentDidMount")
        try
        {
          await this.props.getBoardsList();
          await this.props.getBoardsOrder();
        }
        catch(err)
        {
          console.error(err);
        }
        console.log("componentDidMountEnd");
    }

boardActions.js

// GET BOARDSLIST
export const getBoardsList = () => {
  return async (dispatch, getState) => {
    console.log("get Boards List in boardsAction.js");
    await axios
      .get(`/board_api/boards`, tokenConfig(getState))
      .then((res) => {
        dispatch({
          type: CONSTANTS.GET_BOARDSLIST,
          payload: res.data,
        });
      })
      .catch(err => console.log(err));
  }
};

// GET BOARDSORDER
export const getBoardsOrder = () => {
  return async (dispatch, getState) => {
  console.log("getBoardsOrder in boardAction.js")
  await axios
    .get(`/board_api/boardsOrder`, tokenConfig(getState))
    .then((res) => {
      dispatch({
        type: CONSTANTS.GET_BOARDSORDER,
        payload: res.data,
      });
    })
    .catch(err => console.log(err));
  }
};

출처

https://developer.mozilla.org/ko/docs/Learn/JavaScript/Asynchronous

 

Asynchronous JavaScript - Web 개발 학습하기 | MDN

In this module we take a look at asynchronous (en-US) JavaScript, why it is important, and how it can be used to effectively handle potential blocking operations such as fetching resources from a server.In this module we take a look at asynchronous (en-US)

developer.mozilla.org

내 코드

https://github.com/Donghyeonkim981214/trello-clone/blob/master/frontend/src/components/BoardListPage/Boards.js

 

Donghyeonkim981214/trello-clone

cloning Trello using pytohn, Django restframework and react - Donghyeonkim981214/trello-clone

github.com

https://github.com/Donghyeonkim981214/trello-clone/blob/master/frontend/src/actions/boardActions.js

 

Donghyeonkim981214/trello-clone

cloning Trello using pytohn, Django restframework and react - Donghyeonkim981214/trello-clone

github.com

https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Operators/await

 

await - JavaScript | MDN

Promise에 의해 만족되는 값이 반환됩니다. Promise가 아닌 경우에는 그 값 자체가 반환됩니다.

developer.mozilla.org

https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Statements/async_function

 

async function - JavaScript | MDN

async function 선언은 AsyncFunction객체를 반환하는 하나의 비동기 함수를 정의합니다. 비동기 함수는 이벤트 루프를 통해 비동기적으로 작동하는 함수로, 암시적으로 Promise를 사용하여 결과를 반환

developer.mozilla.org