Files
document-haness/docs/TechLog/tech-log-studio/values-lost-between-boundaries/case/case-a-public-reference-was-entirely-empty.md
T
DongHyeonkaandClaude Opus 5 a8ce0dda07 docs(TechLog): 주제 셋을 스킬대로 다시 쓰고 SSOT 를 저장소 실물로 고친다
건너뛴 참조 다섯을 읽고 나서 다시 썼다 — from-ssot-to-records.md 의 「그림과 증거는
배정 대상이다」, code-tables-diagrams.md 의 표·코드 규칙, explaining.md 의 「이름을
댔으면 왜 있는지도 댄다」.

**SSOT 를 먼저 고쳤다.** §3.3 의 코드블록이 저장소와 달랐다 — PATH_PREFIX_KINDS 는
Record 표가 아니라 튜플 배열이고, 진짜 경로 표는 EXPLORE_KIND_PATHS 다. 저장소에서
확인해 실물로 바꾸고, javadoc 이 적어 둔 이유를 함께 옮겼다. §16.7 에 BRANCH_FIELDS 와
pathOf 실물을, §4.3 에 ContractRouteCoverageTest 의 javadoc 과 면제 상수 둘을 더했다.
62,643 → 65,737 자.

**계약에 ssot-assets·ssot-evidence 를 배정했다.** 그 절차를 건너뛰어서 SSOT 가 이미
가진 그림과 측정이 글감에 배정되지 않은 채였다. TechLog 12 글감, keycloak-session-store
는 그림 21장·증거 19건을 배정하고 붙일 글감이 없는 그림 4장은 이유를 계약에 적었다.
배정하자 검사기가 「배정한 증거를 기록이 쓰지 않는다」 4건을 드러냈다.

**주제 셋을 다시 썼다.**
  hand-listed-kinds            중앙값 1,925 → 3,760 자
  declared-but-not-implemented          → 2,608 자
  values-lost-between-boundaries        → 2,602 자

게시된 기록은 keycloak 4,546 · n+1liner 3,190 이다. 표와 코드를 SSOT 에서 옮기고,
Reference 에 담을 수 없던 표(§5.5 의 여덟 자리)를 짝이 되는 Case 로 내렸다.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-07 18:54:45 +09:00

6.4 KiB

kind, slug, title, topic, topicName, project, status, lastVerifiedOn, sourceRevision, source
kind slug title topic topicName project status lastVerifiedOn sourceRevision source
CASE a-public-reference-was-entirely-empty 공개 Reference 가 통째로 비어 있었다 — 이름이 어긋났고 본문은 다른 테이블에 있었다 values-lost-between-boundaries 값이 경계에서 사라진다 TechLog 게시 전 2026-09-04 tech-log@2026-09-02
final/document.md#§5.1
final/document.md#§6.2

공개 Reference 가 통째로 비어 있었다 — 이름이 어긋났고 본문은 다른 테이블에 있었다

Reference 를 게시했더니 Studio 에서는 모든 칸이 보이는데 공개 화면만 통째로 비어 있었다. 원인이 둘 겹쳐 있었다. 게이트웨이가 읽던 칸 이름이 계약에 없는 것들이었고, Reference 의 본문이 body_markdown 이 아니라 별도 테이블에 있었다. 타입 검사는 as 단언 때문에 아무 말도 하지 않았다.

관계

  • 공개 화면 한 줄이 그려지기까지 값이 지나는 경계 열한 개 이 사건이 그 경계 중 어디에서 났는지가 그 개념에 있다.
  • Studio 에서는 보이는데 공개 쪽만 비면 그 사이에 계약이 있다 이 사건에서 굳힌 진단 규칙이다.
  • TypeScript 가 검사를 놓아 주는 네 곳 as 단언이 어긋남을 가린 것을 그 개념이 설명한다.

문제

Reference 를 공개했다. Studio 편집기에서는 목적·규칙·적용 조건·예외·예시가 다 보이는데 공개 화면은 제목만 있고 아래가 비어 있었다.

DB 에는 작성자가 쓴 값이 그대로 있었다. 두 화면이 같은 데이터를 보는데 한쪽만 비었다.

결론

원인이 둘이었고 서로 다른 경계에 있었다.

게이트웨이가 읽던 이름 : purposeSummary · applyWhenMarkdown · exceptionsMarkdown · examplesMarkdown 계약이 주는 이름 : scopeSummary · appliesTo · excludedScope 결과 : 전부 undefined 로 떨어졌고, as string 단언 때문에 타입 검사가 통과했다

