Tips & Tricks (업데이트: 2026. 6. 2.)

Claude Code/Codex로 대규모 코드베이스를 길 잃지 않고 읽는 법

repo 지도, rg 검색, 의존성 추적, 진입점 분석, 위험 지도로 큰 코드베이스를 안전하게 읽는 절차.

Claude Code/Codex로 대규모 코드베이스를 길 잃지 않고 읽는 법

대규모 코드베이스를 처음 열었을 때 목표는 모든 파일을 이해하는 것이 아닙니다. 먼저 만들어야 할 것은 지도입니다. 시스템이 어디서 시작하는지, 어떤 폴더가 생성물인지, 어떤 파일이 인증·과금·데이터에 영향을 주는지, 어떤 경계는 담당자 확인 없이 건드리면 안 되는지 정리해야 합니다.

Claude Code와 Codex는 이런 탐색에 유용합니다. 다만 큰 파일, 긴 로그, 검색 결과 수백 줄을 그대로 대화에 넣으면 오히려 판단이 흐려집니다. 여기서 말하는 컨텍스트 비대화는 대화량은 늘어나지만 의사결정에 필요한 정보 밀도는 떨어지는 상태입니다.

이 글은 제가 프로젝트 인수인계, 레거시 점검, ClaudeCodeLab 다국어 글 개선에서 쓰는 절차를 명령어와 프롬프트로 정리한 것입니다. 도구 동작은 Claude Code의common workflows, CLI reference, memory, Codex의non-interactive mode, AGENTS.md 같은 공식 문서에 맞춥니다.

repo 지도부터 만든다

AI에게 “전체 프로젝트를 설명해줘”라고 바로 요청하지 말고, 먼저 터미널에서 외형을 줄입니다. rg는 ripgrep입니다. 빠르게 파일을 찾고 dist, build, coverage 같은 노이즈를 뺄 수 있습니다.

git status --short
git rev-parse --show-toplevel
git branch --show-current

rg --files \
  -g '!*node_modules*' \
  -g '!dist' \
  -g '!build' \
  -g '!coverage' \
  -g '!*.lock' \
  | sed 's#^[^/]*/##' \
  | sort \
  | uniq -c \
  | sort -nr \
  | head -40

find . -maxdepth 3 \( \
  -name package.json -o \
  -name pnpm-workspace.yaml -o \
  -name pyproject.toml -o \
  -name go.mod -o \
  -name Cargo.toml -o \
  -name Dockerfile -o \
  -name docker-compose.yml -o \
  -name AGENTS.md -o \
  -name CLAUDE.md \
\) -print

그다음 읽기 전용으로 지도를 요청합니다. Claude Code 공식 워크플로는 넓은 질문에서 시작해 좁혀 가는 방식을 안내합니다. Codex 공식 문서는 codex exec가 기본적으로 read-only sandbox에서 실행된다고 설명하므로, 첫 요약에 적합합니다.

codex exec "Read only. Summarize the repository map: apps, packages, entrypoints, test commands, generated folders, and files that define project rules. Do not edit files."

Claude Code에서는 비대화형 답변이 필요할 때 -p를 씁니다. CLI reference에서 print mode로 설명됩니다.

claude -p "
읽기 전용으로 이 코드베이스의 repo 지도를 만들어 주세요.
출력 순서는 다음과 같습니다.
1. apps, packages, services
2. 실행 진입점, 테스트 진입점, 빌드 진입점
3. 생성 폴더와 읽지 않아도 되는 폴더
4. AGENTS.md, CLAUDE.md, README, 설계 메모의 핵심
5. 다음에 읽을 10개 파일과 이유
편집이나 명령 실행은 제안만 하고 직접 수행하지 마세요.
"

검색은 단계별로 한다

텍스트가 검색됐다고 이해한 것은 아닙니다. 검색은 후보를 만드는 과정입니다. 구조, 도메인 용어, 참조, 설정, 이력의 다섯 층으로 나누면 누락이 줄어듭니다.

# 1. 진입점 후보
rg -n "createServer|listen\(|app\.use|router\.|main\(|bootstrap|hydrateRoot|createRoot" \
  src apps packages server web

# 2. 도메인 용어. 제품에 맞게 바꾸세요.
rg -n "Auth|Billing|Invoice|Notification|Search|FeatureFlag" \
  src apps packages test tests

# 3. 변경 후보 모듈의 호출 지점
rg -n "AuthService|useAuth|requireAuth|authMiddleware" \
  src apps packages test tests

