cs

[JavaScript] Top-level await (+약간의 Promise)

ssoonn 2024. 12. 31. 12:23

Top-level await

js ES2022(ES13)부터 도입된 기능으로, 모듈 스코프에서 직접 await 키워드를 사용할 수 있게 해준다.

이전에는 async 키워드가 있는 스코프 내에서만 await를 통해 해당 스코프에서 비동기 동작이 완료되기까지 블로킹할 수 있었는데

모듈단위에서 await를 통해 특정 비동기 함수의 동작이 완료되기까지 하위 모듈의 동작을 막을 수 있다.

 

1. 기존의 await 사용 제한과 Top-level await의 등장

기존 await 키워드는 반드시 async 함수 내부에서만 사용할 수 있었다.

따라서, await를 모듈의 최상위 레벨에서 사용하려면 async 함수를 감싸야 했다.

// 기존 방식 (async 함수로 감싸야 함)
async function main() {
  const result = await fetchData();
  console.log(result);
}
main();

 

Top-level await을 사용하면 모듈의 최상위 레벨에서 await를 직접 사용할 수 있다.
=>  async 함수를 감싸는 불필요한 작업 없이 비동기 작업을 간단히 처리

// Top-level await 사용 예시
const result = await fetchData();
console.log(result);

 

2. Top-level await의 특징

 

  1. 모듈 스코프에서만 사용 가능
    Top-level await은 ES 모듈(ECMAScript Module)에서만 사용할 수 있.
    스크립트 파일(script 태그, 브라우저의 전역 스코프)에서는 사용 불가
  2. 비동기 작업을 기다림
    Top-level await을 사용하는 모듈은 해당 비동기 작업이 완료될 때까지 다른 모듈의 실행을 블록
  3. 의존 모듈 순서 보장
    Top-level await이 있는 모듈은, 해당 모듈이 의존하는 모듈의 비동기 작업이 모두 끝난 후에 실행된다. (모듈 간 실행 순서 보장)

 

Promise와 await의 기본 관계

 

  • await 키워드는 Promise가 완료될 때까지(성공 또는 실패) 기다리는 역할을 한다.
    • await는 항상 Promise 객체를 처리
  • 성공(resolve)시 결과값 반환, 실패(reject)하면 에러 던지기
const fetchData = () => Promise.resolve("data");

async function main() {
  const result = await fetchData(); // Promise가 완료될 때까지 기다림
  console.log(result); // "data"
}
main();

 

 

Top-level await에서 Promise와의 관계

Top-level await는 Promise를 더 쉽게 처리하기 위한 상위 수준 구문
Promise는 여전히 비동기 작업의 기본이며, Top-level await은 이를 더 직관적이고 간단하게 사용하는 도구이다.

 

Top-level await도 내부적으로 Promise를 기다리는 메커니즘을 사용한다. (모듈의 최상위 스코프에서 Promise를 처리할 때 유용)

기존의 Promise를 처리하려면 then 체인을 사용하거나, async 함수를 작성했다.
Top-level await을 사용하면 코드가 더 간결해지고, 명령형으로 작성 가능하다.

 

1. 간단 예제

Promise와 then 체인을 사용한 기존 방식

import fetch from "node-fetch";

fetch("https://api.example.com/data")
  .then((response) => response.json())
  .then((data) => console.log(data))
  .catch((error) => console.error(error));

 

Top-level await 방식

import fetch from "node-fetch";

const response = await fetch("https://api.example.com/data");
const data = await response.json();
console.log(data);

 

2. todoList.mjs

// todoList.mjs
let todoList;

(async () => {
  const response = await fetch("https://jsonplaceholder.typicode.com/todos/1");
  todoList = await response.json();
})();

export { todoList };

// index.mjs
import { todoList } from "./todoList.mjs";

console.log(todoList); // undefined

 

  • todoList.mjs: todoList를 조회한 후 결과를 내보내는 모듈
  • index.mjs: todoList.mjs의 결과를 import하여 출력하는 모듈

index.mjs에서 todoList.mjs의 비동기 처리가 완료되지 않은 시점에 todoList로 접근이 가능하기 때문에 undefined를 출력

  => todoList.mjs에서 Promise객체를 반환으로 해결

 

Promise와 then 체인을 사용한 기존 방식

Promise 객체의 then 메서드를 활용해 비동기 처리 직후 todoList에 접근한다.

 

문제:

  • promise를 사용하지 않아도 todoList로 접근 가능 (위험요소를 포함)
  • 복잡한 코드
// todoList.mjs
let todoList;

export default (async () => {
  const response = await fetch("https://jsonplaceholder.typicode.com/todos/1");
  todoList = await response.json();
})();

export { todoList };

// index.mjs
import promise, { todoList } from "./todoList.mjs";

promise.then(() => {
  console.log(todoList); // {userId: 1, id: 1, title: 'delectus aut autem', completed: false}
});

 

Top-level await 방식

index.mjs는 todoList.mjs의 await가 모두 실행되기 전(비동기 처리가 완료되기 전까지) 동작을 중지한다.

(Top-level await를 사용한 모듈이 하나의 거대한 async 함수처럼 동작)

 

따라서 index.mjs에서는 todoList로 바로 접근을 해도, 비동기 처리가 완료됐다는 것을 보장하기 때문에 원하던 결과를 얻을 수 있게 된다.

// todoList.mjs
let todoList;

const response = await fetch("https://jsonplaceholder.typicode.com/todos/1");
todoList = await response.json();

export { todoList };

// index.mjs
import { todoList } from "./todoList.mjs";

console.log(todoList); // {userId: 1, id: 1, title: 'delectus aut autem', completed: false}

 

 

 

ref.

https://fe-developers.kakaoent.com/2022/220728-es2022/

 

자바스크립트의 새로운 기능들 | 카카오엔터테인먼트 FE 기술블로그

이동희(east) 스토리FE개발팀 프론트엔드 개발자입니다. 음주가무를 즐기며 활동적인 모든 것을 사랑합니다.

fe-developers.kakaoent.com

https://velog.io/@pds0309/top-level-await

 

top level await

Top-level await enables modules to act as big async functionsES2022에서 나온 기능으로 모듈의 최상위 스코프에서 비동기 동작을 await하여 사용할 수 있다.이전에는 async 키워드가 있는 스코프 내에서만 await

velog.io