nestjs

NestJS Quick Start

NestJS는 효율적이고 확장 가능한 Node.js 서버 프레임워크로, TypeScript를 기본 지원하며 강력한 아키텍처를 제공합니다. pnpm을 사용하여 빠르게 NestJS 프로젝트를 설정해 봅시다.

1. NestJS CLI 설치

NestJS 프로젝트 생성을 간편하게 하기 위해 NestJS CLI를 글로벌로 설치합니다.

cmd
➜ npm add -g @nestjs/cli

CLI를 설치하면, nest 명령어를 사용하여 프로젝트를 손쉽게 생성할 수 있습니다.

2. 프로젝트 생성

새로운 NestJS 프로젝트를 생성하려면 다음 명령어를 실행합니다.

cmd
➜ nest new sample-nestjs

여기서 패키지 매니저 선택 옵션이 나오면, 사용하고 있는 패키지 매니저를 선택하면 됩니다.(저는 pnpm을 선택했습니다.) 만약 자동으로 설치되지 않았다면 프로젝트 폴더로 이동한 후 직접 패키지를 설치할 수도 있습니다.

cmd
➜ cd sample-nestjs
➜ npm install

이제 기본적인 프로젝트 구조가 생성되었으며, NestJS 서버를 실행할 준비가 완료되었다고 할 수 있습니다.

3. 애플리케이션 실행

NestJS 서버를 실행하는 방법은 개발 및 운영 환경에 따라 다릅니다.

cmd
// 개발 모드(Development)
➜ npm run start:dev

단순한 start로 실행하면, 코드의 변화를 반영하려면 서버를 종료했다가 다시 실행해야하는 번거로움이 있습니다. 하지만 위 명령어는 파일 변경을 감지하여 자동으로 서버를 다시 시작하므로, 개발 중에 매우 유용합니다.

cmd
// 운영 모드 (Production)
➜ npm run start:prod

운영 환경에서는 최적화된 빌드를 사용하여 애플리케이션을 실행합니다.

4. 테스트 실행

NestJS는 기본적으로 유닛 테스트(Unit Test)와 E2E(End-to-End) 테스트 환경을 제공합니다.

cmd
// 유닛 테스트 실행
➜ npm run test

각 개별 모듈, 서비스, 컨트롤러의 동작을 검증할 때 사용됩니다.

cmd
// E2E 테스트 실행
➜ npm run test:e2e

애플리케이션의 전체적인 흐름을 테스트할 때 사용되며, API 요청과 응답을 포함한 통합 테스트를 수행합니다.


NestJS 프로젝트 기본 파일 구조

NestJS에서 프로젝트를 생성하면 기본적으로 /src 디렉터리 내에 핵심적인 4개의 파일이 생성됩니다. 이 파일들은 NestJS 애플리케이션의 핵심 아키텍처를 이루며, 각각의 역할을 이해하는 것이 NestJS의 첫 시작이라 할 수 있습니다.

/src
  /app.controller.ts : 요청을 처리하는 컨트롤러
  /app.module.ts : 애플리케이션의 루트 모듈
  /app.service.ts : 비즈니스 로직을 담당하는 서비스
  /main.ts : 애플리케이션의 실행을 담당하는 엔트리 포인트

1. app.controller.ts - 컨트롤러 (Controller)

NestJS의 컨트롤러(Controller)는 클라이언트의 요청을 처리하고, 응답을 반환하는 역할을 합니다. app.controller.ts 파일은 기본적으로 루트 경로(/)에 대한 요청을 처리하도록 설정됩니다. 컨트롤러는 @Controller() 데코레이터를 사용하여 정의되며, 내부에는 @Get(), @Post(), @Put() 등의 HTTP 메서드 핸들러가 포함될 수 있습니다.

app.controller.ts
@Controller()
export class AppController {
  constructor(private readonly appService: AppService) {}
 
  @Get()
  getHello(): string {
    return this.appService.getHello();
  }
}

