NestJS로 API 만들기

https://nomadcoders.co/nestjs-fundamentals


노마드코더 강의를 참고하고 있습니다.

 


결과 화면

 


1. 컨트롤러(controller) 만들기

터미널에서 아래 명령어를 실행한다.

영화 API를 만들 것이기 때문에 컨트롤러의 이름은 movies로 한다. (이름은 API 성격에 맞게 자유롭게 작성하면 된다.)

app.module.ts 파일에서 MoviesController가 자동으로 import 된 것을 확인할 수 있다.

nest generate controller
또는
nest g co

 

참고

터미널에서 nest 명령어를 실행하면 nest에서 사용할 수 있는 명령어 리스트를 확인할 수 있다.

 

  • src/movies/movies.controller.ts

기본 형태

import { Controller } from '@nestjs/common';

@Controller('movies')
export class MoviesController {}

 

 

      1. @Controller('movies')

컨트롤러를 정의하고, 해당 컨트롤러의 기본 URL 경로를 /movies로 지정한다.

 

      2. @Get() getAll()

HTTP GET 메서드에 대한 핸들러이다.

/movies 경로의 GET 요청에 대한 응답을 반환한다.

 

      3. @Get('/:id') getOne()

동적인 URL 파라미터인 :id를 사용해 특정 영화에 대한 정보를 가지고 오는 핸들러이다.

/movies/:id 경로의 GET 요청에 대한 응답을 반환한다.

 

      4. @Post() create()

HTTP POST 메서드에 대한 핸들러이다.

/movies 경로의 POST 요청에 대한 응답을 반환한다.

 

      5. @Delete('/:id') remove()

동적인 URL 파라미터인 :id를 사용해 특정 영화에 대한 정보를 삭제하는 핸들러이다.

/movies/:id 경로의 DELETE 요청에 대한 응답을 반환한다.

 

      6. @Parch('/:id') patch()

동적인 URL 파라미터인 :id를 사용해 특정 영화에 대한 정보를 업데이트하는 핸들러이다.

/movies/:id 경로의 PATCH 요청에 대한 응답을 반환한다.

import { Controller, Get, Post, Delete, Patch, Param, Body } from '@nestjs/common';

@Controller('movies') // Entry Point(URL)
export class MoviesController {
  @Get()
  getAll() {
    return 'This will return all movies.';
  }

  @Get('/:id')
  getOne(@Param('id') movieId: string) {
    return `This will return one movie with the id: ${movieId}`;
  }

  @Post()
  create() {
    return 'This will create a movie.';
  }

  @Delete('/:id')
  remove(@Param('id') movieId: string) {
    return `This will delete a movie with the id: ${movieId}`;
  }

  @Patch('/:id')
  patch(@Param('id') movieId: string) {
    return `This will patch a movie with the id: ${movieId}`;
  }
}

 

2. 서비스(service) 만들기

터미널에서 아래 명령어를 실행한다.

서비스의 이름은 컨트롤러의 이름과 동일하게 movies로 한다. (네이밍 규칙에 따라 이름을 동일하게 작성한다.)

app.module.ts 파일에 MoviesService가 자동으로 import 된 것을 확인할 수 있다.

nest generate services
또는
nest g s

 

  • src/movies/movies.service.ts

기본 형태

import { Injectable } from '@nestjs/common';

@Injectable()
export class MoviesService {}

 

원래는 데이터베이스가 들어오는 영역이지만, 데이터베이스를 만들지 않을 것이기 때문에 가짜 데이터베이스를 위한 비즈니스 로직을 만든다.

 

      1. private movies

가짜 데이터베이스를 만들기 위해 빈 배열은 만든다.

 

      2. getAll()

모든 영화 정보를 반환하는 메서드이다.

movies 배열 전체를 반환한다.

 

      3. getOne()

특정 id에 해당하는 영화 정보를 반환하는 메서드이다.

movies 배열에서 해당 id의 영화를 찾아 반환하고, id가 존재하지 않는다면 NotFoundException()을 반환한다.

 

      4. deleteOne()

특정 id에 해당하는 영화 정보를 삭제하는 메서드이다.

getOne() 메서드를 사용해 해당 id의 영화가 존재하는지 확인한 후, 영화를 movies 배열에서 삭제한다.

 

      5. create()

