본문으로 건너뛰기

© 2026 Molayo

Dev.to헤드라인2026. 06. 07. 18:07

NestJS 모노레포를 위한 Claude Code: 실무 설정 가이드

요약

대규모 NestJS 모노레포 환경에서 Claude Code가 팀의 컨벤션을 준수하도록 설정하는 실무 가이드입니다. CLAUDE.md, rules, skills를 활용하여 AI의 추측을 제거하고 정확한 코드를 생성하는 방법을 다룹니다.

핵심 포인트

  • CLAUDE.md를 통해 프로젝트 브리핑 및 컨텍스트 제공
  • rules 폴더로 N+1 쿼리 금지 등 강력한 제약 사항 설정
  • skills 폴더를 활용한 반복 작업용 워크플로우 구축
  • settings.json을 통한 안전한 명령 실행 제어

대규모 NestJS 모노레포에서 AI가 생성한 코드가 팀의 컨벤션(Conventions)과 일치하도록 CLAUDE.md, 규칙(rules), 기술(skills)을 사용하여 Claude Code를 구성하는 실무적인 단계별 가이드입니다.

Hook: 설정되지 않은 모노레포에서 Claude에게 "예약에 소비자에게 보이는 상태를 추가해줘"라고 요청하면, Claude는 기쁘게도 _잘못된 마이크로서비스(microservice)_를 수정하고, 에러 문자열을 하드코딩하며, user.role === 'admin'을 체크할 것입니다. 이 중 어느 것도 Claude가 틀린 것이 아닙니다. Claude가 추측한 것뿐입니다. 이 가이드는 그러한 추측을 제거합니다.

핵심 요약 (Key Takeaways)

  • Claude Code는 git 루트의 .claude/를 읽습니다. 따라서 하나의 설정이 모노레포 내의 모든 서비스를 제어합니다.
  • 세 가지 메커니즘이 핵심 역할을 수행합니다: CLAUDE.md (항상 로드되는 프로젝트 브리핑), 규칙 (rules) (강력한 금지 사항)

NestJS 모노레포(monorepo)를 위한 Claude Code 설정 방법:
(1) npm install -g @anthropic-ai/claude-code로 설치한 후 claude를 통해 한 번 인증합니다; (2) 어떤 서비스가 무엇을 소유하는지, 요청 파이프라인(request pipeline), 그리고 표준 응답 형태(standard response shape)를 기록하는 루트 .claude/CLAUDE.md 파일을 생성합니다; (3) 강력한 금지 사항(N+1 쿼리 금지, 역할 이름 체크 금지, 상대 경로 임포트(relative imports) 금지 등)을 담은 .claude/rules/ 폴더를 추가합니다; (4) 엔드포인트(endpoint) 생성과 같은 반복적인 작업을 위한 다단계 워크플로우(multi-step workflows) 및 코드 템플릿이 포함된 .claude/skills/ 폴더를 구축합니다; (5) 안전한 명령은 허용하고 파괴적인 명령은 거부하도록 .claude/settings.json을 추가합니다. 팀 전체가 공유할 수 있도록 .claude/ 디렉토리를 git에 커밋하세요. 결과적으로, Claude는 추측하는 대신 여러분의 컨벤션(conventions)을 따르는 코드를 첫 시도에 바로 생성하게 됩니다.

문제점: 왜 Claude는 대규모 NestJS 프로젝트에서 어려움을 겪는가

대규모 NestJS 모노레포는 모든 AI 코딩 어시스턴트에게 가장 어려운 환경 중 하나입니다. 왜냐하면 정확성이 단일 파일에서는 보이지 않는 컨벤션(conventions)에 의존하기 때문입니다. 수십 개의 모듈, 수백 개의 DTO, 그리고 커스텀 가드(guards), 인터셉터(interceptors), 필터(filters), 어댑터(adapters)가 포함된 코드베이스는 진정으로 모호합니다. 컨텍스트(context)가 없다면, Claude는 그 모호함을 합리적인 기본값(defaults)으로 채우려 할 것이며, 그 기본값은 여러분 팀의 컨벤션과 일치하지 않을 것입니다.

