반응형

NestJS + Jest 테스트에서 describe, beforeEach, spyOn을 활용하여 의존성을 주입하고 Mock 데이터를 설정하는 방법

🔍 개요

NestJS에서 Jest를 사용해 테스트 코드를 작성할 때,

  • describe()를 사용해 테스트를 계층적으로 나누고,
  • beforeEach()에서 공통 의존성을 주입하며,
  • jest.spyOn()을 활용해 비즈니스 로직 내부의 특정 메서드를 Mocking하여 원하는 데이터를 설정할 수 있습니다.

이 글에서는 NestJS 서비스의 비즈니스 로직을 단위 테스트하는 과정에서 의존성을 주입하고, Mock 데이터를 설정하는 올바른 방법을 설명합니다.


1️⃣ Jest에서 의존성 주입과 Mock 데이터 설정이 필요한 이유

NestJS에서는 의존성 주입(Dependency Injection, DI)을 사용하여 서비스 간의 의존성을 관리합니다.
하지만 Jest에서 단위 테스트를 작성할 때, 실제 서비스 대신 Mock 데이터를 주입해서 테스트합니다.

이유는 다음과 같습니다:

  1. 독립적인 테스트를 수행하기 위해
    • 실제 데이터베이스나 API 호출 없이 테스트를 실행해야 합니다.
  2. 테스트 실행 속도를 높이기 위해
    • 실제 API나 DB를 호출하면 테스트가 느려지고, 불필요한 비용이 발생합니다.
  3. 예측 가능한 테스트를 위해
    • jest.spyOn()을 사용하여 특정 메소드의 반환값을 제어할 수 있습니다.

2️⃣ NestJS에서 Jest 테스트 환경 설정

📌 1. 기본적인 테스트 코드 구조

다음은 NestJS 서비스에서 Jest를 사용한 기본적인 테스트 코드 구조입니다.
샘플 코드) Android 인앱결제 신호를 받는 비지니스 로직 테스트 코드

import { Test, TestingModule } from '@nestjs/testing';
import { AndroidRtdnCommandHandler } from './android-rtdn-command.handler';
import { IAPValidatorProvider } from '../providers/iap-validator.provider';
import { SubscriptionRepository } from '../subscription.repository';
import { AppConfigService } from 'src/config';

describe('AndroidRtdnCommandHandler', () => {
  let handler: AndroidRtdnCommandHandler;
  let iapValidatorProvider: jest.Mocked<IAPValidatorProvider>;
  let subscriptionRepository: jest.Mocked<SubscriptionRepository>;

  beforeEach(async () => {
    const module: TestingModule = await Test.createTestingModule({
      providers: [
        AndroidRtdnCommandHandler,
        {
          provide: IAPValidatorProvider,
          useValue: { validateGooglePurchase: jest.fn() }, // Mock 설정
        },
        {
          provide: SubscriptionRepository,
          useValue: { findByLatestOrderId: jest.fn() },
        },
      ],
    }).compile();

    handler = module.get<AndroidRtdnCommandHandler>(AndroidRtdnCommandHandler);
    iapValidatorProvider = module.get<IAPValidatorProvider>(IAPValidatorProvider);
    subscriptionRepository = module.get<SubscriptionRepository>(SubscriptionRepository);
  });

  describe('processGooglePlayMessage', () => {
    let validateGooglePurchaseSpy: jest.SpyInstance;
    let findByLatestOrderIdSpy: jest.SpyInstance;

    beforeEach(() => {
      validateGooglePurchaseSpy = jest
        .spyOn(iapValidatorProvider, 'validateGooglePurchase')
        .mockResolvedValue({
          latestOrderId: "test-order-id",
          subscriptionState: 2,
          testPurchase: false,
        });

      findByLatestOrderIdSpy = jest
        .spyOn(subscriptionRepository, 'findByLatestOrderId')
        .mockResolvedValue({
          id: "test-id",
          orderId: "test-order-id",
          state: "active",
        } as unknown as Subscription);
    });

    it('should call handleSubscriptionValidate for subscriptionNotification', async () => {
      const message = {
        subscriptionNotification: {
          notificationType: 1,
          purchaseToken: "test-token",
          subscriptionId: "1month_subscription",
        }
      };

      await handler.processGooglePlayMessage(message);

      expect(validateGooglePurchaseSpy).toHaveBeenCalled();
      expect(findByLatestOrderIdSpy).toHaveBeenCalled();
    });
  });
});

