home

    23-08-22

    자바스크립트에서 비동기 처리하는 방법?

    자바스크립트에서 callback, promise, async/await 사용해서 비동기 처리를 하는 방법에 대해 알아보자

    동기와 비동기 ?

    동기

    자바스크립트는 싱글스레드 언어이기 때문에 한 번에 하나의 작업만 수행할 수 있다. 이전 작업이 끝나야 다음 작업을 실행 할 수 있는 방식이다. 이러한 방식은 오랜 시간이 걸리는 네트워크 요청 등을 할 때 프로그램이 멈추는 단점이 있다.

    비동기

    자바스크립트는 동기의 단점을 해결하기 위해 비동기를 도입했다. 비동기는 코드의 실행 순서와 관계없이 작업을 실행하고, 작업이 완료되면 그 결과를 처리하는 방식이다. 주로 네트워크 요청에 많이 사용한다

    async

    위 사진을 참고하면 동기적으로 실행할 경우 27초가 걸리는 반면에 비동기적으로 실행하면 15초가 걸린다.
    비동기는 웹에서 서버에 요청했을 때 요청이 완료되기 전까지 아무것도 실행되지 않는다면 화면이 멈춘 것 처럼 보일 뿐만 아니라 하나의 프로그램을 실행하는 데 많은 시간이 소요되기 때문이다. 또한 실행 순서가 중요할 때도 있다. 예를 들면 다른서 코드가 서버에 요청한 데이터 값을 이용해야 할 때는 데이터를 받아 온 후에 코드가 실행되는게 필요하다. 이럴때 사용하는 것이 비동기 처리다.

    자바스크립트에서 비동기를 다루는 방법

    1. Callback 함수

    콜백함수는 파라미터로 전달받은 함수를 말한다. 파라미터로 함수를 전달받고 함수 내부에서 필요할 때 호출해서 사용할 수 있다.
    주로 비동기 작업에서 사용되며, 작업이 완료되었을 때 결과를 처리하거나 다음 작업을 수행하기 위해 사용한다.

    function callBackFunc(callback) {
        setTimeout(() => {
            console.log("3초")
        },3000)
        console.log('Hello')
    }
    callBackFunc()

    setTimeout() 함수는 비동기 함수다. 그렇기 때문에 console.log("Hello")가 먼저 나오고 3초 뒤에 console.log("3초")가 나온다


    콜백함수의 단점 🚫

    1. 콜백함수를 사용하다 보면 코드의 가독성과 관리가 어려워지는 콜백지옥이 생긴다.
    getData(function(data) {
      process(data, function(processedData) {
        save(processedData, function() {
          // ...
        });
      });
    });
    1. 에러처리가 어렵고 어디서 에러가 났는지 알기가 어렵다.

    2. Promise

    콜백의 한계점을 극복하기 위해 Promise가 나왔다 Promise는 비동기 작업의 결과나 상태를 표현하는 객체로 표현한다.
    Promise를 사용하면 ?

    • 코드의 유지 보수성이 증가한다.
    • 에러 처리가 용이해진다.
    • Promise의 상태는 3가지의 상태와 결과를 가진다
      • pending(대기): 처리가 완료되지 않은 상태
      • fulfilled(이행): 성공적으로 처리가 완료된 상태
      • rejected(거부) : 처리가 실패로 끝난 상태

    간단하게 Promise 사용 예시를 알아보자.

    function fetchData() {
      return new Promise((resolve, reject) => {
        setTimeout(() => {
          const data = { id: 1, name: 'John' };
          if (data) {
            resolve(data); // 성공
          } else {
            reject(new Error('Error')); // 실패
          }
        }, 1000);
      });
    }
     
    fetchData()
      .then(data => {
        console.log(data);
      })
      .catch(error => {
        console.error(error);
      });

    프로미스는 성공 또는 실패만 해야한다.

    3. async / await

    프로미스도 다음과 같은 문제가 있엇다.

    1. 특정 조건에 따라 분기를 나누기가 어렵다.
    2. 어떤 부분에서 에러가 발생했는지 파악하기가 어렵다.
    3. 프로미스 체이닝도 반복되면 가독성이 떨어져 .then 지옥이 발생할 가능성이 있다.

    이러한 문제를 해결하기 위해 async/await이 등장했 다. async/await은 프로미스를 기반으로 동작하고 프로미스의 후속 처리 메서드인 then 없이도 비동기를 동기처럼 보이도록 구현하는 방식이다. 보다 간결한 코드 작성을 위해 등장한 문법으로 프로미스보다 가독성이 좋고 로직이 물 흐르듯이 직관적인것처럼 보인다.

    async/await의 장점

    • 프로미스의 단점 극복: 프로미스에서 발생한 단점 중 하나인 콜백 헬과 체이닝 구조의 복잡성을 해결해준다.
    • 에러 처리: try-catch를 사용해서 error 처리를 쉽게 할 수 있다.
    • 가독성: 비동기코드를 동기적으로 흐르는 것처럼 작성할 수 있다.

    async와 await의 의미

    • async : async 함수는 항상 Promise를 반환한다.
    • await : await 키워드는 비동기 작업의 완료를 기다리고, 해당 작업의 결과를 반환한다 await는 async 함수 내에서만 사용할 수 있다.✔

    간단하게 async await 사용 예시를 알아보자.

    async function fetchData() {
        try {
            const response = await fetch('api주소');
            const data = await response.json();
            return data;
        } catch (error) {
            console.error('Error', error);
        }
    }
     
    async function process() {
        const result = await fetchData();
        console.log(result)
    }
     
    process();