Nest.js 입문
게시판 만들어보기 Part.1
board 모듈, 컨트롤러,서비스 생성
// 모듈
nest g mo board
// 컨트롤러
nest g co board
// 서비스
nest g s board
import { Controller } from '@nestjs/common';
@Controller('board')
export class BoardController {}
컨트롤러 데코레이터 옆에 문자열은 라우팅이다.!!!
이 컨트롤러는 /board 라는 주소 아래로 요청을 하면 해당 컨트롤러에서 처리
게시판 만들어보기 Part.2
lodash - Javascript로 코딩할 때 유용하게 사용할 수 있는 유틸성 패키지
lodash 패키지 설치
npm i lodash
ES6 모듈 사양을 준수하여 CommonJS 모듈을 가져올 수 있게
tsconfig.json 수정
"esModuleInterop": true
board.controller.ts
import { Controller, Delete, Get, Post, Put } from '@nestjs/common';
import { BoardService } from './board.service';
@Controller('board')
export class BoardController {
// 서비스 주입
constructor(private readonly boardService: BoardService) {}
//전체 게시글 가져오기
@Get('/articles')
getArticles() {
return this.boardService.getArticles();
}
//게시글 상세보기
@Get('/articles/:id')
getArticleById() {
return this.boardService.getArticleById(id);
}
// 게시글 작성
@Post('/articles')
createArticle() {
return this.boardService.createArticle();
}
// 게시글 수정
@Put('/articles/:id')
updateArticle() {
return this.boardService.updateArticle(id);
}
// 게시글 삭제
@Delete('/articles/:id')
deleteArticle() {
return this.boardService.deleteArticle(id);
}
}
POST, PUT의 경우에는 클라이언트로부터 데이터를 전달받아야 생성하거나 수정합니다.
Express에서는 req.body에 담긴 데이터를 받았는데 Nest.js에서는 어떻게 받아올까??
Nest.js에서는 클라이언트로부터 데이터를 받거나 데이터를 줘야 할 때는 DTO를 사용해야 합니다.
DTO (Data Transfer Object)는 클라이언트와 서버 간의 데이터 전송에 사용되는 객체
DTO는 서버로 전송되는 데이터를 표현하는 객체로,
데이터를 송신하는 클라이언트와 수신하는 서버 사이에서 인터페이스의 역할
class-validator 패키지로 입력값 유효성 검사
npm i class-validator
create-article.dto.ts
import { IsNumber, IsString } from 'class-validator';
export class CreateArticleDto {
@IsString()
readonly title: string;
@IsString()
readonly content: string;
@IsNumber()
readonly password: number;
}
update-article.dto.ts
import { IsNumber, IsString } from 'class-validator';
export class UpdateArticleDto {
@IsString()
readonly title: string;
@IsString()
readonly content: string;
@IsNumber()
readonly password: number;
}
delete-article.dto.ts
import { IsNumber } from 'class-validator';
export class DeleteArticleDto {
@IsNumber()
readonly password: number;
}
@IsString(), @IsNumber() 는 class-validator에서 제공하는 데코레이터이다.
각 dto.ts 코드를 보면 비슷하다
@nestjs/mapped-types 패키지를 사용해서 PartialType, PickType 등을 사용하면 코드를 깔끔하게 줄일수있다.
@nestjs/mapped-types 패키지 설치
npm i @nestjs/mapped-types
설치 중 오류가 난다면(의존성 이슈)
해당하는 패키지를 삭제 하고 제일 나중에 설치 하자
npm uninstall class-validator
npm i @nestjs/mapped-types
npm i class-validator
@nestjs/mapped-types 패키지를 사용해서 아래와 같이 코드를 줄일수있다.
update-article.dto.ts
import { PartialType } from '@nestjs/mapped-types';
import { CreateArticleDto } from './create-article.dto';
export class UpdateArticleDto extends PartialType(CreateArticleDto) {}
delete-article.dto.ts
import { PickType } from '@nestjs/mapped-types';
import { CreateArticleDto } from './create-article.dto';
export class DeleteArticleDto extends PickType(CreateArticleDto, [
'password',
] as const) {}
DTO의 유효성 검사를 하기 위해서 main.ts 수정
import { ValidationPipe } from '@nestjs/common';
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.useGlobalPipes(new ValidationPipe());
await app.listen(3000);
}
bootstrap();
유효성 검사 데코레이터는 DTO에서 한 번만 정의하면 된다.
board.controller.ts
import {
Body,
Controller,
Delete,
Get,
Param,
Post,
Put,
} from '@nestjs/common';
import { BoardService } from './board.service';
import { CreateArticleDto } from './create-article.dto';
import { DeleteArticleDto } from './delete-article.dto';
import { UpdateArticleDto } from './update-article.dto';
@Controller('board')
export class BoardController {
// 서비스 주입
constructor(private readonly boardService: BoardService) {}
//전체 게시글 가져오기
@Get('/articles')
getArticles() {
return this.boardService.getArticles();
}
//게시글 상세보기
@Get('/articles/:id')
getArticleById(@Param('id') articleId: number) {
return this.boardService.getArticleById(articleId);
}
// 게시글 작성
@Post('/articles')
createArticle(@Body() data: CreateArticleDto) {
return this.boardService.createArticle(
data.title,
data.content,
data.password,
);
}
// 게시글 수정
@Put('/articles/:id')
updateArticle(
@Param('id') articleId: number,
@Body() data: UpdateArticleDto,
) {
return this.boardService.updateArticle(
articleId,
data.title,
data.content,
data.password,
);
}
// 게시글 삭제
@Delete('/articles/:id')
deleteArticle(
@Param('id') articleId: number,
@Body() data: DeleteArticleDto,
) {
return this.boardService.deleteArticle(articleId, data.password);
}
}
board.service.ts
import {
Injectable,
NotFoundException,
UnauthorizedException,
} from '@nestjs/common';
import _ from 'lodash';
@Injectable()
export class BoardService {
// 데이터베이스를 사용하지 않아 일단은 배열로 구현
private articles = [];
// 게시글 비밀번호를 저장하기 위한 Map 객체입니다.
private articlePasswords = new Map();
getArticles() {
return this.articles;
}
getArticleById(id: number) {
return this.articles.find((article) => {
return article.id === id;
});
}
createArticle(title: string, content: string, password: number) {
// id 먼저 할당
// 1번부터 시작 => 현재 배열의 크기 + 1
const articleId = this.articles.length + 1;
this.articles.push({ id: articleId, title, content });
this.articlePasswords.set(articleId, password);
return articleId;
}
updateArticle(id: number, title: string, content: string, password: number) {
if (this.articlePasswords.get(id) !== password) {
throw new UnauthorizedException(
`Article password is not correct. id: ${id}`,
);
}
const article = this.getArticleById(id);
if (_.isNil(article)) {
throw new NotFoundException(`Article not found. id: ${id}`);
}
article.title = title;
article.content = content;
}
deleteArticle(id: number, password: number) {
if (this.articlePasswords.get(id) !== password) {
throw new UnauthorizedException(
`Article password is not correct. id: ${id}`,
);
}
this.articles = this.articles.filter((article) => {
return article.id !== id;
});
}
}
'코딩캠프 > 내일배움캠프' 카테고리의 다른 글
[ TIL ] 02.17(금) 68일차 (0) | 2023.02.17 |
---|---|
[ TIL ] 02.16(목) 67일차 (0) | 2023.02.16 |
[ TIL ] 02.14(화) 65일차 (0) | 2023.02.14 |
[ TIL ] 02.13(월) 64일차 (0) | 2023.02.13 |
[ WIL ] 02.06~10 13주차 (0) | 2023.02.12 |