NestJS 구조와 주요 개념 이해하기
NestJS 시작하기 관점에서 프로젝트 구조와 의존성 주입 기반 모듈·서비스·컨트롤러 개념을 예제와 함께 쉽게 풀어쓴 기술 소개
목차
소개
NestJS는 Node.js 환경에서 확장성과 유지보수를 중시한 서버 사이드 프레임워크다. TypeScript를 기본 언어로 사용하며, 모듈화와 의존성 주입(DI)을 통해 대형 애플리케이션 관리가 수월하다. 이 글은 NestJS 시작하기 수준에서 핵심 구조와 주요 개념을 차근히 설명한다.
왜 NestJS를 선택하는가
단순한 이유는 설계의 일관성이다. Express 위에서 동작하는 경우에도 구조화된 패턴을 제공한다. 또한 TypeScript의 타입 시스템을 적극 활용해 런타임 오류를 줄인다. 다음은 선택 포인트다.
- 명확한 모듈 구조로 팀 협업에 유리함
- 의존성 주입으로 테스트와 확장성 개선
- Rich한 기능과 데코레이터 기반 선언형 구성
NestJS의 핵심 개념
NestJS를 이해하려면 모듈(Module), 서비스(Service), 컨트롤러(Controller)의 관계부터 파악해야 한다. 이 세 가지는 애플리케이션의 골격을 형성한다.
모듈 (Module)
모듈은 관련 기능을 묶는 단위다. 컴포넌트, 서비스, 컨트롤러를 한 곳에 모아 재사용성과 캡슐화를 제공한다. 앱 루트에는 AppModule이 있으며, 기능별로 모듈을 분리하는 것이 권장된다.
서비스 (Service)
서비스는 비즈니스 로직을 담당한다. 일반적으로 컨트롤러에서 요청을 받아 서비스를 호출하고, 데이터 처리나 외부 API 연동을 수행한다. 의존성 주입으로 컨트롤러에 주입된다.
컨트롤러 (Controller)
컨트롤러는 HTTP 요청을 수신하고 응답을 반환한다. 라우트 핸들러를 정의하여 요청을 서비스로 위임한다. 컨트롤러는 가능한 얇게 유지하는 것이 바람직하다.
간단한 예제
이제 기본 구조를 코드로 확인한다. CLI로 생성한 기본 프로젝트 기준이다. 아래 예제는 AppModule, AppController, AppService의 최소 구성이다.
import { Module } from '@nestjs/common'
import { AppController } from './app.controller'
import { AppService } from './app.service'
@Module({
imports: [],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
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()
}
}
import { Injectable } from '@nestjs/common'
@Injectable()
export class AppService {
getHello(): string {
return 'Hello World from NestJS'
}
}
위 코드는 모듈에 컨트롤러와 서비스를 등록하고, 컨트롤러가 서비스를 주입받아 응답을 반환하는 기본 흐름을 보여준다.
프로젝트 시작과 CLI
NestJS CLI는 프로젝트 스캐폴딩과 코드 생성을 단순화한다. 일반적인 설치 및 프로젝트 생성 과정은 다음과 같다.
npm i -g @nestjs/cli
nest new my-project
cd my-project
npm run start:dev
이 흐름은 빠르게 앱을 띄우는 데 도움이 된다. 생성된 디렉터리 구조를 보면 src 아래에 모듈, 컨트롤러, 서비스 파일들이 위치한다.
의존성 주입과 제공자(Provider)
프로바이더는 서비스를 포함한 주입 가능한 모든 클래스다. @Injectable 데코레이터로 표시하고, 모듈의 providers 배열에 등록하면 다른 클래스에서 주입받을 수 있다. 이 방식은 테스트용 스텁 교체와 구현 분리에 유리하다.
실무적 구조 제안
기본 규칙은 기능별 모듈 분리다. 예를 들면 users, auth, products 같은 기능 단위로 모듈을 만든다. 각 모듈은 해당 도메인의 컨트롤러와 서비스를 포함한다. 이렇게 구성하면 팀 확장 시 충돌이 줄어든다.
- 단일 책임 원칙에 맞춘 모듈 설계
- 공통 기능은 SharedModule로 분리
- 환경별 설정은 ConfigModule로 관리
추가 고려사항
테스트는 Nest의 DI를 활용해 유닛 테스트와 통합 테스트를 작성한다. 또한 데이터베이스 연결은 TypeORM, Prisma 등과 연동해 사용한다. 배포 시에는 빌드된 JavaScript 파일을 컨테이너화하거나 서버에 배포하는 방식이 일반적이다.
맺음말
지금까지 NestJS 시작하기 관점에서 핵심 구조와 모듈·서비스·컨트롤러의 역할을 살펴보았다. 예제 코드를 통해 기본 흐름을 확인했으므로, 실제 프로젝트에 적용하며 구조를 확장하면 이해가 빠르게 진전된다.