JavaScript에서 비동기 작업을 처리하는 데 사용되는 두 가지 중요한 패턴은 콜백(Callback)과 프로미스(Promise)다
이 두 방식은 비동기 로직을 처리하는 방법과 관련된 개념적, 구현적 차이를 가지고 있다
cf) 비동기 작업을 처리한다라는 것은 프로그램의 실행 흐름을 멈추지 않고, 어떤 작업(보통 I/O 작업, 네트워크 요청 등)이 백그라운드에서 수행되는 동안 다른 코드의 실행을 계속 진행할 수 있도록 하는 것을 의미
즉, 특정 작업의 완료를 기다리는 동안 프로그램이 블로킹되지 않고 다른 작업을 수행할 수 있음
JavaScript에서 비동기 처리의 필요성은 주로 I/O 작업, 네트워크 요청, 타이머 설정 등 프로그램의 실행 흐름을 블록하지 않으면서도 특정 작업을 수행해야 할 때 발생한다
이러한 비동기 작업들을 적절하게 관리하지 않으면, 사용자 경험에 부정적인 영향을 미칠 수 있다
비동기 작업의 예
웹 애플리케이션에서 서버에 데이터를 요청하고 응답을 기다리는 경우를 생각해볼 수 있다
비동기 API를 사용하면, 요청이 처리되는 동안 사용자 인터페이스(UI)가 멈추지 않고,
사용자는 다른 작업을 계속할 수 있다
요청에 대한 응답이 도착하면, 응답을 처리하는 콜백 함수나 프로미스 등의 비동기 처리 메커니즘이 실행된다
콜백(Callback)
콜백은 비동기 작업이 완료된 후 실행되어야 하는 함수다
콜백 함수는 다른 함수에 인자로 전달되며, 어떤 이벤트가 발생하거나 특정 작업이 완료된 후에 호출된다
콜백 패턴은 JavaScript에서 오래전부터 사용되어 왔으며, 간단한 비동기 작업에는 잘 작동한다
하지만, 여러 비동기 작업을 연속적으로 처리해야 할 때 콜백 지옥(Callback Hell) 또는 피라미드 오브 둠(Pyramid of Doom)이라 불리는 코드의 중첩 문제가 발생할 수 있다
장점:
- 간단하고 이해하기 쉬움
- 오래된 브라우저와의 호환성이 좋음
단점:
- Callback 지옥(Callback Hell)이나 피라미드 지옥(Pyramid of Doom)으로 알려진, 중첩된 함수 호출로 인해 코드의 가독성이 떨어지고 유지보수가 어려워질 수 있음
- 에러 처리가 번거롭고, 코드 흐름을 추적하기 어려움
fs.readFile('example.txt', 'utf8', function(err, data) {
if (err) {
console.error("파일 읽기 에러", err);
return;
}
console.log(data); // 파일 읽기 성공 시 로그 출력
});
프로미스(Promise)
프로미스는 비동기 작업의 최종 완료(또는 실패)와 그 결과값을 나타내는 객체다
Promise는 세 가지 상태를 가진다: 대기(pending), 이행(fulfilled), 거부(rejected)
Promise는 Callback보다 진화한 개념으로, 비동기 작업을 보다 쉽게 처리할 수 있게 해준다
프로미스는 then, catch, finally 메소드를 사용하여 비동기 작업의 성공, 실패, 완료를 처리할 수 있는 체인을 구성할 수 있다
프로미스는 콜백보다 가독성이 좋고, 콜백 지옥 문제를 해결하는 데 유용하다
또한, 프로미스는 여러 비동기 작업을 쉽게 연결하거나 병렬로 처리할 수 있는 Promise.all 과 같은 메소드를 제공한다
장점:
- 중첩된 Callback에 비해 코드의 가독성이 좋음
- then(), catch(), finally() 메서드를 사용하여 성공, 에러 처리, 최종 실행 로직을 체인 형태로 쉽게 구성할 수 있음
- 여러 비동기 작업을 쉽게 조합하고 관리할 수 있는 Promise.all과 같은 유틸리티 함수를 제공함
단점:
- 오래된 브라우저에서는 폴리필(polyfill)이 필요할 수 있음
- 초보자에게는 Callback보다 이해하기 어려울 수 있음
const promise = new Promise((resolve, reject) => {
// 비동기 작업 수행
if (/* 작업 성공 */) {
resolve(value); // 성공 결과 전달
} else {
reject(error); // 실패 이유 전달
}
});
promise.then(value => {
// 성공 시 처리
}).catch(error => {
// 실패 시 처리
});
콜백과 프로미스의 주요 차이점
- 가독성과 구조: 콜백은 중첩되어 복잡한 코드 구조를 만들 수 있지만, 프로미스는 체이닝을 통해 가독성이 높은 코드를 작성할 수 있다
- 오류 처리: 콜백 패턴에서는 각 콜백마다 오류를 처리해야 하지만, 프로미스는 하나의 catch 블록으로 여러 비동기 작업의 오류를 캐치할 수 있다
- 비동기 작업의 조합: 프로미스는 여러 비동기 작업을 조합하고 관리하기 위한 메소드(Promise.all, Promise.race 등)를 제공하여, 콜백보다 강력한 비동기 흐름 제어를 가능하게 한다
프로미스는 ES6에 정식으로 추가되어 현대 JavaScript 비동기 프로그래밍의 표준으로 자리 잡았으며, 콜백 기반의 비동기 처리 방식의 단점을 극복하는 데 도움을 준다
(cf. async/await은 ES8에 추가됨)
'Frontend' 카테고리의 다른 글
var, let, const 차이 (0) | 2024.03.04 |
---|---|
콜백 지옥 해결법 - Promise 와 async/await (0) | 2024.03.04 |
비동기 함수 (0) | 2024.03.02 |
자바스크립트 클로저 Closure (0) | 2024.03.02 |
호이스팅 (0) | 2024.03.01 |