
node.js 서버 어플리케이션을 조금 더 쉽게 이용하기 위한 프레임워크. progressive javascript 사용, Typescript로 빌드 가능.
내부적으로 Express(defuault)와 같은 HTTP 서버 프레임워크를 사용.
nest.js 공식 문서 https://docs.nestjs.com/
npm i -g @nestjs/cli
nest new project-name
당연히 node.js가 미리 설치되어 있어햐 한다. (v18.15.0 사용 중)
위 명령어를 통해 기본 프로젝트 뼈대를 만들거나 (create-react-app처럼) nest.js에서 제공하는 스타터 프로젝트를 클론해도 된다.

package manager를 선택해주고 잠시 기다리면 이렇게 귀여운 이모지와 함께 프로젝트가 생성된다. (CLI에 이모지라니 새롭다)

이쯤에서 github 저장소를 연결해주고 폴더 구조를 살펴보자.

package.json을 보면 일반 react app보다 많은 스크립트를 제공해준다.

기본 src 폴더는 이렇게 생겼다.

main.ts
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
await app.listen(3000);
}
bootstrap();
NestFactory 클래스의 create 함수로 어플리케이션을 생성한다. 이때 사용되는 모듈이 바로 app.module.ts에 정의된 루트 모듈.
생성한 nest.js 프로젝트를 한 번 실행시켜 보자. 기본 포트는 3000번이다.
npm run start

React 보다 더 심플한 Hello World!가 반겨준다.
개발 모드 스크립트는 따로 있다. (package.json 참고)
npm run start:dev
저 심플한 'Hello World!'는 어디서 왔을까?
app.service.ts에서 발견할 수 있다. 어디서 많이 본 데코레이터가 보인다.
import { Injectable } from '@nestjs/common';
@Injectable()
export class AppService {
getHello(): string {
return 'Hello World!';
}
}
AppService는 app.module.ts를 살펴보면 그 속에서 등록되어 사용되는 것을 볼 수 있다.
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
@Module({
imports: [],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
마찬가지로 app.controller.ts 속의 AppController도 함께 등록된다. 모든 요청은 controller가 처리한다.
import { Controller, Get } from '@nestjs/common';
import { AppService } from './app.service';
@Controller()
export class AppController {
constructor(private readonly appService: AppService) {}
@Get()
getHello(): string {
return this.appService.getHello();
}
}
GET 메서드로 '/'에 요청을 보내면 getHello라는함수가 받아 appService.getHello()를 반환한다. 아까 본 그 'Hello World!'를 반환하는 그 함수이다.
따라서 AppController는 라우터 역할을 해서 각 엔드포인트의 요청을 받고, 그 요청은 AppService에 정의된 메서드가 받아 처리한다. 이처럼 Nest.js에서는 모듈별로 controller와 service를 생성하고 그것을 app.module.ts에 등록하여 사용한다.
Nest.js는 Angular의 영향을 받아 만들어졌다는데 Angular는 사용해보지 않아서 모르겠지만 python의 Flask와도 비슷한 로직 같아서 크게 낯설지는 않다. Express.js에 Flask의 데코레이터를 섞은 느낌이다.
조금 전 살펴본 AppModule이 nest.js의 루트 모듈이다. 모듈은 @Module() 데코레이터로 생성할 수 있다. 모듈은 controller와 service 외에도 entity, repository, pipe 등의 구성 요소를 가진다. 쉽게 말해 모듈이 각 기능을 담당하는 구성 요소들을 모아둔 집합이다. 모듈은 다른 모들에서 쓰일 수 있다. 하나의 모듈을 다른 여러 모듈에서 쓰는 것도 가능하다.
모듈을 만들어보자. nest에서 제공하는 명령어로 만들 수 있다. 직접 파일을 생성하지 않아도 되어 편하다.
nest g module module_name
모듈의 이름으로 된 폴더와 module.ts 파일이 생성된다. app.module.ts에도 새 모듈이 자동으로 import 된다.

Nest의 기본 구성 요소. Service, Repository, Service, Helper, Factory 등이 있다. 종속성 주입(Dependency Injection)을 사용하면 모듈 또는 프로바이더 간의 인스턴스를 쉽게 공유할 수 있다. 예를 들어 한 컨트롤러에서 여러 서비스를 사용할 수 있다. 필요한 모듈에 등록하여 사용한다.
컨트롤러는 요청을 처리하고 클라이언트에 응답을 반환한다. @Controller 데코레이터로 컨트롤러 클래스를 생성할 수있다. @Get, @Post 등의 핸들러를 정의해서 각 endpoint의 요청을 처리한다.
컨트롤러도 마찬가지로 nest의 명령어로 생성할 수 있다.
nest g controller controller_name --no-spec // test 생략
controller.ts 파일이 생성되고 모듈에도 해당 컨트롤러가 등록된다.

@Injectable 데코레이터로 정의되며 서비스 인스턴스는 application 전체에서사용할 수 있다. 앞서 살펴본 예시코드처럼 컨트롤러에서 request를 처리하기 위한 작업(유효성 검증, 데이터베이스 쿼리 등)을 실행한다.
서비스를 생성할 때도 nest 명령어를 사용한다.
nest g service service_name --no-spec // test 생략
service.ts 파일이 생성되고 모듈의 provider에 등록된다.

constructor(생성자)를 사용하여 종속성을 주입한다.
@Controller('boards')
export class BoardsController {
boardsService : BoardsService; //property
constructor(boardsService:BoardsService){ //parameter
this.boardsService = boardsService
}
}
boardsService라는 이름의 클래스 property에 주입하려는 서비스를 삽입해주면된다.
typescript의 접근 제한자를 이용하면 간단하게 종속성을 주입할 수 있다.
@Controller('boards')
export class BoardsController {
constructor(private boardsService:BoardsService){}
}
접근 제한자(public, protected, private)를 생성자 파라미터에 선언하면 암묵적으로 클래스의 property로 선언되는 것을 이용한다. 물론 pure javascript에는 접근 제한자가 없으므로 이러한 방식을 사용할 수는 없다.