AubE Log : 오브 로그

일상 생활에 대한 이야기, 프로그램 개발에 대한 기록 등 일련의 기억들을 다시 되짚어 본다.

JavaScript

자바스크립트 동기 비동기 처리 정리

오브:AubE 2024. 12. 28. 17:51

자바스크립트는 기본적으로 동기 방식으로 작동한다. 즉, 코드가 위에서 아래로 순차적으로 실행된다.

하지만, 자바스크립트는 비동기 처리가 필요한 상황(예: 네트워크 요청, 타이머, 파일 읽기 등)에서 비동기 처리를 할 수 있도록 콜백, 프라미스(Promises), async/await와 같은 기능을 제공하여 비동기 방식으로 작업할 수 있게 한다.

자바스크립트의 비동기 처리는 이벤트 루프(Event Loop)를 통해 이루어지며, 이를 통해 메인 스레드를 차단하지 않고 비동기 작업이 완료될 때까지 기다린 후 실행을 이어갈 수 있다.

자바스크립트에서 여러 함수를 순차적으로 호출할 때, 기본적으로는 각 함수가 이전 함수의 실행이 완료될 때까지 기다리지 않는다. 즉, 자바스크립트는 한 함수가 끝나기 전에 다음 함수를 호출할 수 있다. 하지만 이 동작 방식은 함수 내부의 작업이 동기식인지 비동기식인지에 따라 다르다.

  1. 동기 함수: 함수가 동기적으로 작성된 경우, 자바스크립트는 해당 함수가 완전히 실행될 때까지 기다렸다가 다음 함수를 실행한다. 즉, 이전 함수가 완료되지 않으면 다음 함수로 넘어가지 않는다.
  2. 비동기 함수: 함수 내부에 비동기 코드가 포함된 경우(예: setTimeout, fetch, Promise 등), 해당 함수는 비동기 작업이 완료되기를 기다리지 않고 바로 다음 함수를 호출한다. 비동기 작업이 완료되면 나중에 콜백 또는 Promise의 then 블록에서 결과를 처리한다.

예를 들어, 다음 코드에서는 fetchData()가 비동기 함수라면 processData()가 바로 실행된다.

function fetchData() {
  setTimeout(() => console.log("Data fetched"), 1000); // 1초 후 실행
}

function processData() {
  console.log("Processing data");
}

fetchData(); // 비동기 함수
processData(); // 즉시 실행됨

이 코드에서는 fetchData가 완료되기를 기다리지 않고 processData가 바로 실행된다. 만약 순차적으로 실행되기를 원한다면, Promise나 async/await를 사용하여 비동기 함수를 동기적인 방식으로 제어할 수 있다.

자바스크립트에서 함수의 동기/비동기 동작 여부는 함수가 비동기 작업을 포함하는지에 따라 결정된다. 즉, setTimeout, Promise, async/await 등의 비동기 처리가 포함되어 있는지가 동기/비동기 동작을 구분하는 기준이다.

결과를 반환하지 않는 동기 함수는 여전히 호출된 순서대로 실행을 마치고 다음 코드로 넘어가기 때문에 동기적으로 동작한다.

예시

아래의 calculateSum 함수는 결과를 반환하지 않지만, for 루프를 통해 합계를 계산한 후 console.log로 결과를 출력한다. 이 함수는 순차적으로 실행되며, 완료될 때까지 다음 코드로 넘어가지 않는다.

function calculateSum(arr) {
  let sum = 0;
  for (let num of arr) {
    sum += num;
  }
  console.log("Sum:", sum); // 결과를 출력
}

calculateSum([1, 2, 3, 4, 5]);
console.log("이 문장은 합계가 출력된 후 실행된다.");

위 코드를 실행하면, calculateSum 함수가 완료된 후 "이 문장은 합계가 출력된 후 실행된다."가 출력된다. calculateSum이 결과를 반환하지 않더라도, 순차적으로 실행되므로 동기적으로 동작한다고 볼 수 있다.

따라서 동기/비동기 여부는 반환 여부와 관계없이 함수 내부에 비동기 코드가 있는지에 따라 결정된다.

자바스크립트에서 제공하는 비동기 함수 또는 비동기 처리를 지원하는 메서드는 아래와 같은 것들이 있다. 이를 이용해 시간이 오래 걸릴 수 있는 작업을 비동기적으로 처리할 수 있다.


타이머 관련 비동기 함수

  1. setTimeout 지정된 시간이 지난 후 콜백 함수를 실행한다.
  2. setInterval 지정된 간격마다 콜백 함수를 반복 실행한다.
  3. clearTimeoutsetTimeout으로 설정된 작업을 취소한다.
  4. clearIntervalsetInterval로 설정된 작업을 취소한다.

