검수 기본값을 끔으로 바꿨더니 생성 비용이 세 배가 됐습니다
비용을 아끼려고 자동 검수를 기본 끔으로 바꿨습니다. 며칠 뒤 첫 편을 실제로 만들어 보니, 같은 컷을 세 번씩 다시 사고 있었습니다. 아끼려던 돈보다 훨씬 큰 돈이 조용히 나가고 있었습니다.
에러는 한 줄도 없었습니다. 테스트도 전부 통과했습니다. 원인은 꺼 둔 검사가 돌려준 빈 결과를, 판정하는 쪽이 '불합격'으로 읽고 있었던 것입니다. 이 글은 그 경위를 시간 순으로 짚고, 고친 규칙 한 줄로 마무리합니다.
검수가 비용이라 기본값을 껐습니다
자사 영상 콘텐츠 프로젝트의 제작 도구 이야기입니다. 대사가 들어간 컷을 생성 모델로 만들면, 그 결과를 다시 받아쓰기해서 원래 대본과 맞는지 자동으로 검수합니다. 대본과 다르면 그 컷을 다시 생성합니다. 생성 한 번이 곧 호출 비용이라, 이 흐름에서 '다시 생성'은 '다시 산다'와 같은 말입니다.
받아쓰기 결과를 그대로 믿으면 어떤 일이 생기는지는 앞서 따로 정리했습니다. 소리가 없는 오디오를 넣어도 그럴듯한 글이 나올 수 있습니다.
검수 자체도 호출 비용이 붙는 일입니다. 그래서 어느 시점에 검수를 기본 끔으로 바꿨습니다. 필요할 때 켜서 쓰면 된다는 전제였습니다. 코드는 통과했고 테스트도 통과했습니다. 테스트는 검수를 켠 상태를 확인하고 있었고, 켜고 돌리면 정상이었습니다.
빈 글은 대본과 다릅니다
첫 편을 실제로 만들다가 이상한 장면을 봤습니다. 인트로 대사 컷이 매번 세 번씩 다시 생성됐고, 세 번을 다 쓰고 나면 전부 '사람 확인 필요'로 떨어졌습니다. 정작 결과물은 멀쩡해 보였습니다.
따라가 보니 구조는 단순했습니다.
검수가 꺼져 있으면 받아쓰기를 하지 않으므로, 받아쓰기 결과가 빈 글로 내려옵니다
판정 로직은 '받아쓰기 결과가 대본과 다르면 불합격'이었습니다
빈 글은 어떤 대본과도 다르므로 모든 컷이 불합격이 됩니다
불합격이면 재시도하므로, 컷마다 재시도 3회를 다 쓰고 사람 확인으로 넘어갑니다
검사를 안 했다는 사실이 판정하는 쪽에 도착했을 때는 '대본과 다른 결과'로 바뀌어 있었습니다. 판정 입력에 '검사 안 함'이라는 자리가 아예 없었기 때문입니다. 자리가 없으니 코드는 남은 두 칸 중 하나를 골랐고, 그게 불합격이었습니다.