# 4. 설정과 환경 변수
rg -n "process\.env|import\.meta\.env|PUBLIC_|DATABASE_URL|JWT|STRIPE|OPENAI|ANTHROPIC" \
  . -g '!node_modules' -g '!dist' -g '!build'

# 5. 이력: 왜 이런 설계가 되었는지
git log --oneline --decorate --date=short --max-count=30 -- src/auth packages/auth

검색 결과를 모두 붙여 넣지 말고, 작은 후보 집합을 전달해 분류하게 합니다.

당신은 코드베이스 탐색 리뷰어입니다.
아래 rg 결과를 구현 진입점, 호출자, 설정, 테스트, 노이즈로 분류하세요.
각 분류마다 다음에 읽을 파일을 최대 5개만 고르세요.
각 파일을 고른 이유를 한 줄로 쓰세요.
확실하지 않으면 추측하지 말고 “추가 검색 필요”라고 쓰세요.

가벼운 의존성 그래프를 만든다

정교한 분석 도구를 넣기 전에도 작은 Node 스크립트가 도움이 됩니다. 이 스크립트는 완전한 TypeScript 분석기가 아니라 로컬 상대 import만 봅니다. 그래도 어떤 파일을 바꾸면 어디까지 퍼지는지 대화의 출발점이 됩니다.

#!/usr/bin/env node
import { execFileSync } from "node:child_process";
import { readFileSync } from "node:fs";
import path from "node:path";

const target = process.argv[2]?.replace(/\\/g, "/");
if (!target) {
  console.error("Usage: node scripts/dependency-map.mjs src/path/to/file.ts");
  process.exit(1);
}

const tracked = execFileSync("git", ["ls-files"], { encoding: "utf8" })
  .split(/\r?\n/)
  .filter(Boolean)
  .map((file) => file.replace(/\\/g, "/"));

const trackedSet = new Set(tracked);
const sourceFiles = tracked.filter((file) => /\.(mjs|cjs|js|jsx|ts|tsx)$/.test(file));
const importPattern =
  /(?:from\s+["']([^"']+)["']|import\s*\(\s*["']([^"']+)["']\s*\)|require\s*\(\s*["']([^"']+)["']\s*\))/g;

function resolveLocalImport(specifier, fromFile) {
  if (!specifier.startsWith(".")) return null;
  const base = path.normalize(path.join(path.dirname(fromFile), specifier)).replace(/\\/g, "/");
  const candidates = [
    base,
    `${base}.ts`,
    `${base}.tsx`,
    `${base}.js`,
    `${base}.jsx`,
    `${base}/index.ts`,
    `${base}/index.tsx`,
    `${base}/index.js`,
  ];
  return candidates.find((candidate) => trackedSet.has(candidate)) ?? base;
}

const incoming = [];
for (const file of sourceFiles) {
  const source = readFileSync(file, "utf8");
  for (const match of source.matchAll(importPattern)) {
    const resolved = resolveLocalImport(match[1] || match[2] || match[3], file);
    if (resolved && (resolved === target || resolved.endsWith(`/${path.basename(target)}`))) {
      incoming.push(file);
    }
  }
}

console.log(`Target: ${target}`);
console.log("Direct importers:");
for (const file of incoming.sort()) console.log(`- ${file}`);

저장하고 실행합니다.

mkdir -p scripts
$EDITOR scripts/dependency-map.mjs
node scripts/dependency-map.mjs src/services/AuthService.ts

출력은 모호한 요약이 아니라 위험 평가로 바꿉니다.

다음 Direct importers를 보고 AuthService.ts 변경의 영향 범위를 평가하세요.
분류는 high / medium / low입니다.
high는 인증, 결제, 권한, 영속화, 공개 API 동작에 연결된 경우입니다.
각 분류마다 편집 전에 읽어야 할 테스트와 설정 파일도 제시하세요.

진입점에서 실행 흐름을 추적한다

파일 목록만으로는 런타임 흐름을 알 수 없습니다. 백엔드는 request, middleware, route, controller, service, repository, database 순서로 봅니다. 프론트엔드는 route, loader, state, API client, component, analytics 순서로 봅니다.

rg -n "middleware|loader|action|controller|handler|route|repository|service" \
  src apps packages \
  -g '*.ts' -g '*.tsx' -g '*.js' -g '*.jsx'

