JavaScript에서의 async/await
이 기사에서는 JavaScript에서의 async/await에 대해 설명합니다.
YouTube Video
JavaScript에서의 async/await
JavaScript의 async (및 await)는 비동기 작업을 더 직관적이고 읽기 쉽게 작성할 수 있도록 설계된 기능입니다. 이것을 사용하면 기존의 콜백 함수와 Promise 체인의 복잡성을 줄이고, 비동기 코드를 마치 동기 코드처럼 작성할 수 있습니다.
async 함수
async는 함수를 비동기 함수로 정의하는 데 사용됩니다. async 함수는 항상 Promise를 반환합니다. async로 표시된 함수 내부에서 await를 사용하여 Promise의 결과가 반환될 때까지 기다릴 수 있습니다.
async 함수의 기본 문법
1async function myAsyncFunction() {
2 // Write asynchronous processing here
3 return 'Result'; // Return a Promise
4}이 경우 myAsyncFunction()을 호출하면 자동으로 Promise 객체가 반환됩니다. Promise가 해결되면 그 결과는 return에 의해 반환되는 값이 됩니다.
예제: 기본 async 함수
1async function greet() {
2 return 'Hello, World!';
3}
4
5greet().then((message) => {
6 console.log(message); // Displays "Hello, World!"
7});await
await는 Promise가 해결되기를 기다리는 데 사용됩니다. await를 사용하면 Promise가 해결될 때까지 실행을 일시 중지하고 Promise의 결과를 받을 수 있습니다. await는 async 함수 내부에서만 사용할 수 있습니다.
예제: await 사용 방법
1async function fetchData() {
2 // Wait for the result of the Promise
3 const data = await fetch('https://codesparklab.com/json/example.json');
4 // Wait for the asynchronous operation to complete
5 const jsonData = await data.json();
6 // Retrieve and display the data
7 console.log(jsonData);
8}
9
10fetchData();위의 예제에서 fetch 함수가 반환한 Promise를 await로 기다린 후 해당 결과를 사용하여 추가 비동기 작업을 수행합니다.
async/await로 에러 처리
async 함수 내부에서 에러가 발생하면 해당 에러는 Promise의 reject로 처리됩니다. try...catch 문을 사용하여 에러 처리를 수행할 수 있습니다.
예제: 에러 처리
1async function fetchData() {
2 try {
3 // Invalid URL
4 const data = await fetch('https://invalid.codesparklab.com/');
5 const jsonData = await data.json();
6 console.log(jsonData);
7 } catch (error) {
8 // Catch the error
9 console.error('Failed to fetch data:', error);
10 }
11}
12
13fetchData();try...catch 블록을 사용하면 비동기 작업 중 발생하는 에러를 잡아낼 수 있으며, 에러 발생 시 프로그램이 중단되지 않도록 방지할 수 있습니다.
async/await의 장점
기존의 Promise 체인과 비교했을 때, async/await는 다음과 같은 장점이 있습니다:.
- 가독성 향상
- 비동기 처리를 동기 코드처럼 작성할 수 있어, 중첩된
Promise체인과 콜백의 복잡함을 피할 수 있습니다.
- 비동기 처리를 동기 코드처럼 작성할 수 있어, 중첩된
- 더 쉬운 디버깅
- 동기 코드와 유사하기 때문에, 디버깅 및 에러 처리도 더 쉬워집니다.
- 유지보수성 향상
- 비동기 처리를 더 간단하게 작성할 수 있어, 코드의 변경과 수정이 쉬워지고 장기적인 유지보수성이 향상됩니다.
예시: Promise 체인과 async/await의 비교
Promise 체인을 사용하는 코드와 async/await를 사용하는 코드를 비교해봅시다.
1// Code using Promise chains
2function fetchDataPromise() {
3 fetch('https://codesparklab.com/json/example.json')
4 .then((response) => response.json())
5 .then((data) => {
6 console.log(data);
7 })
8 .catch((error) => {
9 console.error('Failed to fetch data:', error);
10 });
11}
12
13// Code using async/await
14async function fetchDataAsync() {
15 try {
16 const response = await fetch('https://codesparklab.com/json/example.json');
17 const data = await response.json();
18 console.log(data);
19 } catch (error) {
20 console.error('Failed to fetch data:', error);
21 }
22}async/await를 사용하면 비동기 처리를 순차적으로 작성할 수 있어 코드의 가독성이 높아집니다.
여러 비동기 작업을 동시에 실행하기
Promise.all() 또는 Promise.race()를 await와 결합하여 여러 비동기 작업을 동시에 실행하고 그 결과를 함께 처리할 수 있습니다.
Promise.all()
1async function fetchMultipleData() {
2 try {
3 const [data1, data2] = await Promise.all([
4 fetch('https://codesparklab.com/json/example1.json'),
5 fetch('https://codesparklab.com/json/example2.json')
6 ]);
7 const jsonData1 = await data1.json();
8 const jsonData2 = await data2.json();
9 console.log(jsonData1);
10 console.log(jsonData2);
11 } catch (error) {
12 console.error('Failed to fetch data:', error);
13 }
14}
15
16fetchMultipleData();Promise.all()은 여러 Promise를 동시에 해결하고 그 결과를 배열로 반환합니다. 모든 Promise가 해결될 때까지 기다리며, 하나라도 실패하면 전체가 실패로 간주됩니다.
Promise.race()
1async function fetchFastestData() {
2 try {
3 const fastestResponse = await Promise.race([
4 fetch('https://codesparklab.com/json/example1.json'),
5 fetch('https://codesparklab.com/json/example2.json')
6 ]);
7 const jsonData = await fastestResponse.json();
8 console.log('Fastest data:', jsonData);
9 } catch (error) {
10 console.error('Fetch error:', error);
11 }
12}
13
14fetchFastestData();Promise.race()는 가장 먼저 이행되거나 거부된 Promise의 결과를 반환합니다. 비동기 작업 중 가장 먼저 완료되는 작업에 대응하고 싶을 때 유용합니다. 하지만 가장 먼저 완료된 Promise가 실패할 경우, 그 에러는 즉시catch에 의해 포착됩니다.
Promise.allSettled()
1async function fetchWithAllSettled() {
2 const results = await Promise.allSettled([
3 // This URL will success
4 fetch('https://codesparklab.com/json/example1.json'),
5 // This URL will fail
6 fetch('https://invalid.codesparklab.com/')
7 ]);
8
9 results.forEach((result, index) => {
10 if (result.status === 'fulfilled') {
11 const url = result.value.url;
12 console.log(`Request ${index + 1} succeeded:`, url);
13 } else {
14 const reason = result.reason;
15 console.warn(`Request ${index + 1} failed:`, reason);
16 }
17 });
18}
19
20fetchWithAllSettled();Promise.allSettled()는 성공과 실패에 관계없이 모든 결과가 나올 때까지 기다립니다. 각 결과는{ status, value }또는{ status, reason }형태로 반환되어, 어떤 Promise가 성공했고 어떤 것이 실패했는지 알 수 있습니다.
Promise.any()
1async function fetchAnySuccessful() {
2 try {
3 const firstSuccessful = await Promise.any([
4 // This URL will fail
5 fetch('https://invalid.codesparklab.com/'),
6 // This URL will success
7 fetch('https://codesparklab.com/json/example1.json')
8 ]);
9 const jsonData = await firstSuccessful.json();
10 console.log('First successful response:', jsonData);
11 } catch (error) {
12 console.error('All fetch requests failed:', error);
13 }
14}
15
16fetchAnySuccessful();Promise.any()는 가장 먼저 성공적으로 이행된 Promise의 결과만 반환합니다. 모든 Promise가 실패할 경우에만 예외가 발생합니다. 일부 API가 신뢰할 수 없을 때, 하나라도 성공할 때까지 재시도하는 메커니즘처럼 사용할 수 있습니다.
요약
async함수: 항상 Promise를 반환하며 비동기 처리를 작성할 때 사용됩니다.await: Promise가 해결되기를 기다려 그 결과를 받을 때 사용됩니다.- 오류 처리: 비동기 처리 중 발생하는 오류를 처리하기 위해
try...catch를 사용하세요. - 여러 비동기 작업:
Promise.all()과 같은 메서드를 사용하면 여러 비동기 작업을 동시에 실행할 수 있습니다.
async/await는 비동기 처리를 위한 강력한 도구이므로 복잡한 비동기 로직을 간단하게 만들기 위해 반드시 활용하세요.
위의 기사를 보면서 Visual Studio Code를 사용해 우리 유튜브 채널에서 함께 따라할 수 있습니다. 유튜브 채널도 확인해 주세요.