비동기 처리를 위한 Promise/EventEmitter 도입의 고충

seungjun.dev·2025년 8월 11일

Node.js

목록 보기
9/13

Promise vs EventEmitter

둘은 모두 비동기 프로그래밍에 사용된다.
그러나 처리하는 대상과 방식에 근본적인 차이가 있다.

구분PromiseEventEmitter
주요 목적비동기 작업의 최종 결과(성공/실패) 처리이벤트 기반 프로그래밍 및 다중 이벤트 처리
값 처리단일 값 또는 에러를 한 번만 반환하나의 이벤트에 대해 여러 값을 여러 번 전달 가능
실행 횟수한 번 resolve 또는 reject 되면 상태가 고정됨 (일회성)동일한 이벤트를 여러 번 emit(발생)시킬 수 있음 (다회성)
리스너.then(), .catch(), .finally()로 단일 콜백 체인을 구성on() 메서드로 여러 개의 리스너를 등록하여 동시에 처리 가능
주요 사용 사례파일 읽기, HTTP API 요청 등 결과가 한 번만 나오는 비동기 작업사용자 입력, 웹소켓 통신, 데이터 스트리밍 등 반복적으로 발생하는 이벤트 처리

위와 같은 차이가 있으나 둘은 상호 보완적으로 사용될 수 있다.

예를 들어, Promise를 사용해 비동기 작업을 처리한 후, 그 결과(성공/실패)를 바탕으로 EventEmitter를 통해 이벤트를 발생시킬 수 있다.

이렇게 하면 비동기 작업의 상태 관리는 Promise로 명확하게 하고, 결과에 따른 후속 처리는 EventEmitter를 통해 유연하게 분리할 수 있어 효율적인 구현이 가능하다.

Promise

1. 추상적인 상태 개념

Promise는 pending, fulfilled, rejected 세 가지 상태를 갖는데,
이 '상태'라는 개념이 처음에는 추상적으로 느껴질 수 있다.

코드가 직접적인 값을 반환하는 것이 아니라, 값을 감싸고 있는 상태를 가진 상자를 반환하는 격이라 이해하는 데 시간이 걸린다.

2. 놓치기 쉬운 에러 처리

Promise 체인의 큰 함정이다.
.then()으로 이어진 여러 작업 중 어디에선가 에러가 발생했을 때, 체인 마지막에 .catch()를 붙여주지 않으면 에러가 아무런 알림 없이 조용히 무시된다.

3. Promise 지옥

Promise는 콜백 지옥을 해결하기 위해 나왔지만, .then() 내부에 또다른 .then()을 중첩시켜 '프로미스 지옥'을 만들 가능성이 있다.

EventEmitter

1. 메모리 누수

on()으로 이벤트 리스너를 등록한 뒤, 더 이상 필요없을 때 off()removeListener()로 해제해주지 않으면 해당 리스너는 메모리에 계속 남아있게 된다.

2. 문자열 기반 이벤트 이름의 위험성

이벤트는 보통 'success', 'error' 와 같은 문자열로 구분된다.
만약 이벤트를 발생시키는 쪽(emit)이나 구독하는 쪽(on)에서 오타를 낸다면 아무런 에러도 발생하지 않고 그저 이벤트가 동작하지 않을 뿐이다.

컴파일러나 린터가 잡아낼 수 없는 실수이기에 원인을 찾기 매우 힘든 버그로 이어진다.

3. 복잡해지는 이벤트 흐름 추적

앱의 규모가 커지면 하나의 EventEmitter 인스턴스를 여러 곳에서 공유하게 될 수 있다.

이 경우, 특정 이벤트가 발생했을 때 어떤 리스너들이 실행되는지, 그리고 그 실행 순서가 어떻게 되는지 파악하기가 매우 어려워진다.

이벤트들과 발행자-구독자 관계가 서로 얽히고 얽혀있다면 다이어그램이 꽤 복잡하게 그려진다.

profile
Frontend Engineer | Microsoft Student Ambassadors Alumni

0개의 댓글