하지만 이때, 모듈을 통한 의존성주입을 잘해주지 못하면 의도치 않은 에러를 마주하게 될 수도 있다.
직접 한번 예제를 통해 어떤식으로 해야하는지 알아보자.
ReviewService 에서 review 생성을 할때 기존에 구현해둔 UserService 와 GoodsService 를 재사용해서 User 정보와 Goods 정보를 가져와서 저장하고자 한다. (리뷰를 생성할때 리뷰를 작성한 유저 정보와 구매한 상품 정보를 불러와서 저장한다.)
@Injectable()
export class ReviewService {
constructor(
@InjectRepository(ReviewRepository)
private reviewRepository: ReviewRepository,
private goodsService: GoodsService,
private userService: UserService,
) {}
async createReview(createReviewDto: CreateReviewDto) {
const { goodsId, userId } = createReviewDto;
const user = await this.userService.getUserInfo(userId);
const goods = await this.goodsService.getGoodsById(goodsId);
return this.reviewRepository.createReview(createReviewDto, goods, user);
}
}
constructor 안의 부분이 리포지토리에 사용하고자 하는 서비스와 리포지토리를 의존성 주입해주는 부분이다.
그런데, 이렇게만 해서는 서비스와 리포지토리를 사용할 수가 없다.
Nest.js 는 모듈단위로 애플리케이션을 관리하기 때문에 모듈에서 따로 가져오고 내보내 주는 작업을 해주어야 하기 때문이다.
먼저 유저서비스와 상품서비스를 각각의 모듈에서 내보내주는 작업을 해주자.
//UserModule
@Module({
imports: [
TypeOrmModule.forFeature([UserRepository]),
],
controllers: [UserController],
providers: [UserService],
exports: [UserService],
})
export class UserModule {}
//GoodsModule
@Module({
imports: [TypeOrmModule.forFeature([GoodsRepository])],
controllers: [GoodsController],
providers: [GoodsService],
exports: [GoodsService],
})
export class GoodsModule {}
각 Module에서 exports 배열을 통해 원하는 서비스를 내보내 줄 수 있다.
(여기서 UserService 와 GoodsService 는 각각 UserRepository 와 GoodsRepository 를 통해 디비에 데이터를 접근하고 있다.)
이제 내보내 주는 작업을 했으니 가져오는 작업을 해주자.
//ReviewModule
@Module({
imports: [
UserModule,
GoodsModule,
TypeOrmModule.forFeature([
ReviewRepository,
]),
],
controllers: [ReviewController],
providers: [ReviewService, GoodsService, UserService],
})
export class ReviewModule {}
이제 직접 한번 리뷰를 생성하는 코드를 실행해보면 안타깝게도 에러가 나온다.
뭐가 문제일까? 바로 GoodsService 와 UserService 에서 사용하는 레포지토리들도 내보내 주어야 하기 때문이다.
위의 모듈에서 내보내고 가져오는 작업에서 리포지토리를 내보내고 가져오는 작업을 추가해주도록 하자.
위의 코드에서 exports 에 TypeOrmModule 을 추가해주면 레포지토리 내보내는 작업이 완료된다.
//UserModule
@Module({
imports: [
EmailModule,
AuthModule,
TypeOrmModule.forFeature([UserRepository]),
],
controllers: [UserController],
providers: [UserService],
exports: [UserService, TypeOrmModule],
})
export class UserModule {}
//GoodsModule
@Module({
imports: [TypeOrmModule.forFeature([GoodsRepository])],
controllers: [GoodsController],
providers: [GoodsService],
exports: [GoodsService,TypeOrmModule],
})
export class GoodsModule {}
이제 ReviewModule 에서도 가져오는 작업을 추가해주자
imports 의 TypeOrmModule.forFeature 배열안에 리포지토리들을 추가하자.
//ReviewModule
@Module({
imports: [
UserModule,
GoodsModule,
TypeOrmModule.forFeature([
ReviewRepository,
UserRepository,
GoodsRepository,
]),
],
controllers: [ReviewController],
providers: [ReviewService, GoodsService, UserService],
})
export class ReviewModule {}
이제 위의 과정처럼 다른 모듈에 있는 서비스와 레포지토리들을 주입해 재사용하면 된다.
안녕하세요 좋은글 남겨주셔서 감사합니다.
다름이 아니라 EntityMetadataNotFoundError: No metadata for "xxxrepository" was found.
라는 에러가 발생하는데 저의 짐작으로는 TypeOrmModuleOptions의 entites 쪽인거 같은데 리포지토리 클래스들을 넣어줘도 같은 에러가 발생하네요.다른 방안이나 해당 글의 코드 구현하셨을때의 설정 알려주신다면 감사하겠습니다!