1. AI 코드 리뷰 토론 - Lobsters
읽은 날 : 2026-09-15
1.1. 먼저 알아둘 개념
- 변경 예산(Change Budget) : 에이전트나 개발자가 한 번에 제출 가능한 변경 크기와 범위의 한계
- 판정 기준(Test Oracle) : 실행 결과가 올바른지 결정하는 규칙, 명세, 승인 사례, 참조 구현 또는 계산 과정
1.2. 내용
1.2.1. 요약
- 지속 가능한 AI 개발의 4가지 단계가 있음
- 검토 가능성 : 사람이 읽을 수 있는 의미 단위인가?
- 독립 검증 : 구현과 분리된 정답 기준이 있는가?
- 인간의 이해 : 목적/위험/복구를 설명할 사람이 있는가?
- 의도 추적성 : 결정 결과와 이유를 다시 연결할 수 있는가?
- AI 사용을 금지하거나 모든 코드를 한 줄씩 읽으라고 하는게 아님
- 사람이 읽고 유지할 코드는 검토 가능한 크기로 제한
- 테스트 통과보단 테스트가 어떤 오류를 구분하는지 확인
- 자동화가 확인할 것과 사람이 책임지는 판단을 구분
- 구현을 직접 유지할지, 명세와 평가를 기준으로 재생성할지 미리 합의 해야한다.
1.2.2. 본문 시작
- 글쓴이가 먼저 AI 활용 후 리뷰에 대한 의문점을 던짐
- 자신의 PR이 평균 6,000줄의 규모가 되어버림
- AI에게 리뷰를 맡긴다 해도 장황하고 따라가기 어려운 결과가 돌아온다고 호소
- 이에 대한 댓글의 반응은 **"6,000줄 변경은 AI 작성 여부를 떠나 리뷰할 수 없는 수준이다."**라는 것
- 리뷰 불가능한 변경을 되돌려 보낼 수 있는 기준과 권한을 가져야 한다.
- 이제 코드 생성은 짧은 시간에 수천 줄이 가능하지만, 리뷰어들의 읽기 속도와 집중력은 변하지 않았음
- 팀의 실제 처리량 = MIN(코드 생성, 검증/리뷰)
- 코드 생성만을 늘린다고 해서 처리량이 늘어나는 것이 아니라, 리뷰 대기열이 길어지게 된다.
- 그렇다고 실제 검토를 생략하면, 아무도 변경된 의미를 설명하지 못하게 된다.
1.2.3. 정말 시간이 절약된걸까?
- 코드 생성 시간만 측정한다면 AI의 생산성이 과대평가되기 쉽다.
- 팀의 관점에선 사람이 책임질 수 있게 정리된 변경량이 중요한 지표다.
- 좋은 작성자는 리뷰어에게 원시 AI 출력물을 넘기지 않는다.
- 변경을 줄이고, 스스로 검토하고, 테스트를 수행하며 사람이 판단해야 할 부분을 표시 해야한다.
1.2.4. 작은 PR의 의미
- 단순히 줄 수가 적은 PR이 작은 PR이 아니다.
- 다음과 같은 조건을 만족하는 것을 작은 PR로 하는것을 제안
- 하나의 의미 있는 목적을 가져아한다.
- 변경 전후의 차이를 독립적으로 설명해야한다.
- 테스트와 롤백이 단위에 맞춰진다.
- 더 큰 설계 안에서 어디 위치하는지 알 수 있다.
- 줄 수만 줄이기 위해 설계를 임의로 잘게 자르면 각 PR은 작아지더라도 전체 상태를 이해하기 어려워 진다.
- 반대로 파일 이동이나 기계적인 VO, DTO같은 생성 코드라면 줄 수가 커도 의미적 위험은 낮을 수 있다.
1.2.5. Change Budget
- 에이전트 지침에 변경에 대한 기준을 넣어야한다.
- 이를 예산으로 표현했다.
1.3. 흥미로운 점
- 1.2.4. 작은 PR의 의미
- 실제로 보험 업무도 이런 개발에 분류가 가능하다.
- 보험료 계산의 경우 산식, 반올림등의 우선 확인 내용이 필요하다.
- 계약 상태가 바뀌는 경우엔 이력 정합성등의 우선 확인 내용이 필요하다.
- SQL 변경은 실행 계획, 영향 건수등의 우선 확인 내용이 필요하다.
- 기계적 이름 변경은 기능 변경과 분리, 컴파일/테스트가 정상적으로 되었는지 여부가 필요하다.
- 1.2.5. Change Budget
- 실제 지침 예시
- 지침에서의
5개 파일과400줄은 시작점이다. 실제로 개발하며 알맞은 지점을 찾아야한다.- 중요한 것은 에이전트가 한계에 도달한 뒤 몰래 계속해서 진행하지 못하게 해야한다.
- 계획단계로 되돌아가도록 해야한다.
### Reviewability Rules
- 한 작업에서는 하나의 의미 있는 변경만 수행한다.
- 리팩터링, 기능 변경, DB 스키마 변경, 기계적 변경을 섞지 않는다.
- 예상 변경이 production file 5개 또는 non-generated diff 400줄을
초과하면 구현을 중단하고 분할 계획을 먼저 제시한다.
- 신규 dependency, 외부 서비스, DB schema 변경은 명시적 승인 없이 수행하지 않는다.
- 줄 수를 맞추기 위해 논리적으로 결합된 변경을 임의로 분할하지 않는다.
- 각 변경 후 목적, non-goal, 업무 불변 조건, 위험, 롤백,
실행한 검증, 권장 리뷰 순서를 제공한다.
2. gksdud - 씹힘 없고 빠릿빠릿한 Mac 한영 전환
읽은 날 : 2026-09-19
2.1. 먼저 알아둘 개념
- 맥북의 한영 전환은
Ctrl+Space와CapsLock이 있음- 물론
Karabiner와 같은 애플리케이션으로 별도 지정이 가능
- 물론
Ctrl+Space의 경우엔 두 손가락을 쓰다보니 장시간 작업시 손에 피로가 있음CapsLcok의 경우엔 짧게 누르면 한영전환, 길게 누르면 대소문자 전환이 되어 인식이 잘못될 때가 있고, 지연이 있음
2.2. 내용
Karabiner나 별도 설정 없이 한영전환을 빠르게 도와줌- 딜레이, 키 씹힘을 개선하여 빠른 전환이 가능함
Capslock버튼이 아닌 별도 설정없이우측 command키를 사용하여 한영을 빠르게 전환 가능- 물론 이를 의도적으로 사용하고 있었던 이들을 위해 한영키를 길게 눌러 대소문자 전환을 사용가능하게도 함
- 제작자는 이 동작에 딜레이가 없다고 함
- 또한 아래 사진과 같이
누를 때 전환기능이 있어, 기존에 키보드에서 손을 뗄떼 전환되던때보다 더 빠르게 전환이 가능
2.3. 흥미로운 점
- 일단 핸드폰도 안드로이드로 바꾸고, 회사 환경도 윈도우인 관계로 우측 커맨드로 한영키 바꾸는걸 진지하게 고려중이었는데 마침 발견함
- 일단 하루동안 사용하는데 기존
Capslock으로 한영전환 할 때 보다 훨씬 쾌적해짐 - 매우 만족하고 쓰고 있으며, 주변 맥북 사용자들에게 많이들 권할듯
3. Dan Luu - 에이전트가 테스트/검증 기술을 얼마나 잘 사용하나요?
읽은 날 : 2026-09-19
3.1. 먼저 알아둘 개념
- 상단의
1. AI 코드 리뷰 토론 - Lobsters를 미리 읽으면 좋다. - TDD : 코드를 짜기 전에 테스트부터 만드는 개발 방식
- 퍼징(Fuzzing) : 프로그램에 수많은 이상하거나 다양한 입력값을 자동으로 넣어보면서 터지는지 확인하는 테스트
- Property-based Testing : 특정 입력 하나가 아니라 **“모든 입력에서 이런 규칙은 지켜져야 한다”**를 검사하는 방식
- Hegel : 이 실험에서 사용한 Property-based Testing용 도구/스킬. Hypothesis 계열의 테스트 라이브러리
- 상태 공간(State Space) : 프로그램이 가질 수 있는 가능한 모든 상황의 집합
- 구조화된 무작위 입력 : 그냥 아무 값이나 던지는 게 아니라, 실제로 의미 있는 형태를 가진 데이터를 랜덤으로 만드는 것
3.2. 내용
3.2.1. AI 테스트/감사로 리뷰 병목 해결이 가능할까?
- 해당 글의 에이전트 테스트는 위 질문에 대한 실험이다.
- Rust, Zstd를 구현하는 평가에서 Codex(GPT-5.6 Sol)에 26가지 조건을 주었다.
- 코딩 에이전트들에게 테스트 기법에 대한 이름만 주면, 그 기법이 결함을 찾는 원리까지 올바르게 수행하는가?
3.2.2. 테스트 기법 이름과, 결함 탐지의 원리
- 에이전트는 알려주는 기법에 대한 외형 자체는 만들 수 있었다.
- TDD를 지시하면 실제 테스트 수와 테스트-코드 반복이 늘어난다.
- Quick-Check를 지시하면 라이브를 사용하여 무작위 입력의 만들었다.
- 형식 검증을 지시하면 증명 파일을 만든다.
- 차등 테스트를 지시하면 구현을 두 가지를 만든 것처럼 보이는 구조를 만든다.
- 하지만 테스트 기법에 대한 가치의 핵심은 다른 곳에 있다.
- 그래서 어떤 불변 조건을 검증해야해?
- 어떤 입력이 올바른 구현과 그에 근접하는 오답을 구분해야해?
- 기대값은 구현과 독립적으로 어디에서 넘어오는가?
- 무작위 입력이 유효하고 의미 있는 상태에 도달하는가?
- 두 구현은 정말 다른 가정과 경로로 만들어졌나?
- 실제 실험에선 아래와 같은 결과가 나왔다.
- TDD 테스트의 조건을 두 배로 늘렸지만, 어려운 동작을 구분하지 못하는 테스트가 늘었다.
- Hegel에서의 테스트는 AI 에이전트의 추론 강도를 올렸음에도 정확성이 개선되지 않았다.
- 구조화된 무작위 입력의 경우 퍼징 조건은 160회 중 10회 뿐이었고, 그 10회 마저도 절반 가량에서 실제 결함을 발견했다.
3.2.3. 다섯 가지의 실패 패턴
- 용어 준수와 의미 준수의 분리
- 에이전트는 요청받은 파일과 라이브러리를 단순히 만들었다는 사실을 작업 완료로 해석할 수 있다.
- 하나의 함수에 대한 평범한 단위 테스트를 넣거나
- 의미 없는 smoke test를 만든다거나
- 상태 변경 테스트를 요청받고도 실제 상태를 생성하지 않는 식이다.
- 에이전트는 요청받은 파일과 라이브러리를 단순히 만들었다는 사실을 작업 완료로 해석할 수 있다.
- 오염되는 판정 기준
- 테스트에 대한 판정 기준 자체를 에이전트가 잘못된 해석을 할 수 있다.
- 또한 잘못 이해된 요구사항은 잘못된 구현과 잘못된 기대값을 가진 테스트로 흘러간다.
- 상태 공간을 탐색하지 못하는 입력
- 랜덤 바이트를 수천 개가 있어도, 대부분 같은 이유로 거부되는 케이스만 테스트할 수 있다.
- 커버리지가 늘거나 크래시가 없다는 사실로 핵심 업무 상태를 테스트했다고 볼 수는 없다.
- 검증 산출물의 팽창
- AI는 테스트 개수, 커버리지, 검증 파일, 감사 보고서나 토큰 사용량이나 리뷰 코멘트를 빠르게 만들 수 있다.
- 이건 활동량 지표지 검증의 증거가 아니다.
- 자기 감사의 비독립성
- 같은 대화, 코드, 요구사항을 공유한 모델은 다른 역할을 맡는다 해도 같은 오해를 반복 할 수 있다.
- 단순히 "새로운 시각으로 다시 검토하라" 라는 문장만으론 정보 독립성이 생기지 않는다.
3.2.4. 검증 극장
- 코드, 테스트, 리뷰 결과가 모두 같은 잘못된 가정을 바탕으로 만들어졌다면, 산출물이 많아도 실제 검증은 이루어지지 않는다.
- 에이전트가 요구사항을 잘못 이해한 상태에서 코드를 작성하고, 그 코드의 동작을 기준으로 다시 테스트를 만든다면 다음과 같은 상황이 생길 수 있다.
- 구현도 잘못됨
- 테스트도 그 잘못된 구현을 정답이라고 판단함
- 리뷰나 감사 결과도 해당 테스트를 근거로 정상이라고 판단함
- 에이전트가 요구사항을 잘못 이해한 상태에서 코드를 작성하고, 그 코드의 동작을 기준으로 다시 테스트를 만든다면 다음과 같은 상황이 생길 수 있다.
- 겉으로는 코드, 테스트, 리뷰가 서로 일치하기 때문에 충분히 검증된 것처럼 보이지만, 실제로는 같은 오류를 서로 확인해주고 있을 뿐이다.
- 이를 **자기 확증형 검증(Self-confirming verification)**이라고 하며, 이런 상황을 **검증 극장(Verification Theater)**이라고 볼 수 있다.
- 검증 극장을 줄이기 위해서는 다음과 같은 방법이 필요하다.
- 정답 기준을 구현과 분리한다.
테스트의 기대값을 현재 프로그램의 출력 결과에서 그대로 가져오지 않는다. 요구사항, 명세, 수작업 계산 등 별도의 기준으로 정답을 정한다. - 틀릴 수 있는 경우를 먼저 생각한다.
구현이 어떤 방식으로 잘못될 수 있는지 가능한 오류 유형을 미리 정리한다. - 오류를 구분할 수 있는 입력을 만든다.
정상 구현과 잘못된 구현이 서로 다른 결과를 내는 입력값을 테스트에 사용한다. - 테스트 작성자와 구현자의 정보를 일부 분리한다.
테스트를 만드는 에이전트가 구현 코드나 구현 과정의 추론을 그대로 따라하지 않도록 한다. - 실패하는 테스트를 임의로 없애지 못하게 한다.
구현 에이전트가 테스트를 통과시키기 위해 실패하는 테스트를 삭제하거나 assertion 조건을 느슨하게 변경하지 못하도록 한다.
- 정답 기준을 구현과 분리한다.
- 핵심은 “테스트가 통과했는가?”가 아니라 “그 테스트의 정답 기준이 구현과 독립적으로 만들어졌는가?”를 확인하는 것이다.
- 커버리지와 오류 구분력
- 커버리지는 코드가 진짜 실행되었는지를 알려준다.
- 오류 구분력은 코드가 잘못 바뀌었을 때 테스트가 이를 감지하는지를 알려준다.
- 둘은 같지 않다.
- 라인 커버리지가 100%라고 해도 모든 테스트를 기대값으로 복사했다면 업무 규칙의 오류를 발견하지 못한다.
- 검증 신뢰성의 4가지 질문
- 판정 기준의 독립성 -> 기대값이 구현과 다른 출처인가?
- 오류 구분력 -> 어떤 잘못된 구현이 이 테스트에서 실패하는가?
- 상태 도달성 -> 입력이 실제 업무 상태와 경계를 통과하는가?
- 우회 방지 구조 -> 에이전트가 테스트 삭제/약화/API 변경으로 통과할 수 없는가?
3.2.4. 검증 극장에서 말한 검증 극장을 줄이기 위한 네 가지 방법과 일맥상통한다.
3.3. 흥미로운 점
3.3.1. 검증 단계를 구조로 분리하라
검증 독립성을 프롬프트에게만 의지 하는게 아니라 구조를 분리한다.
- Specification 사람이 업무 규칙, 불변 조건, 승인 사례를 직접 확정한다.
- Test Design 구현에 참여한 세션(또는 에이전트)가 아닌 다른 세션이 오류 모델과 구별 입력을 만든다.
- Implementation 별도 세션이 구현한 테스트를 임의로 수정할 수 없게 한다.
- Adversarial verification 명세, Public API, diff를 기준으로 그럴듯한 오답, 잔여 위험을 찾는다.
- Human review 변경 이유, 테스트 판정 기준, 보구 방법과 미검증 영역을 판단한다.
가장 중요한 질문은 "특정 에이전트가 어떤 정보에서 의도적으로 분리되었는가?" 이다.
3.3.2. 회사 시스템에 어떻게 적용할 수 있을까?
단순히 AI에게 테스트를 많이 작성해달라 하는 것은 옳지 않다. 실제로 업무 정의를 바탕으로 기대값을 현업에게 요청하거나 미리 정의해놓는 것이 좋다.
| 업무 영역 | 의미 없는 테스트 | 의미 있는 테스트 |
|---|---|---|
| 보험료/준비금 계산 | 현재 계산 결과를 그대로 expected로 복사 | 산식/승인 사례에서 별도로 계산 한 값을 사용 |
| 금액 반올림 | 평범한 정수만을 가지고 계산 | 계산 순서에 따라 값이 달라지는 소수를 사용 |
| 계약 상태 전이 | 해피케이스만 사용 | 금지된 전이/재시도/부분 실패의 경우 테스트 |
| 청약일/설계일 | 임의의 날짜 몇 가지 | 경계 전날, 당일, 다음 날 |
| 트랜잭션 | repository 호출여부만 테스트 | 실제 commit/rollback 결과 |
| Oracle SQL | 쿼리 실행 여부 | NULL, 중복, outer join, 영향 건수 |
| 데이터 이행 | 전체 건수만 비교 | 업무 키별 불변 조건/재실행 |
예제) 반올림 순서에 대한 최소 반례
다음과 같은 업무 규칙을 가정
- 각 담보의 원보험료를 원 단위로 반올림한 후 합산한다.
@Test
void rounds_each_coverage_before_summing() {
var rawPremiums = List.of(
new BigDecimal("100.4"),
new BigDecimal("100.4")
);
var total = premiumCalculator.total(rawPremiums);
// 업무 규칙: 100 + 100 = 200
// 흔한 오답: 200.8을 마지막에 반올림해 201
assertThat(total)
.isEqualByComparingTo(new BigDecimal("200"));
}
만약 각 담보의 보험료 반올림 전 합산된다면 201이 나와야 할테지만, 합산 전에 각각 반올림하여 200이란 값이 나온다는 테스트이다.
이는 좋은 테스트에 속한다. 단순히 테스트 프레임워크를 사용했거나 코드량에 따른것이 아닌 다음과 같은 이유다.
- 올바른 구현과 의도한 오답의 결과가 다르다.
- 기대값이 특정 헬퍼에서 나오지 않았다.
- 하나의 작은 사례로 특정 해석 오류를 드러낸다.
- 어떤 업무 규칙을 검사하는지 설명할 수 있다.
특히 마지막 점이 매우 중요한데, 이는 테스트가 하나의 교보재 또는 업무 정의서로써의 역할도 가능하기 때문이다.
만약 에이전트에게 단순히 경계값에 대한 테스트를 진행하라하면, 100이나 200같은 값을 추가 할 수 있겠지만 위와 같은 결함을 탐지할 능력을 가지지는 못할 것이다.
만약 레거시의 동작이 틀렸다면?
신규 구현한 코드의 결과와 기존 시스템을 비교하는 것은 유용한 테스트이다.
하지만 기존 동작이 틀린 것이라면? 아래 세 가지가 함께 필요하다.
- 기존 시스템과 신규 시스템의 결과 비교
- 의도적으로 변경한 기존 동작의 allowlist
- 양쪽 구현과 독립된 승인 사례
유의해야할 점은 신규 구현과 레거시가 같다는 사실은 회귀가 없다는 증거일 수 있지만, 업무적으로 옳다는 증거는 아니다.
4. Quiz Gate
읽은 날 : 2026-09-26
4.1. 내용
PR을 올렸을 때, 해당 PR에 대한 퀴즈를 만들어 사용자가 해당 PR에 대해 이해하지 못한다고 판단하면 병합을 막는 Github 병합 게이트다.
PR 작성자에게 변경 사항에 대한 객관식 퀴즈를 만드는데, 생각없이 그저 에이전트가 만들어준 소스를 냅다 병합할 수 없게 하는 하나의 검증 수단이다.
사용방법
사용방법은 간단하다. OpenAI를 사용한다고 가정하면 Github Repository에 QUIZ_GATE_API_KEY와 같은 API 키를 Actions에 사용 가능한 Secret으로 등록하면 된다.
그리고 해당 Github App을 내 repositry에 설치하면 된다.
또한 .quiz-gate.yml을 사용하여 더 디테일 하게 변경할 수 있다.
version: 1
enabled: true
provider:
kind: openai
model: gpt-5.4-mini
api: responses
quiz:
question_count: 5
pass_threshold: 80
language: ko
answer_command: /quiz
answerers: author
max_attempts: 3
max_diff_chars: 60000
instructions: >-
변경한 코드의 동작을 실제로 이해했는지 확인한다.
특히 다음 내용을 질문한다.
- 정상 동작
- 예외 상황
- 장애 발생 가능성
- 기존 기능에 미치는 영향
- 롤백 방법
- 주요 설계상의 trade-off
4.2. 흥미로운 점
종종 이런걸 상상은 해봤는데, 직접 구현할 생각을 안했다.
stateless하게 만들어, 누구나 쉽게 해당 형태의 검증을 사용할 수 있게 만들어 좋아보인다.
그런데 뭔가 직접 써보고 싶진 않고 바이브코딩으로 나에게 맞춤으로 하나 만들고 싶어지는 생각이 든다(?)
아마 바이브 코딩을 하면서 이런 류의 APP을 쓰는 사람이라면 이미 자신만의 검증 게이트를 가지고 있을거라는 생각이 든다.
해당 아이디어를 회사용으로 하나 만들어 적용한다면 아래와 같은 정보를 포함해야할 거 같다.
- 작업 요구사항 또는 이슈
- 해당 작업(티켓)의 목적과 non-goal
- 변경 전후의 불변 조건
- 테스트와 실제 실행의 결과
- 위험과 롤백 설명
오히려 암기 시험이 아니고 openbook 형식으로 풀어갈 수 있으므로 내가 적용하고자 하는 소스에 대한 이해도도 높아진다고 예상할 수 있다.
5. 아직도 코드를 읽습니까?
읽은 날 : 2026-09-26
5.1. 내용
저자는 AI를 적극적으로 사용한다. 하지만 자신이 커밋하고 배포하는 코드에 책임을 지기 위해 생성된 코드들을 읽는다.
하지만 코드를 읽지 않는 방식도 충분한 가드레일이 있다면 의식적인 선택이 될 수 있다고 한다.
글에서 가장 큰 문제는 이와 다른 방식을 선택한 사람들이 같은 코드베이스에서 일하며 동료에게 넘기는 유지보수에 대한 부담을 합의하지 않는 것이라고 말한다.
AI 결과물을 어떻게 사용하냐에 따라 Accelerator와 Vibecoder로 분류한다.
- Accelerator
AI를 자신의 이해를 코드로 번역하는 가속기로 사용한다.
이들은 구현 모델과 업무 정의의 이유를 자신이 가지며, 생성된 코드에 대한 핵심 내용을 읽고 설명할 수 있다.
생성된 코드로 인한 변경을 예측하며 직접 유지보수할 생각을 가지며, 이들에게 AI는 강력한 편집기 또는 개발을 도와주는 IDE와 같은 역할을 수행한다.
- Vibecoder
이들은 구현과 그 이후의 수정마저 AI에 위임한다.
원하는 동작, 제약, 명세 그리고 그에 대한 평가기준을 소유한다. 구현의 세부는 교체 가능한 산출물로 취급한다.
다시 소스를 재생성하거나 검증하는 절차를 유지하며, 이들에게 AI는 컴파일러나 코드 생성기에 가깝다.
중요한건 구분 기준이다.
단순히 AI가 작성한 코드 비율이 아니다. 95%를 AI가 작성했더라도 사람이 구현 이론과 결정을 소유한다면, 이는 Accelerator 방식이다.
반대로 사람이 상세한 명세를 작성했더라도, 구현이 불투명하고 재생성을 통해 고쳐간다면 이는 Vibecoder 방식이다.
가장 위험한 상태는 Accelerator로 시작한 자가 점점 diff를 대충 보며 Vibecoding에 필요한 외부 명세와 검증 체계마저 갖추지 못한 채 표류하는 것이다.
5.1.1. 프로그램의 진짜 자산은 이론이다
글은 Peter Naur의 Programming as Theory Building을 인용하며 핵심 자산은 코드가 아니라 시스템에 대한 이론이라고 설명한다.
그 이론은 아래와 같다.
- 프로그램이 현실의 어떤 문제를 다루는가?
- 각 부분이 왜 현재 형태로 존재하는가?
- 요구사항이 바뀐다면 어디를 어떻게 수정해야 하는가?
코드는 위 이론을 표현하는 매개체다.
AI는 이론 없이 이해를 가진 사람처럼 보이는 코드를 만들 수 있다. 그래서 과거에는 코드 품질이 대신 보여주던 인간의 이해를 이제 별도로 확인해야하는 시대가 왔다.
Green test suite같은 TDD이론이 우리가 정의한 동작대로 프로그램이 작동한다는 증거일 수 있으나, 현실의 업무와 맞다는 것까지는 증명해주지 않는다.
구현 과정은 단순히 완성된 명세를 옮기는 작업만이 아니다.
예외와 경계를 코드로 구체화하며 처음의 업무 이해를 수정하는 학습 과정이기도 하다.
5.1.2. 코드를 읽어도 의도는 남지 않을 수 있다
Duration expiryTime = Duration.ofHours(6);
위 코드를 보고 어떤 의도가 보이는가?
6시간이란 값은 보이지만 코드만으로 어떤 의도를 띄는지 우리는 알 수 없다.
6시간을 12시간으로 바꿔도 되는지 판단하려면 값이 아닌 값의 출처가 필요하다.
Code는 무엇을 하는지 나타낸다. 하지만 왜 그렇게 해야하는가에 대한 의도는 표현해주지 않는다.
모든 코드를 읽어도 의도가 남아 있지 않으면 의도 부채가 해소되지 않는다. 반대로, 코드를 읽지 않더라도 명세와 평가 시나리오가 관리된다면 구현을 재생성하는 일관된 방식은 남아있다고할 수 있다.
5.1.3. 유지보수 계약
앞으로 Accelerator를 A, Vibecoder를 V라 부르겠다.
A가 V의 코드를 인수하려면, 원 작성자는 의도를 보존할 생각이 없었기에 인수받은 A는 V의 코드를 역으로 추론해야한다.
반대로 V에게 모든 세부 선택을 설명하라고 한다면, 명세와 재생성 체계에 투자하고 구현을 의도적으로 교체 가능하게 만든 방식과 충돌한다.
병합 전에 아래 세 가지를 합의해야한다.
- 인간이 구현을 이해하고 직접 유지하는가?
- 외부 명세와 평가 시나리오를 기준으로 AI가 재생성하는가?
- 두 방식을 모듈 경계로 분리할 것인가?
그리고 한 가지 방식만을 사용하는 것이 아니라, 업무나 시스템상 위치로 구별할 수 있다.
보험을 예로 든다면 보험료 계산, 설계 상태 변경, 트랙잭션, 오류 복구등의 작업은 A의 방식으로, 그 외에 API Client, DTO, CRUD, 반복되는 Adapter등은 V의 방식이 가능하다.
각 업무 영역에 따라 A와 V의 비율 차이가 있겠지만, 핵심 업무 결정은 사람이 소유하고, 반복 산출물만 재생성하는 것이 바람직하다고 생각한다.
5.2. 흥미로운 점
1, 3, 4, 5번 글을 읽으며 네 가지의 운영 경계가 생겼다.
- Tool Boundary 에이전트가 어떤 도구/의존성/서비스를 사용하는가?
- Change Boundary 얼마나 큰 변경을 어떤 의미 단위로 제출할 수 있는가?
- Verification Contract 무엇을 어떤 독립적인 증거로 검증해야하는가?
- Maintenance Contract 구현을 사람이 이해하여 유지할 것인가, 명세와 시나리오로 재생성할 것인가?
결국 지속 가능한 AI 변경은 아래와 같다.
지속 가능한 AI 변경
= 검토 가능성
× 독립 검증
× 인간의 이해
× 의도 추적 가능성
모두가 곱셈인 이유는 그 무엇 하나도 장식이 아니기 때문이다. 요소 중 하나라도 빠져있다면 그것은 지속 가능한 AI 변경이 아니다.
또한 PR을 하나의 검증 패킷으로 만들어 병합 판단에 필요한 증거 묶음으로 본다.
## Why
이 변경이 필요한 이유
## Scope / Non-goals
이번 PR에서 바뀌는 것과 바뀌지 않는 것
## Domain Invariants
반드시 유지되어야 하는 업무 규칙과 예외
## Distinguishing Cases
올바른 구현과 흔한 오답의 결과가 달라지는 입력
## Risk and Rollback
트랜잭션, 데이터, 보안, 성능 영향과 복구 방법
## Verification
테스트, 정적 분석, SQL 검증, 수동 확인 결과
각 기대값과 판정 기준의 출처
## AI Involvement
AI가 생성·수정한 범위와 사람이 직접 판단한 부분
## Review Map
권장 리뷰 순서와 집중해서 볼 파일
## Maintenance Mode
Human-owned / Regenerated / Mixed
## Decision Provenance
요구사항, 의도적인 설계 결정, 기존 관례,
AI의 우연한 선택, 아직 근거가 불명확한 선택
지금과 같은 시대에 와서 하나하나 작성하는건 옳지 않아 보일 수 있다.
자동 생성할 수 있는 부분이 있다면 AI의 도움을 받은 뒤 이를 검토하는 방식으로 작성하는 것도 좋아보인다.
중요한 것은 해당 PR 문서는 자신의 책임이라는 자각을 가지는 것이다.
에이전트에게 검증을 지시하는 법
- 약한 지시
이 기능을 구현하고 테스트를 충분히 작성한다.
TDD, property-based testing, mutation testing을 활용한다.
모든 edge case를 검증한다.
위와 같은 프롬프트를 자주 접할테지만, 행동 기준이 부족하다고 평가할 수 있다.
물론 길게 쓴다고 좋은 프롬프트는 아니지만 아래와 같이 디테일하게 작성한다면 더 퀄리티 있는 결과물을 가질 수 있을 것이다.
## Verification Contract
구현 전에 다음을 수행한다.
1. 요구사항에서 반드시 유지되어야 할 업무 invariant를 나열한다.
2. 각 invariant마다 가능한 잘못된 구현을 최소 2개 제시한다.
3. 올바른 구현과 각 오답의 결과가 달라지는 최소 입력을 설계한다.
4. 경계 양쪽과 순서·방향·상태가 다른 비대칭 사례를 사용한다.
5. 기대값의 권위 있는 출처를 밝힌다.
현재 구현, production helper, 현재 실행 결과에서 복사하지 않는다.
테스트 작성 시 다음을 지킨다.
- 랜덤 데이터는 유효한 도메인 객체를 먼저 만들고 의미 있는 한 축을 바꾼다.
- validation rejection이나 no-throw만 반복하는 테스트를 정확성 증거로 세지 않는다.
- 동일한 production helper를 구현과 테스트 양쪽에서 사용하지 않는다.
- 업무 계산은 mock하지 않고 실제 외부 경계만 mock한다.
- 구현을 통과시키려고 기존 테스트를 삭제하거나 assertion을 약화하지 않는다.
변경 유형별 증거:
- Bug fix:
수정 전 실패하고 수정 후 통과하는 regression test
- Business rule change:
요구사항 기반 decision table과 경계 양쪽 사례
- Refactoring:
변경 전후 동일하게 통과하는 characterization test
- SQL/Data change:
fixture, 예상 row set, 영향 건수, 재실행과 rollback 결과
- Retry/Idempotency change:
중복 실행, 부분 실패, 재시작 시나리오
완료 보고서:
- 검증한 invariant
- 고려한 잘못된 구현
- 각 테스트가 구분하는 오류
- 실제 실행한 명령과 결과
- 독립적으로 검증하지 못한 영역
- 사람이 판단해야 하는 항목
핵심은 테스트 기술을 사용하라는 것이 아닌, 어떤 오류를 어떻게 구분했는지 증명하라로 변경된 내용이다.
지표를 생성 코드량보단 처리량으로 봐야한다.
이제 더이상 코드 생성은 병목이 아니다.
지속 가능한 AI 개발과 유지보수 가능한 애플리케이션을 위해서 아래와 같은 지표들을 관찰해야한다.
- PR 대기 시간, 리뷰 재작업 횟수
- 변경 예산 초과율과 분할 이후 변화
- 승인 사례가 없는 고위험 변경 수
- 운영 결함이 어떻게 검증을 통과할 수 있었는지
- 재처리, 롤백 절차로 실제 재현이 가능한지
- 생성 코드 영역을 원본 명세에서 다시 만들 수 있는지
팀을 평가하는 지표라기보다는 정책을 조정하기 위한 지표라고 볼 수 있다.