


대규모 코드베이스에서 테스트를 거쳐 리뷰에 바로 낼 수 있는 변경을 만든다
AI 에이전트가 대규모 다국어 코드베이스를 수정할 때 사용한다. 프로젝트의 래퍼 명령으로 빌드하고, 테스트를 코드 옆에 두어 변경 전에는 실패하는지 확인하며, 리뷰 기준을 따르고, 직접 실행해 본 결과만 보고한다.
이 AI 규칙을 사용하려면
## 빌드와 테스트는 프로젝트의 래퍼 명령으로만 실행한다
대규모 프로젝트는 대체로 컴파일러와 테스트 러너를 하나의 프로젝트 명령으로 감싸서, 무언가를 실행하기 전에 재컴파일하고 로컬 변경사항을 반영한다. 항상 이 래퍼를 통해 빌드하고 실행해야 한다. 원본 테스트 러너나 이전에 컴파일된 바이너리를 직접 호출해서는 안 된다. 이는 변경사항이 반영되지 않은 오래된 산출물을 실행하는 것이므로, 테스트를 통과해도 아무것도 증명하지 못한다.
어떤 수정이 네이티브 재빌드를 건너뛸 수 있는지 파악해 둔다. 타입 선언이나 스스로 다시 로드되는 번들 스크립트처럼 컴파일되지 않는 입력만 건드리는 변경은 전체 빌드가 필요 없으며, 억지로 빌드를 돌리는 것은 시간 낭비일 뿐이다. 이런 경우에는 더 가벼운 대상 검사를 직접 실행한다.
전체 빌드에는 타임아웃을 걸지 않는다. 정상적인 콜드 빌드는 시간이 오래 걸릴 수 있으며, 도중에 강제 종료하면 혼란스럽고 오해를 부르는 실패가 발생한다. 래퍼가 뒤에 오는 인자를 빌드된 프로그램으로 전달하는 경우, 라우팅이 모호해지지 않도록 빌드 플래그를 그 실행 인자보다 앞에 둔다.
## 테스트는 수정하는 코드의 기존 테스트 파일에 추가한다
기본적으로 변경하는 코드에 대한 기존 테스트 파일에 테스트를 추가한다. 특정 영역의 동작에서 발생한 버그는 새 파일이 아니라 그 영역의 기존 테스트 파일에 속한다. 관련 테스트 옆에 두어야 쉽게 찾을 수 있고 설정이 중복되지 않는다.
저장소에 정해진 테스트 구조를 그대로 따른다. 하위 시스템별로 묶인 단위 테스트, 호환성 테스트, 플랫폼·웹 API 테스트, 커맨드라인 테스트, 엔드투엔드 통합 테스트는 각각 자기 영역에 위치한다. 이미 동등한 커버리지가 있는 곳에 테스트를 둔다.
특수 목적 폴더는 원래 용도에만 사용한다. 이슈 번호로 구분되는 리그레션 폴더는 진짜 리그레션, 즉 이전 릴리스에서는 정상 동작하다가 이후에 깨진 경우에만 쓰며, 그 식별자는 실제 이슈 번호여야지 임시 값이어서는 안 된다. 처음부터 제대로 동작한 적이 없었다면 그것은 리그레션이 아니므로, 테스트는 해당 모듈의 일반 파일에 넣는다.
## 실행할 때마다 같은 결과가 나오는 테스트를 작성한다
큰 출력값에 대해서는 깨지기 쉬운 동등성 비교보다 스냅샷 검증을 선호하고, 임시 경로 같은 부수적인 값 때문에 불필요하게 스냅샷이 바뀌지 않도록 정규화한다. 크래시나 처리되지 않은 예외 문자열이 없는지만 확인하는 테스트는 절대 작성하지 않는다. 이런 테스트는 파이프라인에서 절대 실패하지 않아 거짓된 안심을 준다.
비결정성의 원인을 전부 제거한다. 네트워크 포트를 하드코딩하지 말고, 임시 포트에 바인딩한 뒤 실제로 할당된 포트를 읽어온다. 무언가를 기다리기 위해 sleep이나 타이머를 쓰지 않는다. 테스트하는 대상은 시간의 경과가 아니라 조건이므로, 실제 조건을 기다려야 한다. 임시 디렉터리는 직접 만들지 말고 테스트 하네스가 제공하는 헬퍼를 사용하며, 테스트 안에서 파일 검색이나 텍스트 검색 같은 셸 유틸리티를 쓰는 대신 프로젝트 자체의 파일 API를 사용한다.
테스트가 프로세스를 실행할 때는 종료 코드보다 출력을 먼저 검증한다. 그래야 실패했을 때 단순한 비정상 종료 코드가 아니라 유용한 메시지를 얻을 수 있다.
## 새 테스트가 변경 전에는 실패하는지 확인하고, 실행한 결과만 보고한다
테스트를 거치지 않은 변경은 끝난 것이 아니다. 테스트를 실행하지 않았다면 코드가 동작하지 않는다고 가정한다. 테스트 실행은 선택적인 후속 작업이 아니라 작업을 마무리하는 과정의 일부다.
새로 작성한 테스트가 실제로 변경사항을 검증하는지 증명한다. 수정 전 기준 코드에서는 실패하고, 자신의 빌드에서는 통과해야 한다. 변경 전에도 이미 통과하는 테스트는 아무것도 증명하지 못하므로, 신뢰하기 전에 양쪽 방향을 모두 확인한다.
모든 커밋 메시지, 리뷰 답변, 상태 보고에서 겸손하고 정직해야 한다. 실제로 이룬 성과나 실제로 동작하는 부분을 과장해서는 안 된다. 자신이 직접 실행해서 관찰한 결과만 보고하고, 아직 검증되지 않았거나 끝나지 않은 부분은 작업이 완료된 것처럼 암시하지 말고 명확히 밝힌다.
## 수정하기 전에 코드베이스의 구조를 파악한다
수정에 앞서 코드베이스가 어떻게 구성되어 있는지 파악한다. 어느 계층이 어떤 책임을 맡고 있는지, 공용 유틸리티는 어디에 있는지, 어떤 파일이 자동 생성된 것이고 어떤 파일이 직접 작성된 것인지 알아둔다. 자동 생성 파일은 소스 정의로부터 만들어지므로 소스를 수정하고 빌드가 다시 생성하도록 해야 한다. 생성된 결과물을 직접 수정하면 다음 빌드에서 덮어써지므로 절대 하지 않는다.
자신이 건드리는 동작이 파싱, 모듈 해석, 런타임 API, 네트워킹, 스토리지, 번들러, 패키지 매니저 중 어디에 속하는지 확인해서, 변경사항과 그 테스트가 모두 올바른 위치에 자리 잡도록 한다.
기존 코드 스타일을 따른다. 다른 프로젝트의 관례를 그대로 들여오지 말고, 주변 파일에서 이미 자리 잡은 패턴을 확인해 맞춘다. 수동 해제보다는 스코프 기반 자동 정리 같은 해당 언어 고유의 자원 관리 관용구를 우선한다. 예를 들어 리셋 시 소멸자가 호출되지 않는 영역에 할당된 값처럼 문서화된 예외 상황은 반드시 먼저 명시적으로 해제해야 한다는 점을 존중한다.
## 리뷰 기준을 읽고 프로젝트의 필수 규칙을 따른다
성숙한 프로젝트는 리뷰어가 머지를 막는 기준을 문서화된 규칙집으로 정리해 둔다. 명확하지 않은 선택을 하는 코드를 작성하기 전에 이 규칙집을 읽고, 호환성 레이어, 사용자 대상 API 설계, 성능이 민감한 핫 패스, 플랫폼별 조건부 코드, 의존성·벤더링 변경, 문서와 타입 선언 등 자신이 다루는 영역에 해당하는 상황별 가이드가 있다면 그 작업을 하기 전에 미리 읽어둔다.
자동화된 파이프라인이 강제하므로 프로젝트의 필수 규칙을 정확히 지킨다. 정해진 브랜치명 접두사를 사용하고, 코드 주석은 짧게 유지하며 더 깊은 설명은 문서로 옮기되 명시적으로 요청받았을 때만 작성한다. 파일 작업에는 절대 경로를 사용한다. 플랫폼별 변경을 할 때는 지원하는 모든 타깃에 대해 컴파일해야 한다. 조건부로 컴파일되는 코드는 해당 타깃이 실제로 빌드되지 않으면 타입 검사가 이루어지지 않기 때문이다.
## 빌드가 실패하면 프로젝트의 진단 도구를 쓰고, 잘못된 정보를 주면 도구를 고친다
자동화된 빌드가 실패하면, 상황을 직접 손으로 재구성하지 말고 실패한 테스트를 보여주고 작업 상태를 요약하며 전체 로그를 저장해 주는 프로젝트 전용 진단 명령을 사용한다. 이런 도구는 새로 발생한 실패와 다른 곳에서도 이미 실패하고 있는 것을 이미 구분해 주며, 일상적인 노이즈도 걸러준다.
변경사항에 대한 피드백을 확인할 때는 전체 그림을 보여주는 명령을 사용한다. 일반적인 목록 조회는 리뷰 요약이나 라인 단위 코멘트를 조용히 빠뜨리는 경우가 많으므로, 최상위 코멘트·리뷰·인라인 코멘트를 하나의 시간순 정리된 화면에 함께 보여주는 도구를 우선한다.
헬퍼의 출력이 잘못 파싱된 주석이나 상류에서 형태가 바뀐 필드처럼 이상해 보인다면, 하류에서 우회하지 말고 그 표시 로직 자체를 고친다. 헬퍼는 기반 도구 위에 얹힌 얇은 레이어이므로, 이를 고쳐두면 이후의 모든 실행이 올바르게 유지된다.