Reference 의 본문은 body_markdown 이 아니라 reference_detail 의 규칙과 예시에 있다. Studio 편집기가 규칙을 제목과 본문으로 나눠 받고 마크다운 본문은 비워 두기 때문이다. 공개 조회는 body_markdown 만 보고 빈 문자열을 내보냈다.

고친 뒤에는 값이 아니라 이름을 지키는 테스트를 뒀다. 계약에서 그 칸이 사라지면 satisfies 가 먼저 깨진다. 값을 검사하는 테스트로는 이 결함이 잡히지 않는다.

검증 환경

tech-log-frontend : 7211dd1 이후 tech-log-design-package : ff0c12a 이후 tech-log-backend : a5f93b9 이후 확인 방식 : 계약이 주는 이름과 게이트웨이가 읽는 이름을 대조

재현 조건

  1. Studio 에서 Reference 를 작성하고 규칙과 예시를 채운 뒤 게시한다
  2. 공개 화면에서 그 Reference 를 연다 — 제목만 보이고 아래가 비어 있다
  3. 게이트웨이 매퍼에서 읽는 칸 이름을 계약의 스키마와 맞춰 본다

본문

계약에 없는 이름을 읽고 있었다

게이트웨이는 응답에서 네 칸을 꺼내고 있었다. 그중 계약에 있는 것은 하나도 없었다.

const summary = body.purposeSummary as string;   // 계약에 그런 칸이 없다

as 는 「이 값을 이 타입으로 다루겠다」는 선언이므로, 컴파일러는 그 이름이 응답 타입에 있는지 묻지 않는다. 실행하면 undefined 가 나오고 화면은 빈 문자열을 그린다.

게이트웨이가 읽던 이름 계약이 주는 이름
purposeSummary scopeSummary
applyWhenMarkdown appliesTo
exceptionsMarkdown excludedScope
examplesMarkdown (해당 칸 없음)

본문이 다른 테이블에 있었다

첫 번째 원인을 고쳐도 본문은 여전히 비어 있었다. 두 번째 원인이 저장 구조에 있었다.

Reference 의 본문은 문서 본문 칸이 아니라 규칙과 예시를 담는 별도 테이블에 들어 있다. Studio 편집기가 규칙을 제목과 본문으로 나눠 받고 마크다운 본문을 비워 두기 때문이다. 공개 조회는 문서 본문만 읽고 빈 문자열을 내보냈다.

한 종류의 저장 구조가 다른 종류와 다르면 조회 쪽이 그것을 알아야 한다. 여기서는 몰랐다.

같은 신호가 여덟 번 더 있었다

계약에 칸이 없어 값이 화면에 오지 못한 것이 이 건 말고도 여덟 번 있었다.

무엇이 비었나 원인
문서 요약(제목 아래 한 줄) 공개 응답에 summary 자리가 없어 유형별 요약을 대신 씀
프로젝트 「주요 주제」 project_topic 테이블도 조인도 가능했는데 응답에 실을 칸이 없었다
프로젝트 기록 목록의 요약·주제·게시일 RelatedEntry 를 그대로 실어 칸이 없었다
질문 목록의 주제 지식 목록은 처음부터 primaryTopic 을 실었는데 질문 목록만 빠짐
프로젝트·주제의 논지 담을 칸이 없어 purpose 를 대신 보여 줌
주제 목록의 논지·축 이름과 개수만 실어, 독자가 들어갈지 말지 정할 근거가 없었다
프로젝트 목록 행의 slug 다른 목록이 프로젝트를 가리킬 때 쓰는 것은 id 가 아니라 slug 인데 행이 싣지 않았다
결정 목록 항목의 slug 공개 주소가 앵커인데 항목에 slug 가 없어 화면이 앵커를 달 수 없었다

문서 요약은 증상이 조금 다르다. 빈 칸에 유형별 요약을 대신 넣었더니 머리말이 바로 아래와 같은 글을 두 번 말했다 — 비어 보이는 대신 겹쳐 보였다.

값이 아니라 이름을 지킨다

고친 뒤에 둔 테스트는 값을 비교하지 않는다. 게이트웨이가 읽는 이름이 계약의 타입에 있는지를 satisfies 로 묻는다. 계약에서 그 칸이 사라지면 컴파일이 먼저 멈춘다.

값을 비교하는 테스트로는 이 결함이 잡히지 않는다. 픽스처를 게이트웨이가 읽는 이름으로 만들면 값이 그대로 나오기 때문이다 — 테스트 작성자와 게이트웨이 작성자가 이름에 대해 합의한 것을 확인할 뿐이다.

확인하지 못한 것

as 단언을 걷어낸 것은 이 매퍼 하나다. 같은 모양이 다른 매퍼에 남아 있는지 전수로 세지 않았다.