리뷰 문제
AI 생성 코드에 대한 표준 조언은 “주의 깊게 리뷰하라”입니다.
이 조언은 정확하지만 규모에서는 쓸모없습니다.
AI 출력을 리뷰하는 개발자는 주의력이 높고, 해당 도메인에 익숙하고, 시간 압박이 없을 때 문제를 잡아냅니다. 그 외의 모든 조건에서 — 그리고 대부분의 조건이 그렇습니다 — 빠져나가는 것들이 생깁니다.
AI 리뷰어가 AI 생성 문제를 잡는 것은 더욱 신뢰하기 어렵습니다. 확률적 시스템에게 다른 확률적 시스템의 출력을 검증하라고 요청하는 것입니다. 실패 모드가 상관됩니다.
확장되는 유일한 패턴은 결정론적 enforcement입니다. 모든 커밋에서 검사되고, 피로나 낙관으로 우회할 수 없으며, 위반 시 빌드를 실패시키는 규칙입니다.
결정론적이란 무엇을 의미하는가
결정론적이란 누가 언제 실행하든 검사가 매번 같은 결과를 내는 것을 의미합니다.
- 린터 규칙은 결정론적입니다.
- 타입 검사는 결정론적입니다.
- 경계 import 제한은 결정론적입니다.
- contract test는 결정론적입니다.
- 사람 리뷰어의 집중 시간은 결정론적이지 않습니다.
- LLM의 평가는 결정론적이지 않습니다.
이 구분은 AI 생성 codebase에서 더 중요합니다. 생성된 코드의 양이 어떤 팀도 수동으로 리뷰할 수 있는 범위를 초과하기 때문입니다. 리뷰를 생성 속도에 비례해서 선형으로 늘릴 수는 없습니다. 결정론적 검사는 사소하게 확장할 수 있습니다.
가드레일 스택
AI 생성 codebase를 위한 가드레일 스택은 네 개의 계층으로 구성됩니다:
계층 1: 타입 시스템
타입 시스템이 첫 번째 가드레일입니다. 엄격한 타입은 어떤 리뷰 프로세스 — 사람이든 AI든 — 도 일관되게 잡지 못하는 부류의 오류를 잡아냅니다:
- Null 위반
- Interface 불일치
- 누락된 케이스 처리
- 잘못된 인자 타입
프로젝트가 TypeScript를 사용한다면 strict: true는 타협 불가입니다. 강한 타입 시스템이 없는 언어를 사용한다면 도구를 통해 추가하거나 다른 언어를 선택하십시오.
계층 2: 아키텍처 규칙
아키텍처 규칙은 경계 규율을 enforcement합니다:
- 어떤 화면도 다른 화면의 내부를 import하지 않는다.
- 도메인 로직은 인프라를 직접 import하지 않는다.
- 어떤 module도 의존성 접근을 위해 composition root를 우회하지 않는다.
- 벤더 SDK는 해당 어댑터 module 바깥에 나타나지 않는다.
Semgrep, ArchUnit, dependency-cruiser, 또는 커스텀 ESLint 규칙 같은 도구로 이것들을 정적으로 enforcement할 수 있습니다. 핵심은 CI에서 실행되고 빌드를 실패시킨다는 것입니다. 개발자가 무시할 수 있는 경고는 가드레일이 아닙니다.
계층 3: Contract Tests
Contract tests는 전체 시스템을 실행하지 않고 module이 자신의 interface를 충족하는지 검증합니다:
- 인증 어댑터가 인증 interface를 충족한다.
- 분석 어댑터가 분석 interface를 충족한다.
- 저장소 어댑터가 저장소 interface를 충족한다.
이것들은 빠르게 실행되고, 통합 경계를 테스트하며, AI 생성 코드가 타입 시그니처는 만족하지만 행동 contract를 위반하는 특정 실패 모드를 잡아냅니다.
계층 4: 결정론적 통합 검사
통합 수준에서 검사는 시스템 전체 속성을 검증합니다:
- composition root가 런타임 오류 없이 모든 의존성을 해결한다.
- 의존성 그래프에 순환이 없다.
- 모든 필수 환경 변수가 선언되어 있다.
- 구성이 런타임이 아닌 빌드 타임에 유효하다.
AI 생성 코드를 위한 Semgrep
Semgrep은 아키텍처 규칙을 코드로 표현하는 데 탁월하여 특별히 언급할 가치가 있습니다:
- 문자열 매칭이 아닌 AST 구조에 대한 패턴 매칭.
- 일반적인 린팅만이 아닌 프로젝트별 커스텀 규칙.
- 모든 커밋에서 실행할 수 있을 만큼 빠름.
- 경계 위반을 인코딩할 수 있을 만큼 표현력이 풍부함.
AI 생성을 광범위하게 사용하는 팀은 자신의 아키텍처 경계를 인코딩하는 Semgrep 규칙셋을 유지해야 합니다. AI가 경계를 위반하는 코드를 생성하면 병합 전에 빌드가 실패합니다. 사람의 주의력이 필요 없습니다.
이것은 AI 출력의 버그를 잡는 것이 아닙니다. 구조적 위반을 어떻게 생성되었든 병합 불가능하게 만드는 것입니다.
AI 코드 리뷰가 실제로 잡는 것
AI 코드 리뷰 도구가 유용한 영역:
- 스타일 일관성
- 문서 누락
- 명백한 로직 오류
- 대안적 접근 방식 제안
AI 코드 리뷰 도구가 신뢰할 수 없는 영역:
- 아키텍처 경계 위반
- module 간에 도입되는 미묘한 결합
- 행동 contract 위반
- 전체 시스템 추론이 필요한 보안 속성
실패 모드는 AI 리뷰가 가끔 놓치는 것이 아닙니다. 실패 모드는 예측 불가능하게 놓치며, 언제 놓쳤는지 알 수 없다는 것입니다. 그래서 결정론적 enforcement를 대체할 수 없고, 오직 보충할 수만 있습니다.
경제학
결정론적 가드레일은 실행 비용은 싸고 초기 구축 비용은 비쌉니다.
아키텍처 규칙을 작성하는 데 며칠이 걸립니다. Semgrep 구성을 유지하는 데 지속적인 관심이 필요합니다. Contract tests를 설정하려면 먼저 interface를 정의해야 합니다.
하지만 한 번 존재하면 거의 0에 가까운 한계 비용으로 모든 커밋에서 실행됩니다. 피로해지지 않습니다. 금요일 오후에 검사를 건너뛰지 않습니다. 연차나 사회적 압박에 양보하지 않습니다.
코드 볼륨이 높고 생성 속도가 빠른 AI 생성 codebase에서 이 경제적 프로파일은 결정적입니다. 대안 — AI 생성 속도에 맞춰 사람 리뷰를 확장하는 것 — 은 실행 불가능합니다.
AI-Native 아키텍처와의 연결
이 더 넓은 패턴에 대해 Stanford CS146S는 AI coding을 제대로 보고 있다 — 빠진 과목은 아키텍처다에서 다루었습니다. 결정론적 가드레일은 대체 가능한 아키텍처를 현실로 만드는 enforcement 메커니즘입니다.
가드레일 없이 아키텍처 경계는 희망 사항입니다. 가드레일과 함께 경계는 구조적입니다. “module 격리를 유지하려고 노력한다”와 “module 격리가 위반되면 빌드가 실패한다”의 차이는 AI 속도의 반복을 견디는 아키텍처와 그 아래에서 무너지는 아키텍처의 차이입니다.
현대 소프트웨어 개발자에게는 AI 도구 숙련도만 필요한 것이 아닙니다. AI 생성 코드를 속도를 유지하면서 구조적으로 안전하게 배포할 수 있게 만드는 가드레일 스택이 필요합니다.
FAQ
AI 생성 코드에 아키텍처 규칙을 enforcement하기 위한 최적의 도구는 무엇인가요?
Semgrep이 커스텀 아키텍처 규칙에 가장 유연한 선택입니다. AST 구조에 대한 패턴 매칭을 지원하고, CI에서 빠르게 실행되며, 프로젝트별 경계를 인코딩할 수 있습니다. JavaScript/TypeScript 프로젝트의 경우 dependency-cruiser와 커스텀 ESLint 규칙도 효과적입니다.
AI 코드 리뷰가 사람 코드 리뷰를 대체할 수 있나요?
아닙니다. AI 코드 리뷰는 스타일과 문서에 대해 사람 리뷰를 보충하지만, 아키텍처 경계 enforcement와 보안 속성에 대해서는 신뢰할 수 없습니다. 결정론적 검사(타입 시스템, 린터, 아키텍처 규칙, contract tests)가 주의력에 의존하는 리뷰를 대체할 수 있는 유일한 확장 가능한 방법입니다.
팀 속도를 늦추지 않고 가드레일을 설정하는 방법은?
타입 시스템부터 시작하십시오(strict 모드, 예외 없음). 위험도가 가장 높은 세 개의 경계에 대해 아키텍처 규칙을 추가하십시오. 외부 연동에 대한 contract tests를 추가하십시오. 각 계층은 설정에 하루, 실행에 몇 초가 걸립니다. 느려지는 것은 검사 자체가 아니라 위반에서 옵니다.
가드레일과 린터의 차이는 무엇인가요?
린터는 개선을 제안합니다. 가드레일은 빌드를 실패시킵니다. 차이는 enforcement입니다. AI 생성 codebase에서 제안은 규모에서 무시됩니다. 볼륨이 너무 높아서 일관된 수동 주의가 불가능하기 때문입니다. 빌드 실패만이 준수를 보장합니다.