자바스크립트 비동기 기초
지금까지 변수와 데이터 타입, 조건문과 반복문, 함수, 배열, 객체, 이벤트를 배웠다면, 이번엔 비동기 프로그래밍을 배워볼 거다. 비동기는 자바스크립트에서 시간이 걸리는 작업(예: 서버 요청, 파일 읽기)을 기다리지 않고 동시에 처리할 수 있게 해주는 핵심 개념으로, 현대 웹 개발에서 필수적이다. 비동기를 잘 이해하면 느린 작업에도 반응 빠른 애플리케이션을 만들 수 있다.
내가 처음 코딩을 배울 때 서버에서 데이터를 가져오는데 페이지가 멈추는 경험을 했는데, 비동기를 배우고 나니까 이런 문제를 해결할 수 있었다. 이번 글에선 비동기의 정의와 필요성, 콜백 함수, 프로미스, async/await 사용법, 그리고 실습 예제를 상세히 다룰 거다. 천천히 따라오면서 콘솔이나 HTML 파일에서 실행해보면 비동기의 매력을 느낄 수 있을 거다. 비동기는 자바스크립트가 단일 스레드 언어임에도 불구하고 멀티태스킹처럼 동작하게 해주는 강력한 도구다.
앞서 배운 개념들과 비동기를 결합하면 더 실용적인 코드를 작성할 수 있다. 예를 들어, 이벤트로 버튼 클릭을 감지하고, 비동기로 서버에서 데이터를 가져와서 객체에 저장한 뒤, 배열로 화면에 표시하는 작업을 쉽게 할 수 있다.
비동기란 무엇인가?
비동기(Asynchronous)는 코드가 순차적으로 실행되지 않고, 시간이 걸리는 작업을 기다리지 않고 다음 작업을 먼저 처리하는 방식이다. 자바스크립트는 기본적으로 단일 스레드(Single-Threaded) 언어로, 한 번에 한 가지 작업만 처리한다. 예를 들어, 서버에서 데이터를 가져오는 데 5초가 걸린다면 동기(Synchronous) 방식으론 그 5초 동안 아무것도 못 하고 기다려야 한다. 하지만 비동기 방식은 데이터를 요청한 뒤 기다리는 동안 다른 코드를 실행할 수 있다.
예를 들어, 동기 방식은 이렇게 동작한다:
console.log("시작");
function slowTask() {
let start = Date.now();
while (Date.now() - start < 3000) {} // 3초 대기
console.log("느린 작업 완료");
}
slowTask();
console.log("끝");
// 출력: "시작" -> 3초 후 -> "느린 작업 완료" -> "끝"
위 코드는 3초 동안 멈춘 뒤 다음 줄로 넘어간다. 내가 처음 이걸 봤을 때 답답했는데, 비동기는 이런 문제를 해결한다:
console.log("시작");
setTimeout(function() {
console.log("느린 작업 완료");
}, 3000);
console.log("끝");
// 출력: "시작" -> "끝" -> 3초 후 -> "느린 작업 완료"
setTimeout
은 비동기 함수로, 3초 후에 실행할 코드를 예약하고 바로 다음 줄로 넘어간다. 내가 처음 비동기를 접했을 때 코드가 순서대로 안 돼서 혼란스러웠지만, 나중에 보니 이게 자바스크립트의 강점이었다.
비동기는 서버 요청, 파일 읽기, 타이머 같은 시간이 걸리는 작업에서 필수다. 실무에선 사용자 인터페이스가 멈추지 않게 하고, 데이터를 백그라운드에서 가져오거나, 여러 작업을 병렬로 처리할 때 많이 쓴다. 자바스크립트의 비동기는 이벤트 루프(Event Loop)라는 메커니즘으로 동작하는데, 이는 나중에 더 깊이 다룰 예정이다.