3️⃣ Jest에서 의존성을 주입하는 방법

📌 Test.createTestingModule을 사용해 의존성 주입

Test.createTestingModule()을 사용하면 NestJS의 providers를 Mock 객체로 대체하여 테스트 환경을 구성할 수 있습니다.

예제: beforeEach에서 의존성 주입

beforeEach(async () => {
  const module: TestingModule = await Test.createTestingModule({
    providers: [
      AndroidRtdnCommandHandler,
      {
        provide: IAPValidatorProvider,
        useValue: { validateGooglePurchase: jest.fn() }, // Mock 설정
      },
      {
        provide: SubscriptionRepository,
        useValue: { findByLatestOrderId: jest.fn() },
      },
    ],
  }).compile();

  handler = module.get<AndroidRtdnCommandHandler>(AndroidRtdnCommandHandler);
  iapValidatorProvider = module.get<IAPValidatorProvider>(IAPValidatorProvider);
  subscriptionRepository = module.get<SubscriptionRepository>(SubscriptionRepository);
});

이렇게 설정하면 실제 서비스 대신 Mock 객체가 주입되므로, 테스트가 독립적으로 실행될 수 있습니다.


4️⃣ jest.spyOn()을 사용하여 특정 메소드 Mocking

📌 jest.spyOn()을 사용해 특정 함수의 반환값을 변경

단위 테스트에서는 비즈니스 로직이 내부에서 실행하는 특정 메소드를 Mocking할 필요가 있습니다.

예제: 특정 함수의 반환값을 변경

const validateGooglePurchaseSpy = jest
  .spyOn(iapValidatorProvider, 'validateGooglePurchase')
  .mockResolvedValue({
    latestOrderId: "test-order-id",
    subscriptionState: 2,
    testPurchase: false,
  });

const findByLatestOrderIdSpy = jest
  .spyOn(subscriptionRepository, 'findByLatestOrderId')
  .mockResolvedValue({
    id: "test-id",
    orderId: "test-order-id",
    state: "active",
  } as unknown as Subscription);

이렇게 하면 테스트에서 특정 함수의 반환값을 원하는 값으로 설정할 수 있습니다.


5️⃣ jest.spyOn()을 사용해 함수 호출 여부 검증

테스트 실행 후 특정 함수가 정상적으로 실행되었는지 확인해야 합니다.

📌 expect(...).toHaveBeenCalled()을 사용

it('should call handleSubscriptionValidate for subscriptionNotification', async () => {
  const message = {
    subscriptionNotification: {
      notificationType: 1,
      purchaseToken: "test-token",
      subscriptionId: "1month_subscription",
    }
  };

  await handler.processGooglePlayMessage(message);

  expect(validateGooglePurchaseSpy).toHaveBeenCalled(); // ✅ 함수가 호출되었는지 확인
  expect(findByLatestOrderIdSpy).toHaveBeenCalled();
});

이제 이 테스트는 특정 메소드가 호출되었는지 검증할 수 있습니다.


🚀 결론

✔ Jest에서 의존성을 주입하고 Mock 데이터를 설정하는 Best Practice

  1. Test.createTestingModule()을 사용해 Mock 서비스를 주입
  2. beforeEach()에서 공통적으로 필요한 Mock 설정을 적용
  3. jest.spyOn()을 사용해 내부 메소드의 반환값을 설정
  4. expect(...).toHaveBeenCalled()을 사용해 함수 호출 여부를 검증
  5. 중복된 Mock 설정을 beforeEach()에서 한 번만 설정하여 유지보수를 쉽게 만듦

