//main.js
const response = await fetch('https://learn.codeit.kr/api/employees');
const data = await response.json();
console.log(data);

console.log('Task 2');

console.log('Task 3');

원래 비동기 프로그램의 목적은 비동기 작업의 결과를 기다리는 동안 다른 작업을 먼저 처리하는 것이다. fetch 결과를 기다리는 동안 아래에 있는 코드(작업)들을 먼저 처리해주면 좋을 것 같은데, 코드를 실행해보면 직원 데이터가 먼저 출력되고, Task 2, Task 3이 출력된다. 코드가 위에서부터 아래로 순서대로 실행되고 있는 것인데 Promise와 await으로 비동기 처리를 제대로 하려면 함수를 이용해야한다.

//asyncFunctions.js
export function printEmployees() {
  const response = await fetch('https://learn.codeit.kr/api/employees');
  const data = await response.json();
  console.log(data);
};

새로운 js 파일을 만들어 printEmployees라는 함수를 정의하고 main.js의 일부분을 긁어온다. 그런데 await에 빨간줄이 가있는걸 볼 수 있다.

await은 async 함수 내에서나 모듈(module)의 최상위 레벨에서만 사용할 수 있다고 한다. 일단 여기서 모듈이라는건 ES 모듈을 뜻하는데 package.json 파일에서 type을 모듈로 설정해 줬다. 

그래서 이 async-js 디렉토리 안에서는 파일들이 기본적으로 ES 모듈로 인식되기 때문에 함수 바깥에서도 await을 쓸 수 있었던 것이다. 만약 json 파일에서 type 모듈을 지우면 main.js 파일을 CommonJS 모듈로 인식하기 때문에 오류가 난다.
await으로 비동기 처리를 제대로 하려면 함수를 이용해야 하기 때문에 함수 바깥에서 await을 쓰는게 흔하진 않다. ES6 모듈 안에서만 이게 가능하다는 사실을 기억해두자.
다시 본론으로 돌아가서 async 함수 안에서만 사용할 수 있다는건 무슨 뜻일까? async 함수를 만들려면 function 앞에 async 키워드를 붙여주면 된다. 

//asyncFunctions.js
export async function printEmployees() {
  const response = await fetch('https://learn.codeit.kr/api/employees');
  const data = await response.json();
  console.log(data);
};

//참고, 화살표 함수 문법으로 async 함수를 정의하려면? async의 위치가 조금 다르니까 주의!

const printEmployeesArrow = async () => {
  const response = await fetch('https://learn.codeit.kr/api/employees');
  const data = await response.json();
  console.log(data);
}

그러면 아까 오류를 보이던 await의 빨간 줄이 더이상 보이지 않는다. 그럼 main.js 파일에서 printEmployees 함수를 가져와서 호출해 보자.

//main.js
import { printEmployees } from './asyncFunctions.js'
printEmployees();

console.log('Task 2');

console.log('Task 3');

실행해보면 이번엔 아까와 다르게 Task 2와 Task 3이 출력되고 그 아래에 직원 데이터가 출력됐다. 
코드의 실행 순서를 살펴보면

  1. 가장 먼저 printEmployees 함수를 import 하고 (main.js 1번째 줄)
  2. printEmployees 함수를 실행한다. (main.js 3번째 줄)
  3. 그러면 함수 안으로 가서 fetch를 실행 (asyncFunctions.js 2번째 줄)
  4. fetch는 prmise를 리턴하는데 앞에 await 문이 있기 때문에 promise가 fulfilled 상태가 될 때까지 기다린다. (asyncFunctions.js 2번째 줄)
  5. 여기서 중요한 사실!  async 안에서 await 함수를 쓰면 promise가 fulfilled가 될 때까지 기다리는 동안은 다시 함수 바깥으로 나와서 나머지 코드를 모두 실행한다.
  6. 나머지 코드 = main.js의 5, 7번째 줄  (그래서 printEmployee 함수 아래에 있는 코드들이 먼저 실행된 것)
  7. 그러다 promise 상태가 fulfilled 가 되어 성공 결과를 갖게 되면
  8. 다시 함수의 body로 돌아와 코드를 이어서 실행한다. (asyncFunctions.js 2-3번째 줄)
  9. 그런데 여기에 또 promise를 await 하는 부분이 있다. (asyncFunctions.js 3번째 줄)
  10. 그럼 다시 함수 바깥으로 나가서 코드를 실행한다. (main.js로 가지만 남은 코드는 없다.)
  11. 이번엔 실행할 코드가 더이상 없기 때문에 그냥 기다리다가 promise가 fulfilled 상태가 되면 다시 돌아와서 코드를 마저 실행한다. (asyncFunctions.js 3-4번째 줄)
  12. 콘솔창에 직원 데이터 출력 (asyncFunctions.js 4번째 줄)
그래서 이런 결과창을 갖게 되는 것이다.

 

'코린이 개념잡기 > 비동기 자바스크립트' 카테고리의 다른 글

async 함수의 리턴 값  (0) 2024.12.23
async 함수 사용시 주의사항  (0) 2024.12.23
await 문법  (0) 2024.12.22
Promise  (0) 2024.12.22
콜백의 한계점(Callback Hell)  (0) 2024.12.22

+ Recent posts