스크래치 호스트가 오라클을 소유해서는 안 되는 이유
요약
본 기사는 소프트웨어 테스트 및 릴리스 프로세스에서 '오라클(Oracle)'의 정의와 중요성을 강조합니다. 오라클은 단순히 모델이 생성한 결과나 임시 호스트에 존재하는 것이 아니라, 팀이 관리하고 재현 가능한 고정된 예상 바이트와 점수 계산기여야 합니다. 모델 기록이나 무료 서버 옵션 같은 것은 초안(draft) 단계에 머물러 있으며, 신뢰할 수 있는 테스트 시스템의 핵심 요소가 될 수 없습니다.
핵심 포인트
- 오라클은 팀이 관리하는 고정된 예상 바이트와 점수 계산기여야 합니다.
- 모델 기록이나 임시 호스트는 '초안' 수준이며 권위가 부족합니다.
- 신뢰할 수 있는 테스트를 위해서는 재현 가능하고 관리되는 시스템이 필수적입니다.
- 단순한 프롬프트나 메시지로는 근본적인 프로세스 문제를 해결할 수 없습니다.
무료 모델 패스는 출시 게이트(release gate)가 아니라 초안 신호(draft signal)입니다. 황금 고정값(golden fixture), 그 내용 해시(content hash), 그리고 변경 사항이 배포될 수 있음을 나타내는 비트(bit)는 팀이 이미 소유하고 벤더 왕복(vendor round trip) 없이 재실행할 수 있는 인프라에 남아 있어야 합니다. 호스팅된 어시스턴트는 패치를 제안할 수 있고, 여분의 호스트는 임시 스모크 테스트를 실행할 수 있습니다. 하지만 어느 쪽도 해당 스위트가 통과했는지에 대한 기록 시스템(system of record)은 아닙니다.
혼란은 어시스턴트가 리뷰보다 더 빠르다고 느낄 때 시작됩니다. 불안정한 단언문(flaky assertion)이 실패하고, 모델이 단언문이 조용해지도록 예상 파일을 재작성하며, 스크래치 호스트는 누군가가 릴리스 노트에 붙여넣을 녹색 줄을 출력합니다. 실험실 노트북은 건물에서 사라졌고, 밀랍 인장(wax seal)도 함께 사라졌습니다. 회귀 증거(Regression evidence)는 팀이 관리하는 장비에서 내일 같은 바이트로 해시될 수 있을 때만 유효합니다.
그 속성은 초안의 신뢰성(confidence)에 달려 있는 것이 아니라 스토리지와 프로세스 자체에 있습니다. 스택 트레이스(stack trace)에 대한 도움이 되는 설명이 빨리 도착했다는 이유만으로 오라클이 될 수는 없습니다. 오라클은 팀이 오프라인에서 실행할 수 있는 고정된 예상 바이트와 점수 계산기(scorer)입니다. 스케치(sketch)의 속도는 별개의 문제이며, 이 둘을 혼합하는 것이 녹색 로그가 테스트를 대체하게 만드는 방식입니다.
공개: 본 기사는 MonkeyCode의 제품 아웃리치(product outreach)의 일환으로 작성되었습니다. 무료 모델 접근은 패치 스케치나 실패 설명에 대한 요청을 할 수 있는 합리적인 장소입니다. 무료 서버 옵션은 팀이 실행 실패 시 버릴 여유가 있는 프로세스를 부팅할 수 있는 합리적인 장소입니다. 이러한 역할들은 초안에서 멈추며, 고정값(fixtures)의 관리, 점수 계산기(scorer), 또는 다른 작업들이 신뢰하는 통과 비트(pass bit)까지 확장되지 않습니다.
장애가 아닌 위험 신호들
위험 신호는 극적인 서비스 중단보다는 소유권 누락 형태로 나타납니다. 어시스턴트 기록에만 존재하고 검토된 diff로 저장소에 들어오지 않는 고정 요소(fixture)가 있거나, 예상 출력의 유일한 사본이 팀이 관리하지 않는 호스트에 놓여 있을 수 있습니다. '통과'라는 문구는 모델이 자신의 패치에 대해 작성한 문장이거나, 해시를 재계산하지 않고 녹색으로 출력되는 러너(runner)의 로그 라인일 수 있습니다. 릴리스 시점은 팀이 실제로 확보할 수 있는 시간 동안 해당 경로가 응답하는지에 따라 결정되기 시작합니다.
이러한 누락 중 어느 하나만으로도 게이트를 다시 끌어당기기에 충분합니다. 이 모든 것들이 합쳐져서, 이 스위트(suite)는 더 이상 테스트가 아니며, 타임스탬프가 찍힌 소문은 다음 사고 검토에서 살아남지 못할 것이라는 의미입니다. 해결책은 더 엄격한 프롬프트나 더 긴 시스템 메시지가 아닙니다. 신중한 문구만으로는 커밋된 적이 없는 파일을 복원할 수 없으며, 관리되지 않는 디스크를 기록 시스템으로 바꿀 수도 없습니다.
'통과'라는 표시가 있을 세 곳의 홈은 혼동하기 쉽습니다. 왜냐하면 이 세 곳 모두 'passed'라는 단어를 출력할 수 있기 때문입니다. 모델 기록은 읽기는 쉽지만 권위로서는 쓸모가 없습니다. 나중에 읽는 사람이 판단된 바이트를 재연할 수 없기 때문입니다. 무료 서버의 디스크는 충돌 덤프(crash dump)를 저장하기에는 적절하지만, 유일한 오라클(oracle)을 두기에는 부적절합니다. 그 이유는 해당 디스크의 보존 및 재구축이 릴리스 작업 외부에 있기 때문입니다. 이미 릴리스 아티팩트를 생성하는 주 러너(primary runner)는 스케치하기가 더 느리며, 요청 없이 벗어난 고정 요소를 거부할 수 있는 유일한 홈입니다.
반복되는 안티패턴은 기록이나 무료 호스트가 주 러너가 신뢰해야 할 파일을 작성하도록 내버려 두는 것입니다. 이후 작업들은 고정 요소(fixture)를 열지 않고 부울 값(boolean)을 읽기 시작합니다. 부울 값은 잘 전파되며, 어떤 트리가 점수화되었는지 숨기기 때문에 소유된 '통과' 표시는 색상 대신 해시를 포함해야 합니다.
초안이 새로 고칠 수 없는 봉인
더 나은 구성은 의도적으로 지루합니다. Fixtures는 소비하는 코드 옆의 리포지토리에 존재하며, 로컬 명령어는 어떠한 어시스턴트가 편집을 제안하기 전에 해당 파일들을 해싱(hashes)합니다. 이 해시는 mtime, 파일 소유자, 디렉토리 순회 순서를 무시하므로, 동일한 바이트에 대한 두 번의 체크아웃은 일치합니다. 어시스턴트는 소스 변경이나 fixture 변경을 제안할 수 있지만, 그 제안은 커밋(commit)이 아니라 diff이며, seal을 업데이트하는 경로가 없습니다.
무료 서버는 출력이 신뢰되지 않는(untrusted) scratch 디렉토리에서 후보를 실행할 수 있습니다. 소유된 러너(owned runner)는 해시를 확인하고, 팀이 이미 유지하는 스코어러(scorer)를 실행하며, pass 파일의 유일한 작성자입니다. 무료 경로가 중단되면, 인간이 패치(patch) 초안을 잡아야 할 때 릴리스 속도가 느려집니다. 그들은 오라클(oracle)이 사라졌다고 해서 멈추지 않는데, 이것이 이 분리가 막기 위해 구축된 실패 사례입니다.
아래의 Python 코드는 포착된 실행 결과가 아니라 제안입니다. 이는 실제 무료 서버에서 실행된 적이 없으며, 모델 이름, 할당량(quota), 또는 타이밍 결과를 명시하지 않습니다. 이는 신뢰되지 않는 smoke 결과에 권위를 부여하는 것을 거부하며, fixture 트리가 seal 이후로 벗어나면 중단됩니다. NUL 구분자(NUL separators)는 파일명이 내용물과 충돌하는 것을 방지하고, 정렬은 다이제스트를 파일 시스템 순서와 독립적으로 만듭니다.
#!/usr/bin/env python3
"""제안: fixtures를 로컬에서 seal한 다음, 신뢰되지 않는 pass 비트를 거부합니다.
...
scratch 디렉토리는 누군가 호스트(host)를 연결하기 전에 경계를 보이게 합니다. 첫 번째 게이트는 실패 시 닫히도록(fail closed) 되어야 하며, fixture 편집 후의 게이트도 마찬가지로 실패 시 닫혀야 합니다. 이러한 실패들이 바로 제어 장치이며, 데모의 버그가 아닙니다.
mkdir -p fixtures
printf 'expected: 2\n' > fixtures/add.out
python3 seal_fixtures.py seal
...
아래의 기록(transcript)은 예시적입니다. 이는 실행에서 포착된 로그가 아니며, fixture 바이트가 다르면 16진수 다이제스트도 달라질 것입니다.
sealed <sha256 of fixtures/>
ignored untrusted smoke; it cannot set the pass bit
primary has not scored; refuse to promote a draft
...
성공적인 게이트를 통과한 후 소유된 패스(owned pass)를 읽고 free-smoke identity가 부재할 때입니다. 파일 이름은 주 실행기(primary runner)를 지정하고 봉인된 해시(sealed hash)를 반복하는데, 이는 이후 작업들이 받아들여야 하는 유일한 식별자입니다. 오라클을 eager rewrite 방식으로 드리프트시키고 다음 게이트는 봉인을 새로 고치기 전에 멈춥니다. 사람이 피처 변경 사항을 커밋하고, 검토자가 diff를 읽은 후, 누군가 주 실행기에 대해 다시 seal을 실행합니다.
데모에서 작성된 primary-score.json은 게이트가 작동하도록 만든 임시 파일(stand-in)입니다. 실제 작업은 그 파일을 팀이 이미 신뢰하는 스위트의 출력물로 대체해야 하며, 이 임시 파일은 CI에 절대 복사되어서는 안 됩니다. free server JSON은 무엇이 잘못되었는지 힌트로 빌드 로그에 남아 있을 수 있습니다. gate가 결과 필드를 통해 아무것도 전달하지 않는 것은 의도적이며, 왜냐하면 부울(boolean) 값을 뒤집을 수 있는 힌트는 주 실행기가 느려질 때 처음 사용되는 부울 값으로 사용될 것이기 때문입니다.
스크래치 호스트는 후보 파일에 대한 복사본을 받지, seal, primary score 또는 owned pass에 대한 쓰기 자격 증명(write credential)을 받지 않습니다. 만약 이러한 경로들이 free server로 마운트된다면 분리는 연극이 됩니다. 올바른 실행기 이름과 함께 위조된 primary-score.json은 단지 또 다른 신뢰할 수 없는 녹색 라인일 뿐입니다. 게이트는 파일 시스템 자체가 허용한 식별자에 대한 거짓말을 감지할 수 없습니다.
동일한 규칙을 이미 아티팩트를 게시하는 작업에 연결하세요. 셸 스크립트는 특정 공급업체의 워크플로우가 아니라 예시적인 것이며, seal_fixtures.py에 실제 primary score 옆에 제안이 존재한다고 가정합니다.
set -euo pipefail
test -f fixtures.seal.json
test -f primary-score.json
...
만약 gate가 0이 아닌 값으로 종료되면, 작업은 중단됩니다. 빨간색 결과가 아마도 괜찮았는지 free 모델에게 물어보는 폴백(fallback)은 없는데, 왜냐하면 그 폴백 자체가 부드러운 목소리로 나타난 원래 버그이기 때문입니다. 잘못된 제안이 배포된 오라클 대신 검토 코멘트를 비용으로 지불하는 브랜치에서 더 일찍 스케치가 발생할 수 있습니다.
언제 포기해야 하는가
종료(Exit)는 분위기가 아니라 일련의 조건입니다. 피처 해시가 사람이 커밋하지 않았는데 변경될 때, 스모크 호스트가 유일하게 예상되는 출력을 가지고 있을 때, 또는 동일한 후보를 두 번 실행했을 때 불일치하고 누구도 점수가 매겨진 바이트를 지목할 수 없을 때 게이트에서 자유롭게 빠져나오십시오. 또한 릴리스 기간이 해당 경로에서 팀이 실제로 관찰한 최악의 정체 시간보다 짧을 때도 마찬가지입니다. 측정되지 않은 희망은 SLO가 아니며, 이 메모는 아무것도 발명하지 않습니다.
동일한 종료 조건은 스위트가 비밀 정보(secrets), 실시간 결제(live payments), 프로덕션 행(production rows) 또는 고객 텍스트를 여전히 포함하는 프롬프트를 건드릴 때도 적용됩니다. 이러한 바이트는 더 빠른 주석을 얻기 위해 팀이 관리하지 않는 호스트로 이동해서는 안 됩니다. 대안은 어시스턴트가 편집자 역할만 하는, 소유된 러너(owned runner) 단독 사용입니다. 그 편집자는 패스 비트를 결코 보지 못하며, 봉인(seal)을 다시 쓸 수 있는 자격 증명도 받지 못합니다.
이러한 접근 방식은 여러 팀에 적합하지 않으며, 부분적인 채택은 건너뛰는 것보다 더 나쁩니다. 주된 러너가 없는 그룹은 무료 서버를 러너로 이름 변경해서는 안 됩니다. 왜냐하면 부족한 것은 호스트 이름이 아니라 관리(custody)이기 때문입니다. 피처에 고객 데이터, 토큰 또는 비편집된 프롬프트를 보유하는 그룹은 더 빠른 스케치를 위해 그 트리를 업로드해서는 안 됩니다. 무료 경로가 정체될 때 수동 패치가 불가능한 그룹은 어시스턴트를 릴리스 경로에서 제외해야 합니다.
본 문서는 할당량, 하드웨어 형태, 기간 또는 무료 옵션이 유지된다는 약속을 제시하지 않습니다. 그러한 세부 사항들은 변하며, 게시글에 그것들을 고정시키는 것은 잘못된 장소입니다. 해시 동등성은 도메인 정확성을 증명하지도 못합니다. 단지 오라클이 초안 아래에서 움직이지 않았다는 것만 증명할 뿐이며, 실제 스코어러는 여전히 기본(primary) 위치에 있어야 하고, 이는 CI가 이미 실행하는 언어로 되어 있으며, 실패는 사람이 열 수 있는 상태여야 합니다.
이러한 한계 내에서 MonkeyCode의 무료 모델 접근은 스케치 단계입니다. 이는 후보 차이점(candidate diff)이며, 사람이 읽고 주 브랜치에 점수를 매길 곳으로 내려놓습니다. 무료 서버 옵션은 스크래치 연기(scratch smoke)와 같아서, 여기서 후보를 실행하더라도 크래시가 봉인(seal)을 삭제하지 않습니다. 이미 CI를 소유한 팀에게 다음 단계는 작습니다. 스케치를 그 무료 모델 접근에 겨냥하고, 봉인 파일은 주 브랜치에 유지하며, 다른 모든 녹색 줄들은 소유된 게이트가 다시 인쇄할 때까지 읽지 않은 것으로 취급합니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기