💡 이렇게 하면?

  • 독립적인 단위 테스트 가능
  • 외부 API나 DB 호출 없이 빠른 테스트 실행
  • 비즈니스 로직이 의도한 대로 동작하는지 검증 가능
728x90
반응형

'NestJS' 카테고리의 다른 글

[Nest.js] PIPE  (0) 2023.08.27
[Nest.js] TypeORM 이용한 CRUD  (0) 2023.08.22
[Nest.js] 기본 파일 구조 및 요청 흐름  (2) 2023.08.20
[Nest.js] Quick Start!  (0) 2023.08.15
반응형

nest.js

 

PIPE 란?

파이프는 @Injectable () 데코레이터로 주석이 달린 클래스입니다. 파이프는 주로 요청 데이터의 변환유효성 검사, 응답 데이터의 가공 등을 처리하기 위해 사용됩니다. 


1. 데이터 유효성 검사 : 파이프를 사용하여 들어오는 데이터의 유효성을 검사할 수 있습니다. 이를 통해 잘못된 데이터가 들어오는 것을 방지하고, 안전한 데이터 처리를 보장할 수 있습니다.
2. 데이터 변환 : 클라이언트로부터 들어오는 데이터를 원하는 형식으로 변환할 수 있습니다. 예를 들어 JSON 형식의 데이터를 객체로 변환하거나, 문자열을 숫자로 변환할 수 있습니다.
3. 데이터 가공 : 파이프를 사용하여 요청 데이터나 응답 데이터를 가공할 수 있습니다. 예를 들어 문자열을 대문자로 변경하거나, 특정 필드를 추가하거나 제거할 수 있습니다.

 

Built-in pipe 종류

  • ValidationPipe
  • ParseIntPipe
  • ParseFloatPipe
  • ParseBoolPipe
  • ParseArrayPipe
  • ParseUUIDPipe
  • ParseEnumPipe
  • DefaultValuePipe
  • ParseFilePipe

 

PIPE 사용하는 방법

Handler-level Pipes

핸들러 레벨에서 @UsePipes() 데코레이터를 이용해서 사용 할 수 있습니다. 이 파이프는 모든 파라미터에 적용이 됩니다.

아래 "유효성 체크 해보기"에서 조금 구체적으로 사용하는 방법을 말씀드리겠습니다.

@UsePipes(ValidationPipe)
    createBoard(@Body() createBoardDto: CreateBoardDto) : Promise<Board> {
        return this.boardsService.createBoard(createBoardDto);
    }

 

Parameter-level Pipes

파라미터 레벨의 파이프 이기에 특정한 파라미터에게만 적용이 되는 파이프 입니다. 아래와 같은 경우에는 id만 파라미터 파이프가 적용이 됩니다.  

@Patch('/:id/status')
    updateBoardStatus(
        @Param('id', ParseIntPipe) id: number,
        @Body('status') status : BoardStatus
    ) {
        return this.boardsService.updateBoardStatus(id, status);
    }

 

Global Pipes

글로벌 파이프로서 애플리케이션 레벨의 파이브 입니다. 클라이언트에서 들어오는 모든 요청에 적용이 됩니다. 가장 상단 영역인 main.ts에 넣어주시면 됩니다.

 

유효성 체크 해보기

먼저 class-validator , class-transformer 모듈을 사용하기 위해서 아래와 같이 모듈을 설치해줍니다.

npm install class-validator class-transformer --save

참고 페이지 여기에서 여러가지 validation 데코레이터를 확인 할 수 있습니다.

 

1. create-board.dto.ts

  - board에 title과 description은 빈값이 안오도록 @IsNotEmpty() 데코레이터를 사용해보겠습니다.

import { IsNotEmpty } from "class-validator";

export class CreateBoardDto{
    @IsNotEmpty()
    title:string;

