"뭐 기준으로 done? 그 질문에 답 못 하는 플래그는 입력이 바뀌길 기다리는 버그야."
한-비트 거짓말
파이프라인은 거의 다 processed = true 플래그를 키워. 작업을 다시 안 돌리는 뻔한 방법이니까. 항목마다 done 표시해두고, 다음엔 done 인 걸 건너뛰는 거지. 괜찮아. 입력이 바뀌기 전까지는. 그다음부터 그 플래그는 조용한 거짓말이 돼. 항목에 done 표시는 돼 있는데, 뭘 기준으로 done 이지? 그 뒤에 다시 export 한 source 파일? 그 뒤에 바꾼 오디오 설정? 그 뒤에 업그레이드한 model config? boolean 하나로는 말을 못 해. 서로 다른 열두 개의 질문을 비트 하나로 뭉갠 거라, 밑에 깔린 입력 중 아무거나 움직여도 비트는 여전히 true 로 읽히고 진짜 바뀐 작업은 조용히 건너뛰어져.
stale cache 랑 똑같은 함정이야. cache 항목은 '답을 갖고 있다' 고 말하지만, 그 답은 특정 입력에 대해 계산된 거잖아. 입력이 바뀌면 cache 에 든 답은 여전히 권위 있어 보이면서 틀려. done 플래그는 딱 key 없는 cache 야. 작업이 일어났다는 건 기억하는데 뭐에 대해 됐는지는 안 기억해. cache invalidation 이 컴퓨팅의 어려운 문제로 유명한데, 덜렁 놓인 done-flag 는 곧장 그 안으로 걸어 들어가는 거지.
'이미 done' 은 identity 기준으로만 뜻이 있어
답은 '이거 done 이야?' 대신 '이거 이 identity 기준으로 done 이야?' 를 묻기 시작하는 거야. Recall 은 영상마다 boolean 을 두는 대신, 정확히 정의된 identity 에 대해 뭐가 됐는지를 기록해. 이 source 콘텐츠, 이 오디오 설정, 이 provider 설정, 이 release. 이제 '이미 done' 은 확인할 수 있는 답이 있는 진짜 질문이 돼. 지금 입력을 hash 해서 그 identity 아래 기록이 있는지 찾아. 있으면 진짜 done 이니까 안전하게 건너뛰어. 없으면 뭔가 바뀐 거니까 작업해. 건너뛰기가 작업이 실제로 기댔던 것에 묶였으니까 이제 맞는 거야.
'이 영상에 뭔가 한 번 했다' 와 '이 입력에서 이 출력을 냈다' 는 다른 얘기야. 건너뛰어도 안전한 건 뒤엣것뿐이고. 입력이 바뀌는 순간 false 가 되는 것도 뒤엣것뿐이니까. 이 트랙의 나머지는 그 identity 를 잘 고르는 얘기야. 네가 알아채야 할 변화 종류마다 하나씩.
시스템이 커질수록 왜 더 중요해
장난감 프로젝트에서는 done-flag 가 대체로 통해. 입력이 밑에서 바뀌는 일이 드무니까. 근데 몇 달에 걸쳐 다시 스캔되고, 다시 export 되고, 설정이 바뀌고, 다시 돌아가는 진짜 아카이브에서는 입력이 끊임없이 움직여. 그 변화 하나하나가 덜렁 놓인 done-flag 가 다시 돌아야 할 작업을 건너뛸 기회고. 이런 버그는 자기를 알리지 않아. 원인이 생긴 지 한참 지나서 '왜 이 영상 transcript 가 옛 model 거지?' 하는 식으로 나타나지. 계층 identity 는 그런 조용한 staleness 를 나중에 디버그하지 않으려고 미리 내는 값이야. 지금 정밀하게 가든지, 아니면 영원히 원인 모를 skip 을 안고 가든지.