← 미리디 아카이브

내용시각화 담당자 지도 · 작업 항목 2026-08-26 코드 실측

병합 대치 정렬 문제

내용 대치를 '병합'으로 하면 정렬이 깨진다. 원인이 두 층이고 해결 레이어가 두 갈래라 담당자가 갈린다 — 어디서 깨지는지를 먼저 판정하면 물어볼 사람이 자동으로 정해진다. 그리고 이 문제의 정면 해결은 이미 MOR-2018에서 진행 중이다.

miricanvas-iui comp-sign MOR-2018 post-replace-relayout ailabs SmartBlock
§1

원인 두 층

'병합'은 렌더링 장치가 아니다. 검색용 쿼리 트리를 한 단계 접는 변형이고, 접은 만큼 점수를 깎는다. 그림을 고쳐 주는 코드가 아니라 후보를 더 찾아 주는 코드다.

① 병합 대치 시 정렬 깨짐
창석님(강창석) 요청 · "스마트블록으로 가능?"
② 병합 = 검색 재현율 트릭
자식을 한 leaf 로 접어 재검색 · 감점 mergeStep
③ 근본원인: 구조 재배치가 없다
대치 = 텍스트 주입 + 박스 보정만 → 없는 계층을 만들어 내지 못한다

② 병합이 실제로 하는 일 — 코드

병합은 시그니처 트리를 접는 연산이고, 접힌 단계 수만큼 점수에서 빠진다.

한 단계 자식 병합 comp-match/matching.ts:459
/**
 * 한 단계 자식 병합. 현재 최대 leaf depth 의 형제 그룹 / 외동 leaf 를
 * 모두 한 번에 병합해 하나의 새 forest 를 만든다.
 * ...
 * 형제 병합할 그룹이 없는 depth ≤1 트리는 null.
 */
병합 감점 — root 에 가까울수록 크게 comp-match/scoring.ts:456
// 병합 감점은 root 에 가까운 단계일수록 크게: 1+2+...+step = step(step+1)/2.
const mergeWeight = (args.mergeStep * (args.mergeStep + 1)) / 2;

그래서 "스마트블록으로 가능?"의 답은

병합은 검색 단계의 연산이라 정렬을 고칠 수단이 애초에 없다. 정렬은 그 뒤 단계(박스 보정 · 재배치)의 일이고, 그 단계에 지금 무엇이 있는지가 §2다.

③ 대치가 실제로 넘기는 것 — 코드

대치는 렌더러에 ThumbnailLoad 한 덩어리를 넘긴다. 그 안에 구조를 바꾸는 필드가 없다 — 글자(nodeTextMap)와 박스(nodeBboxMap)뿐이다.

buildContentReplacement 반환 build-replacement.ts:109-168
return {
  type: 'COMPONENT_THUMBNAIL',
  sheetJson,           // 후보 원본 — 구조 그대로
  nodeTextMap,         // 글자 주입
  nodeBboxMap,         // 박스 보정 (여기가 전부다)
  siblingGroups: buildSiblingGroups(textMap, sheetJson),
  ...(rlsc ? { rlsc } : {}),
};

박스 보정 토글 네 개 — 기본값이 중요하다

토글하는 일기본값
expandText텍스트 노드를 형제·부모와 겹치지 않는 선에서 가로 확장false
relieveTopBias위로 쏠림 완화 — 글씨 절반만큼 아래로 이동true
ensureBgMargin텍스트 박스를 배경 도형 경계 안쪽으로 clamptrue
tidyLayout 공간 정돈force-directed 시뮬레이션으로 box 일괄 조정 — 켜지면 위 셋을 대체false

근거: build-replacement.ts:54-70 · 즉 정렬 개선 수단(tidyLayout)은 기본으로 꺼져 있다. "왜 정렬이 안 맞나"의 첫 번째 답이 여기일 수 있다.

§2

해결 레이어 두 갈래

박스가 넘치거나 변이 어긋나는 기하 문제인지, 대상이 담을 수 없는 계층이 필요한 구조 문제인지에 따라 손댈 곳이 다르다.

