티스토리 뷰

반응형

🚀  들어가며...

동기(Syncronous)와 비동기(Asynchronous)는 프로그래밍 언어에서 중요한 개념입니다.

  • 동기는 요청 후 응답을 받아야 다음 동작을 실행하는 방식을 말하며
  • 비동기는 요청을 보낸 후 응답과 관계없이 다음 동작을 실행하는 방식입니다.

자바스크립트에서 동기와 비동기

자바스크립트는 단일 스레드 프로그래밍 언어로 단일 호출 스택이 있어 한 번에 하나의 일을 처리할 수 있습니다. 그러므로 자바스크립트는 동기 방식으로 진행이 됩니다. 하나의 호출 스택만 있기 때문에 하나의 함수를 처리하는데 매우 오랜 시간이 걸린다면 다음 실행해야할 함수에 지장을 줄 수 있다는 문제가 발생합니다. 이 부분이 바로 비동기의 필요성입니다. 단일 호출 스택을 가진 자바스크립트에서 비동기를 구현할 수 있게 하는 방법을 알아봅시다!

 

📑 내용

  • 예시1 (Ajax)
function getData() {
   var tableData;
   $.get('url', function(response) {
      tableData = response;
   });
   // $.get()으로 데이터 요청 후 기다리지 않고 바로 return 하기 때문에
   return tableData;
}

console.log(getData()); // 결과는 undefined
  • 예시2 (SetTimeout())
// #1
console.log('First');
// #2
setTimeout(function() {
   console.log('Second');
}, 3000);
// #3
console.log('Third');

// 결과:  First -> Third -> Second 순으로 출력

개발자가 의도한대로 비동기 처리가 되지 않는 모습을 볼 수 있습니다.

 

  • 해결방안1(callback함수이용)
function getData(callback) {
 $.get('url', (response)=> {
  callback(response) // 서버에서 받은 데이터 response를 callbackFunc() 함수에 넘겨줌
 })
}

getData(function (tableData) {
 console.log(tableData) // $.get()의 response 값이 tableData에 전달됨
})

callback함수는 다른 함수의 인자로써 이용될때나 어떤 이벤트에 의해 호출되어질때 사용하는 함수로, 비동기 처리의 해결방안이 될 수 있지만, callback함수 안에 callback함수를 계속 중첩으로 사용하다 보면 코드의 가독성이 매우 나빠지고 로직변경도 어려운 '콜백지옥'에 빠질수 있습니다. 따라서 저는 위 방식을 선호하지는 않습니다.

 

  • 해결방안2(Promise)

프로미스를 사용할 때 알아야 하는 가장 기본적인 개념이 바로 프로미스의 상태(states)입니다. 여기서 말하는 상태란 프로미스의 처리 과정을 의미합니다. new Promise()로 프로미스를 생성하고 종료될 때까지 3가지 상태를 갖습니다.

  • Pending(대기) : 비동기 처리 로직이 아직 완료되지 않은 상태
  • Fulfilled(이행) : 비동기 처리가 완료되어 프로미스가 결과 값을 반환해준 상태
  • Rejected(실패) : 비동기 처리가 실패하거나 오류가 발생한 상태

Pending(대기)

먼저 아래와 같이 new Promise() 메서드를 호출하면 대기(Pending) 상태가 됩니다.

new Promise();

 

new Promise() 메서드를 호출할 때 콜백 함수를 선언할 수 있고, 콜백 함수의 인자는 resolve, reject입니다.

new Promise(function(resolve, reject) {
  // ...
});

 

 

Fulfilled(이행)

여기서 콜백 함수의 인자 resolve를 아래와 같이 실행하면 이행(Fulfilled) 상태가 됩니다.

new Promise(function(resolve, reject) {
  resolve();
});
 

그리고 이행 상태가 되면 아래와 같이 then()을 이용하여 처리 결과 값을 받을 수 있습니다.

