← 미리디 기술 사전

내용시각화 규약 v0.5.6 작성 2026-08-26 · 갱신 2026-09-18

Visual Summary 규약 v0.5.6

사용자가 쓴 글을 컴포넌트로 바꿀 때 구조가 뭉개지는 것이 지금 품질 문제의 핵심이다. Summary 를 Markdown 에서 구조화 형식으로 바꿔 슬롯을 보존하고, 컴포넌트 쪽에는 의미 태그를 붙여 대조한다. 2026-08-04 MORDOR 체크인 덱을 정리하고, 3주 뒤 SSoT 와 대조해 무엇이 바뀌었는지까지 붙였다. 2026-08-29 통합본(visual-summary-overview.pdf, 96쪽)으로 규약 개정 셋 · 강등의 나머지 절반 · PoC 구현물 로직을 반영했고, 2026-09-08 에 구현 폴더와 규약 폴더를 직접 읽어 여섯 구간의 관계(§11) · I.I.S. 와 대치의 연결(§12) · RLSC 가 만나는 자리(§13)를 더했다.

덱 저자 정원석 (MORDOR) SSoT mordor-wiki 대조 시점 2026-08-26 정본 mordor-wiki bbabab9 규약 대조 2026-09-18
§0

30초 요약

  • 문제내용시각화 BAD 의 85% 가 렌더링이 아니라 매칭 문제다. 검색이 컴포넌트를 잘 골라도 그 다음이 정의돼 있지 않다.
  • 원인Summary 가 Markdown 이라 값·단위·계열이 문자열로만 남는다. 「152억」이 숫자인지 텍스트인지 구분이 없다.
  • 처방Summary 를 YAML 구조화 형식으로 바꿔 슬롯을 보존하고(질의 쪽), 컴포넌트에는 semantic tag 를 붙인다(색인 쪽). 둘은 별개 경로이고 BE 검색 모듈에서 만난다.
  • 규약v0.5 는 2026-08-02 확정. 최상위는 항상 components[], type 은 대분류.중분류 문자열 하나, 생성은 LLM 이 YAML 을 직접 쓴다.
  • 보장성립 조건을 못 채우면 fallback 순서로 물러나고 마지막 셋(List · LongFormTextLayout · HighlightedMessage) 은 개수 조건만 보므로 언제나 하나는 성립한다 — 빈 결과가 사용자에게 가지 않는다.
  • 뒤집힘2026-08-03 에 어제까지의 결정이 뒤집혔다. 꾸밈은 등급 하나가 아니라 축 2개 × 값 3개, 계층은 새 필드 없이 entity.components[] 로 간다.
  • 그 뒤3주 사이 2단계는 스킵, 3단계는 취소, 4단계 직행으로 정리됐다. §15
  • 개정2026-08-29 에 type 이 필수가 되고 대분류 단독이 막혔다(0.5.1·0.5.2). 현행은 0.5.6 — 생성기 어휘가 45종에서 36종으로 좁혀졌다. §6
  • 나머지 절반강등은 내용을 옮긴다(P1~P8). 노드가 여럿일 때의 포기 순서(N1~N5)가 2026-08-28 확정됐다. §8
  • 실물PoC 가 생성 → 검색 → 대치 → 채점까지 돈다. 결함의 대부분이 검색 탓(생성 36 · 검색 466 · 대치 17). §11
  • I.I.S.색인 쪽 모듈이다. 컴포넌트 안을 경계 노드로 잘게 나눠 그 서브트리 안에만 채운다 — 검색·대치 규칙은 다시 구현하지 않고 재사용한다. §12
  • RLSC사용자 입력이 RLSC 로 변환되는 것이 아니다. 질의 쪽과 색인 쪽이 BE 검색에서 합류하고, RLSC 는 대치가 채울 슬롯을 대는 쪽이다. §13
확정 · 규약 성립 · 닫힘 열림 · 미정 취소 · 문제

이 문서의 위치

원본 덱도 파생물이고 이 페이지는 그 파생물의 파생물이다. SSoT 는 mordor-wiki / projects/mordor/visual-summary/ 이고, 규약은 spec/schema-v0.5.md, 할 일은 TODO.md 가 갖는다. 숫자나 결정이 여기와 다르면 그쪽이 맞다.

현황

첫 출시 생성 범위가 확정됐다

  • 확정Visual Summary First Release 의 generator 생성 범위는 P0 + 기본/표·차트로 정해졌다 (2026-09-18).
  • 층이 둘같은 45종 목록을 검색·I.I.S. 태깅 층과 생성기 층이 다르게 본다. 불허는 생성기 한 층에서만 걸린다(규약 10.1절). 단어장 P0 20종은 검색 층에서 하나도 빠지지 않는다.
  • 실제 충돌 2종Gauge·RadarChart 가 P0 인데 생성 불허다. 붉은 9종 중 나머지 7종은 단어장도 P1·P2 라 우선순위와 부딪히지 않는다.
  • 기록처범위 명세는 「visual summary 첫출시 시점에 generator에 담을 생성범위 확정」에 적고 허재영님이 완료처리할 예정이다. 규약 폴더에는 아직 그 문서가 없다.

① 두 층은 같은 목록을 다르게 본다

이것을 먼저 잡아야 나머지가 읽힌다. 불허는 생성기 한 층에서만 거른다 — 검색과 I.I.S. 태깅은 45종 전량을 그대로 쓴다.

검색 · I.I.S. 태깅 층

단어장 v2 P0 가 사는 곳

45종 전량 어휘 유지 — Gauge·RadarChart 도 P0 그대로 유효하다. 손그림 게이지·레이더도 Gauge·RadarChart 로 태깅하는 것이 맞다. 노란 5종도 그대로다 — native 여부는 코드가 읽는 사실이지 태깅 기준이 아니다.

결론 — 단어장 P0 20종은 이 층에서 하나도 빠지지 않는다. 단어장(7/30)에는 generatable 열이 없어 이 구분이 아예 안 보인다.

Visual Summary 생성기 층

B-36 불허가 걸리는 곳

P0 20종 중 생성기가 고를 수 있는 것은 18종이다. 빠진 둘은 이렇게 간다.

Gauge → BigNumber (P1 · fallback[0])
RadarChart → ComparisonTable (P0 · generatorRedirect 예외)

P0 요청이 Gauge 면 도착지가 P1 카테고리다 — 우선순위 역전 1건. 스마트 다이어그램 대응이 되면 재검토 없이 어휘로 복귀한다.

② 4색 × 3등급으로 놓으면

색은 생성 가능 여부, 행은 단어장 v2 우선순위다. 두 축은 서로를 참조하지 않으므로 교차해야 실제 범위가 나온다.

등급 허용 · Native 불필요
30종 · 어느 층에서도 안 거른다
주의 · 엔진 있음
6종 · 생성 허용, native Chart 풀 필요
불허
9종 · generatable:false
45종 밖
4종
P0
20종
13 — List ListingTable ComparisonTable Versus SWOT Transformation Steps Staircase Cycle Timeline HighlightedMessage LongFormTextLayout TableOfContents
텍스트·위상 치환으로 대치되는 P0 본대. 충돌 여지가 없다
5 — BarChart PieChart DonutChart LineAreaChart ComboChart
생성기는 허용. 단 손그림 후보에 새 값을 넣으면 정보가 틀린다
2 — Gauge RadarChart
실제 충돌. 아래 ③
0
P1
13종
12 — CombinedResult ProblemSolution BigNumber VennDiagram Pyramid NestedScope SectionDivider Ending QnACard Opening ProfileCard ResumeCV
VennDiagram·Pyramid 는 단어장이 스마트기능 필요로 봤지만, B-36 은 원 2~3개·층이 적어 손그림도 신뢰 가능하다고 「둘 다 가능」으로 뒀다
0 1 — HierarchicalTree
「지금 없음」 — 엔진은 있고 연결 코드(B-13)만 대기. 어댑터가 나오면 복귀한다. P1 이라 우선순위와 안 부딪힌다
0
P2
16종
5 — DialogueChat QuoteTestimonial Funnel FlowChart Fishbone
뒤 셋은 단어장이 스마트기능 필요로 봤으나 B-36 이 「둘 다 가능」으로 내렸다(Funnel 은 2026-09-04 정원석 재검토). 생성은 허용, 단어장 순위는 P2 그대로
1 — StackedBarChart
노란 6종 중 유일한 비-P0. 엔진이 있어(isStacked) 규약 쪽 제약은 없고 순위만 낮다
6 — Quadrant GanttChart Calendar TreeMap PictogramChart BubbleChart
「영구 없음」 — 원본 노드도 vizType 도 없다. 단어장이 이미 뒤로 미뤄 둔 것이라 B-36 불허와 정합한다
4 — Geo 4종
Distribution Location Highlight Flow. 단어장에만 있고 capability 45종 밖이다
겹침 요약내역
노란 6종P0 5 + P2 1 (StackedBarChart)
붉은 9종P0 2 + P1 1 + P2 6
실제 충돌붉은 ∩ P0 = 2종. 둘 다 2026-09-11 「공급 0」 신설 판정분이다
엔진 없음 7종단어장도 P1·P2 — L4·스마트기능 필요 표기와 정합한다

③ 충돌 P0 인데 생성 불허인 둘

단어장은 「쉽다」고 봤고, 규약은 「공급이 없다」로 막았다. 둘 다 스마트기능 불필요로 표기돼 있어서 예측하지 못한 불허다 — 나머지 7종처럼 「L4·스마트기능 필요」로 미리 걸러진 것이 아니다.

종단어장우선순위 이력규약이 막은 이유와 도착지
GaugeL2 (쉬움)v1 P0 → v2 P0 유지엔진 remap 은 있으나 운영 I.I.S. native Chart 풀이 0. 생성기가 고르면 대치 불능 질의가 된다. → BigNumber(P1) — 우선순위 역전
RadarChartL1 (가장 쉬움)v1 P2 → v2 P0 승격같은 이유. → ComparisonTable(P0) — generatorRedirect 로 따로 적은 유일한 예외다. BarChart 로 내리면 축이 붕괴한다

RadarChart 의 P2 → P0 승격이 충돌을 하나에서 둘로 늘린 원인이다. 승격 전이었다면 Gauge 하나만 걸렸다.

④ 노란 6종 — 막히지는 않았지만 조건이 붙는다

생성기는 허용하고 엔진도 있다. 문제는 손그림 후보에 새 값을 넣으면 정보가 틀린다는 것이다. 막대 길이·각도가 값과 무관한 그림에 숫자만 갈아 끼우면 보이는 것과 뜻이 어긋난다.

그래서 native Chart 공급 확보가 P0 달성 조건이다. 노란 6종 중 5종이 P0(BarChart·PieChart·DonutChart·LineAreaChart·ComboChart)이므로, 공급이 안 붙으면 P0 범위를 선언해도 실질이 안 채워진다. 불허 2종과 달리 이쪽은 규약이 막은 것이 아니라 데이터가 비어 있는 것이다.

⑤ 단어장 우선순위가 v1 에서 v2 로 바뀌었다

규약 폴더의 semantic-taxonomy-v7.md 는 2026-08-25 스냅샷(v1) 이라 P0=19 · P1=13 · P2=7 · P3=3 · P4=7 로 적혀 있다. 위 표의 v2 는 그 문서에 아직 반영되지 않았다 — 이 절은 공유된 그림을 기준으로 적었고, 저장소 값과 대조해 차이 셋을 확인했다.

종v1v2무엇이 달라지나
RadarChartP2P0승격. 충돌 종수가 1 → 2 가 된 직접 원인
TableOfContentsP1P0승격. 색 없음(허용)이라 범위에 그대로 들어온다
StackedBarChartP0P2강등. 노란 6종 중 유일한 비-P0 가 된 이유다

v2 등급 체계는 P0·P1·P2 셋뿐이고 합이 49종(45 + Geo 4)이다. v1 의 P2~P4 가 v2 P2 로 합쳐진 모양이지만, 그 합침 규칙 자체는 확인하지 않았다 — 그림이 제시한 것은 최종 배치다.

