| 서론
안녕하세요, 팡일입니다
이번 글에서는 간단한 게시글 예제를 통해 Nest.js에서 제공하는 데코레이터를 활용하여 CRUD API를 직접 구현하는 과정을 정리해보았습니다.
Controller와 Service를 어떻게 나누고, 각 HTTP 메서드가 어떤 역할을 하는지 흐름 중심으로 이해해보시면 좋을 것 같습니다.
| GET 데코레이터
GET 요청은 서버에서 데이터를 조회할 때 사용하는 HTTP 메서드입니다.
Nest.js에서는 @Get() 데코레이터를 사용하여 해당 요청을 처리할 수 있습니다.
이번 예제에서는 간단한 게시글 데이터를 기반으로 전체 조회 / 단건 조회 API를 구현해보겠습니다.
1) interface 생성
먼저 게시글 데이터의 구조를 정의하기 위해 인터페이스를 생성합니다.
// board.type.ts
export interface Board {
id: string;
title: string;
content: string;
}
인터페이스를 정의하면, 데이터의 형태를 명확하게 관리할 수 있고, 타입 안정성도 확보할 수 있습니다.
2) 목데이터 생성
DB를 연결하기 전이기 때문에, Service 내부에 간단한 목(mock) 데이터를 생성합니다.
private boards: Board[] = [
{
id: '1',
title: '첫 번째 게시글의 제목',
content: '첫 번재 게시글의 본문',
},
{
id: '2',
title: '두 번째 게시글의 제목',
content: '두 번재 게시글의 본문',
},
{
id: '3',
title: '세 번째 게시글의 제목',
content: '세 번재 게시글의 본문',
},
];
실제 서비스에서는 DB에서 데이터를 가져오지만, 학습 단계에서는 이렇게 목데이터로 흐름을 먼저 이해하는 것이 중요합니다.
3) 실제 Service 함수에 변경
이제 Service에서 데이터를 반환하는 로직을 구현합니다.
findAll() {
// return 'findAll 호출';
return this.boards;
}
findOne(id: string): Board {
// return `게시물 조회 (ID : ${id})`;
const board = this.boards.find((board) => board.id === id);
if (!board) {
throw new NotFoundException(
`ID ${id}에 해당하는 게시글을 찾을 수 없습니다.`,
);
}
return board;
}
- findAll : 저장된 게시글 전체를 그대로 반환한다.
- findOne : 특정 ID에 해당하는 게시글을 찾아 반환한다.
- 만약 데이터가 존재하지 않으면, NotFoundException을 발생시켜 에러를 처리한다.
| POST 데코레이터
POST 요청은 서버에 새로운 데이터를 생성할 때 사용하는 HTTP 메서드입니다.
Nest.js에서는 @Post() 데코레이터를 사용하여 데이터를 생성하는 API를 구현할 수 있습니다.
이번 예제에서는 게시글을 새롭게 생성하는 기능을 구현해보겠습니다.
1) 실제 Controller에 반영
먼저 Controller에서 클라이언트의 요청을 받아 Service로 전달합니다.
@Post()
create(@Body() data: any) {
return this.boardService.create(data);
}
- @Post()
→ POST 요청을 처리하는 메서드 - @Body()
→ 클라이언트가 보낸 요청 데이터(Request Body)를 추출
즉, Controller는 데이터를 직접 처리하지 않고, Service로 전달하는 역할만 수행합니다.
2) 실제 Service에 반영
이제 실제 데이터 생성 로직은 Service에서 구현합니다.
create(data: any) {
const newBoard = { id: this.generateId(), ...data };
this.boards.push(newBoard);
return newBoard;
}
전달받은 데이터를 기반으로 새로운 게시글을 생성하고, 배열에 추가한 뒤, 생성된 데이터를 반환합니다.
(1) ID 생성 함수
generateId() {
return this.boards.length === 0
? 1
: Math.max(...this.boards.map((board) => board.id)) + 1;
}
현재 게시글 목록에서 가장 큰 ID를 찾아 +1을 하여, 중복되지 않는 새로운 ID를 생성합니다.
3) 테스트 in POSTMAN
이제 API가 정상적으로 동작하는지 테스트해봅니다.
// Request Body
{
"title" : "다섯 번째 포스팅 제목",
"content" : "다섯 번째 포스팅 내용"
}
위와 같이 요청을 보내면, 아래의 사진과 같이, 새로운 게시글이 생성되고, 응답으로 생성된 데이터가 반환됩니다.

