Nest.js Install, Controller, Provider, Module
2021-07-25 13:41:27

소개

Node.js 웹프레임워크, 타입스크립트를 지원을 하며 내부는 기본으로 Express를 사용

꽤 구조적이고 체계적인 프레임워크 같다 (스프링 프레임워크과 비슷한 컨셉인듯?)

프로젝트 생성

nest cli를 통해 프로젝트를 생성할 수 있고 npm 또는 yarn 으로 관리할지 선택만 하면 된다

1
2
3
npm i -g @nestjs/cli # cli 설치
nest new 프로젝트명 # 프로젝트명으로 폴더가 생성되고, 필요한 모듈 모두 다운 받는다.
# 이후 npm || yarn 선택하면 생성됨

번외로 프로젝트 생성 시 _(언더스코어)가 포함된 프로젝트명은 -(하이픈)으로 자동 변경 된다 😮

실행

1
npm run start:dev # 개발 버전으로 실행, 코드 변경점이 있으면 바로 적용 된다.

package.json에 실행 및 유틸 명령어가 존재 한다

실행 코드는 main.ts에 bootstrap란 함수인데 포트번호 말곤 현재로선..

컨트롤러

1
nest g controller 컨트롤러명 # 컨트롤러명의 폴더에 컨트롤러, 테스트 컨트롤러 생성
1
2
3
4
5
6
7
8
import { Controller } from '@nestjs/common';

...

@Controller('user')
export class UserController {
...
}

@Controller 데코레이터를 통해 인식을 하는 듯 하다

값은 접근할 path, 예로 localhost:3000/user

Get

1
2
3
4
5
6
7
8
9
10
11
12
import { Controller, Get } from '@nestjs/common'; // 소스 최상단

...

@Controller('user')
export class UserController {
@Get() // localhost:3000/user로 접근 시
main(): string {
return 'Hello UserController!'; // 해당 문자열을 출력 한다.
}
...
}

@nestjs/common에서 Get을 선언 한 다음 @Get 데코레이터를 선언해줘야 한다

값이 없으면 컨트롤러 + 루트, 값을 적으면 컨트롤러 + 경로로 접근이 가능하다

1
2
3
4
5
6
7
8
import { Controller, Get, Query } from '@nestjs/common';

...

@Get('get-user') // localhost:3000/user/get-user
getUser(@Query('id') id: string): UserDto {
return this.userService.getUser(Number(id));
}

쿼리스트링은 @nestjs/common에서 Query를 선언 한 다음 @Query 데코레이터를 선언해줘야 한다

데이터 타입은 문자열로만 오며 존재하지 않을 시에는 undefined로 넘어온다

그리고 리턴을 객체로 하면 자동으로 JSON 변환 되어 응답 한다

POST

1
2
3
4
5
6
7
8
9
import { Controller, Get, Query, Post, Body } from '@nestjs/common';
import { DeleteUserDto } from './user.dto';
...

@Post('delete-user')
deleteUser(@Body() deleteUserDto: DeleteUserDto) {
const result = this.userService.deleteUser(deleteUserDto);
return result;
}
1
2
3
export class DeleteUserDto {
id: string
}

@nestjs/common에서 Post를 선언 한 다음 @Post 데코레이터를 선언해줘야 한다

값이 없으면 컨트롤러 + 루트, 값을 적으면 컨트롤러 + 경로로 접근이 가능하다

파라미터는 @Body를 선언(마찬가지로 nestjs/common에서 Body 선언 필요) 해야 하며

클래스를 통해 가져올 수 있다 근데 인터페이스나 타입 as 대신 클래스로 작성 하는 이유는

문서에 적혀 있긴 한데, 결론은 클래스로..

1
2
3
4
5
6
7
8
9
10
11
import { Controller, Get, Query, Post, Body, Response } from '@nestjs/common';
import { DeleteUserDto, createUserDto } from './user.dto';

...

@Post('create-user')
createUser(@Body() createUserDto: CreateUserDto, @Response() res): Res {
const accessToken = Common.makeAccessToken();
const result = this.userService.createUser(createUserDto);
return res.set({ 'x-access-token': accessToken }).json(result);
}
1
2
3
4
export class CreateUserDto {
name: Types.Name;
age: Types.Age;
}

헤더에 동적인 데이터를 넣기 위해서는 @nestjs/common에서 Response를 선언해줘야 하고

리턴은 Express 방식대로 해줘야 한다

@Header 데코레이터도 있던데 동적으로는 동작하지 않고 정적으로만 사용 가능했다

프로바이더

1
nest g service 서비스명 # user로 적으면 컨트롤러처럼 user 폴더에 서비스, 테스트 파일이 생성

문서 제목은 프로바이더로 되어 있는데 정작 생성 명령어는 서비스..

1
2
3
4
5
import { Injectable } from '@nestjs/common';
@Injectable()
export class UserService {
...
}

컨트롤러와 동일하게 클래스로 생성이 되는데 데코레이터만 바뀌었다 간단하게 몇개만 작성하고 패스

모듈

1
nest g module 모듈명

이부분이 오늘 본 거 중에 제일 흥미로웠다

예로 유저 모듈이면 유저와 관련된 컨트롤러, 서비스, 모델 등등을 하나로 묶어서

어플리케이션 모듈(app.module)에 주입 시키면 끝 👍🏻

1
2
3
4
5
6
7
8
9
import { Module } from '@nestjs/common';
import {UserController} from './user.controller';
import {UserService} from './user.service';

@Module({
controllers: [UserController],
providers: [UserService]
})
export class UserModule {}

생성된 모듈에 작성한 컨트롤러와 서비스 파일을 주입 시켜 주고 나서 app.module에 넣으면 끝

1
2
3
4
5
6
7
8
9
10
11
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { UserModule } from './user/user.module';

@Module({
imports: [UserModule],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}

기존에는 컨트롤러 폴더, 서비스 폴더, 모델 폴더 등등 폴더벌로 나누었는데

위의 방식이 더 신선하고 유지보수적인 측면에서 좋을 꺼 같다 (공통적인 건 다른 폴더로)

참고