rg -n "fetch\(|axios|graphql|trpc|prisma|drizzle|sequelize|typeorm" \
  src apps packages \
  -g '*.ts' -g '*.tsx' -g '*.js' -g '*.jsx'

AI에게는 문단이 아니라 흐름 표를 요구합니다.

관점좋은 출력위험한 출력
진입점POST /login -> auth route -> AuthService.login“auth가 중요합니다”
상태Cookie, session, DB, cache 변경상태 변경 누락
실패에러 응답, 로그, 감사 이벤트, 재시도happy path만 설명
테스트기존 테스트 파일과 부족한 케이스“테스트 추가”만 말함
login 흐름을 진입점에서 영속화까지 추적하세요.
표의 열은 순서, 파일, 함수/클래스, 상태 변경, 실패 시 동작, 읽을 테스트입니다.
빈칸을 추측으로 채우지 말고, 모르면 다음에 읽을 파일을 쓰세요.

소유권과 위험 지도를 만든다

큰 저장소에서는 “실행되나?”보다 먼저 “누구의 경계인가?”를 봐야 합니다. 팀 경계, 데이터 경계, 릴리스 경계, 컴플라이언스 경계가 모두 포함됩니다.

find . -maxdepth 4 \( \
  -name CODEOWNERS -o \
  -name OWNERS -o \
  -name README.md -o \
  -name AGENTS.md -o \
  -name CLAUDE.md \
\) -print

rg -n "owner|maintainer|deprecated|legacy|do not edit|generated|migration|rollback|release" \
  . -g '!node_modules' -g '!dist' -g '!build'

Codex는 공식적으로AGENTS.md를 읽으므로 저장소 규칙을 여기에 두는 가치가 큽니다. Claude Code는CLAUDE.md와 memory로 다음 세션을 짧게 만들 수 있습니다. 더 자세한 예시는CLAUDE.md Best Practices를 참고하세요.

## Codebase map

### Entry points
- Web: apps/web/src/main.tsx
- API: services/api/src/server.ts
- Jobs: services/jobs/src/index.ts

### Ownership boundaries
- services/payments: owned by payments team; never change schema without migration review.
- packages/ui: shared design system; visual regression test required.
- legacy/: read-only unless the issue is production severity.

### High-risk files
- services/api/src/auth/AuthService.ts: login, session rotation, audit log.
- packages/db/schema.ts: migrations affect API and jobs.
- apps/web/src/routes/checkout.tsx: revenue path and analytics.

### Handoff notes
- Always start with rg search, then read top files.
- Prefer small diffs with tests.
- Do not paste large logs into the main conversation; summarize first.

읽기 전용 탐색 프롬프트를 쓴다

초기 탐색에서는 AI를 상담 모드로 두는 편이 좋습니다. 수정하기 전에 지도, 가설, 미확인점을 분리해야 하기 때문입니다.

읽기 전용으로 조사하세요. 파일 편집, 의존성 추가, 포맷 변경, 테스트 실행은 하지 마세요.

목표:
[기능명]의 구현 범위와 변경 위험을 이해한다.

출력:
1. 진입점 파일
2. 핵심 데이터 모델
3. 직접/간접 의존성
4. 소유권 경계
5. high / medium / low 위험 지도
6. 다음에 읽을 파일
7. 아직 확인되지 않은 가설

규칙:
추측은 반드시 “가설”이라고 표시하세요.
파일명과 근거를 쓰세요.
큰 파일 본문을 길게 인용하지 마세요.

Claude Code subagent는 많은 파일 읽기를 메인 대화 밖으로 빼는 데 유용합니다. 공식 문서는 subagent가 별도 컨텍스트에서 일하고 요약만 반환한다고 설명합니다. Codex의subagents도 코드베이스 탐색 같은 병렬 작업에 사용할 수 있다고 설명합니다. 다만 토큰을 쓰므로 범위를 좁혀야 합니다. 실전 패턴은Subagent Patterns에 정리했습니다.

3개의 읽기 전용 subagent를 실행하세요.
1. API 진입점과 인증 경계
2. DB schema와 migration 경계
3. UI route와 수익 경로

각 subagent는 최대 8개 파일만 읽고 최종 발견만 반환합니다.
마지막에 parent agent가 중복, 충돌, 미확인점을 통합하세요.

컨텍스트 비대화를 막는다

핵심은 증거와 판단을 분리하는 것입니다. 전체 파일, 긴 로그, 검색 결과 100개는 너무 무겁습니다. 먼저 줄이고, 그다음 판단하게 합니다.