| PUT 데코레이터
PUT 요청은 기존 데이터를 수정할 때 사용하는 HTTP 메서드입니다.
Nest.js에서는 @Put() 데코레이터를 통해 특정 리소스를 수정하는 API를 구현할 수 있습니다.
이번 예제에서는 특정 ID를 가진 게시글을 수정하는 기능을 구현해보겠습니다.
1) 실제 Controller에 반영
먼저 Controller에서 클라이언트의 요청을 받아 Service로 전달합니다.
@Put(':id')
update(@Param('id') id: number, @Body() data: any): Board {
return this.boardService.update(Number(id), data);
}
- @Put(':id')
→ 특정 ID를 가진 데이터를 수정하는 요청 처리 - @Param('id')
→ URL 경로에서 ID 값을 추출 - @Body()
→ 클라이언트가 보낸 수정 데이터를 가져옴
즉, Controller는 요청을 받고, Service로 전달하는 역할만 수행합니다.
2) 실제 Service에 반영
이제 실제 데이터 수정 로직은 Service에서 구현합니다.
update(id: number, data: any) {
const boardIndex = this.boards.findIndex((board) => board.id === id); // findIndex는 못 찾으면 -1을 반환
if (boardIndex === -1) {
throw new NotFoundException(
`ID ${id}에 해당하는 게시글을 찾을 수 없습니다.`,
);
}
this.boards[boardIndex] = { ...this.boards[boardIndex], ...data };
return this.boards[boardIndex];
}
- findIndex를 사용하여 수정할 데이터의 위치를 찾음
- 존재하지 않으면 예외 처리 (NotFoundException)
- 기존 데이터에 새로운 데이터를 덮어쓰기 방식으로 수정
즉, 기존 데이터를 업데이트하는 방식으로 동작합니다.
3) 테스트 in POSTMAN

PUT /board/4 요청을 보내면, ID가 4인 게시글이 수정됩니다.
| DELETE 데코레이터
DELETE 요청은 기존 데이터를 삭제할 때 사용하는 HTTP 메서드입니다.
Nest.js에서는 @Delete() 데코레이터를 사용하여 특정 리소스를 삭제하는 API를 구현할 수 있습니다.
이번 예제에서는 특정 ID를 가진 게시글을 삭제하는 기능을 구현해보겠습니다.
1) 실제 Controller에 반영
먼저 Controller에서 클라이언트의 요청을 받아 Service로 전달합니다.
@Delete(':id')
delete(@Param('id') id: number): Board[] {
return this.boardService.delete(Number(id));
}
- @Delete(':id')
→ 특정 ID를 가진 데이터를 삭제하는 요청 처리 - @Param('id')
→ URL 경로에서 ID 값을 추출
Controller는 요청을 받고, Service로 전달하는 역할만 수행합니다.
2) 실제 Service에 반영
이제 실제 데이터 삭제 로직은 Service에서 구현합니다.
delete(id: number) {
const boardIndex = this.boards.findIndex((board) => board.id === id); // findIndex는 못 찾으면 -1을 반환
if (boardIndex === -1) {
throw new NotFoundException(
`ID ${id}에 해당하는 게시글을 찾을 수 없습니다.`,
);
}
this.boards.splice(boardIndex, 1);
return this.boards;
}
- findIndex를 사용하여 수정할 데이터의 위치를 찾음
- 존재하지 않으면 예외 처리 (NotFoundException)
- 기존 데이터에 새로운 데이터를 덮어쓰기 방식으로 수정
즉, 기존 데이터를 찾아서 제거하는 방식으로 동작합니다.
3) 테스트 in POSTMAN

DELETE /board/4 요청을 보내면, ID가 4인 게시글이 삭제되고, 삭제 이후의 게시글 목록이 반환됩니다.
| 결론
이번 글에서는 Nest.js의 데코레이터를 활용하여 GET, POST, PUT, DELETE까지 전체 CRUD API를 구현해보았습니다.
각 요청은 단순히 기능만 다른 것이 아니라, 역할이 명확하게 구분된다는 점이 중요합니다.
- GET → 데이터 조회
- POST → 데이터 생성
- PUT → 데이터 수정
- DELETE → 데이터 삭제
또한 모든 흐름은 공통적으로 Controller → Service → 결과 반환 구조를 따른다는 점도 확인할 수 있습니다.
이러한 구조는 코드의 역할을 명확하게 나누고, 프로젝트가 커지더라도 유지보수가 쉬운 형태를 만들어줍니다.
아직은 목데이터를 기반으로 간단하게 구현했지만, 앞으로는 DTO, Validation, Database 연동까지 확장하면서, 실제 서비스 구조에 가까운 형태로 발전시켜보는 것이 다음 단계가 될 것 같습니다.
'💻 개발 > 🌸 NestJS' 카테고리의 다른 글
| [NestJS] DTO와 유효성 검사 (0) | 2026.03.27 |
|---|---|
| [NestJS] NestJS에서 Swaager 사용하기 (0) | 2026.03.27 |
| [NestJS] NestJS 기본 구조부터 CRUD까지 완벽 정리 (초보자 가이드) (0) | 2026.03.27 |
