NestJS (v10·v11)¶
웹빌더 같은 TypeScript 제품의 백엔드가 커지면, "라우트가 여기저기 흩어지고, 어느 파일이 어떤 역할인지 점점 모호해진다"는 문제가 생겨요. 순수 Express로도 API는 만들 수 있지만, 팀이 여럿이 되고 기능이 늘어날수록 구조를 잡아주는 무언가가 필요해지죠. NestJS는 그 자리에 프레임워크의 골격을 미리 짜둔 Node.js 백엔드 프레임워크예요. 우리는 v10과 v11을 함께 쓰고 있어요.
핵심 개념¶
모듈(Module)로 기능을 묶는다¶
NestJS에서 기본 단위는 모듈이에요. 인증, 알림, 주문 같은 기능을 각각 하나의 모듈로 묶고, 모듈이 필요한 의존성을 선언합니다. 기능 단위로 조각나 있으니 여러 팀이 충돌 없이 저마다의 모듈을 개발할 수 있어요.
의존성 주입(DI)으로 결합을 느슨하게¶
객체가 필요한 의존성을 직접 만들지 않고 컨테이너에 요청하는 의존성 주입이 NestJS의 심장이에요. Provider로 등록한 서비스를 생성자에 주입받으면, 구현을 갈아 끼우거나 테스트에서 가짜로 바꾸기 쉬워집니다. 서비스가 컨트롤러에 묶이지 않고 인터페이스 뒤에 숨는 구조죠.
파이프(Pipe)로 요청을 검증·변환¶
들어오는 요청은 파이프를 거쳐 검증·변환돼요. 예를 들어 ParseIntPipe는 경로의 문자열을 숫자로 바꾸고, DTO 기반 검증 파이프는 요청 본문이 스키마에 맞는지 확인합니다. v11에서는 ParseDatePipe가 추가돼 ISO-8601 문자열이나 타임스탬프를 Date로 다뤄요.
TypeORM으로 엔티티와 마이그레이션을 관리¶
NestJS 진영의 ORM 기준은 TypeORM이에요. 엔티티로 스키마를 정의하고, 마이그레이션으로 스키마 변경을 버전처럼 관리합니다. 관계·트랜잭션을 TypeScript 타입 위에서 다루죠.
Bull 큐로 무거운 작업을 뒤로 미룬다¶
이메일 발송, 파일 변환처럼 시간이 걸리는 작업은 Bull(BullMQ) 큐에 밀어 넣고 백그라운드에서 처리해요. Redis를 저장소로 써서 작업을 순차·병렬로 나눠 처리하고, 실패하면 재시도할 수 있습니다. 응답은 빠르게 주고 무거운 일은 뒤로 미루는 구조죠.
v11에서는 모듈 식별을 해시 대신 객체 참조로 바꿔 동적 모듈이 많은 앱의 부팅이 빨라졌고, 기본 ConsoleLogger가 JSON 로그를 지원해요. Node.js 18은 지원하지 않으니 v11은 Node.js 20 이상이 필요합니다.
사용 사례 / 실제 적용¶
웹빌더 백엔드는 NestJS로 돌아가요. 계층형 구조(표현·응용·도메인·인프라) 아래에서 이렇게 쓰입니다.
- 모듈별 개발 — 기능을 모듈로 나눠 여러 작업이 독립적으로 진행돼요. 공통 코드는 Factory 패턴이나 모듈화로 재사용합니다.
- LLM 통합 — Vercel AI SDK로 벤더를 추상화하고, SSE로 토큰을 스트리밍하며 Tool Calling으로 모델이 외부 도구를 호출하게 해요. 같은 계약이면 벤더를 바꿔도 코드가 안 바뀌죠.
- 비동기·배치 처리 — Bull 큐로 시간이 걸리는 작업을 밀어 넣고 처리합니다. 실패 시 재시도 전략으로 일시적 장애를 견뎌요.
- 검증 파이프 — 요청이 컨트롤러에 닿기 전에 파이프로 검증해, 잘못된 입력이 서비스 로직까지 내려가지 않게 막아요.
더 알아보기¶
- 공식 문서 (1차): NestJS 공식 문서 · NestJS 11 마이그레이션 · BullMQ · TypeORM
- 큐레이션/블로그 (2차): NestJS 공식 블로그 · NestJS 11 릴리스 노트