"독도 날씨"가 전남 고흥 관측소로 잡히길래 파봤더니 한 건이 아니었다.
KR_CITY_COORDS에 없는 ASOS 지명 66개를 기상청 공식 좌표와 대조한 결과
44개가 틀렸다 — 25개는 Open-Meteo 지오코더가 아예 못 찾고, 19개는
엉뚱한 좌표를 줬다.
홍성 724km / 고산 629km / 보령 551km / 밀양 459km / 서산 / 홍천
→ 전부 북한 동명 지역
동해 408km / 남원 246km / 제천 214km / 상주 188km / 남해 187km
→ 사람들이 실제로 묻는 도시들
이제 ASOS 97 + AWS 745 지점 이름표를 지오코딩 소스로 쓴다. 순서는
손으로 넣은 표 → 지점 이름표 → 지오코더이고, 한글이 섞인 입력만
이름표를 탄다(영문·해외 지명은 종전 경로 그대로). 지점 좌표는 기상청
발표값이라 이 문제가 구조적으로 안 생기고, 날씨를 묻는 맥락에서는
"그 지명의 관측소 위치"가 사실상 정답이다.
고친 뒤 ASOS 97개 전부 공식 좌표 20km 이내로 들어왔다(수정 전 53/97).
같은 이름이 100km 넘게 떨어져 둘씩 있는 3건(진안·옥천·가산)은 이름표에서
일부러 제외했다 — 조용히 한쪽을 고르면 틀렸을 때 드러나지 않는다. 대신
널리 통하는 행정구역 쪽을 KR_CITY_COORDS에 못박았다. 안 그러면 넘어간
지오코더가 옥천을 북한(39.94, 124.53)으로 보낸다. 버린 쪽은 전부 경기도의
동명 지점(진안 439, 옥천 449, 가산 473).
미해결로 남긴 것: 'New York'이 네브래스카의 York로 간다. 영문·해외 지명
쪽 지오코더 문제라 이번 변경 경로와 무관하다(한글 없는 입력은 이름표를
안 탄다).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
tests/
npm test # 전체 실행 (약 0.6초)
npm run test:watch # 파일 저장할 때마다 재실행
npx tsx --test tests/prompt-gates.test.ts # 한 파일만
Node 22 내장 러너(node:test) + tsx. 테스트 프레임워크 의존성 없음 — jest/vitest 설치 불필요.
배경
2026-07-29 기준 이 디렉터리는 비어 있었고, package.json의 test 스크립트는 존재하지 않는
tests/test-v2.ts를, gateway 스크립트는 v4.3.5에서 삭제된 src/gateway/server-v2.ts를
가리킨 채 방치돼 있었다. 즉 npm test가 실행 자체가 안 되는 상태로 몇 달을 보냈다.
그 대가는 명확했다. 같은 날 프롬프트 게이트 정규식을 다섯 번 고치면서, 매번 node -e "..."로
임시 검증 스크립트를 손으로 짜고 버렸다. 회귀 방지는 하나도 남지 않았다.
무엇을 테스트하는가
순수 함수 우선. 이 저장소에서 가장 값어치 있는 테스트 대상은 I/O가 없는 판정 함수들이다:
| 파일 | 대상 | 왜 중요한가 |
|---|---|---|
prompt-gates.test.ts |
src/gateway/guards/prompt-gates.ts |
모델 동작을 강제/억제하는 정규식 게이트. 각 함수는 전부 실제 프로덕션 사고를 겪고 생겼다 |
usage-log.test.ts |
src/providers/usage-log.ts |
Ollama 외 모든 provider의 토큰 집계 단일 지점 |
이 함수들의 회귀는 크래시도 스택트레이스도 없이 조용히 구멍을 다시 연다. 예를 들어
looksLikeUnverifiedSpecClaim이 한 패턴을 놓치면, 모델이 지어낸 수치가 검증 없이 그대로
사용자에게 간다 — 로그에는 아무 이상도 남지 않는다.
케이스 작성 규칙
프로덕션 원문을 그대로 쓸 것. 줄이거나 다듬지 말 것.
[2026-07-29] 태그가 붙은 케이스들은 실제 대화 로그에서 가져온 문장이다. 어색한 표현이
바로 핵심이다 — 정규식이 놓치는 건 언제나 "예상하지 못한 말투"이지 교과서적인 문장이 아니다.
이 규칙은 실제로 값을 했다. 위 테스트를 처음 쓸 때 원문
"...GPU 간 통신 병목으로 인해 토큰 처리 속도 손실이 약 15%~25%..."를
"...토큰 처리 속도 손실이 약 15%~25%..."로 줄여 썼더니 테스트가 실패했고, 그게 진짜
버그였다. 원문에 우연히 들어있던 GPU 덕에 걸리던 것이지, 같은 주장을 한 단어 다르게
쓰면 그대로 통과하고 있었다. (→ SPEC_CONTEXT_KEYWORD에 토큰/대역폭/추론/처리속도 추가)
다음에 추가하면 좋을 것
현재 커버리지는 순수 함수에 한정된다. 아래는 값어치는 크지만 먼저 리팩터링이 필요하다:
skillToolFilter(handle-chat.ts) — 도구 노출을 결정하는 키워드 게이트.handleChat()내부 클로저라 지금은 테스트 불가. 순수 함수로 추출하면 바로 테스트 가능해진다.- 시스템 프롬프트 조립 — 도구 유무에 따른 조건부 블록(
imageEditRuleBlock등). 역시handleChat()내부에 있다. executeWebSearchprovider 폴백 체인 — I/O가 있어 mock 서버가 필요하다.
handleChat()은 단일 함수가 2,959줄이라 위 둘 다 막혀 있다. 그 분해가 테스트 커버리지를
넓히는 가장 큰 지렛대다.