구체적으로, 설정되지 않은 Claude는 다음과 같은 행동을 할 것입니다:

  • 리포지토리(repository)를 거치지 않고 서비스(service)에서 데이터베이스를 직접 호출함
  • ErrorMessages 상수를 사용하는 대신 에러 문자열을 하드코딩함
  • 새 파일을 잘못된 서비스에 배치함 (예: api-service에 있어야 할 예약 로직을 operator-service에 작성)
  • PermissionCodes를 사용하는 대신 user.role === 'admin'을 체크함
  • 구조화된 로거(structured logger) 대신 console.log를 사용함
  • src/ 경로 별칭(path alias) 대신 ../../common/utils를 작성함

이 문제가 존재하는 이유

이것은 Claude의 버그가 아닙니다. 모델에게 알려준 적 없는 팀 고유의 결정 사항을 추론하도록 요청했을 때 나타나는 예측 가능한 결과입니다. AI 어시스턴트는 세션 동안 읽어들인 파일만 볼 수 있습니다. 여러분의 팀이 왜 RolesGuard를 제거했는지, 왜 synchronize를 반드시 false로 유지해야 하는지, 혹은 두 서비스가 오직 HTTP 어댑터를 통해서만 통신하는지 등의 이유를 알 수 없습니다. 엔지니어들의 머릿속에만 존재하는 암묵적 지식(Tribal knowledge)이 바로 Claude에게 결여된 지식입니다.

해결책은 세 가지 메커니즘을 통해 해당 암묵적 지식을 버전 관리되는 컨텍스트(context)로 외부화하는 것이며, 각 메커니즘은 서로 다른 종류의 지식에 적합하도록 설계되었습니다:

메커니즘인코딩하는 내용Claude가 사용하는 시점
CLAUDE.md아키텍처, 소유권, 컨벤션 (conventions)매 세션마다 자동으로 로드됨
...

저장소 구조 (Repository Structure)

무엇인가를 설정하기 전에, 레이아웃을 먼저 확정해야 합니다. 잘 구조화된 NestJS 모노레포(monorepo)는 다음과 같은 형태를 띱니다:

my-backend/
├── .claude/                  # Claude가 원활하게 작동하는 데 필요한 모든 것
│   ├── CLAUDE.md             # 루트 레벨 지침 (항상 로드됨)
...

각 서비스는 자체적인 package.json, tsconfig.json, 그리고 빌드 결과물을 가진 독립적인 NestJS 앱입니다. 각 서비스 내부의 모든 기능 모듈(feature module)은 동일한 엄격한 3계층 구조를 따릅니다:

src/modules/booking/
├── booking.module.ts
├── controllers/    # HTTP 라우팅만 담당, 로직 없음
...

중요한 이유: 이 분리(separation)야말로 Claude가 반드시 준수해야 하는 핵심 사항입니다. 만약 Claude가 이 패턴을 모른다면 계층을 뒤섞어 버립니다. 즉, 서비스(services)가 DB에 직접 쿼리하거나, 컨트롤러(controllers)가 리포지토리(repositories)를 직접 호출하게 됩니다.

[시각 자료 제안: git-root의 .claude/ 디렉토리가 4개의 모든 서비스에 적용되는 다이어그램]

단계별 가이드: NestJS를 위한 Claude Code 설정하기

1단계 — Claude Code 설치

npm install -g @anthropic-ai/claude-code
claude   # 일회성 OAuth를 위해 브라우저를 엽니다

인증을 마친 후에는 어느 디렉토리에서든 claude를 실행할 수 있습니다. 각 개발자는 독립적으로 설치 및 인증을 수행하며, 공유되는 API 키는 없습니다.

모노레포 (Monorepo) 팁: Claude는 **git 루트 (git root)**에 있는 .claude/를 읽기 때문에, Claude를 호출하는 위치와 상관없이 지침이 적용됩니다. 특정 서비스에서 작업할 때는 해당 디렉토리로 cd (예: services/api-service/)하여 파일 검색 및 명령의 범위(scope)가 올바르게 설정되도록 하세요.

