1. 자바스크립트의 콜백(Callback) 함수
콜백 함수는 자바스크립트에서 매우 중요한 개념 중 하나입니다. 기본적으로 콜백 함수는 다른 함수의 인자로 전달되어 그 함수가 실행된 이후에 호출되는 함수를 의미합니다. 자바스크립트는 비동기 처리가 필요한 작업(예: 데이터베이스 호출, 파일 읽기, HTTP 요청 등)에서 주로 콜백을 사용하여 해당 작업이 완료된 후 어떤 동작을 수행할지 정의합니다.
1.1 콜백 함수의 특징
• 비동기 작업에서 주로 사용되지만, 동기 작업에서도 사용될 수 있습니다.
• 콜백 함수는 나중에 호출될 함수를 인자로 받는 패턴으로, 특정 작업이 완료되면 해당 함수가 호출됩니다.
• 콜백 패턴은 자바스크립트의 이벤트 기반 구조와 비동기 처리에서 매우 자주 사용됩니다.
1.2 콜백 함수 예시
1. 동기 콜백 예시: 동기 작업에서의 콜백 함수는 작업이 즉시 완료되며, 함수가 순차적으로 실행됩니다.
function greeting(name) {
console.log(`Hello, ${name}`);
}
function processUserInput(callback) {
const name = "Alice";
callback(name); // 콜백 함수 호출
}
processUserInput(greeting); // "Hello, Alice"
2. 비동기 콜백 예시: 비동기 작업에서의 콜백 함수는 시간이 걸리는 작업(예: HTTP 요청) 이후에 실행됩니다.
function fetchData(callback) {
setTimeout(() => {
console.log("Data fetched!");
callback(); // 콜백 함수 실행
}, 2000); // 2초 후 데이터 가져오기를 완료
}
fetchData(() => {
console.log("Processing fetched data...");
});
// 출력:
// "Data fetched!" (2초 후)
// "Processing fetched data..."
위 코드에서 fetchData 함수는 setTimeout을 사용해 비동기 작업을 시뮬레이션하고, 작업이 끝난 후 콜백 함수가 실행됩니다.
2. 콜백 헬(Callback Hell)
**콜백 헬(Callback Hell)**은 비동기 작업을 처리할 때 중첩된 콜백 함수들로 인해 코드의 가독성이 떨어지고, 유지보수가 어려워지는 상황을 일컫는 용어입니다. 콜백 함수가 여러 번 중첩되면 코드가 계단 형태로 깊이 들어가게 되어, 코드의 흐름을 이해하고 관리하기가 어려워집니다.
2.1 콜백 헬의 원인
콜백 헬은 비동기 작업이 연속적으로 실행되어야 할 때 발생합니다. 즉, 첫 번째 작업이 완료된 후 두 번째 작업이 시작되고, 두 번째 작업이 완료된 후 세 번째 작업이 시작되는 연쇄적인 비동기 작업을 처리할 때 콜백 함수들이 여러 번 중첩되는 방식으로 작성되기 때문에 코드가 복잡해집니다.
2.2 콜백 헬의 예시
아래는 콜백 헬의 대표적인 예시입니다. 여러 비동기 작업이 순차적으로 실행되면서 코드가 중첩됩니다.
function fetchData(url, callback) {
setTimeout(() => {
console.log(`Fetched data from ${url}`);
callback();
}, 1000);
}
fetchData('url1', () => {
fetchData('url2', () => {
fetchData('url3', () => {
fetchData('url4', () => {
console.log('All data fetched');
});
});
});
});
위 코드를 보면 각 작업이 완료될 때마다 다음 비동기 작업이 중첩된 콜백 안에서 호출됩니다. 이런 구조는 코드를 수정하거나 확장하기 어려워질 뿐만 아니라, 오류 처리가 복잡해지고 유지보수가 매우 어려워집니다. 또한, 이 방식으로 작성된 코드는 콜백 피라미드나 크리스마스트리라고 불리기도 합니다.
3. 콜백 헬의 해결책
콜백 헬을 해결하기 위해 여러 방법이 고안되었습니다. 그중 가장 대표적인 해결책은 프로미스(Promise), **async/await**입니다. 이들은 콜백 함수의 중첩을 줄이고, 비동기 코드를 동기적인 방식으로 작성할 수 있게 해줍니다.
3.1 프로미스(Promise) 사용
프로미스는 비동기 작업의 성공(이행) 또는 실패(거부)를 처리하는 객체입니다. 프로미스를 사용하면 비동기 작업이 완료되었을 때 then() 메서드를 사용해 콜백을 연결할 수 있습니다.
• 프로미스 예시:
function fetchData(url) {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log(`Fetched data from ${url}`);
resolve();
}, 1000);
});
}
fetchData('url1')
.then(() => fetchData('url2'))
.then(() => fetchData('url3'))
.then(() => fetchData('url4'))
.then(() => {
console.log('All data fetched');
});
위 코드에서는 Promise 객체를 반환하여 then() 체인을 사용해 비동기 작업을 순차적으로 처리합니다. 콜백 헬에 비해 가독성이 훨씬 좋아졌고, 흐름을 쉽게 파악할 수 있습니다.
3.2 async/await 사용
**async/await**는 ES8에서 도입된 기능으로, 프로미스를 더 간결하고 동기적인 코드 스타일로 작성할 수 있게 도와줍니다. async 함수는 항상 프로미스를 반환하며, 함수 내부에서 await 키워드를 사용해 프로미스가 완료될 때까지 기다릴 수 있습니다.
• async/await 예시:
function fetchData(url) {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log(`Fetched data from ${url}`);
resolve();
}, 1000);
});
}
async function fetchAllData() {
await fetchData('url1');
await fetchData('url2');
await fetchData('url3');
await fetchData('url4');
console.log('All data fetched');
}
fetchAllData();
위 예시에서 async/await를 사용하면 코드의 흐름이 마치 동기 함수처럼 간결해집니다. 이 방식은 콜백 헬을 방지하고 비동기 코드를 읽기 쉽고, 유지보수하기 좋은 방식으로 작성할 수 있게 도와줍니다.
4. 콜백, 프로미스, async/await 비교
• 콜백: 비동기 작업 완료 후 실행될 함수를 전달하는 기본적인 방식. 중첩이 많아질 경우 콜백 헬 발생.
• 프로미스: 콜백 헬을 방지하고, then() 체인으로 비동기 작업을 순차적으로 처리 가능.
• async/await: 프로미스를 기반으로 한 구문으로, 비동기 작업을 마치 동기 코드처럼 작성할 수 있음. 가독성과 유지보수성이 가장 뛰어남.
결론
콜백 함수는 자바스크립트의 핵심 개념으로, 비동기 작업에서 필수적인 기능입니다. 하지만 여러 비동기 작업을 처리할 때 콜백 헬 문제가 발생할 수 있으며, 이를 해결하기 위해 프로미스와 async/await 같은 구조가 도입되었습니다. 이들은 코드의 가독성과 유지보수성을 크게 개선해주며, 비동기 처리를 보다 쉽게 관리할 수 있게 해줍니다.
'JavaScript' 카테고리의 다른 글
[JS] Promise (0) | 2024.09.08 |
---|---|
[JS] 자바스크립트의 동작방식(비동기,동기) (0) | 2024.09.08 |
[JS] 함수와 클래스(this) (0) | 2024.09.08 |
[JS] Scope (0) | 2024.09.08 |
[JS] Execution context (0) | 2024.09.08 |