    @IsNotEmpty()
    description:string;
}

 

2. 위와 같이 데코레이터를 추가해줬다면 아래 컨트롤러에 @UsePipes(ValidationPipe) 데코레이터를 넣어주면 적용이 됩니다.

boards.controller.ts

@UsePipes(ValidationPipe)
    createBoard(@Body() createBoardDto: CreateBoardDto) : Promise<Board> {
        return this.boardsService.createBoard(createBoardDto);
    }

 

잘 적용된 걸 확인할 수 있습니다.

 

Custom PIPE 만들기

board-status-validation.pipe.ts

  - custom pipe를 만들기 위해서는 PipeTransform interface를 구현하여야 합니다.

  - transform 함수 안에 구현하고자 하는 비지니스 로직을 구현하면 됩니다.

  - status 상태 값이 PRIVATE, PUBLIC 으로만 수정될 수 있도록 구현하였습니다.

import { ArgumentMetadata, BadRequestException, PipeTransform } from "@nestjs/common";
import { BoardStatus } from "../board-status.enum";

export class BoardStatusValidationPipe implements PipeTransform {

    readonly StatusOptions = [
        BoardStatus.PRIVATE,
        BoardStatus.PUBLIC
    ]

    transform(value: any, metadata: ArgumentMetadata) {

        if(!this.isStatusValid(value)) {
            throw new BadRequestException(`${value} isn't in the status options`); 
        }


        return value;
    }

    private isStatusValid(status : any) {
        const index = this.StatusOptions.indexOf(status);
        return index !== -1
    }
}

 

boards.controller.ts

@Patch('/:id/status')
    updateBoardStatus(
        @Param('id', ParseIntPipe) id: number,
        @Body('status', BoardStatusValidationPipe) status : BoardStatus
    ) {
        return this.boardsService.updateBoardStatus(id, status);
    }

 

참고 

- https://docs.nestjs.com/first-steps

- 따라하며 배우는 NestJS

 

728x90
반응형
반응형

nest.js

 

이번 시간에는 TypeORM 모듈을 이용해서 DB을 연결해서 간단한 게시판(Board 모듈) CRUD를 진행해 보도록 하겠습니다.

 

준비사항 : mysql DB

간단하게 docker를 이용해서 local에서 mysql 사용하고 싶으시다면 참고 하시면 좋을 것 같습니다.

docker-compose.yml

version: '3.1'

services:
  db:
    image: mysql
    restart: always
    command: --lower_case_table_names=1 # 대소문자 구분
    container_name: mysql-db
    environment:
      - MYSQL_DATABASE=test
      - MYSQL_ROOT_PASSWORD=1234
      - TZ=Asia/Seoul
    command:
      - --character-set-server=utf8mb4
      - --collation-server=utf8mb4_unicode_ci
    volumes:
      - ./db:/var/lib/mysql # db 볼륨 처리
    ports:
      - 3306:3306

      # docker-compose up -d

 

1. TypeORM 모듈 install

  - 저는 mysql db를 사용하도록 하겠습니다.

  - mysql과 typeorm 모듈을 설치합니다.

npm install mysql2 typeorm @nestjs/typeorm

 

2. TypeORM config 설정

config.typeorm.ts

import { TypeOrmModuleOptions } from "@nestjs/typeorm";

export const typeORMConfig : TypeOrmModuleOptions = {
    type: 'mysql',
    host: 'localhost',
    port: 3306,
    username: 'root',
    password: '1234',
    database: 'test',
    entities: [__dirname+ '/../**/*.entity.{js,ts}'],
    synchronize:true
}

 

app.module.ts

import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { typeORMConfig } from './configs/config.typeorm';

@Module({
  imports: [
    TypeOrmModule.forRoot(typeORMConfig)
  ],
})
export class AppModule {}

 

3. board 모듈을 만들어 보도록 하겠습니다.

board 모듈 구조는 아래 그림과 같습니다.