2단계 — CLAUDE.md 생성

CLAUDE.md는 여러분이 작성하게 될 가장 중요한 파일입니다. 이는 Claude가 매 세션 시작 시 읽는 브리핑 자료입니다. 첫 출근을 한 시니어 엔지니어를 위한 온보딩 문서라고 생각하세요. 다음 두 가지 수준에 파일을 배치합니다:

  1. 루트 .claude/CLAUDE.md — 서비스 소유권, 공유 컨벤션 (conventions), 요청 파이프라인 (request pipeline)
  2. 서비스별 services/{service}/CLAUDE.md — 해당 서비스에 특화된 모듈 패턴, 인증 (auth), 의존성 주입 (DI)

루트 CLAUDE.md

  • 문제점: Claude는 어떤 서비스가 새 파일의 소유자가 되어야 하는지 판단할 수 없어 추측하게 되며, 이로 인해 소비자 로직 (consumer logic)이 운영자 서비스 (operator service)에 배치되는 일이 발생합니다.
  • 해결책: 라우팅 결정 테이블과 명시적인 "절대 하지 말아야 할 것" 규칙을 추가합니다.
  • 결과: 첫 시도부터 파일이 올바른 서비스에 배치됩니다.
# CLAUDE.md

## Monorepo Structure
...

좋은 CLAUDE.md의 조건:

  • 디렉토리 목록보다는 결정 규칙을 작성하세요. "데이터가 경험이 무엇인지 설명한다면, operator-service에 위치한다"와 같은 규칙은 Claude가 사용자에게 묻지 않고도 모호함을 해결할 수 있게 합니다.
  • 응답 형태 (response shape)를 포함하세요. 그렇지 않으면 Claude가 모든 컨트롤러 (controller)에서 응답을 수동으로 래핑하여 일관성이 깨질 수 있습니다.
  • 하지 말아야 할 일을 나열하세요. "우리의 로거 (logger)를 사용하세요"보다 "console.log를 절대 사용하지 마세요"가 더 실행 가능한 지침입니다.
  • 삭제된 내용을 문서화하세요. RolesGuardsynchronize 플래그를 삭제했을 때는 그 이유를 명시해야 합니다. 그렇지 않으면 Claude가 자연스럽다고 판단하여 이를 다시 도입할 수 있습니다.

서비스 수준의 CLAUDE.md

각 서비스는 루트에 두기에는 너무 구체적인 세부 사항을 위해 자체 파일을 가집니다:

# api-service/CLAUDE.md

## Module Architecture — never mix layers
...

3단계 — 규칙(Rules) 추가

규칙(Rules)은 강력한 금지 사항입니다. 아키텍처를 설명하는 것이 아니라, AI가 생성하는 코드에 대한 ESLint 설정처럼 특정 패턴을 방지하는 역할을 합니다. 규칙은 .claude/rules/ 디렉토리에 Markdown 파일 형태로 저장됩니다.

CLAUDE.md 사용 용도
아키텍처, 모듈 구조
rules/ 사용 용도
강력한 금지 사항 (Hard prohibitions)

규칙: N+1 쿼리 방지

  • 문제점: N+1 쿼리는 발생하기 쉽고 코드 리뷰를 통과하여 슬쩍 넘어가는 경우가 많습니다.
  • 해결책: 올바른 벌크 쿼리 (Bulk-query) 패턴을 포함한 금지 규칙을 설정합니다.
  • 결과: Claude가 코드를 생성하는 시점에 벌크 쿼리를 작성하므로, 버그가 아예 생성되지 않습니다.

.claude/rules/database-queries.md

