5. Repository patterns
1. ID를 이용해서 특정 게시물을 가져오는 서비스/컨트롤러 만들기
이제 데이터베이스에 접근하여 특정 게시물을 가져올 수 있도록 다음과 같이 작성한다. 이전 코드와 다른 점은 boardRepository
를 이용하는 것과 async
/await
를 사용한다는 것이다. 그리고 async
/await
를 사용하기 때문에 Promise
객체를 반환하게 된다.
src/boards/boards.service.ts
import { Injectable, NotFoundException } from "@nestjs/common";
import { InjectRepository } from "@nestjs/typeorm";
import { Repository } from "typeorm";
import { BoardStatus } from "./board-status.enum";
import { Board } from "./board.entity";
import { CreateBoardDto } from "./dto/create-board.dto";
@Injectable()
export class BoardsService {
constructor(
@InjectRepository(Board) private boardRepository: Repository<Board>
) {}
async getBoardById(id: number): Promise<Board> {
const found = await this.boardRepository.findOneBy({ id });
if (!found) {
throw new NotFoundException(`Can't find Board with id ${id}`);
}
return found;
}
}
컨트롤러도 이에 맞게 작성한다. id
는 숫자여야 하므로 ParseIntPipe
를 추가한다.
src/boards/boards.controller.ts
import {
Body,
Controller,
Delete,
Get,
Param,
ParseIntPipe,
Patch,
Post,
UsePipes,
ValidationPipe,
} from "@nestjs/common";
import { BoardStatus } from "./board-status.enum";
import { Board } from "./board.entity";
import { BoardsService } from "./boards.service";
import { CreateBoardDto } from "./dto/create-board.dto";
import { BoardStatusValidationPipe } from "./pipes/board-status-validation.pipe";
@Controller("boards")
export class BoardsController {
constructor(private boardsService: BoardsService) {}
@Get("/:id")
getBoardById(@Param("id", ParseIntPipe) id: number): Promise<Board> {
return this.boardsService.getBoardById(id);
}
}
2. 게시물을 생성하는 서비스/컨트롤러 만들기
이번에는 게시물을 생성하는 부분을 처리해 보자.
import { Injectable, NotFoundException } from "@nestjs/common";
import { InjectRepository } from "@nestjs/typeorm";
import { Repository } from "typeorm";
import { BoardStatus } from "./board-status.enum";
import { Board } from "./board.entity";
import { CreateBoardDto } from "./dto/create-board.dto";
@Injectable()
export class BoardsService {
constructor(
@InjectRepository(Board) private boardRepository: Repository<Board>
) {}
async createBoard(createBoardDto: CreateBoardDto): Promise<Board> {
const { title, description } = createBoardDto;
const board = this.boardRepository.create({
title,
description,
status: BoardStatus.PUBLIC,
});
await this.boardRepository.save(board);
return board;
}
async getBoardById(id: number): Promise<Board> {
const found = await this.boardRepository.findOneBy({ id });
if (!found) {
throw new NotFoundException(`Can't find Board with id ${id}`);
}
return found;
}
}
import {
Body,
Controller,
Delete,
Get,
Param,
ParseIntPipe,
Patch,
Post,
UsePipes,
ValidationPipe,
} from "@nestjs/common";
import { BoardStatus } from "./board-status.enum";
import { Board } from "./board.entity";
import { BoardsService } from "./boards.service";
import { CreateBoardDto } from "./dto/create-board.dto";
import { BoardStatusValidationPipe } from "./pipes/board-status-validation.pipe";
@Controller("boards")
export class BoardsController {
constructor(private boardsService: BoardsService) {}
@Post("/")
@UsePipes(ValidationPipe)
createBoard(@Body() createBoardDto: CreateBoardDto): Promise<Board> {
return this.boardsService.createBoard(createBoardDto);
}
@Get("/:id")
getBoardById(@Param("id", ParseIntPipe) id: number): Promise<Board> {
return this.boardsService.getBoardById(id);
}
}
3. 게시물을 삭제하는 서비스/컨트롤러 만들기
게시물을 삭제하는 메서드는 remove()
와 delete()
가 있다. remove()
는 존재하는 아이템을 삭제하며, 존재하지 않는 경우 에러를 발생시킨다. 반대로 delete()
는 아이템이 존재하는 경우 삭제하며, 존재하지 않는 경우 어떤 메시지도 발생시키지 않는다.
import { Injectable, NotFoundException } from "@nestjs/common";
import { InjectRepository } from "@nestjs/typeorm";
import { Repository } from "typeorm";
import { BoardStatus } from "./board-status.enum";
import { Board } from "./board.entity";
import { CreateBoardDto } from "./dto/create-board.dto";
@Injectable()
export class BoardsService {
constructor(
@InjectRepository(Board) private boardRepository: Repository<Board>
) {}
async createBoard(createBoardDto: CreateBoardDto): Promise<Board> {
const { title, description } = createBoardDto;
const board = this.boardRepository.create({
title,
description,
status: BoardStatus.PUBLIC,
});
await this.boardRepository.save(board);
return board;
}
async getBoardById(id: number): Promise<Board> {
const found = await this.boardRepository.findOneBy({ id });
if (!found) {
throw new NotFoundException(`Can't find Board with id ${id}`);
}
return found;
}
async deleteBoard(id: number): Promise<void> {
const result = await this.boardRepository.delete(id);
if (result.affected === 0) {
throw new NotFoundException(`Can't find Board with id ${id}`);
}
}
}
import {
Body,
Controller,
Delete,
Get,
Param,
ParseIntPipe,
Patch,
Post,
UsePipes,
ValidationPipe,
} from "@nestjs/common";
import { BoardStatus } from "./board-status.enum";
import { Board } from "./board.entity";
import { BoardsService } from "./boards.service";
import { CreateBoardDto } from "./dto/create-board.dto";
import { BoardStatusValidationPipe } from "./pipes/board-status-validation.pipe";
@Controller("boards")
export class BoardsController {
constructor(private boardsService: BoardsService) {}
@Post("/")
@UsePipes(ValidationPipe)
createBoard(@Body() createBoardDto: CreateBoardDto): Promise<Board> {
return this.boardsService.createBoard(createBoardDto);
}
@Get("/:id")
getBoardById(@Param("id", ParseIntPipe) id: number): Promise<Board> {
return this.boardsService.getBoardById(id);
}
@Delete("/:id")
deleteBoard(@Param("id", ParseIntPipe) id: number): Promise<void> {
return this.boardsService.deleteBoard(id);
}
}
4. 게시물의 상태를 업데이트하는 서비스/컨트롤러 만들기
이번에는 게시물의 상태를 업데이트하는 부분을 처리해 보자.
import { Injectable, NotFoundException } from "@nestjs/common";
import { InjectRepository } from "@nestjs/typeorm";
import { Repository } from "typeorm";
import { BoardStatus } from "./board-status.enum";
import { Board } from "./board.entity";
import { CreateBoardDto } from "./dto/create-board.dto";
@Injectable()
export class BoardsService {
constructor(
@InjectRepository(Board) private boardRepository: Repository<Board>
) {}
async createBoard(createBoardDto: CreateBoardDto): Promise<Board> {
const { title, description } = createBoardDto;
const board = this.boardRepository.create({
title,
description,
status: BoardStatus.PUBLIC,
});
await this.boardRepository.save(board);
return board;
}
async getBoardById(id: number): Promise<Board> {
const found = await this.boardRepository.findOneBy({ id });
if (!found) {
throw new NotFoundException(`Can't find Board with id ${id}`);
}
return found;
}
async deleteBoard(id: number): Promise<void> {
const result = await this.boardRepository.delete(id);
if (result.affected === 0) {
throw new NotFoundException(`Can't find Board with id ${id}`);
}
}
async updateBoardStatus(id: number, status: BoardStatus): Promise<Board> {
const board = await this.getBoardById(id);
board.status = status;
await this.boardRepository.save(board);
return board;
}
}
import {
Body,
Controller,
Delete,
Get,
Param,
ParseIntPipe,
Patch,
Post,
UsePipes,
ValidationPipe,
} from "@nestjs/common";
import { BoardStatus } from "./board-status.enum";
import { Board } from "./board.entity";
import { BoardsService } from "./boards.service";
import { CreateBoardDto } from "./dto/create-board.dto";
import { BoardStatusValidationPipe } from "./pipes/board-status-validation.pipe";
@Controller("boards")
export class BoardsController {
constructor(private boardsService: BoardsService) {}
@Post("/")
@UsePipes(ValidationPipe)
createBoard(@Body() createBoardDto: CreateBoardDto): Promise<Board> {
return this.boardsService.createBoard(createBoardDto);
}
@Get("/:id")
getBoardById(@Param("id", ParseIntPipe) id: number): Promise<Board> {
return this.boardsService.getBoardById(id);
}
@Delete("/:id")
deleteBoard(@Param("id", ParseIntPipe) id: number): Promise<void> {
return this.boardsService.deleteBoard(id);
}
@Patch("/:id/status")
updateBoardStatus(
@Param("id", ParseIntPipe) id: number,
@Body("status", BoardStatusValidationPipe) status: BoardStatus
): Promise<Board> {
return this.boardsService.updateBoardStatus(id, status);
}
}
5. 모든 게시물을 가져오는 서비스/컨트롤러 만들기
이번에는 모든 게시물을 가져오는 부분을 처리해 보자.
import { Injectable, NotFoundException } from "@nestjs/common";
import { InjectRepository } from "@nestjs/typeorm";
import { Repository } from "typeorm";
import { BoardStatus } from "./board-status.enum";
import { Board } from "./board.entity";
import { CreateBoardDto } from "./dto/create-board.dto";
@Injectable()
export class BoardsService {
constructor(
@InjectRepository(Board) private boardRepository: Repository<Board>
) {}
async getAllBoards(): Promise<Board[]> {
const boards = await this.boardRepository.find();
return boards;
}
async createBoard(createBoardDto: CreateBoardDto): Promise<Board> {
const { title, description } = createBoardDto;
const board = this.boardRepository.create({
title,
description,
status: BoardStatus.PUBLIC,
});
await this.boardRepository.save(board);
return board;
}
async getBoardById(id: number): Promise<Board> {
const found = await this.boardRepository.findOneBy({ id });
if (!found) {
throw new NotFoundException(`Can't find Board with id ${id}`);
}
return found;
}
async deleteBoard(id: number): Promise<void> {
const result = await this.boardRepository.delete(id);
if (result.affected === 0) {
throw new NotFoundException(`Can't find Board with id ${id}`);
}
}
async updateBoardStatus(id: number, status: BoardStatus): Promise<Board> {
const board = await this.getBoardById(id);
board.status = status;
await this.boardRepository.save(board);
return board;
}
}
import {
Body,
Controller,
Delete,
Get,
Param,
ParseIntPipe,
Patch,
Post,
UsePipes,
ValidationPipe,
} from "@nestjs/common";
import { BoardStatus } from "./board-status.enum";
import { Board } from "./board.entity";
import { BoardsService } from "./boards.service";
import { CreateBoardDto } from "./dto/create-board.dto";
import { BoardStatusValidationPipe } from "./pipes/board-status-validation.pipe";
@Controller("boards")
export class BoardsController {
constructor(private boardsService: BoardsService) {}
@Get("/")
getAllBoards(): Promise<Board[]> {
return this.boardsService.getAllBoards();
}
@Post("/")
@UsePipes(ValidationPipe)
createBoard(@Body() createBoardDto: CreateBoardDto): Promise<Board> {
return this.boardsService.createBoard(createBoardDto);
}
@Get("/:id")
getBoardById(@Param("id", ParseIntPipe) id: number): Promise<Board> {
return this.boardsService.getBoardById(id);
}
@Delete("/:id")
deleteBoard(@Param("id", ParseIntPipe) id: number): Promise<void> {
return this.boardsService.deleteBoard(id);
}
@Patch("/:id/status")
updateBoardStatus(
@Param("id", ParseIntPipe) id: number,
@Body("status", BoardStatusValidationPipe) status: BoardStatus
): Promise<Board> {
return this.boardsService.updateBoardStatus(id, status);
}
}