board 모듈 구조

board.entity.ts

  - DB 테이블이 되는 Entity 객체

import { BaseEntity, Column, Entity, PrimaryGeneratedColumn } from "typeorm";
import { BoardStatus } from "./board-status.enum";

@Entity()
export class Board extends BaseEntity {

    @PrimaryGeneratedColumn()
    id:number;

    @Column()
    title:string;

    @Column()
    description:string;

    @Column()
    status:BoardStatus;
}

 

board.repository.ts

import { Repository } from "typeorm";
import { Board } from "./board.entity";

export class BoardRepository extends Repository<Board> {
}

 

boards.controller.ts

import { Body, Controller, Delete, Get, Param, ParseIntPipe, Patch, Post, UsePipes, ValidationPipe } from '@nestjs/common';
import { BoardsService } from './boards.service';
import { BoardStatus } from './board-status.enum';
import { CreateBoardDto } from './dto/create-board.dto';
import { Board } from './board.entity';

@Controller('boards')
export class BoardsController {
    constructor( private boardsService : BoardsService) {} 
    // nest에서는 boardsService 인스턴스를 프로퍼티라고 부르는 것 같다

    @Get('/:id')
    getBoardById(@Param('id') id:number) : Promise<Board> {
        return this.boardsService.getBoardById(id);
    }

    @Post()
    @UsePipes(ValidationPipe)
    createBoard(@Body() createBoardDto: CreateBoardDto) : Promise<Board> {
        return this.boardsService.createBoard(createBoardDto);
    }

    @Patch('/:id/status')
    updateBoardStatus(
        @Param('id', ParseIntPipe) id: number,
        @Body('status') status : BoardStatus
    ) {
        return this.boardsService.updateBoardStatus(id, status);
    }

    @Delete('/:id')
    deleteBoard(@Param('id', ParseIntPipe) id: number) {
        return this.boardsService.deleteBoard(id);
    }

}

  - validationPipe를 사용하기 위해서는 아래와 같이 npm install이 필요합니다.

설치하게되면 기본적인 validation 체크를 위한 데코레이터를 사용할 수 있습니다.

npm install class-validator class-transformer --save

 

boards.service.ts

import { Injectable, NotFoundException } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { BoardStatus } from './board-status.enum';
import { Board } from './board.entity';
import { CreateBoardDto } from './dto/create-board.dto';

@Injectable() // nest js 어디에서나 사용할 수 있게 해준다
export class BoardsService {

    constructor(
        @InjectRepository(Board)
        private boardRepository : Repository<Board>,
    ){}

    async getBoardById(id: number): Promise <Board> {
        const found = await this.boardRepository.findOneBy({id});
        if(!found) {
            throw new NotFoundException(`Can't find Board with id ${id}`);
        }
        return found;
    }

    async createBoard(createBoardDto : CreateBoardDto) : Promise<Board> {
        const {title, description} = createBoardDto;

        const board = this.boardRepository.create({
            title,
            description,
            status: BoardStatus.PUBLIC
        })

        await this.boardRepository.save(board);
        return board;
    }

    async updateBoardStatus(id:number, status: BoardStatus) : Promise<Board> {
        const board = await this.getBoardById(id);
        
            board.status = status;
            await this.boardRepository.save(board);

            return board;
    }

    async deleteBoard(id:number) : Promise<void> {
        const result = await this.boardRepository.delete(id);

        if(result.affected === 0 ) {
            throw new NotFoundException(`Can't find Board with id ${id}`);
        }
    }

}

 

create-board.dto.ts

  - dto class

import { IsNotEmpty } from "class-validator";

export class CreateBoardDto{
    @IsNotEmpty()
    title:string;

    @IsNotEmpty()
    description:string;
}

 

board-status.enum.ts

  - BoardStatus를 상수로 쓰기 위한 enum

// 게시판 모델 정의
// interface : 변수의 타입만의 체크한다.
// classes   : 변수의 타입도 체크하고 인스턴스 생성할 수 있다.

