Capstone 09 — 코드 마이그레이션 에이전트(Repo-Level Language / Runtime Upgrade)

Amazon의 MigrationBench(Java 8에서 17로)와 Google의 App Engine Py2-to-Py3 migrator는 2026년의 기준선을 세웠습니다. Moderne의 OpenRewrite는 대규모 결정적 AST(Abstract Syntax Tree; 추상 구문 트리) 재작성(rewrite)을 수행합니다. Grit은 codemod 스타일 DSL(Domain-Specific Language; 도메인 특화 언어)로 같은 문제를 겨냥합니다. 프로덕션 패턴은 둘을 결합합니다. 안전한 재작성을 위한 결정적 기반(deterministic substrate), 애매한 경우를 처리하는 에이전트 계층(agent layer), 브랜치별 빌드를 위한 샌드박스(sandbox), PR을 열기 전에 초록불로 바뀌는 테스트 하네스(test harness)를 함께 둡니다. 이 캡스톤은 실제 저장소 50개를 마이그레이션하고, 통과율과 실패 분류 체계(failure taxonomy)를 공개하는 것입니다.

유형: Capstone 언어: Python(에이전트), Java / Python(대상 저장소), TypeScript(대시보드) 선수 지식: Phase 5(NLP), Phase 7(transformers), Phase 11(LLM engineering), Phase 13(tools), Phase 14(agents), Phase 15(autonomous), Phase 17(infrastructure) 실습 Phase: P5 · P7 · P11 · P13 · P14 · P15 · P17 예상 시간: 30시간

문제

대규모 코드 마이그레이션(code migration)은 2026년 코딩 에이전트(coding agent)를 프로덕션에 적용하기 가장 깔끔한 사례 중 하나입니다. 정답 기준이 명확합니다. 마이그레이션 후 테스트 스위트(test suite)가 통과하는가를 보면 됩니다. 보상도 실제적입니다. Java 8 플릿(fleet) 마이그레이션은 인력 규모(headcount-scale)의 프로젝트가 될 수 있습니다. 벤치마크도 공개되어 있습니다. MigrationBench 50개 저장소 서브셋(subset)이 그 예입니다. Moderne의 OpenRewrite는 결정적인 부분을 처리합니다. 에이전트 계층은 OpenRewrite recipe가 처리하지 못하는 모든 것을 맡습니다. 애매한 재작성, 빌드 시스템 드리프트(build-system drift), 긴 꼬리 구문(long-tail syntax), 전이 의존성(transitive dependency) 깨짐 같은 문제입니다.

여기서는 Java 8 저장소 또는 Python 2 저장소를 입력으로 받아, CI(Continuous Integration; 지속적 통합)가 초록불로 통과하는 마이그레이션 브랜치를 만드는 에이전트를 구축합니다. 통과율, 테스트 커버리지 보존(test-coverage preservation), 저장소당 비용, 실패 분류 체계를 측정합니다. 결정적 도구만 사용하는 기준선(baseline)과 나란히 비교하면 에이전트의 실제 가치가 어디에 있는지 알 수 있습니다.

사전 테스트

2문제 · 이 강의를 시작하기 전에 얼마나 알고 있는지 확인해보세요

1.코드 마이그레이션 파이프라인이 LLM 에이전트 계층과 함께 결정적 기반(deterministic substrate, OpenRewrite/libcst)을 사용하는 이유는 무엇인가요?

2.코드 마이그레이션에서 테스트 스위트(test suite)가 핵심 성공 기준인 이유는 무엇인가요?

0/2 답변 완료

개념

