Backend/NestJS

NestJS로 백엔드 프로젝트 시작하기 (TypeORM, PostgreSQL)

민 채 2025. 5. 12. 09:03

Nest.js 란?

Java Spring의 구조를 차용한 Node.js 환경의 새로운 프레임워크입니다. 이는 MVC 디자인 패턴(Controller, Service, Entity, Repository 등)을 기본 패턴으로 하므로 역할과 구현(또는 책임)이 명확하게 구분된다는 장점이 있습니다. 따라서, 협업 시 매우 효율적으로 작업할 수 있으며, Typescript를 기본으로 적용하므로 잠재적인 오류 발생 확률을 줄일 수 있습니다.

 

실제로 저는 Nest 는 이번 기회에 처음 써봤는데, Spring 개발 경험과 Typescript 로 프론트엔드 개발했던 경험이 있어서 그런지 금방 적응 할 수 있었습니다.


프로젝트 생성

$ nest new project1
$ cd project1
$ npm run start
  • Node 가 설치되어 있는 환경에서 위 명령어를 통해 프로젝트를 생성해주었습니다.
  • vscode 터미널에서 간단히 프로젝트를 생성할 수 있습니다.

 

프로젝트가 정상적으로 생성되었을 경우에는 브라우저에서 localhost:3000 에 접속했을 때 위와같이 Hello world! 라는 글자가 보이게 됩니다.

nest start 명령어로도 로컬 서버를 실행시킬 수 있습니다.

 


TypeORM 의존성 설치

$ npm install @nestjs/typeorm typeorm pg
  • @nestjs/typeorm: NestJS에서 TypeORM을 사용하기 위한 모듈
  • typeorm: Node.js ORM(Object Relational Mapper) 라이브러리. 엔티티를 통해 DB 테이블을 정의하고, 쿼리 작성 없이도 조작이 가능함.
  • pg: PostgreSQL을 TypeORM과 함께 사용하기 위한 드라이버

 

사용 예시

// app.module
    TypeOrmModule.forRoot({
      type: 'postgres',
      host: process.env.PG_HOST,
      port: parseInt(process.env.PG_PORT ?? '5432'), // 기본값 5432
      username: process.env.PG_USER,
      password: process.env.PG_PASSWORD,
      database: process.env.PG_DBNAME,
      entities: [__dirname + '/**/*.entity.{ts,js}'],
      synchronize: true,
    }),

app.module 파일에서 orm 설정을 할 수 있습니다.
저는 .env 파일을 통해 민감정보를 처리하는 방식을 활용했습니다.

 

// src/data-source.ts

import { DataSource } from 'typeorm';

export const AppDataSource = new DataSource({
  type: 'postgres',
  host: process.env.DATABASE_HOST || 'localhost',
  port: Number(process.env.DATABASE_PORT) || 5432,
  username: process.env.DATABASE_USER || 'postgres',
  password: process.env.DATABASE_PASSWORD || 'postgres',
  database: process.env.DATABASE_NAME || 'board_db',
  entities: [__dirname + '/../**/*.entity.{ts,js}'],
  synchronize: true,
});

data-source.ts 파일을 src 안에 생성해주고 위 설정을 추가해줍니다.

 


환경변수 관리 (.env)

$ npm install @nestjs/config
  • .env 파일을 사용해서 환경별 설정을 분리할 수 있게 해주는 모듈입니다.
  • DB 정보, JWT 시크릿 키, 포트 번호 등 민감한 정보를 코드에서 분리할 수 있습니다.

 

저는 개발환경과 서비스 환경의 DB를 분리하기 위해 두개의 .env파일을 만들었습니다. (.env.production, .env.development)

// .env.development
NODE_ENV=development
PG_HOST=localhost
PG_PORT=5432
PG_USER=postgres
PG_PASSWORD=password
PG_DBNAME=boarddev
JWT_SECRET=access-secret
JWT_REFRESH_SECRET=refresh-secret
POSTGRES_USER=postgres
POSTGRES_PASSWORD=password
POSTGRES_DB=boarddev

이런식으로 민감정보를 따로 관리하여 노출되지 않게 할 수 있습니다.

 

//main.ts
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { ValidationPipe } from '@nestjs/common';
import { config } from 'dotenv';

// NODE_ENV에 따라 환경변수 파일 선택
const envFile =
  process.env.NODE_ENV === 'production'
    ? '.env.production'
    : '.env.development';
config({ path: envFile });

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.useGlobalPipes(new ValidationPipe());

  // 개발 환경일 경우 요청 로그 기록
  if (process.env.NODE_ENV === 'development') {
    app.use((req, res, next) => {
      const { method, originalUrl } = req;
      const start = Date.now();

      res.on('finish', () => {
        const duration = Date.now() - start;
        const log = `${method} ${originalUrl} ${res.statusCode} ${res.statusMessage} - ${duration}ms`;
        console.log(log);
      });

      next();
    });
  }
  await app.listen(process.env.PORT ?? 3000);
}
bootstrap();

그리고, 개발환경일 경우 api 호출이 될때 로그를 찍고 싶어서 위 코드를 추가해주었습니다.

 


데이터 검증

$ npm install class-validator class-transformer

위 라이브러리를 설치하면, 들어오는 데이터를 자동으로 검증하고 변환할 수 있습니다.

import { IsString, IsEmail } from 'class-validator';

export class CreateUserDto {
  @IsString()
  name: string;

  @IsEmail()
  email: string;
}

예를 들어, 이메일 형식인지 string 형식인지 자동으로 검증해줍니다.

 

위 사진은 postman 으로 테스트한 결과입니다. 올바르지 않은 형식으로 요청했을 때, 자동으로 에러메세지를 반환해주는 모습을 볼 수 있습니다.

 

설정 방법

// main.ts
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { ValidationPipe } from '@nestjs/common';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.useGlobalPipes(new ValidationPipe());
  await app.listen(process.env.PORT ?? 3000);
}
bootstrap();
  • main.tsapp.useGlobalPipes(new ValidationPipe()); 이 부분을 넣어줍니다. listen 코드 이전에 넣어야합니다.

 

마무리

이렇게 기본적인 NestJS 프로젝트를 구성하면서 필수적인 라이브러리들을 설치하고 활용하는 방법을 살펴봤습니다. 다음 포스팅에서는 swagger 설정부터 docker 활용까지 확장해보겠습니다.