비동기/대기 (Async/Await)
자바스크립트(JavaScript)에서 비동기/대기(Async/Await)는 프로미스(Promises)를 기반으로 비동기 작업(Asynchronous Operations)을 처리하는 문법이다. 비동기 코드를 동기 코드처럼 작성할 수 있게 하여 가독성을 높인다. 비동기/대기(Async/Await)의 정의, 동작 방식, 프로미스(Promises)와의 차이점, 그리고 사용 사례를 예제를 통해 확인한다.
비동기/대기(Async/Await)는 프로미스(Promises)의 syntactic sugar로, 비동기 프로그래밍(Asynchronous Programming)을 간소화한다. 자바스크립트(JavaScript)의 이벤트 루프(Event Loop)와 결합하여 비동기 작업의 흐름을 제어한다.
비동기/대기(Async/Await)란 무엇인가?
비동기/대기(Async/Await)는 async
와 await
키워드를 사용해 비동기 작업(Asynchronous Operations)을 처리한다. async
는 함수가 프로미스(Promises)를 반환하도록 정의하며, await
는 프로미스(Promises)가 해결(Resolved)될 때까지 실행을 일시 중지한다. 기본적인 예제를 살펴보자:
async function fetchData() {
return "데이터";
}
fetchData().then(data => console.log(data)); // 데이터
async
함수는 항상 프로미스(Promises)를 반환한다. await
를 사용한 예제는 다음과 같다:
async function delayedMessage() {
const promise = new Promise(resolve => setTimeout(() => resolve("완료"), 1000));
const result = await promise;
console.log(result);
}
delayedMessage(); // 1초 후 "완료"
await
는 프로미스(Promises)가 이행(Fulfilled)되기를 기다린 후 결과를 반환한다. await
는 async 함수 내에서만 사용 가능하다.
비동기/대기(Async/Await)의 동작 방식
비동기/대기(Async/Await)는 프로미스(Promises)를 기반으로 작동하며, 비동기 작업을 순차적으로 처리한다. await
는 코드 실행을 일시 중지하고, 프로미스(Promises)가 완료되면 값을 반환한다.
동작 방식을 예제로 확인한다:
async function sequence() {
const first = await new Promise(resolve => setTimeout(() => resolve(1), 1000));
const second = await new Promise(resolve => setTimeout(() => resolve(first + 1), 1000));
console.log(second);
}
sequence(); // 2초 후 2
위 코드에서 await
는 각 프로미스(Promises)가 해결될 때까지 기다리며, 순차적으로 값을 처리한다. 에러 처리를 포함한 예제는 다음과 같다:
async function withError() {
try {
const result = await new Promise((_, reject) => setTimeout(() => reject("오류"), 1000));
console.log(result);
} catch (error) {
console.log(error);
}
}
withError(); // 1초 후 "오류"
try/catch
블록은 await
로 발생한 에러를 처리한다.
비동기/대기(Async/Await)와 프로미스(Promises)의 차이점
비동기/대기(Async/Await)는 프로미스(Promises)와 비동기 코드 작성 방식에서 차이가 있다.
1. 코드 구조
- 프로미스: then
체인을 사용한다.
function fetchPromise() {
return new Promise(resolve => setTimeout(() => resolve("데이터"), 1000))
.then(data => console.log(data));
}
fetchPromise(); // 1초 후 "데이터"
- 비동기/대기: 동기처럼 작성한다.
async function fetchAsync() {
const data = await new Promise(resolve => setTimeout(() => resolve("데이터"), 1000));
console.log(data);
}
fetchAsync(); // 1초 후 "데이터"
2. 에러 처리
- 프로미스: catch
로 처리한다.
new Promise((_, reject) => setTimeout(() => reject("실패"), 1000))
.catch(err => console.log(err)); // 1초 후 "실패"
- 비동기/대기: try/catch
를 사용한다.
async function handleError() {
try {
await new Promise((_, reject) => setTimeout(() => reject("실패"), 1000));
} catch (err) {
console.log(err);
}
}
handleError(); // 1초 후 "실패"
사용 사례
비동기/대기(Async/Await)의 활용 사례를 예제를 통해 확인한다.
1. 데이터 요청
async function getUser(id) {
const response = await new Promise(resolve => setTimeout(() => resolve({ id, name: "철수" }), 1000));
console.log(response.name);
}
getUser(1); // 1초 후 "철수"
2. 순차 처리
async function steps() {
const step1 = await new Promise(resolve => setTimeout(() => resolve("1단계"), 1000));
const step2 = await new Promise(resolve => setTimeout(() => resolve(`${step1}, 2단계`), 1000));
console.log(step2);
}
steps(); // 2초 후 "1단계, 2단계"
3. 병렬 요청
async function parallel() {
const [result1, result2] = await Promise.all([
new Promise(resolve => setTimeout(() => resolve("첫 번째"), 1000)),
new Promise(resolve => setTimeout(() => resolve("두 번째"), 2000))
]);
console.log(result1, result2);
}
parallel(); // 2초 후 "첫 번째 두 번째"
4. 에러 복구
async function recover() {
try {
await new Promise((_, reject) => setTimeout(() => reject("문제"), 1000));
} catch (err) {
console.log("복구됨");
}
}
recover(); // 1초 후 "복구됨"
5. 반복 요청
async function fetchMultiple() {
const ids = [1, 2, 3];
for (const id of ids) {
const data = await new Promise(resolve => setTimeout(() => resolve(id * 2), 1000));
console.log(data);
}
}
fetchMultiple(); // 1초 간격으로 2, 4, 6
6. 조건부 실행
async function conditionalFetch(flag) {
if (flag) {
const result = await new Promise(resolve => setTimeout(() => resolve("참"), 1000));
console.log(result);
} else {
console.log("거짓");
}
}
conditionalFetch(true); // 1초 후 "참"
7. 타임아웃 처리
async function withTimeout() {
const promise = new Promise(resolve => setTimeout(() => resolve("늦음"), 2000));
const timeout = new Promise((_, reject) => setTimeout(() => reject("시간 초과"), 1000));
const result = await Promise.race([promise, timeout]);
console.log(result);
}
withTimeout().catch(err => console.log(err)); // 1초 후 "시간 초과"
8. 외부 API 호출
async function fetchApi() {
try {
const response = await fetch("https://jsonplaceholder.typicode.com/posts/1");
const data = await response.json();
console.log(data.title);
} catch (err) {
console.log("API 오류");
}
}
fetchApi(); // 실제 API 응답에 따라 출력
성능과 한계
장점
- 가독성: 비동기 코드를 동기처럼 작성한다.
- 에러 처리: try/catch
로 통합된다.
- 흐름 제어: 작업 순서를 명확히 한다.
한계
- 병렬성: 순차 실행이 기본이므로 병렬 처리를 별도로 구현해야 한다.
- 오용: await
를 남용하면 성능이 저하될 수 있다.
불필요한 await 사용을 피하고, 병렬 작업에는 Promise.all을 고려한다.
마무리
비동기/대기(Async/Await)는 자바스크립트(JavaScript)에서 비동기 작업(Asynchronous Operations)을 처리하는 유용한 문법이다. 사용 사례를 통해 그 활용 방식을 살펴봤다.
'코딩 공부 > 자바스크립트' 카테고리의 다른 글
37. 자바스크립트 객체 생성 패턴 (Object Creation Patterns) (1) | 2025.03.08 |
---|---|
36. 자바스크립트 함수 인자 처리 (Handling Function Arguments) (1) | 2025.03.08 |
34. 자바스크립트 프로미스 (Promises) (1) | 2025.03.07 |
33. 자바스크립트 클로저 (Closures) (1) | 2025.03.07 |
32. 자바스크립트 고차 함수 (Higher-Order Functions) (0) | 2025.03.07 |