
목차
안녕하세요, 이번에는 Angular Router의 이벤트를 subscribe하는 과정에서 발생하는 중복 호출 문제를 어떻게 해결했는지에 대해 이야기하려고 합니다. 본인이 경험한 실제 문제 상황과 그 해결 방법을 공유하려고 합니다. 이 과정을 통해 Angular에서 일어나는 이벤트 구독의 특징을 이해하고 어떻게 관리해야 하는지에 대한 아이디어를 얻을 수 있을 것입니다.
1. Angular Router에서 발생한 문제
우선 제가 경험한 문제 상황에 대해 설명하겠습니다. Angular에서 화면 전환을 위해 router를 사용하는 상황에서 이 문제가 발생했습니다. index 화면에서 상단 메뉴를 선택하여 다른 화면으로 넘어갈 때, 좌측에 메뉴를 조회하여 보여주는 기능이 있었습니다.
그런데 이상하게도 index 화면으로 돌아간 후에 다시 상단 메뉴를 선택하여 화면으로 돌아오면, router의 이벤트가 여러 번 실행되는 문제가 발생했습니다. 이로 인해 메뉴를 여러 번 조회하게 되어 메뉴의 로딩이 늦어지는 현상이 발생했습니다.
이 문제를 보다 구체적으로 이해하기 위해서는 Angular에서의 이벤트 구독 방식에 대한 이해가 필요합니다. 보통 Angular에서 이벤트는 subscribe를 통해 구독하게 되는데, 이 경우 한번 subscribe를 하게 되면 이후에 이벤트가 발생할 때마다 이벤트 핸들러가 호출됩니다.
2. 원인
제가 이 문제의 원인을 분석해 본 결과, 이는 Angular Router 이벤트를 구독하는 부분에서 문제가 발생한 것으로 보였습니다.
기존 코드에서는 subLayoutComponent 클래스의 생성자에서 Angular Router의 이벤트를 구독하고 있었습니다. 이렇게 되면 해당 컴포넌트가 생성될 때마다 이벤트를 새로 구독하게 되므로, 이전에 구독한 이벤트들이 계속해서 호출되게 됩니다. 따라서 화면이 바뀔 때마다 이벤트가 추가로 호출되는 문제가 발생한 것입니다.
3. 해결 방법
-- 기존 소스
export class subLayoutComponent extends BaseLayoutComponet {
constructor(
private router: Router
){
this.loadSubMenu(router);
}
ngOnInit(): void {
super.ngOnInit();
}
loadSubMenu(router: Router) {
router.events.subscribe(event => {
let route: ActivatedRoute = router.routerState.root;
let menuLink: string = "";
while (route!.firstChild) {
route = route.firstChild;
}
if (route.snapshot.routeConfig.path) {
menuLink = route!.snapshot.routeConfig.path;
}
super.loadMenu(menuLink);
}
}
}
-- 변경 소스
export class subLayoutComponent extends BaseLayoutComponet implements OnInit, OnDestroy {
menuLikn: string = '';
_routerSub = Subscription.EMPTY;
constructor(
private router: Router
){
this.loadSubMenu(router);
}
ngOnInit(): void {
super.ngOnInit();
}
loadSubMenu(router: Router) {
this._routerSub = router.events.subscribe(event => {
let route: ActivatedRoute = router.routerState.root;
let menuLink: string = "";
while (route!.firstChild) {
route = route.firstChild;
}
if (route.snapshot.routeConfig.path) {
menuLink = route!.snapshot.routeConfig.path;
}
super.loadMenu(menuLink);
}
}
ngOnDesctory(): void {
_routerSub.unsubscribe();
}
}
이 문제를 해결하기 위해서는 이벤트 구독을 적절하게 관리해야 합니다. 그래서 제가 선택한 방법은 컴포넌트가 소멸될 때 이벤트 구독을 해제하는 것이었습니다.
이를 위해 우선 subLayoutComponent 클래스에 _routerSub라는 멤버 변수를 추가하였습니다. 이 변수는 router의 이벤트 구독을 관리하는 Subscription 객체를 저장하는 역할을 합니다. 그리고 이 변수를 이용해 loadSubMenu 메소드에서 이벤트 구독을 할 때 반환되는 Subscription 객체를 저장합니다.
그 다음으로는 이 컴포넌트가 소멸될 때 이벤트 구독을 해제하는 코드를 추가하였습니다. 이를 위해 ngOnDestroy 메소드를 오버라이드하여 이 안에서 _routerSub.unsubscribe()를 호출하도록 하였습니다.
이렇게 함으로써 화면이 바뀔 때마다 새로운 이벤트 구독이 추가되던 문제를 해결할 수 있었습니다. 이제 컴포넌트가 소멸될 때마다 이벤트 구독이 해제되므로, 이전에 구독한 이벤트가 계속해서 호출되는 문제를 방지할 수 있습니다.
이번 경험을 통해 Angular에서 이벤트를 구독할 때는 항상 이벤트 구독을 관리하는 것의 중요성을 깨닫게 되었습니다. 이벤트 구독이 계속해서 누적되면 의도치 않은 문제를 일으킬 수 있으므로, 반드시 이벤트 구독을 적절하게 해제하는 코드를 작성해야 합니다.
또한, 이 문제 해결을 위해 공부하면서 Angular의 동작 방식에 대해 좀 더 깊게 이해할 수 있었습니다. Angular의 이벤트 시스템은 매우 강력하면서도 복잡한 만큼, 이를 제대로 이해하고 사용하지 않으면 이런 문제가 발생할 수 있다는 것을 깨닫게 되었습니다.
이상으로 Angular Router의 이벤트를 subscribe할 때 발생하는 문제와 그 해결 방법에 대해 설명하였습니다. 이 글을 통해 Angular에서 이벤트를 관리하는 방법에 대한 이해를 돕고자 했습니다. 다음에도 이와 같은 유용한 정보를 계속해서 공유하도록 하겠습니다. 감사합니다.