파이프라인은 두 계층으로 구성됩니다. 결정적 기반(Deterministic substrate)은 Java에서는 OpenRewrite, Python에서는 libcst를 사용해 대량의 기계적 재작성을 안전하게 수행합니다. import, method signature, null-safety 수정, try-with-resources, deprecated API replacement 같은 작업이 여기에 속합니다. 이 계층은 빠르고, 감사 가능한(auditable) diff를 만듭니다. 에이전트 계층(Agent layer)은 OpenAI Agents SDK 또는 LangGraph를 Claude Opus 4.7과 GPT-5.4-Codex 위에 얹어 recipe가 처리하지 못하는 경우를 다룹니다. Maven/Gradle/pyproject 같은 빌드 파일 업그레이드, 전이 의존성 충돌, 테스트 플레이크(flake), 커스텀 어노테이션(annotation)이 대표적입니다.

각 저장소는 대상 런타임(target runtime)이 미리 설치된 Daytona 샌드박스를 하나씩 받습니다. 에이전트는 빌드를 실행하고, 실패를 분류하고, 수정하고, 다시 실행하는 루프를 돕니다. 하드 제한은 저장소당 30분, 저장소당 8달러, 에이전트 20턴입니다. 모든 테스트가 통과하고 커버리지 변화량이 음수가 아니면 브랜치가 PR(Pull Request; 풀 리퀘스트)로 열립니다. 그렇지 않으면 해당 저장소는 근거와 함께 실패 클래스(class) 아래에 기록됩니다.

산출물의 핵심은 실패 분류 체계입니다. 50개 저장소에서 무엇이 깨졌습니까? 전이 의존성입니까? 커스텀 어노테이션입니까? 빌드 도구 버전입니까? 마이그레이션과 무관한 테스트 플레이크입니까? 각 클래스에는 개수와 대표 diff가 붙습니다. 이후 recipe 작성자는 상위 3개 실패 원인을 겨냥해 개선할 수 있습니다.

아키텍처

target repo
      |
      v
OpenRewrite / libcst deterministic recipes
   (safe, fast, auditable, ~70-80% of fixes)
      |
      v
Daytona sandbox per branch
      |
      v
agent loop (Claude Opus 4.7 / GPT-5.4-Codex):
   - run build -> capture failures
   - classify failures (build, test, lint)
   - apply fix (patch or retry recipe)
   - rerun
   - budget: 30 min, $8, 20 turns
      |
      v
test + coverage delta gate
      |
      v (passed)
open PR
      |
      v (failed)
file under failure class + attach repro

스택

  • 결정적 기반(Deterministic substrate): Java는 OpenRewrite, Python은 libcst를 사용합니다.
  • 에이전트(Agent): Claude Opus 4.7 + GPT-5.4-Codex 위에서 OpenAI Agents SDK 또는 LangGraph를 사용합니다.
  • 샌드박스(Sandbox): 브랜치마다 Daytona devcontainer를 만들고, 대상 런타임(Java 17 / Python 3.12)을 미리 설치합니다.
  • 빌드 시스템(Build systems): Maven, Gradle, Python용 uv를 다룹니다.
  • 벤치마크(Benchmarks): Amazon MigrationBench의 50개 저장소 서브셋(Java 8 to 17)과 Google App Engine Py2-to-Py3 저장소를 사용합니다.
  • 테스트 하네스(Test harness): 병렬 러너(runner)를 사용하고, 커버리지는 Java에서는 Jacoco, Python에서는 coverage.py로 측정합니다.
  • 관측성(Observability): Langfuse와 저장소별 트레이스 번들(trace bundle)을 사용해 모든 diff 청크(chunk)를 기록합니다.
  • 대시보드(Dashboard): 실패 클래스별 개수와 대표 diff를 보여주는 failure-taxonomy 대시보드를 만듭니다.