OpenAI의compaction은 API 기능이지만 운영 원리는 동일합니다. 필요한 요약은 남기고 오래된 세부정보는 버립니다.

다음 작업자가 이어받을 수 있도록 지금까지의 조사를 300단어 이내로 압축하세요.
남길 것:
- 확인된 진입점
- high risk 파일
- 넘지 말아야 할 경계
- 미확인 가설
- 다음에 실행할 명령

버릴 것:
- 이미 틀린 가설
- 긴 로그
- 읽을 필요 없는 생성 파일

인수인계 메모는 개발과 콘텐츠 운영 모두에 중요합니다. 다국어 글이라면 어떤 locale 파일을 소유했는지, 앱 작업이라면 어느 진입점까지 추적했는지, 버그라면 어떤 가설이 실패했는지 남깁니다. 테스트 관점은Claude Code Testing Strategies, 권한은approval and sandbox guide도 함께 보세요.

세 가지 실제 사용 사례

첫째, SaaS 온보딩 인수인계입니다. 첫날에는 로그인, 결제, 관리자 화면, 알림만 지도화합니다. AuthServiceBillingService의 import 위치를 찾고 checkout route에서 DB까지 추적합니다. 아직 편집하지 않습니다. 산출물은 위험 지도와 읽기 순서입니다.

둘째, 레거시 마이그레이션입니다. legacy, deprecated, migration을 먼저 검색하고, 대체 코드보다 호환성 위험을 물어봅니다. DB migration, 공개 API, 배치 작업, cron은 롤백 비용이 크므로 특히 조심합니다.

셋째, ClaudeCodeLab 같은 콘텐츠와 수익화 사이트입니다. 글, CTA 컴포넌트, 내부 링크, 상품 페이지, 번역 파일이 다른 폴더에 있습니다. slug 단위로 소유권을 정하고, AI에게 해당 slug만 편집하게 하며 다른 글은 링크 확인에만 쓰게 합니다. 병렬 작업에서 충돌이 줄어듭니다.

자주 터지는 실패

  • README만 믿는다. 실제 진입점은 오래된 문서와 다를 수 있습니다.
  • 검색 결과를 실행 흐름으로 착각한다. 검색은 후보일 뿐입니다.
  • 소유권이 불명확한 상태에서 AI에게 편집을 맡긴다.
  • 생성 폴더, lockfile, coverage, dist를 대화에 넣는다.
  • subagent에게 너무 넓은 범위를 준다.
  • “안전하게 고쳐줘”라고만 말하고 위험 기준을 정의하지 않는다.

팀 도입과 수익 경로

대규모 코드베이스 탐색은 수익 경로에도 영향을 줍니다. checkout, 문의 폼, 유료 콘텐츠, analytics, 광고는 모두 소유권과 위험 경계 뒤에 있습니다. 편집 전에 repo 지도를 만들면 되돌림이 줄어듭니다.

팀에서 Claude Code나 Codex를 도입한다면 repo 지도 템플릿, AGENTS.md/CLAUDE.md, 리뷰 규칙, 읽기 전용 탐색 프롬프트부터 정리하세요. 개인은무료 cheat sheet로 시작할 수 있고, 실제 저장소 기준의 팀 교육은Claude Code training and consulting으로 이어갈 수 있습니다.

실제 검증 메모

이 절차를 쓰면 큰 파일을 처음부터 붙여 넣는 방식보다 이후 구현 프롬프트가 안정적이었습니다. 특히 repo 지도, 분류된 rg 결과, 작은 의존성 표, high / medium / low 위험 지도가 효과적이었습니다. 이 과정을 건너뛰면 생성 폴더, 오래된 테스트, 다른 팀 모듈까지 대화에 들어와 컨텍스트가 빠르게 흐려졌습니다. 게시 전에는 명령어, 프롬프트, Node 스크립트를 다시 읽고, 복사 가능한 형태와 기본 JavaScript 구문을 확인했습니다.

#claude-code #codex #codebase #repository-analysis #productivity
무료

무료 PDF: Claude Code 치트시트

이메일을 입력하면 명령, 리뷰 습관, 안전한 워크플로를 정리한 PDF를 받을 수 있습니다.

개인정보를 안전하게 관리하며 스팸을 보내지 않습니다.

Masa

작성자 소개

Masa

Claude Code 실무 워크플로와 팀 도입을 검증하는 엔지니어입니다.