에이전트가 레거시 C/C++ 앞에서 헤매는 이유는 코드가 복잡해서가 아니라, 자기가 한 일이 맞는지 확인할 방법이 없어서다. 현대화의 첫 투자는 언어 전환이 아니라 검증 환경이다.

정도현 - 로보코 수석 컨설턴트


바이브 코딩 도입 컨설팅을 하다 보면 비슷한 하소연을 자주 듣는다. “우리 프로젝트는 너무 복잡해서 에이전트가 시킨 일을 제대로 못 합니다.” 처음에는 도메인이 특수하거나 프롬프트를 잘못 쓰는 문제라고 생각했다. 그런데 사례가 쌓이자 공통점이 보였다. 이런 이야기를 하는 팀의 프로젝트는 대부분 20년이 넘은 C/C++ 코드베이스 였다.

같은 팀이 새로 만든 Python 도구나 웹 관리 화면에서는 에이전트를 잘 쓰고 있었다. 따라서 문제는 팀의 역량이나 에이전트 자체보다 코드베이스 쪽에 있다고 보는 것이 자연스럽다. 이 글에서는 이런 레거시 프로젝트를 바이브 코딩으로 현대화하는 방법을 공개 사례와 연구를 바탕으로 정리한다. 근거 자료는 2026년 10월 15일 기준으로 조사한 공개 사례·논문·도구 문서이며, 각 수치는 발표 주체의 자체 보고라는 점을 함께 밝힌다.

이 글은 레거시 코드베이스 현대화를 다루는 2부작의 첫 번째 글이다. 1편은 C/C++로 작성된 레거시 애플리케이션을 다루고, 2편은 PHP로 작성된 레거시 웹 애플리케이션의 현대화 전략을 다룬다.

시리즈: 바이브 코딩으로 레거시 현대화하기

  1. 20년 된 C/C++ 애플리케이션 (이 글)
  2. 웹의 역사와 함께 쌓인 PHP

TL;DR

  • 에이전트가 레거시 C/C++에서 실패하는 주된 이유는 빌드를 재현할 수 없고, 포인터의 소유권이 코드에 드러나 있지 않으며, 변경을 검증할 테스트가 없기 때문이다(이는 내 컨설팅 경험에서 나온 해석이다).
  • 공개된 성공 사례(Google giflib, Wiz fastText, Rukuzu)는 모두 범위가 좁은 모듈을 강한 검증과 함께 교체했다. 수백만 줄을 한 번에 다른 언어로 번역한 사례가 아니다.
  • 권장하는 방식은 전면 재작성이 아니라 점진적 현대화다. 기존 코어는 Modern C++로 안정화하고, 경계가 좁고 메모리 결함이 잦은 모듈만 선택적으로 Rust 등으로 옮긴다.
  • 에이전트는 조사·변환·테스트·반복 수정을 맡고, 사람은 소유권 설계·호환성 판단·릴리스를 책임진다.
  • 첫 90일의 목표는 전체 전환이 아니라 대표 모듈 하나를 운영 전환하고, 같은 절차를 반복할 수 있음을 증명하는 것이다.

1. 에이전트는 왜 레거시 C/C++에서 헤매는가

코딩 에이전트는 코드를 읽고, 고치고, 빌드와 테스트를 돌려 결과를 확인하는 루프로 일한다. 이 루프의 마지막 단계인 “확인"이 막히면 에이전트는 자기가 고친 코드가 맞는지 알 수 없다. 내가 현장에서 본 20년 된 C/C++ 프로젝트에서는 이 루프가 여러 지점에서 끊겨 있었다.

첫째, 빌드를 재현할 수 없다. 특정 개발자의 PC에만 맞춰진 빌드 설정, 버전이 고정되지 않은 벤더 SDK, 수십 개의 전처리기 매크로와 조건부 컴파일이 얽혀 있다. 에이전트가 깨끗한 환경에서 빌드를 돌리지 못하면 자기가 만든 변경이 컴파일되는지조차 확인하지 못한다. 또한 같은 함수라도 어떤 매크로가 켜져 있느냐에 따라 실제로 컴파일되는 코드가 다르다. 실제 컴파일 옵션 없이 소스 파일만 읽은 에이전트는 존재하지 않는 코드 경로를 근거로 판단하게 된다.