function getData() {
  return new Promise(function(resolve, reject) {
    var data = 100;
    resolve(data);
  });
}

// resolve()의 결과 값 data를 resolvedData로 받음
getData().then(function(resolvedData) {
  console.log(resolvedData); // 100
});
 

※ 프로미스의 '이행' 상태를 좀 다르게 표현해보면 '완료' 입니다.

Rejected(실패)

new Promise()로 프로미스 객체를 생성하면 콜백 함수 인자로 resolve와 reject를 사용할 수 있다고 했습니다. 여기서 reject를 아래와 같이 호출하면 실패(Rejected) 상태가 됩니다.

new Promise(function(resolve, reject) {
  reject();
});
 

그리고, 실패 상태가 되면 실패한 이유(실패 처리의 결과 값)를 catch()로 받을 수 있습니다.

function getData() {
  return new Promise(function(resolve, reject) {
    reject(new Error("Request is failed"));
  });
}

// reject()의 결과 값 Error를 err에 받음
getData().then().catch(function(err) {
  console.log(err); // Error: Request is failed
});

프로미스 처리 흐름 - 출처: MDN

이제 본론으로 들어와서 Promise함수를 이용해서 비동기처리를 해봅시다.

function getData() {
  return new Promise(function(resolve, reject) {
    $.get('url', function(response) {
      if (response) {
        resolve(response);
      }
      reject(new Error("Request is failed"));
    });
  });
}

// 위 $.get() 호출 결과에 따라 'response' 또는 'Error' 출력
getData().then(function(data) {
  console.log(data); // response 값 출력
}).catch(function(err) {
  console.error(err); // Error 출력
});

서버에서 제대로 응답을 받아오면 resolve() 메서드를 호출하고, 응답이 없으면 reject() 메서드를 호출합니다. 호출된 메서드에 따라 then()이나 catch()로 분기하여 응답 결과 또는 오류를 출력할 수도 있습니다.

 

  • 해결방안3(async, await)

 

function getData(callback) {
  return new Promise((resolve)=> {
    $.get('url', (response)=> {
       resolve(response);
    });
  });
}

async function callData() {
    try {
       let result = await getData(); // 프로미스 결과를 기다립니다.
       console.log(result)
    } catch(error) {
       console.log(error)
    }
}

async/await 는 Promise를 더욱 쉽게 사용할 수 있도록 해 주는 ES2017(ES8) 문법입니다.

 

이 문법을 사용하려면 함수의 앞부분에 async 키워드를 추가하고,

해당 함수 내부에서 Promise 앞부분에 await 키워드를 사용합니다.

 

이렇게 하면 Promise가 끝날 때까지 기다리고, 결과 값을 특정 변수에 담을 수 있습니다.

 

🙋🏻‍♂️ 후기

이해만 하면 어렵지 않게 구현이 가능한 React 비동기에 대해 알아보았습니다. 저는 API를 호출할 때 자주 사용하는것 같습니다. API 호출 시 상황에 따라 시간소요가 오래걸릴 수 있으므로, async, await 사용을 적극 추천합니다!!

 

🔗  참고한 글

https://velog.io/@thsoon/JS-%EB%B9%84%EB%8F%99%EA%B8%B0%EB%8A%94-%EC%96%B4%EB%96%BB%EA%B2%8C-%EA%B5%AC%ED%98%84%EB%90%98%EC%96%B4%EC%9E%88%EB%8A%94%EA%B0%80

 

JS 비동기는 어떻게 구현되어있는가??

JS의 비동기 프로그래밍의 중요한 요소들을 간단하게 짚고 넘어간 뒤, 비동기를 처리하는 방식 3가지인 Callback, Promise, Async Await의 내부를 살펴봅니다.

velog.io

 

 

반응형

'React' 카테고리의 다른 글

[React] Fragment에 대해 알아보자!  (0) 2022.06.30
[React] React.PureComponent 이해하기  (0) 2022.05.19
댓글
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/12   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
글 보관함