네트워크 요청 관련 함수

  1. fetch
    fetch("<https://api.example.com/data>").then(response => response.json());
    
    
  2. HTTP 요청을 보내고 응답을 비동기적으로 처리한다.
  3. XMLHttpRequest
    const xhr = new XMLHttpRequest();
    xhr.open("GET", "<https://api.example.com/data>", true);
    xhr.send();
    
    
  4. 옛날 방식으로 HTTP 요청을 처리하는 객체로, 비동기 호출 지원.
  5. WebSocket
    const ws = new WebSocket("wss://example.com/socket");
    ws.onmessage = (event) => console.log(event.data);
    
    
  6. 서버와 실시간 통신을 위한 비동기 API.
  7. Axios
    axios.get("<https://api.example.com/data>").then(response => console.log(response));
    
    
  8. 외부 라이브러리지만, 널리 사용되는 Promise 기반 HTTP 요청 라이브러리.

이벤트 관련 비동기 처리

  1. DOM Event Listeners
    document.addEventListener("click", () => console.log("Clicked!"));
    
    
  2. DOM 이벤트를 비동기로 처리.
  3. EventEmitter (Node.js)
    const EventEmitter = require("events");
    const emitter = new EventEmitter();
    emitter.on("event", () => console.log("Event triggered"));
    emitter.emit("event");
    
    
  4. 이벤트 기반 비동기 처리를 위한 객체.

Promise 기반 비동기 함수

  1. Promise
    const promise = new Promise((resolve, reject) => {
      setTimeout(() => resolve("Done"), 1000);
    });
    
    
  2. 비동기 작업의 성공 또는 실패를 처리하는 객체.
  3. Promise.all
  4. 여러 Promise를 병렬로 처리하고, 모두 완료되면 결과를 반환한다.
  5. Promise.race
  6. 여러 Promise 중 가장 먼저 완료된 하나의 결과를 반환한다.
  7. Promise.allSettled
  8. 모든 Promise의 상태(성공/실패)를 반환한다.
  9. Promise.any
  10. 여러 Promise 중 가장 먼저 성공한 결과를 반환한다.

Async/Await

  1. async/awaitPromise를 쉽게 다룰 수 있도록 지원하는 ES8 구문.
  2. async function fetchData() { const response = await fetch("<https://api.example.com/data>"); return await response.json(); }

타이머 및 스케줄링 관련 (Node.js)

  1. process.nextTick 이벤트 루프의 다음 틱에서 실행.
  2. setImmediate 이벤트 루프의 다음 반복 주기에서 실행.
  3. queueMicrotask 마이크로태스크 큐에 작업을 추가.
  4. queueMicrotask(() => console.log("Microtask executed"));

File I/O 및 데이터 처리 (Node.js)

  1. fs.readFile
    const fs = require("fs");
    fs.readFile("file.txt", "utf-8", (err, data) => console.log(data));
    
    
  2. 파일을 비동기적으로 읽음.
  3. fs.writeFile
  4. 파일을 비동기적으로 씀.

실시간 작업 및 워커 관련

  1. setTimeout/setInterval (실시간 작업)
  2. Web Workers
    const worker = new Worker("worker.js");
    worker.onmessage = (event) => console.log(event.data);
    
    
  3. 스레드에서 실행되는 비동기 작업.
  4. SharedWorker
  5. 여러 스크립트 간 공유되는 워커.
  6. Service Workers
  7. 웹 애플리케이션의 백그라운드 작업 처리.

애니메이션 및 UI 관련

  1. requestAnimationFrame
    requestAnimationFrame(() => console.log("Animation frame"));
    
    
  2. 브라우저에서 애니메이션 작업을 효율적으로 처리하기 위해 비동기로 실행.
  3. cancelAnimationFrame
  4. 예약된 애니메이션 프레임을 취소.

기타 비동기 처리

  1. setTimeout/setInterval
  2. queueMicrotask
  3. process.nextTick (Node.js 전용)
  4. IntersectionObserver
  5. 요소가 뷰포트에 진입하거나 나갈 때 비동기적으로 알림.
  6. MutationObserver
    const observer = new MutationObserver((mutations) => console.log(mutations));
    observer.observe(document.body, { childList: true });
    
    
  7. DOM 변경 사항을 비동기로 감지.
  8. FileReader
    const reader = new FileReader();
    reader.onload = (event) => console.log(event.target.result);
    reader.readAsText(someFile);
    
    
  9. 파일을 비동기적으로 읽는 Web API.
  10. Geolocation API
    navigator.geolocation.getCurrentPosition((position) => console.log(position));
    
    
  11. 위치 정보를 비동기로 가져옴.
  12. Notification
  13. 사용자에게 비동기로 알림을 표시.
https://aube1225.blogspot.com/2024/12/javascript-async.html