거대해진 모놀리스에서 AI 에이전트가 엉뚱한 코드를 건드리지 않게 만드는 디렉터리 정리법
TuBrief 편집팀
2026년 8월 21일
0
컴퓨터/소프트웨어원본 영상을 바탕으로 AI의 도움을 받아 작성했습니다. 원본 영상이 기준입니다.
커뮤니티의 다른 글
댓글 (0)
Log in to leave a comment
아직 작성된 글이 없습니다
원본 영상을 바탕으로 AI의 도움을 받아 작성했습니다. 원본 영상이 기준입니다.
Log in to leave a comment
아직 작성된 글이 없습니다
수십만 줄짜리 단일 저장소에 Claude Code나 Aider를 붙이면 엉뚱한 파일부터 읽기 시작합니다. 모델의 컨텍스트 창은 한정되어 있는데, 관련 없는 파일까지 긁어모으다 토큰 한도를 채우고 엉뚱한 코드를 수정해 버립니다.
이 문제는 프롬프트를 길게 쓴다고 해결되지 않습니다. 에이전트가 탐색하는 코드의 물리적 반경을 줄이고, 기계적으로 검증하는 규칙을 로컬에 심어야 합니다.
모놀리스 저장소에서 에이전트가 무한 탐색에 빠지는 지점은 대개 세 곳입니다. 잡다한 헬퍼 함수가 모인 공통 유틸 폴더(src/utils/), 비즈니스 로직이 얽힌 서비스 레이어(src/services/), 전역 모델 디렉터리(src/models/)입니다. 이 세 폴더가 서로를 참조하기 시작하면 에이전트는 코드 한 줄을 고치려고 수십 개 파일을 읽어 들입니다.
기술 계층별로 나뉜 폴더를 도메인 단위로 묶어 격리하면 탐색 범위가 줄어듭니다.
| 구분 | 레이어 중심 구조 | 도메인 분리 구조 | 에이전트 동작 변화 |
|---|---|---|---|
| 폴더 기준 | 기술 계층 분리 (/controllers, /services) |
도메인 분리 (/domains/order) |
필요한 파일만 한 폴더 안에서 탐색 |
| 의존성 연결 | 전역 엔티티 직접 임포트 | 도메인 인터페이스 경계로 통신 | 관련 없는 파일까지 연쇄 로딩하는 현상 차단 |
| 공통 로직 | 단일 src/utils/에 함수 혼재 |
도메인 전용 유틸과 공통 패키지로 분리 | 불필요한 전역 컨텍스트 오염 방지 |
작업 중인 서비스가 멈추지 않게 디렉터리를 옮기는 순서는 다음과 같습니다.
src/domains/{도메인명}/ 폴더로 옮기고 tsconfig.json의 경로 별칭을 갱신합니다.CLAUDE.md)을 넣습니다.자연어로 길게 적어둔 코딩 컨벤션은 에이전트가 쉽게 지나칩니다. 설정 파일 상단에 명확한 수치와 금지 사항을 배치해야 지침을 정확히 따릅니다.
# 프로젝트 제약 사항 (CLAUDE.md 상단 배치)
1. 보안 및 예외 처리
- NEVER allow raw SQL string concatenation. ALWAYS use parameterized queries with ORM.
- NEVER throw generic Exception or Error. ALWAYS throw domain-specific exceptions inheriting from BaseDomainException.
- ALWAYS enforce tenant_id filtering in all database queries under src/domains/.
2. 코드 구조 수치 제약
- Functions MUST NOT exceed 40 lines of code.
- Cyclomatic complexity MUST be kept under 8 per function.
- ALWAYS return Result<T, E> pattern for business layer operations instead of null.
설정 파일이 200줄을 넘어가면 뒤쪽 지시사항을 누락하는 일이 잦아집니다.
CLAUDE.md에는 빌드 명령과 전역 커밋 규칙만 200줄 이내로 유지합니다.src/domains/order/ 같은 하위 폴더 규칙은 해당 디렉터리 안의 전용 룰 파일로 분산합니다.CLAUDE.local.md에 작성하고 .gitignore에 등록해 충돌을 막습니다.에이전트가 만든 코드의 문법 오류나 회귀 버그는 커밋 시점에 자동으로 잡아야 합니다. Go 단일 바이너리로 작동하는 Lefthook을 쓰면 Node.js 기반 도구보다 가볍게 병렬 검사를 돌릴 수 있습니다.
루트에 lefthook.yml을 두고 가벼운 정적 검사와 무거운 테스트 단계를 분리합니다.
pre-commit:
parallel: true
commands:
linter:
glob: "*.{ts,tsx}"
run: npx eslint --fix {staged_files}
stage_fixed: true
formatter:
glob: "*.{ts,tsx,json,md}"
run: npx prettier --write {staged_files}
stage_fixed: true
security-scan:
run: gitleaks git --staged --no-banner
pre-push:
parallel: false
commands:
typecheck:
run: npx tsc --noEmit
unit-tests:
run: npm run test:unit -- --passWithNoTests
커밋 단계의 pre-commit은 스테이징된 파일만 10초 이내로 검사하고, 전체 타입 검사와 단위 테스트는 푸시 단계인 pre-push로 넘깁니다.
에이전트가 --no-verify 옵션을 써서 훅을 우회하지 못하도록 .claude/hooks/block-no-verify.mjs 인터셉터를 등록합니다.
import fs from 'fs';
const input = fs.readFileSync(0, 'utf8');
const parsed = JSON.parse(input);
if (parsed.tool_input?.command?.includes('--no-verify')) {
console.error("Policy Violation: `--no-verify` flag is strictly prohibited.");
process.exit(1);
}
process.exit(0);
훅이 실패하면 콘솔 에러 출력이 다음 프롬프트로 들어가 에이전트가 스스로 코드를 수정합니다.
에이전트가 빌드 결과물이나 락 파일을 읽기 시작하면 토큰이 빠르게 소진됩니다. 파일 탐색 범위를 닫아두어야 의도치 않은 비용 발생을 막을 수 있습니다.
프로젝트 루트에 .ignore 또는 .aiderignore를 만들고 대용량 아티팩트를 등록합니다.
node_modules/
dist/
build/
coverage/
*.min.js
*.svg
*.lock
package-lock.json
public/assets/
db/migrations/
터미널에서 실행할 때도 작업할 디렉터리를 명시해 전역 스캔을 차단합니다.
aider "Refactor Order validation logic" --path=src/domains/order/ --exclude=src/domains/order/__tests__/
코드를 수정하기 전 계획 모드로 변경 사항을 먼저 확인하고, 실패하는 단위 테스트를 작성한 뒤 통과하는 코드만 작성하게 만들면 에이전트의 작업 반경이 안전하게 유지됩니다.