1. 개요
JavaScript는 싱글 스레드 기반의 비동기 프로그래밍 언어로, 코드 실행 흐름을 블로킹하지 않고 작업을 처리할 수 있다. 이를 통해 네트워크 요청, 파일 읽기, 타이머 실행 등 시간이 걸리는 작업을 효율적으로 수행할 수 있다.
JavaScript에서 비동기 처리를 수행하는 주요 방법으로는 콜백(Callback), 프로미스(Promise), async/await이 있다. 각각의 방식은 코드의 가독성과 유지보수성에 영향을 미치므로, 적절한 방법을 선택하는 것이 중요하다.
이 글에서는 JavaScript의 비동기 처리 개념과 콜백, 프로미스, async/await의 동작 방식 및 차이점을 자세히 살펴본다.
2. JavaScript의 비동기 처리 개념
JavaScript는 기본적으로 단일 스레드(Single Thread) 이벤트 루프 기반으로 동작한다. 즉, 한 번에 하나의 작업만 실행할 수 있지만, 비동기 처리를 통해 여러 작업을 병렬적으로 실행하는 것처럼 보이게 할 수 있다.
(1) 동기(Synchronous) vs 비동기(Asynchronous)
- 동기 방식(Synchronous)
- 하나의 작업이 끝나야 다음 작업을 실행하는 방식
- 코드가 순차적으로 실행되므로 직관적이지만, 시간이 오래 걸리는 작업이 있을 경우 전체 프로세스가 멈출 수 있음
js복사편집console.log("작업 시작"); for (let i = 0; i < 1000000000; i++) {} // 오래 걸리는 작업 console.log("작업 완료"); - 비동기 방식(Asynchronous)
- 특정 작업을 백그라운드에서 실행하고, 결과가 완료되면 콜백 함수를 호출하는 방식
- 실행 중인 작업이 완료될 때까지 다른 작업을 수행할 수 있음
js복사편집console.log("작업 시작"); setTimeout(() => { console.log("3초 후 실행"); }, 3000); console.log("작업 완료");
위 코드에서 "작업 완료"가 "3초 후 실행"보다 먼저 출력되는 것을 확인할 수 있다.
3. 콜백(Callback) 함수
콜백 함수는 다른 함수의 인자로 전달되어 특정 작업이 완료된 후 실행되는 함수를 의미한다.
(1) 콜백 함수의 기본 개념
위 코드에서 fetchData() 함수가 2초 후 실행된 후, processData() 함수가 호출된다.
(2) 콜백 지옥(Callback Hell) 문제
콜백 함수는 간단한 작업에는 유용하지만, 여러 개의 비동기 작업이 중첩될 경우 코드가 복잡해지는 콜백 지옥(Callback Hell) 문제가 발생할 수 있다.
이처럼 콜백이 중첩되면서 코드의 가독성이 떨어지고 유지보수가 어려워지는 문제가 발생한다. 이를 해결하기 위해 등장한 것이 **프로미스(Promise)**이다.
4. 프로미스(Promise)
프로미스는 비동기 작업의 결과를 나타내는 객체로, 성공 또는 실패 여부를 나타내는 **3가지 상태(Pending, Fulfilled, Rejected)**를 가진다.
(1) 프로미스의 3가지 상태
- Pending(대기 상태): 비동기 작업이 아직 완료되지 않은 상태
- Fulfilled(성공 상태): 작업이 성공적으로 완료된 상태
- Rejected(실패 상태): 작업이 실패한 상태
(2) 프로미스의 기본 사용법
- resolve(value): 작업이 성공하면 then()으로 결과를 전달
- reject(error): 작업이 실패하면 catch()로 에러를 전달
(3) 프로미스를 활용한 비동기 처리
프로미스를 사용하면 콜백 지옥을 방지할 수 있다.
이처럼 then() 체이닝을 사용하여 가독성을 개선하고, 에러 처리를 중앙에서 관리할 수 있다. 하지만 여전히 코드가 길어지는 문제점이 있다. 이를 해결하기 위해 등장한 것이 async/await이다.
5. async/await
async/await는 프로미스를 보다 간결하게 사용할 수 있도록 도와주는 문법으로, 비동기 코드를 동기 코드처럼 작성할 수 있다.
(1) async/await의 기본 개념
- async 키워드를 함수 앞에 붙이면 해당 함수는 항상 프로미스를 반환
- await 키워드는 프로미스가 완료될 때까지 기다리고 결과를 반환
(2) async/await을 활용한 비동기 처리
(3) async/await vs 프로미스
가독성 | then() 체이닝으로 코드가 길어질 수 있음 | 동기 코드처럼 작성 가능 |
에러 처리 | catch() 블록에서 에러 처리 | try-catch 블록으로 간단하게 처리 가능 |
코드 구조 | 비동기 흐름을 추적하기 어려움 | 가독성이 높고 유지보수가 쉬움 |
6. 결론 – 어떤 방식을 사용할까?
JavaScript에서 콜백, 프로미스, async/await은 각각 장단점이 있으며, 프로젝트의 요구사항에 맞게 선택해야 한다.
- 콜백(Callback): 간단한 비동기 작업에는 적합하지만, 콜백 지옥 문제 발생 가능
- 프로미스(Promise): 비동기 작업을 체이닝할 수 있지만, 여전히 코드가 길어질 수 있음
- async/await: 가장 직관적이고 유지보수하기 쉬운 방식
현대 JavaScript 개발에서는 async/await을 기본적으로 사용하며, 예외 처리는 try-catch 문으로 관리하는 것이 일반적이다.
'IT & 웹개발' 카테고리의 다른 글
JavaScript 메모리 관리와 가비지 컬렉션(Garbage Collection) 이해하기 (0) | 2025.04.02 |
---|---|
TypeScript 도입 시 고려해야 할 점 및 장단점 (0) | 2025.04.02 |
Scss(Sass)와 Less의 차이점 및 활용법 (0) | 2025.04.02 |
Tailwind CSS vs Bootstrap – 어떤 CSS 프레임워크를 선택할까? (0) | 2025.04.01 |
CSS-in-JS vs 전통적인 CSS – 장단점 비교 (0) | 2025.04.01 |