직접 만들기

  1. Recipe 단계(Recipe pass). OpenRewrite(Java) 또는 libcst(Python) recipe를 먼저 실행합니다. 기계적인 마이그레이션의 70-80%를 여기서 처리합니다. 이 결과는 "recipe" 커밋으로 남깁니다.

  2. 빌드 시도(Build trial). Daytona 샌드박스에서 대상 런타임을 설치하고 빌드를 실행합니다. 초록불이면 테스트 단계로 넘어갑니다. 실패하면 에이전트에게 넘깁니다.

  3. 에이전트 루프(Agent loop). LangGraph에 run_build, read_file, edit_file, run_test, git_diff 도구를 붙입니다. 에이전트는 실패를 의존성(dep), 구문(syntax), 테스트(test), 빌드 도구(build-tool) 문제로 분류하고, 목적이 분명한 수정(targeted fix)을 적용합니다. 그리고 다시 실행합니다.

  4. 예산 제한(Budget caps). 저장소당 실제 경과 시간(wall-clock) 30분, 비용 8달러, 에이전트 20턴을 제한으로 둡니다. 제한을 넘으면 즉시 중단하고 현재 diff와 함께 budget_exhausted로 분류합니다.

  5. 테스트와 커버리지 게이트(Test + coverage gate). 빌드가 초록불로 바뀌면 테스트 스위트를 실행합니다. 기준 저장소(base repo)와 커버리지를 비교합니다. 커버리지가 2% 넘게 떨어지면 coverage_regression으로 기록합니다.

  6. PR 열기(PR open). 성공하면 브랜치를 push하고 PR을 엽니다. PR에는 diff, 적용된 recipe 요약, 에이전트가 작성한 커밋 요약을 포함합니다.

  7. 실패 분류 체계(Failure taxonomy). 실패한 저장소마다 클래스를 붙입니다. 예시는 dep_upgrade_required, build_tool_drift, custom_annotation, test_flake, syntax_edge_case, budget_exhausted입니다. 이를 대시보드로 만듭니다.

  8. 50개 저장소 실행(50-repo run). MigrationBench 서브셋 전체에 대해 실행합니다. 클래스별 통과율, 저장소당 비용, 커버리지 보존, 결정적 도구만 사용한 기준선 대비 결과를 보고합니다.

사용해보기

$ migrate legacy-java-service --target java17
[recipe]   27 rewrites applied (JUnit 4->5, HashMap initializer, try-with-resources)
[build]    FAIL: cannot find symbol sun.misc.BASE64Encoder
[agent]    turn 1 classify: removed_jdk_api
[agent]    turn 2 apply: sun.misc.BASE64Encoder -> java.util.Base64
[build]    OK
[tests]    412/412 passing; coverage 84.1% -> 84.3%
[pr]       opened #1841  cost=$3.20  turns=4

위 흐름에서 recipe는 JUnit 4에서 5로의 변경, HashMap 이니셜라이저(initializer), try-with-resources 같은 기계적 수정을 먼저 처리합니다. 빌드에서 sun.misc.BASE64Encoder가 더 이상 없다는 실패가 발생하면, 에이전트는 이를 제거된 JDK API(removed JDK API)로 분류하고 java.util.Base64로 바꿉니다. 빌드와 테스트가 통과하고 커버리지가 보존되면 PR을 엽니다.

산출물 만들기

outputs/skill-migration-agent.md가 제출 산출물입니다. 이 산출물은 저장소를 입력으로 받아 결정적 recipe를 실행한 뒤 에이전트 루프를 수행해 초록불인 마이그레이션 브랜치를 만들거나, 실패한 저장소를 분류 체계의 클래스 아래에 기록합니다.

가중치기준측정 방법
25MigrationBench 통과율50-repo subset pass@1
20테스트 커버리지 보존기준 저장소 대비 평균 커버리지 변화량
20마이그레이션된 저장소당 비용성공한 실행의 저장소당 비용
20에이전트 / 결정적 도구 통합OpenRewrite가 처리한 수정과 에이전트가 작성한 수정의 비율
15실패 분석 보고서(write-up)대표 사례가 포함된 분류 체계의 완성도
100

