티스토리 뷰

우아한테크코스

자바스크립트의 비동기

개발여행가 2023. 3. 27. 23:26

많은 인터렉션이 일어나는 웹 환경에서 필수적인 비동기에 대한 학습


비동기란?

비동기는 동기의 반대 개념으로, 순차적으로 진행되는 것이 아닌 동시다발적으로 진행되는 것을 말한다.

 

동기적 일처리 방식

순차적으로 일이 처리되는 방식

비동기적 일처리 방식

동시다발적으로 일이 처리되는 방식

 

 

자바스크립트의 비동기 동작을 이해하기 위해 다음의 예시를 작성해봤다.

console.log('1');
setTimeout(() => console.log('2'), 5000); // 1000은 ms 단위, 즉 1초를 뜻한다.
console.log('3');

MDN에서는 setTimeout 을 다음과 같이 설명한다.

 

전역 setTimeout() 메서드는 만료된 후 함수나 지정한 코드 조각을 실행하는 타이머를 설정합니다.

 

위의 코드를 실행해보면 다음과 같은 결과가 나온다.

1
3
// 5초 후
2

이렇게 setTimeout 은 코드가 작성된 순서대로 동작하지 않고, 비동기 동작을 한다.

 

그런데 의아한 점이 있다.

자바스크립트 엔진은 싱글 스레드 기반이다. 싱글 스레드는 한 번에 하나의 일만, 즉 동기적으로 동작한다.

그렇다면 왜 console.log('2') 보다, 바로 밑의 console.log('3') 메서드가 먼저 실행될까?

 

Web API

사실 setTimeout은 자바스크립트 내장 메서드가 아니라, Web API의 메서드다.

Web API는 DOM, Ajax, setTimeout, Event Handler 등과 같이 웹 브라우저에서 제공하는 기능들이다.

 

위에서 비동기 동작을 할 수 있던 이유를 다시 확인해보자.

  1. console.log('1')이 실행되고 CallStack에서 사라진다.
  2. setTimeout 는 Web API를 호출하고, CallStack에서 사라진다. 이와 함께 아래의 Web API의 상황이 동시에 진행된다.
  3. console.log(’3’) 이 실행되고 CallStack에서 사라진다.

 

Web API의 상황 → 비동기적으로 동작하는 부분!!

  1. setTimeout 의 타이머가 동작한다.
  2. 타이머가 완료되면 setTimeoutconsole.log('2') 을 Task Queue에 저장한다
  3. 이벤트 루프는 CallStack과 Task Queue의 상태를 체크하면서 CallStack이 비어있을 경우, Task Queue에 저장된 console.log('2') 을 CallStack에 넣는다.
  4. console.log('2') 이 실행되고 CallStack에서 사라진다.

 

잘 이해가 되지 않겠지만, 핵심은 WebAPI가 제공하는 메서드는

자바스크립트 엔진(CallStack) → Web APITaskQueue → 자바스크립트 엔진(CallStack)

를 거쳐 실행된다.

따라서 자바스크립트 엔진에서 setTimeout이 사라지면서 바로 밑의 코드가 실행될 수 있는 것이다.

 

또한 주의할 점이 있다.

console.log('1');
setTimeout(() => console.log('2'), 0);
console.log('3');
// ... console.log('3'); 1억개
console.log('3');

/* 출력 결과 */
1
3
// 3 1억번
3
2

CallStack이 완전히 비워지지 않으면, TaskQueue의 콜백은 Callback으로 들어가지 않는다.

따라서 3이 1억번이 아니라 10억번이어도 2는 제일 마지막에 출력될 것이다. (실험은 해보지 않았다.)

 

웹 프론트엔드에서 비동기 처리가 필요한 이유

비동기 처리는 웹 프론트엔드에서 필수적인 기술이다. 이는 웹 애플리케이션에서 많은 인터렉션이 일어나기 때문이다.

 

