Angular 프로젝트에서 RxJS Observable 제대로 관리하기
문제 상황
최근 Angular 4로 개발 중인 대시보드 애플리케이션에서 페이지 전환 시 메모리 사용량이 계속 증가하는 문제를 발견했다. Chrome DevTools로 프로파일링한 결과, 컴포넌트가 파괴된 후에도 Observable 구독이 살아있어 메모리 누수가 발생하고 있었다.
해결 방법
1. 수동 구독 해제
가장 기본적인 방법은 ngOnDestroy에서 직접 구독을 해제하는 것이다.
export class DashboardComponent implements OnInit, OnDestroy {
private subscription: Subscription;
ngOnInit() {
this.subscription = this.dataService.getData()
.subscribe(data => this.handleData(data));
}
ngOnDestroy() {
this.subscription.unsubscribe();
}
}
2. Subscription 배열 관리
여러 구독이 있을 때는 배열로 관리하면 편하다.
export class DashboardComponent implements OnInit, OnDestroy {
private subscriptions: Subscription[] = [];
ngOnInit() {
this.subscriptions.push(
this.dataService.getData().subscribe(data => this.handleData(data)),
this.userService.getUser().subscribe(user => this.user = user)
);
}
ngOnDestroy() {
this.subscriptions.forEach(sub => sub.unsubscribe());
}
}
3. takeUntil 패턴
개인적으로 선호하는 방법이다. RxJS의 takeUntil 오퍼레이터를 활용한다.
export class DashboardComponent implements OnInit, OnDestroy {
private destroy$ = new Subject<void>();
ngOnInit() {
this.dataService.getData()
.takeUntil(this.destroy$)
.subscribe(data => this.handleData(data));
this.userService.getUser()
.takeUntil(this.destroy$)
.subscribe(user => this.user = user);
}
ngOnDestroy() {
this.destroy$.next();
this.destroy$.complete();
}
}
주의사항
async파이프를 사용하면 Angular가 자동으로 구독 해제를 처리해준다.- HTTP 요청은 자동으로 complete되지만, 명시적으로 해제하는 습관을 들이는 게 좋다.
- interval, fromEvent 같은 long-living Observable은 반드시 구독 해제가 필요하다.
결과적으로 takeUntil 패턴을 프로젝트 전체에 적용했고, 메모리 누수 문제를 해결했다. 코드도 더 깔끔해졌다.