의존성 순환은 두 개의 클래스가 서로에게 종속되어 있는 상황을 말합니다. 예를 들어, 클래스 A는 클래스 B가 필요하고, 클래스 B도 클래스 A가 필요한 경우입니다. 원형 종속성은 Nest에서 모듈 간 및 프로바이더 간에 발생할 수 있습니다.
가능한 경우에는 의존성 순환을 피하는 것이 좋지만 항상 그렇게 할 수는 없습니다. 이러한 경우에는 Nest에서 두 가지 방법으로 프로바이더 간의 의존성 순환을 해결할 수 있습니다. 이 장에서는 forward referencing
을 사용하는 기술과 ModuleRef
클래스를 사용하여 DI 컨테이너에서 프로바이더 인스턴스를 검색하는 방법 및 모듈간의 의존성 순환을 해결하는 방법에 대해서 설명합니다.
경고
"바렐 파일" 또는 index.ts 파일을 사용하여 가져온 파일들을 그룹화할 때도 의존성 순환이 발생할 수 있습니다. 모듈 또는 프로바이더 클래스에 대해서는 바렐 파일을 사용하지 않아야 합니다. 예를 들어, 바렐 파일 내부와 동일한 디렉토리 내에 있는 파일을 가져올 때 cats/cats.controller는 cats/cats.service 파일을 가져오기 위해 cats를 가져오면 안됩니다. 자세한 내용은 이 GitHub 이슈를 참조하십시오.
전방 참조(Forward reference
)는 Nest가 아직 정의되지 않은 클래스를 참조할 수 있게 해주는 forwardRef()
유틸리티 함수를 사용하는 것을 말합니다. 예를 들어, CatsService
와 CommonService
가 서로에게 종속되어 있는 경우, 관계의 양쪽에서 모두 @Inject()
와 forwardRef()
유틸리티를 사용하여 원형 종속성을 해결할 수 있습니다. 그렇지 않으면 Nest는 필요한 모든 메타데이터가 사용 가능하지 않기 때문에 이들을 인스턴스화하지 않습니다. 다음은 예시입니다:
//cats.service.ts
@Injectable()
export class CatsService {
constructor(
@Inject(forwardRef(() => CommonService))
private commonService: CommonService,
) {}
}
CatService
의 관계를 다뤘으니, 이제 CommonService
도 똑같은 과정을 거쳐줍시다.
//common.service.ts
@Injectable()
export class CommonService {
constructor(
@Inject(forwardRef(() => CatsService))
private catsService: CatsService,
) {}
}
forwardRef()
함수는@nestjs/common
패키지에서 import 합니다.
경고
인스턴스화 순서는 결정되지 않습니다. 코드가 어떤 생성자가 먼저 호출되는지에 의존하지 않도록 주의하십시오. 의존성 순환이Scope.REQUEST
를 가진 프로바이더에 의존하는 경우에는 정의되지 않은 종속성이 발생할 수 있습니다. 자세한 내용은 여기에서 확인할 수 있습니다.
forwardRef()
를 사용하는 대신 코드를 리팩토링하고 ModuleRef
클래스를 사용하여 (그렇지 않은 경우) 원형 종속성을 가진 관계의 한쪽에서 프로바이더를 검색하는 대안이 있습니다. ModuleRef
유틸리티 클래스에 대한 자세한 내용은 다음 장인 Module reference에서 확인할 수 있습니다.
모듈 간의 원형 종속성을 해결하기 위해, 모듈 연관성의 양쪽에서 동일한 forwardRef() 유틸리티 함수를 사용하세요.
// common.module.ts
@Module({
imports: [forwardRef(() => CatsModule)],
})
export class CommonModule {}
위의 코드는 관계의 한쪽을 다루고 있습니다. 이제 CatsModule에서도 동일한 방법을 사용해봅시다
// cats.module.ts
@Module({
imports: [forwardRef(() => CommonModule)],
})
export class CatsModule {}