[NestJS] Module, DTO, Controller, Service

혜진·2024년 9월 1일
0

NestJS

목록 보기
3/12
post-thumbnail

NestJS - Module, DTO, Controller, Service

모듈(Module)

  • NestJS 애플리케이션의 기본 구성 요소로, 관련 기능들을 그룹화하는 역할을 한다. 모든 애플리케이션은 최소 하나의 루트 모듈을 가지고 있으며, 기능별로 여러 모듈로 나눌 수 있다.
  • 모듈은 @Module() 데코레이터를 사용하여 정의되며, 컨트롤러, 서비스, 그리고 다른 모듈들을 가져와서 사용할 수 있다.

모듈(Module) 간 의존성 관리

@Module({
  imports: [UsersModule],
  controllers: [AuthController],
  providers: [AuthService],
  exports: [AuthService],
})
export class AuthModule {}
  • @Module() 데코레이터: 해당 클래스가 NestJS 모듈임을 나타낸다. @Module 데코레이터 내부에는 imports, controllers, providers, exports와 같은 속성들이 정의된다.

  • imports: 이 모듈에서 사용할 다른 모듈들을 가져온다. 이를 통해 UsersModule에서 제공하는 서비스나 다른 기능을 AuthModule에서 사용할 수 있다.

  • controllers: 이 모듈에서 사용하는 컨트롤러를 지정한다. AuthController는 AuthModule에 속해 있는 컨트롤러로, 인증 관련 요청을 처리한다.

  • providers: 서비스나 다른 종속성을 제공하는 부분으로, 이 서비스는 인증과 관련된 비즈니스 로직을 처리한다.

  • exports: 모듈 외부에서 사용할 수 있도록 내보내는 서비스나 프로바이더를 지정한다. 이로 인해 다른 모듈에서도 AuthService를 주입받아 사용할 수 있다.

DTO (Data Transfer Object)

  • 계층 간에 데이터를 주고받을 때 사용되는 객체로, DTO를 통해 요청 데이터를 검증하고, 명확한 데이터 구조를 정의할 수 있다.
  • 보통 클래스 형태로 정의되며, class-validator와 같은 패키지를 사용해 데이터 검증을 추가할 수 있다.

DTO(Data Transfer Object)에서 유효성 검사

  • @IsString(): 해당 필드가 문자열이어야 한다는 것을 명시한다. 클라이언트가 숫자나 다른 타입의 데이터를 전송할 경우, 서버는 유효성 검사에서 실패하고 에러를 반환한다.

  • @IsInt(): 해당 필드(age)가 정수여야 함을 명시한다.

  • @Min(1): 정수 값이 최소 1 이상이어야 한다는 것을 명시힌다.

  • @IsOptional(): 해당 필드가 선택 사항임을 나타낸다. 즉, 클라이언트가 이 필드를 전송하지 않아도 유효성 검사에서 실패하지 않는다.

Controller

  • 요청을 처리하고 응답을 반환하는 역할을 한다. 클라이언트로부터 HTTP 요청을 받으면, 적절한 서비스 메서드를 호출하여 결과를 반환한다.
  • 경로, 요청 메서드(GET, POST, PUT, DELETE 등)를 정의하고 DTO를 사용해 데이터의 유효성을 검사할 수 있다.

Controller에서 라우팅 및 요청 데이터 처리

@Controller('users')
export class UserController {
  constructor(private readonly userService: UserService) {}

  @Get()
  findAll(@Query('limit') limit: number): Promise<User[]> {
    return this.userService.findAll(limit);
  }

  @Get(':id')
  findOne(@Param('id') id: string): Promise<User> {
    return this.userService.findOne(id);
  }

  @Post()
  create(@Body() createUserDto: CreateUserDto): Promise<User> {
    return this.userService.create(createUserDto);
  }
}
  • @Get(): HTTP GET 요청을 처리하는 메서드를 정의한다. 각각 모든 사용자를 조회하거나(findAll), 특정 사용자를 조회하는(findOne) 역할을 한다.

  • @Query('limit'): 요청의 쿼리 파라미터에서 데이터를 추출한다. 요청을 보내면, limit 쿼리 파라미터의 값이 findAll() 메서드로 전달된다.

  • @Param('id'): 요청 경로의 파라미터에서 데이터를 추출한다. /users/123와 같이 요청을 보내면, 123이 id로 전달되어 findOne() 메서드에서 사용된다.

  • @Post(): HTTP POST 요청을 처리하는 메서드를 정의한다.

  • @Body(): 요청 본문에서 데이터를 추출한다. 클라이언트가 사용자를 생성하기 위해 JSON 형식의 데이터를 전송하면, 이 데이터가 createUserDto로 전달되고, create() 메서드가 이를 사용해 새로운 사용자를 생성한다.

Service

  • 비즈니스 로직을 처리하는 곳으로, 데이터베이스와 상호작용하거나, 다른 복잡한 로직을 수행하는 데 사용된다.
  • 일반적으로 Controller에서 호출되며, 하나의 서비스는 여러 컨트롤러에서 재사용될 수 있다.

Service에서 비즈니스 로직 처리 및 의존성 주입

@Injectable()
export class ProductService {
  constructor(
    private readonly productRepository: ProductRepository,
    private readonly logger: LoggerService,
  ) {}

  findAll(): Promise<Product[]> {
    this.logger.log('Fetching all products');
    return this.productRepository.findAll();
  }
}
  • @Injectable(): 해당 클래스가 의존성 주입 시스템에 의해 주입될 수 있는 서비스임을 나타낸다.

  • 의존성 주입: ProductService 클래스는 ProductRepository와 LoggerService를 생성자에서 주입받는다. 이를 통해, 서비스는 필요한 의존성을 생성하지 않고도 사용할 수 있다. 의존성 주입은 테스트를 쉽게 하고, 모듈 간의 결합도를 낮추는 데 도움을 준다.

    • productRepository: 이 서비스는 실제 데이터베이스와 상호작용하여 데이터를 가져오거나 저장하는 역할을 한다.
    • logger: 이 서비스는 로깅 작업을 담당한다. findAll() 메서드가 호출될 때마다 "Fetching all products"라는 메시지를 로그에 기록한다.
  • 비즈니스 로직: findAll() 메서드는 비즈니스 로직을 처리한다. 이 메서드는 모든 제품을 가져오며, 로깅 작업을 수행한 후 데이터를 반환한다. 이 로직은 컨트롤러에서 호출될 수 있다.

0개의 댓글