예를 들어, 사용자가 버튼을 클릭하면 서버에 데이터를 요청하고 응답을 기다리는 동안 화면이 멈춰있게 된다.
이러한 상황에서 비동기 처리를 사용하면 서버의 응답을 기다리는 동안 다른 작업을 수행할 수 있다.

따라서 비동기 처리를 사용하면 사용자 경험을 향상시킬 수 있다.

 

예를 들어, 데이터를 불러오는 동안 로딩 애니메이션을 표시하거나 다른 작업을 수행할 수 있다.

비동기 처리는 자바스크립트에서 callback Promise, async/await 등의 문법을 사용하여 구현할 수 있다.

 

비동기를 처리할 수 있는 방법 세 가지

Call Back

콜백은 함수를 다른 함수의 인자로 전달하여, 특정 작업이 완료된 후 실행되도록 하는 방법이다. 콜백을 사용하면 비동기 작업을 처리할 수 있다.

 

예를 들어, setTimeout 함수는 첫 번째 인자로 콜백 함수를 받는다. 이 콜백 함수는 지정된 시간이 지난 후 실행된다.

setTimeout(() => {
  console.log('1초 후 출력!');
}, 1000);

위의 코드에서 setTimeout 함수는 1초 후에 콜백 함수를 실행한다.

 

Promise

Promise는 비동기 작업의 완료 또는 실패를 반환하는 객체다. Promise를 사용하면 비동기 작업의 성공 또는 실패에 따라 다른 작업을 수행할 수 있다.

 

예를 들어, 서버에서 데이터를 가져오는 작업을 수행하는 함수가 있다고 가정해보겠다. 이 함수는 Promise 객체를 반환한다.

function fetchData() {
  return new Promise((resolve, reject) => {
    // 서버에서 데이터를 가져오는 코드
    // 데이터를 성공적으로 가져왔다면 resolve 함수 호출
    // 데이터를 가져오지 못했다면 reject 함수 호출
  });
}

위의 코드에서 fetchData 함수는 Promise 객체를 반환한다. 이 Promise 객체의 then 메서드를 사용하여 데이터를 성공적으로 가져왔을 때 수행할 작업을 지정할 수 있다.

fetchData().then(data => {
  // 데이터를 성공적으로 가져왔을 때 수행할 작업
});

또한 catch 메서드를 사용하여 데이터를 가져오지 못했을 때 수행할 작업을 지정할 수 있다.

fetchData()
  .then(data => {
    // 데이터를 성공적으로 가져왔을 때 수행할 작업
  })
  .catch(error => {
    // 데이터를 가져오지 못했을 때 수행할 작업
  });

 

Async Await

async/await 문법은 Promise 기반의 비동기 작업을 동기식으로 작성할 수 있게 해준다. async/await 문법을 사용하면 비동기 코드를 더 간결하고 가독성 높게 작성할 수 있다.

 

예를 들어, 위에서 작성한 fetchData 함수의 데이터를 async/await 로 받아보겠다.

async function getData() {
  try {
    const data = await fetchData();
    // 데이터를 성공적으로 가져왔을 때 수행할 작업
  } catch (error) {
    // 데이터를 가져오지 못했을 때 수행할 작업
  }
}

위의 코드에서 getData 함수는 async 키워드로 정의된다.

해당 함수는 암묵적으로 Promise 객체를 반환하는 것으로 정의된다.

이 함수 내부에서 await 키워드와 함께 Promise 객체를 반환하는 fetchData 함수가 호출된다.

 

await 키워드는 Promise가 처리될 때까지 기다린 후, 결과 값을 반환한다.

따라서 data 변수에는 fetchData 함수가 성공적으로 데이터를 가져왔을 경우 해당 데이터가 저장된다. (Promise then을 사용하지 않아도 된다.)

만약 fetchData 함수가 실패하여 데이터를 가져오지 못했다면 예외가 발생한다. 이 예외는 try...catch 문으로 처리된다.

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/03   »
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
글 보관함