둘째, 포인터의 소유권이 코드에 드러나 있지 않다. 오래된 C/C++ 코드에서 T* 하나는 “이 객체를 내가 해제해야 한다"는 뜻일 수도 있고, “잠시 빌려 쓴다"는 뜻일 수도 있다. 그 구분은 코드가 아니라 20년 전 작성자의 머릿속이나 사라진 위키에 있다. 에이전트가 grep으로 호출 위치를 찾아도, 콜백이 객체 파괴 후에 실행되는지, 컨테이너 재할당으로 참조가 무효화되는지는 알 수 없다. 그래서 에이전트의 수정은 그럴듯해 보이지만 해제 후 접근(use-after-free)이나 이중 해제를 새로 만들 수 있다.

셋째, 변경을 검증할 테스트가 없다. 테스트가 있더라도 소수의 정상 경로만 다루는 경우가 많다. 사람 개발자는 이 공백을 경험과 수동 테스트로 메워 왔지만, 에이전트에게는 그런 안전망이 없다. 결과적으로 에이전트의 생성 속도는 검증되지 않은 변경량 만 늘린다.

정리하면, 이 프로젝트들이 “너무 복잡해서” 에이전트가 실패한다는 진단은 절반만 맞다. 더 정확한 진단은 에이전트가 성공 여부를 판단할 수단이 없다는 것이다. 그래서 현대화의 첫 투자 대상은 언어 전환이 아니라 에이전트가 원본과 새 구현을 빌드하고, 같은 입력으로 비교할 수 있는 검증 환경 이 되어야 한다.

2. 공개 사례가 실제로 보여주는 것

에이전트로 C/C++를 현대화한 공개 사례는 아직 많지 않다. 그리고 숫자만 떼어 보면 과장되게 읽히기 쉽다. 아래 표는 주요 사례를 정리하되, 각 수치가 무엇을 입증하고 무엇을 입증하지 않는지 함께 적었다.

사례 원본과 대상 발표된 결과 이 결과가 입증하지 않는 것
Google giflib1 C 약 3천 줄 → Rust 3천만 개 이상 GIF 회귀 비교, 2억 회 이상 차등 퍼징, 성능 중립 대형 애플리케이션 일괄 번역의 가능성
Wiz fastText2 C++ 약 2만 줄 → Go 이틀 만에 5,434줄 Go, 보유한 모델 검증 테스트 100% 통과 모든 API·플랫폼·학습 기능의 동등성
Loxation Rukuzu3 Kuzu C++ 약 20만 줄 → Rust 보고 시점에 15개 crate, 2,700개 이상 테스트 20만 줄 전체의 기능 동등성 완료
Google ID 타입 변경4 32비트 → 64비트 ID 횡단 변경 변경 595건 중 74.45%를 LLM이 생성, 총 시간 약 50% 감소 추정 언어 전면 교체의 효과
Bun5 Zig → Rust (C++ 아님) 2주 미만에 100만 줄 이상 생성, 기존 CI 전부 통과 운영 동등성 (통과 후에도 회귀 19건 발견)

이 사례들에서 반복되는 패턴이 있다. Google은 SIMD나 어셈블리가 없는 작은 라이브러리를 골랐고, C ABI(바이너리 수준의 호출 규약)를 그대로 유지하는 교체 구현을 목표로 했다. 초기 변환 뒤에는 FFI(언어 간 호출 경계)의 메모리 관리가 불건전하다는 문제가 발견되었고, 전문가가 unsafe 코드를 직접 검토했다. Rukuzu는 기존 C++ 백엔드와 새 Rust 백엔드가 같은 추상화 인터페이스를 구현하게 만들어, 빌드 옵션으로 둘 중 하나를 고를 수 있게 했다. 두 사례 모두 교체 가능한 경계를 먼저 만들고, 그 경계 뒤에서 신구 구현을 비교 했다.

