NestJS + Prisma로 강의(Lecture) CRUD API 구현하기

김민석·2026년 3월 25일
post-thumbnail

온라인 강의 플랫폼의 강의(Lecture) CRUD API를 NestJS + Prisma로 구현했다.
전체 흐름은 Controller → Service → Prisma(DB) 3계층 구조다.

  • Controller: HTTP 요청을 받아 Service에 위임, Swagger 문서화
  • Service: 비즈니스 로직 + 권한 검사 + DB 접근
  • Prisma: ORM으로 실제 DB 쿼리 실행

Controller 부분 코드

라우팅 구조

POST   /lectures/sections/:sectionId/lectures  → 강의 생성
GET    /lectures/:lectureId                    → 강의 상세 조회
PATCH  /lectures/:lectureId                    → 강의 수정
DELETE /lectures/:lectureId                    → 강의 삭제

강의를 생성할 때는 어느 섹션에 넣을지 알아야 하므로 (섹션 하나에 여러 강의가 들어갈 수 있음) URL에 sectionId를 포함시켰다.
반면 조회/수정/삭제lectureId만으로 대상을 특정할 수 있으므로 단순하게 /:lectureId로 설계했다.


Service 부분 코드

create

async create(sectionId: string, createLectureDto: createLectureDto, userId: string): Promise<Lecture> {
    const section = await this.prisma.section.findUnique({
      where: {
        id: sectionId,
      },
      include: {
        course: true,
      },
    });
    if (!section) {
      throw new NotFoundException('Section not found');
    }
    if (section.course.instructorId !== userId) {
      throw new ForbiddenException('You are not the instructor of this section');
    }
    const lastLecture = await this.prisma.lecture.findFirst({
      where: {
        sectionId: sectionId,
      },
      orderBy: {
        order: 'desc',
      },
    });
    const order = lastLecture ? lastLecture.order + 1 : 0;
    return this.prisma.lecture.create({
      data: {
        ...createLectureDto,
        order,
        section: {
          connect: {
            id: sectionId,
          },
        },
        course: {
          connect: {
            id: section.courseId,
          },
        },
      },
    });
  }

처리 순서:

  1. sectionId로 섹션 존재 여부 확인 → 없으면 NotFoundException
  2. section.course.instructorId === userId 검사 → 다르면 ForbiddenException
    => section.course.instructorId (이 코스의 주인)이 userid(현재 사용자) 와 같다면
    즉 내 코스의 섹션에만 강의를 추가할 수 있다
  3. 해당 섹션의 마지막 강의 order 조회 후 +1
  4. 강의 생성 (섹션과 코스에 동시 연결)
    => connet를 사용해 강의 생성시 섹션과 코스에도 반영

order 자동 증가 로직:

const lastLecture = await this.prisma.lecture.findFirst({
  where: { sectionId },
  orderBy: { order: 'desc' },
});
const order = lastLecture ? lastLecture.order + 1 : 0;

섹션 내 강의 순서를 DB 레벨에서 직접 관리한다.
첫 번째 강의면 order = 0, 이후엔 마지막 강의의 order + 1을 자동으로 부여한다.


update 및 delete 코드

// 1. 존재 여부 확인
const lecture = await this.prisma.lecture.findUnique({
  where: { id: lectureId },
  include: {
    course: { select: { instructorId: true } },
  },
});
if (!lecture) throw new NotFoundException('...');

// 2. 권한 확인
if (lecture.course.instructorId !== userId)
  throw new ForbiddenException('...');

// 3. 실제 작업 수행

courseinclude할 때 select: { instructorId: true }로 필요한 필드만 가져온다.
course 전체를 끌어오지 않으므로 조금이라도 최적화가 된다..


에러 처리 정리

상황예외HTTP
lectureId가 UUID 형식이 아님BadRequestException (Pipe 자동 처리)400
섹션 / 강의가 존재하지 않음NotFoundException404
본인 강의가 아님ForbiddenException403

profile
나만의 기록장

0개의 댓글