새로운 영화 정보를 추가하는 메서드이다.

movies 배열에 새로운 영화를 추가하고, id는 현재 배열 길이 +1로 설정한다.

 

      6. update()

특정 id에 해당하는 영화 정보를 업데이트 하는 메서드이다.

getOne() 메서드를 사용해 해당 id의 영화를 가져와 deleteOne() 메서드를 사용해 삭제한 후, 업데이트된 영화를 movies 배열에 추가한다.

import { Injectable, NotFoundException } from "@nestjs/common";
import { Movie } from './entities/movies.entity';

@Injectable()
export class MoviesService {
  private movies: Movie[] = [];

  getAll(): Movie[] {
    return this.movies;
  }

  getOne(id: string): Movie {
    const movie = this.movies.find((movie) => movie.id === +id);

    if (!movie) {
      throw new NotFoundException(`Movie with ID: ${id} not found.`);
    }

    return movie;
  }

  deleteOne(id: string) {
    this.getOne(id);
    this.movies = this.movies.filter((movie) => movie.id !== +id);
  }

  create(movieData) {
    this.movies.push({
      id: this.movies.length + 1,
      ...movieData,
    });
  }

  update(id: string, updateData) {
    const movie = this.getOne(id);
    
    this.deleteOne(id);
    this.movies.push({ ...movie, ...updateData });
  }
}

 

2-1. 엔티티(entity) 만들기

  • src/movies/entities/movies.entity.ts

Nest.js는 타입스크립트 기반이기 때문에 데이터 타입을 정의한다.

export class Movie {
  id: number;
  title: string;
  year: number;
  genres: string[];
}

 

3. 컨트롤러 수정하기

  • src/movies/movies.controller.ts

2번에서 컨트롤러에 대한 개념을 잡기 위해 문자열을 return을 했지만, HTTP 요청을 처리할 수 있도록 서비스에 만든 비즈니스 로직을 return 한다.

 

    1. constructor(private ~) {}

의존성 주입을 사용해 MoviesService를 주입한다.

 

    2. @Get() getAll()

movieService의 getAll() 메서드를 호출해 모든 영화에 대한 정보를 반환한다.

 

    3. @Get('/:id') getOne()

@Param 데코레이터를 사용해 URL 파라미터인 id를 추출하고, moviesService의 getOne() 메서드를 호출해 id에 해당하는 영화 정보를 반환한다.

 

    4. @Post() create()

@Body 데코레이터를 사용해 요청 본문에서 전달된 데이터를 moviesSevice의 create() 메서드를 호출해 새로운 영화 정보를 추가한다.

 

    5. @Delete('/:id') remove()

@Param 데코레이터를 사용해 URL 파라미터인 id를 추출하고, moviesService의 deleteOne() 메서드를 호출해 id에 해당하는 영화 정보를 삭제한다.

 

    6. @Parch('/:id') patch()

@Param 데코레이터를 사용해 URL 파라미터인 id를 추출하고, @Body 데코레이터를 사용해 요청 본문에서 데이터를 전달한다.

moviesService의 update() 메서드를 호출해 id에 해당하는 영화 정보를 업데이트한다.

import { Controller, Get, Post, Delete, Patch, Param, Query, Body } from '@nestjs/common';
import { MoviesService } from './movies.service';
import { Movie } from './entities/movies.entity';

@Controller('movies')
export class MoviesController {
  constructor(private readonly moviesService: MoviesService) {}

  @Get()
  getAll(): Movie[] {
    return this.moviesService.getAll();
  }

  @Get('/:id')
  getOne(@Param('id') movieId: string) {
    return this.moviesService.getOne(movieId);
  }

  @Post()
  create(@Body() movieData) {
    return this.moviesService.create(movieData);
  }

  @Delete('/:id')
  remove(@Param('id') movieId: string) {
    return this.moviesService.deleteOne(movieId);
  }

  @Patch('/:id')
  patch(@Param('id') movieId: string, @Body() updateData) {
    return this.moviesService.update(movieId, updateData);
  }
}

 

데코레이터란,

@로 시작하는 함수를 데코레이터 라고 부르며, 클래스, 메서드, 프로터디 또는 매개변수에 부가적인 메타데이터를 제공하는 역할을 한다.

 

  • @Module

