본 콘텐츠의 이미지 및 내용은 AI로 생성되었습니다.
본 콘텐츠의 이미지 및 내용을 무단으로 복제, 배포, 수정하여 사용할 경우 저작권법에 의해 법적 제재를 받을 수 있습니다.
이미지 로딩 중...
AI Generated
2025. 11. 4. · 21 Views
Observer Pattern 실무 활용 가이드
Observer Pattern의 고급 활용 방법을 실무 중심으로 알아봅니다. 이벤트 기반 아키텍처, 메모리 관리, 성능 최적화까지 실전에서 바로 사용할 수 있는 패턴을 다룹니다.
들어가며
이 글에서는 Observer Pattern 실무 활용 가이드에 대해 상세히 알아보겠습니다. 총 12가지 주요 개념을 다루며, 각각의 개념에 대한 설명과 실제 코드 예제를 함께 제공합니다.
목차
- 기본_Observer_구현
- 타입_안전한_이벤트_시스템
- 자동_구독_해제_패턴
- 조건부_알림_최적화
- 우선순위_기반_알림
- 비동기_Observer_처리
- 에러_핸들링_패턴
- 선택적_구독_필터링
- Once_구독_패턴
- WeakMap_기반_메모리_관리
- Debounced_알림_패턴
- 이벤트_버스_패턴
1. 기본 Observer 구현
개요
Observer Pattern의 기본 구조를 TypeScript로 구현합니다. Subject와 Observer 인터페이스를 정의하여 느슨한 결합을 만듭니다.
코드 예제
interface Observer {
update(data: any): void;
}
class Subject {
private observers: Observer[] = [];
attach(observer: Observer) {
this.observers.push(observer);
}
notify(data: any) {
this.observers.forEach(o => o.update(data));
}
}
설명
Subject는 observers 배열로 구독자를 관리하고, notify로 모든 구독자에게 데이터를 전파합니다.
2. 타입 안전한 이벤트 시스템
개요
제네릭을 활용하여 타입 안전성을 보장하는 이벤트 시스템을 구현합니다.
코드 예제
class TypedEventEmitter<T> {
private listeners: ((data: T) => void)[] = [];
subscribe(callback: (data: T) => void) {
this.listeners.push(callback);
return () => this.unsubscribe(callback);
}
emit(data: T) {
this.listeners.forEach(cb => cb(data));
}
}
설명
제네릭 T로 이벤트 데이터 타입을 지정하여, 컴파일 타임에 타입 오류를 잡을 수 있습니다.
3. 자동 구독 해제 패턴
개요
메모리 누수를 방지하기 위해 구독 해제 함수를 반환하는 패턴입니다.
코드 예제
class Store<T> {
private state: T;
private listeners = new Set<(state: T) => void>();
subscribe(listener: (state: T) => void) {
this.listeners.add(listener);
listener(this.state);
return () => this.listeners.delete(listener);
}
}
설명
subscribe가 unsubscribe 함수를 반환하여, 컴포넌트 언마운트 시 쉽게 정리할 수 있습니다.
4. 조건부 알림 최적화
개요
모든 변경사항을 알리지 않고, 실제 값이 변경될 때만 notify하여 성능을 최적화합니다.
코드 예제
class OptimizedStore<T> {
private state: T;
private listeners = new Set<(state: T) => void>();
setState(newState: T) {
if (this.state !== newState) {
this.state = newState;
this.listeners.forEach(fn => fn(newState));
}
}
}
설명
얕은 비교로 상태 변경을 체크하여 불필요한 렌더링이나 연산을 방지합니다.
5. 우선순위 기반 알림
개요
옵저버에게 우선순위를 부여하여 특정 순서로 알림을 받을 수 있게 합니다.
코드 예제
class PrioritySubject {
private observers: Map<number, Set<Function>> = new Map();
subscribe(fn: Function, priority: number = 0) {
if (!this.observers.has(priority)) {
this.observers.set(priority, new Set());
}
this.observers.get(priority)!.add(fn);
}
notify(data: any) {
[...this.observers.keys()].sort((a, b) => b - a)
.forEach(p => this.observers.get(p)!.forEach(fn => fn(data)));
}
}
설명
우선순위가 높은 옵저버부터 실행되어, 중요한 로직을 먼저 처리할 수 있습니다.
6. 비동기 Observer 처리
개요
비동기 작업을 처리하는 옵저버를 위해 Promise 기반으로 구현합니다.
코드 예제
class AsyncSubject {
private observers: ((data: any) => Promise<void>)[] = [];
subscribe(fn: (data: any) => Promise<void>) {
this.observers.push(fn);
}
async notify(data: any) {
await Promise.all(
this.observers.map(fn => fn(data))
);
}
}
설명
Promise.all로 모든 비동기 옵저버를 병렬로 실행하고, 모두 완료될 때까지 대기합니다.
7. 에러 핸들링 패턴
개요
하나의 옵저버 에러가 전체 알림 체인을 중단하지 않도록 에러를 격리합니다.
코드 예제
class SafeSubject {
private observers: Function[] = [];
notify(data: any) {
this.observers.forEach(fn => {
try {
fn(data);
} catch (error) {
console.error('Observer error:', error);
}
});
}
}
설명
try-catch로 각 옵저버를 감싸서, 한 옵저버의 실패가 다른 옵저버에 영향을 주지 않습니다.
8. 선택적 구독 필터링
개요
특정 조건을 만족하는 이벤트만 받도록 필터링 기능을 추가합니다.
코드 예제
class FilterableSubject<T> {
private observers: Map<Function, (data: T) => boolean> = new Map();
subscribe(fn: Function, filter?: (data: T) => boolean) {
this.observers.set(fn, filter || (() => true));
}
notify(data: T) {
this.observers.forEach((filter, fn) => {
if (filter(data)) fn(data);
});
}
}
설명
filter 함수로 조건을 지정하여, 관심 있는 이벤트만 처리할 수 있어 효율적입니다.
9. Once 구독 패턴
개요
한 번만 실행되고 자동으로 구독 해제되는 일회성 옵저버를 구현합니다.
코드 예제
class EventEmitter {
private listeners = new Map<string, Set<Function>>();
once(event: string, fn: Function) {
const wrapper = (data: any) => {
fn(data);
this.listeners.get(event)?.delete(wrapper);
};
this.on(event, wrapper);
}
}
설명
wrapper 함수가 실행 후 스스로를 제거하여, 이벤트를 한 번만 처리하고 메모리를 정리합니다.
10. WeakMap 기반 메모리 관리
개요
WeakMap을 사용하여 객체가 가비지 컬렉션될 때 자동으로 구독이 해제되도록 합니다.
코드 예제
class WeakObserver {
private observers = new WeakMap<object, Function>();
subscribe(target: object, fn: Function) {
this.observers.set(target, fn);
}
notify(data: any) {
// WeakMap은 순회 불가, 특정 target으로 접근
}
}
설명
WeakMap은 키 객체가 더 이상 참조되지 않으면 자동으로 제거되어 메모리 누수를 방지합니다.
11. Debounced 알림 패턴
개요
짧은 시간 내 여러 변경사항을 하나로 묶어서 알림 횟수를 줄입니다.
코드 예제
class DebouncedSubject {
private observers: Function[] = [];
private timeout: NodeJS.Timeout | null = null;
notify(data: any, delay = 300) {
if (this.timeout) clearTimeout(this.timeout);
this.timeout = setTimeout(() => {
this.observers.forEach(fn => fn(data));
}, delay);
}
}
설명
delay 시간 내 마지막 호출만 실행되어, 빈번한 상태 변경 시 성능을 크게 향상시킵니다.
12. 이벤트 버스 패턴
개요
전역 이벤트 버스로 컴포넌트 간 통신을 구현합니다. 여러 이벤트 타입을 관리합니다.
코드 예제
class EventBus {
private events = new Map<string, Set<Function>>();
on(event: string, fn: Function) {
if (!this.events.has(event)) {
this.events.set(event, new Set());
}
this.events.get(event)!.add(fn);
}
emit(event: string, data: any) {
this.events.get(event)?.forEach(fn => fn(data));
}
}
설명
이벤트 이름으로 구분하여 여러 타입의 메시지를 관리하고, 컴포넌트 간 느슨한 결합을 유지합니다.
마치며
이번 글에서는 Observer Pattern 실무 활용 가이드에 대해 알아보았습니다. 총 12가지 개념을 다루었으며, 각각의 사용법과 예제를 살펴보았습니다.
관련 태그
#TypeScript #ObserverPattern #DesignPatterns #EventDriven #Architecture
댓글 (0)
함께 보면 좋은 카드 뉴스
마이크로서비스 배포 완벽 가이드
Kubernetes를 활용한 마이크로서비스 배포의 핵심 개념부터 실전 운영까지, 초급 개발자도 쉽게 따라할 수 있는 완벽 가이드입니다. 실무에서 바로 적용 가능한 배포 전략과 노하우를 담았습니다.
마이크로서비스 아키텍처 완벽 가이드
모놀리식에서 마이크로서비스로의 전환은 현대 소프트웨어 개발의 핵심 화두입니다. 초급 개발자도 쉽게 이해할 수 있도록 실무 관점에서 마이크로서비스의 개념, 장단점, 설계 원칙을 스토리텔링으로 풀어냅니다.
Application Load Balancer 완벽 가이드
AWS의 Application Load Balancer를 처음 배우는 개발자를 위한 실전 가이드입니다. ALB 생성부터 ECS 연동, 헬스 체크, HTTPS 설정까지 실무에 필요한 모든 내용을 다룹니다. 초급 개발자도 쉽게 따라할 수 있도록 단계별로 설명합니다.
고객 상담 AI 시스템 완벽 구축 가이드
AWS Bedrock Agent와 Knowledge Base를 활용하여 실시간 고객 상담 AI 시스템을 구축하는 방법을 단계별로 학습합니다. RAG 기반 지식 검색부터 Guardrails 안전 장치, 프론트엔드 연동까지 실무에 바로 적용 가능한 완전한 시스템을 만들어봅니다.
에러 처리와 폴백 완벽 가이드
AWS API 호출 시 발생하는 에러를 처리하고 폴백 전략을 구현하는 방법을 다룹니다. ThrottlingException부터 서킷 브레이커 패턴까지, 실전에서 바로 활용할 수 있는 안정적인 에러 처리 기법을 배웁니다.