JS - 비동기 공부

0

JavaScript

목록 보기
11/11
post-thumbnail

동기와 비동기

동기

먼저 시작된 하나의 작업이 끝날 때까지 다른 작업을 하지 않고, 해당 작업이 끝나야지만 다음 작업을 시작할 수 있는 방식.

비동기

먼저 실행된 작업이 끝나기도 전에 다음 작업을 수행. 즉 한 번에 여러 작업을 동시에 수행할 수 있는 방식

JavaScript의 비동기식 처리

Java Script는 싱글 스레드 런타임을 가진 동기식 언어이다. 분기, 반복, 함수 호출 등이 차례로 동기로 실행되며, 이 때 코드의 처리는 코드의 흐름과 동일하게 진행된다.
하지만 JavaScript에서는 브라우저에서 별도 API를 사용하여 비동기적으로 작업을 처리할 수 있다. 비동기 코드를 처리하는 모듈로는 이벤트 루프, 태스크 큐, 잡 큐 등이 있다.

JavaScript의 비동기 내장 함수

JavaScript는 비동기 내장함수를 제공한다. 종류로는 setTimeout, XMLHttpRequest, fetch 등이 있다.

setTimeout / clearTimeout

setTimeout 함수는 특정 코드를 바로 실행하지 않고 일정 시간 지연시킨 후 실행한다.

setTimeout(() => console.log("5초 후에 실행"), 5000);
///5초 뒤에 "5초 후에 실행"이 콘솔에 출력된다.

clearTimeout 함수는 setTimeout을 취소 또는 중지시키는 함수이다.

const timer = setTimeout(() => console.log('10초 후 실행'), 10000);
clearTimeout(timer);
// setTimeout이 종료됨 => 출력 안됨

fetch (fetch API)

간단하게만 말하자면 fetch 함수는 JavaScript에서 서버로 네트워크 요청을 보내고 응답을 받을 수 있도록 해준다. Promise 기반으로 구성되어 있기에 비동기 처리에 편리하다는 장점을 가지고 있다. 따라서 Promise의 후속 처리 메서드인 then이나 catch와 같은 체이닝으로도 작성할 수 있다.

let url =
  "https://..........url.............";
fetch(url, options)
  .then((response) => response.json())	//데이터 타입 결정
  .then(data => console.log(data))	//데이터 전달 받음
  .catch((error) => console.log(error));	//catch에서 에러 요청 발생 시 에러를 받음

위와 같은 구조를 가지고 있다. Promise 객체와 기본적인 구조 및 동작은 비슷하다.
첫번째 인자로 URL, 두번째 인자로 옵션 객체를 받고 Promise 타입의 객체를 반환한다. 반환된 객체는 API 호출이 성공했을 경우에는 응답(response) 객체를 resolve하고, 실패했을 경우에는 예외(error) 객체를 reject한다.

fetch HTTP 요청

Create : POST
Read : GET
Update : PUT
Delete : DELETE

JavaScript의 3가지 비동기 처리 방법

  1. Callback Function
  2. Promise
  3. async/await

Callback

단순하게 비동기 코드 순서를 제어할 수 있는 함수이다.

const printString = (string, callback) => {
  setTimeout(function () {
    console.log(string);
    callback();
  }, Math.floor(Math.random() * 100) + 1);
};

const printAll = () => {
  printString('A', () => {
    printString('B', () => {
      printString('C', () => {});
    });
  });
};

printAll();
console.log(
  `비동기 제어 성공`
);

/* 출력내용
비동기 제어 성공
A
B
C
*/

간단한 코드의 경우 이렇게 쉽게 구현이 가능하지만, 만일 코드가 길어지게 된다면 가독성이 심하게 낮아지는 Callback Hell 현상이 발생할 우려가 있다.

Promise

이러한 Callback Hell 현상을 해결하기 위해 등장했다. Promise 역시 간편한 비동기 처리를 위한 객체이다.
Promise는 아래의 3가지의 상태를 갖는다.

① 대기(pending) : 진행 상태, Promise 객체가 생성되어 사용될 준비가 된 상태
Promise의 객체는 new Promise()로 생성할 수 있으며, 콜백 함수를 선언할 수 있고, 콜백 함수의 인자는 resolve, reject이다.
new Promise(function(resolve, reject) {})
② 이행(Fulfilled) : 성공 상태, 비동기 처리에 의해 원하는 올바른 결과를 얻어와 그 결과를 정상적으로 처리하고자 resolve가 호출된 상태
③ 거부(Rejected) : 실패 상태, 무언가 잘못되어 예외로 처리하고자 reject가 호출된 상태

const promise = new Promise((resolve, reject) => { // 대기 상태
  getData(
    response => resolve(response.data),			   // 이행 상태
    error => reject(error.message)        		   // 거부 상태
  )
})

Promise는 또한 then, catch, finally 를 통해 메서드 체이닝을 수행할 수 있다.

then() - 성공(resolve) 시에는 then 메서드에 실행할 콜백 함수를 인자로 넘긴다.
catch() - 실패(reject) 시에는 catch 메서드에 실행할 콜백 함수를 인자로 넘긴다.
finally() - 성공/실패 여부와 상관없이 모두 실행 시에는 finally 메서드에 실행할 콜백 함수를 인자로 넘긴다.

promise
  .then(data => console.log(data))
  .catch(err => console.error(err))
  .finally(() => console.log("always run")

위와 같이 체이닝을 통해 함수를 호출한 주체가 실행을 완료한 뒤 자기 자신을 리턴한다.

Promise.all

여러 개의 비동기 작업을 동시에 처리하고 싶을 때 사용하며, 인자로는 배열을 받는다.

Promise.all([timer(1000), timer(2000), timer(3000)])
  .then((value) => { console.log(value); });
// [1000, 2000, 3000] → 3000까지 모두 다 실행이 끝난 후에 다 반환

async/await

then()을 연쇄적으로 체이닝하다보면 Callback Hell 급으로 혼란에 빠질 수 있다. 이러한 문제를 해결하기 위해 탄생한 것이 async/await이다.
https://velog.io/@cline1103/JavaScript-%EA%B3%B5%EB%B6%80-asyncawait

0개의 댓글