모듈을 정의하는데 사용되며, 모듈은 애플리케이션을 구성하고 기능을 캡슐화한다.

 

  • @Controller

컨트롤러를 정의하는데 사용되며, HTTP 요청을 처리하는 역할을 한다.

 

  • @Injectable

서비스를 정의하는데 사용되며, 의존성 주입을 가능하게 한다.

 

  • @Body

POST, PUT, PATCH 등의 HTTP 메서드에서 주로 사용한다.

json 또는 대량의 데이터 전송에 적합하다.

 

  • @Query 

GET HTTP 메서드에서 주로 사용한다.

데이터를 필터링하거나 정렬하는 기분값을 전송에 적합하다.

ex) /movies?year=2024

 

  • @Param

동적인 경로를 가지는 라우팅에서 사용한다.

특정 데이터를 식별할 때 적합하다.

ex) /movies/2024

 

4. 결과 확인하기

Postman 또는 Insomnia로 HTTP에 대한 요청을 확인할 수 있다.

 

  • GET 

빈 배열을 확인할 수 있다.

 

  • POST

Status 201을 확인할 수 있다.

 

  • GET 

POST로 전송한 데이터를 확인할 수 있다.

 

  • DELETE

Status 200을 확인할 수 있다.

NestJS로 API 만들기

https://nomadcoders.co/nestjs-fundamentals


노마드코더 강의를 참고하고 있습니다.

 


결과 화면

 


Nest.js 설치하기

NestJs 설치에 대한 설명은 아래 링크를 참고한다.

https://jae-study.tistory.com/78

 

[Nest] #1 NestJs 설치하기

NestJS(Nest)란? https://docs.nestjs.com/ NestJs는 효율적이고, 확장 가능한 Node.js 서버 애플리케이션을 구축하기 위한 프레임워크이다. 프로그레시브 Javascript를 사용하고, Typescript로 구축되어 Typescript를

jae-study.tistory.com

 


Nest.js

네스트(Nest.js)는 Node.js를 위한 서버 사이드 애플리케이션을 개발하기 위한 프레임워크이다.

애플리케이션을 구성하는데 모듈, 컨트롤러, 서비스의 개념을 사용한다.

 

모듈 (Module)

@Module 데코레이터를 사용해 모듈을 정의하고, 해당 모듈은 컨트롤러, 서비스, 미들웨어 및 다른 컴포넌트들을 그룹화하는 방법을 제공한다.

Nest.js 애플리케이션을 여러 모듈로 구성되며, 의존성 주입을 통해 모듈 간에 서비스 및 기능을 공유하고, 코드의 재사용성을 높인다.

 

  • src/app.module.ts
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';

@Module({
  imports: [],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

 

컨트롤러 (Controller)

@Controller 테코레이터를 사용해 컨트롤러를 정의하고, 해당 컨트롤러에는 특정 엔드포인트(경로)에 대한 라우팅 정보가 포함된다.

또한 각 컨트롤러는 HTTP 메서드(GET, POST 등)에 메핑 되며, HTTP 요청을 처리하고 응답하는 역할을 수행한다.

 

  • src/app.controller.ts
import { Controller, Get } from '@nestjs/common';
import { AppService } from './app.service';

@Controller()
export class AppController {
  constructor(private readonly appService: AppService) {}

  @Get()
  getHello(): string {
    return this.appService.getHello();
  }

  @Get('/hi')
  sayHello(): string {
    return this.appService.getHi();
  }
}

 

서비스 (Service)

@Injectable() 데코레이션을 사용해 서비스를 정의하고, 해당 서비스에는 필요한 비즈니스 로직이나 데이터를 구현한다.

컨트롤러에서 호출되어 컨트롤러에게 데이터가 기능을 제공하는 역할을 한다.

 

  • src/app.service.ts
import { Injectable } from '@nestjs/common';

@Injectable()
export class AppService {
  getHello(): string {
    return 'Hello Nest!';
  }

  getHi(): string {
    return 'Hi Nest!';
  }
}

 

주의

데코레이터는 함수나 클래스랑 붙어있어야 한다. (스페이지 또는 엔터를 사용하면 안 된다.)

+ Recent posts