NestJS 기초 사용 방법
NestJS 기초 사용 방법에 대해 설명하는 페이지입니다.
Tags
TypeScript, NestJS
Environment
Node.js v20.11.1
@nestjs/cli v10.3.2
reflect-metadata v0.2.2
1. 개요
이번 글에서는 NestJS 기초 사용 방법에 대해 설명하도록 하겠습니다.
2. Step 1 - NestJS 애플리케이션 생성
다음 명령어를 입력하여 @nestjs.cli를 사용하여 NestJS 애플리케이션을 생성합니다.
1npx @nestjs/cli new [프로젝트 이름]명령어를 입력하면 어떤 패키지 매니저를 사용할 것인지를 결정해야 합니다. 저의 경우 npm을 선택하였습니다.
1? Which package manager would you ❤️ to use? npm3. Step 2 - eslintrc 설정 파일 수정
자신이 사용하는 운영체제에 따라 다음과 같은 오류가 발생할 수 있습니다.

이 오류가 발생하는 경우 .eslintrc.js 파일을 열고 다음과 같이 endOfLine에 내용을 추가하거나 변경하면 됩니다.
1rules: {
2
3 /* ... */
4
5 'prettier/prettier': [
6 'error',
7 {
8 endOfLine: 'auto',
9 },
10 ],
11},4. Step 3 - Folder Structure / Architecture 확인하기
nest-cli로 생성한 프로젝트 구조는 다음과 같습니다.
1├── src
2| ├── app.controller.spec.ts // 컨트롤러 테스트 코드
3| ├── app.controller.ts // 컨트롤러
4| ├── app.module.ts // 모듈
5| ├── app.service.ts // 서비스
6| └── main.ts // 서비스 메인 파일
7├── .gitignore // git 버전 관리에서 제외할 목록 지정
8├── .prettierrc // 코드 포매팅 관련 설정 파일
9├── nest-cli.json // nest-cli 설정
10└── (...)4.1. NestJS의 Naming 규칙
NestJS의 Naming Convention은 다음과 같습니다.
- 파일명은
.으로 연결하며, 모듈이 둘 이상의 단어로 구성되어 있으면대시로 연결합니다.plaintext1// <모듈명>.<컴포넌트명>.ts 2blog.controller.ts 3my-first.controller.ts - 클래스명은
Pascal Case로 표기합니다.plaintext1// <모듈명><컴포넌트명> 2BlogController - 같은 디렉토리에 있는 클래스는 index.ts를 통해서 임포트하는 것이 권장됩니다.
- 인터페이스를 사용해서 타입을 정의하고 구체적인 내용을 클래스를 만들어 인터페이스를 상속하는 방식으로 작성합니다.
4.2. main.ts
main.ts 파일은 NestJS 서버의 시작점이 되는 파일입니다. NestJS에서는 진입점을 bootstrap()으로 하는 것이 관례입니다.
1import { NestFactory } from "@nestjs/core";
2import { AppModule } from "./app.module";
3
4// NestJS를 실행시키는 함수
5// NestJS에서는 진입점을 bootstrap()으로 이름 짓는 것이 관례이다.
6async function bootstrap() {
7 // NestFactory를 사용해서 NestApplication 객체 생성
8 const app = await NestFactory.create(AppModule);
9
10 // 3000번 포트로 서버 기동
11 await app.listen(3000);
12}
13
14bootstrap();4.3. 모듈명.controller.ts
컨트롤러는 유저가 보낸 HTTP 요청을 어떤 코드에서 처리할지 결정하는 역할을 합니다.
1import { Controller, Get } from "@nestjs/common";
2import { AppService } from "./app.service";
3
4@Controller() // 컨트롤러 데코레이터
5export class AppController {
6 // 외부에서 사용하므로 export를 붙임.
7
8 constructor(private readonly appService: AppService) {}
9
10 @Get() // GET 요청 처리 데코레이터
11 getHello(): string {
12 return this.appService.getHello();
13 }
14}4.4. 모듈명.service.ts
서비스는 비즈니스 로직을 담는 파일입니다.
1import { Injectable } from "@nestjs/common";
2
3@Injectable()
4export class AppService {
5 getHello(): string {
6 return "Hello World! 안녕하세요!";
7 }
8}4.5. 모듈명.module.ts
모듈은 수평적으로 흩어진 Provider와 Controller들을 논리적인 기능이나 도메인에 따라 하나로 묶어주는 역할을 하며, 재사용성을 높여줍니다.
1import { Module } from "@nestjs/common";
2import { AppController } from "./app.controller";
3import { AppService } from "./app.service";
4import { BlogModule } from "./blog/blog.module";
5
6// 모듈 데코레이터
7@Module({
8 imports: [],
9 controllers: [AppController],
10 providers: [AppService],
11})
12export class AppModule {}5. Step 4 - Blog API 만들기
데이터베이스를 사용하지 않는 간단한 Blog API를 만들어 보겠습니다. 먼저 다음과 같이 모듈 단위로 애플리케이션을 구성합니다.
1├── src
2| ├── app.controller.spec.ts
3| ├── app.controller.ts
4| ├── app.module.ts
5| ├── app.service.ts
6| ├── main.ts
7| └── modules
8| └── blog
9| ├── blog.controller.ts
10| ├── blog.module.ts
11| ├── blog.service.ts
12| └── dtos
13| └── blog.dto.ts
14└── (...)modules 디렉토리에 도메인별 모듈을 저장합니다. 각 모듈은 해당 기능과 관련된 컨트롤러, 서비스, DTO 등을 포함합니다.
5.1. blog.controller.ts
1import {
2 Body,
3 Controller,
4 Delete,
5 Get,
6 Param,
7 Post,
8 Put,
9} from "@nestjs/common";
10import { BlogService } from "./blog.service";
11import { PostDto } from "./dtos/blog.dto";
12
13@Controller("blog") // 클래스에 붙이는 Controller 데코레이터
14export class BlogController {
15 constructor(private readonly blogService: BlogService) {}
16
17 @Get() // GET 요청 처리하기
18 getAllPost() {
19 console.log("모든 게시글 가져오기");
20 return this.blogService.getAllPosts();
21 }
22
23 @Post() // POST 요청 처리하기
24 createPost(@Body() postDto: PostDto) {
25 // HTTP 요청의 body 내용을 post에 할당
26 console.log("게시글 작성");
27 this.blogService.createPost(postDto);
28 return "success";
29 }
30
31 @Get("/:id") // GET 요청에 URL 매개변수에 id가 있는 요청 처리
32 getPost(@Param("id") id: string) {
33 console.log("게시글 하나 가져오기");
34 return this.blogService.getPost(id);
35 }
36
37 @Delete("/:id") // DELETE 방식에 URL 매개변수로 id가 있는 요청 처리
38 deletePost(@Param("id") id: string) {
39 console.log("게시글 삭제");
40 this.blogService.delete(id);
41 return "success";
42 }
43
44 @Put("/:id") // PUT 방식에 URL 매개변수로 전달된 id가 있는 요청 처리
45 updatePost(@Param("id") id: string, @Body() postDto: PostDto) {
46 console.log("게시글 업데이트", id, postDto);
47 return this.blogService.updatePost(id, postDto);
48 }
49}위의 코드에서 Get, Post, Delete, Put 등의 데코레이터는 모두 함수에 붙이는 것으로,
HTTP 요청 방식에 따라 해당 데코레이터가 붙은 함수를 실행합니다.
@Body는 함수의 body로 오는 값을 매개변수에 할당하며, @Param은 URL param의 값을 함수 매개변수에 할당합니다.
5.2. blog.service.ts
1import { Injectable } from "@nestjs/common";
2import { PostDto } from "./dtos/blog.dto";
3
4@Injectable()
5export class BlogService {
6 posts: PostDto[] = []; // 게시글 배열 선언
7
8 // 모든 게시글 가져오기
9 getAllPosts() {
10 return this.posts;
11 }
12
13 // 게시글 작성
14 createPost(postDto: PostDto) {
15 const id = this.posts.length + 1;
16 this.posts.push({
17 id: id.toString(),
18 ...postDto,
19 createdAt: new Date(),
20 });
21 }
22
23 // 게시글 하나 가져오기
24 getPost(id: string) {
25 const post = this.posts.find((post) => post.id === id);
26 console.log(post);
27 return post;
28 }
29
30 // 게시글 삭제
31 delete(id: string) {
32 const filteredPosts = this.posts.filter((post) => post.id !== id);
33 this.posts = [...filteredPosts];
34 }
35
36 // 게시글 업데이트
37 updatePost(id: string, postDto: PostDto) {
38 const updateIdx = this.posts.findIndex((post) => post.id === id);
39 const updatePost = { id, ...postDto, updatedAt: new Date() };
40 this.posts[updateIdx] = updatePost;
41 return updatePost;
42 }
43}Blog API 로직을 위와 같이 service 파일에 작성합니다.
5.3. blog.module.ts
1import { Module } from "@nestjs/common";
2import { BlogController } from "./blog.controller";
3import { BlogService } from "./blog.service";
4
5@Module({
6 imports: [],
7 controllers: [BlogController],
8 providers: [BlogService],
9 exports: [],
10})
11export class BlogModule {}위와 같이 blog 컨트롤러와 서비스를 모듈 파일에 선언합니다.
5.4. blog.dto.ts
1// 게시글의 타입을 인터페이스로 정의
2export interface PostDto {
3 id: string;
4 title: string;
5 content: string;
6 name: string;
7 createdAt: Date;
8 updatedAt?: Date; // 수정 일시는 필수가 아님.
9}Dto란 data transfer object의 약자입니다. 주로 데이터 전송을 위한 객체로, 애플리케이션 계층 간에 데이터를 주고받을 때 사용됩니다.
타입스크립트에서는 데이터만 가지고 있는 타입을 선언할 때 클래스보다는 인터페이스를 많이 사용합니다.
5.5. app.module.ts
작성한 Blog 모듈을 사용하기 위해 다음과 같이 app 디렉토리의 최상위 모듈 파일에 모듈을 import 합니다.
1import { Module } from "@nestjs/common";
2import { AppController } from "./app.controller";
3import { AppService } from "./app.service";
4import { BlogModule } from "./modules/blog/blog.module";
5
6// 모듈 데코레이터
7@Module({
8 imports: [BlogModule],
9 controllers: [AppController],
10 providers: [AppService],
11})
12export class AppModule {}6. Step 5 - Postman으로 테스트하기
6.1. 서버 실행하기
Postman을 사용하여 위의 API가 잘 작동하는지 확인하도록 하겠습니다. 먼저 다음 명령어를 입력하여 서버를 시작합니다.
1npm run start서버를 시작하는 방법은 위 방법 외에도 다음과 같은 방법이 있습니다. 이에 대해선 package.json 파일을 참고하시길 바랍니다.
1npm run start // 서버 시작
2npm run start:dev // development 모드로 실행할 때 사용
3npm run start:prod // production 모드로 실행할 때 사용6.2. 게시글 작성


6.3. 게시글 조회