④a 기하적 정렬
박스 넘침 · 변 어긋남 · 여백 불균형
comp-sign tidyLayout
force-directed 공간 정돈 (이미 있음 · 기본 꺼짐)
홍지혜 · 담당
이 갈래를 맡는다 — miricanvas-iui
이석님 Pod 의 기존 구현은 참고만 한다
④b 구조적 재배치
대상이 못 담는 계층 필요
SmartBlock 생성엔진
DimensionPolicy: resize · 정렬 · gap 재배치
장주영 · AI연구팀
조건부 에스컬레이션
ailabs SmartBlock 생성기 소관일 때
내 라인에서 안 풀릴 때만 장주영님 라인으로 넘어간다. 이석님 Pod 이 이미 만들어 둔 것은 「기존 접근 방법」 절로 따로 뺐다 — 참고만 한다.

⚠ 세 번째 갈래가 있다 — MOR-2018

기존 지도에는 ④a·④b 둘뿐이었지만, 실제로는 이 문제를 정면으로 푸는 세 번째 작업이 이미 돌고 있다 — miricanvas-iui/src/post-replace-relayout/ 의 재배치 후보 다섯 개다. 그리고 그 안에서 tidyLayout후보가 아니라 대조군으로 쓰인다. 자세한 것은 §5-B.

§3

먼저 확인할 것 — 정의 충돌

⚠ "스마트블록"이 두 갈래다

같은 단어가 서로 다른 것을 가리켜서, 어느 쪽을 말하는지에 따라 담당이 갈린다.

A. 이석 Pod · 스마트블록 검색·대치
내용시각화 엔진 내부 (RLSC 기반) · miricanvas-iui + miricanvas-web-2
B. ailabs · SmartBlock 생성기
AI연구팀 독립 파이프라인 (장주영) · 이 머신에 체크아웃 없음
창석님 질문이 A/B 어느 쪽인지 확인하면 담당이 자동 결정된다.
§4

코드 지도 — 어디를 열면 되나

아래 줄 번호는 고정 커밋 기준이라 링크가 그 시점을 가리킨다. 코드가 움직이면 어긋날 수 있으니, 엉뚱한 곳이 뜨면 커밋을 갱신할 것.

miricanvas-iui — 대치·정돈이 실제로 도는 곳

무엇파일 · 줄메모
대치 페이로드 조립build-replacement.ts:109buildContentReplacement() — 여기가 대치의 출구
박스 보정 토글build-replacement.ts:61-70tidyLayout 기본 false
공간 정돈 본체comp-match/tidyLayout.ts815줄 · buildTidyLayoutBboxMap
병합 트리 생성comp-match/matching.ts:459한 단계 자식 병합
병합 감점comp-match/scoring.ts:456step(step+1)/2
재배치 후보 · 지표src/post-replace-relayout/MOR-2018의 구현 대상 · 14,836줄
컨테이너 판정relayout-core/metrics.tsfindTextContainer — 넘침·겹침 전부의 기반

miricanvas-web-2 — 렌더러 쪽 (블랙박스)

무엇파일메모
대치 4단계buildMappedComponentSheetJson.ts:108내용→폰트→스타일→이미지
SmartBlock 자동 레이아웃AbstractSmartBlockLayoutWithChildrenStrategy.tsFlex · Grid · V1 세 구현
캔버스 반영ComponentItemReplaceCommand.ts대치의 종착점

⚠ 렌더러(텍스트 흘리기 · 폰트 오토핏 · 재레이아웃)는 우리 통제 밖이다. 끄는 레버는 shrinkConfigs 하나뿐이고, 줄바꿈·재레이아웃은 그래도 일어난다.

aippt-prisonbreak

이 문제에 직접 닿는 코드는 없다 — RLSC(structure_json)를 생산하는 쪽이라 대치·정렬 런타임에는 관여하지 않는다. 다만 대치의 판단 근거인 Component RLSC가 여기서 나오므로, "구조가 애초에 잘못 잡혔나"를 의심할 때 거슬러 올라가는 지점이다 (RLSC 생성 여정).

§5

작업 항목 — 지금 열려 있는 것

담당을 가르는 질문(A)과, 그와 별개로 이미 돌고 있는 근본 해결 작업(B)을 나눠 적는다. B는 MOR-2018 의 조사·구현 문서에서 가져왔고, 아래 ↻ 표시가 붙은 표는 원본이 바뀌면 sync-sources.py 로 다시 채워진다.

