Nest.js 예제 따라해보기

2025-11-23

이번에는 Nest.js 공식 문서에 있는 예제를 따라 만들어보면서, Nest.js를 학습해보도록 하겠다. Nest.js 공식 문서는 고양이들이 사용할 수 있는 커뮤니티를 예제로 들고 있다. 우선 나도 프로젝트를 생성해보겠다.

프로젝트 생성

nest new cat-app

nest new 명령어를 사용하여 바탕화면에 cat-app 이라는 Nest.js 프로젝트를 생성한다. 생성한 뒤 Ide를 사용하여 프로젝트를 열어준다. 본인은 cursor를 사용하였다.

프로젝트 실행

pnpm start:dev

프로젝트를 Ide로 연 뒤, 위 명령어를 사용하여 실행한다. pnpm start 와 달리 위 명령어를 사용하면 핫 리로딩 기능을 사용할 수 있다.

프로젝트를 실행한다면 터미널에서 위와 같은 결과를 확인할 수 있다.

컨트롤러

컨트롤러는 클라이언트가 보낸 요청을 처리하고 응답을 보내는 역할을 수행한다. Nest.js 프로젝트 안에서 @ 로 시작하는 데코레이터를 사용하여 구현할 수 있다. 보통 한 컨트롤러 내에는 유사한 기능을 하는 함수들을 모아서 구현한다.

예를 들어 커뮤니티라고 하였을 때, 유저 컨트롤러에는 회원가입, 로그인, 유저 정보 가져오기 등의 함수를 구현하고, 글 컨트롤러에는 글 작성, 글 수정, 글 가져오기, 글 삭제 등의 함수를 구현할 것이다.

우선 이 프로젝트에서 필요한 고양이들에 대한 컨트롤러를 만들어주겠다.

nest g controller cats

위 명령어를 사용하여 고양이 컨트롤러를 생성한다.

명령어를 실행하면, 위와 같은 고양이 컨트롤러가 자동으로 생성된 것을 확인할 수 있다. 또한 앞서 말했던 데코레이터 중 @Controller 를 사용하여 컨트롤러가 구현된 것을 확인할 수 있고, 데코레이터 내에 'cats'/cats 로 라우팅 되는 것을 의미한다.

고양이 컨트롤러라고 하면 이해가 잘 되지 않을 수 있는데, 고양이 커뮤니티이기 때문에 유저 컨트롤러라고 생각하면 된다. 이 프로젝트에서 “고양이 = 유저”라고 생각하면 이해하기 편하다.

// cats.controller.ts
import { Controller, Get } from "@nestjs/common";

@Controller("cats")
export class CatsController {
  @Get()
  findAll(): string {
    return "This action returns all cats";
  }
}

위 파일에는 CatsControllerfindAll()이라는 함수를 추가한 것이다. @Get 이라는 데코레이터를 통해 Get 역할을 수행할 모든 고양이를 찾는 함수를 추가한 것이다. 앞서 말했듯이 “고양이 = 유저”라는 생각을 통해 모든 유저를 찾아오는 역할을 하는 함수를 유저 컨트롤러 내에 추가한 것이다.

그래서 위와 같은 함수를 추가해준다면, 현재 로컬 기준 http://localhost:3000/cats 로 Get 요청을 보낸다면, “This action returns all cats”라는 응답을 얻을 수 있다.

근데 이처럼 에러가 발생할 수 있다. 에러를 살펴본다면, 고양이 모듈을 찾을 수 없다고 한다. 이를 해결하기 위해 우선 모듈에 대한 얘기를 하고 넘어가도록 하겠다.

모듈

모든 Nest.js 프로젝트는 적어도 하나의 모듈로 이루어져 있다. 하지만 대부분의 프로젝트에는 수 많은 모듈이 존재한다. 모듈은 앞서 기능별로 컨트롤러를 나누었던 것들을 연결하기 위해 사용하는 것이라고 다시 생각하면 이해하기 쉬울 것이다. 위의 예에는 유저, 주문, 채팅 모듈이 하나의 애플리케이션 모듈로 모이는 것을 볼 수 있는데, 애플리케이션 모듈을 루트로 나머지 컨트롤러들을 루트로 연결하기 위해 필요한 것이 모듈이다. 공식 문서에는 애플리케이션 그래프를 구축한다라는 표현을 사용하고 있다. 즉 모듈은 애플리케이션을 구조화하는 핵심 단위이다.

