본문으로 건너뛰기

NX 모노레포 가이드라인

버전: v20.6
작성일: 2025-03-22

1. 개요

NX는 JavaScript/TypeScript 프로젝트를 위한 강력한 모노레포 도구입니다. 이 가이드라인은 DTA-WIDE 프로젝트에서 NX를 효과적으로 사용하기 위한 표준과 모범 사례를 제공합니다.

참고: 개발 환경 설정, 소프트웨어 설치, 환경 변수 설정 등 실제 개발 환경 구축에 관한 내용은 개발 환경 설정 가이드를 참조하세요.

2. NX 워크스페이스 구조

2.1 디렉터리 구조

dta-wide-mono/
├── apps/ # 애플리케이션 (배포 가능한 단위)
│ ├── dta-wide-api/ # 백엔드 API (NestJS)
│ └── web/ # 프론트엔드 앱 (React)
├── libs/ # 라이브러리 (재사용 가능한 코드)
│ ├── feature/ # 도메인별 기능 라이브러리
│ │ ├── auth/
│ │ ├── user/
│ │ └── ...
│ ├── core/ # 핵심 인프라 라이브러리
│ │ ├── database/
│ │ ├── config/
│ │ └── ...
│ └── shared/ # 공유 유틸리티 라이브러리
│ ├── dto/
│ ├── interfaces/
│ └── ...
├── tools/ # 개발 도구 및 스크립트
│ ├── generators/ # 커스텀 제너레이터
│ └── scripts/ # 유틸리티 스크립트
├── .nx/ # NX 캐시 및 설정
└── nx.json # NX 설정 파일

2.2 프로젝트 구성 원칙

  • 애플리케이션(apps): 최종적으로 배포 가능한 단위
  • 라이브러리(libs): 재사용 가능한 코드 모듈
  • 도구(tools): 개발 도구 및 스크립트

3. 프로젝트 구성 규칙

3.1 네이밍 컨벤션

애플리케이션

  • 짧고 명확한 이름 사용 (dta-wide-api, web)
  • 하이픈(-)으로 단어 구분

라이브러리

  • 계층-기능 형식으로 구성
  • 예: feature-auth, core-database, shared-interfaces

태그 규칙

"tags": [
"scope:{core|feature|shared}",
"type:{api|ui|util|domain|...}",
"domain:{auth|user|...}"
]

3.2 의존성 규칙

  • 단방향 의존성: core → shared → feature → app
  • 순환 의존성 금지: 라이브러리 간 순환 참조 금지
  • 의존성 경계:
    • core 모듈은 다른 모듈에 의존하지 않음
    • shared 모듈은 core 모듈에만 의존
    • feature 모듈은 coreshared에 의존 가능
    • 애플리케이션은 모든 모듈에 의존 가능

4. NX 명령어 체계

4.1 주요 명령어

프로젝트 생성 및 수정

# 워크스페이스 생성
npx create-nx-workspace@20.6.0 dta-wide-mono --preset=empty --packageManager=yarn

# NestJS 애플리케이션 생성
nx g @nx/nest:app --name dta-wide-api --directory=apps/dta-wide-api --tags=scope:api

# 라이브러리 생성
nx g @nx/nest:lib --name=feature-auth --directory=libs/feature/auth --tags=scope:feature,domain:auth

# Shared 라이브러리 생성
nx g @nx/nest:lib --name=shared-contracts-notification --directory=libs/shared/contracts-notification --tags=scope:shared,domain:contract

# 컨트롤러 생성
nx g @nx/nest:controller auth --project=feature-auth --directory=lib/controllers

참고: 이 명령어들의 실제 사용법과 로컬 개발 환경 설정 방법은 개발 환경 설정 가이드를 참조하세요.

빌드 및 실행

# 개발 서버 실행
nx serve dta-wide-api

# 빌드
nx build dta-wide-api

# 테스트
nx test feature-auth

# 린트
nx lint feature-auth

고급 기능

# 영향 받는 프로젝트만 실행
nx affected -t test

# 의존성 그래프 시각화
nx graph

# 여러 프로젝트에 대해 동시 실행
nx run-many -t build -p dta-wide-api feature-auth

4.2 NX v20.6의 새로운 기능

  • Nx Agents: 빌드 및 테스트 실행 최적화
  • 디스크 캐시 개선: 분산 환경에서의 캐시 효율성 향상
  • 플러그인 API 개선: 확장성 강화
  • 타겟 설정 개선: 더 유연한 실행 구성

5. 라이브러리 설계 가이드

5.1 라이브러리 유형

기능(Feature) 라이브러리

  • 특정 도메인 기능 구현
  • 특정 애플리케이션에 종속될 수 있음
  • 예: feature-auth, feature-user

유틸리티(Utility) 라이브러리

  • 재사용 가능한 헬퍼 함수 및 유틸리티
  • 애플리케이션에 독립적
  • 예: shared-utils

모델(Model) 라이브러리

  • 데이터 모델 및 인터페이스 정의
  • 여러 라이브러리에서 공유
  • 예: shared-dto, shared-interfaces

UI 라이브러리

  • 재사용 가능한 UI 컴포넌트
  • 프론트엔드 애플리케이션용
  • 예: shared-ui-components