A. 담당과 에스컬레이션

담당 — 홍지혜

병합 · 대치 · 정돈 갈래(④a)는 홍지혜가 맡는다. 이석님 Pod 이 이미 만들어 둔 접근(tidyLayout · comp-sign 스마트블록 대치)은 「기존 접근 방법」 절로 뺐고 참고만 한다 — 전제로 삼지 않는다. 실제 해결 경로는 아래 B 다.

A-1

장주영 — 생성엔진 영역이면 에스컬레이션

조건부 장주영 · AI연구팀

확인 결과 생성엔진 영역이면 AI연구팀으로 넘긴다. ailabs SmartBlock 생성기 소관일 때만.

A-2

제품 판단 — 우선순위·PRD

상시 김수현 · 정원석

우선순위·PRD는 내용시각화 스쿼드가 갖는다 — 김수현(스쿼드 리더) + 정원석(PM-E), 창석님은 요청자.

한 줄 결론

문제가 나는 지점(병합 · 대치 · 정돈)은 홍지혜가 맡는다. 이석님 Pod 의 기존 구현은 참고 자료이고, 구조 재배치가 필요할 때만 주영님.

B. 근본 해결 — post-replace-relayout (MOR-2018)

"내용 대치가 끝난 컴포넌트를 ① 넘침 ② 과도 축소 ③ 여백 낭비가 없도록 재정렬한다." 정확히 이 페이지의 문제이고, 후보 다섯 개가 이미 구현되어 돌고 있다.

하위 문서 — 폰트 축소 하한

후보 다섯을 다 돌리고도 남는 FAIL 을 글자를 줄여 풀 수 있나, 줄인다면 어디서 멈춰야 하나. 커밋된 119건 실측과 하한 기준의 결정 (「원안 대비 배율」 vs 「페이지 대비 크기」)을 그 페이지에 따로 뒀다.

B-0

채점 방식 결정 — 다른 모든 작업의 전제

최우선 방법론 결정

정답(expected_result.json)이 스크립트 산출물이라 알고리즘이 같은 절차를 쓰면 채점이 순환한다. 커밋 a0cb02aa 에서 손으로 만든 정답이 스크립트 산출물로 덮였다.

  • (a) 정답을 사람이 다시 만든다 — 비용 크지만 채점이 뜻을 갖는다
  • (b) 절대 지표로만 채점 — 넘침·유휴 여백·겹침만. "얼마나 예쁜가"는 못 잰다
  • (c) 정답을 참고 답안으로 격하 — 정량 게이트가 사라진다

현재 코드는 (b)에 가깝게 이동했다 — README가 채점 기준을 original.json(대치 이전 원안)으로 바꿨다. 문서(w3 §5)와 코드의 결론이 갈리는 지점이라 확인이 필요하다.

B-1

후보 다섯 + 합본 넷 — 구현 완료, 실측 진행 중

구현됨 miricanvas-iui
  • method1세로 공간 재분배. 폭 고정이라 예측 0
  • method2가로 확장. 줄 수를 줄인다 · 줄바꿈 예측이 들어간다
  • method3가로 넘침 해소. 도형을 좌우로 키우고, 막히면 텍스트를 안쪽 폭으로 좁힌다
  • method4대치가 만든 겹침 해소 (유닛 사이) · 크기 고정 · 예측 0
  • method5유닛 안의 겹침 해소. 한 배경 도형 안에서 글자끼리 포개진 것

읽는 법 — 넘침을 줄이는 일은 합본 3+1+2 에서 끝난다 (4,107,470 → 534,454px², 87%). 게이트(신규 겹침)는 +4·+5+4 가 따로 푼다. tidy 열이 대조군이다 — 게이트 34/119로 before(35)보다도 낮다.

