TIL - 20260228

juni·2026년 2월 28일

TIL

목록 보기
280/316

0228 NestJS 기초 최종 정리: 아키텍처와 발전 방향


✅ 1. NestJS의 핵심 아키텍처: 계층형 구조와 의존성 주입

  • 지난 시간 동안 학습한 NestJS의 모든 구성 요소는 계층형 아키텍처(Layered Architecture)의존성 주입(DI)이라는 두 가지 핵심 원리를 기반으로 유기적으로 동작합니다.

  • 요청 처리 흐름 (복습):
    RequestMiddlewareGuardInterceptor(Pre)PipeControllerServiceRepositoryDatabase
    ResponseInterceptor(Post)Exception FilterControllerServiceRepository

  • 역할 분리:

    • Controller: 라우팅, 요청/응답의 입출력 담당.
    • Service: 핵심 비즈니스 로직 처리.
    • Repository (via TypeORM): 데이터베이스와의 상호작용.
    • Guard, Pipe, Interceptor 등: 인증, 유효성 검증, 로깅 등 횡단 관심사(Cross-cutting Concerns) 처리.
  • 의존성 주입 (DI):

    • NestJS의 IoC 컨테이너는 @Injectable()이 붙은 클래스(프로바이더)들을 관리합니다.
    • 생성자(constructor)를 통해 필요한 의존성을 선언하면, NestJS가 알아서 적절한 인스턴스를 주입해줍니다.
    • 이러한 DI 구조 덕분에 각 컴포넌트는 자신의 책임에만 집중할 수 있고, 다른 컴포넌트의 구체적인 구현을 알 필요 없이 느슨하게 결합(Loosely Coupled)되어, 테스트하기 쉽고 유지보수하기 좋은 코드가 만들어집니다.

✅ 2. 모듈(Module)을 이용한 기능 단위 설계

  • 애플리케이션이 커질수록, 모든 컨트롤러와 서비스를 하나의 거대한 app.module.ts에 등록하는 것은 비효율적입니다.

  • 모듈은 관련된 기능(컨트롤러, 서비스, 리포지토리 등)을 하나의 독립적인 단위로 캡슐화하는 역할을 합니다.

  • 설계 원칙:

    • 기능별 모듈 분리: UsersModule, MoviesModule, AuthModule과 같이 도메인 또는 기능별로 모듈을 분리합니다.
    • 캡슐화와 공개 (exports): 각 모듈은 기본적으로 내부의 프로바이더를 캡슐화합니다. 다른 모듈에서 사용해야 하는 프로바이더(e.g., UsersService)가 있다면, exports 배열에 명시적으로 추가하여 외부로 공개해야 합니다.
    • 의존성 관리 (imports): MoviesModuleUsersModule에서 공개한 UsersService를 사용해야 한다면, MoviesModuleimports 배열에 UsersModule을 추가합니다.
  • 장점:

    • 관심사 분리: 코드의 구조가 명확해지고, 특정 기능을 찾고 수정하기 쉬워집니다.
    • 느슨한 결합: 모듈 간의 의존성이 imports 배열을 통해 명시적으로 관리됩니다.
    • 재사용성: 잘 만들어진 모듈은 다른 프로젝트에서도 재사용할 수 있습니다.

✅ 3. GraphQL: 또 다른 선택지

  • NestJS는 전통적인 REST API뿐만 아니라, GraphQL을 위한 훌륭한 아키텍처도 제공합니다.
구분REST APIGraphQL
엔드포인트여러 개 (e.g., /users, /movies)단 하나 (e.g., /graphql)
데이터 요청서버가 정의한 고정된 구조로 받음클라이언트가 필요한 데이터의 구조를 직접 정의하여 요청
장점• 직관적이고 단순함
• HTTP 캐싱 등 생태계 성숙
• Over/Under-fetching 문제 해결
• 프론트엔드 개발 유연성 증대
NestJS 구현ControllerResolver
  • 프로젝트의 특성(다양한 클라이언트, 복잡한 데이터 관계 등)에 따라 GraphQL이 더 적합한 선택이 될 수 있으며, NestJS는 두 가지 방식을 모두 지원하거나 심지어 함께 사용하는 것도 가능합니다.

✅ 4. 테스트 전략의 중요성

  • 안정적인 애플리케이션을 위해서는 반드시 테스트 코드를 작성해야 합니다. NestJS는 테스트를 위한 훌륭한 환경을 기본적으로 제공합니다.

  • 테스트 피라미드 전략:

    1. 단위 테스트 (Unit Test):
      • 대상: 주로 서비스(Service) 계층의 비즈니스 로직.
      • 방법: 외부 의존성(Repository 등)을 Mocking하여, 순수한 로직의 정확성을 검증. 매우 빠르고 안정적.
    2. E2E 테스트 (End-to-End Test):
      • 대상: 전체 애플리케이션.
      • 방법: Supertest를 사용하여 실제 HTTP 요청을 보내고, 모든 계층을 거친 최종 응답을 검증. 느리지만 가장 높은 신뢰도를 제공.
      • 주의: 반드시 테스트 전용 데이터베이스를 분리하여 사용해야 함.

📌 최종 요약 및 다음 단계

  • NestJS는 모듈, 컨트롤러, 프로바이더라는 구조화된 아키텍처와 의존성 주입(DI)을 통해, 대규모 서버 애플리케이션을 체계적으로 구축할 수 있는 강력한 프레임워크입니다.

  • TypeORM을 통해 데이터베이스와의 상호작용을 객체 지향적으로 처리하고, class-validator파이프로 데이터 유효성을 검증하며, 가드JWT로 인증/인가를 구현했습니다.

  • 또한, @nestjs/config로 설정을 안전하게 관리하고, E2E 테스트로 애플리케이션의 안정성을 보장하는 방법을 학습했습니다.

  • 다음 학습 로드맵:

    • 데이터베이스 심화: 복잡한 관계 매핑, 트랜잭션 관리, QueryBuilder 사용.
    • 인증/인가 심화: OAuth2 소셜 로그인, Refresh Token 전략.
    • 비동기 처리: Task Scheduling, Queue, WebSocket.
    • 배포: Docker, CI/CD, 클라우드(AWS) 환경에 배포하기.

0개의 댓글