⑥ 다음에 확인할 것

  1. 범위 명세 문서. 「visual summary 첫출시 시점에 generator에 담을 생성범위 확정」에 Gauge·RadarChart 를 P0 범위에서 빼는지를 명시해야 한다. 안 적으면 다음 사람이 P0 20종 전부로 읽는다. 허재영님 완료처리 예정.
  2. 단어장 v2 를 저장소에 반영. semantic-taxonomy-v7.md 3절이 아직 v1 이다. 반영 전까지는 저장소만 읽는 사람과 이 그림을 본 사람의 숫자가 갈린다.
  3. native Chart 공급. 노란 5종(P0)의 실질을 정하는 값이다. 공급 일정이 첫 출시에 닿는지 확인한다.
  4. Gauge 의 우선순위 역전. P0 요청이 P1 카테고리로 떨어지는 유일한 자리다. 허용할지, 다른 도착지를 줄지 정한다.
  5. 「기본」의 경계. 「기본 + 표/차트」에서 기본이 색 없음 13종을 뜻하는지, 별도 목록인지 확인이 필요하다.

출처 범위 확정과 위 4색 × 3등급 배치는 사용자가 공유한 구현 범위 그림(2026-09-18)과 Slack 대화(miridih.slack.com · C091C6JFYH0)다. Slack 링크를 따로 조회하지 않고 공유된 본문과 그림만 사용했다. generatable 9종·generatorRedirect·불허 사유는 mordor-wiki bbabab9(2026-09-16)의 spec/schema/capability.json 과 spec/capability-table.md 10.1절에서 직접 확인했고 그림과 일치한다. v1↔v2 우선순위 차이 셋은 그림과 저장소 semantic-taxonomy-v7.md 3절을 대조해 이 문서에서 계산한 것이다.

§1

오해부터 지운다 — 두 갈래

덱 p.3

「사용자 입력이 RLSC 로 변환된다」는 사실이 아니다. 경로가 둘이고 서로 별개로 진행된다. 이 그림을 잘못 들고 있으면 뒤의 결정이 전부 이상하게 들린다.

"사용자 입력이 RLSC 로 변환된다" — 아니다. 경로가 둘이고 별개로 진행된다. 질의 쪽 (QUERY SIDE) 사용자 입력을 검색 조건으로 바꾼다 Summary structure 입력마다 새로 만든다 · 생성기(LLM)가 쓴다 규약 = spec/schema-v0.5.md 색인 쪽 (INDEX SIDE) 템플릿 컴포넌트를 미리 검색 가능하게 뽑아 둔다 RLSC Search Signature v2 이미 있는 자산에서 배치로 뽑는다 · 83,771건 적재 태그는 4단계에서 node 단위로 내려간다 BE 검색 모듈에서 합류 질의 쪽 조건 색인 쪽 파생물
structure 에서 RLSC 로 가는 화살표는 변환이 아니라 capability 대조다. 그 규약이 spec/capability-table.md 다.
§2

왜 하나 — BAD 의 85%

덱 p.4

렌더링 문제가 아니다

2026-07-26 BAD 원인 분석. judge 채점 16,819행 집계 + BAD 200건 직접 분류.

→ 85% 가 컴포넌트와 내용이 안 맞는 문제

세부 원인 넷

  • 텍스트 용량 초과
  • 매핑과 위계 오류
  • 슬롯 수 불일치
  • 대치 실패

검색이 컴포넌트를 잘 골라도 그 다음이 정의돼 있지 않아 결과가 나빠지고 있다.

2026-08-03 방향 1.5개월 이내에 구조 불일치를 해결한다. 체감 BAD 50% → 20% 이하가 기대치다.

§3

무엇이 뭉개지나

덱 p.5

같은 입력인데 결과가 둘이다. 차이는 슬롯이 남느냐 하나다.

② MARKDOWN SUMMARY (현행) # 2025 사업 성과 * 총매출 152억 * 온라인 매출 22억 값과 단위, 계열이 문자열로만 남는다. 「152억」이 숫자인지 텍스트인지 구분이 없다. → 검색이 KPI 컴포넌트를 골라도    어느 자리에 152 를 넣을지 모른다 ②' VISUAL SUMMARY (YAML) components:   - type: KPIKeyMetric.BigNumber     structure:       entities:         - { label: 총매출,            value: 152, unit: 억원 } 슬롯이 그대로 남는다. value 가 숫자 자리, unit 이 단위 자리다. ① 사용자 입력 ② Summary ③ 검색 조건 ④ 후보 컴포넌트 ⑤ 대치 파이프라인에서 ②만 바꾼다
바꾸는 것은 파이프라인 ② 한 칸뿐이다. ①·③·④·⑤ 는 그대로 두고 Summary 의 형식만 바꾼다.
§4

로드맵과 태그의 모호성

덱 p.6–7

단계마다 Summary 형식 · 검색 방식 · 태그 범위 셋이 동시에 바뀐다. 아래는 덱 시점(2026-08-04)의 계획이고, 실제로 어떻게 됐는지는 §15 에 있다.

단계Summary검색태그 범위태그가 가리키는 것
1 현행Markdown임베딩 유사도안 단다—
2 목표 8-18Markdownsemantic tag컴포넌트 하나이 컴포넌트 어딘가에 그 타입이 있다
3YAMLtag + structure컴포넌트 하나2단계와 같음
4YAMLtag + node 태그컴포넌트 안 node 마다어느 node 인지 특정된다
5 미정YAML4단계와 같음node 마다4단계 + 카테고리별 property

3단계는 실행하지 않는다

3단계에서 만들 대치 로직이 4단계에서 버려질 수 있다. 정보가 확실한 4단계로 바로 간다 7/24 회의

배포 일정은 다시 봐야 한다 덱 시점

2026-08-03 에 제품 배포가 연기됐다. 2단계 마감 8/18 이 그 연기에 포함되는지 티켓 반영이 없다.

왜 단계를 나누나 — 태그 하나로는 두 경우를 못 가른다

컴포넌트 하나에 태그를 다는 한 — 두 경우가 같아 보인다 경우 A root 자체가 그 타입이라 붙었다 root : ComparisonTable child child 태그 = ComparisonTable 경우 B 하위 어딘가에 그 타입 node 가 있다 root : (분류 없음) ComparisonTable List 태그 = ComparisonTable (같다) 실데이터가 B 를 증명한다 design_object_id 4757227 에 ComparisonTable · HierarchicalTree · List · HighlightedMessage 넷이 함께 붙어 있다. root 가 넷을 동시에 가질 수는 없다. 복수 태그 83,771건 중 260건(0.3%), 최대 4개 4단계에서 node 단위로 태그를 달면 해소된다 그 일을 I.I.S. 가 맡는다
복수 태그가 0.3% 밖에 안 되는 것이 오히려 문제다 — 대부분의 컴포넌트는 태그 하나만 갖고, 그 하나가 A 인지 B 인지 알 방법이 없다.
§5

실증 근거 — 공급과 수요

덱 p.8

설계를 정한 것은 취향이 아니라 이 분포다. 색인에 있는 것은 거의 List 하나인데, 사용자가 원하는 것은 흩어져 있다.

색인 쪽 — 붙어 있는 태그 모수 83,771 design object · 2026-07-22 적재 List 81.1% BigNumber 3.6% Steps 2.4% ListingTable 0.5% 상위 8종이 94.5% 질의 쪽 — 사용자가 원하는 것 List 31.96% ListingTable 15.08% Steps 10.92% ComparisonTable 7.24% 0% 40% 80% 수요는 다양한데 풀이 쏠려 있다 색인은 한 종이 8할을 먹고, 수요는 네 종에 걸쳐 있다 두 판은 같은 눈금(0–85%)과 같은 기준선을 쓴다 · 값은 모두 막대 옆에 직접 적었다
두 판은 같은 가로 눈금을 쓴다. 모든 값이 막대 옆에 직접 적혀 있어 색만으로 읽지 않아도 된다. 붉은 막대 하나가 이 프로젝트가 존재하는 이유다.

이 분포가 설계를 정했다. VennDiagram · Tree · NestedScope · Pyramid 는 각 164건 이하, 데이터 차트는 각 51건 이하다. 성립 조건을 엄격하게 걸면 후보가 0이 되어 전부 List 로 강등된다. 그래서 §7 의 capability 는 성립 조건을 최소로 줄이는 방향으로 설계됐다.

§6

v0.5 가 정한 것

덱 p.9–10 · 2026-08-02 확정
항목결정
최상위 형태항상 components[]. 하나면 길이 1 배열
type문자열 하나로 대분류.중분류. 덱 시점 v7 단어장 49종 중 41종 — 지금은 결합값 45종이고 대분류 단독은 막혔다(0.5.2·0.5.3). 생성기가 고를 수 있는 것은 그중 36종(0.5.6, 아래)
confidence제거. 생성기가 채우지 않는다
alternatives[]신설. fallback 순서보다 먼저 본다
entity.id생성물에서 뺐다. 파싱 뒤 배열 순서로 매긴다
datasetmeasure 와 matrix 두 모양. 표 계열도 matrix
relation.typeintersects 와 compares 둘
생성 방식LLM 이 YAML 을 직접 쓴다. JSON 변환 후 스키마 검증
원소 수 상한두지 않는다. 원소 간 관계는 자리만 예약

검증 실측 스키마 Draft 2020-12 유효성 통과 · 본문 예시 18종 전량 통과 · 부정 사례 12종 의도대로 거부

v0.4 → v0.5, 원문 12건 전량

위 표는 덱이 아홉 줄로 줄인 것이다. 규약 원문 0절이 적어 둔 변경은 열두 건이다.

# v0.4 v0.5
1LLM 이 JSON 을 생성하고 YAML 로 직렬화LLM 이 YAML 을 직접 생성한다. 이유는 추론 속도다
2최상위가 structure(단일) 또는 components[](다중)항상 components[] 배열이다. 하나면 길이 1이다
3component.type enum 11종type 문자열 하나, 대분류.중분류 결합값 45종. 종전에는 대분류 21값을 더해 62값이었으나 2026-08-29 에 뺐다 (6절 상자). v7 단어장 49종에서 지도 전용 4종을 뺀 45종이다 — 지도는 지원하지 않는다(capability-table.md 범위 절)
4component.confidence optional제거했다
5없음alternatives[] 를 열었다. 못 쓸 때 대신 쓸 카테고리를 선호 순서로 적는다
64-1절이 traits(계층, 장식) 도입을 제안도입하지 않는다 → 2026-08-03 에 뒤집혔다 (아래 상자). traits 묶음은 두지 않고 꾸밈은 decoration, 계층은 entity.components[] 로 나눠 갔다. 2026-08-04 에 2절에 반영했다
7dataset.type 3종(gauge, stacked_bar, combo)dataset.shape 2종(measure, matrix)
8relation.type 1종(intersects)2종(intersects, compares)
9entity.id 필수생성물에서 뺐다. 파싱 뒤 기계가 매긴다 (3.2절)
10없음page 수준 relations 를 예약했다. Summary 생성기는 채우지 않는다
113절에 capability 테이블 11행별도 문서 41행으로 분리했다
1211절에 열린 결정 15건TODO.md B절이 SSoT 다

↻ v0.4 → v0.5 변경 12건 · schema-v0.5.md — 원본에서 자동 동기화

type — 단어장 49종에서 왜 8종이 빠졌나

v7 단어장 49종 − 페이지 역할 4종 Opening · TableOfContents SectionDivider · Ending − 지도 전용 4종 Distribution · Location Highlight · Geo_Flow = 41종 capability 대상 왜 뺐나 페이지 역할은 의미 구조가 아니라 페이지에서의 자리다. 지도 전용은 지도 데이터가 있어야 성립해 structure 가 표현할 대상이 아니다. 다시 열린 질문 (B-24) 49종 전량으로 열어야 하지 않나 — 페이지 역할은 색인에 실재한다 (v3.5)
허재영님 지적 2026-08-03. 이 질문은 덱 이틀 뒤에 닫혔다 — 결론은 「49종으로 연다」. §15 참고.
실제 생성물 — 가장 단순한 형태 spec/schema-v0.5.md 8.1절
version: "0.5"
title: 효과적인 회의를 위한 3가지 원칙
components:
  - type: Enumeration.List
    structure:
      entities:
        - { label: 명확한 아젠다, items: [회의 전 안건 공유, 목표 한 문장 정의] }
        - { label: 시간 관리,     items: [시작과 종료 시간 엄수, 항목별 타임박스] }
        - { label: 액션 아이템,   items: [담당자 지정, 마감일 명시] }

