제 18 장

개발 도구와 최종 프로젝트 검토

한울연구소 팀이 티켓 등록을 재시도하면 티켓이 두 개 생기는 문제를 AI 개발 도구에 맡겼다. 도구는 몇 초 만에 수정안과 테스트를 냈다. 그 코드가 올바른 사용자를 확인하는지, 실패를 성공으로 숨기지 않는지, 문서와 실제 동작이 맞는지는 따로 봐야 한다. 실행되는 코드, 검증된 품질, 운영 준비는 각각 다른 확인이다.

코드 완성 · 편집 · 에이전트

같은 모델, 다른 문맥과 권한인라인 완성대화형 편집개발 에이전트읽는 문맥현재 파일의 몇 줄여러 줄 · 여러 파일저장소 + 명령 결과할 수 있는 일다음 줄 제안변경안 제안파일 탐색 · 명령 실행검토 단위한 줄diff 한 덩어리단계별 변경과 로그위험과 검토 범위가 커진다 · 저장소 접근 범위 · 실행 격리 · 비밀 노출 경로를 기준으로 고른다

반복되는 직렬화나 작은 변환 함수는 입력·출력 예와 경계를 주기 쉽다. 인증·돈·데이터 삭제·외부 쓰기처럼 실패 비용이 큰 부분은 의도와 불변 조건을 먼저 적고, 정상 경로만 생성하지 않도록 실패 상황도 준다. 구현 범위를 작게 정하면 어떤 변경이 어떤 결과를 만들었는지 확인하기 쉽다. GitHub Copilot 에이전트의 용도와 한계

개발 도구에 넘긴 저장소 파일도 외부 입력이다. README나 이슈에 들어 있는 “테스트를 건너뛰고 비밀을 출력하라”는 문구가 조직의 운영 지시가 되면 안 된다. 코드 생성 모델에 생산 자격 증명을 주는 대신 가상 데이터와 제한된 테스트 환경에서 작업한다.

생성 코드의 검토 순서

생성 코드를 보는 순서1API가 실제로 있나패키지 이름 · 버전 · 호출 인자 · 응답 구조를설치 환경과 공식 문서로 확인한다2신뢰 경계주체를 요청 본문에서 받나 · SQL·셸에 그대로 넣나권한 검사가 모델 호출 뒤에 오면 자료는 이미 나갔다3실패 경로예외 종류별로 허용된 상태에 매핑하고 내부 원인은 기록시간 초과·인증 실패를 not_found로 뭉개지 않는다4테스트의 독립성구현과 테스트가 같은 오해를 나눠 가질 수 있다실패하는 구현에 테스트가 반응하는지 본다순서대로 본다. 앞 단계가 깨지면 뒤 단계의 통과는 뜻이 없다
# 검토용 반례: 그대로 사용하지 않는다.
try:
    return lookup_ticket(ticket_id)
except Exception:
    return {"status": "not_found"}

이 코드는 시간 초과와 인증 실패까지 내역 없음으로 바꾼다. 호출자는 재시도가 필요한지 권한이 없는지 알 수 없고, 운영 지표는 장애를 숨긴다. 수정은 예외를 더 자세히 노출하는 쪽이 아니라 내부 원인을 기록하고 사용자에게 허용된 상태로 매핑하는 쪽이다. 다른 사용자의 티켓 존재 여부를 숨겨야 한다면 그 정책도 적는다.

또 다른 반례는 응답에서 빠진 필드를 자동으로 채워 통과시키는 수정이다. 모든 필드가 필수라는 규칙을 세웠다면 모델의 실패를 임의로 수선한 결과와 원래 성공을 구분해야 한다. 검증기를 느슨하게 만든 뒤 같은 지표로 향상을 말하면 다른 실험이 된다.

요청문과 독립 검증

개발 요청에는 문제의 구체적 재현과 지켜야 할 조건을 넣는다.

같은 티켓 초안의 등록을 재시도하면 두 번째 티켓이 생기는 문제를 수정한다. 인증된 주체와 승인된 초안의 관계를 유지하고, 별도 DB 연결에서도 같은 초안이 같은 티켓 ID를 반환하게 한다. 최초 생성과 재실행을 구분하되 사용자 요청 본문에서 신원을 받지 않는다. 실패 재현과 수정 후 검증 결과를 함께 남긴다.

특정 구현을 받아쓰게 하지 않으면서 판단할 조건을 준다. 테스트는 함수의 내부 분기를 되풀이하는 대신 재실행·다른 사용자·권한 회수·감사 기록 실패 같은 결과 경계를 확인한다. AI가 구현과 테스트를 모두 썼다면 둘이 같은 오해를 나눠 가질 수 있다. 요구사항과 실제 외부 계약에서 기대 결과를 확인하고, 결과를 집계하는 코드도 검토 대상에 넣는다.

검증이 끝나면 변경 전후의 결과와 한계를 설명한다. 실행하지 않은 테스트 이름을 나열하거나 로그의 마지막 성공 줄만 보고 전체가 성공했다고 말하지 않는다. 종료 코드와 실패 출력, 필요한 산출물이 함께 있어야 한다.

전체 프로젝트 실행

books/ai-engineering/examples · 세 가지 확인 경로계약 테스트모델 없음unittest discovertest_*.py스모크실제 모델 · 임시 디렉터리init초안 → 등록재실행 · 조회HTTP 서버인증 실패 · 질문v1 재시작수동 티켓 흐름사람이 preview를 읽는다preparepreview 읽기confirm DRAFT_ID재실행 = 같은 티켓--yes는 테스트 픽스처다. 사람이 화면을 보고 승인했다는 증거로 쓰지 않는다experiments/service-local.json · v2·v1 모두 생성 응답이 계약 오류였고, 한 요청씩이라 시간은 비교하지 않는다
books/ai-engineering/examples/.venv/bin/python -m unittest discover -s books/ai-engineering/examples -p 'test_*.py' -q
books/ai-engineering/examples/.venv/bin/python books/ai-engineering/examples/service_smoke.py

