이미 소멸한 인젝터에서 서비스를 가져오려고 하면 이 오류가 발생합니다. 보통 컴포넌트, 디렉티브, 모듈이 소멸한 뒤 코드가 의존 대상에 접근하려고 할 때 발생합니다.
흔히 발생하는 상황
소멸 후 콜백에서 서비스에 접근하는 경우
컴포넌트가 소멸하면 인젝터도 함께 소멸합니다. 이후 비동기 콜백이 서비스에 접근하려고 하면 이 오류가 발생합니다.
@Component(/* ... */)
export class UserProfile implements OnInit {
private userClient = inject(UserClient);
ngOnInit() {
setTimeout(() => {
// 오류: 타이머가 실행되기 전에 컴포넌트가 소멸하면
// 인젝터를 더 이상 사용할 수 없습니다.
this.userClient.fetchData();
}, 5000);
}
}
구독 해제 후 서비스에 접근하는 경우
옵저버블에서도 정리 작업의 순서가 잘못되면 비슷한 문제가 발생합니다.
@Component(/* ... */)
export class DataView implements OnDestroy {
private dataStore = inject(DataStore);
ngOnDestroy() {
// 문제: 소멸 도중 다른 정리 작업이 이미 실행되었을 수 있는데
// 인젝터를 사용하려고 합니다.
this.dataStore.cleanup();
}
}
오류 디버깅
이 오류를 해결하려면 다음 사항을 확인하세요.
- 비동기 작업을 확인하세요. 컴포넌트가 소멸할 때 콜백, 프로미스, 구독이 취소되도록 하세요. 정리 작업에는
takeUntilDestroyed()나DestroyRef를 사용하세요.
- 의존 대상을 미리 확보하세요. 콜백에서 인젝터에 접근하는 대신 서비스 참조를 클래스 필드에 저장하세요.
- 소멸 상태에 대비하세요. 컴포넌트보다 오래 실행될 수 있는 작업에서는 서비스에 접근하기 전에 컴포넌트가 여전히 활성 상태인지 확인하세요.
@Component(/* ... */)
export class UserProfile implements OnInit {
private destroyRef = inject(DestroyRef);
private userClient = inject(UserClient);
ngOnInit() {
// 소멸 시 자동으로 취소하도록 takeUntilDestroyed를 사용합니다.
interval(5000)
.pipe(takeUntilDestroyed(this.destroyRef))
.subscribe(() => {
this.userClient.fetchData();
});
}
}
스택 트레이스에는 소멸한 인젝터에 접근한 위치가 표시됩니다. 이를 거슬러 올라가 컴포넌트가 소멸한 뒤에도 계속된 비동기 작업을 찾으세요.