2026-08-29 개정 셋 — 회피를 막고, 판번호를 붙였다

v0.5 는 확정 뒤에도 자리에서 네 번 고쳐졌고, 그동안 판번호가 그대로였다. 그래서 「지금 규약이 무엇인가」를 버전으로 가리킬 수 없었다. 2026-08-29 에 세 건을 한꺼번에 고치면서 판번호 규칙을 함께 신설했다.

판무엇을 고쳤나왜
0.5.1 component.type 필수화. 종전에는 optional 이었다 설계 원칙 첫째가 「생성 단계에서 최적 semantic category 를 정한다」인데, type 을 비우는 것은 그 판단을 검색으로 미루는 시각화 책임 회피다. 원칙 1과 optional 은 처음부터 어긋나 있었다
0.5.2 대분류 단독 금지. type 과 alternatives 는 결합값(대분류.중분류)만 받는다 같은 성격의 회피다. 대분류는 그릴 수 있는 표현형이 아니다 — Hierarchy 로는 아무것도 못 그리고 그릴 수 있는 것은 Hierarchy.Pyramid 다
0.5.3 enum 을 결합값 45종으로 반영. 종전 62값(대분류 21 + 결합 41)에서 대분류를 뺐다 PageNavigation 4종이 스키마와 capability.json 에 빠져 있던 격차도 같이 닫혔다
0.5.4 ScopeCoverage.NestedScope 가 children 필수 조건을 버리고 direction(inward/outward) 속성을 신설 필드 하나가 빠지고 하나가 선택 속성으로 늘었을 뿐이라 기존 산출물을 무효로 만들지 않는다 (B-34)
0.5.5 5절에 남아 있던 type “optional” 잔존 문구를 정정하고, 2.5.1 의 어휘 수 41 을 45 로 갱신 규범 내용 변경 없는 문구 정정이라 무효 산출물 0건
0.5.6 생성기 type 어휘에서 9종 제외(첫 출시) — capability.json 에 generatable·generatorRedirect 반영. 함께 생성 시점 쓰기 의무 명문화(B-33) enum 을 줄이지 않는다. 생성기만 부분집합을 쓰고, 쓰기 의무도 생성기 스코프 한정이라 기존 산출물이 소급 무효가 되지 않는다

「못 고르겠다」의 답은 비우는 것이 아니다

필수가 된다고 type 이 지시가 되지는 않는다. 적을 의무만 바뀌고 따를 의무는 그대로다 — 검색은 여전히 성립 조건과 색인 공급을 보고 fallback 으로 벗어난다. 못 고르겠으면 종단 셋 중 하나를 고른다. 셋 다 개수 조건만 보므로 고를 수 없는 입력은 없다.

깨지는 산출물도 없다. 골든셋 v1 의 컴포넌트 470개가 전부 이미 type 을 갖고 있었고 (0.5.1), 결합값 검사에서도 type 454개가 전부 결합값이었다(0.5.2). 생성기 프롬프트도 결합값 45종만 준다. 실제로 지켜지던 것을 규약에 올린 개정이다.

판번호 규칙 — 원리가 아니라 실측으로 가른다

자리언제 올리나예
MAJOR기존 산출물이 실제로 무효가 된다v0.4 → v0.5 의 「최상위가 항상 components[]」
MINOR기존 산출물은 유효하고 새로 쓸 수 있는 것이 는다entities + columns 대안 경로 추가
PATCH유효성이 안 바뀐다. 실제로 지켜지던 것의 명문화위 세 개정 전부

type 필수화는 원리적으로는 required 를 좁히는 변경이지만, 무효가 되는 산출물이 실제로 0건이라 PATCH 다. 실측 없이 좁히는 변경은 MINOR 이상으로 본다. 검증기는 MAJOR·MINOR 만 대조하고 PATCH 는 보지 않는다 — PATCH 가 유효성을 안 바꾼다고 정의해 놓고 patch 차이로 옛 산출물을 떨어뜨리면 자기모순이기 때문이다. 그래서 파일 이름(schema-v0.5.md)은 그대로다.

0.5.6 — 생성기가 고를 수 있는 것은 36종이다

규약 enum 은 45종 그대로다. 줄인 것은 생성기 어휘뿐이고, 그 부분집합을 capability.json 의 generatable 이 정한다(첫 출시 기준 36종). I.I.S. 추출·검색 인식 어휘는 45종 전량이다.

왜 층마다 어휘가 다른가 — 하는 일이 다르다

I.I.S.(색인 쪽) 는 이미 있는 컴포넌트를 알아보는 일이다. 네이티브 엔진이 없어도 「이 도형 배치가 Quadrant 처럼 생겼다」는 인식은 유효하고 검색에 필요하다 — 뺄 이유가 없다.

생성기(질의 쪽) 는 없는 것을 만들어 달라고 쓰는 일이다. 그릴 수단이 없는 카테고리를 고르면 대치가 원천적으로 불가능한 요청이 된다 — 그래서 아예 못 고르게 막는다.

판정 기준은 RLSC 태그 유무가 아니다. I.I.S. 는 RLSC 어휘와 무관하게 구조를 추론할 수 있다. 진짜 기준은 그 카테고리를 뒷받침할 엔진이 어디에든 있는가(RLSC Chart/Table 이든 Smart Diagram vizType 이든)다.

빠진 9종왜생성 재지정
RelationalComparison.Quadrant엔진 자체가 없다 (2026-09-04 확정)
원본 노드도 Smart Diagram vizType 도 없어 지금 수단으로는 못 그린다
—
TimelineSchedule.GanttChart—
TimelineSchedule.Calendar—
ProportionComposition.TreeMap—
ProportionComposition.PictogramChart—
RelationalComparison.BubbleChart—
Hierarchy.HierarchicalTree대치가 안 된다—
AttributeComparison.RadarChart첫 출시 공급 제외 (2026-09-11 추가)ComparisonTable — 다축 보존
KPIKeyMetric.GaugeBigNumber — 3.2절과 같다

RadarChart 만 재지정이 따로 있는 이유

RadarChart 의 fallback 첫 후속은 BarChart 인데, 생성기가 그리로 가면 축이 붕괴한다 — 다축 프로파일이 막대 하나로 뭉개진다. 그래서 생성 재지정만 ComparisonTable 로 따로 뒀다(generatorRedirect). Gauge 는 fallback 순서와 같은 BigNumber 라 예외가 필요 없다.

즉 fallback 순서(검색용)와 생성 재지정(쓰기용)이 갈리는 자리가 생겼고, 그 예외를 데이터로 적어 둔 것이 generatorRedirect 한 줄이다.

0.5.6 — 생성 시점 쓰기 의무 B-33

무시는 읽는 쪽의 기본 동작이지 쓰는 쪽의 허가가 아니다

규약 1절의 「선언되지 않은 것은 무시한다」는 읽는 쪽 규칙이다. 이것을 쓰는 쪽까지 확대해 「어차피 무시되니 적어도 된다」로 읽으면 안 된다는 것이 2026-09-05 확정, 0.5.6 에 정본 반영됐다.

생성기는 그 카테고리가 읽는다고 선언하지 않은 내용 필드에 값을 담지 않는다. 담을 것이 있으면 그 entity 의 items 로 적는다.

왜 그런가 — 생성 경로에는 P3 가 돌지 않는다

projection P3(안 읽는 내용 필드를 items 뒤로 보존)은 fallback 엣지 한정 규칙이다 — 출발→도착으로 카테고리를 바꿀 때 옮길 것을 정한다. 생성기가 처음부터 그 카테고리로 쓰면 옮겨 줄 주체가 없어 내용이 그대로 소멸한다.