연습문제

  1. (쉬움) 에이전트 없이 OpenRewrite만 사용해 마이그레이션 파이프라인을 실행하세요. 전체 파이프라인과 통과율을 비교하세요. 에이전트가 있어야만 차이가 나는 사례를 식별하세요.

  2. (중간) "lint-clean" 검사를 구현하세요. 마이그레이션 후 Java는 spotless, Python은 ruff 같은 스타일 린터(style linter)를 실행합니다. 새로운 린트 오류(lint error)가 생기면 PR을 실패 처리합니다. 커버리지는 보존됐지만 스타일이 퇴행한 비율을 측정하세요.

  3. (중간) "minimal-diff" 최적화기(optimizer)를 추가하세요. 에이전트 브랜치가 테스트를 통과한 뒤, 두 번째 패스(pass)로 불필요한 변경을 줄입니다. diff 크기 감소량을 보고하세요.

  4. (어려움) 세 번째 마이그레이션으로 Node 18에서 Node 22로 확장하세요. 샌드박스 래핑(wrapping)은 재사용하고, recipe 계층은 커스텀 코드모드(custom codemod)로 바꾸세요.

  5. (어려움) 사용자 경험(UX) 지표로 첫 초록불 빌드까지 걸린 시간(time-to-first-green-build; TTFGB)을 측정하세요. 목표는 p50 기준 10분 미만입니다.

핵심 용어

용어흔한 설명실제 의미
결정적 기반(Deterministic substrate)"레시피 엔진(Recipe engine)"OpenRewrite / libcst처럼 안전성이 보장되는 선언적 AST 재작성 계층이다.
코드모드(Codemod)"코드를 고치는 프로그램"소스 코드를 기계적으로 변경하는 재작성 규칙이다.
빌드 드리프트(Build drift)"도구 버전 차이"주요 버전(major version) 사이에서 Maven / Gradle / uv 동작이 미묘하게 달라지는 문제다.
실패 클래스(Failure class)"분류 체계의 버킷(Taxonomy bucket)"저장소가 마이그레이션되지 못한 라벨링된 이유다. 의존성, 구문, 테스트, 빌드 도구, 예산 등이 포함된다.
커버리지 변화량(Coverage delta)"커버리지 보존"기준 브랜치에서 마이그레이션 브랜치로 이동했을 때 테스트 커버리지 %가 얼마나 바뀌었는지를 나타낸다.
에이전트 턴(Agent turn)"도구 호출 한 라운드"에이전트 루프에서 plan -> act -> observe가 한 번 도는 주기다.
예산 소진(Budget exhaustion)"한도에 도달함"저장소가 30분 / 8달러 / 20턴 제한을 다 쓰고도 통과하지 못한 상태다.

더 읽을거리

실습 코드

이 강의의 실습 코드 1개

main
Code

산출물

이 강의에서 생성된 프롬프트, 스킬, 코드 산출물 1개

migration-agent

Build a repo-level code migration agent that combines deterministic recipes with an agent fallback loop, passes MigrationBench, and publishes a failure taxonomy.

Skill

확인 문제

3문제 · 모두 맞추면 완료 표시가 가능합니다

1.레시피 패스 후 'sun.misc.BASE64Encoder를 찾을 수 없음' 오류로 저장소가 마이그레이션에 실패했습니다. 이것이 다른 레시피가 아닌 에이전트 계층을 필요로 하는 이유는 무엇인가요?

2.실패 분류 체계(failure taxonomy)는 마이그레이션에 실패한 저장소를 dep_upgrade_required, build_tool_drift, custom_annotation, test_flake, budget_exhausted 같은 클래스로 분류합니다. 이 분류 체계가 캡스톤의 가장 가치 있는 산출물인 이유는 무엇인가요?

3.저장소당 예산 상한은 벽시계 시간 30분, 8달러, 에이전트 20턴입니다. 테스트가 여전히 실패하는 상태에서 저장소가 예산 한도에 도달했습니다. 올바른 동작은 무엇인가요?

0/3 답변 완료

추가 문제 풀기

AI가 강의 내용을 바탕으로 새로운 문제를 생성합니다