정화 코딩

[Node.js] NestJS에서 semester의 controller 파일 생성 본문

Web Development

[Node.js] NestJS에서 semester의 controller 파일 생성

jungh150c 2024. 11. 8. 01:05

semester.controller.ts 파일 생성

생성은 지난 포스트에서 했었다. 

https://jungh150c.tistory.com/184

semester의 create DTO 생성

semester 폴더 아래에 새로운 dto 폴더를 만들고 create-semester.dto.ts 파일을 만들어준다.

...apps\admin-backend> pnpm i class-validator

class-validator 패키지를 설치해준다.

// src/semester/dto/create-semester.dto.ts

import { Season } from '@prisma/client';
import { IsInt, IsEnum, IsNotEmpty } from 'class-validator';

export class CreateSemesterDto {
    @IsInt()
    @IsNotEmpty()
    year: number;

    @IsEnum(Season)
    @IsNotEmpty()
    season: Season;
}

create-semester.dto.ts 파일에 위와 같이 새로운 semester를 만들 때 필요한 필드들을 적어준다. 

semester의 update DTO 생성

...apps\admin-backend> pnpm i @nestjs/mapped-types

@nestjs/mapped-types 패키지를 설치해준다.

// src/semester/dto/update-semester.dto.ts

import { PartialType } from '@nestjs/mapped-types';
import { CreateSemesterDto } from './create-semester.dto';

export class UpdateSemesterDto extends PartialType(CreateSemesterDto) {}

update-semester.dto.ts 파일을 위와 같이 생성해준다. update DTO는 create DTO를 그대로 가져와 사용하되, 각 필드가 필수가 아니므로 PartialType를 붙여 구현해준다. 

[참고] https://kyounghwan01.github.io/blog/etc/nest/validation-dto/#%E1%84%86%E1%85%A1%E1%86%AB%E1%84%83%E1%85%B3%E1%86%AB-dto%E1%84%85%E1%85%B3%E1%86%AF-controller%E1%84%8B%E1%85%A6-%E1%84%8C%E1%85%A5%E1%86%A8%E1%84%8B%E1%85%AD%E1%86%BC

semester.controller.ts 파일에서 DTO를 사용하도록 수정

// src/semester/semester.controller.ts

import { Controller, Body, Param, Get, Post, Patch, Delete } from '@nestjs/common';
import type { Semester } from '@prisma/client';
import type { SemesterService } from './semester.service';
import type { CreateSemesterDto } from './dto/create-semester.dto';
import type { UpdateSemesterDto } from './dto/update-semester.dto';

@Controller('semester')
export class SemesterController {
  constructor(private semesterService: SemesterService) {}

  @Get()
  getAllSemester(): Promise<Semester[]> {
    return this.semesterService.getSemesters();
  }

  @Get('/:id')
  getSemesterById(
    @Param('id') id: number
  ): Promise<Semester | null> {
    return this.semesterService.getSemesterById(id);
  }

  @Post()
  createSemester(
    @Body() createSemesterDto: CreateSemesterDto
  ): Promise<Semester> {
    return this.semesterService.createSemester(createSemesterDto)
  }

  @Patch('/:id')
  updateSemester(
    @Param('id') id: number,
    @Body() updateSemesterDto: UpdateSemesterDto
  ): Promise<Semester> {
    return this.semesterService.updateSemester(id, updateSemesterDto)
  }

  @Delete('/:id')
  deleteSemester(
    @Param('id') id: number
  ): Promise<Semester> {
    return this.semesterService.deleteSemester(id)
  }
}

Decorators are not valid here.biome(parse) 이라는 오류가 날 수도 있다.

    "javascript": {
        "parser": {
            "unsafeParameterDecoratorsEnabled": true
        }
    },

biome.json 파일에서 위의 블록을 추가해주면 된다.

 

이렇게 추가하면 됨. 

 

그러면 오류가 해결된 걸 확인할 수 있다. (참고로 vscode를 껐다 켜야 반영된다.)

[참고] https://stackoverflow.com/questions/77804479/decorators-are-not-valid-here-biomeparse

semester.service.ts, semester.repository.ts 파일에서 DTO와 Prisma 입력 형식을 사용하도록 수정

// src/semester/semester.service.ts

import { Injectable } from '@nestjs/common';
import type { Prisma, Semester } from '@prisma/client';
import type { SemesterRepository } from './semester.repository';
import type { CreateSemesterDto } from './dto/create-semester.dto';
import type { UpdateSemesterDto } from './dto/update-semester.dto';

@Injectable()
export class SemesterService {
  constructor(private semesterRepository: SemesterRepository) {}

  async createSemester(createSemesterDto: CreateSemesterDto): Promise<Semester> {
    const semesterCreateInput: Prisma.SemesterCreateInput = {
      ...createSemesterDto,
    };
    const semester = await this.semesterRepository.createSemester({ data: semesterCreateInput });
    return semester;
  }

  async getSemesters(): Promise<Semester[]> {
    const semesters = await this.semesterRepository.getSemesters();
    return semesters;
  }

  async getSemesterById(id: number): Promise<Semester | null> {
    const semester = await this.semesterRepository.getSemester({
      where: { id },
    });
    return semester;
  }

  async updateSemester(id: number, updateSemesterDto: UpdateSemesterDto): Promise<Semester> {
    const semesterUpdateInput: Prisma.SemesterUpdateInput = {
      ...updateSemesterDto,
    };
    const semester = await this.semesterRepository.updateSemester({
      where: { id },
      data: semesterUpdateInput,
    });
    return semester;
  }

  async deleteSemester(id: number): Promise<Semester> {
    const semester = await this.semesterRepository.deleteSemester({
      where: { id },
    });
    return semester;
  }
}
// src/semester/semester.repository.ts

import { Injectable } from '@nestjs/common';
import type { Prisma, Semester } from '@prisma/client';
import type { PrismaService } from 'src/prisma/prisma.service';

@Injectable()
export class SemesterRepository {
  constructor(private prisma: PrismaService) {}

  async createSemester(params: {
    data: Prisma.SemesterCreateInput;
  }): Promise<Semester> {
    const { data } = params;
    return this.prisma.semester.create({ data });
  }

  async getSemesters(): Promise<Semester[]> {
    return this.prisma.semester.findMany();
  }

  async getSemester(params: {
    where: Prisma.SemesterWhereUniqueInput;
  }): Promise<Semester> {
    const { where } = params;
    return this.prisma.semester.findUnique({ where });
  }

  async updateSemester(params: {
    where: Prisma.SemesterWhereUniqueInput;
    data: Prisma.SemesterUpdateInput;
  }): Promise<Semester> {
    const { where, data } = params;
    return this.prisma.semester.update({ where, data });
  }

  async deleteSemester(params: {
    where: Prisma.SemesterWhereUniqueInput;
  }): Promise<Semester> {
    const { where } = params;
    return this.prisma.semester.delete({ where });
  }
}

참고로, prisma의 create 메서드는 파라미터로 data라는 객체를 받아 처리하기 때문에 createSemesterDto를 data 객체 안에 담아 전달해주어야 한다.

Service 계층과 Repository 계층의 역할 정리

Service 계층

컨트롤러로부터 데이터를 DTO 형식(CreateSemesterDto, UpdateSemesterDto, ...)으로 받아서 Prisma의 입력 형식(Prisma.SemesterCreateInput, Prisma.SemesterUpdateInput, ...)으로 변환하여 Repository로 전달

Repository 계층

Service 계층으로부터 받은 Prisma 입력 형식의 데이터를 그대로 사용해 데이터베이스 작업을 처리합니다.

 

Comments