AI 에이전트에게 코드를 수정해달라고 했는데 엉뚱한 파일을 건드리거나, 이미 있는 함수를 새로 만들거나, 빌드도 돌리지 않고 “완료”라고 보고한 경험이 있으신가요? 문제는 대부분 AI의 능력이 아니라 코드베이스 환경에 있습니다. AI가 일하기 좋은 환경을 하네스(Harness)라고 부르며, 이를 진단하고 개선하면 AI 활용 효율이 극적으로 달라집니다.
하네스는 말 그대로 “마구(馬具)” — AI라는 말(馬)이 제 힘을 발휘하도록 잘 맞춰진 환경입니다. 하네스가 부실한 코드베이스에서 AI는 지속적으로 맥락을 잃고, 불필요한 파일을 탐색하며, 잘못된 가정 위에 코드를 작성합니다. 반대로 잘 설계된 하네스에서는 같은 AI가 훨씬 빠르고 정확하게 동작합니다.
하네스 품질 3계층
하네스 품질은 세 가지 계층으로 나뉩니다. 아래로 갈수록 기초에 해당하며, 상위 계층은 하위 계층이 갖춰져야 의미가 있습니다.
- 발견 가능성(Discoverability): AI가 관련 파일과 함수를 빠르게 찾을 수 있는가
- 이해 가능성(Understandability): 코드의 의도와 제약을 AI가 파악할 수 있는가
- 실행 가능성(Executability): AI가 빌드·테스트·검증을 스스로 수행할 수 있는가
발견 가능성 원칙 (1~4)
원칙 1 — 진입점 명확화: README나 CLAUDE.md에 “이 프로젝트를 이해하려면 여기서 시작하라”는 지도가 있어야 합니다. AI는 수천 개의 파일 중 어디를 먼저 봐야 할지 모릅니다. 핵심 파일 목록과 의존성 흐름을 한 페이지로 정리하는 것만으로도 AI의 탐색 비용이 크게 줄어듭니다.
원칙 2 — 네이밍 일관성: 같은 개념에 다른 이름이 혼재하면 AI가 중복 구현합니다. user_id와 userId와 uid가 섞여 있는 코드베이스에서 AI는 혼란에 빠집니다. Hungarian notation처럼 일관된 네이밍 규칙을 프로젝트 전체에 적용하는 것이 핵심입니다. 실제로 MFC 프로젝트에서 멤버 변수에 m_b(BOOL), m_p(포인터), m_str(문자열) 접두사를 통일한 것만으로 AI의 변수 추론 오류가 크게 줄었습니다.
원칙 3 — 모듈 경계 명확화: 파일 하나가 500줄을 넘으면 AI의 컨텍스트 효율이 급격히 떨어집니다. 기능별로 파일을 분할하고(ClassSendProc.cpp, ClassReceiveProc.cpp), 헤더 파일에서 인터페이스를 먼저 확인할 수 있도록 구조화합니다. 헤더를 읽으면 구현을 읽지 않아도 공개 API를 파악할 수 있어야 합니다.
원칙 4 — 의존성 그래프 단순화: 순환 참조와 과도한 전역 상태는 AI가 “이 함수를 바꾸면 어디에 영향을 미치는가”를 추적하기 어렵게 만듭니다. 단방향 의존성과 명확한 계층 구조를 유지합니다.
이해 가능성 원칙 (5~8)
원칙 5 — 비자명한 제약만 주석화: “왜 이렇게 했는가”가 코드만 봐서는 알 수 없는 경우에만 주석을 작성합니다. // WM_DPICHANGED 재귀 방지 — SetWindowPos가 DPI 경계를 넘을 때 OS가 재발행처럼 숨겨진 제약을 명시하면 AI가 올바른 맥락에서 수정합니다. 자명한 코드에 “변수를 초기화한다”는 주석은 오히려 노이즈입니다.
원칙 6 — 에러 처리 일관성: Win32는 GetLastError(), COM은 HRESULT, 파일 I/O는 반환값이 혼재합니다. 에러 처리 패턴이 코드베이스 전체에 일관되게 적용되어야 AI가 새 코드를 올바른 방식으로 작성합니다. 일관성 없는 에러 처리는 AI가 가장 많이 실수하는 지점 중 하나입니다.
원칙 7 — 테스트가 명세 역할을 하는가: 잘 작성된 테스트는 AI에게 “이 함수는 이렇게 동작해야 한다”는 명세서 역할을 합니다. 테스트가 없으면 AI는 기존 동작을 유추해야 하고, 이 과정에서 회귀가 발생합니다. 특히 엣지케이스를 다루는 테스트는 AI가 수정 시 놓치기 쉬운 경계 조건을 명시합니다.
원칙 8 — 설정과 코드의 분리: 하드코딩된 상수, 경로, 환경 의존값이 코드 곳곳에 박혀 있으면 AI가 수정 범위를 파악하기 어렵습니다. .env, config 파일, 상수 모듈로 분리합니다.
실행 가능성 원칙 (9~12)
원칙 9 — 빌드 명령 단일화: AI가 빌드를 실행할 수 있어야 수정 결과를 스스로 검증할 수 있습니다. 복잡한 사전 설정 없이 msbuild Solution.sln 한 줄로 빌드되는 환경이 이상적입니다. 빌드가 안 되는 환경에서 AI는 “아마 될 것 같습니다”는 추측만 할 수 있습니다.
원칙 10 — 검증 계층 정의: Small(파일 1~3개): 빌드만 / Medium(4~10개): 빌드+관련 테스트 / Large(10개+): 전체 테스트+코드 리뷰처럼 작업 크기에 맞는 검증 기준을 문서화합니다. AI가 “빌드만 되면 됐어”라고 합리화하는 것을 방지하고, 적절한 수준의 검증을 강제합니다.
원칙 11 — Stop-the-Line 규칙: 무언가가 깨지는 순간 즉시 전진을 중단하고 재현→원인 특정→수정→검증 순서를 강제하는 규칙입니다. AI는 빠르게 진행하려는 경향이 있어 이 규칙이 없으면 버그 위에 버그를 쌓습니다. “재현 가능한 최소 케이스 확보 전 수정 금지”를 하네스 문서에 명시합니다.
원칙 12 — 합리화 차단 테이블: “단순 수정이라 검증 생략해도 돼”, “다음 커밋에서 고치면 되지” 같은 AI의 자기 합리화 패턴을 미리 정의하고 차단합니다. 이 테이블을 하네스 문서에 포함시키면 AI가 스스로 점검하게 됩니다.
하네스 진단 방법
코드베이스의 하네스 품질을 측정하는 가장 실용적인 방법은 신규 AI 에이전트를 투입해 실제 태스크를 수행시켜보는 것입니다. 에이전트가 자주 막히는 지점, 잘못된 파일을 수정하는 패턴, 빌드 없이 완료라고 보고하는 빈도가 하네스 취약 지점을 가리킵니다.
정량 지표로는 AI 수정 후 빌드 성공률, 회귀 발생 빈도, 태스크당 평균 컨텍스트 사용량을 추적합니다. 수치가 개선되면 하네스 품질이 올라간 것이고, 악화되면 새로 추가된 코드가 하네스를 약화시킨 신호입니다.
실행 체크리스트
- README 또는 CLAUDE.md에 프로젝트 진입점 지도를 작성한다
- 500줄 초과 파일을 기능별로 분할하고 헤더에서 인터페이스를 노출한다
- 네이밍 규칙을 코드베이스 전체에 통일한다
- 비자명한 제약과 우회책에만 주석을 달고 자명한 코드에는 달지 않는다
- 빌드 명령을 단일 명령어로 실행 가능하게 만든다
- Small/Medium/Large 검증 계층을 문서화하고 AI에게 주지시킨다