Nest.JS

공부의 기록·2021년 11월 24일
0

Node.JS

목록 보기
16/32
post-thumbnail

서론

Node.js , Express 기반 서버사이드 프레임워크

Nest.JS 의 기본 셋팅값 (추가 설정 없이 사용 가능)
1. Typescript | 타입 안정성 확보
2. Jest | 유닛테스트, e2e테스트로 서비스 안정성 확보
3. Fastify | @Req, @Res 외에 퍼포먼스 확보


설치

npm install -g @nestjs/core
npm install -g @nestjs/cli

  • 주의사항
    nest 커맨드 라인은 cmd 에서는 바로 사용 가능하나,
    VSC 에서는 cmd 모드로 변환한 이후에 사용이 가능하다.

npm i @nestjs/graphql@^7 graphql@^15 apollo-server-express@^2

  • GraphQL server settings

npm install @nestjs/mapped-types

  • 목적
    nest.js 의 핵심기능인 partial-types 를 사용하기 위한 모듈

npm install class-validator
npm install class-transformer

  • 목적
    nest.js 의 useGlobalPipes 의 new ValidationPipe 기능 사용
    유효성 검사 등의 행위를 생략할 수 있다.

npm install --save @nestjs/typeorm
npm install @nestjs/sequelize

  • postgreSQL && (typeORM || sequelize)
    postgreSQL && pgAdmin4 를 설치하고 node.js 와 연결하기 위해서 설치(택 1)
  1. typeORM : TS 기반
  2. sequelize : JS 기반
  • mongoDB 를 사용하고 싶으면 mongoose 를 설치

npm install --save @nestjs/config

  • env | 환경변수 사용 목적

npm install cross-env

  • virtual env | 가상의 환경변수 설정 가능

https://github.com/unchaptered/21-11-lecture-nestjs


핵심이론

  1. DI : 의존성 주입
  2. Express : Nest 안에서 사용
  3. Fastify : Adv. Express
  4. Jest : Unit Test

Dependency Injection

DI, 의존성 주입

Typescript | 의존성 주입이란 무엇인가?
Java | Spring 의존성 주입(DI) 이란?

서론

DI 에 대한 더욱 구체적인 내용과 구현은 기회가 된다면 다른 포스트에서 제대로 파고 들어가도록 해야겠다.

정의

클래스에 대한 의존성의 인터페이스를 통한
코드 유연성 증대 및 클래스의 인스턴스를 외부에서 생성하여 주입

예시 | movies.module.ts

import { MovieService } from "./movies.service";

@Module({
  controller: [MoviesController],
  providers: [MoviesService],
})

export class MoviesModule {}

Nest.JS 가
providers 항목들 을 뽑아와서
controller 안 에 inject(주입) 한다.

Express

Express.JS

Express 프레임워크는 Request, Response 속성을 쉽게 사용할 수 있다.

export const getAllMovies=(req,res)=>{
  const { ... }=req;
}

Nest.JS

Nest 프레임워크에서도 사용이 가능하다.

import { Controller, Get, Req, Res } from "@nestjs/common";
import { Movie } from "./entities/movie.entity";
import { MovieService } from "./movies.service";

@Controller("movies")
export const MoviesController{
  @Get()
  getAllMovies(@Rea() req, @Res() res):Movie[] {
    return this.movieService.getAllMovies();
  }
}

하지만...

Nest.JS 에서는 성능 상의 이유로 Fastify 라이브러리 사용을 추천한다.

Fastify

Jest

Jest 라이브러리에 대한 자세한 점들은 따로 포스트를 작성하도록 하겠다.

Jest 는 유닛테스트 및 e2e테스트 라이브러리이다.
아래는 Nest.JS 로 생성한 프로젝트의 package.json 의 script 항목이다.

  1. test:cov | 전체 테스트 진척도 확인
  2. test:watch | 유닛 테스트 진행
  3. test:e2e | 전체 테스트 진행
"scripts": {
  	...
    "test": "jest",
    "test:watch": "jest --watch",
    "test:cov": "jest --coverage",
    "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
    "test:e2e": "jest --config ./test/jest-e2e.json"
  },

test:cov | 전체 테스트 진척도 확인

test:watch | 유닛 테스트 진행

purpose : 유닛테스트 실행

test:e2e(end to end) | 전체 테스트 진행

purpose : 프로젝트 테스트 실행


파일구조

  1. [name].module.ts
  2. [name].service.ts
  3. [name].controller.ts
  4. dto/[name].dto.ts
  5. entities/[name].entity.ts

[name].module.ts

Nest.JS 는 최종적으로 하나의 APP 으로 이루어져 있다.
해당 APP 이 각각의 모듈로 연결되어 있으며, 전술한 의존성 담당하고 있다.

@Module({
  import: [ModuleName], // 다른 모듈 임포트
  controller: [ControllerName], // 반환메서드
  provider: [ServiceName] // 클래스와 메서드 구현부
});

[name].service.ts

@Injectable()
export class ServiceName {
  private movies: Movie[]=[];
  
  getAllMovies(): Movie[] {
    return this.movies;
  }
  getSingleMovie(id:number): Movie {
    const movie=this.movies.find(movie=>movie.id===+id);
    if(!movie){
      throw new NotFoundException(`Movie with ID ${id} not found`);
    }
    return movie;
  }
  deleteSingleMovie(id:number) {
    this.getSingleMovie(id);
    this.movies=this.movies.filter(movie=>movie.id!==+id);
  }
  patchPartOfMovie(id:number, updateData:UpdateMovieDto) {
    const movie=this.getSingleMovie(id);
    this.deleteSingleMovie(id);
    this.movies.push({ ...movie, ...updateData });
  }
}

[name].controller.ts

controller 는 express 의 router-controller 와 동일한 역할을 합니다.
Decorator 가 URL 을 받아서 function 안의 기능을 실행시킵니다.
function 뒤의 괄호 () 에서 여러 가지 값들을 받을 수 있습니다.
단, 여기에 적어놓지 않은 값들은 받지 않습니다.
(express.js 에서는 받아졌고 사용의 유무만 결정했다.)

controller 에서 사용할 수 있는 키워드는 다음과 같습니다.
@Get : 수신
@Post : API 송신
@Delete : 삭제
@Put : 모든 리소스 업데이트
@Patch : 일부 리소스 업데이트

@Controller("movies")
export class MovieController {
  constructor(private readonly moviesService: MoviesService) {}
  
  @Get // https methods
  getAllMovies():Movie[] {
    return this.moviesService.getAllMovies();
  }
  @Get("search") // https methods
  searchSingleMovie(@Query("year") year:string) {
    return `We are searching for a movie made after ${year}`;
  }
  @Get(":id") // https methods
  getSingleMovie(@Param("id") movieID:number) {
    return this.moviesService.getSingleMovie(movieID);
  }
  // ... more functions ...
}

dto/[name].dto.ts

import { IsNumber, IsOptional, IsString } from "class-validator";
export class CreateMovieDto{
  @IsString() // in "class-validator"
  readonly title: string;
  
  @IsNumber()
  readonly year: number;
  
  @IsOptional()
  @IsString({ each: true })
  readonly genres: string[];
}

entities/[name].entity.ts

타입스크립트는 사용할 객체 타입을 따로 entity 라고 선언해두어야 한다.

export class Movie{
    id: number;
    title: string;
    year: number;
    genres: string[];
}
profile
2022년 12월 9일 부터 노션 페이지에서 작성을 이어가고 있습니다.

0개의 댓글