// export interface Board {

//     id: string;
//     title: string;
//     description: string;
//     status: BoardStatus

// }

export enum BoardStatus {
    PUBLIC = 'PUBLIC',
    PRIVATE = 'PRIVATE'
}

 

boards.module.ts

import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { Board } from './board.entity';
import { BoardsController } from './boards.controller';
import { BoardsService } from './boards.service';

@Module({
    imports: [
        TypeOrmModule.forFeature([Board])
    ],
    controllers: [BoardsController],
    providers: [BoardsService]
})
export class BoardsModule {}

 

app.module.ts

  - imports에 BoardsModule을 추가합니다.

import { Module } from '@nestjs/common';
import { BoardsModule } from './boards/boards.module';
import { TypeOrmModule } from '@nestjs/typeorm';
import { typeORMConfig } from './configs/config.typeorm';

@Module({
  imports: [
    TypeOrmModule.forRoot(typeORMConfig),
    BoardsModule
  ],
})
export class AppModule {}

 

참조

- 따라하며 배우는 NestJS

728x90
반응형

'NestJS' 카테고리의 다른 글

Jest에서 의존성 주입과 Mock 데이터를 설정하는 방법  (0) 2025.02.04
[Nest.js] PIPE  (0) 2023.08.27
[Nest.js] 기본 파일 구조 및 요청 흐름  (2) 2023.08.20
[Nest.js] Quick Start!  (0) 2023.08.15
반응형

nest.js

 

지난 시간에 nest.js 셋업에 이어서

이번 시간에는 nest.js client로 프로젝트를 생성하였을 때 기본적으로 생성되는 파일client 요청에 따른 흐름을 알아보겠습니다.

 

1. 기본적으로 생성되는 파일

 

 

1.eslintrc.js : 개발자들이 특정한 규칙을 가지고 코드를 깔끔하게 짤 수 있도록 도와주는 라이브러리, 타입스크립트를 쓰는 가이드 라인 제시, 문법에 오류가 나면 알려주는 역할 등

2. prettierrc : 주로 코드 형식을 맞추는데 사용합니다. 작은 따옴표를 사용할지 큰 따옴표를 사용할지 Indent 값을 두줄로 줄지 네줄로 줄지등등 에러 찾는 것이 아닌 코드 포멧터 역할

3. nest-cli.json : nest 프로젝트를 위한 특정한 설정을 할 수 있는 json 파일

4. tsconfig.json : 어떻게 타입스크립트를 컴파일 할지 설정

5. tsconfig.build.json : tsconfig.json의 연장선상 파일이며, build를 할 때 필요한 설정등 "excludes"에서는 빌드할 때 필요 없는 파일들 명시

6. package.json : build : 운영환경을 위한 빌드, format: 린트에러가 났을지 수정, start : 앱 시작 

7. src : 대부분의 비지니스 로직이 들어가는 곳

 

 

2. client 요청에 따른 흐름

client(브라우저)에서 localhost:3000번으로 요청을 보내면

nest.js 애플리케이션에서는 app.module 요청에 대한 진입점 역할을 하는데 요청을 구분해서 등록되어 있는 controller에 요청을 전달합니다.

controller로 요청을 보내고, service에서 'Hello World!'라는 문자열을 리턴 받아서 client에서 응답하는 흐름입니다.

 

1. app.module.ts

  - controllers에 AppController가 providers에 AppService가 등록되어 있습니다.

  - module에 대해서는 아래에서 더 상세하게 설명을 하도록 하겠습니다.

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

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

 

2. app.controller.ts

  - @Get 데코레이터를 보시면 "/" 요청이 오면 getHello() 함수를 실행하도록 되어 있습니다.

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();
  }
}

 

3. app.service.ts

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

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

 

모듈이란

모듈은 @Module() 데코레이터로 주석이 달린 클래스입니다. @Module() 데코레이터는 Nest가 애플리케이션 구조를 구성하는 데 사용하는 메타 데이터를 제공합니다. 

