
안녕하세요. 저번 포스팅 때 자바스크립트에서 비동기에 대해 알아본 내용을 알아봤었는데요.
오늘은 비동기를 다시 한번 알아보고 동기, async와 await에 대한 특징, 장*단점에 대해 알아볼게요.
1. 동기(Synchronous) 프로그래밍
동기 프로그래밍은 코드가 작성된 수서대로 실행되는 방식을 의미해요.
이 말은 하나의 작업이 완료되어야만 다음 코드가 실행된다는 뜻이에요.
이 방식의 장점은 단순하고 직관적인 것이에요.
코드의 실행 순서를 예측하고 쉽고, 디버깅도 간단해요.
그러나 단점은 시간이 오래 걸리는 작업이 있으면 프로그램 전체가 멈춘 것처럼 보여요.
이 때문에 응답성이 떨어지고, 사용자 경험(UX)이 나빠질 수 있어요.
// syncExample.ts
function syncTask1() {
console.log('첫 번째 작업 시작');
let sum = 0;
for (let i = 0; i < 999999999; i++) {
sum += i;
}
console.log(`첫 번째 작업 완료: ${sum}`);
}
function syncTask2() {
console.log('두 번째 작업 시작');
let sum = 0;
for (let i = 0; i < 100; i++) {
sum += i;
}
console.log(`두 번째 작업 완료: ${sum}`);
}
function runSyncExample() {
syncTask1(); // 첫 번째 작업이 끝나야 다음 작업이 시작됨
syncTask2();
}
runSyncExample();
위의 코드를 예시로 설명하자면, syncTask1()이 끝날 때까지 syncTask2()는 절대 실행되지 않아요.
즉, 긴 반복문을 포함한 첫 번째 함수 때문에 전체 프로그램이 잠시 멈춰 있는 것처럼 보일 수 있어요.
2. 비동기(Asynchronous) 프로그래밍
비동기 프로그래밍은 앞선 작업의 완료를 기다리지 않고 다음 코드를 실행하는 방식이에요.
특정 작업이 시간이 오래 걸리더라도 프로그램의 나머지 부분은 계속 진행될 수 있어요.
대표적인 비동기 처리 방식으로 setTimeout, Promise, async/await 등이 있어요.
이 방식을 사용하면, 서버에 데이터를 가져오는 동안에도 UI가 멈추지 않고 반응할 수 있어요.
// asyncExample.ts
function asyncTask1() {
setTimeout(() => {
let sum = 0;
for (let i = 0; i < 99999999; i++) {
sum += i;
}
console.log(`시간이 오래 걸리는 계산식 결과: ${sum}`);
}, 10); // 10ms 이후 실행
}
function asyncTask2() {
setTimeout(() => {
let sum = 0;
for (let i = 0; i < 100; i++) {
sum += i;
}
console.log(`두 번째 작업(첫 번째 작업을 기다리지 않음): ${sum}`);
}, 0);
}
function runAsyncExample() {
console.log('첫 번째 시작');
asyncTask1();
console.log('두 번째 시작');
asyncTask2();
console.log('모든 함수 호출 완료 (작업 완료와는 다름)');
}
runAsyncExample();
위 코드는 asyncTask1()은 setTimeout을 사용해 나중에 실행되도록 예약이 돼요.
즉, asyncTask1() 내부의 연산이 시작되기 전에 asyncTask2()와 다음 코드들이 이미 실행이 돼요.
이처럼, 비동기 코드는 프로그램 전체의 응답성을 유지하면서도 병렬적으로 여러 일을 처리할 수 있어요.
3. async와 await - 비동기 코드의 “동기식 표현”
async와 await은 Promise를 기반으로 한 비동기 처리 문법이에요.
이 문법의 가장 큰 장점은 비동기 코드를 마치 동기 코드처럼 작성할 수 있다는 것이에요.
async 키워드를 함수 앞에 붙이면, 그 함수는 자동으로 Promise를 반환해요.
그리고 await은 Promise가 처리(resolve)될 때까지 기다렸다가, 결과 값을 반환받아요.
단, await은 반드시 async 함수 내부에서만 사용할 수 있어요.
// asyncAwaitExample.ts
async function fetchUserData() {
try {
console.log('서버로부터 데이터 요청 중...');
const response = await fetch('https://jsonplaceholder.typicode.com/users/1');
if (!response.ok) {
throw new Error('데이터를 가져오는 데 실패했습니다.');
}
const data = await response.json();
console.log('가져온 데이터:', data);
} catch (error) {
console.error('데이터 요청 중 오류 발생:', error);
}
}
fetchUserData();
console.log('비동기 함수 뒤의 코드 (await를 기다리지 않음)');
위의 코드를 보시면 fetchUserData() 내부의 await fetch(...) 구문은 서버의 응답을 받을 때까지 기다려요.
하지만 함수 자체는 비동기이기 때문에, 함수 바깥의 console.log()는 즉시 실행되고,
“비동기 함수 호출 → 다음 코드 실행 → 응답 도착 후 데이터 출력”의 순서로 작동해요.
마지막으로 세 가지의 정리표예요.
| 구분 | 설명 | 장점 | 단점 | 예시 |
| 동기(Sync) | 코드가 순서대로 실행됨 | 간단하고 예측 가능 | 오래 걸리는 작업 시 전체 지연 | 반복문 계산 |
| 비동기(Async) | 이전 코드 완료를 기다리지 않음 | 응답성 향상, 효율적 처리 | 흐름 파악 어려움 | setTimeout, 이벤트 |
| async/await | Promise를 동기처럼 작성 | 가독성, 예외 처리 용이 | async 내부에서만 사용 가능 | fetch() 예제 |

여기까지 동기, 비동기, async & await에 대해 알아봤는데요.
타입스크립트에서 자바스크립트의 비동기를 알아본 이유는
TypeScript는 JavaScript를 확장한 언어이기 때문에, 동일한 개념과 문법을 사용해요.
차이는 오직 “타입 검증(Type Checking)”이 있느냐 없느냐뿐이에요.
그러니 아주 다르게 보기보다 함께 이해하는 게 더 중요한 것 같아요.
'Frontend > TypeScript' 카테고리의 다른 글
| TypeScript Generic(Advanced) (0) | 2025.11.23 |
|---|---|
| TypeScript Generic (0) | 2025.11.21 |
| TypeScript Interface (0) | 2025.11.21 |
| TypeScript Type (0) | 2025.11.20 |
| TypeScript(TS) (0) | 2025.11.19 |