따라하면서 배우는 NestJS 를 따라가면서 간단하게 게시판 애플리케이션을 만들어보고자 한다.
예전에도 NestJS를 사용해봤지만 기초부터 차근차근 하면서 글로 정리할 것이다.
해당 프로젝트의 개요는 다음과 같다.

nest new ./npm run start:deveslintrc.js
prettierrc
nest-cli.json
tsconfig.json
tsconfig.build.json
package.json
src 폴더
// main.ts
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
// AppModule에 등록된 정보를 통해 앱을 생성한다.
await app.listen(3000);
// 앱 실행
}
bootstrap();
// app.controller.ts
import { Controller, Get } from '@nestjs/common';
import { AppService } from './app.service';
@Controller()
export class AppController {
constructor(private readonly appService: AppService) {}
@Get('/')
// http://localhost:3000/로 get 요청이 들어올때 실행되는 함수
getHello(): string {
return this.appService.getHello();
}
}
// app.service.ts
import { Injectable } from '@nestjs/common';
@Injectable()
export class AppService {
getHello(): string {
return 'Hello World!'; // Hello World! 를 반환
}
}
흐름을 파악한 후 필요한 파일만 남기도록 파일을 정리해주자.
파일 삭제하기
app.controller.spec.ts
app.controller.ts
app.service.ts
=> 위의 파일 삭제
app.module.ts에서 삭제한 파일에 대한 에러 수정하기
// app.module.ts
import { Module } from '@nestjs/common';
@Module({
imports: [],
})
export class AppModule {}
모듈은 @Module() 데코레이터가 달린 클래스를 의미한다.
@Module() 데코레이터는 Nest가 애플리케이션 구조를 구성하는 데 사용하는 메타데이터를 제공한다.
각 애플리케이션에는 하나 이상의 모듈(루트 모듈)이 있으며 루트 모듈은 Nest가 사용하는 시작점이다.
모듈은 밀접하게 관련된 기능 집합으로 구성 요소를 구성하는 효과적인 방법이다. (ex. 유저 모듈, 주문 모듈, 챗 모듈...)
같은 기능에 해당하는 것들은 하나의 모듈 폴더 안에 넣어서 사용한다. (UserController, UserService, UserEntity 다 같은 기능이기에 UserModule 안에 넣는다.)
모듈은 기본적으로 싱글톤이므로 여러 모듈간에 쉽게 공급자의 동일한 인스턴스를 공유할 수 있다.
nest g module boards
명령어를 사용하면 boards 폴더를 생성하고 그 안에 boards.module.ts 파일이 생성되고 이 생성된 파일을 app.module.ts에서 알 수 있도록 수정이 되었다.
이제부터 위에서 흐름을 파악한 것과 같이 로직을 작성해보면된다.
컨트롤러는 들어오는 요청을 처리하고 클라이언트에 응답을 반환한다.
@Controller() 데코레이터로 클래스를 정의하며 데코레이터의 인자로 들어오는 값이 Controller에 의해서 처리되는 "경로"다.
Hendller
@Get, @Post, @Delete 등과 같은 데코레이터로 장식된 컨트롤러 클래스 내의 단순한 메서드
nest g controller boards --no-spec
명령어를 사용하면 cli가 boards 폴더를 찾아서 안에 boards.controller.ts 파일을 생성한다.
boards 폴더 안에 module 파일을 찾아서 controller를 등록하도록 수정한다.
컨트롤러에서 요청한 데이터 및 정보를 주기 위해 비즈니스 로직을 처리한다.
nest g service boards --no-spec
@Injectable() 데코레이터를 통해 nestJS 프로젝트 내의 다른 컴포넌트에서 이 서비스를 사용할 수 있다.
사용하는 방법은 다음과 같이 controller에서 사용하는 예시를 통해 보자.
// boards.controller.ts
import { Controller } from '@nestjs/common';
import { BoardsService } from './boards.service';
@Controller('boards')
export class BoardsController {
boardsService: BoardsService;
// 3. typescript에서는 선언한 값만 객체의 프로퍼티로 사용할 수 있기때문에 위와 같이 선언
constructor(boardsService: BoardsService) { // 1. BoardsService 타입 지정
this.boardsService = boardsService;
// 2. boardsService 를 BoardsController 클래스 내에서 사용하기 위해서 this.boardsService 에 할당
}
// 4. boardsService 라는 프로퍼티를 통해 BoardsService 사용 가능
}
위와 같은 코드는 TypeScript의 private와 같은 접근제한자를 사용하여 다음과 같이 작성할 수 있다.
private과 같이 생성자 안에서 사용할 경우 인수인 파라미터가 암묵적으로 클래스의 프로퍼티로 선언이 된다.
// boards.controller.ts
import { Controller } from '@nestjs/common';
import { BoardsService } from './boards.service';
@Controller('boards')
export class BoardsController {
constructor(private boardsService: BoardsService) {}
}
프로바이더는 Nest의 기본 개념이며, 대부분의 기본 Nest 클래스는 서비스, 레포지토리, 팩토리, 헬퍼등 프로바이더로 취급할 수 있다.
프로바이더는 종속성을 주입할 수 있다.
위의 챕터에서와 같이 서비스를 컨트롤러에 주입한 것과 같다.
provider를 사용하기 위해서는 module에 다음과 같이 등록이 되어있어야한다.
// boards.module.ts
import { Module } from '@nestjs/common';
import { BoardsController } from './boards.controller';
import { BoardsService } from './boards.service';
@Module({
controllers: [BoardsController],
providers: [BoardsService], // 등록
})
export class BoardsModule {}