넘침 노드(H/V) 넘침 면적 게이트 PASS 폰트 배율(평균) 정렬선(평균)
original(기준)45 (39/11)1,086,451px²기준1.0001.000
before139 (48/111)4,107,470px²34/1111.0000.932
method167 (48/26)2,607,978px²40/1111.0000.913
method2111 (48/84)3,204,852px²36/1111.0000.891
method3117 (12/112)3,315,905px²35/1111.0000.927
합본 1+245 (43/6)1,816,735px²42/1111.0000.894
합본 3+1+214 (12/5)534,454px²43/1111.0000.895
합본 3+1+2+414 (12/5)534,454px²71/1111.0000.885
합본 3+1+2+5+414 (12/5)534,454px²83/1111.0000.864
합본 3+1+2+5+4+611 (9/4)368,345px²97/1110.9820.861
tidy126 (72/98)4,897,172px²34/1191.0000.900
expected(목표선)39 (25/24)699,729px²60/900.9930.849

post-replace-relayout 후보별 실측 — 원본에서 자동 동기화

B-2

착수 순서 — 공용 기반 먼저, method2 는 조건부

진행 MOR-2018 w3 §4.4

예비 실측에서 커밋된 7건 전부가 세로 여유만으로 부족분을 덮었다 — 가로 넘침 0건. 그래서 method2method1 이 실패하는 케이스를 찾은 뒤에 착수한다는 것이 원래 계획이었다. (실제로는 method3 이 필요해지면서 계획이 한 번 갈렸다 — B-1 참고)

# 항목 어디에 규모
0채점 방식 결정 (§5)먼저. 이게 없으면 비교 자체가 무의미
1tight box를 판정 기준으로 붙이기공용2일
2위상 동결 — 관계 그래프 추출공용3일
3Abacus PlaceRow + 스택 추출공용4일
4여백 대수(1D, 닫힌 형식)method12일
5최대 빈 사각형 열거method1 (+ 합본의 분기 기준)3일
6method1 완성 → 5건 채점
7DocIframepageJson 반환하도록 수정공용1일
8최소구성 + 자기 캘리브레이션method2조건부4일
9제약 그래프 여유 + 실현가능성method2조건부1주
10method2 완성 → 채점 → §4.3 판정

착수 순서 — 원본에서 자동 동기화

B-3

남은 확인 필요 항목 11건

미해결 MOR-2018 w3 §8

이 중 #1 채점 방식은 B-0이고, #6 폰트 복원·#7 행간 변경제품 결정이라 엔지니어링으로 못 넘긴다 — B-4.

# 항목 무엇을 막나 상태
1채점 방식 결정 (§5의 a/b/c)정답이 스크립트 산출물이라 지금은 채점이 성립하지 않는다. 다른 모든 작업의 전제최우선, 방법론 결정
2wrapBlock 오차 2건(78/80)의 정체 — CJK 금칙? 긴 라틴 토큰?4위 전체의 전제미측정
3tight box 굽기의 프로덕션 비용 (headless Chrome, 문서당)5위 [전] 적용 가능 여부미측정
4여백 균등 분배 vs 비율 분배2위의 유일한 설계 미결케이스로 확인 가능
5렌더러가 실제로 무엇을 바꾸나 — 특히 컨테이너를 키우면 폰트를 되돌리나5위 [후]의 "뜻밖의 이득" 가설pageJson을 버리고 있어 아무도 안 봄
6폰트 복원 권한 (original.json 사용 허용)§6.1 — 문제유형 ②를 다룰 수 있느냐제품 결정
7행간(lineSpacing) 변경 허용§6.2 — 가장 싼 세로 회수 수단제품 결정
8장식 요소 필터링의 정확도3위의 거짓 양수 사이클DECORATION_TYPES 재사용 검증
9기요틴 분해율 (샘플 ≥500)§6.4 계측기 착수w2에서 이월, 미측정
10케이스를 7건보다 늘려 method1이 실패하는 사례 찾기§4.3.1 실측이 7건 전부 "세로로 해결"이라 method2를 만들 근거가 아직 없다. 반례가 없으면 만들지 않는다미착수
11case.jsonproblems 라벨 채우기 (7건 중 6건이 비어 있음)케이스가 어떤 증상인지 사람이 분류한 기록이 없어 교차 검증이 불가능사람이 이미지를 봐야 함

남은 확인 필요 항목 — 원본에서 자동 동기화

테스트가 0개다wrapBlock·boxHeightOf·rendererLineCount 는 method 4·5위의 기반이고 findContainer·overflowOf 는 전부의 기반이라, 여기가 조용히 깨지면 전부 깨진다. (문서 기준. 현재 코드에는 relayout-core/ 아래 테스트 파일이 다수 있어 재확인 필요)