각 응용 프로그램에는 하나 이상의 모듈이 있습니다. 루트 모듈(AppModule)은 Nest가 사용하는 시작점입니다.

모듈은 밀접하게 관련있는 기능 집합으로 구성 요소를 구성한느 효과적인 방법입니다.

모듈은 기본적으로 싱글 톤이므로 여러 모듈간의 쉽게 공급자의 동일한 인스턴스를 공유 할 수 있습니다.

 

참조 

- 따라하며 배우는 NestJS

728x90
반응형

'NestJS' 카테고리의 다른 글

Jest에서 의존성 주입과 Mock 데이터를 설정하는 방법  (0) 2025.02.04
[Nest.js] PIPE  (0) 2023.08.27
[Nest.js] TypeORM 이용한 CRUD  (0) 2023.08.22
[Nest.js] Quick Start!  (0) 2023.08.15
반응형

nest.js

 

 

1. Nest.js 사용이유

Nest.js는 구조화된 코드 작성, 의존성 관리, 유연한 미들웨어 처리, 데이터 유효성 검사등의 장점을 제공하여 백엔드 애플리케이션 개발을 효율적이고 유지보수하기 쉽게 만들어주는 프레임워크입니다.

 

2. Nest.js 특징

1. 모듈러 아키텍처 : Nest.js는 애플리케이션을 모듈 단위로 구성하여 코드를 구조화하고 유지보수하기 쉽게 만들어줍니다.

2. 의존성 주입 : 의존성 주입은 컴포넌트 간의 의존성을 효율적으로 관리하고 분리하는 방법을 제공합니다.

3. 데코레이터 : 데코레이터는 컨트롤러, 서비스 등의 메타데이터를 정의하여 사용합니다. 이를 통해 라이팅, 유효성 검사 등을 더 쉽게 처리할 수 있습니다.

 

3. Express 프레임워크와 비교

Node.js를 이용한 백엔드 서버는 Express가 많이 보편적으로 사용되어 왔습니다. 미니멀리스트적인 접근 방식을 취하고, 기본적인 웹 프레임워크로서 필요한 기능만 제공하며, 개발자가 직접 확장하거나 추가 기능을 구현해야 합니다.

반면에 Nest.js는 구조화된 코드, 의존서 주입, TypeScript의 강력한 지원과 같은 장점을 통해 큰 규모의 백엔드 애플리케이션을 더 효율적으로 개발하고 유지보수 할 수 있도록 도와줍니다.

 

4. Nest.js Setup

Nest CLI를 사용하여 새 프로젝트를 설정할 수 있습니다.

npm이 설치된 상태에서 터미널에 아래와 같이 명령어를 사용하여 Nest 프로젝트를 만들어줍니다.

 

4.1) 프로젝트 생성

$ npm i -g @nestjs/cli
$ nest new project-name

 

디렉토리가 프로젝트 이름으로 생성되고 노드 모듈 및 여러 파일과 src/ 생성되어 여러 코어 파일이 생성됩니다.

 

main.ts

 - NestFactory 핵심 기능을 사용하여 Nest 애플리케이션 인스턴스를 생성하는 애플리케이션 엔트리 파일입니다.

 - app.listen() : 웹 어플리케이션 포트

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  await app.listen(3000);
}
bootstrap();

 

4.2) 프로젝트 실행

$ npm run start			프로젝트 실행
$ npm run start:dev		파일의 변경 사항을 적용하려면 개발 모드로 실행

 

http://localhost:3000 으로 접속 성공

다음장에서는 기본적으로 생성된 파일 역할을 간략하게 설명하고 localhost:3000에 접속하였을 때 nest.js 애플리케이션의 간단한 진행 흐름을 알아보도록 하겠습니다.

 

 

 

참고 

- https://docs.nestjs.com/first-steps

 

728x90
반응형

+ Recent posts