// 잘못된 예 — N개의 쿼리 발생
for (const b of bookings) {
  b.user = await this.userRepo.findOne(b.userId);
...

규칙: 권한 확인 (Permission Checks)

.claude/rules/permissions.md

// 잘못된 예
if (user.roles.includes('admin')) { ... }

...

이유: 역할(Role) 이름은 병합되거나, 분리되거나, 이름이 변경될 수 있으며, 이에 의존하는 확인 로직은 조용히(silently) 깨지게 됩니다. PermissionCodes는 역할 구조 재편성 시에도 유지되는 안정적인 상수입니다. src/common/constants/permissions.constant.ts에서 임포트하여 사용하세요.

규칙: 임포트 스타일 (Import Style)

.claude/rules/imports.md

// 잘못된 예
import { UserService } from "../../services/user.service";
// 올바른 예
...

src/ 별칭(Alias)은 tsconfig.json (baseUrl: "./") 및 Jest의 moduleNameMapper에 설정되어 있습니다. 모든 곳에서 이를 사용하세요.

정의할 가치가 있는 기타 규칙들

동일한 금지 패턴을 NestJS에서 자주 발생하는 많은 함정들에 적용할 수 있습니다. 별도의 파일로 만들 가치가 있는 몇 가지 규칙을 더 소개합니다:

  • 에러 처리 (Error handling) — 항상 ErrorMessages/ResponseCodeKeys 상수를 사용하여 에러를 던지고 NestJS 예외(exceptions)를 사용하세요. 문자열을 하드코딩하거나 가공되지 않은(raw) 에러 객체를 반환해서는 안 됩니다.
  • 로깅 (Logging) — 적절한 레벨에서 구조화된 logMessage() 헬퍼를 사용하세요. console.log를 절대 사용하지 마세요.
  • 트랜잭션 (Transactions) — 다중 쓰기(multi-write) 작업은 반드시 단일 EntityManager 트랜잭션 내에서 실행되어야 합니다. 절반만 커밋(half-commit)될 수 있는 독립적인 쓰기 작업을 실행하지 마세요.
  • DTO 검증 (DTO validation) — 모든 요청 DTO에는 class-validator 데코레이터가 필요합니다. ValidationPipe의 화이트리스트(whitelist) 기능은 데코레이터가 없는 모든 것을 삭제하므로, 데코레이터가 누락되면 데이터가 조용히 유실됩니다.
  • 엔티티 ↔ 마이그레이션 일치 (Entity ↔ migration parity) — 엔티티의 모든 변경 사항은 그에 상응하는 Flyway 마이그레이션이 필요합니다. synchronize 옵션은 false로 유지합니다.
  • Swagger 커버리지 (Swagger coverage) — 생성된 문서의 정확성을 유지하기 위해 모든 엔드포인트는 @ApiSpec과 타입이 지정된 응답 DTO를 포함해야 합니다.

4단계 — 스킬 구축 (Build Skills)

스킬(Skills)은 워크플로우, 코드 템플릿, 참조 자료를 하나로 묶은 프로젝트별 슬래시 명령어(slash commands)입니다. 이는 반복되는 다중 파일 작업을 단 하나의 명령어로 변환해 줍니다. 엔드포인트 구축, 마이그레이션 작성, 모듈 스캐폴딩(scaffolding), PR 리뷰와 같이 반복되는 다단계 작업에 대해 스킬을 작성하세요.

스킬 구조 (Skill Structure)

.claude/skills/api-development/
├── SKILL.md                    # 워크플로우, 트리거, 단계
├── assets/
...

SKILL.md 작성하기

# API 개발 스킬 (API Development Skill)

## 트리거 (Trigger)
...

에셋 템플릿 (Asset Template, 예시)

템플릿은 의사 코드(pseudocode)가 아닌, 실제 컴파일 가능한 코드여야 합니다. assets/controller-template.md 예시:

@ApiTags("bookings")
@Controller("bookings")
export class BookingController {
...

이 스킬을 사용하면 완전한 엔드포인트(컨트롤러 + 서비스 + 리포지토리 + DTO, 모듈에 연결됨)를 구축하는 데 약 20분이 아닌 3분 미만이 소요되며, 첫 시도부터 여러분의 컨벤션(conventions)과 일치하게 작성됩니다.

구축할 가치가 있는 기타 스킬들

팀 고유의 컨벤션이 포함된 반복적인 다단계 워크플로우는 모두 스킬 후보가 될 수 있습니다. 엔드포인트 스캐폴딩 외에도:

  • Migration generator (마이그레이션 생성기) — 버전 관리 및 명명 규칙(naming convention)에 맞춰 적절한 스키마 폴더에 Flyway 마이그레이션을 스캐폴딩(scaffold)하고, 그에 맞는 엔티티(entity) 변경 사항까지 생성합니다.
  • Module scaffolder (모듈 스캐폴더) — 연결이 완료되어 즉시 사용 가능한 전체 모듈 스켈레톤(module file, 3계층 구조, DI 토큰)을 생성합니다.
  • PR review (PR 리뷰) — 팀의 컨벤션에 따라 diff를 리뷰합니다: N+1 문제 체크, 권한(permission) 사용, 계층 경계(layer boundaries), 누락된 테스트 등을 확인합니다.
  • Test generator (테스트 생성기) — 특정 서비스에 대해 팀의 모킹(mocking) 및 픽스처(fixture) 패턴을 따르는 *.spec.ts 파일을 생성합니다.
  • Cross-service adapter (교차 서비스 어댑터) — 새로운 IMS 어댑터 메서드와 그에 대응하는 응답 인터페이스(response interface) 및 변환 헬퍼(transform helper)를 생성합니다.
  • Use-case / BDD docs (유스케이스 / BDD 문서) — 요구사항을 Given/When/Then 수락 기준(acceptance criteria)을 포함한 사용자 스토리(user stories)로 변환합니다.

Step 5 — 설정 및 권한 구성 (Configure Settings & Permissions)

.claude/settings.json은 권한 확인 프롬프트 없이 실행될 Bash 명령어를 제어합니다. 읽기 전용 및 안전한 테스트/린트(lint) 작업은 자유롭게 허용하되, 파괴적인 작업은 거부하십시오.

{
  "permissions": {
    "allow": [
...
파일적용 대상커밋 여부
.claude/settings.json팀 내 모든 구성원
.claude/settings.local.json본인 전용 (재정의용)아니요 (gitignored)

베스트 프랙티스 (Best Practices)

베스트 프랙티스 권고: .claude/ 디렉토리를 프로덕션 코드(production code)처럼 취급하십시오. 이는 여러분의 컨벤션을 모든 엔지니어와 모든 AI 세션에 전달합니다. 다른 소스 코드와 마찬가지로 리뷰하고, 버전 관리하며, 정리(prune)하십시오.

  • CLAUDE.md를 300행 미만으로 유지하십시오. 컨텍스트(Context)에는 비용이 따릅니다. 파일이 비대해지면 Claude가 읽어야 할 코드를 밀어내게 됩니다. 코드에서 유도할 수 있는 내용이라면 삭제하십시오.
  • 규칙을 가이드가 아닌 금지 사항으로 작성하십시오. "루프 내에서 DB를 절대 호출하지 마십시오"는 강제되지만, "벌크 쿼리(bulk queries)를 선호하십시오"는 압박 상황에서 무시됩니다.
  • 템플릿은 CLAUDE.md가 아닌 스킬(skills)에 넣으십시오. 템플릿은 모든 세션마다 로드되는 것이 아니라, 해당 스킬이 호출될 때만 로드되어야 합니다.
  • .claude/ 디렉토리를 git에 버전 관리하십시오. 이는 코드베이스의 일부입니다. 동일한 리뷰 과정을 거치고 동일한 이력을 가집니다. 새로운 규칙은 PR(Pull Request)을 통해 반영하고, 오래된 규칙은 삭제하십시오.
  • 의사결정 테이블(decision tables)을 적극적으로 활용하십시오. DTO 배치, 엔티티(entity) 위치, 서비스 경계와 같이 두 가지 합리적인 선택지가 존재하는 모든 곳에서 테이블은 산문(prose)보다 효과적입니다.

AI 자동 생성 콘텐츠

본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.

원문 바로가기
0

댓글

0