5.2 라이브러리 경계 설정 원칙

  1. 단일 책임 원칙: 각 라이브러리는 하나의 책임 영역에 집중
  2. 변경 빈도에 따른 분리: 함께 변경되는 코드는 같은 라이브러리에 배치
  3. 팀 경계 고려: 팀 구조에 맞게 라이브러리 경계 설정
  4. 재사용성 평가: 재사용 패턴에 따라 라이브러리 분리

6. 모노레포 최적화 기법

6.1 빌드 최적화

  • 증분 빌드 활용: 변경된 프로젝트만 빌드
  • 병렬 빌드 설정: 동시에 여러 프로젝트 빌드
  • 캐시 활용: nx.json에서 캐시 설정 최적화
// nx.json
{
"tasksRunnerOptions": {
"default": {
"runner": "nx/tasks-runners/default",
"options": {
"cacheableOperations": ["build", "lint", "test", "e2e"],
"parallel": 4
}
}
}
}

참고: 로컬 개발 환경에서의 구체적인 최적화 방법과 문제 해결에 대한 내용은 개발 환경 설정 가이드를 참조하세요.

6.2 CI/CD 최적화

  • 영향 받는 프로젝트만 검증:
nx affected -t lint,test,build
  • 이전 빌드 캐시 활용:
# GitHub Actions 예시
- name: Nx Cache
uses: actions/cache@v3
with:
path: .nx/cache
key: ${{ runner.os }}-nx-${{ hashFiles('**/package-lock.json') }}
restore-keys: ${{ runner.os }}-nx-

7. NX 설정 가이드

7.1 project.json

모든 프로젝트는 자체 project.json 파일을 가지며, 다음과 같은 표준 구성을 따릅니다:

{
"name": "feature-auth",
"sourceRoot": "libs/feature/auth/src",
"projectType": "library",
"tags": ["scope:feature", "domain:auth"],
"targets": {
"lint": { /* 린트 설정 */ },
"test": { /* 테스트 설정 */ },
"build": { /* 빌드 설정 */ }
},
"implicitDependencies": []
}

7.2 nx.json

루트 nx.json 파일은 모노레포 전체에 대한 설정을 포함합니다:

{
"extends": "nx/presets/npm.json",
"npmScope": "dta-wide",
"tasksRunnerOptions": { /* 실행기 옵션 */ },
"targetDefaults": {
"build": {
"dependsOn": ["^build"],
"inputs": ["production", "^production"]
},
"test": {
"inputs": ["default", "^production", "{workspaceRoot}/jest.preset.js"]
}
},
"workspaceLayout": {
"appsDir": "apps",
"libsDir": "libs"
}
}

8. 모범 사례 및 팁

8.1 코드 생성 활용

  • 내장 제너레이터를 사용하여 일관된 코드 생성
  • 커스텀 제너레이터를 개발하여 프로젝트 표준 적용

8.2 의존성 그래프 관리

  • 정기적으로 nx graph 검토
  • 불필요한 의존성 제거 및 순환 의존성 방지

8.3 공통 코드 재사용

  • 중복 코드는 공유 라이브러리로 추출
  • 공유 인터페이스와 타입을 활용한 일관성 유지

8.4 캐시 최적화

  • 클라우드 캐시 활용 (대규모 팀)
  • 로컬 캐시 정기적 정리

9. NestJS와 NX 통합 팁

9.1 라이브러리 임포트 최적화

// 권장 임포트 방식
import { UserService } from '@dta-wide/feature/user';

// 비권장 상대 경로 임포트
import { UserService } from '../../../libs/feature/user/src/lib/user.service';

9.2 프로젝트 경계 유지

  • 각 라이브러리의 public API는 index.ts에서만 내보내기
  • 라이브러리 내부 구현 세부사항은 노출하지 않기

9.3 모듈 구성 최적화

// 도메인 모듈 구조
@Module({
imports: [CoreDatabaseModule],
controllers: [UserController],
providers: [UserService, UserRepository],
exports: [UserService]
})
export class UserModule {}

10. 문제 해결 및 디버깅

10.1 일반적인 문제 해결

  • 캐시 관련 문제: nx reset 명령으로 캐시 초기화
  • 의존성 문제: nx graph 로 의존성 검사
  • 빌드 실패: nx build --verbose 로 상세 로그 확인

참고: 실제 개발 중 발생하는 구체적인 문제 해결 방법과 환경 설정 관련 문제는 개발 환경 설정 가이드에서 더 자세히 다루고 있습니다.

10.2 성능 문제 해결

  • 느린 빌드: 캐시 설정 및 증분 빌드 확인
  • CI/CD 최적화: 영향받는 프로젝트만 빌드/테스트

11. 버전 업그레이드 가이드

11.1 NX 버전 업그레이드 절차

# 최신 버전 확인
nx --version

# 마이그레이션 실행
nx migrate latest

# 패키지 업데이트
yarn

# 마이그레이션 적용
nx migrate --run-migrations

11.2 마이그레이션 고려사항

  • 주요 변경 사항 체크: 공식 마이그레이션 가이드 참조
  • 단계적 업그레이드: 메이저 버전 간 직접 업그레이드 지양
  • 충분한 테스트: 업그레이드 후 모든 빌드/테스트 수행

12. 참고 자료

13. 변경 이력

버전날짜작성자변경 내용
0.1.02025-03-22bok@weltcorp.com최초 작성 (NX v20.6 기준)
0.1.12025-03-27bok@weltcorp.com개발 환경 설정 가이드(setup.md) 참조 추가 및 역할 명확화