더 큰 모델이 더 느리고 더 틀렸다
원문을 그대로 둔 채 옆에 직역을 띄워주는 작은 도구를 만들고 있다. 구조는 고정이다 — 화면을 캡처하고, 글자를 읽고, 번역하고, 렌더링한다. 번역 단계는 그동안 원문을 그대로 돌려주는 자리표시자 엔진으로 돌아가고 있었다. 실제 로컬 언어모델로 갈아끼우기 전에, 크기가 다른 네 모델을 같은 만화 페이지의 말풍선 13개로 나란히 돌려봤다.
큰 모델이 이기지 않았다. 작은 모델 하나와 중간 크기 모델 하나가 각각 4.2초·11.4초에 답을 냈는데, 서로 다른 방식으로 틀렸다 — 하나는 고유명사를 일반명사처럼 뭉갰고, 다른 하나는 종교적 용어를 뜻으로 옮기지 않고 음으로만 옮겨 알아들을 수 없는 말을 만들었다. 훨씬 큰 모델은 5배 느린 20.8초를 쓰고도 둘보다 못했다 — 원문에 없는 이름을 지어냈고 존칭을 그대로 남겼다. 어려운 대목(고유명사는 고유명사로, 관용구는 뜻으로)을 실제로 맞힌 건 중간보다 작은 모델이었고, 그 모델이 가장 빠르기도 했다. 크기가 정확도를 사지 않았다 — 크기가 산 건 느려지는 시간뿐이었다.
열다섯 개를 한 번에 보내니 끝이 사라졌다
모델을 고른 뒤 만난 문제는 언어가 아니라 구조였다. 텍스트 조각 15개를 한 요청에 보냈더니 뒤쪽 3개가 조용히 사라졌다 — 깨진 것도, 실패로 표시된 것도 아니고 그냥 없었다. 마치 애초에 요청받지 않은 것처럼. 같은 조각을 6개씩 나눠 보내니 누락이 완전히 사라졌고, 전체 소요 시간은 거의 그대로였다. 실제로 도움이 된 건 배치 크기를 키우거나 재시도를 추가하는 게 아니라, 매 묶음이 끝난 뒤 작은 검증 하나를 넣는 것이었다 — 보낸 조각 전부가 빈 값 없이 돌아왔는지 확인하고, 이 검증을 통과하지 못한 묶음만 한 개씩 낱개로 다시 번역하는 규칙이다. 조용히 사라지는 번역보다는, 눈에 띄게 못한 번역이 낫다.
재부팅마다 리셋되는 권한
별개로, 화면 기록 권한을 분명히 허용했는데 바로 다음 재빌드에서 작동을 멈췄다. 요청 로직은 아무것도 바뀌지 않았다. 원인은 코드 서명이었다 — 임시 서명(ad-hoc)으로 빌드할 때마다 서명 해시가 새로 생기는데, 운영체제는 그 정확한 서명에 권한을 묶지, 앱 이름이나 번들 식별자에 묶지 않는다. 권한을 주고 다시 빌드하면, 운영체제 입장에서는 같은 옷을 입은 낯선 사람이 나타난 것과 같다. 지금은 이미 권한을 가진 프로세스를 통해 도구를 실행하는 우회로 버티고 있고, 근본적인 해결은 고정된 서명 신원을 마련하는 것인데 빌드가 이렇게 잦은 동안은 그 작업의 효용이 크지 않다.
세 문제 — 모델 선택, 배치 크기, 운영체제 권한 — 는 겉보기엔 전혀 다른데, 실패하는 모양이 같았다. 셋 다 조용히, 겉보기엔 완전히 정상적인 결과물을 내놓으며 실패했다. 끝이 잘린 번역도 여전히 번역처럼 읽힌다. 조용히 취소된 권한도 제대로 된 질문을 던지기 전까지는 계속 “허용됨”이라고 답한다. 이런 종류의 실패를 잡는 도구는 더 똑똑한 출력이 아니라, 모든 결과물에 대해 매번 돌리는 체크리스트다 — 보낸 것과 받은 것의 개수가 정말 똑같은가.