콜백 함수로 비동기 처리
비동기를 처리하는 가장 기본적인 방법은 콜백 함수(Callback Function)다. 콜백은 작업이 끝난 후 실행할 함수를 전달하는 방식이다.
기본 예제
console.log("시작");
setTimeout(function() {
console.log("3초 후 실행");
}, 3000);
console.log("끝");
// 출력: "시작" -> "끝" -> 3초 후 -> "3초 후 실행"
setTimeout
에 전달된 함수가 콜백이다. 내가 처음 콜백을 썼을 때 타이밍이 신기했는데, 비동기의 기본을 이해하는 데 큰 도움이 됐다.
중첩 콜백 문제
콜백을 여러 번 쓰면 코드가 복잡해진다(Callback Hell):
setTimeout(function() {
console.log("첫 번째 작업");
setTimeout(function() {
console.log("두 번째 작업");
setTimeout(function() {
console.log("세 번째 작업");
}, 1000);
}, 1000);
}, 1000);
내가 처음 이걸 봤을 때 들여쓰기가 너무 깊어져서 읽기 힘들었다. 이를 해결하기 위해 나중에 프로미스와 async/await가 나왔다.
프로미스로 비동기 개선
프로미스(Promise)는 ES6에서 도입된 비동기 처리 방식으로, 콜백 헬을 피하고 코드를 더 깔끔하게 만든다. 프로미스는 작업의 상태를 나타내는 객체다.
프로미스 상태
- Pending
: 작업 진행 중.
- Fulfilled
: 작업 성공.
- Rejected
: 작업 실패.
기본 사용
let promise = new Promise(function(resolve, reject) {
setTimeout(function() {
resolve("성공!");
}, 2000);
});
promise.then(function(result) {
console.log(result); // 2초 후 "성공!"
});
resolve
는 성공 시 호출, reject
는 실패 시 호출한다. 내가 처음 프로미스를 썼을 때 체이닝이 가능하다는 점이 인상 깊었다:
promise
.then(function(result) {
console.log(result);
return "다음 단계";
})
.then(function(next) {
console.log(next);
})
.catch(function(error) {
console.log("에러: ", error);
});
// 출력: "성공!" -> "다음 단계"
catch
로 에러를 잡을 수 있어서 안정적이다.
async/await로 더 간결하게
async/await는 ES2017에서 추가된 비동기 방식으로, 프로미스를 더 직관적으로 쓸 수 있게 한다.
기본 사용
async function fetchData() {
let promise = new Promise((resolve) => {
setTimeout(() => resolve("데이터 도착!"), 2000);
});
let result = await promise;
console.log(result);
}
fetchData(); // 2초 후 "데이터 도착!"
async
함수 안에서 await
를 쓰면 프로미스가 완료될 때까지 기다린다. 내가 처음 이걸 썼을 때 동기 코드처럼 보이는데 비동기라 놀랐다.
에러 처리
async function fetchData() {
try {
let promise = new Promise((resolve, reject) => {
setTimeout(() => reject("에러 발생!"), 2000);
});
let result = await promise;
console.log(result);
} catch (error) {
console.log("에러: ", error);
}
}
fetchData(); // 2초 후 "에러: 에러 발생!"
try-catch
로 깔끔하게 에러를 잡는다.

실습 예제
비동기를 활용한 실습을 해보자:
<button id="fetchButton">데이터 가져오기</button>
<div id="result"></div>
<script>
function fetchData() {
return new Promise((resolve) => {
setTimeout(() => resolve("서버에서 온 데이터"), 2000);
});
}
async function loadData() {
let button = document.getElementById("fetchButton");
let resultDiv = document.getElementById("result");
button.addEventListener("click", async () => {
resultDiv.textContent = "로딩 중...";
try {
let data = await fetchData();
resultDiv.textContent = data;
} catch (error) {
resultDiv.textContent = "에러 발생!";
}
});
}
loadData();
</script>
버튼 클릭 시 2초 후 데이터를 표시한다. 이벤트와 비동기를 결합한 예제다.
주의할 점
콜백 중첩은 피하고, 프로미스나 async/await를 쓰자. 비동기 작업은 순서를 잘 관리해야 한다. 에러 처리를 반드시 추가하자.
결론
이번 포스팅에서 자바스크립트 비동기의 기초를 다뤘다. 콜백, 프로미스, async/await를 배웠으니 이제 시간이 걸리는 작업도 효율적으로 처리할 수 있다. 다음 글에선 비동기의 이벤트 루프와 고급 활용법을 알아보자.
'코딩 공부 > 자바스크립트' 카테고리의 다른 글
10. 자바스크립트 DOM 조작 (0) | 2025.02.26 |
---|---|
9. 자바스크립트 이벤트 루프와 비동기 고급 활용 (0) | 2025.02.26 |
7. 자바스크립트 이벤트 기초 (0) | 2025.02.25 |
6. 자바스크립트 객체 기초 (1) | 2025.02.24 |
5. 자바스크립트 배열 기초 (0) | 2025.02.24 |