Nest.js Providers & Modules

나주엽·2024년 6월 23일
0

nest

목록 보기
1/3

Providers

providers 는 Nest 의 기본 개념이다.

services, respositories, factories, helpers 등이 모두 providers 이다.

주요 아이디어는 종속성으로 주입될 수 있다는 것이다.

@Injectable() 데코레이터를 통해 class 를 provider로 설정할 수 있다.

import { Injectable } from '@nestjs/common';
import { Cat } from './interfaces/cat.interface';

@Injectable()
export class CatsService {
  private readonly cats: Cat[] = [];

  findAll(): Cat[] {
    return this.cats;
  }
}

Nest.js가 의존성 주입을 수행하기 위해서는

위와 같이 정의한 provider 를 사용할 consumer 에 연결(등록)해 주어야 한다.

이 동작은 Module 을 통해 진행된다. 따라서, Module 을 알아보자.

Modules

module 은 @Module() 데코레이터로 주석이 달린 클래스이다.

이렇게 설정된 모듈 정보를 활용해 Nest.js 가 어플리케이션의 구조를 짜게 된다.

@Module() 데코레이터는 하나의 객체를 인자로 받을 수 있고, 아래의 프로퍼티를 가질 수 있다.

프로퍼티설명
providers적어도 module 내에서는 공유되고, Nest injector 에 의해 인스턴스화 될 providers
controllersmodule 내에서 정의된, 인스턴스화 해야 하는 controllers
imports이 module 에서 필요한 providers 를 export 한 다른 module
export이 module 이 내보낼 providers, 다른 module 에서는 이 module 을 import 해서 해당 providers 를 사용할 수 있다.

예제

많이 구현하는 사용자 인증 / 토큰 관련한 AuthModuleUserModule 을 예제로 작성해보자.

우선, TokenEntityUserEntity 가 있을 것이다.

그리고, TokenEntity 와 관련된 로직을 수행하는 TokenService

UserEntity 와 관련된 로직을 수행하는 UserService 가 있다.

그리고 이 전체를 관장하는 AuthServiceAuthController 를 작성해보자.

엔티티는 생략하겠습니다.

// user.service.ts

import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { UserEntity } from './user.entity';

@Injectable()
export class UserService {
  constructor(
    @InjectRepository(UserEntity)
    private userRepository: Repository<User>,
  ) {}

	findOneById = async (userId: string): Promise<UserEntity | undefined> => {
    ...
  }
  
  createOne = async (username: string, hashPassword: string): Promise<UserEntity> => {
	  ...
	}
	
	...
}
// token.service.ts

import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { TokenEntity } from './token.entity';
import { UserEntity } from './user.entity';

@Injectable()
export class TokenService {
  constructor(
    @InjectRepository(TokenEntity)
    private tokenRepository: Repository<TokenEntity>,
  ) {}

  generateToken = async (user: User): Promise<any> => {
	  ... // access token 및 refresh token 생성 후 반환
			  // 이 과정에서 refresh token 도 저장
	}
	
	...
}
// auth.service.ts

import { Injectable } from '@nestjs/common';
import { UserService } from './user.service';
import { TokenService } from './token.service';
import { UserEntity } from './user.entity';

@Injectable()
export class AuthService {
  constructor(
    private userService: UserService,
    private tokenService: TokenService,
  ) {}

  validateUser = async (username: string, password: string): Promise<User> => {
		...
  }

  signIn = async (user: User): Promise<any> => {
	  ...
  }

  signUp = async (username: string, password: string): Promise<void> => {
		...
  }
  
  ...
}

이렇게 작성한 세 가지 서비스는 모두 provider 이다.

이제 UserModuleAuthModule 을 작성하자.

// user.module.ts

import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { UserService } from './user.service';
import { UserEntity } from './user.entity';

@Module({
  imports: [TypeOrmModule.forFeature([UserEntity])],
  providers: [UserService],
  exports: [UserService],
})
export class UserModule {}

AuthModule 에서 UserService 를 사용할 예정이기 때문에 exports 에 UserService 를 추가해야 한다.

// auth.module.ts

import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { TokenService } from './token.service';
import { AuthService } from './auth.service';
import { TokenEntity } from './token.entity';
import { UserModule } from '../user/user.module';

@Module({
  imports: [TypeOrmModule.forFeature([Token]), UserModule],
  providers: [TokenService, AuthService],
  exports: [AuthService],
})
export class AuthModule {}

AuthModule 에서 UserService 를 사용하려면, UserModule 을 import 하면 된다.

마지막으로 auth/signup , auth/signin 등의 route 를 사용할 예정이면 AuthModulecontrollersAuthController 를 추가하면 된다.

TypeOrmModule.forFeatrue()DynamicModule 을 반환합니다.

위에서 작성한 내용을 그림으로 표현하면 아래와 같다. (TypeOrmModule 생략)

정리

Nest.js로 개발하면, 서비스, 컨트롤러, 모듈이 많아질수록 모듈 간의 관계가 복잡해진다.

어디에 어떻게 연결되어 있는지, 어떤 부분을 수정해야 할지 판단하기 어려울 때가 있다.

이러한 개념을 잘 이해하고, 설계를 할 때 이런 부분도 충분히 고민한 후 코드를 작성해야 겠다.

0개의 댓글