제6장: 비동기 자바스크립트 (콜백, 프로미스, async/await, 오류 처리)
자바스크립트 비동기 처리의 이해
현대 자바스크립트 개발에서 비동기 프로그래밍은 필수입니다. 서버에서 데이터를 받아오거나, 파일을 읽어들이는 등 시간이 걸리는 작업을 할 때 프로그램 전체가 멈추지 않고 다음 동작을 계속하기 위해 비동기 방식을 사용합니다.
콜백 함수: 최초의 비동기 패턴
콜백 함수는 비동기 작업이 끝난 뒤 실행되는 함수를 의미합니다. 데이터 요청처럼 완료 시점을 알 수 없는 작업에서, 처리 완료 후 콜백을 호출하여 결과를 전달합니다. 예를 들어 setTimeout
함수에서 두 번째 인자에 전달하는 함수가 대표적인 콜백입니다. 하지만 콜백이 중첩되기 시작하면 가독성이 떨어지고, 에러 처리나 흐름 관리가 어려워집니다. 이를 흔히 콜백 지옥(callback hell)이라고 부릅니다.
프로미스: 더 나은 비동기 방식
비동기 코드의 복잡함을 줄이기 위해 프로미스(Promise)가 도입되었습니다. 프로미스는 "언젠가 값을 제공하겠다"는 약속 개념을 코드에 반영합니다. 비동기 함수가 값을 약속(Pending)하고, 작업이 끝나면 이행(Fulfilled) 혹은 거부(Rejected) 상태로 바뀝니다. 각각의 결과는 then
과 catch
메서드로 받아서 처리할 수 있습니다.
fetchData()
.then(result => {
// 성공 시 결과 처리
})
.catch(error => {
// 실패 시 에러 처리
});
프로미스를 사용하면 각 단계마다 명확하게 후처리를 연결할 수 있어 코드의 구조가 훨씬 읽기 쉬워집니다.
async/await: 동기식 코드처럼 비동기 제어하기
ES2017에서 도입된 async
와 await
는 프로미스 기반 비동기 처리를 마치 동기 코드처럼 쓸 수 있게 해줍니다. async
함수 내에서 await
을 만나면, 해당 작업의 끝을 기다렸다가 다음 동작을 이어갑니다. 이는 복잡한 비동기 플로우를 한눈에 파악하기 쉽게 만들어줍니다.
async function loadUser() {
try {
const user = await fetchUser();
console.log(user);
} catch (err) {
console.error('오류 발생:', err);
}
}
여러 비동기 작업이 연속적으로 필요할 때, 각 단계마다 코드를 일렬로 적으면 동기 코드와 비슷하게 동작 흐름을 이해할 수 있습니다.
비동기 에러 처리: try/catch의 역할
콜백 방식에서는 에러가 첫 번째 인자로 전달되는 경우가 많으며, 프로미스와 async/await의 경우엔 catch
또는 try/catch
구문을 사용합니다. 특히 async/await
에서는 동기 코드의 예외 처리와 유사하게 try 블록으로 감싸고 catch 블록에서 에러를 한 곳에서 처리할 수 있습니다. 덕분에 에러가 어디서 발생했는지 쉽게 추적할 수 있고, 다양한 후처리 로직을 명확하게 적용할 수 있습니다.
현실 세계의 비동기 제어: 실전 팁
여러 개의 비동기 작업을 동시에 처리하고 싶을 때는 Promise.all
이나 Promise.race
등 다양한 유틸리티 메서드를 사용합니다. 예를 들어 여러 서버에서 데이터를 받아와야 하는 상황에서 각각의 결과를 한꺼번에 기다릴 수 있습니다. 또한, 에러가 발생할 때 특정 작업만 실패하고 나머지는 문제없이 처리할 수 있게 분기 처리를 세밀하게 구현할 수 있습니다.
마치며
콜백에서 프로미스, async/await로 발전하면서 자바스크립트 비동기 프로그래밍은 훨씬 강력하고 읽기 쉬워졌습니다. 각각의 방법이 가진 한계와 장점을 익히고, 상황에 맞는 방식을 선택하세요. 견고한 에러 처리와 명확한 코드 구조를 갖춘 비동기 코드는 실전에서 반드시 필요한 중급 역량입니다.