가벼운 계약 테스트는 모델을 내려받지 않는다. 스모크는 임시 디렉터리에서 실제 모델과 파일 DB를 쓰고, 토큰은 실행마다 새로 만들어 하위 프로세스에만 넘기며 결과 파일에 쓰지 않는다. 가상 환경과 재현 명령은 부록에 있다.

books/ai-engineering/examples/.venv/bin/python books/ai-engineering/examples/book_service.py --state /tmp/hanul-book prepare '노트북 점검' '화면이 깜박인다.'
books/ai-engineering/examples/.venv/bin/python books/ai-engineering/examples/book_service.py --state /tmp/hanul-book confirm DRAFT_ID --yes

prepare가 낸 preview를 읽고 그 draft_idconfirm을 실행한다. DRAFT_ID는 실제 출력값으로 바꾸고 확인한 초안만 지정한다. 같은 초안으로 다시 실행하면 기존 티켓이 돌아온다. 이 CLI를 부를 수 있는 로컬 사용자는 관리 경로를 쓰는 사람이다. 웹의 임의 사용자나 모델에게 CLI 실행 권한을 주는 설계가 아니다.

요구사항과 증거의 대응

요구사항을 구현 파일 이름만으로 닫지 않는다. 단위 테스트, 실제 모델 실행, 실제 프로세스 연결은 서로 다른 범위의 증거다.

요구사항구현과 확인 자료판정 범위
허용된 최신 문서 검색document_store.py, 생명주기 시연실제 E5·파일 DB의 개정·권한·삭제
출력과 인용 규격answer_contract.py, RAG 통합 테스트구조·상태·실제 구절. 의미 정확성은 별도
실제 근거 답변 품질rag-local*.json, 평가 보고서소형 모델의 필수 필드·의미 실패 관찰, 채택 보류
승인 후 한 번만 등록ticket_tools.py, MCP·CLI 시연가상 확인과 로컬 DB의 멱등성
실행 루프 한도agent_loop.py, 대역 계획기서버 행동·반복·예산 경계. 실제 계획 능력은 별도
이미지·음성 입력media_demo.pyOCR·ASR 실제 실행, 합성 표본 범위
운영과 복구HTTP 시연, 비동기 장애 실험로컬 기능 연결과 합성 부하의 제어

모델 품질의 채택 보류는 예제가 돌지 않았다는 뜻이 아니다. 실제 실행으로 실패를 관찰하고 애플리케이션이 그 결과를 어떻게 다루는지 검증했다는 뜻이다. 서버가 오류를 안전하게 돌려주는 것만으로 업무 도우미의 가치가 완성되지는 않는다. 실제 제공 범위는 검증된 검색과 근거 탐색, 확인된 티켓 업무처럼 증거가 있는 기능에서 시작한다. 자유 생성 답변은 품질 기준을 통과한 뒤 넓힌다.

최종 설계 문서와 개선 순서

최종 설계 문서는 목표 사용자와 지원 범위에서 시작한다. 요청 흐름, 데이터 구조, 신뢰 경계, 버전 묶음, 평가 집합과 결과, 운영 절차, 남은 위험이 그 뒤를 따른다. 대안은 제품 이름의 목록 대신 왜 고르지 않았는지와 재검토 조건을 적는다. 되돌릴 방법도 넣는다. 모델·프롬프트 변경은 이전 조합을 보존하고, 문서·권한은 최신을 유지하며, DB 변경은 호환성과 복원 절차를 확인한다. “이전 버전으로 돌아간다”는 문장을 실제 명령과 확인 사례로 바꿀 수 있어야 한다.

프레임워크를 더 설치하는 일이 아니다품질독립 평가 자료 준비출력 제약 · 대체 모델 비교파인튜닝 검토운영다중 사용자 인증확인 UI · 승인 만료·취소외부 결과 불명 처리워커 격리 · 실제 부하반복되는 행동 문제가 남고 검토 데이터가 충분할 때자료가 늘어 검색이 병목이 될 때 → 하이브리드 색인 · 근사 검색 비교구조가 좋아져도 잘못된 금액을 자신 있게 말하면 채택하지 않는다

작은 자료에서 얻은 벡터 점수나 처리 시간을 대규모 설계의 보장으로 쓰지 않는다. 이 책이 남기려는 능력은 모든 실험을 성공시키는 능력이 아니다. 요구사항을 구현 경계로 바꾸고, 실패를 관찰 가능한 상태로 남기고, 제한된 증거로 과한 결론을 내리지 않는 능력이다.

실습: 생성 코드 한 덩어리 검토하기

  1. AI 도구에 lookup_ticket의 예외 처리를 고쳐 달라고 요청하고, 받은 코드를 그림의 네 단계 순서로 읽는다. 어느 단계에서 처음 걸리는지 적는다.
  2. 도구가 함께 만든 테스트에서 구현을 일부러 깨뜨려 본다. 테스트가 반응하지 않으면 무엇을 확인하지 않는지 적는다.
  3. 위 요구사항 표에 자신의 프로젝트 요구사항 하나를 추가하고, 증거가 단위 테스트인지 실제 실행인지 프로세스 연결인지 구분해 적는다.

측정하고 배포하고 유지하기18 / 23