Bun 사례는 반대 방향의 교훈을 준다. 기존 CI 테스트를 모두 통과했는데도 운영에서 회귀 19건이 나왔다. API 환산 비용도 약 16만 5천 달러였다. 테스트 통과와 운영 동등성은 다르며, 대규모 병렬화는 비용도 크다는 점을 보여준다.

연구 쪽도 비슷하다. C→Rust 자동 변환 연구(ORBIT, ACToR, RustAssure)는 소규모 벤치마크에서 테스트 통과율 90% 안팎을 보고한다.6 그러나 이 수치는 평균 수백 줄 규모의 C 프로그램에서 나온 것이다. C++의 템플릿·상속·예외·매크로·정적 초기화·플러그인 ABI는 또 다른 난점이므로, 이 수치를 수백만 줄 C++ 제품의 자동 전환 성공률로 읽으면 안 된다. 또한 C2Rust 같은 변환기는 C 코드를 기능을 보존하는 unsafe Rust 로 옮기는 출발점일 뿐이다. Rust 파일이 생성되고 컴파일되었다는 사실만으로 메모리 안전성을 얻었다고 볼 수는 없다.7

3. 사례에서 뽑은 다섯 가지 원칙

언어 전환을 성과 지표로 삼지 않는다. 같은 C++로 남아 있어도 소유권이 명확해지고 회귀가 줄었다면 현대화에 성공한 것이다. 반대로 Rust로 옮긴 뒤 unsafe 블록이 넓어지고 FFI와 업스트림 유지비가 커졌다면 목표를 다시 평가해야 한다. 컨테이너화나 서비스 분리는 배포와 장애 범위에는 도움이 되지만, 포인터 결함 자체를 고치지는 않는다.

변환과 재설계를 분리한다. 첫 단계에서는 구조와 외부 동작을 최대한 유지하며 검증 가능한 전환을 만든다. 소유권·데이터 구조·동시성 모델의 개선은 그다음 단계에서 한다. 두 가지를 동시에 하면 출력이 달라졌을 때 번역 실수인지 설계 변경의 결과인지 구분할 수 없다. Anthropic의 Code Migration Kit도 구조를 보존하는 전환을 기본으로 한다.8

결정적 도구와 에이전트 판단을 나눈다. AST(구문 트리)로 정확히 찾을 수 있는 API 치환이나 문법 수정은 clang-tidy나 Clang LibTooling 같은 결정적 도구에 맡긴다. 에이전트는 변환 규칙 초안 작성, 예외 사례 처리, 실패 원인 분석, 테스트 보강을 맡는다. Google의 ID 변경 사례도 정적 분석과 코드 검색으로 변경 위치를 찾고, LLM이 문맥에 맞춰 수정하고, 자동 검증을 거쳐 사람이 수용하는 구조였다.4

테스트와 합격 기준을 구현 에이전트로부터 독립시킨다. 구현을 맡은 에이전트가 기대값·테스트·합격 기준을 바꿀 수 있으면, 에이전트는 테스트를 완화해서 통과시키는 쉬운 길을 택할 수 있다. 새 입력을 생성하는 검증 역할을 분리하고, 구현 과정에서 쓰지 않은 holdout 데이터를 따로 둔다.

저장소 전체 대신 필요한 근거를 공급한다. 수백만 줄을 프롬프트에 통째로 넣는 대신, 실제 빌드 설정·심벌 정의와 참조·모듈 계약·실패 로그·관련 테스트를 공급한다. 작업 중 발견한 규칙은 채팅 기억이 아니라 파일에 남긴다. 이 원칙은 다음 절에서 더 구체적으로 다룬다.

4. 에이전트가 읽을 수 있는 코드베이스 만들기