예를 들어, app.controller.ts의 기본 코드에서는 @Get()을 통해 루트 경로에 대한 요청을 받아 "Hello World!"를 반환하도록 구현되어 있습니다. 이 파일을 확장하여 API 엔드포인트를 추가하고, 다양한 요청을 처리할 수 있습니다.

2. app.module.ts - 애플리케이션의 루트 모듈(Module)

NestJS는 모듈(Module) 기반 아키텍처를 따르며, app.module.ts는 애플리케이션의 루트 모듈(Root Module) 역할을 합니다. 모든 NestJS 애플리케이션은 최소한 하나의 모듈을 가져야 하며, 이 모듈 내에서 컨트롤러, 서비스, 다른 모듈들을 관리합니다.

app.module.ts
@Module({
  imports: [],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

이 파일에서는 @Module() 데코레이터를 사용하여 컨트롤러(Controllers), 프로바이더(Providers), 임포트된 모듈(Imports) 등을 정의합니다. 예를 들어, app.controller.ts와 app.service.ts가 AppModule에 등록되어 있어야 NestJS가 이를 정상적으로 인식하고 실행할 수 있습니다. 애플리케이션이 확장되면서 여러 개의 모듈을 생성하게 되는데, app.module.ts는 이들의 중심에서 역할을 하게 됩니다.

조금 더 세부적으로 확인해보면, 아래와 같습니다.

  • providers : ioc 인젝션 해줄 수 있는 부분 넣어 줍니다.
  • controller : 단순히 모듈의 controller가 포함됩니다.
  • imports : 다른 모듈을 불러들일 때 사용됩니다. 포함 시 따로 providers 할 필요 없이 바로 사용가능합니다.
  • exports : 모듈을 내보낼때 사용한다. 따라서 import에서 사용하려면 export에서 내보내야 사용가능합니다.

3. app.service.ts - 서비스(Service) 레이어

NestJS의 서비스(Service)는 비즈니스 로직을 처리하는 핵심적인 역할을 담당합니다. app.service.ts 파일은 기본적으로 app.controller.ts에서 사용되는 메서드를 제공하며, @Injectable() 데코레이터를 통해 의존성 주입(DI, Dependency Injection)이 가능하도록 설정됩니다.

app.service.ts
@Injectable()
export class AppService {
  getHello(): string {
    return 'Hello World!';
  }
}

컨트롤러는 사용자 요청을 받아 직접 로직을 처리하지 않고, 서비스에 위임하여 비즈니스 로직을 실행하는 것이 일반적인 패턴입니다. 예를 들어, app.controller.ts에서 app.service.ts를 호출하여 "Hello World!" 메시지를 가져오는 방식으로 동작합니다. 서비스는 데이터베이스 연동, API 호출, 복잡한 연산 등 컨트롤러가 직접 담당하지 않는 핵심 로직을 구현하는 데 사용됩니다.

4. main.ts - 애플리케이션의 엔트리 포인트(Entry Point)

main.ts는 NestJS 애플리케이션이 실행될 때 가장 먼저 실행되는 파일로, 애플리케이션의 엔트리 포인트(Entry Point) 역할을 합니다. 이 파일에서는 NestFactory를 사용하여 AppModule을 기반으로 NestJS 애플리케이션을 생성하고 실행합니다.

기본적으로 main.ts는 다음과 같은 기능을 수행합니다.

main.ts
async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  await app.listen(process.env.PORT ?? 3000);
}
bootstrap();

NestFactory.create(AppModule)을 호출하여 애플리케이션을 초기화합니다. .listen(3000)을 호출하여 서버를 포트 3000에서 실행합니다. 필요한 경우 global middleware, interceptors, pipes 등의 설정을 추가할 수 있습니다. NestJS 프로젝트에서 가장 먼저 실행되는 파일이므로, 환경 설정을 추가하거나 글로벌 미들웨어를 적용하는 등의 역할을 하게 됩니다.