Choorai
Lv.4 실무 Node.js TypeScript

NestJS로 실무 구조 배우기

NestJS는 Angular에서 영감을 받은 엔터프라이즈급 Node.js 프레임워크입니다. 모듈, 의존성 주입, 데코레이터 패턴을 사용합니다.

Hono를 먼저 해보세요

NestJS는 구조가 복잡합니다. 백엔드가 처음이라면 Hono (Lv.1)부터 시작하세요.

왜 NestJS인가?

👍 장점

  • • 명확한 구조 (모듈/컨트롤러/서비스)
  • • 의존성 주입 (DI) 지원
  • • 채용 시장에서 인기
  • • 대규모 팀에 적합

👎 단점

  • • 학습 곡선이 가파름
  • • 보일러플레이트 코드 많음
  • • 작은 프로젝트에는 과함
  • • 데코레이터 문법 익숙해야 함

프로젝트 구조

NestJS는 모듈 기반 아키텍처를 사용합니다. 각 기능은 모듈로 분리되고, 모듈은 컨트롤러와 서비스로 구성됩니다.

프로젝트 구조
src/
├── main.ts                    # 진입점
├── app.module.ts              # 루트 모듈
├── health/
│   ├── health.module.ts       # 헬스 모듈
│   └── health.controller.ts   # 헬스 컨트롤러
└── projects/
    ├── projects.module.ts     # 프로젝트 모듈
    ├── projects.controller.ts # 라우팅 담당
    ├── projects.service.ts    # 비즈니스 로직
    └── dto/
        ├── create-project.dto.ts
        └── update-project.dto.ts

핵심 개념

  • Module: 관련 기능을 묶는 단위. imports/exports로 의존성 관리
  • Controller: HTTP 요청 처리. 라우팅과 응답 담당
  • Service: 비즈니스 로직. 컨트롤러에 주입됨
  • DTO: 데이터 전송 객체. 입력 검증에 사용

코드 예제

1. 메인 진입점

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

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

  // CORS 설정
  app.enableCors({
    origin: ['http://localhost:5173'],
    credentials: true,
  });

  // 전역 검증 파이프
  app.useGlobalPipes(new ValidationPipe({
    whitelist: true,
    transform: true,
  }));

  await app.listen(8000);
  console.log('🚀 NestJS running on http://localhost:8000');
}

bootstrap();

2. 루트 모듈

src/app.module.ts
import { Module } from '@nestjs/common';
import { HealthModule } from './health/health.module';
import { ProjectsModule } from './projects/projects.module';

@Module({
  imports: [HealthModule, ProjectsModule],
})
export class AppModule {}

3. DTO (입력 검증)

src/projects/dto/create-project.dto.ts
import { IsString, IsOptional, MinLength, MaxLength } from 'class-validator';

export class CreateProjectDto {
  @IsString()
  @MinLength(1)
  @MaxLength(100)
  name: string;

  @IsOptional()
  @IsString()
  @MaxLength(500)
  description?: string;
}

4. 컨트롤러

src/projects/projects.controller.ts
import { Controller, Get, Post, Body, Param, Delete, HttpCode } from '@nestjs/common';
import { ProjectsService } from './projects.service';
import { CreateProjectDto } from './dto/create-project.dto';

@Controller('api/v1/projects')  // 라우트 프리픽스
export class ProjectsController {
  // 의존성 주입
  constructor(private readonly projectsService: ProjectsService) {}

  @Post()
  @HttpCode(201)
  create(@Body() createProjectDto: CreateProjectDto) {
    return this.projectsService.create(createProjectDto);
  }

  @Get()
  findAll() {
    return this.projectsService.findAll();
  }

  @Get(':id')
  findOne(@Param('id') id: string) {
    return this.projectsService.findOne(id);
  }

  @Delete(':id')
  @HttpCode(204)
  remove(@Param('id') id: string) {
    return this.projectsService.remove(id);
  }
}

5. 서비스

src/projects/projects.service.ts
import { Injectable, NotFoundException } from '@nestjs/common';
import { CreateProjectDto } from './dto/create-project.dto';

@Injectable()  // DI 컨테이너에 등록
export class ProjectsService {
  private projects = new Map();

  create(dto: CreateProjectDto) {
    const project = {
      id: crypto.randomUUID(),
      name: dto.name,
      description: dto.description || null,
      created_at: new Date().toISOString(),
    };
    this.projects.set(project.id, project);
    return project;
  }

  findAll() {
    return {
      items: Array.from(this.projects.values()),
      total: this.projects.size,
    };
  }

  findOne(id: string) {
    const project = this.projects.get(id);
    if (!project) throw new NotFoundException('Project not found');
    return project;
  }

  remove(id: string) {
    if (!this.projects.delete(id)) {
      throw new NotFoundException('Project not found');
    }
  }
}

Hono vs NestJS 비교

항목 Hono (Lv.1) NestJS (Lv.4)
파일 수 5개 12개
코드량 ~150줄 ~300줄
학습 곡선 낮음 높음
구조 자유로움 규칙적
팀 규모 1-3명 5명+
적합한 상황 빠른 프로토타입, 간단한 API 복잡한 도메인, 장기 유지보수

전체 예제 코드

B2B Admin API의 NestJS 버전을 확인하세요: examples/b2b-admin/api-nest

다음 단계

백엔드 배포가 완료되었다면, Cycle 4: 데이터베이스에서 PostgreSQL을 연결하는 방법을 배웁니다.

마지막 업데이트: 2026년 2월 22일 · 버전: v0.0.1

피드백 보내기

입력한 내용으로 새 이슈 페이지를 엽니다.

GitHub 이슈로 보내기