실측이 있다 — HierarchicalTree 를 Pyramid 로 재지정한 실행에서 하위 9개가 사라졌다(iui #1023).

B-33 결정문의 「안 읽는 내용 필드는 P3 으로 보존돼 소멸하지 않는다」는 대치 경로 한정이다. 이 의무는 생성기 스코프에만 적용하고, 색인 검색·대치 경로는 그대로 두며(「빈 결과보다 낫다」), 이미 만들어진 산출물을 소급해 무효로 보지 않는다. 생성 단계 검증이 이것을 재시도 사유로 볼지는 구현(I-16·I-17)에서 정한다.

version 은 LLM 이 쓰지 않는다. 프롬프트가 「쓰지 말라」고 지시하고 후처리(generator/postprocess.ts)가 상수를 붙인다. 2026-08-20 100회 실행에서 모델도 100/100 정확히 적었으므로 품질 개선이 아니라 책임 분리다 — 모델이 판단할 것이 아닌 값은 모델에게 맡기지 않는다.

§7

capability 와 fallback

덱 p.11–12

카테고리마다 셋을 선언한다. 요구 등급을 필수·선호·무시로 나누는 대신, 성립 조건은 최소로 줄이고 나머지는 기본값을 가진 선택 값으로 옮겼다.

선언무엇인가못 채우면
성립 조건이게 없으면 그 종류로 배치가 불가능한 것그 종류가 후보에서 빠진다
선택 속성안 적어도 되는 것. 규약이 기본값을 정해 둔다기본값으로 그린다
fallback 순서그 종류가 색인에 없을 때 물러날 곳순서를 따라 내려가고 마지막은 항상 List

성립 조건을 최소로 줄였다

내용을 요구하는 것은 넷뿐이다 — BigNumber·Gauge 의 수치, HierarchicalTree 의 children, ComboChart 의 혼합 조건, 그리고 페이지 역할 쪽 3행.

NestedScope 는 0.5.4 에서 children 요구가 빠져 다섯에서 넷으로 줄었다 — 동심원은 가변 깊이 트리가 아니라 배열 순서만 있으면 되는 구조라서다.

나머지는 개수와 matrix 유무만 본다.

기본값 규칙

기본값은 표현 선택에만 준다. 내용에는 주지 않는다.

apex(어느 쪽이 꼭대기인가) → 기본값 OK

value(숫자가 얼마인가) → 없는 데이터를 지어내는 것이므로 성립 조건

fallback — 빈 결과가 사용자에게 가지 않는다

예시 — 게이지를 원했는데 색인에 없을 때 Gauge BigNumber List 근접도 순서만 지키면 몇 칸이든 종단이 셋이다 — 셋 다 개수 조건만 본다 Enumeration.List entities 가 2개 이상 TextBasedCommunication.LongFormTextLayout 1개이고 여러 문장 TextBasedCommunication.HighlightedMessage 1개이고 한 문장 언제나 하나는 성립한다. 그래서 대치 실패 정책을 따로 두지 않았다 — 빈 결과가 사용자에게 갈 길이 없다. 모든 structure 는 리스트로 읽히는 entities 를 가진다. dataset 만 있으면 거기서 파생한다.
덱 시점의 fallback 맵은 엣지 55개였고, 손으로 쓰지 않고 규칙 여덟 개를 세운 뒤 각 엣지에 어느 규칙이 걸리는지를 capability 에서 계산했다. 그래서 표가 capability 와 어긋날 수 없다. (지금은 45종·엣지 130개다 — §15)

계산 중에 결함 하나가 드러났다

「선택 속성」열이 내용 필드(period, speaker)와 표현 선택(orientation, apex)을 섞어 담고 있었다. 그대로 계산하면 Timeline → Steps 에서 시각(period)을 버리게 된다. 갈라서 내용은 옮기고 표현만 버리도록 고쳤다.

§8

강등이 옮기는 것 — projection · 복잡도 · 복합 구조

2026-08-28 · 08-29 신설

앞 절이 어디로 내려가나였다면 이 절은 내려갈 때 내용이 어떻게 되나다. 덱에는 이 절반이 없었다. 그 사이에 규칙 이름이 붙고(P1~P8), 질의가 얼마나 복잡해질 수 있는지가 레벨로 묶였고(L1~L3), 노드가 여럿일 때 어느 것부터 포기하는지가 2026-08-28 에 확정됐다(N1~N5).

projection — 내용은 버리지 않고 옮긴다

fallback 은 카테고리를 바꾸는 일이라 출발 카테고리가 쓰던 필드를 도착이 못 읽는 경우가 생긴다. 이때 어디로 옮기는지를 정하는 것이 규칙 여덟이다. 버리는 규칙은 P2 하나뿐이고 나머지 일곱은 전부 옮기는 규칙이다.

규칙무엇을 하나
P1entities 는 그대로 간다. 순서와 label·items·children 은 어느 엣지에서도 손대지 않는다
P2도착이 선언하지 않은 params 는 버린다. 표현 선택이지 내용이 아니기 때문이다
P3도착이 안 읽는 내용 필드는 그 entity 의 items 맨 뒤에 이름: 값 으로 붙인다
P4matrix 를 못 읽는 곳으로 가면 entities 로 편다. 첫 열이 label, 나머지가 items
P5measure 를 못 읽는 곳으로 가면 value·unit 을 entity 로 옮긴다. 나머지는 P3
P6entities 만 있는데 matrix 가 필요하면 행으로 편다
P7도착이 관계를 못 그리면 relation.desc 를 of 첫 항목의 items 맨 뒤로 보낸다
P8도착의 개수 상한을 넘으면 초과분을 마지막 항목의 items 로 접는다
P9 제안measure → matrix 필수인 곳. value 를 1행짜리 matrix 로 접는다 (Gauge → PictogramChart 근거)
P10 제안matrix → measure 필수인 곳. 대표값 1행을 value 로 쓴다. 대표값 고르는 기준(첫 행·합계·최대값)이 아직 없다
출발 → 도착걸리는 규칙무엇이 옮겨지나
BarChart → ListP1 P2 P3 P4matrix 행이 entities 가 되고 unit·value 가 items 로 간다. orientation·sort 는 표현 선택이라 버린다
BigNumber → HighlightedMessageP1 P2 P3 P5 P8value·unit 이 entity 로 옮겨지고 delta·emphasis 도 함께 간다. 1개를 넘으면 나머지는 마지막 항목으로 접는다
ComparisonTable → VersusP1 P2 P4 P8matrix 행이 entities 가 되고, Versus 는 정확히 2가 조건이므로 초과분을 마지막 항목에 접는다

복잡도 레벨 셋 — 산출물의 모양이 아니라 생성기에 허용된 범위

레벨은 산출물 한 건을 분류하는 이름이 아니다. 누적이고(L1 ⊂ L2 ⊂ L3), 그래서 L3 를 켠 생성기가 컴포넌트 하나짜리를 내는 것은 정상이다. 「질의」라고 부르지 않는다 — 검색용 질의로 바뀌는 것은 질의 변환기를 거친 뒤다.

레벨이름최상위 components[]entity.components[]그 레벨을 켜려면
L1단일 컴포넌트길이 1안 쓴다없음 지금 도는 것이 이것이다
L2병치 위상여럿 허용안 쓴다조각마다 검색을 호출하고 결과를 한 페이지로 조립하는 오케스트레이션(I-11)
L3전체 위상여럿 허용쓴다위의 것 전부 + 중첩 후보의 대치 로직(D-7) + N3·N4 반복 시 최상위 원소 수 상한(B-32)

레벨을 가르는 축은 하나다 — 컴포넌트 경계를 넘는 계층(entity.components[])을 쓰느냐. 같은 컴포넌트 안 계층(entity.children[])은 어느 레벨에서나 쓴다. 그것은 내용 구조이지 위상이 아니다.

생성기가 둘이고 지금 레벨이 서로 다르다

실서비스 Summary 생성기(허재영·황현진)는 L2 까지다 — 규약 1절이 「entity.components[] 를 채우지 않는다」고 정한 그 생성기다. PoC 생성기(정원석)는 이미 L3 를 낸다. 프롬프트에 ## 이종 컴포넌트 절이 있고 골든셋에 중첩 산출물이 들어 있다.

그래서 「L3 는 자리만 열려 있다」는 말은 생성 쪽에는 더 이상 맞지 않는다. 비어 있는 것은 그다음 두 칸이다 — 조각을 조립하는 오케스트레이션(I-11)과 중첩 후보의 대치 로직(D-7). 4단계 실서비스에서 어느 레벨까지 켤지는 정해진 바 없다.

복합 구조 fallback — 노드가 여럿일 때 어느 것부터 포기하나

앞 절의 사다리는 노드 하나의 카테고리를 내리는 규칙이다. 질의가 중첩이나 병치로 노드를 여럿 가지면 그것과 별개로 포기 순서가 필요하다. 2026-08-28 확정, SSoT 는 capability-table.md 3.6절이다. 위에서부터 시도하고 후보가 나오면 멈춘다.

단계무엇을 하나잃는 것
N1질의 트리 전체를 그대로 담은 후보를 색인에서 찾는다없다
N2트리 모양을 고정한 채 노드마다 앞 절의 fallback 순서를 따라 내려간다노드마다의 카테고리 표현
N3가장 바깥 부모를 벗겨 자식을 최상위 components[] 로 올리고 N1 부터 다시벗긴 부모의 카테고리 표현과 형제 사이의 인접성
N4남은 노드가 모두 단일 카테고리가 될 때까지 N3 을 반복한다위와 같다. 깊이마다 한 번씩
N5규약 1절 「중첩은 평탄화된다」대로 자식 entities 를 부모 items 로 편다자식 전부의 카테고리 표현

왜 위부터 벗기나

부모를 벗기면 질의 하나가 여럿으로 갈라져 후보 풀이 커지고, 자식의 내용과 카테고리 표현은 전부 남는다. 반대로 자식을 벗기면 내용을 지불하는데 부모는 여전히 복합 구조라 매칭 난이도가 그대로다. 내용을 내주고 검색 가능성을 못 얻는다.

왜 평탄화가 마지막인가

평탄화와 떼어내기는 둘 다 텍스트를 하나도 버리지 않는다. 다른 것은 표현이다 — 평탄화는 자식의 카테고리 표현을 잃고 부모의 배치를 지키며, 떼어내기는 그 반대다. 표현을 더 많이 남기는 쪽을 먼저 두기로 정했다.

#붙는 규칙 여섯
N-R1벗긴 부모의 label·items·relations[].desc 는 버리지 않고 승격된 첫 조각의 첫 entity items 맨 뒤로 (P3·P7 과 같은 방식)
N-R2형제는 큰 묶음부터 그리디로 나눈다. 4형제면 [4] · [3,1] · [2,2] · [2,1,1] · [1,1,1,1] 순. 연속한 형제만 묶고 순서를 바꾸지 않는다
N-R3색인 어휘의 Unclassified 는 카테고리가 아니라 경계다. 질의 type 이 될 수 없다
N-R4N 단계 수와 카테고리 강등 칸 수는 서로 다른 예산이다. N3 한 번이 강등 칸을 소모하지 않는다
N-R5 미확정부모 대분류가 Hierarchy 면 N3 을 건너뛰고 N5 로. 깊이 3 이상 계층 질의가 실측에 없어 판정 근거가 없다(B-31)
N-R6N2 의 조합 순서는 강등 칸수 합이 작은 것부터. 합이 같으면 뿌리에서 먼 노드를 먼저 내린다 — 뿌리를 내리면 자식 슬롯이 함께 바뀌기 때문이다

이종 질의는 실질적으로 N3 에서 시작한다

D-7 이 이종중첩 템플릿을 검색 풀에서 제외하기로 확정했으므로(2026-08-11, 전체 약 2%), 뿌리가 Unclassified 인 템플릿이 후보로 걸리지 않는다. 그래서 N1 은 지금 정책상 언제나 비어 있고, 모양이 이종중첩인 채로 남는 N2 도 후보가 0이다. 동종중첩은 D-7 밖이라 N1·N2 가 살아 있다.

D-7 의 결정 근거가 「대부분 조합 fallback 만으로 해결될 것으로 예상」이었으므로, N3~N5 의 결과 품질이 그 예상의 검증 자료가 된다. 되돌릴지는 열려 있다(D-8).

alternatives 와 fallback 순서는 보는 것이 다르다

fallback 순서alternatives
어디 있나capability 상수. 카테고리마다 미리 박혀 있다생성물. 입력마다 다르다
무엇을 보나카테고리 대 카테고리만그 입력의 내용을 본다
언제 정하나규약을 쓸 때 한 번생성할 때마다

Gauge → BigNumber → List 는 게이지에 무엇이 담기든 같다. 반면 생성기는 입력을 이미 읽었으므로, 같은 Hierarchy.Pyramid 라도 층마다 크기 차이가 의미를 지니면 Staircase 가 낫다는 것을 안다. 다만 이것은 가정이고 실측이 없다 — 생성기가 고른 alternatives 가 정적 순서보다 나은지 검증된 적이 없어 optional 로 열어 두고 생성기 정책으로 켜고 끈다.

SSoT — projection 은 규약 5절, 복잡도 레벨은 규약 8.8절, 복합 구조 순서는 spec/capability-table.md 3.6절. 코드는 projection.ts(P1~P8 계산·적용) · fallback.ts(카테고리 확정)이고, N1~N5 는 규약만 확정되고 코드는 미착수(I-11)다.

§9

꾸밈구조 — 뒤집힌 결정

덱 p.13–18 · 2026-08-03

덱에서 가장 중요한 부분이다. 어제까지의 결정이 하루 만에 뒤집혔다.

항목2026-08-022026-08-03
계층structure 에 선언하지 않는다컴포넌트를 nested 구조로 두어 해결한다
꾸밈질의 쪽 필드를 두지 않는다꾸밈구조를 둔다. 다만 1단계는 전역 기준만

뒤집은 이유 1

8/2 결정이 판정 책임을 색인 쪽으로 넘겼는데, 색인 쪽에 그것을 받을 선언이 없었다.

capability-table.md 에 꾸밈 언급이 0건이었다.

뒤집은 이유 2

그 결정의 근거표가 보존 전용 문서에만 있었다.

허브가 「v0.5 는 이 철학을 따르지 않는다」고 적어 둔 문서다.

왜 등급 하나로는 안 되나

7/24 회의의 N / N+α / N+β 는 누적 등급이다 (N ⊂ N+α ⊂ N+β). 여기에 네 가지 문제가 있었다.

1. 다른 것이 섞인다

N+β 가 「요소 배치와 장식」이다. 배치가 정교한데 그림이 없는 컴포넌트가 있다.

2. 조합을 못 적는다

「배경은 원하지만 일러스트는 싫다」에 이름이 없다.

3. 끼울 자리가 없다

배경·테두리·아이콘이 생기면 「N+β 안쪽」이라 할 수밖에 없다.

4. N 은 애초에 꾸밈 축이 아니다

N 의 「최소 필요 조건」은 capability 성립 조건과 같은 대상이다. 등급 최하단에 두면 같은 사실이 두 곳에 생긴다.

그래서 축 집합으로 둔다

꾸밈구조 — 축 하나가 RLSC role 하나에 대응한다 component.decoration
decoration:                # 꾸밈구조 하나
  ornament: prefer          # 꾸밈 축 하나 + 선호값 하나 → Element.Decoration
  background: avoid         # 꾸밈 축 하나 + 선호값 하나 → Element.Background

선호값은 셋이다

  • prefer — 있으면 가점
  • indifferent — 보지 않는다 (기본값)
  • avoid — 있으면 감점

require 를 두지 않는다. 꾸밈을 필수로 걸면 후보가 0이 된다.

축이 role 하나를 가리키는 이유

축이 RLSC role 하나에 정확히 대응하면 추출이 이미 붙인 표식을 그대로 쓸 수 있다.

minimal(N)·rich(N+β)는 문서와 회의에서 부르는 별명이고 스키마 값이 아니다 — 축이 늘면 뜻이 바뀌기 때문이다.

판정 기준 하나로 축이 갈린다

대치가 이 노드를 내용으로 채우는가? 이 질문 하나가 축의 유무를 정한다 채운다 안 채운다 축 아님 — 내용이 이미 답이다 Element.Title · Subtitle · Description → entity.label 과 entity.components[] 가 담는다 Element.Highlight → entity.emphasis 가 이미 있다 축 필요 — 입력에 대응물이 없다 Element.Decoration → decoration.ornament (role 정의: "내용 대치 시 변경 불필요") Element.Background → decoration.background 부수 효과 N+α(타이틀·디스크립션 등급)는 개념 자체가 사라졌다. 표현 밀도가 아니라 내용 유무이기 때문이다.
기준이 「표현 밀도」에서 「대치가 채우나」로 바뀌자 등급 세 층이 축 두 개로 접혔다.

1단계 범위 — 전역 기준만 잡는다

층1단계 (지금)요소 대치 착수 후
Summary (질의)생성하지 않는다. 스키마에 optional 로 자리만필요하면 생성기가 적는다
카테고리 기본미정45종에 채운다
시스템 전역 기본여기만 잡는다 (예: 꾸밈 많은 것을 우선)유지

왜 미루나

  • 지금 소비할 주체가 없다. 요소 대치가 아직 동작하지 않는다
  • 색인이 대조할 대상을 못 받는다
  • 지금 필요한 것은 전역 기준 하나로 된다

선례가 있다

entity.components[] 와 page relations 가 모두 「스키마에 열어 두고 생성기는 채우지 않는다」.

decoration 도 같은 방식으로 연다.

§10

다섯 구간이 다 붙어야 돈다

덱 p.19–20

꾸밈구조를 실제로 쓰는 곳은 요소 대치다. 그런데 그게 돌려면 앞뒤 다섯 구간이 전부 대응해야 한다. 덱 시점에 한 구간이 끊겨 있었다.

추출 노드에 Decoration · Background role role 은 이미 붙는다 색인 그 role 을 얼마나 가졌는지 담는다 경로가 없다 text_map·text_node_roles· semantic_tags 는 있는데 노드 분류 자리가 없다 검색 기본값과 선호를 대조해 순위를 움직인다 capability 에 꾸밈 축 열이 없다 Visual Summary 그 입력의 선호를 적는다 표기 미정 (B-18) 대치 선호에 맞춰 role 노드를 지우거나 남긴다 아직 동작하지 않는다 색인 경로가 먼저 풀려야 나머지가 동작한다. 추출이 role 을 붙여도 색인이 못 받으면 검색이 대조할 대상이 없다. 해법 선례는 semantic_tags denormalize 방식이다 — 그 표를 색인 테이블에 펴서 담는 것. 할 일: TODO.md I-4, B-22
점선 화살표가 끊긴 구간이다. B-18(표기)은 덱 당일 닫혔고, B-22(색인 경로)는 2026-08-26 기준 아직 열려 있다.

요소 대치 — 꾸밈구조를 쓰는 곳

신동한님 쪽 모듈(AI 꾸미기)을 참고해 구현하기로 했다 2026-07-23 회의. 흐름은 넷이다.

①②③④
reference design
template / page / component
교체 target
AI 가 식별
query · embedding
교체 대상 서술
확정 제약
size 등

난점은 ②와 ③이다

7/23 회의 원문: 「비슷한 요소 찾기 사용. 다만 교체 타겟 결정 및 타겟별 query 생성이 중요」

검색 자체보다 무엇을 바꿀지 정하고 어떻게 서술할지가 문제다.

정하지 않은 것

reference design 이 꾸밈 수준을 이미 정해 버리면 꾸밈구조는 요소 대치에 안 쓰이고 검색 단계에만 쓰인다.

7/23 기록은 「장식 요소는 유지하고 내용 관련 요소만 대치」다.

§11

구현물 로직 — PoC 파이프라인

2026-08-29 통합본 4절

이 구간에 없던 것은 구현이 아니라 규약이었다

이석님의 packages/comp-sign 이 시그니처 추출 · 검색 · 랭킹 · 내용 대치 네 단계를 이미 구현하고 있다. 비어 있던 것은 「고른 다음에 무엇을 어디에 어떻게 넣을 것인가」의 규약이다. 그래서 PoC 의 목적은 데모가 아니라 스쿼드가 못 닫고 있는 결정을 실측으로 닫는 것이고, 화면이 있는 이유도 보여 주기 위해서가 아니라 판정 이력을 사람이 열어 볼 수 있게 하기 위해서다.

전체 흐름 여덟 단계

사용자 글 한 덩어리 → 결과물과 결함 채점표src/lib/visual-summary/pipeline.ts
사용자 입력
  → ① LLM YAML 생성    generator/       LLM 이 YAML 을 쓴다 · 재생성 루프
  → ② 검증            validate.ts      파싱 → id 부여 → zod → capability
  → ③ 카테고리 확정     fallback.ts      성립 조건 + 자기 행 fallback + projection
  → ④ 검색 질의 변환    query.ts         structure → 태그·제약 (④ 는 ⑤ 의 입력)
  → ⑤ 실색인 검색      search.ts        태그 군 우선 · 군 안에서 구조 적합도
  → ⑥ 내용 대치        binding.ts       RLSC 슬롯에 직접 삽입 (규약 경로)
  ┈┈┈┈┈┈┈ 여기까지가 질의 갈래. 아래는 실서비스 경로와의 대조 ┈┈┈┈┈┈┈
  → ⑦ comp-sign 비교   markdown.ts → compSignService.ts → intersect.ts
                             structure → markdown → textTree → 구조 검색·대치
  → ⑧ 렌더·채점        sheet.ts · audit.ts   같은 기준으로 두 경로를 비교

여섯 구간의 관계 — 무엇이 무엇의 입력인가

각 구간은 앞 구간의 산출물만 입력으로 받는다. 그래서 어느 구간이 나빴는지를 뒤의 귀속 채점이 가를 수 있다. 모듈 이름은 전부 src/lib/visual-summary/ 기준이다.

구간모듈입력 → 산출물이 구간이 지키는 계약
① LLM YAML 생성 generator/
prompts/system.md
vocabulary.ts
generate.ts
사용자 글 → YAML 문자열 어휘 45종(41 + PageNavigation_* 4)만 준다. version 은 LLM 이 쓰지 않고 postprocess.ts 가 상수로 붙인다. 스키마 위반은 오류 문장을 되먹여 재생성
② 검증 parse.ts
assignIds.ts
schema.ts
validate.ts
capabilityCheck.ts
YAML → VisualSummary 객체 파싱 → id 부여(e1.., relation of label→id) → zod → 카테고리별 정합. silent corruption 을 따로 센다 — 파싱은 됐는데 값 타입이 조용히 바뀐 것
③ 카테고리 확정 capability.ts
establish.ts
projection.ts
fallback.ts
구조 → 확정 카테고리 + 투영된 구조 요청 카테고리는 원 구조로, 도착지는 투영(P1~P8) 뒤 구조로 성립을 본다. 자기 행만 끝까지 타고 도착지 행으로 갈아타지 않는다
④ 검색 질의 변환 query.ts 확정 결과 → 태그 군 + 제약 항목 수·글자 용량 제약과 태그 군(tier) 을 만든다. structureDigest 는 comp-sign structureHash 자리 표시다 — 실물이 오면 이 함수 하나만 바꾼다
⑤ 실색인 검색 search.ts 질의 + 색인 → 후보 순위 군이 점수보다 절대 우선하고, 군 안에서 구조 적합도(단위 수·글자 용량·슬롯)로 채점. 이 모듈은 DB 를 모른다 — 색인을 배열로 주입받는다
⑥ 내용 대치 rlsc.ts
binding.ts
구조 + 후보 RLSC → 대치된 RLSC 검색과 같은 단위 정의(detectUnitLayout)를 쓴다 — 점수가 좋다고 판단한 구조 그대로 채워진다
⑦ comp-sign 비교 markdown.ts
intersect.ts
api/…/compSignService.ts
구조 → markdown → 실서비스 경로 결과 같은 입력을 실서비스 경로로도 돌려 나란히 놓는다. 교집합과 RRF 순위 융합으로 판정 지표를 만든다

④ 와 ⑤ 사이가 이 PoC 의 경계다

pipeline.ts 가 조립하는 것은 ① 부터 ④ 까지다. 코드 머리말이 그대로 적는다 — 「색인 갈래(RLSC, Search Signature)와 실제 검색 실행(BE)은 범위 밖이고, 그 경계까지의 산출물(질의)을 만든다」.

⑤ 이후는 PoC 가 BE 를 대행하는 구간이다. search.ts 는 실서비스 rankCompCandidates() + BE 검색의 자리를 대신하되 계약의 핵심 둘(군 우선, 군 안 채점)만 재현한다.

⑦ 이 별도 구간인 이유 — 같은 입력을 두 경로로 돌린다

comp-sign 은 Visual Summary YAML 을 직접 받지 않는다. 유일한 진입 방언이 parseSummaryTree(markdown) 라서, markdown.ts 가 다리를 놓는다 — structure → markdown → buildCompSearchData → textTree.

그래서 ⑥(규약 RLSC 대치)과 ⑦(comp-sign 대치)은 경쟁 관계가 아니라 대조 관계다. ⑥ 은 MORDOR PoC 전용 베이스라인이고 실서비스가 쓰는 대치는 ⑦ 의 buildContentReplacement() 하나뿐이다. 둘을 같은 후보 풀·같은 용량 근거로 재야 판정이 성립한다.

버전 제약이 하나 걸려 있다 — nexus 배포판이 4.3.5(SIGNATURE_VERSION 36)라 파이프 표(격자 leaf)와 헤딩 H 마킹이 없다. 그래서 markdown.ts 는 표를 파이프 표가 아니라 중첩 리스트로 직렬화한다. 4.3.8 이 배포되면 바꾼다.

「PoC」가 어디까지 임시인가

구간상태설명
Visual Summary 생성실서비스 코드실제 OpenAI 호출과 프롬프트, 재생성 루프가 그대로 돈다
검증 · 카테고리 확정 · 질의 변환실서비스 코드규약을 코드로 옮긴 것. 문서와의 정합을 테스트가 기계로 대조한다
시그니처 색인계산은 실서비스 · 저장은 PoC실제 createCompSignatureBuilder() 로 만들지만, 실서비스는 테이블에 미리 적재하고 PoC 는 서버가 뜰 때 메모리에 즉석으로 만든다
후보 조회PoC 코드실서비스는 BE 가 DB 를 조회하는데 PoC 는 메모리 안에서 해시를 맞춰 본다
랭킹·대치 (구조 검색)실서비스 코드rankCompCandidates, buildContentReplacement 를 그대로 호출한다. 내용시각화 BE 가 쓰는 4단계 경로다
랭킹·대치 (시멘틱 검색)PoC 자체 구현검색 search.ts, 대치 binding.ts. comp-sign 이나 BE 경로가 아니다
결함 채점자체 구현실서비스에 대응물이 없는, 이 PoC 가 새로 만든 계측기

색인 규모는 로컬 태깅 컴포넌트 2,468건(시그니처 3,424벌 · 고유 구조 해시 668개 · 빌드 33초 · 30분 캐시). 실서비스는 178,095건이라 이 방식을 그대로 쓸 수 없고, 그것이 아직 스쿼드가 정해야 할 열린 결정이다. 범위 밖 — 차트·이미지 데이터 대치, 색상 대치, 실제 테이블 적재, 백엔드 검색 실행.

왜 검색 경로를 두 갈래로 나란히 두었나

시멘틱 검색 자체 구현

design_object_semantic_tags 의 의미 태그로 후보를 찾는다. 태그가 맞는 후보를 먼저 채우고, 그 안에서 항목 수와 글자 용량이 얼마나 맞는지로 점수를 매긴다.

구조 검색 comp-sign 실코드

의미 태그를 보지 않는다. 내용을 markdown 으로 바꿔 comp-sign 에 넣으면 구조 해시와 변형이 나오고, 해시가 정확히 일치하는 컴포넌트를 채점 항목 20여 종으로 순위 매긴다.

두 축이 깨끗하게 갈린 것이 뜻밖의 자산이 됐다. 스쿼드가 합의한 판정 지표가 「두 검색의 교집합 상위 10건 품질」인데, 이 PoC 에 그 두 검색이 각각 실서비스 코드로 있어서 교집합을 실제로 계산할 수 있다.

두 경로를 잇는 다리는 markdown 이다

comp-sign 의 입력은 markdown 인데 Visual Summary 는 항목 트리를 내놓는다. 그 사이가 structure → markdown 변환이다. 트리를 직접 조립하지 않고 markdown 을 거치는 이유는 comp-sign 이 트리와 해시를 같은 파싱 과정에서 만들기 때문이다 — 트리를 직접 만들면 해시 경로와 어긋날 수 있다고 패키지 소스가 명시한다.

결함 16종과 심각도

이전 라운드에서는 대치 결과 23장을 손으로 봤다. 결함을 실제로 찾아냈지만 코드를 고칠 때마다 23장을 다시 볼 수 없어 「이 변경이 좋아졌나」를 말할 수 없었다. 그래서 같은 판정 기준을 기계로 옮겼다. 16종 각각이 §2 의 원인 넷 중 하나에 대응한다.

원인결함무슨 일이 벌어진 것인가
텍스트 용량 초과capacity.lineOverflow넣은 글이 그 자리의 줄 수를 넘는다
capacity.charOverflow줄 수를 모르는 자리에서 글자 수가 용량을 넘는다
매핑과 위계 오류mapping.categoryDrift규약이 허용하지 않는 카테고리의 컴포넌트를 골랐다
mapping.roleInversion제목에 들어갈 내용이 설명 자리로 내려간다
mapping.markerAbuse순서 번호 자리에 문장이 들어간다
mapping.orderInversion화면 순서가 입력 순서와 뒤집힌다
슬롯 수 불일치slots.unitDeficit항목이 칸보다 많다
slots.unitSurplus칸이 항목보다 많아 빈 칸이 남는다
slots.lineDeficit여러 항목이 한 자리에 접히거나 아예 버려진다
slots.lineSurplus채우지 못한 텍스트 자리가 남는다
대치 실패replace.residue결과에 남은 글이 사용자 입력에서 온 것이 아니다
replace.placeholdercomp-sign 이 임시 문구로 채웠다
replace.emptied채울 내용이 없어 템플릿 원문을 비웠다
replace.markupLeakmarkdown 표기가 결과 글에 그대로 나갔다
replace.unmapped대치할 텍스트를 실제 요소에 못 붙였다
replace.contentLoss사용자가 넣은 조각이 결과 어디에도 없다

심각도는 셋이다 — blocker ×5(사용자 내용이 사라졌거나 남의 내용이 남음), major ×2(위계 어긋남), minor ×1(빈 자리·임시 문구). 결함 수를 그냥 더하면 가벼운 결함이 많은 결과가 더 나빠 보이므로 가중치를 곱해 더한다.

설계 원칙은 하나 — 런타임 랭킹이 최적화하는 바로 그 양을 잰다

넘침 판정을 comp-sign 채점과 같은 계산으로 맞췄다(글자 수가 아니라 줄 수 기준). 자리마다의 용량도 comp-sign 시그니처가 담은 값을 두 경로 모두에서 그대로 쓴다. 이게 성립하려면 RLSC 노드 식별자와 sheet 요소 식별자가 같아야 하는데, 색인 2,468건의 텍스트 자리 17,899개 전량에서 결합률 100% 였다.

기계 채점을 그대로 믿지 않고 눈으로 확인해 잘못 잡은 것 셋을 걷어냈다 — 순서 번호를 「입력에서 오지 않은 글」로 세던 것, 정상 배치를 위계 어긋남으로 세던 것, 잔존 템플릿에 markdown 기호가 있으면 한 결함을 두 번 세던 것. 셋 다 회귀 테스트로 고정했다.

결함을 생성 · 검색 · 대치 중 누구 탓으로 돌리나

귀속은 단일 결과가 아니라 대안과의 비교에서만 나온다. 두 경로 다 상위 후보 전부에 대치를 돌려 보고 그중 하나만 쓰는데, 채점기가 그 버려지던 것을 주워 담아 셋으로 나눈다.

조건귀속
후보 풀 안 어느 것으로도 못 피한 결함생성 탓
같은 경로의 다른 후보로는 피할 수 있던 것검색 탓
같은 후보를 다른 경로가 더 잘 채운 것대치 탓

정직성 장치가 하나 붙는다 — 랭킹이 애초에 볼 수 없었던 결함(시그니처 밖 자리의 넘침 등)은 검색 탓에서 덜어낸다. 랭킹에게 없는 정보로 벌점을 매기면 이 수치로 가중치를 튜닝할 때 잘못된 방향으로 간다.

기준선 수치 2026-08-15 · 입력 50건 · 컴포넌트 65개 · 상위 10건

지표시멘틱 검색구조 검색순위 융합
심각도 가중 평균 (낮을수록 좋음)20.022.020.7
1위 후보가 결함 0 인 비율0.0%1.6%1.5%
blocker 없는 입력 비율8%7%원문에 없음

1 · 의미를 재기 시작하자 격차가 사라졌다

08-15 이전에는 구조 검색(17.5)이 시멘틱(19.9)을 크게 이겼다. 「검색이 허용한 카테고리 밖에서 고른 것」을 결함으로 새로 세자 순위가 뒤집혔다.

구조 검색이 앞서 보이던 것의 대부분은 의미를 재지 않은 덕이었다.

2 · 넘침은 경로를 바꿔도 안 줄었다

텍스트 넘침이 양쪽 모두 1위 결함이고 건수가 거의 같다(시멘틱 176 · 구조 177).

대치 방식이 아니라 검색 풀과 용량 자체의 문제라는 뜻이다.

3 · 결함의 대부분이 검색 탓

귀속을 세면 생성 36 · 검색 466 · 대치 17 · 랭킹이 못 본 것 74.

랭킹 가중치 실험(MOR-1936)이 대치 알고리즘을 다듬는 것보다 값이 큰 다음 수라는 근거가 여기서 나온다.

다만 두 검색은 1위 후보가 65개 중 2개(3%)만 겹쳐서, 「교집합 상위 10건」을 그대로 지표로 쓰면 표본이 거의 남지 않는다.

군(tier) 이 둘 있고 나누는 축이 다르다

이름이 같아서 섞이기 쉽다 — 항상 어느 쪽 군인지 밝혀 적는다

comp-sign 의 태그 군 셋은 「그 후보를 끌어온 근거가 사용자냐 LLM 이냐」로 나눈다. PoC 실색인 검색의 군 넷은 「그 태그가 강등 사다리의 어느 지점에서 나왔나」로 나눈다.

comp-sign 태그 군그 컴포넌트가 후보에 들어온 이유
0군사용자가 직접 고른 분류에 속한 태그를 갖고 있다
1군LLM 이 글을 보고 추정한 태그를 갖고 있다. 0군과 겹치는 태그는 뺀다
2군0군에도 1군에도 없다 — 태그와 무관하게 구조 해시만으로 걸린 후보
PoC 검색 군질의가 그 태그를 어디서 얻나
1군생성기가 적은 type 과 alternatives
2군요청 카테고리의 fallback 행
3군강등 사다리가 최종 확정한 카테고리
4군안전망. 종단 셋. 1~3군이 하나도 못 찾았을 때만 발동한다

양쪽 다 군이 점수보다 절대 우선이다. 1군 후보가 아무리 점수가 높아도 0군을 앞설 수 없고, 2군은 fallback 행의 순서 그대로라 Timeline 이 List 보다 항상 먼저다. 이 규칙은 원래 없었고 실사용 로그 10건 실행에서 「같은 군 안에서 순서가 점수에 밀리는」 문제를 발견해 고정한 것이다.

규약과 구현이 어긋나는 자리 (I-5)

규약 5절은 「성립 조건을 못 채우면 후보에서 빠진다」는 이분법인데, comp-sign 은 제외하지 않고 뒤 군으로 미룬다. 규약은 컴포넌트가 무엇을 소화하는지를 보고 구현은 그 후보가 어디서 왔는지를 본다 — 축이 다르다. PoC 는 1군에서만 빼고 2·3군으로 내려보내므로 규약 쪽에 가깝지만 완전히 같지는 않다.

대치 계층 다섯 — fallback 이 끝난 뒤

계층무엇을 하나상태
복합 구조 순서 (N1~N5)노드가 여럿일 때 어느 노드부터 포기하나규약 확정(08-28) · 코드 미착수 (I-11)
exact structure match해시와 태그로 동일 구조 후보를 찾는다동작 풀이 얕으면 실패가 잦다
semantic fallback카테고리 강등과 P1~P8규약·코드 모두 완료
4단계 comp-sign 대치textTree 와 시그니처로 텍스트를 넣는다실서비스 경로 · 규약 contract 미완
5단계 property 대치이종 type 사이 카테고리 고유 속성 투영부분 T-7 추출만 있고 T-8 미착수

structure projection 과 property projection 은 이름만 비슷하다

앞은 내용(structure)을 옮기고 뒤는 카테고리 고유 속성(질의 쪽 params, 색인 쪽 properties)을 옮긴다. P1~P8 만으로는 「List 안의 BigNumber」처럼 서로 다른 카테고리 사이에서 속성을 옮기는 문제를 풀지 못하고, 그것이 5단계 T-8 의 영역이다.

PoC 규약 RLSC 대치(binding.ts)는 실서비스 경로가 아니다 — MORDOR PoC 전용 기준선이고, 내용시각화 BE 가 쓰는 대치는 buildContentReplacement 하나다.

실사용 E2E 실측 2026-08-12 · 로그 원문 10건 · gpt-5.4-mini

단계결과
생성10/10 성공 (재생성 루프 사용 7회)
검색컴포넌트 15개 전부 후보 확보 — 검색 군으로 1군 5 · 2군 8 · 3군 1 · 4군 안전망 1
대치entity 56개 중 56개 수용 (43개 배치, 13개 접기)

절반 이상이 2군이라는 것은 생성기가 고른 카테고리를 색인이 그대로 대 주지 못한다는 뜻이다. 이 실행에서 시스템 구멍 두 가지를 찾아 코드에 반영했다 — 같은 군 안에서 순서가 점수에 밀리는 문제(2군 정렬을 태그 순위 우선으로 고정), 마지막 fallback 카테고리마저 색인에 없으면 후보가 0이 되는 문제(4군 안전망 추가).

평가 pool 을 고정하는 규칙 다섯

전 컴포넌트(실서비스 17만여 건)에 시그니처와 속성을 한꺼번에 구울 수는 없다. 세 대치 경로를 공정하게 비교하려면 같은 후보 풀 위에 미리 구워 둬야 한다.

#규칙
1기준 pool 은 indexPool.ts 술어와 같다 — sheet_json 과 structure_json 이 둘 다 있는 것
2평가 pool 은 그중 고정 subset. 실사용 50건(컴포넌트 65개)이 입력이다
3후보 pool 크기는 약 5,000건 제안 — 카테고리별 후보가 마르지 않고 굽는 비용이 하루 안에 끝나는 지점
4시그니처 · I.I.S. 경계 · I.I.S. 속성을 같은 design_object_id 집합에 굽는다. 한쪽만 있으면 5단계 비교가 성립하지 않는다
55단계 화면은 속성 bake 와 T-8 규칙이 있어야 연동된다. 지금은 4단계 2-way 만 가능하다

비용 어림의 근거는 실측이다 — 시그니처 빌드가 2만 건에 약 4.4분, 5만 건에 약 9.9분이고 properties 추출이 137건에 4분(입력 23만 토큰)이었다. 5,000건이면 추출 약 2.4시간 · 입력 약 840만 토큰으로 어림된다.

코드가 어디 있는가

무엇어디 (aippt-prisonbreak)
규약을 코드로 옮긴 것 — 어휘·타입·스키마·capability 상수·establish/fallback/projection·query·auditsrc/lib/visual-summary/
항목 트리를 markdown 으로 바꾸는 다리…/markdown.ts
결함 채점과 귀속…/audit.ts
교집합과 순위 융합(RRF)…/intersect.ts
I.I.S. 대행 생산 — 경계 추출, properties·구조 대응, 노드 검색·대치…/iis/
생성 프롬프트와 재생성 루프…/generator/
규약 예시 18종 · 안티패턴 5종 · 평가셋 50건 · 생성 스냅샷…/fixtures/
두 경로가 공유하는 후보 풀src/app/api/visual-summary/indexPool.ts
comp-sign 실제 코드 호출src/app/api/visual-summary/compSignService.ts
Eregion 화면 (탭 다섯)src/app/visual-summary/

comp-sign v4.3.8 의 네 함수 — buildCompSignatures(구조 해시·text_map·채점 feature, DB 적재용) · buildCompSearchData(markdown → textTree 와 조회용 해시) · rankCompCandidates(채점·중복 제거·정렬) · buildContentReplacement(대치 텍스트 생성·box 보정·형제 그룹). DB 접근과 후보 fetch 는 호출자(BE) 몫이고 이 패키지는 순수 계산만 한다. 입력이 markdown 이라는 점이 중요하다 — Visual Summary YAML 이 이 경로에 직접 들어갈 자리가 아직 없다.

§12

I.I.S. 는 내용 대치와 어떻게 이어지나

src/lib/visual-summary/iis/

I.I.S. 는 색인 쪽 모듈이다. 질의를 만들지 않고, 이미 있는 컴포넌트 안을 더 잘게 나눈다. 그 결과가 대치에 닿는 경로가 이 절이다.

왜 필요한가 — 컴포넌트 단위 태그로는 자리를 못 짚는다

현행 검색은 컴포넌트 전체에 붙은 최대 4개 태그로 후보를 고른다. 한 컴포넌트 안에 여러 의미가 섞여 있으면 그 안의 어느 부분이 요청 카테고리인지 특정할 수 없다.

실물이 그렇다 — design_object_id 4757227 에는 Comparison Table · Hierarchical Tree · List · Highlighted Message 넷이 함께 붙어 있다. 최상위 하나가 이 넷을 동시에 가질 수는 없으니 하위에 여러 유형의 노드를 품고 있다는 뜻이다.

네 단계 — 경계 → 검색 → 대치, 그리고 속성

T모듈무엇을 하나상태
T-4iis/extractBoundary.ts 경계 추출. 컴포넌트 안 어느 노드 묶음이 어느 카테고리인지 LLM 이 판정해 iis_semantic_component 에 적재 코드 있음
사람 검수 미완
T-5iis/nodeSearch.ts 노드 단위 검색. 경계 노드마다 그 서브트리를 독립된 컴포넌트처럼 취급해 검색 코드 있음
메인 통합 미완
T-6iis/nodeBinding.ts 노드 단위 대치. 매칭된 경계 서브트리 안에만 채우고 밖은 원본 보존 코드 있음
평가셋 전량 미실행
T-7iis/extractProperty.ts 속성·구조 대응 추출. 경계가 잡힌 노드에 카테고리 고유 속성과 구조 대응을 붙인다 v1 코드
정확도 검수 미완
T-8iis/propertyMatch.ts 속성 대조와 정책. 질의 params ↔ 노드 properties 를 맞대고 정책 셋을 다 낸다 판정부만

대치로 이어지는 지점 — 규칙을 다시 구현하지 않는다

T-5·T-6 의 설계가 같은 문장을 공유한다. nodeSearch.ts 는 경계 노드의 서브트리를 독립 컴포넌트로 취급해 rankComponents() 를 그대로 재사용하고, nodeBinding.ts 는 bindComponentToRlsc() 를 그대로 재사용한다 — 그 함수가 이미 「RLSC 트리 하나」에 대해서만 동작하므로, 컴포넌트 전체 대신 매칭된 서브트리를 넘기면 그만이다.

nodeBinding 이 더하는 것은 둘뿐이다 — 그 서브트리를 찾는 것과, 대치 결과를 원래 자리에 도로 이어붙이는 것. T-6 완료 판정의 핵심이 「태그 밖 노드는 안 건드린다」이다.

이유가 코드 주석에 적혀 있다 — 「같은 규칙을 두 벌 만들면 반드시 어긋난다」. PR 리뷰가 같은 종류의 Critical 을 다섯 번 낸 원인이었다고 한다.

경계 판정은 LLM 으로만 한다 — 규칙으로 뼈대를 먼저 고정하지 않는다

반복 단위(patternLabel)와 role 로 경계 위치를 규칙으로 뽑고 LLM 은 카테고리만 고르게 하는 안은 기각됐다. 반복 단위와 역할은 배치 정보이지 의미 경계가 아니기 때문이다 — 같은 반복 묶음이 절차일 수도 목록일 수도 있고, 의미상 한 경계가 여러 반복 단위에 걸칠 수도 있다.

규칙으로 뼈대를 먼저 고정하면 LLM 이 고칠 수 없는 자리에 오답이 박힌다. 그래서 RLSC 를 줄여 보여 주는 투영은 「판단하지 않는다. 무엇을 보여 줄지만 정한다」.

T-7 은 한 번의 호출로 둘을 낸다

산출물무엇인가없으면 무엇을 모르나
properties카테고리마다 정해진 표현 값 — 피라미드 꼭대기가 어느 쪽인가, 순서가 어느 방향인가이 컴포넌트를 어떻게 그리는가
structure
구조 대응
경계 안 어느 노드가 label 인지 items 인지의 대응표사용자 내용의 어느 조각을 어느 노드에 넣는가

한 컴포넌트에 한 번만 부른다. 노드마다 따로 부르지 않는 이유가 코드에 적혀 있다 — 한 컴포넌트 안의 경계 여럿이 같은 그림 하나를 공유하고, 회전 방향·오름차순 같은 속성은 서로 무관하지 않다 (Cycle 의 rotation 과 그 안 Steps 의 sequence 가 같은 그림에서 나온다).

속성은 「읽어낼 수 없으면 뺀다」가 계약이다. 허용 밖 키·모양 밖 값·없는 노드 참조는 버리고 보고할 뿐 재시도를 걸지 않는다 — 값 하나가 어긋났다고 컴포넌트 전체를 다시 물으면 맞게 읽은 나머지까지 버리게 된다. 재시도는 응답을 아예 못 읽을 때만 건다.

T-8 의 미결 — 정책을 고르지 않은 채 셋을 다 낸다

질의 속성과 노드 속성이 어긋났을 때 무엇을 할지는 미리 고르지 않는다. 완료 판정 자체가 「세 정책을 다 돌려 결과를 비교한 표. 어느 하나를 미리 고르지 않는다」이기 때문이다 — exclude(후보 탈락) · reorder(채우는 순서를 뒤집어 해소) · ignore(감점만).

reorder 가 blueprint 의 property projection 이고, 구조 투영 P1~P8 과는 다른 축이다 — 앞은 내용을 옮기고 뒤는 표현 값을 옮긴다.

§13

RLSC 는 어디서 만나나

design/pipeline-flow.md · rlsc.ts

가장 흔한 오해 — 사용자 입력이 RLSC 로 변환되지 않는다

경로가 둘이고 별개로 진행된다. 질의 쪽은 사용자 입력을 검색 조건으로 바꾸고(Summary · structure), 색인 쪽은 이미 있는 템플릿을 미리 뽑아 둔다(RLSC · Search Signature v2).

둘은 BE 검색 모듈에서 합류한다. structure 에서 RLSC 로 가는 화살표는 변환이 아니라 capability 대조이고, 그 규약이 capability-table.md 다.

RLSC 가 실제로 하는 일 셋

① 색인 갈래의 구조 어휘

템플릿 페이지 → ALSC → Structuriser → RLSC → 유효 컴포넌트 게이트 → design_objects.

거기서 comp-sign 시그니처와 semantic 태깅 두 갈래가 갈린다.

파이프라인 그림에서 굵은 테두리 셋 중 하나 — Visual Summary(질의 표현) · Search Signature v2(색인 contract) · RLSC(구조 어휘).

② 대치의 슬롯 제공자

실물 RLSC 는 Group/Text/SVG/Chart 노드 트리이고, Text 노드가 role 을 단다 — Role.Element.Title · Subtitle · Description · Marker.

규약 7절의 대응(entity.label → Title, items[] → Description)이 이 슬롯 위에 선다.

③ I.I.S. 가 더 잘게 나누는 대상

4단계에서 Old RLSC → I.I.S. → New RLSC. 노드마다 semantic tag 가 붙어 §12 의 모호성이 사라진다.

New RLSC 가 충분히 쌓이면 Structuriser 자체 모델을 재학습한다는 것이 그다음 계획이다.

슬롯 대응 — binding.ts 가 실제로 넣는 자리

규약 7절 대응src/lib/visual-summary/binding.ts
entity.label   → 단위의 Title 슬롯
entity.value   → 단위의 Subtitle 슬롯
                 (없으면 Description 앞줄, 그것도 없으면 label 병기)
entity.items[] → 단위의 Description 슬롯들에 분배
                 (모자라면 마지막 슬롯에 이어 붙임)
순번             → 단위의 Marker 슬롯 (01, 02, …)
페이지 제목       → 머리 영역(반복 단위 밖)의 Title/Subtitle/Description

단위를 Title 등장 순서로 어림하지 않는다

RLSC 서브트리의 role 시그니처 반복으로 찾은 반복 단위(detectUnitLayout)에 맞춘다. 검색 채점(search.ts)과 같은 단위 정의를 쓰므로, 점수가 좋다고 판단한 구조 그대로 채워진다.

색인 쪽 노드 분류 — CORE / DESC / DECO

추출 쪽은 이미 노드 단위로 핵심·위성·장식을 식별하고 있다. §6 이 지적한 「질의 쪽에 위성 자리가 없다」는 구멍의 반대편이 이것이다.

태그무엇인가대치에서의 의미
CORE컴포넌트 경계 그 자체반드시 채워야 하는 슬롯
DESCsatellite 컴포넌트있으면 채우는 슬롯
DECO컴포넌트 안팎을 가리지 않는 장식 요소비우거나 제거 가능

OUT 은 폐기됐다 2026-09-05

원 출처(2026-07-31)의 「DESC·DECO·OUT」 표기는 RAT pod 의 semantic tagging 검증 트랙에서 파생된 것이고, 그 트랙 자체가 holding 또는 deprecated 다. I.I.S. 대치 계약에서 유효한 것은 위 셋뿐이라고 2026-09-05 에 정리됐다.

「트리」가 층마다 다르다 — 넷을 갈라 읽는다

이름무엇인가만드는 곳 · 쓰는 곳
structureYAML 의 entities·relations·dataset. 질의와 P1~P8 의 입력생성기 · validate.ts · projection.ts
textTreecomp-sign 이 markdown 을 파싱해 만든 대치용 텍스트 트리compSignService.ts · buildContentReplacement
text_map
text_node_roles
컴포넌트 시그니처의 슬롯 용량·역할. 런타임 용량의 SSoT(legacy textCapacity 아님)buildCompSignatures 적재 · 채점 · 대치
RLSC text slotsPoC 자체 대치가 RLSC 서브트리의 Title/Description/Marker 에 직접 넣는 경로binding.ts · rlsc.ts

다리는 structure → markdown → buildCompSearchData → textTree 다. comp-sign 경로는 Visual Summary YAML 을 직접 받지 않는다 — markdown 과 textTree 를 받는다. 이름을 섞어 쓰면 fallback 이후 대치 계층을 따라갈 수 없다.

§14

소유와 순서

덱 p.21–23
구간담당
단어장 v7 정의와 유지김수현
Summary 생성기스키마 정원석 · 생성 실무 허재영, 황현진
시멘틱 쿼리 추출 LLM · 컴포넌트 태깅황현진
태깅 결과 수신·검증·적재류민 → 박지우
노드 분류와 카테고리별 속성신영빈 · 류민
I.I.S. (4단계)류민 덱 시점 정지
시그니처·랭킹·대치 계산 (comp-sign)이석
Visual Summary 규약정원석
검색과 대치 실행최운식 (BE)

layouts 태깅은 BE 로 가지 않는다. RAT pod 내부용이고 검색에는 컴포넌트 태깅만 쓴다.

덱이 각자에게 물으려던 것

강창석님

  • dataset 을 DataViz Matrix 로 바로 넘길 수 있나 (어댑터 실측)
  • nested_scope 를 concentric_rectangles 로 볼 수 있나
  • 스마트 다이어그램 32종 중 2단계에 열 것이 있나

이석님

  • semantic 만 빼고 검색·대치가 되나. toggle 이 있나
  • 세 축 정렬을 언제 누구와
  • rankCompCandidates 위계 가중치 A/B
  • 41종 fallback 순서 검토

류민님

  • I.I.S. 재개 시점
  • tree children → Graph relations 규칙
  • 카테고리별 속성 목록 초안 리뷰

허재영님

  • Venn 라벨 오류 프롬프트 225건 중 148건이 오라벨
  • entity.components[] 생성 시점
  • 평가셋 38 중분류 확장

덱 시점의 급한 순서 2026-08-02 기준

  1. C-1 모듈 버전 2.0 BE 정책 협의
  2. C-2 semantic tag 데이터 흐름 공유
  3. C-6 태깅 증량분 재전달 9만 → 16만
  4. C-7 컴포넌트 분포 재측정
  5. I-2 세 축 정렬
  6. I-6 위계 가중치 A/B
§15

그 뒤 3주에 바뀐 것

2026-08-04 → 08-26 SSoT 대조

덱은 3주 전 사진이다. 아래 대조표는 손으로 쓴 것이고, 그 아래 두 표(DASHBOARD.md 로드맵·절별 잔여)와 §6 의 변경 12건은 mordor-wiki 원문에서 자동 동기화된다 — 원본이 바뀌면 sync-sources.py 가 낡음을 잡아낸다.

로드맵 5단계, 지금 어디까지 왔나

단계 무엇이 바뀌는가 목표 시점 지금 상태
1단계 (현행)Markdown Summary, 임베딩 검색지금운영 중, 변동 없음
2단계컴포넌트에 Semantic Component Category2026-08-18 사실상 스킵2026-08-07 확정. 4단계로 직행
3단계YAML + structure 검색없음실행하지 않음 (2026-08-06 Cancelled)
4단계RLSC node 태그로 정확한 범위 특정단독 단계로는 건너뛴다 (2026-09-08 확정)실행 티켓 여섯이 Cancelled. 끝난 산출물(fallback map, 꾸밈 축 등)은 5단계가 그대로 쓴다
5단계node 에 semantic category 속성까지여기로 직행한다 (2026-09-08 확정, 정원석)경계 4,764건·속성 3,955건 로컬 파일럿(09-06), 노드 검색 엔진 배선(09-07). 정확도 판정(K-9-1)과 10만 건 추출(MOR-2415)이 남았다

↻ 로드맵 5단계 현재 상태 · DASHBOARD.md — 원본에서 자동 동기화

덱이 열어 둔 것지금근거
B-24 type 을 41종으로 좁힐지 49종으로 열지 열림 닫힘 49종으로 확정. 페이지 역할 4종은 어휘에 넣고, 지도 4종은 capability 성립 불가로 표시 2026-08-06 정원석 · MOR-1909
B-18 꾸밈구조 규약 표기 열림 닫힘 키는 decoration, page 수준도 연다. 1단계에서 생성기는 안 채운다 덱 당일 2026-08-04 규약 2.7절에 반영
B-22 장식 role 표식을 색인으로 넘기는 경로 끊김 아직 열림 — §10 의 끊긴 구간이 그대로다 MOR-1935
B-25 대분류를 없애고 중분류만 남겨도 되나 아직 열림 B-24 와 별개 항목으로 남았다 허재영 2026-08-04 제기
fallback 엣지 55개, 최대 두 칸 개정 45종 · 엣지 130개, 칸 수 상한 폐지. 근접도 순서만 지키면 몇 칸이든 capability-table.md 2026-08-17
capability 41행 확장 45행 (41종 확정 + PageNavigation 4종. 그 성립 조건도 2026-08-27 에 채워져 격차가 닫혔다 — 남은 것은 Opening 이 맨 앞장 전용인지 하나뿐이다) capability-table.md 범위 절
「선택 속성」한 열에 내용과 표현이 섞여 있다 해결 선택 내용 / 속성 두 열로 분리. fallback 때 내용은 옮기고(P3·P7) 표현은 버린다(P2) 2026-08-23
I.I.S. 정지 — 류민, 2026년 6월 중순부터 막힘 우회 기다리지 않는다. PoC 에서 같은 출력을 대행 생산하는 것이 4단계 실행 경로 (D-5 닫힘) 2026-08-22 DASHBOARD 4절
급한 순서 1위 = C-1 BE 정책 협의 재편 실행 1순위는 I-8 평가 pool bake. 그 다음 I-7+I-9(속성 projection), I-2(대치 contract) 2026-08-22 PoC 우선순위
— 신규 B-30 measure↔matrix projection 규칙(P9·P10) 미정 — Gauge↔PictogramChart fallback 이 여기 걸려 있다 2026-08-17 열림
— 신규 B-27 도착의 개수 상한을 넘을 때 규약 5절 1번(후보 탈락)과 P8(접기)이 같은 상황에 답이 둘 MOR-1934

절별 남은 일

TODO.md 는 할 일을 아홉 절(A~J)로 나눈다. 품질을 좌우하는 것은 I절(내용 대치 contract) 이고, 그것이 §2 의 BAD 85% 구간이다.

절 무엇을 다루는가 마감 남은 것
A규약 확정2026-08-071건 (A-4)
B규약 열린 결정A 에 종속0건
C2단계 배포사실상 스킵 (2026-08-07)2건 (C-6, C-7)
D스쿼드 차원에서 정할 것각각 다름1건 (D-8)
E7/24 회의 후속미정3건
F사후 검증 (마감 후로 미룸)마감 후1건 (F-2)
G최근 해소된 것없음기록만
H문서 정합 백로그없음3건
I내용 대치 contract미정14건
J생성 모델 파인튜닝착수 전8건
KWeek 27 PoCweek 272건 (K-9-1, K-11)

↻ 절별 남은 일 · DASHBOARD.md — 원본에서 자동 동기화

새로 생긴 것 — 생성 파이프라인 실측

덱에는 없던 축이다. 2026-08-24 싱크에서 mastra 기반 생성 파이프라인의 첫 실측이 공유됐다. 평가셋 50건 × 3회, 모델 gpt-5.6-luna, 재시도 없음.

항목split — 정의를 tool 로 받아 거른다inline — 정의 45종 전량 주입
규약 통과49~50 / 5049~50 / 50
라벨 정렬21~25 / 5019~20 / 50
1,000건 비용$3.36$2.19
지연 중앙값8,894 ms6,741 ms

규약 통과는 잡음을 넘었다

값의 타입 규칙과 「스키마에 없는 키를 만들지 않는다」규칙을 넣기 전 37/50, 넣은 뒤 49~50/50. 케이스 단위 흔들림이 10~18/50 이므로 이 상승은 흔들림보다 크다.

라벨 정렬로는 갈래를 못 고른다

split 이 3회 모두 앞섰지만 150 시도 기준 46% 대 39%, 차이 7.3pp. 비용은 1.53배다. 「다름」23건 중 모델이 확실히 틀린 것은 10건 남짓이고, 그 다수가 Enumeration.List 로 물러선 경우다.

카테고리 우선순위도 P0~P2 로 재편됐다 (2026-08-21 김수현). P0 는 10월 배포에서 잘 되어야 하는 범위이고 UX 의 유저 프리셋 버튼과 같은 범위다. 역제안 대상으로 지목된 넷은 CombinedResult · ProblemSolution · BigNumber · SectionDivider. 「잘 되어야 한다」의 판정 기준은 아직 비어 있다.

§16

알려진 격차 다섯

2026-08-29 자기정합 재실행

통합본이 부록을 쓰면서 문서 사이에 어긋난 자리를 다섯 확인했다. 파생물이 규약 본문보다 뒤처진 것이 셋이었고, 넷은 그 자리에서 닫혔다. 남은 것은 5번 하나와 3번의 꼬리다.

#무엇이 어긋나 있었나어떻게 됐나
1visual-summary-0.5.schema.json 에 structure.columns 와 entity.values[] 가 없다닫힘 2026-08-29 에 규약 2.2절에서 파일을 다시 내보냈다
2semanticCategory enum 과 capability.json 에 PageNavigation 4종이 빠져 있다닫힘 enum 이 결합값 45종(0.5.3), capability.json 도 45종이 됐다
3capability-table.md 2.6절의 페이지 역할 4종 성립 조건이 비어 있다닫힘 2026-08-27 에 채워졌다. 남음 Opening 이 맨 앞장 전용인지 — 골든셋은 맨 앞장 전용으로 만들었고(08-25 황현진) 단어장 오너 확인 대기
4fallback 엣지 수가 131개와 128개로 함께 적혀 있다오탐 남아 있는 숫자는 전부 이력 서술이다. 현재 값은 130개 — 2026-09-05 에 PictogramChart↔Gauge 와 PictogramChart → BigNumber 를 빼면서 줄었다(B-30, measure↔matrix projection 규칙을 만들지 않기로 확정)
5capability.json 이 BigNumber 의 선택 내용에 delta 를 넣어 뒀는데 스키마의 entity 에는 delta 가 없다 — measure 에만 있다열림 항목이 여럿인 BigNumber 는 증감을 적을 자리가 없다. 둘 중 어느 쪽을 맞출지 정해야 한다

검사 정의 자체도 낡아 있었다

자기정합 검사 14가지를 마지막으로 전량 돌린 것은 2026-08-04 였고, 그 뒤 개정 다섯 번이 검사 없이 들어갔다. 2026-08-29 에 전량 다시 돌려 통과시켰다.

그 과정에서 검사 둘을 고쳤다 — F2(「어느 행도 대체 후보를 셋 이상 두지 않는가」)는 두 칸 상한이 2026-08-17 에 없어져 폐기했고, F3 은 「종단 셋으로 끝나는가」였는데 같은 날 List 뒤에 ListingTable 을 안전망으로 덧붙인 행이 넷 생겨 「거치거나 자신이 그 셋인가」로 고쳤다.

이 대조는 capability.test.ts 가 capability.json 과 45종 전량을 맞대는 형태로 코드에도 있다. 다만 docs/ 가 비공개 submodule 이라 CI 체크아웃에 없어서 로컬에서만 돌고 CI 에서는 건너뛴다.

§17

원문 지도

먼저 볼 것 둘은 규약(spec/schema-v0.5.md)과 할 일 SSoT(TODO.md)다. 나머지는 필요할 때 찾아 들어가면 된다.

이 페이지의 갱신 원천은 두 폴더다 2026-09-08 고정

앞으로 이 문서는 항상 아래 둘을 다시 읽어 갱신한다. 값이 어긋나면 이쪽이 맞다.

구현  aippt-prisonbreak/src/lib/visual-summary/ — 모듈 37개 · 9,753줄. 진입점은 README.md(모듈 구성)와 _SIGNATURE.md.
규약  aippt-prisonbreak/docs/projects/mordor/visual-summary/ — mordor-wiki 가 submodule 로 붙은 것. spec/ 이 규약, design/ 이 설계 근거.
이번 갱신 기준  mordor-wiki 013fff13 (정본 v0.5.6, 2026-09-12 조회)

구현 쪽 README 가 스스로 적는다 — 「이 모듈은 그 규약의 실행 가능한 파생물이고, 문서와 어긋나면 문서를 따른다」. 정합은 capability.test.ts 가 spec/schema/capability.json 과 45종 전량을 기계로 대조한다. 다만 docs/ 가 비공개 submodule 이라 CI 에서는 skip 되고 로컬에서만 돈다.

문서무엇
spec/schema-v0.5.md 규약 SSoT. 0절 v0.4→v0.5 변경 12건 · 2절 스키마 · 5절 fallback 규칙 · 9절 열린 결정
TODO.md 할 일 A~J 아홉 절. B절이 규약 열린 결정 29건의 SSoT
DASHBOARD.md 진행 현황 요약판. 로드맵 5단계 상태 · 절별 잔여 건수 · 병목 셋
spec/capability-table.md 45종 성립 조건 · 선택 내용/속성 · fallback 순서 · 엣지 130개 projection · 생성기 불허 9종(10.1절)
design/decoration-model.md 꾸밈구조 설계 SSoT — §9 의 근거
design/pipeline-flow.md 전체 흐름
design/content-binding-contract.md 내용 대치 구간 contract — I절 8건의 근거
reference/semantic-taxonomy-v7.md 단어장 v7 49종
spec/schema/…0.5.schema.json 기계 판정용 SSoT. TypeScript 타입과 zod 는 여기서 나온 파생물
meetings/2026-08-24-…sync.md 최신 생성 파이프라인 실측 · I.I.S. 골든셋 · P0 재편 — §15 의 근거
reference/2026-08-04-visual-summary.pdf 이 페이지의 원본 덱 24쪽 (로컬)
reference/visual-summary-overview.pdf 최신 2026-08-29 통합본 96쪽 — 개념·일정·작업 상태·구현물 로직에 부록(45종 전량 · params 27종 · fallback 엣지 131개(당시) · 열린 결정 47건 · 자기정합 14가지)까지. §6·§8·§11·§16 의 근거 (로컬)

저장 위치

github.com/miridih/mordor-wiki → projects/mordor/visual-summary/. aippt-prisonbreak 를 클론했다면 docs/ submodule 이 같은 저장소다 — git submodule update --init docs 후 docs/projects/mordor/visual-summary/. GitHub 계정이 없으면 Confluence 발행본으로 공유한다.