에이전트가 레거시를 잘 다루게 하려면, 먼저 에이전트가 사람 개발자와 같은 수준의 정보를 볼 수 있어야 한다. 출발점은 실제 컴파일 옵션의 복원이다. CMake 프로젝트라면 compile_commands.json을 생성하고, 다른 빌드 시스템이라면 Bear 같은 도구로 컴파일 명령을 수집한다. 이 파일이 있어야 clangd 같은 언어 서버가 매크로와 조건부 컴파일을 반영한 정의·참조·타입 정보를 정확히 돌려줄 수 있다. 다만 MSVC 전용 확장이나 크로스 컴파일 환경에서는 Clang 기반 분석이 실제 빌드와 다를 수 있으므로, 분석 결과가 어떤 빌드 변형에 해당하는지 표시해 두어야 한다.9

다음으로 에이전트를 위한 문서를 저장소 안에 둔다. 이 문서들은 사람 신입 개발자에게도 그대로 유용하다.

문서 내용 갱신 시점
AGENTS.md 등 운영 규칙 빌드·테스트 명령, 금지된 변경, 완료 조건 도구체인이나 검증 정책이 바뀔 때
모듈 계약 입출력, 오류, 소유권, 스레드, ABI 인터페이스가 바뀔 때
심벌 매핑 대장 원본 심벌과 신규 심벌의 대응, 진행 상태, 누락 작업 하나가 끝날 때마다
ADR(설계 결정 기록) 언어·경계·예외·성능 결정과 그 이유 설계를 결정할 때
결함 코퍼스 최소 재현 입력과 회귀 테스트 새 결함을 발견할 때

Rukuzu 사례가 이 방식을 잘 보여준다. 그 팀은 세션마다 진행 상황을 요약하고, 원본과 신규 심벌을 대조하고, 차이와 소유권 결정을 문서화한 다음 의존성 순서대로 구현했다. 각 단계에서 build·test·clippy를 실행했고, 작업 중 발견한 함정은 명령 문서에 계속 누적했다.3 이렇게 하면 에이전트의 컨텍스트가 초기화되어도 다음 세션이 같은 실수를 반복하지 않는다.

5. 핵심 난제: 포인터와 객체 수명

레거시 C/C++ 현대화에서 가장 어려운 일은 포인터의 소유권을 밝히는 것이다. 에이전트에게 “raw pointer를 스마트 포인터로 바꿔라"라고 일괄 지시하면 위험하다. 포인터마다 생성 지점, 소유자, 해제 함수, 별칭(같은 객체를 가리키는 다른 포인터), 저장 위치, 접근 스레드, 비동기 종료 조건을 먼저 확인해야 한다. 아래 표는 기존 패턴별 기본 전환 방향이다.

기존 패턴 기본 전환 주의할 점
단독 소유 T* 값 타입 또는 unique_ptr 기존 해제 경로와 별칭을 먼저 파악
실제 공동 소유 shared_ptr, 필요하면 weak_ptr 순환 참조와 데이터 레이스는 별도 문제
일시적 비소유 참조 참조 또는 비소유 포인터 원본 객체보다 오래 저장하지 못하게 계약
버퍼와 길이 vector, array, span span은 비소유이며 수명을 증명하지 않음
C SDK 핸들 전용 RAII 래퍼 반드시 짝이 맞는 해제 함수와 할당자 사용
비동기 this 캡처 취소, join, 약한 참조 구독 해제와 종료 순서를 설계

RAII는 자원을 객체 수명에 묶어 자동으로 반환하는 C++ 방식이다. 메모리뿐 아니라 파일·소켓·락·스레드·이벤트 구독에도 적용된다. 다만 Qt의 QObject 부모-자식 소유권, COM 참조 카운트, Unreal 리플렉션처럼 프레임워크마다 고유한 수명 규칙이 있다. 이런 코드는 표준 스마트 포인터로 일률 치환하면 안 된다.

그래서 나는 역할을 이렇게 나눈다. 에이전트는 호출·저장·해제·콜백 경로를 추적해 근거가 붙은 소유권 표를 만든다. 사람은 그 표를 검토해 최종 수명 설계를 승인한다. 확인하지 못한 수명은 “미확정"으로 남기고, 근거가 없으면 에이전트가 변경하지 않도록 지시문에 명시한다. 또한 malloc/free와 new/delete의 짝을 바꾸거나, Rust에서 할당한 메모리를 C의 free로 해제하는 변경은 명시적으로 금지한다.

