1. 비동기란 무엇인가
자바스크립트는 단일 스레드(Single Thread) 로 동작한다.
즉, 한 번에 한 가지 작업만 처리할 수 있다.
하지만 실제 웹 환경에서는 동시에 많은 일이 일어난다.
예를 들어,
- 서버에서 데이터를 불러오면서
- 버튼 클릭도 감지하고
- 애니메이션도 실행되어야 한다.
이걸 가능하게 하는 게 바로 비동기 처리(Asynchronous Processing) 다.
💡 “비동기란, 기다리지 않고 다음 일을 진행하는 프로그래밍 방식”이다.
2. 동기 vs 비동기
console.log("1️⃣ 첫 번째");
console.log("2️⃣ 두 번째");
console.log("3️⃣ 세 번째");
이건 동기(Synchronous) — 순서대로 실행된다.
반면, setTimeout 같은 비동기 코드를 섞으면 결과가 달라진다.
console.log("1️⃣ 시작");
setTimeout(() => console.log("2️⃣ 1초 뒤 실행"), 1000);
console.log("3️⃣ 종료");
출력:
1️⃣ 시작
3️⃣ 종료
2️⃣ 1초 뒤 실행
→ “기다리지 않고 다음 줄로 넘어갔다.”
이게 바로 비동기 실행의 본질이다.
3. 자바스크립트의 실행 구조 — 콜 스택과 이벤트 루프
자바스크립트는 아래 구조로 동작한다.
📦 Call Stack (호출 스택)
📬 Event Queue (이벤트 대기열)
🔁 Event Loop (순환하며 대기열을 비움)
- Call Stack: 즉시 실행되는 코드가 쌓이는 곳
- Event Queue: setTimeout, 이벤트, Promise 등의 콜백이 기다리는 곳
- Event Loop: 스택이 비면 대기열에서 하나씩 꺼내 실행
즉, 자바스크립트는 실제로 “동시에 실행되는 것처럼 보이지만”,
사실은 순차적으로 빠르게 돌면서 비동기 콜백을 처리하는 구조야.
4. setTimeout / setInterval
비동기의 가장 기본형.
console.log("A");
setTimeout(() => console.log("B"), 2000);
console.log("C");
결과:
A
C
B
✅ setTimeout()은 지정된 시간 후 실행
✅ setInterval()은 일정 간격으로 반복 실행
let count = 0;
const timer = setInterval(() => {
console.log(`타이머 실행: ${++count}`);
if (count === 3) clearInterval(timer);
}, 1000);
5. 콜백 함수의 한계
비동기 코드를 콜백만으로 처리하면 이런 코드가 된다.
getUser(() => {
getPosts(() => {
getComments(() => {
console.log("모든 데이터 로드 완료!");
});
});
});
이런 구조를 “콜백 지옥(Callback Hell)”이라 부른다.
→ 가독성, 유지보수, 디버깅 모두 최악.
이를 해결하기 위해 등장한 게 Promise 다.
6. Promise — 비동기의 약속
Promise는 “나중에 결과를 돌려줄게”라는 약속 객체다.
const promise = new Promise((resolve, reject) => {
const success = true;
setTimeout(() => {
success ? resolve("✅ 성공!") : reject("❌ 실패!");
}, 1000);
});
promise
.then((result) => console.log(result))
.catch((err) => console.error(err))
.finally(() => console.log("작업 완료"));
✅ then : 성공 시 실행
✅ catch : 실패 시 실행
✅ finally : 무조건 실행
7. Promise 체이닝
비동기 작업을 순서대로 연결할 수도 있다.
getUser()
.then((user) => getPosts(user.id))
.then((posts) => getComments(posts[0].id))
.then((comments) => console.log("결과:", comments))
.catch((err) => console.error("에러:", err));
→ 콜백 지옥 대신 “논리적 흐름” 으로 읽힌다.
8. async / await — 비동기를 동기처럼 쓰는 문법
async/await은 Promise 기반 문법을 더 직관적으로 만든 문법이다.
function getData() {
return new Promise((resolve) => {
setTimeout(() => resolve("서버 응답 완료!"), 1000);
});
}
async function main() {
console.log("데이터 요청 중...");
const result = await getData();
console.log(result);
console.log("로직 종료");
}
main();
출력:
데이터 요청 중...
(1초 후)
서버 응답 완료!
로직 종료
✅ await은 Promise가 끝날 때까지 기다린다.
✅ async 함수 안에서만 사용할 수 있다.
✅ 코드 가독성이 획기적으로 개선된다.
9. 에러 처리
비동기에서 에러를 다루는 방법은 try-catch가 핵심이다.
async function main() {
try {
const res = await fetch("https://invalid.url");
const data = await res.json();
console.log(data);
} catch (error) {
console.error("에러 발생:", error.message);
}
}
main();
✅ 비동기 함수에서도 try-catch 문법으로 안전하게 처리 가능.
10. 실무 예시 — API 데이터 불러오기
async function loadPosts() {
const res = await fetch("https://jsonplaceholder.typicode.com/posts?_limit=3");
const posts = await res.json();
const container = document.createElement("div");
posts.forEach((p) => {
const item = document.createElement("div");
item.innerHTML = `
${p.title}
${p.body}
`;
container.appendChild(item);
});
document.body.appendChild(container);
}
loadPosts();
✅ 실제 서비스에서 “데이터 불러오기 → DOM 출력”의 기본 패턴이다.
✅ React의 useEffect + fetch도 사실상 이 구조를 단순화한 것.
11. Promise.all — 병렬 처리
여러 비동기 작업을 동시에 실행하고 모두 끝날 때까지 기다릴 수 있다.
async function loadData() {
const [users, posts] = await Promise.all([
fetch("https://jsonplaceholder.typicode.com/users").then((r) => r.json()),
fetch("https://jsonplaceholder.typicode.com/posts").then((r) => r.json()),
]);
console.log("유저 수:", users.length);
console.log("포스트 수:", posts.length);
}
loadData();
✅ 병렬 실행으로 성능 향상
✅ API 연속 호출이 아닌, 독립적인 요청 처리에 적합
12. 정리
개념 설명
| 비동기 | 기다리지 않고 다음 코드 실행 |
| 콜백 | 기본 구조지만 중첩 문제 발생 |
| Promise | 콜백 지옥 해결, 체이닝 가능 |
| async/await | 비동기를 동기처럼 표현 |
| try/catch | 비동기 오류 제어 |
| Promise.all | 여러 비동기 병렬 처리 |
13. 마무리
이제 자바스크립트의 진짜 흐름 제어 방식을 이해했다.
async/await을 완벽히 다루면,
React의 데이터 패칭, Next.js의 서버 액션, API 통신도 어렵지 않다.
자바스크립트는 “언제 실행되는가”를 이해할 때 비로소 통제할 수 있다.
비동기를 제어할 줄 아는 개발자는, 코드를 기다리게 만들 수 있다.
'frontend > javascript' 카테고리의 다른 글
| 🟨 2-10. Axios 완전 정복 — fetch보다 강력한 HTTP 클라이언트 사용법과 실무 패턴 (0) | 2025.11.07 |
|---|---|
| 🟨 2-9. fetch 완벽 가이드 — API 데이터 요청, JSON 응답 처리, 에러 핸들링까지 한 번에 배우기 (0) | 2025.11.07 |
| 🟨 2-7. 이벤트 위임(Event Delegation) — 반복되는 이벤트 코드를 깔끔하게 정리하는 기술 (0) | 2025.11.07 |
| 🟨 2-6. DOM 완벽 이해 — 자바스크립트로 HTML 요소를 자유자재로 조작하는 법 (0) | 2025.11.07 |
| 🟨 2-5. JSON 다루기 완벽 가이드 — 자바스크립트에서 데이터를 구조적으로 관리하는 법 (0) | 2025.11.07 |