Provider는 NestJS의 의존성 주입(DI) 시스템의 핵심입니다. Provider는 다음과 같은 것들을 제공할 수 있습니다:
// src/user/user.module.ts
@Module({
providers: [UserService], // 클래스 자체를 Provider로 등록
})
export class UserModule {}
// src/user/user.module.ts
const UserMockService = {
findAll: () => {
return 'find mock users';
},
};
@Module({
providers: [
{
provide: UserService, // 토큰
useValue: UserMockService, // 실제 값
},
],
})
export class UserModule {}
설명:
provide
: 의존성 주입 시 사용할 토큰useValue
: 실제로 주입될 값 (객체, 함수, 원시값 등)// src/auth/auth.module.ts
@Module({
imports: [
JwtModule.registerAsync({
inject: [ConfigService], // 주입받을 의존성들
useFactory: async (configService: ConfigService) => {
return {
global: true,
secret: configService.get('jwt.secret'),
signOptions: { expiresIn: '1d' },
};
},
}),
],
})
export class AuthModule {}
설명:
inject
: 팩토리 함수에 주입할 의존성들의 배열useFactory
: 실제 Provider 인스턴스를 생성하는 함수// src/user/user.service.spec.ts
const module: TestingModule = await Test.createTestingModule({
providers: [
UserService,
{
provide: getRepositoryToken(User),
useClass: MockRepository, // MockRepository 클래스의 인스턴스 생성
},
],
}).compile();
설명:
useClass
: 지정된 클래스의 인스턴스를 생성하여 주입// src/auth/auth.module.ts
@Module({
providers: [
AuthService,
JwtStrategy,
{
provide: APP_GUARD, // 전역 가드 토큰
useClass: JwtAuthGuard, // 전역적으로 적용될 가드 클래스
},
],
})
export class AuthModule {}
설명:
APP_GUARD
: NestJS에서 제공하는 특별한 토큰@UseGuards()
데코레이터 없이도 전역 인증 적용// src/app.module.ts
@Module({
imports: [
ConfigModule.forRoot({
isGlobal: true, // 전역 모듈로 설정
load: [postgresConfig, jwtConfig], // 커스텀 설정 로드
}),
],
})
export class AppModule {}
설명:
isGlobal: true
: 모든 모듈에서 ConfigService를 주입받을 수 있음load
: 커스텀 설정 파일들을 로드// src/config/postgres.config.ts
import { registerAs } from '@nestjs/config';
export default registerAs('postgres', () => ({
host: process.env.POSTGRES_HOST || 'localhost',
port: process.env.POSTGRES_PORT ? Number(process.env.POSTGRES_PORT) : 5434,
database: process.env.POSTGRES_DATABASE || 'postgres',
username: process.env.POSTGRES_USERNAME || 'postgres',
password: process.env.POSTGRES_PASSWORD || 'postgres',
}));
설명:
registerAs
: 네임스페이스를 가진 설정 객체 생성configService.get('postgres.host')
형태로 접근 가능// src/config/jwt.config.ts
import { registerAs } from '@nestjs/config';
export default registerAs('jwt', () => ({
secret: process.env.JWT_SECRET || 'temp secret',
}));
// src/app.module.ts
TypeOrmModule.forRootAsync({
inject: [ConfigService], // 주입받을 의존성
useFactory: async (configService: ConfigService) => {
let obj: TypeOrmModuleOptions = {
type: 'postgres',
host: configService.get('postgres.host'),
port: configService.get('postgres.port'),
database: configService.get('postgres.database'),
username: configService.get('postgres.username'),
password: configService.get('postgres.password'),
autoLoadEntities: true,
};
// 환경에 따른 조건부 설정
if (configService.get('STAGE') === 'local') {
console.info('Sync postgres');
obj = Object.assign(obj, {
synchronize: true,
logging: true,
});
}
return obj;
},
}),
설명:
inject
: 팩토리 함수에 주입할 의존성들useFactory
: 동적으로 설정을 생성하는 함수// src/auth/auth.module.ts
JwtModule.registerAsync({
inject: [ConfigService],
useFactory: async (configService: ConfigService) => {
return {
global: true,
secret: configService.get('jwt.secret'),
signOptions: { expiresIn: '1d' },
};
},
}),
설명:
global: true
로 전역 모듈 설정// src/auth/jwt.strategy.ts
@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
constructor(configService: ConfigService) {
super({
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
ignoreExpiration: false,
secretOrKey: configService.get('jwt.secret'), // 설정에서 JWT 시크릿 가져오기
});
}
}
설명:
ConfigService
를 주입받아 설정값 사용// src/app.module.ts
@Module({
imports: [
ConfigModule.forRoot({
isGlobal: true,
load: [postgresConfig, jwtConfig],
}),
TypeOrmModule.forRootAsync({
inject: [ConfigService],
useFactory: async (configService: ConfigService) => {
// 동적 설정 로직
},
}),
AuthModule,
UserModule,
VideoModule,
AnalyticsModule,
],
})
export class AppModule {}
// src/user/user.module.ts
@Module({
imports: [TypeOrmModule.forFeature([User])], // 엔티티 등록
exports: [UserService], // 다른 모듈에서 사용할 서비스 내보내기
controllers: [UserController],
providers: [UserService], // 또는 커스텀 Provider 설정
})
export class UserModule {}
# package.json
"start:dev": "cross-env STAGE=local nest start --watch"
// src/main.ts
console.info(`STAGE: ${process.env.STAGE}`);
if (configService.get('STAGE') === 'local') {
console.info('Sync postgres');
obj = Object.assign(obj, {
synchronize: true,
logging: true,
});
}
forwardRef()
사용하여 해결 가능isGlobal: true
설정 시 모든 모듈에서 접근 가능이러한 Provider와 Module 심화 과정을 통해 NestJS 애플리케이션의 구조를 더욱 견고하고 유연하게 만들 수 있습니다.