async, awiat을 사용할 때는
항상 코드의 실행 순서를 생각하면서 효율적인 코드를 짜는 것이 중요하다.
async 함수를 사용할 때 주의할 점
다음 예시를 보고 async 함수를사용할 때 주의해야 하는 부분을 참고하자.
const response = await fetch('https://todo-api.fesp.shop/api/todolist/638');
API 주소 뒤에 id를 붙이면 특정 데이터에 대한 정보를 가져올 수 있는데
한번 638번부터 641번까지의 데이터를 각자 가져와서 출력해보자.
// main.js
async function printList() {
for (let i = 638; i < 642 ; i++){
const response = await fetch(`https://todo-api.fesp.shop/api/todolist/${i}`)
const data = await response.json();
console.log(data);
}
}
printList()
for문을 사용하는 printList 함수를 정의하였고
템플릿 문자열을 이용해서 request를 보내고 있다.
실행 해보면 id가 638번부터 641번까지 정상적으로 출력되는 것을 확인할 수 있다.
그런데 딱 봐도 코드가 비효율적으로 보이는데
for문을 풀어서 쓰면 아래와 같은 코드의 형태가된다.
// for문을 풀어서 쓸경우
async function printList() {
const response = await fetch(`https://todo-api.fesp.shop/api/todolist/638`)
const data = await response.json();
console.log(data);
const response = await fetch(`https://todo-api.fesp.shop/api/todolist/639`)
const data = await response.json();
console.log(data);
const response = await fetch(`https://todo-api.fesp.shop/api/todolist/640`)
const data = await response.json();
console.log(data);
}
printList()
이 코드는 결국 수많은 await문을 순차적으로 실행하게 된다.
첫 번째 await문 (const response = await fetch(...638)) 을 기다리는 동안 함수 바깥으로 나갔다가
다시 돌아와서 두 번째 await (const data = await response.json()) 을 기다리고
또 돌아와서 데이터를 출력한 다음 (console.log(data))
그 아래에 있는 await (await fetch(...639)) 을 기다린다.
이런식으로 비동기 작업을 하나씩 순서대로 기다리기 때문에 당연히 오래걸린다.
좀 더 효율적으로, 비동기 작업을 하나하나 기다리지 말고
한꺼번에 request를 보내고 결과를 기다리는 방법을 채택해야 한다.
코드를 다음과 같이 수정한다.
// main.js
async function printList(id) {
const response = await fetch(`https://todo-api.fesp.shop/api/todolist/${id}`)
const data = await response.json();
console.log(data);
}
for (let i = 638; i < 642 ; i++){
printList(i)
}
파라미터로 id를 받게하고 for문을 함수 바깥으로 옮겨주는데
언뜻 보면 전과 비슷한 코드로 보이지만
이 방법이 훨씬 더 효율적이며
출력 결과를 보면 이전보다 더 빨리 끝나는 것을 볼 수 있다. (0.542sec -> 0.492sec)
한 가지 주의해야하는 점은
위 아래의 결과를 놓고 봐도 출력 순서가 뒤죽박죽이라는 점이다.
이러한 방법이 빠른 이유는 다음과 같다.
for문을 풀어서 쓰면 아래의 코드와 같아지는데
// for문을 풀어서 쓸경우
async function printList(id) {
const response = await fetch(`https://todo-api.fesp.shop/api/todolist/${id}`)
const data = await response.json();
console.log(data);
}
printList(638);
printList(639);
printList(640);
printList(641);
가장 먼저 printList(638)을 실행할텐데
함수 안에서 fetch request를 보내고 기다리는 동안 바깥으로 나온다.
그 아래에 있는 코드 printList(639) 이므로
fetch todolist/639의 request를 보내고 다시 바깥으로 나온다.
이런식으로 640, 641의 request를 보내는데
중요한 점은 request의 결과를 기다리지 않고 바로 다음 URL에 request를 보낸다는 것이며
4개의 request를 거의 동시에 보냈기 때문에
response도 거의 동시에 돌아오고
결국 하나의 request를 처리하는 데 걸리는 시간만큼만 기다리면 된다.
이때 request를 보낸 순서대로 response가 돌아온다는 보장은 없기 때문에
출력 순서가 뒤죽박죽인 것이다.
하지만 비동기 작업을 처리하는 순서는 중요하지 않고
작업들을 최대한 빨리 끝내는 것이 목표라면 이 방법을 사용하는 것이 좋다.
이제 response가 돌아온 다음에는 response를 parsing하고
parsing 작업이 끝나는 대로 data를 출력할 것이다.
async 함수를 이용해서 비동기 프로그램을 짤 때는
어디에 await이 있고 어떤 순서로 코드가 실행되는지 파악하는 것이 중요하다.
'JS' 카테고리의 다른 글
(9) Asynchronous JavaScript - try catch로 비동기 오류 처리 (0) | 2025.01.07 |
---|---|
(8) Asynchronous JavaScript - async 함수의 리턴값 (0) | 2025.01.03 |
(6) Asynchronous JavaScript - Promies 다루는 방법 (0) | 2025.01.02 |
(5) Asynchronous JavaScript - Promies (0) | 2025.01.01 |
(1) ~ (4) Callback 정리 (0) | 2025.01.01 |