B-4

제품 결정 대기 2건 — 규칙 개정이 필요하다

대기 제품 판단 (A-2)
  • 폰트 복원 권한original.json(대치 전 원안)의 글자 크기로 되돌려도 되나. 허용하지 않으면 문제유형 ②(과도 축소)를 아예 다룰 수 없다.
  • 행간(lineSpacing) 변경 허용 — 현행 규칙(before-after-rules.md §2)이 금지한다. 하지만 행간 −20%는 세로 20%를 회수하면서 글자 크기 손실이 0이라 가장 싼 세로 회수 수단이다 (폰트 0.894와 동일한 면적 효과).

이 둘은 A-2(김수현·정원석) 이 답할 항목이다 — 엔지니어링 선택이 아니라 품질 정책이다.

B-5

확정된 결정 — 되돌리려면 근거가 필요하다

확정 MOR-2018 w2 §10
  • 결정론이 요구사항이다 — LLM·VLM 호출, 학습된 생성 모델, SA·force-directed 전부 채점 대상에서 제외. 같은 입력이 같은 출력을 내야 회귀 테스트가 성립한다. 이 결정이 tidyLayout(force-directed)을 후보가 아니라 대조군으로 만든 이유다.
  • 비겹침은 하드 제약tidyLayout 실측에서 5건 중 2건이 신규 겹침 게이트 FAIL, 1건은 중앙 오차 26.1 → 87.4. 소프트로 다루면 안 된다는 우리 데이터.
  • 연산 순서 — "크기 먼저 vs 위치 먼저"를 채택하지 않는다. 위상 고정 → 크기·위치 동시 → 여백 흡수 마지막.
  • 목적함수는 이차(QP) 필수, LP 금지 — 선형 목적함수는 slack을 한 변수에 몰아 "요소가 한쪽으로 치우침" 증상을 수학적으로 재현한다.
날짜 구분 항목 내용 반영 위치
2026-08-20확정Method 1 착수 승인w2 §3 "크기·위치 동시" 원칙과 모순 없음. 폭 동결 시 높이는 자유변수가 아니라 실측값 — 최소 섭동 목적 하에서 h_i* = h_실측,i가 조인트 최적임이 증명됨(h를 더 키우면 자기 페널티↑ + y 실현가능 영역↓). 잔여 (y, θ) 조인트 QP는 PlaceRow/여백대수가 정확해를 냄. Method 1 = 예측 0 부분공간으로 제한한 조인트 솔브이지 grow-then-move 휴리스틱이 아님. w2의 경고는 폭이 자유변수여서 피드백 루프가 있을 때의 얘기(→ Method 2 영역)w3 §4
2026-08-20확정갭 분배는 델타 균등(닫힌 형식)method1 노트 §5 장난감 예제의 완전 균등(55×4)과 w3 2위 닫힌 형식 θ_j = θ^orig + Δ/m(→ 25/45/25/125)이 불일치. 후자가 디자이너 여백 위계를 보존하므로 구현 기준. 완전 균등화는 idle-margin용 별도 플래그로 분리 채점w3 2위
2026-08-20권고착수 순서 #7을 #6 앞으로Method 1의 "예측 0"에 숨은 피드백 채널 = 렌더러 오토핏(박스 확대 → 폰트 복원 → 텍스트 높이 변화). h_실측은 현재 fontSizeScale에서 잰 값이라 최종 렌더와 어긋날 수 있음(w3 §8-5 "아무도 안 봄"). pageJson 회수(1일)를 m1 채점 전에 넣어 5건 채점을 render-verified로. "뜻밖의 이득"(증상 ② 간접 해결) 가설도 같은 실험에서 확인됨 — m1 vs m2 판정에 영향w3 §4.4, §8-5
2026-08-20권고m1 1차 채점은 보수 모드확대 + 법제화 + 델타 분배만. 미학적 채움·전면 균등화 제외 — §4.3 축 판정의 귀속(attribution) 보전w3 §4.3
2026-08-20권고배경 도형은 이동 결합이 아니라 크기 결합텍스트 박스가 자라면 배경 도형도 padding 보존으로 커져야 Rule.md §0 overlap 요구 유지. 재줄바꿈 없으므로 예측 0w3 1위 필요조건

