2026-08-13 (목) 개발일지
오늘은 세 가지 이슈를 잡았다. workbook 검증의 게이트 8에서 걸린 OX 정답 편중, 개발창에서 떠버린 확대/축소 UI, 그리고 장표 병합에서 “성공했지만 0건”을 만든 타입 필터 대소문자 버그. 셋 다 처음 봤을 때는 전부 다른 원인이겠거니 싶었는데, 로그를 파고들수록 지엽적인 곳에서 실제 결함이 튀어나왔다.
mongle-ranch workbook — 게이트 1~7이 전부 PASS인데 OX 92%가 true
/workbook-verify를 3개 팩 100문항에 돌렸다. 스키마 헤더, type, answer 범위, choices 2~6개, ox boolean, Korean 인용, explanation 100자 — 1~7번 게이트는 전부 통과. 문제는 게이트 8(정답 분산)에서 났다. 처음엔 “answer 필드 값이 잘못된 건가” 싶어 answer 범위 검증을 다시 봤지만, 값 자체는 전부 유효한 boolean이었다.
여기서 파이썬 린터의 한계가 드러났다. 린터는 mcq 인덱스 범위만 보고, OX처럼 boolean이면 자료형만 확인하고 넘어간다. 실제로 카운트해보니 OX 정답 13개 중 12개가 true 였다.
item 하나하나를 훑는 구조적 검증으로는 분포 편중이 절대 안 보인다. 분포를 보는 검사가 따로 필요하다.
개편은 patch_cim.py로 진행했다. 편중을 7 true / 7 false로 재배치하고, 같은 패치에서 계산 문항 1개 오류도 같이 수정했다. 3개 팩 다시 돌려 게이트 8 통과를 확인했다. 게이트 9(정답 유일성)는 의미 검증이라 이번에도 수작업 체크리스트로 넘겼다. 자동화로 원리상 대체 불가한 항목이 게이트 9라는 건, 이번 검증에서도 그대로 확인됐다.
cockpit — #zoomBar 가 hidden 을 이긴 건 #terminal 과 똑같은 CSS 우선순위 함정
확대/축소 UI가 개발창 우측 하단에 계속 떠 있었다. 조건은 “공유맵/워크플로우에서만 노출”이어야 한다. 처음엔 뷰 분기 로직이 빠진 줄 알고 페이지 전환 상태부터 훑었다. 그런데 DOM을 보니 #zoomBar에는 hidden 속성이 정상적으로 붙어 있었다. 상태는 문제가 아니었다.
그제서야 CSS를 의심했다. DevTools에서 확인하니 #zoomBar { display: flex } 가 UA 스타일시트의 [hidden] 규칙을 이기고 있었다. 명시도와 무관하게, display가 지정되면 hidden 속성이 죽는 CSS 동작 때문이다. 이 함정은 이미 겪은 적이 있었다 — #terminal에서 같은 문제가 있었고 override 규칙을 추가했던 것. #zoomBar만 그 처리를 안 받았던 거다.
해법은 단순했다. #terminal에 넣은 것과 동일하게, #zoomBar[hidden]에 display: none을 강제하는 override 규칙을 추가했다. 확인해보니 이제 개발창에선 안 뜨고 맵/워크플로우에서만 노출된다. 이건 두 번째 반복된 함정이라, 다음부터 display: flex를 강제하는 UI는 hidden override를 기본으로 넣어야겠다.
copilot_proposal — “성공했지만 0건” 로그가 가리킨 건 타입 이름 대소문자
장표 병합을 돌렸는데 결과가 이해할 수 없는 상태로 나왔다. 1차 시도는 InvalidArgument로 죽었고, 후보 필터를 완화한 후퇴 시도는 “성공했지만 0건”이었다. 처음엔 “후보 필터가 너무 빡빡해서 다 걸러졌나”라고만 생각했다. 하지만 그렇게 보면 1차에서 왜 Image가 안 걸러져서 InvalidArgument가 났는지 설명이 안 됐다.
로그에 찍힌 타입 분포를 보는 순간 확정됐다.
런타임 값은
"GeometricShape","Image"처럼 대문자 시작인데, 내 필터는"geometricshape"소문자와 비교하고 있었다.
그 결과 1차에선 Image 계열이 필터에 안 걸려 셰이프 API가 잘못된 타입을 받아 터졌고, 후퇴 시도에선 전부 소문자 비교라 후보가 0개가 되어 “성공했지만 0건”이 된 것이다. 타이포 하나가 두 가지 증상을 만들어낸 셈.
수정은 비교 문자열만 실제 런타임 타입 케이스에 맞추는 것으로 끝났다. 그래도 이번엔 오염된 베이스2를 버리고 깨끗한 베이스3 사본으로 처음부터 다시 돌렸다. 확인은 기준을 세워서 — 순서가 HANA → KB → KYOBO, 1번 장에 신한은행 표시, KB 장 그림·디자인 원본 유지 — 끝까지 통과했다.
오늘의 한줄
구조 검증은 분포를 못 보고, CSS는 hidden이 display에 지고, 타입 필터는 대소문자를 외면한다 — 셋 다 “값이 존재하는가”보다 “값이 어떻게 생겼는가”를 봐야 잡힌다.