10.Nest.js로 RESTful API 구축하기, 블로그 API의 기본 엔드포인트 설정하기 (CRUD)

Nest.js는 현대적인 웹 애플리케이션 개발을 위한 강력한 프레임워크로, TypeScript로 작성되어 있습니다. Nest.js는 다양한 아키텍처와 디자인 패턴을 지원하며, 특히 RESTful API 구축에 유용합니다. 이 글에서는 Nest.js를 사용하여 블로그 API의 기본 엔드포인트를 설정하고, CRUD(Create, Read, Update, Delete) 작업을 구현하는 과정을 살펴보겠습니다.

1. Nest.js 소개

Nest.js는 Angular에서 영감을 받아 만들어진 Node.js의 프레임워크로, 모듈화, 의존성 주입(DI), 그리고 유연한 구조를 제공합니다. Nest.js는 Express.js를 기반으로 하며, 다양한 라이브러리와 미들웨어를 활용하여 강력한 API 서버를 구축할 수 있습니다.

2. Nest.js 설치 및 프로젝트 생성

Nest.js를 사용하기 위해 먼저 Nest CLI를 설치하고, 새로운 프로젝트를 생성해야 합니다. Nest CLI는 Nest.js 프로젝트를 빠르게 생성하고 관리할 수 있는 도구입니다.

npm install -g @nestjs/cli
nest new blog-api

명령어를 입력하면, 새로운 디렉터리가 생성되고 관련 파일과 종속성이 설치됩니다. 프로젝트 디렉터리로 이동하여 서버를 실행할 수 있습니다.

cd blog-api
npm run start

3. 블로그 API 기본 엔드포인트 설계

블로그 API는 여러 개의 엔드포인트를 통해 블로그 게시물을 관리합니다. 기본적인 CRUD 작업을 위한 엔드포인트는 다음과 같습니다.

  • GET /posts: 모든 게시물 조회
  • GET /posts/:id: 특정 게시물 조회
  • POST /posts: 새로운 게시물 생성
  • PUT /posts/:id: 게시물 수정
  • DELETE /posts/:id: 게시물 삭제

4. 게시물 모듈 생성

Nest.js의 모듈 시스템을 이용하여 게시물 모듈을 생성할 수 있습니다. 아래 명령어를 입력하여 게시물 모듈을 생성합니다.

nest generate module posts
nest generate controller posts
nest generate service posts

위 명령어를 통해 posts라는 이름의 모듈, 컨트롤러, 서비스를 생성합니다. 생성된 파일들은 src/posts 디렉터리 안에 위치하게 됩니다.

5. 게시물 DTO(Data Transfer Object) 정의

게시물 데이터의 형식을 정의하기 위해 DTO를 설정합니다. DTO는 클라이언트와의 데이터 교환을 위한 객체로, 데이터의 유효성을 검사하는 데도 사용됩니다. 다음과 같은 게시물 DTO를 정의하겠습니다.

import { IsNotEmpty, IsString } from 'class-validator';

export class CreatePostDto {
    @IsNotEmpty()
    @IsString()
    readonly title: string;

    @IsNotEmpty()
    @IsString()
    readonly content: string;
}

6. 게시물 서비스 구현

게시물 서비스를 사용하여 데이터의 비즈니스 로직을 관리합니다. 서비스는 데이터베이스와의 상호작용, 데이터 처리 등을 담당합니다. 다음은 간단한 게시물 서비스 코드입니다.

import { Injectable, NotFoundException } from '@nestjs/common';
import { CreatePostDto } from './dto/create-post.dto';

@Injectable()
export class PostsService {
    private posts = [];

    create(createPostDto: CreatePostDto) {
        const newPost = {
            id: this.posts.length + 1,
            ...createPostDto,
        };
        this.posts.push(newPost);
        return newPost;
    }

    findAll() {
        return this.posts;
    }

    findOne(id: number) {
        const post = this.posts.find(p => p.id === id);
        if (!post) {
            throw new NotFoundException(`Post with ID ${id} not found`);
        }
        return post;
    }

    update(id: number, updatePostDto: CreatePostDto) {
        const postIndex = this.posts.findIndex(p => p.id === id);
        if (postIndex === -1) {
            throw new NotFoundException(`Post with ID ${id} not found`);
        }
        this.posts[postIndex] = { id, ...updatePostDto };
        return this.posts[postIndex];
    }

    delete(id: number) {
        const postIndex = this.posts.findIndex(p => p.id === id);
        if (postIndex === -1) {
            throw new NotFoundException(`Post with ID ${id} not found`);
        }
        this.posts.splice(postIndex, 1);
        return { message: 'Post deleted successfully' };
    }
}

7. 게시물 컨트롤러 구현

마지막으로, HTTP 요청을 처리하는 게시물 컨트롤러를 구현합니다. 각 엔드포인트에 해당하는 메소드를 정의하여 요청을 처리합니다.

import { Controller, Get, Post, Body, Param, Put, Delete } from '@nestjs/common';
import { PostsService } from './posts.service';
import { CreatePostDto } from './dto/create-post.dto';

@Controller('posts')
export class PostsController {
    constructor(private readonly postsService: PostsService) {}

    @Post()
    create(@Body() createPostDto: CreatePostDto) {
        return this.postsService.create(createPostDto);
    }

    @Get()
    findAll() {
        return this.postsService.findAll();
    }

    @Get(':id')
    findOne(@Param('id') id: string) {
        return this.postsService.findOne(+id);
    }

    @Put(':id')
    update(@Param('id') id: string, @Body() updatePostDto: CreatePostDto) {
        return this.postsService.update(+id, updatePostDto);
    }

    @Delete(':id')
    delete(@Param('id') id: string) {
        return this.postsService.delete(+id);
    }
}

8. API 테스트

API를 테스트하기 위해 Postman 또는 Insomnia와 같은 API 클라이언트를 사용할 수 있습니다. 아래는 각 엔드포인트를 테스트하기 위한 방법입니다.

  • POST /posts: 새 게시물 생성
  • GET /posts: 모든 게시물 조회
  • GET /posts/:id: 특정 게시물 조회
  • PUT /posts/:id: 게시물 업데이트
  • DELETE /posts/:id: 게시물 삭제

8.1 새 게시물 생성 예제

POST /posts
Content-Type: application/json

{
    "title": "첫 번째 게시물",
    "content": "이것은 첫 번째 게시물의 내용입니다."
}

8.2 모든 게시물 조회 예제

GET /posts

8.3 특정 게시물 조회 예제

GET /posts/1

8.4 게시물 수정 예제

PUT /posts/1
Content-Type: application/json

{
    "title": "수정된 게시물 제목",
    "content": "수정된 내용입니다."
}

8.5 게시물 삭제 예제

DELETE /posts/1

9. 결론

이번 글에서는 Nest.js를 사용하여 블로그 API의 기본 CRUD 엔드포인트를 생성하는 방법을 살펴보았습니다. Nest.js는 직관적이고 유연한 API 개발을 가능하게 하며, 간결하고 유지보수하기 쉬운 코드를 작성할 수 있게 도와줍니다. 이제 여러분은 Nest.js를 활용하여 자신의 요구에 맞는 API를 완성해보시기 바랍니다.

10. 다음 단계

이 튜토리얼을 마친 후, 다음 단계로는 데이터베이스와의 연동을 추가하여 영속성을 제공하는 방법을 분석할 수 있습니다. TypeORM 또는 Sequelize와 같은 ORM 라이브러리를 사용하여 데이터베이스에 저장하고 관리하는 방법에 대해 배우는 것도 추천합니다.