Method 1 착수 전 재검토 결정 — 원본에서 자동 동기화

C. 참고 — MOR-2018 문서 지도

이 아카이브 표시가 붙은 둘은 이 사이트로 옮겨 왔다 — 사이드바에서 이 문서의 하위로 들어가 있고, 슬라이더·시뮬레이터도 원본 그대로 돈다. 나머지는 MOR-2018/ 안의 원본이다.

문서무엇
Rule.mdBefore/After 정의 규칙 · 불변 조건 · 문제 유형 ①②③
research/relayout-research_w2.md문헌 조사 정본 · 결정 로그(§10)
research/relayout-research_w3.md순수 알고리즘 Top 5 · 조립 계획(§4) · 남은 항목(§8)
post-replace-relayout_method1-method2-notes.mdMethod 1/2 직관 설명 · 장난감 예제
logics/find-text-container.mdfindTextContainer 판정 3순위 해부
logics/overlap-area-map.mdoverlapAreaMap · 신규 겹침 게이트
overlapAreaMap 겹침 게이트 이 아카이브지표 ⑥ 의 2단계 알고리즘 · 제외 규칙 다섯 · 판정 시뮬레이터. 원본 overlap-gate-notes.html
TC/ · 예시/테스트 케이스 sheetJson · Before/After 예시 이미지

logics/ 의 로직 문서는 사내에 배포되어 있다 — post-replace-relayout-key-func.miridih.app (VPN).

참고

기존 접근 방법 — 이석님 Pod 이 이미 만들어 둔 것

이 절은 참고용이다

아래는 이석님 Pod 이 이미 구현해 둔 접근이다. 담당이 홍지혜로 넘어왔으므로 이번 작업의 전제로 삼지 않는다 — 무엇이 이미 있고 어디까지 커버되는지 알아 두는 용도로만 읽는다.

실제 해결 경로는 §5-B(post-replace-relayout) 다. 그 안에서 tidyLayout 은 후보가 아니라 대조군으로 쓰인다.

tidyLayout 은 무엇인가 — 힘 일곱 개의 물리 시뮬레이션

각 노드의 bbox 네 변을 1D Verlet 입자로 두고, 아래 힘을 합산해 240회 적분한 뒤 최종 박스만 낸다. 결정론적이지 않고, 비겹침을 하드 제약으로 다루지 않는다 — 이 성질이 §5에서 문제가 된다.

내용
텍스트 확장 단방향예측 높이가 현재 박스보다 크면 verticalAlign 방향으로 확장. 작으면 그대로
텍스트 가로 확장 단방향세로로 겹치는 형제·부모 경계 안에서 horizontalAlign 방향으로 펼침 (WIDE_PADDING=24)
배경 확장 단방향자식이 커져 여백이 좁아지면 목표 여백(BG_MAX_MARGIN=24)까지 배경 변을 바깥으로
가이드 선 유지시작 시 같은 직선(GUIDE_TOL=4)에 있던 변들을 묶어 평균으로 당김. 부모-자식은 서로 영향 없음
겹침 방지형제끼리 겹치면 최소 침투축으로 밀어냄. 시작 시 이미 겹쳐 있던 쌍은 제외
여백 균형배경 컨테이너의 자식 텍스트에 한해 상하 여백이 같아지도록 세로 평행이동 (크기 보존)
페이지 제한 hard변을 페이지 안으로 clamp. 최초부터 밖이던 입자는 예외

ITERATIONS=240 · DAMPING=0.6 · comp-match/tidyLayout.ts:13-46

확인

tidyLayout 이 어디까지 커버하나 — 이석님께 확인할 것

참고 이석 · IUI 엔진 (구현자)

④a(기하적 정렬)가 tidyLayout 커버 범위인지, comp-sign '스마트블록 대치'로 ④b(구조적 재배치)까지 가능한지 확인.

  • 같이 물을 것 — 대치 시 tidyLayout 을 켜고 있나? 기본값이 false다(§1).
  • 같이 물을 것 — 켰을 때 신규 겹침 게이트에 걸리는 사례를 알고 있나? (MOR-2018 실측: 5건 중 2건 FAIL)