비용은 생성 비용이 세 배로 나갔습니다. 시간도 같이 세 배로 들었습니다. 이 도구에서 클립 생성은 실측으로 42초, 인트로 프레임은 한 장에 4분 15초와 6분 4초가 걸린 작업입니다. 그 작업을 컷마다 세 번씩 반복하고 있었습니다.
에러가 없으면 청구서만 남습니다
이 사고가 조용했던 이유는 재시도가 정상 동작이기 때문입니다. 불합격이면 다시 생성하는 것은 설계대로입니다. 로그에는 에러가 한 줄도 남지 않습니다. 이상하다는 신호는 비용 청구서와, 화면에 쌓인 '사람 확인 필요' 목록뿐이었습니다.
재시도만 조용히 돌아 아무도 모르는 구조는 이번이 처음이 아닙니다. 청크 수천 개가 2분 만에 끝났는데 모델을 한 번도 안 부른 일도 같은 모양이었습니다.
고치게 된 계기는 질문 하나였습니다. 화면에 뜬 실패 사유가 내부 변수를 그대로 찍은 모양이었습니다. '받아쓰기는 빈 문자열, 구성은 없음' 같은 식이었습니다. 이게 무슨 뜻이냐는 질문이 들어왔고, 거기서부터 따라가 원인을 찾았습니다.
곁다리 문제도 하나 더 드러났습니다. 사람이 결과물을 그대로 쓰기로 정해도, 화면의 빨간 실패 줄에는 원래 걸렸던 사유가 그대로 남아 있었습니다. 유지 버튼은 영상 아래에만 있었습니다. 그래서 그 빨간 줄을 지우는 방법이 화면 어디에도 보이지 않았습니다.
판정 입력을 두 값에서 세 값으로 바꿨습니다
규칙은 하나로 정했습니다. **안 돌린 검사는 판정에 쓰지 않는다. 대신 기록에 '검사 꺼짐'을 남긴다.** 고친 것은 세 가지입니다.
판정 입력을 합격·불합격·검사 안 함 세 값으로 나눴습니다. 세 번째 값은 재시도를 일으키지 않고, 왜 판정이 없는지가 기록에 남습니다
실패 사유를 사람이 읽을 수 있는 말로 바꿨습니다. 변수 값을 그대로 화면에 찍지 않습니다
사람이 유지를 고르면 빨간 줄의 사유를 '사람이 유지'로 바꿔 적습니다. 유지 버튼도 영상 아래에서 그 빨간 줄 옆으로 옮겼습니다

세 번째로 고친 버튼 위치는 작은 일로 보이지만 뿌리가 같습니다. 사람이 결과를 뒤집을 수 있는 기능은 처음부터 있었습니다. 다만 뒤집을 대상과 버튼이 떨어져 있어서 아무도 그 방법을 찾지 못했습니다. 이 일을 정리하는 데 모두 180분이 걸렸고, 플러그인 265개·서버 137개·웹 225개 테스트가 통과했습니다.
끄는 쪽만 보면 여기서 어긋납니다
기본값을 끔으로 바꾸는 것은 기능 하나를 끄는 일이 아니었습니다. 그 기능의 출력을 받아 쓰는 모든 곳의 입력이 같이 바뀌는 일이었습니다. 이번에는 끄는 쪽만 보고, 그 빈 값을 받는 판정 쪽까지는 따라가지 않았습니다.
'없음'과 '불합격'을 한 칸에 담으면 코드는 둘 중 하나로 읽습니다. 부분 수정 API 에서 '비운 값'과 '안 보낸 값'이 서버에서 같은 빈 값이 된 일도 같은 구조였습니다.
다만 이 규칙을 그대로 가져가면 위험한 자리가 있습니다. 여기서 '검사 안 함'을 통과 쪽으로 둔 것은 이 검수가 품질 보조였기 때문입니다. 결제·권한·보안처럼 못 했으면 막아야 하는 검사라면 반대입니다. 안 돌았으면 멈추는 쪽이 맞습니다. 그리고 끌 수 없는 필수 검증이라면 세 번째 값은 분기만 늘립니다.
기본값을 끈 판단 자체는 옳았다고 봅니다. 문제는 절감 결정이 아니라, 그 변경이 판정 쪽까지 따라가지 않은 것입니다. 테스트도 켠 상태만 확인했고, 끈 상태로 판정까지 흘려보는 경로는 어떤 테스트도 지나가지 않았습니다.

검사를 끌 수 있게 만들 때 보는 것
비용 때문에 검사를 선택 사항으로 바꾸는 일은 AI 를 붙인 시스템에서 자주 생깁니다. 그럴 때 아래를 봅니다.
그 검사의 결과를 받아 쓰는 곳이 어디인지 셌는가
받는 쪽에 '검사 안 함'이라는 값이 따로 있는가, 빈 값이 불합격으로 읽히지 않는가
그 검사가 품질 보조인가 관문인가 — 관문이면 안 돌았을 때 멈추는가
새 기본값(끔) 상태로 판정까지 흘려보는 테스트가 있는가
돈이 붙는 재시도가 있다면, 실패 판정의 근거가 화면과 기록에 사람 말로 남는가
이번 일에서 남긴 규칙은 한 줄입니다. 안 돌린 검사는 판정에 쓰지 않고, 껐다는 사실을 기록에 남깁니다. 기록에 '꺼짐'이 없으면 나중에 그 결과를 보는 사람도, 그 결과를 읽는 코드도 왜 비었는지 알 수 없습니다.