완료 기준도 주의해야 한다. 성공의 기준은 raw pointer 개수의 감소가 아니라 소유권의 명확성, 결함 재현 테스트, 새 분석 경고의 부재다. 비소유 경계에 raw pointer가 남는 것은 허용할 수 있다.

6. 어떤 언어로 갈 것인가

모든 모듈을 같은 언어로 옮길 필요는 없다. 아래 표는 모듈 성격별 기본 선택과, 다른 선택이 필요한 조건이다.

판단 대상 기본 선택 다른 선택이 필요한 조건
기존 코어 Modern C++(C++17/20)와 RAII로 안정화 메모리 결함이 지속되고 경계를 분리할 수 있으면 Rust 검토
입력 파서와 프로토콜 좁은 인터페이스 뒤에서 Rust 파일럿 ABI 제약이 크거나 검증 자료가 부족하면 C/C++ 개선 먼저
업무 로직과 관리 기능 배포 환경에 맞는 관리형 언어(C#, Java, Go 등) 실시간성·메모리·호출 비용 제약이 강하면 네이티브 유지
수정하기 어려운 엔진 어댑터 또는 별도 프로세스로 격리 IPC 지연과 데이터 복사를 허용할 수 없으면 프로세스 내 경계

Rust를 택하는 경우에도 C와 C++의 경로는 다르다. C 중심 모듈은 C2Rust로 기능을 보존하는 unsafe Rust를 만든 뒤 단계적으로 안전한 코드로 바꿔 갈 수 있다. C++ 중심 모듈은 좁은 C ABI나 CXX 같은 연동 계층으로 경계를 만든 뒤, 인터페이스 계약에 맞춰 관용적인 Rust로 재구현하는 편이 현실적이다. 이때 borrow checker를 통과시키려고 Rc·Arc·Mutex를 기계적으로 늘리는 것은 피해야 한다. 이는 원래의 소유권 문제를 다른 형태로 숨길 뿐이다.

언어를 바꿀 때는 숫자 처리의 차이도 확인해야 한다. 정수 overflow, 부동소수점과 NaN, 엔디언, 인코딩, 로캘 동작은 언어마다 다르다. C/C++에서 우연히 성립하던 동작이나 정의되지 않은 동작(UB)은 대상 언어에서 달라질 수 있다.

7. 단계별 절차와 통과 조건

현대화는 아래 단계로 진행하고, 각 단계에는 다음 단계로 넘어가기 위한 증거를 요구한다. 각 단계의 이름은 이 글에서 정의한 것이다.

단계 사람과 에이전트의 작업 통과 조건
G0 재현 도구체인·의존성 고정, CI 빌드 깨끗한 환경에서 기준 버전의 빌드·테스트 로그
G1 이해 업무 흐름·심벌·소유권 분석 담당자가 확인한 계약과 불확실성 목록
G2 보호 특성화 테스트, 장애 재현, 비교 하네스 원본을 같은 입력으로 반복 실행 가능
G3 설계 경계·언어·오류·스레드 정책 결정 ADR, 인터페이스, 롤백 계획, 성능 예산
G4 변환 제한된 파일 범위에서 작은 변경 빌드·정적 분석·회귀 테스트 통과
G5 반증 차등 실행, 퍼징, 동시성·성능 검증 원인이 분류되지 않은 출력 차이 0건
G6 전환 shadow 실행, canary, 기능 플래그 승인된 관측 지표와 복구 절차 충족
G7 정착 구버전 제거, 문서, 업스트림 관리 새 구현의 소유자와 운영 절차 확정

에이전트가 실질적으로 속도를 내는 구간은 G1(조사), G2(테스트 작성), G4(변환), G5(반증 입력 생성)다. 반면 G0은 사람이 주도해야 하는 경우가 많다. 사내 SDK 라이선스, 빌드 서버 접근, 벤더 도구체인 확보는 에이전트가 해결할 수 없는 일이기 때문이다. 내 경험상 “에이전트가 일을 못 한다"고 말하는 팀의 상당수는 G0에서 멈춰 있다.

G5의 차등 실행은 같은 입력과 초기 상태에서 원본과 신규 구현을 실행하고, 결과를 정규화해 비교하는 방식이다. 비교 대상은 반환값뿐 아니라 파일·DB 변경, 오류 코드, 출력 순서, 종료 상태, 메모리 사용량까지 포함한다. 원본이 UB를 포함하고 있으면 원본의 실행 결과를 정답으로 볼 수 없다. 그래서 차이가 나오면 레거시 결함, 의도한 호환 동작, 신규 결함, 환경 차이 중 어느 것인지 분류하고, 업무 담당자와 기술 담당자가 판단한다. Google giflib 팀도 이 과정에서 기존 C 코드의 범위 초과 쓰기를 발견했다.1 원본의 메모리 오류까지 보존할 필요는 없으며, 발견한 결함은 의도적인 동작 변경으로 기록한다.

수정 반복에는 한도를 둔다. 나는 한 작업당 수리 3회 또는 정한 시간·비용 한도를 기본값으로 제안한다. 반복 실패, 새 unsafe 블록, ABI 변경, 원인을 모르는 출력 차이, 테스트 삭제가 나타나면 작업을 멈추고 진단 단계로 돌아간다. 완료 보고에는 기준 커밋, 변경한 심벌, 실행한 명령과 종료 코드, 테스트 결과를 포함하게 한다. 실행하지 않은 검사는 “미실행"으로 남기고, 에이전트의 자연어 주장만으로 통과 처리하지 않는다.

8. 첫 90일 계획과 멈춰야 할 때

아래는 대규모 프로젝트에서 첫 모듈을 전환하기 위한 90일 계획 예시다. 실제 일정은 빌드 복구 난이도, 테스트 공백, 지원 플랫폼 수에 따라 달라진다.

기간 작업 결과물
1-2주 빌드·의존성·장애 이력·테스트 진단 기준선과 후보 모듈 2-3개
3-4주 계약, 재현 코퍼스, 차등 하네스 구축 파일럿 1개 선정, 언어·경계 ADR
5-8주 모듈 개선·이식과 반복 검증 비교 가능한 신규 구현과 결함 대장
9-10주 holdout·퍼징·성능·운영 시험 G5 증거와 롤백 리허설
11-12주 shadow 실행, canary, 전환, 회고 운영 결과와 다음 모듈 확대 여부 결정

첫 파일럿 후보로는 파서, 변환기, 계산 라이브러리, 독립 CLI처럼 입력과 출력이 명확한 모듈이 적합하다. UI 프레임워크와 뒤섞인 코어, 여러 스레드가 공유하는 전역 객체 그래프, 드라이버나 인증 모듈은 두 번째 이후로 미룬다. 업무 가치(장애와 수정 빈도), 경계의 명확성, 검증 가능성이 높은 모듈을 고르고, 결합도와 전환 비용이 높은 모듈은 뒤로 미룬다. 점수만으로 정하지 말고, 후보 모듈의 빌드와 대표 입력을 실제로 실행해 가정을 확인한다.

에이전트 구성도 단순하게 시작한다. 처음에는 주력 에이전트 하나가 역할을 순차적으로 수행하고, 검증 단계에만 별도 세션이나 담당자를 둔다. 병렬 에이전트 수는 개발자 수가 아니라 빌드 자원과 리뷰 처리량에 맞춘다. 공개 사례의 수백 에이전트 구성을 시작 구성으로 복제하지 않는다.

다음 상태가 나타나면 에이전트 수를 늘리지 말고 재현·계약·분할 단계로 돌아가야 한다.

  • 빌드가 특정 개인의 환경에만 의존하거나, 원본을 실행할 수 없다.
  • 기대 동작을 결정할 사람이 없고, 테스트를 줄여야만 통과한다.
  • unsafe 블록이나 공유 가변 상태가 계속 늘어난다.
  • 공용 타입 변경 때문에 모든 작업이 서로 충돌한다.

대상 플랫폼·인증·벤더 지원이 목표 언어를 허용하지 않거나, 검증 환경 자체를 만들 수 없는 모듈도 있다. 이런 모듈은 언어 전환 대신 기존 C/C++ 개선, 프로세스 격리, 유지보수되는 대체 제품 채택으로 목표를 달성하는 편이 낫다.

마치며

“우리 코드는 너무 복잡해서 에이전트가 못 한다"는 말은 사실 “우리 코드는 너무 복잡해서 변경이 맞는지 확인할 방법이 없다"는 말에 가깝다. 이 문제는 에이전트가 등장하기 전부터 있었다. 사람 개발자들은 경험과 조심성으로 이 공백을 메워 왔을 뿐이다. 에이전트는 그 공백을 메울 경험이 없기 때문에 문제를 더 빨리, 더 분명하게 드러낸다.

그래서 레거시 C/C++ 현대화는 에이전트에게 번역을 맡기는 일이 아니라, 에이전트가 일할 수 있는 검증 환경을 만드는 일에서 시작해야 한다. 재현 가능한 빌드, 컴파일 문맥, 모듈 계약, 차등 비교 하네스가 갖춰지면 에이전트는 조사와 변환과 반증을 사람보다 훨씬 빠르게 반복한다. 이 구조는 이 블로그에서 다룬 소프트웨어 팩토리와 같은 방향이다.10 특히 증거로 거르는 팩토리에서 다룬 것처럼, 변경을 받아들이는 기준은 에이전트의 주장이 아니라 실행 증거여야 한다.11

이 글의 일정·임계값·구성은 공개 사례를 바탕으로 한 제안이다. 실제 적용 전에는 해당 저장소를 진단해서 조정해야 한다.

다음 글인 2편에서는 레거시 웹, 그중에서도 PHP로 작성된 웹 애플리케이션을 바이브 코딩으로 현대화하는 전략을 다룬다.


  1. Google Bug Hunters, “Scaling Memory Safety: AI Assisted Rewrites of C/C++ Dependencies to Rust” (2026-08-24): https://bughunters.google.com/blog/scaling-memory-safety ↩︎ ↩︎

  2. Anthropic, Wiz 고객 사례(고객 자체 보고): https://claude.com/customers/wiz ↩︎

  3. Loxation, “Rukuzu: Porting a 200,000 line codebase from C++ to Rust” (2026-03-04): https://www.loxation.com/blog/posts/article_porting_workflow/ ↩︎ ↩︎

  4. Ziftci et al., “Migrating Code At Scale With LLMs At Google” (FSE 2025): https://arxiv.org/html/2504.09691 , Google Research 블로그: https://research.google/blog/accelerating-code-migrations-with-ai/ ↩︎ ↩︎

  5. Anthropic, “How Anthropic runs large scale code migrations with Claude Code” (2026-07-16): https://claude.com/blog/ai-code-migration ↩︎

  6. ORBIT: https://arxiv.org/html/2604.12048 , ACToR: https://arxiv.org/html/2510.03879 , RustAssure: https://arxiv.org/html/2510.07604 . 세 연구는 서로 다른 단위와 데이터셋을 쓰므로 수치를 직접 비교할 수 없다. ↩︎

  7. C2Rust Manual: https://c2rust.com/manual/ ↩︎

  8. Anthropic, Code Migration Kit (reference code이며 적극 유지보수되지 않는다고 명시): https://github.com/anthropics/code-migration-kit-with-claude-code ↩︎

  9. clangd 설치와 컴파일 문맥: https://clangd.llvm.org/installation ↩︎

  10. 바이브 코딩을 넘어서 소프트웨어 팩토리로: https://roboco.io/posts/beyond-vibe-coding-software-factory/ ↩︎

  11. 오픈소스 프로젝트들로부터 배우는 소프트웨어 팩토리 모범사례 (3/4): https://roboco.io/posts/software-factory-evidence-before-fix/ ↩︎