Nest.js를 배워보자/4. NestJS에서 데이터베이스 연결하기 — Prisma 기반 실습

NestJS + Prisma: CRUD 예제 (Service 구현)

_Blue_Sky_ 2025. 12. 2. 14:26
728x90

 


이 예제에서는 이전에 설정한 PrismaService를 주입받아, 실제 비즈니스 로직을 담당하는 PostsService를 구현하고 기본적인 CRUD (Create, Read, Update, Delete) 작업을 수행해 보겠습니다.

가정: schema.prisma에 Post 모델이 정의되어 있으며, id, title, content 필드가 있다고 가정합니다.

1. 📝 Post DTO 정의 (입력/출력)

CRUD 작업을 위해 DTO를 먼저 정의합니다.

// posts/dto/create-post.dto.ts
import { IsString, IsNotEmpty } from 'class-validator';

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

  @IsString()
  content: string;
}

// posts/dto/update-post.dto.ts (부분 업데이트를 위해 PartialType 사용 가능)
import { PartialType } from '@nestjs/mapped-types';
import { CreatePostDto } from './create-post.dto';

export class UpdatePostDto extends PartialType(CreatePostDto) {}

728x90

2. ⚙️ PostsService 구현

PostsService에서 PrismaService를 주입받아 CRUD 로직을 구현합니다.

// posts/posts.service.ts
import { Injectable, NotFoundException } from '@nestjs/common';
import { PrismaService } from '../prisma/prisma.service';
import { CreatePostDto } from './dto/create-post.dto';
import { UpdatePostDto } from './dto/update-post.dto';
import { Post } from '@prisma/client'; // Prisma가 생성한 Post 타입을 사용

@Injectable()
export class PostsService {
  // 💡 생성자 주입을 통해 PrismaService 인스턴스 사용
  constructor(private prisma: PrismaService) {}

  // 1. CREATE: 새 게시물 생성
  async create(createPostDto: CreatePostDto): Promise<Post> {
    // prisma.post.create() 메서드 사용
    return this.prisma.post.create({
      data: createPostDto,
    });
  }

  // 2. READ (목록): 모든 게시물 조회
  async findAll(): Promise<Post[]> {
    // prisma.post.findMany() 메서드 사용
    return this.prisma.post.findMany();
  }

  // 3. READ (단일): 특정 ID의 게시물 조회
  async findOne(id: number): Promise<Post> {
    const post = await this.prisma.post.findUnique({
      where: { id },
    });
    
    // 조회 결과가 없으면 예외 발생
    if (!post) {
      throw new NotFoundException(`Post with ID ${id} not found`);
    }
    return post;
  }

  // 4. UPDATE: 특정 ID의 게시물 수정
  async update(id: number, updatePostDto: UpdatePostDto): Promise<Post> {
    try {
      // prisma.post.update() 메서드 사용
      return await this.prisma.post.update({
        where: { id },
        data: updatePostDto,
      });
    } catch (error) {
      // ID가 존재하지 않을 경우 Prisma에서 예외 발생
      throw new NotFoundException(`Post with ID ${id} not found`);
    }
  }

  // 5. DELETE: 특정 ID의 게시물 삭제
  async remove(id: number): Promise<Post> {
    try {
      // prisma.post.delete() 메서드 사용
      return await this.prisma.post.delete({
        where: { id },
      });
    } catch (error) {
      throw new NotFoundException(`Post with ID ${id} not found`);
    }
  }
}
728x90

3. 🔑 핵심 Prisma Client 메서드

작업 Prisma Client 메서드 역할
생성 (Create) prisma.model.create() 새 레코드를 생성합니다. data 객체를 전달합니다.
조회 (Read - All) prisma.model.findMany() 모든 레코드 또는 필터링된 레코드 목록을 반환합니다.
조회 (Read - One) prisma.model.findUnique() id나 @unique 필드를 기준으로 하나의 레코드를 조회합니다.
수정 (Update) prisma.model.update() where로 대상을 지정하고 data로 수정할 내용을 전달합니다.
삭제 (Delete) prisma.model.delete() where로 대상을 지정하여 레코드를 삭제합니다.

Prisma는 모델 이름(예: post)을 기반으로 메서드를 제공하며, TypeScript 타입을 통해 매개변수와 반환 값이 정확히 일치하도록 보장합니다.

728x90