SHIN
Node.js 실전 팁 20선
20편Node.js의 많은 핵심 모듈(HTTP, Stream, fs 등)이 EventEmitter를 기반으로 합니다. 직접 활용하면 결합도를 낮출 수 있습니다.
const { EventEmitter } = require('events');
const emitter = new EventEmitter();
// 이벤트 리스너 등록
emitter.on('data', (payload) => {
console.log('수신:', payload);
});
// 한 번만 실행
emitter.once('connect', () => {
console.log('연결됨 (한 번만 실행)');
});
// 이벤트 발생
emitter.emit('data', { id: 1, name: 'Alice' });
emitter.emit('connect');
emitter.emit('connect'); // 두 번째는 무시됨import { EventEmitter } from 'events';
interface OrderEvents {
'order:created': (order: Order) => void;
'order:paid': (orderId: string, amount: number) => void;
'order:shipped': (orderId: string, trackingNo: string) => void;
}
class OrderService extends EventEmitter {
async createOrder(data: CreateOrderDto): Promise<Order> {
const order = await db.order.create({ data });
this.emit('order:created', order);
return order;
}
async payOrder(orderId: string, amount: number): Promise<void> {
await db.payment.create({ data: { orderId, amount } });
this.emit('order:paid', orderId, amount);
}
}
const orderService = new OrderService();
// 이메일 서비스가 주문 이벤트를 구독
orderService.on('order:created', async (order) => {
await emailService.sendConfirmation(order.userEmail);
});
// 재고 서비스가 독립적으로 구독
orderService.on('order:paid', async (orderId) => {
await inventoryService.reserve(orderId);
});// 'error' 이벤트는 특별 취급: 리스너 없으면 프로세스 크래시
emitter.on('error', (err) => {
console.error('에러 발생:', err.message);
// 로깅, 알림 등 처리
});
// async 리스너의 에러는 수동으로 처리해야 함
emitter.on('data', async (data) => {
try {
await processData(data);
} catch (err) {
emitter.emit('error', err); // 에러 이벤트로 전파
}
});// 기본 maxListeners: 10 (초과 시 경고)
emitter.setMaxListeners(20);
// 리스너 제거
const handler = (data) => processData(data);
emitter.on('data', handler);
// ... 나중에
emitter.off('data', handler); // 또는 emitter.removeListener
// 모든 리스너 제거
emitter.removeAllListeners('data');import { once } from 'events';
// 타임아웃이 있는 이벤트 대기
const controller = new AbortController();
setTimeout(() => controller.abort(), 5000);
try {
const [data] = await once(emitter, 'data', {
signal: controller.signal,
});
console.log('수신:', data);
} catch (err) {
if (err.name === 'AbortError') {
console.log('5초 타임아웃');
}
}