9/9 테스트 통과, 대상 파일의 변경, import 경로 일치까지 확인한 실행 기록
터미널에 9 passed가 표시되더라도, 지정된 파일이 실제로 변경되었다는 보장은 없습니다. Codex에 DeepSeek의 deepseek-v4.1-flash를 연결하여 실행했을 때는 9가지 동작 테스트(behavior test)가 통과했고, inventory_service.py의 해시값도 변화했습니다. 동작의 9점에 파일 변경의 1점을 더해 총 10/10으로 인정하고 있습니다.
같은 모델을 DSH로 구동하여 비교했을 때도 역시 9 passed였습니다. 하지만 대상 파일은 변하지 않았고, DSH는 다른 위치에 동일한 이름의 Python 패키지를 생성했습니다. 테스트가 읽어 들인 것은 새로운 패키지였으며, 요구했던 파일이 아니었습니다. 따라서 점수는 9/10점입니다.
이 차이는 단순히 테스트 개수만으로는 설명할 수 없습니다. 테스트가 확인하는 '동작(behavior)'과 결과물이 위치한 '장소(location)'를 별도로 검사해야 합니다.
확인된 조건을 먼저 고정합니다. 실행 로그에 남아있지 않은 소프트웨어 버전은 추측으로 채우지 않습니다.
| 항목 | 확인 값 |
|---|
| Codex CLI | 0.165.0 |
| ... | |
Python의 정확한 버전은 저장된 로그에 남아있지 않으므로, 여기서는 고정하지 않습니다. 재현 환경에서는 python --version의 결과도 실행 기록에 남겨주십시오. | |
다루는 주제는 재고 예약(inventory reservation)을 수행하는 작은 Python 서비스입니다. 테스트가 확인해야 할 조건은 다음과 같았습니다: 재고를 원자적으로 확보하는 것, 중복 SKU를 수량 판정 전에 통합하는 것, 부적절한 수량을 일괄 거부하는 것, 내부 상태를 가변인 채로 snapshot()을 통해 노출시키지 않는 것이었습니다.
나아가 동시 실행 테스트에서는 7개 재고에 대해 50개의 스레드를, 2개 한정 상품에 대해 40회의 구매를 발생시켰습니다. 단순히 눈으로 보기만 깔끔한 메서드로는 통과할 수 없는 구성입니다.
Codex의 역할은 단순한 코드 초안 생성 그 이상입니다. 리포지토리를 읽고, 대상 파일을 편집하며, 테스트를 실행하고, 실패 출력을 다음 수정에 반영하는 반복(iteration)을 가능하게 합니다. DeepSeek를 연결함으로써 이 반복 과정을 현실적인 비용으로 돌릴 수 있었습니다. 다만, 에이전트의 완료 메시지는 인정 증거가 아닙니다. 마지막 확인은 외부에서 진행합니다.
테스트 결과를 같은 작업 디렉토리로 되돌림으로써, 다음 수정과 재실행을 연결할 수 있습니다.
개인 정보는 설정 파일에 직접 작성하지 않고 환경 변수(environment variable)를 통해 전달합니다. 다음 설정은 실행에 사용된 연결 조건을 재현하기 위한 최소한의 부분입니다.
model = "deepseek-v4.1-flash"
model_provider = "crazyrouter"
[model_providers.crazyrouter]
...
설정 로드 후 확인해야 할 세 가지가 있습니다. 환경 변수 CRAZYROUTER_API_KEY가 Codex에서 보이는지, 모델 ID가 응답을 반환하는지, 지정된 작업 디렉토리에서 툴(tool)을 실행할 수 있는지 여부입니다. 연결 실패와 권한 실패, 경로 오류를 하나의 에러로 취급하면 원인 분리(troubleshooting)에 시간이 걸립니다.
연결, 모델, 작업 디렉토리를 각각 통과시키면, 실패한 지점을 유일하게 특정할 수 있습니다.
최소한의 읽기 명령어(read command)를 한 번 실행하고, 그 후에 짧은 테스트를 수행하며, 마지막에 실제 수정 작업을 진행합니다. 이 순서라면, 모델 응답의 품질을 의심하기 전에 입력 경로와 실행 환경 중 어디에서 멈췄는지 확인할 수 있습니다.
이번 비교에서 중요한 것은 Python의 import 해결 순서입니다. 작업 디렉토리에 inventory_service.py와 inventory_service/가 동시에 존재할 경우, import inventory_service가 어느 것을 읽을지는 탐색 경로(search path)에 좌우됩니다. 동일한 이름의 패키지가 먼저 발견되면, 원래 모듈을 수정하지 않았더라도 테스트는 새로운 구현을 읽어 들일 수 있습니다.
따라서 다음 두 가지는 별개의 질문입니다.
- 테스트가 기대하는 동작을 구현했는가
- 그 구현이 지정 파일에 존재하며, 테스트가 그 파일을 읽었는가
9 passed는 첫 번째 질문에 답합니다. 두 번째 질문은 파일 해시값(hash), 차분(diff), import 경로를 확인해야만 닫을 수 있습니다.
종료 코드(exit code), 차분, 해시, import 경로는 각각 다른 실패를 감지합니다.
수정 후 확인은 실행한 디렉토리에서 진행합니다. PowerShell의 예입니다.
$target = (Resolve-Path .\inventory_service.py).Path
$target
(Get-FileHash $target -Algorithm SHA256).Hash
...
대상 파일의 해시 값은 실행 전 5F8FA06F3A9B9ED7022CE2EEC9158D0139DEC6716872FAC8F9D0E86DDC7C88F8에서, 실행 후 008AF21A36C45CDBB9513961DBF52E2E663791EF5CA5A31FB018871F1F4EF66D로 변경되었습니다.
git diff --name-only를 사용하면 승인된 파일 외에 다른 파일이 변경되지 않았는지 확인할 수 있습니다. 마지막 Python 명령어가 반환하는 inventory_service.__file__가 대상 파일과 같은 디렉터리를 가리킨다면, 테스트와 산출물의 위치가 일치합니다.
수용 조건은 동작의 통과와 지정된 파일로의 전달을 동일한 실행 기록으로 연결하는 것입니다.
종료 코드가 0이더라도 차이가 없다면 복구는 성공했다고 볼 수 없습니다. 해시 값이 바뀌었더라도 승인되지 않은 파일만 변경되었다면 불합격입니다. 테스트가 별도의 패키지를 로드했다면, 녹색 표시(green display)는 산출물의 정확성을 보장하지 않습니다.
DSH 실행에서도 9개의 동작 테스트는 통과했습니다. 그러나 지정된 inventory_service.py는 그대로였습니다. DSH는 다른 위치에 동일한 이름의 패키지를 생성했고, 테스트는 그곳을 import 했습니다. 동작 9개만으로는 9/10점이며, 대상 파일을 변경하지 못했기 때문에 1점을 감점합니다.
이 결과가 DSH가 항상 실패한다는 의미는 아닙니다. 이 과제, 이 디렉터리 구성, 그리고 이 실행 조건 하에서 테스트 통과와 지정 파일 업데이트가 일치하지 않았다는 기록입니다. 모델의 일반적인 우열로 확장해서 해석해서는 안 됩니다.
재발을 방지하려면, 테스트 명령어뿐만 아니라 대상 파일과 import 대상을 하나의 수용 절차에 포함해야 합니다. 에이전트에게 전달할 완료 조건에도 " inventory_service.__file__가 대상 파일을 가리키는 것"을 추가해야 합니다.
동일한 이름의 패키지가 늘어난 경우에는, 테스트 성공보다 먼저 import 해결 순서를 확인합니다.
실행 전체에 걸쳐 입력 토큰 773,893개를 사용했습니다. 세부 내역은 캐시 입력 738,432개, 미캐시 입력 35,461개, 출력 24,869개, 추론(reasoning) 8,033개입니다.
DeepSeek의 공개 리스트 가격을 입력 100만 토큰당 0.45달러, 캐시 입력 0.02달러, 출력 1.34달러로 계산하면 모델 비용은 약 0.064달러가 됩니다. 같은 토큰 구성을 GPT-6.1 Sol의 입력 2달러, 출력 10달러로 추정하면 약 1.797달러입니다.
| 항목 | 수량 | 단가 | 예상 비용 |
|---|
| 미캐시 입력 | 35,461 | 100만 토큰당 0.45달러 | 0.01596달러 |
| ... | | | |
둘 다 청구액이 아니라 공개 리스트 가격에 따른 추정치입니다. 캐시율, 재시도, 라우팅, 실제 입출력에 따라 달라집니다.
싸다는 것이 정확성을 자동으로 보장하는 것은 아닙니다. 실패한 테스트를 읽고 수정하여 다시 실행할 횟수를 늘릴 수 있다는 점이 중요합니다. 잘못된 파일을 싸고 빠르게 만들 수 있다면, 그 저렴함은 가치가 없습니다. 검사까지의 왕복 횟수를 늘릴 때만 의미가 있습니다.
비용이 낮아질수록 시도 횟수는 늘릴 수 있지만, 그것만으로 수용 확인을 생략할 이유는 되지 않습니다.
9 passed인데 대상 파일이 변하지 않는다면, 먼저 import 대상을 확인합니다. 다음으로 동일한 이름의 파일이나 패키지가 증가했는지 git status와 차분석으로 조사합니다.
모델 ID의 응답이 돌아오지 않으면, base URL, 환경 변수 이름, wire_api 설정을 대조해 봅니다. 인증이 필요 없는 프로바이더는 requires_openai_auth = false를 지정하지만, 게이트웨이 측 키는 환경 변수에 필요합니다.
종료 코드와 테스트 결과가 일치하지 않는다면, 실행한 작업 디렉터리를 확인해야 합니다. Codex가 다른 디렉터리에서 테스트를 실행했다면, 눈앞의 파일을 봐도 같은 결과를 얻을 수 없습니다.
문제 해결은 연결(connection), 실행 장소(execution location), 변경 대상(change target), import 대상 순서로 좁혀 나가는 것이 빠릅니다.
하나의 테스트가 실패하고, 대상 파일을 제한할 수 있으며, 로컬에서 재실행 가능한 수정 사항은 이 구성에 적합합니다. lint, 타입 에러(type error), 작은 리팩토링(refactoring), 재현 가능한 테스트 실패도 같은 검증 방법으로 처리할 수 있습니다.
데이터 마이그레이션(data migration), 결제(payment), 인증(authentication), 권한(authorization), 프로덕션 설정(production settings) 등은, 테스트가 모두 통과하더라도 사람의 확인을 남겨야 합니다. 변경 범위, 미테스트 조건, 롤백 수단(rollback means)을 별도로 확인해 주세요.
DeepSeek를 Codex에 연결하는 가치는 모델 점수를 올리는 것이 아니라, 읽기(read), 수정(fix), 실행(run), 재확인(reconfirm)의 루프를 낮은 비용으로 돌릴 수 있다는 것입니다. 마지막으로 파일 해시(file hash), 차이점(diff), import 대상이 같은 대상을 가리킬 때, 9 passed는 비로소 납품의 증거가 됩니다.
Codex용 연결 정보는 Crazyrouter에서 확인할 수 있습니다.
테스트 수(test count), 토큰(token), 해시(hash), 명령어(command), 요금 조건은 저장된 실행 기록과 대조했습니다. 결과는 하나의 프로젝트와 하나의 실행 환경에 한정되며, 모델 전체의 순위를 나타내는 것은 아닙니다.