심플한 정적 모듈 바인딩 구현
순환 종속성을 설명하기 전, 먼저 심플한 정적 모듈 바인딩을 구현해 보도록 하겠습니다.
다음과 같이, auth service, user service를 만들었다고 가정하겠습니다.
그 다음, 정적 모듈 바인딩을 위하여 user module에서 user service를 export 시켜주고 auth service 에서는 user module을 import 한 뒤 각 서비스에서 간단한 함수를 만들어서 정적 모듈 바인딩을 구현합니다.
- UsersModule
import { Module } from '@nestjs/common';
import { UsersController } from './users.controller';
import { UsersService } from './users.service';
@Module({
controllers: [UsersController],
providers: [UsersService],
exports:[UsersService] // 서비스를 export
})
export class UsersModule {}
- AuthModule
import { Module } from '@nestjs/common';
import { AuthController } from './auth.controller';
import { AuthService } from './auth.service';
import { UsersModule } from 'src/users/users.module';
@Module({
imports: [UsersModule], // users Module import
controllers: [AuthController],
providers: [AuthService]
})
export class AuthModule {}
- UsersService
import { Injectable } from '@nestjs/common';
@Injectable()
export class UsersService {
public test() {
return 'a';
}
}
- AuthService
import { Injectable } from '@nestjs/common';
import { UsersService } from '../users/users.service';
@Injectable()
export class AuthService {
constructor(private usersService: UsersService) {}
public test() {
return this.usersService.test()
}
}
다음, 테스트를 위하여 AuthController에 간단하게 Get Method를 하나 작성합니다.
- AuthController
import { Controller, Get } from '@nestjs/common';
import { AuthService } from './auth.service';
@Controller('auth')
export class AuthController {
constructor(private readonly authService: AuthService) {}
@Get('test')
public test() {
return this.authService.test()
}
}
그리고 값을 확인해보면 user service 에서 반환한 'a' 가 출력되는 것을 확인 할 수 있습니다.
이렇게 특정 모듈을 export 하고 다른 모듈에서 import 하여 하는 방식을 정적 모듈 바인딩 이라고 합니다.
그렇다면, 현재 상황에서 auth service를 export 하고 user module에서 import 하게 된다면 어떻게 될까요?
서로가 서로를 참조하다 보니, 오류가 발생할 것으로 예상 됩니다.
순환 종속성의 오류 발생
- Auth Module
import { Module } from '@nestjs/common';
import { AuthController } from './auth.controller';
import { AuthService } from './auth.service';
import { UsersModule } from 'src/users/users.module';
@Module({
imports: [UsersModule], // users Module import
controllers: [AuthController],
providers: [AuthService],
exports: [AuthService] // Auth Service export
})
export class AuthModule {}
- Users Module
import { Module } from '@nestjs/common';
import { UsersController } from './users.controller';
import { UsersService } from './users.service';
import { AuthModule } from 'src/auth/auth.module';
@Module({
imports: [AuthModule], // Auth Service import
controllers: [UsersController],
providers: [UsersService],
exports:[UsersService] // 서비스를 export
})
export class UsersModule {}
위와 같이 서로가 서로를 바인딩 하게 될 시, 다음과 같은 오류가 발생합니다.
[Nest] 38564 - 2023. 10. 02. 오후 9:12:48 ERROR [ExceptionHandler] Nest cannot create the AuthModule instance.
The module at index [0] of the AuthModule "imports" array is undefined.
Potential causes:
- A circular dependency between modules. Use forwardRef() to avoid it. Read more: https://docs.nestjs.com/fundamentals/circular-dependency
- The module at index [0] is of type "undefined". Check your import statements and the type of the module.
서로가 서로를 참조하다 보니 당연히 오류가 발생 할 수 밖에 없을 것 같습니다.
다만, nest.js 에서는 이를 해결하기 위한 방식을 제공해 주고 있다고 합니다.
각 서비스와 모듈에서 서비스 호출시 다음과 같이 코드를 수정해 줍니다.
- AuthService
import { Inject, Injectable, forwardRef } from '@nestjs/common';
import { UsersService } from '../users/users.service';
@Injectable()
export class AuthService {
constructor(
@Inject(forwardRef(() => UsersService))
private usersService: UsersService,
) {}
public test() {
return this.usersService.test()
}
public test2() {
return 'b'
}
}
- AuthModule
import { Module, forwardRef } from '@nestjs/common';
import { AuthController } from './auth.controller';
import { AuthService } from './auth.service';
import { UsersModule } from 'src/users/users.module';
@Module({
imports: [forwardRef(() => UsersModule)],
controllers: [AuthController],
providers: [AuthService],
exports: [AuthService] // Auth Service export
})
export class AuthModule {}
User쪽도 동일하게 적용하면 됩니다.
결론
코드를 순환 종속성이 없도록 짜는게 BEST 일 것 같습니다.
Service 단에서 참조 하는 거니, 공통적으로 필요한 로직들은 따로 common service나 lib등을 이용하여 참조 합시다.
RDB를 기준으로 보더라도, 서로의 쿼리를 참조할 일은 별로 없어 보입니다.
한쪽에서 참조되는 값을 가져오는 경우는 있겠지만, 반대로 구현하는건 불필요 한 것 같습니다.
'JAVASCRIPT > nest.js' 카테고리의 다른 글
[NestJS] NestJS + prisma CRUD (0) | 2024.06.11 |
---|---|
[nest.js] prisma schema 분리 (0) | 2024.06.04 |
[nest.js] nest.js + prisma - setting (0) | 2024.05.10 |
[nest.js] module reference (2) | 2023.10.02 |