모듈은 providers , controllers , imports , exports 의 속성을 가지며, 컨트롤러와 마찬가지로 @Module 이라는 데코레이터를 통해 구현한다. 각 속성은 다음과 같은 역할을 수행한다.

속성설명
providers현재 모듈 내에 존재하는 서비스 정의
controllers현재 모듈에 연결될 컨트롤러들을 등록
imports다른 모듈에서 exports로 내보낸 providers를 현재 모듈에서 사용하고 싶을 때 등록
exports현재 모듈에서 providers 중 다른 모듈도 사용할 수 있도록 공개할 것들을 정의

앞서 나왔던 모듈에 대한 오류를 해결하기 위해 모듈을 생성해주도록 한다.

nest g module cats

위의 명령어를 사용하면 아래와 같이 고양이 모듈이 생성된 것을 확인할 수 있다.

이제 앞서 말했던 속성들을 추가해주어야 한다.

// cats.module.ts
import { Module } from "@nestjs/common";
import { CatsController } from "./cats.controller";

@Module({
  controllers: [CatsController],
})
export class CatsModule {}

위 코드를 보면 controllers 에는 고양이 컨트롤러를, providers 에는 고양이 서비스를 등록해준 것을 알 수 있다. 그리고 고양이 모듈에서 고양이 컨트롤러를 관리하기 때문에, 애플리케이션 모듈에서는 고양이 컨트롤러에 대한 속성을 제거해도 될 것이다.

// app.module.ts
import { Module } from "@nestjs/common";
import { AppController } from "./app.controller";
import { AppService } from "./app.service";
import { CatsModule } from "./cats/cats.module";

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

이제 http://localhost:3000/cats 에 Get 요청을 보내면 고양이 컨트롤러에 있던 findAll() 함수가 실행되는 것을 알 수 있다. 공식문서와 같이 고양이 컨트롤러에 더 다양한 기능을 추가해보도록 하겠다.

컨트롤러

// cats.controller.ts
import { Controller, Get, Post } from "@nestjs/common";

@Controller("cats")
export class CatsController {
  @Post()
  create(): string {
    return "This action adds a new cat";
  }

  @Get()
  findAll(): string {
    return "This action returns all cats";
  }
}

위 코드는 create() 라는 고양이 추가 함수를 컨트롤러에 추가한 것이다. 아래를 보면 Post 요청을 보냈을 때 create() 함수가 실행되는 것을 알 수 있다.

 @Get('abcd/*')
  findAll() {
    return 'This route uses a wildcard';
  }

데코레이터에는 다양한 인자값을 넣을 수 있는데 위 처럼 라우팅을 지정해줄 수도 있다. 위와 같이 수정하는 경우, http://localhost:3000/cats/abcd 혹은 abcd 뒤에 어떤 경로가 와도 findAll() 함수가 실행된다.

@Post()
@HttpCode(204)
create() {
  return 'This action adds a new cat';
}

위 처럼 Status Code를 지정해줄 수도 있다. 기본 상태는 보통 200이고, Post 요청의 경우 201이다.

@Post()
@Header('Cache-Control', 'no-store')
create() {
  return 'This action adds a new cat';
}

그리고 위처럼 헤더를 지정해서 응답 때 반환되는 값의 헤더를 수정할 수도 있다.

@Get('docs')
@Redirect('https://docs.nestjs.com', 302)
getDocs(@Query('version') version) {
  if (version && version === '5') {
    return { url: 'https://docs.nestjs.com/v5/' };
  }
}

이렇게 리다이렉션도 설정해줄 수 있는데, 위의 경우 요청에서 쿼리의 버전이 5라면 https://docs.nestjs.com/v5/ 로 이동하지만, 아니라면 https://docs.nestjs.com 이동한다는 의미이다.

@Get(':id')
findOne(@Param() params: any): string {
  console.log(params.id);
  return `This action returns a #${params.id} cat`;
}

파라미터도 설정해줄 수 있는데, 위 처럼 @Get 데코레이터에 ‘:id’를 설정해주고, findOne() 함수에서 @Param 이라는 파라미터 데코레이터로 파라미터 값을 가져오면, 위 처럼 파라미터 내에 id라는 값에 접근할 수 있다. http://localhost:3000/cats/1 에 Get 요청을 보낸다면, “This action returns a #1 cat”이라는 값을 반환받을 수 있다.

링크가 복사되었습니다.