핵심 요약
연산자는 여전히 8개
method 1~8을 단독으로 등록한 8개와 합성 후보 9개를 합쳐 17개다. 새 연산자가 추가된 것이 아니라 3+1+2+5+4+7+8 조합이 추가됐다.
이동 기준은 실제 글자 영역
placementBoxMap이 글머리 기호를 포함한 글자 영역을 계산한다. method 7·8은 이 영역으로 유닛의 겹침 깊이와 이동 여유를 구한다.
축소 전에 먼저 실측
대표 조합의 검증 경로는 축소 전 문서를 렌더하고, method 5·7·8로 겹침을 다시 처리한다. 실측으로 통과한 문서는 method 6을 생략한다.
SUCCESS도 최대 10% 축소 허용
현재 SUCCESS의 최소 폰트 배율은 0.90이다. 신규 겹침·넘침·유휴 여백 조건도 충족해야 한다. 1.00만 허용하던 v0.6과 다르다.
근거: 내부 후보 레지스트리 · 실측 점유 영역 · 대표 조합·실측 검증 · 최종 판정
전체 실행 흐름
대표 조합은 3 → 1 ↔ 2 → 5 → 4 → 7 → 8 → 6이다. 다만 예측 경로와 실측 검증 경로는 실행 방식이 다르다. 모든 단계가 매번 문서를 바꾸는 것은 아니며, 처리 대상과 검사 결과에 따라 건너뛴다.
단계별 상세
대치 직후 문서와 원안 기준
rendered.json을 입력으로 받고 original.json의 좌표계를 맞춘다. 원안에서 텍스트 소속과 컨테이너 계층을 정해 전달한다.
추가 데이터: tight · baseTight · outlines
크기 조정 → 유닛 내부 정리 → 유닛 간 분리
- method 3 — 가로 넘침을 줄인다.
- method 1 ↔ 2 — 세로 여백을 재분배하고 필요한 텍스트 폭을 넓힌다. 가로 단계는 최대 3회이며, 상한에 도달하면 세로 단계로 한 번 더 마무리한다.
- method 5 — 같은 유닛 안에서 겹친 텍스트의 폭과 세로 배치를 조정한다.
- method 4 — 신규 겹침으로 묶인 밴드를 분리해 유닛을 세로로 배치한다. 짝 밀기는 여기서 실행하지 않는다.
세로 이동 후 가로 이동
method 7은 세로 빈 구간에 함께 배치하거나 두 유닛의 위·아래 이동량을 나눠 겹침을 줄인다. method 8은 가로로 분리할 쌍을 처리한다.
method 7의 스택 재배치는 유휴 비율 ≥ 0.5, 짝 밀기는 기본 문턱 0이다. method 8은 유휴 비율 ≥ 0.5일 때 실행한다. 모두 원안 대비 신규 겹침이 있어야 한다.
예측 경로
- 7·8의 결과에 method 6을 적용한다. 자체 판정이 FAIL인 경우에만 축소를 시도한다.
- 7·8이 실제로 이동했다면, 4까지의 결과에도 method 6을 적용해 비교 경로를 만든다.
- betterOf가 두 결과를 비교한다. 7·8이 이동하지 않았다면 비교 경로는 실행하지 않는다.
각 축소 시도에서 다시 실행하는 범위는 3+1+2+5+4다.
실측 검증 경로
- 축소 전 결과를 만든다. 7·8이 이동했다면 기본 배치 결과와 먼저 비교한다.
- 원안과 원안 tight가 있으면 렌더 후 runMethod5Verified로 유닛 내부를 정리한다.
- 새 tight로 method 7 → 8의 이동만 다시 시도한다. 이동했다면 결과를 다시 렌더한다.
- 완전한 실측으로 SUCCESS 또는 ACCEPTABLE이면 축소 없이 반환한다. 아니면 원래 입력에서 A 경로를 실행한다.
최종 글자 영역을 도형 외곽선과 다시 비교
실측 → 내부 겹침 정리 → 이동 전용 보정 → 필요 시 후보 재실행 → 위치·도형 크기 보정 → 마지막 폰트 축소 순으로 확인한다. 문서가 바뀌면 다시 렌더한다.
외곽선 데이터가 있을 때 실행한다. 반복 상한에 도달하거나 해결하지 못한 채 반환할 수도 있으므로, 반환됐다는 사실만으로 SUCCESS를 뜻하지 않는다.
replaceLayoutVerified에서 호출하며, 동기 함수 replaceLayout에는 포함되지 않는다. 뷰어는 먼저 예측 결과를 표시한 뒤 검증 결과를 반영한다.근거: 예측 진입점 · 실측 검증 진입점 · 1↔2 반복 · 축소 전 비교 · 대표 조합·예측 · 대표 조합·실측 검증 · 공통 외곽선 보정 · 뷰어의 검증 호출
배치 단위와 판정 기준
| 용어 | 의미 | 주의할 점 |
|---|---|---|
| 유닛 · unit | 함께 움직이는 단위. 배경 도형과 그 안의 텍스트 등을 묶는다. | 같은 유닛의 글자를 통째로 옮기면 내부 겹침은 줄지 않는다. 내부는 method 5가 처리한다. |
| 밴드 · band | 처리 축의 구간이 겹쳐 함께 배치되는 유닛 묶음. | method 4는 splitUnitPairs로 특정 쌍이 같은 밴드로 묶이지 않게 한다. |
| 체인 · chain | 같은 축의 공간을 나눠 쓰는 배치 묶음. | axisChains는 해당 시점의 좌표와 분리 조건으로 밴드·체인을 계산한다. |
| 프레임 · frame | 노드의 좌표·크기 또는 배치 경계로 사용하는 박스. | 실제 글자가 차지하는 영역과는 다를 수 있다. |
| 소속·계층 | containers와 containerParents. 원안에서 텍스트 소속과 컨테이너의 부모 관계를 정한다. | 기본 경로는 자동 추론한다. 승인된 정답 관계를 주입하는 fixedContainers는 별도의 평가 용도다. |
파이프라인 전체에서 모든 관계를 한 번만 계산하는 것은 아니다
replaceLayout이 원안에서 소속·계층을 정해 전달하고, 개별 단계가 freezeRelations로 필요한 배치 그래프를 만든다. axisChains는 이동·확장 뒤 좌표로 다시 계산할 수 있다. v0.6 흐름도의 “이후 재계산 없음”을 전체 실행의 규칙으로 읽으면 현재 코드와 맞지 않는다.
단계별 검사와 최종 판정은 구분한다
이동을 채택할 때는 단계 입력보다 다른 겹침 쌍을 키우지 않았는지, 원안 대비 신규 겹침이 감소했는지, 넘침이 늘지 않았는지 등을 검사한다. 검사 항목과 허용 오차는 단계마다 다르다. 예를 들어 method 5의 실측 경로는 측정 누락, 유닛 내부 잔여 겹침, 페이지 잘림 증가도 확인한다.
1.00이었다 — 현재는 0.90이라 오른쪽 초록 구간이 10% 넓어졌다.
배율이 구간 안에 들어와도 나머지 조건에서 떨어질 수 있다.
| 최종 라벨 | 현재 조건 |
|---|---|
| UNKNOWN | 결과 지표나 원안 기준이 없다. requireComplete: true이면 tight 누락이나 외곽선 판정 불완전도 UNKNOWN이다. |
| FAIL | 넘침 노드가 원안보다 많거나, 넘침 면적이 원안의 110%를 초과하거나, 신규 겹침 쌍이 있거나, 최소 폰트 배율이 가독성 하한보다 작다. 기본 하한은 0.70이다. |
| SUCCESS | FAIL 조건이 없고, 최소 폰트 배율이 0.90 이상이며, 유휴 여백 비율이 원안 이하이다. 배율·여백 비교에는 VERDICT_EPS = 0.0005를 적용한다. |
| ACCEPTABLE | FAIL은 아니지만 SUCCESS의 폰트 또는 여백 조건을 충족하지 못한다. |
| UNSOLVABLE | 결과 지표가 없고 규칙 안에서 해답을 만들 수 없다는 사유가 명시돼 있다. 일반적인 실행 실패와는 구분한다. |
SUCCESS가 반드시 “넘침 0”이나 “폰트 크기 유지”를 뜻하지는 않는다. 근거: 배치 관계 구성 · 밴드·체인 계산 · 예측 진입점 · 이동 결과 검사 · method 5 실측 검증 · 최종 판정
연산자 8개와 등록 후보 17개
왜 17개인가?
단독 연산자 8개 + 합성 후보 9개 = 내부 등록 후보 17개다. 합성 후보는 기존 method들을 조합한 실행 경로다. method 9가 생긴 것이 아니다. 화면에서는 이 목록을 모두 노출하지 않고 Adaptive Relayout과 tidyLayout 두 항목만 보여 준다.
8개 연산자의 역할
| 연산자 | 처리 대상 | 주요 동작 | 현재 구현에서 볼 점 |
|---|---|---|---|
| method 1 | 세로 공간 부족 | 컨테이너 높이와 세로 여백을 조정하고 체인을 배치한다. | 가로 폭을 유지한 채 세로 문제를 먼저 푼다. |
| method 2 | 넘침·좁은 열·전달받은 충돌 텍스트 등 | 이웃과 도형 경계 안에서 폭을 넓혀 줄바꿈을 줄인다. | 폭이 바뀌면 기존 tight를 그대로 사용할 수 없다. 검증 경로에서는 재렌더한다. |
| method 3 | 가로 넘침 | 도형 확장과 텍스트 폭 조정을 검토한다. | 원안의 컨테이너 관계와 외곽선 한계를 함께 사용한다. |
| method 4 | 유닛 간 신규 겹침 | 밴드를 분리하고 여백 재분배·placeRow로 세로 배치한다. | 짝 밀기 제거. 밴드 분리만 담당한다. |
| method 5 | 같은 유닛 안의 텍스트 겹침 | 폭 확장, 세로 재배치, 필요한 공간 확보를 시도한다. | 실측 경로는 먼저 현재 폭으로 재배치하고, 실패하면 폭을 넓혀 다시 측정·배치한다. |
| method 6 | 앞 단계에서 해결하지 못한 결함 | 대상 텍스트의 폰트를 단계적으로 줄이고 배치를 다시 계산한다. | 기본 상대 하한 0.70과 페이지 높이 기반 하한 중 더 엄격한 값을 적용한다. |
| method 7 | 유닛 간 세로 분리 대상 | 세로 빈 구간에 스택으로 배치하거나 위·아래 이동량을 나눠 겹침을 줄인다. | 스택과 짝 밀기의 여백 문턱이 다르다. 실측 점유 영역을 사용한다. |
| method 8 | 유닛 간 가로 분리 대상 | 좌우 이동 여유를 계산해 한쪽 또는 양쪽 유닛을 이동한다. | 세로 위치와 크기를 유지한다. 실측 점유 영역을 사용한다. |
등록된 합성 후보 9개
| 조합 | 의미 |
|---|---|
1+2 | 세로 조정과 가로 확장의 반복 |
3+1+2 | 가로 넘침 조정을 먼저 수행 |
3+1+2+4 | 유닛 간 밴드 분리 추가 |
3+1+2+5+4 | 유닛 내부 정리 후 유닛 간 분리 |
3+1+2+5+4+7+8 | v0.6 이후 추가. 폰트 축소 없이 세로·가로 여백을 활용하는 조합 |
3+1+2+5+4+6 | 기본 배치 후 폰트 축소 |
3+1+2+5+4+7+6 | 세로 여백 활용 후 폰트 축소 |
3+1+2+5+4+8+6 | 가로 여백 활용 후 폰트 축소 |
3+1+2+5+4+7+8+6 | 현재 Adaptive Relayout에 연결된 대표 조합 |
표에서는 반복되는 method 접두어를 생략했다. 실제 등록 키는 method3+method1+… 형식이다. tidyLayout은 이 17개에 포함되지 않는다. 근거: 내부 후보 레지스트리 · 화면 선택지 · method 1 · method 2 · method 3 · method 4 · method 5 실측 검증 · method 6
method 7·8은 겹침 방향을 나눠 처리한다
두 연산자는 겹친 유닛의 실측 점유 영역에서 가로 겹침 길이 ix, 세로 겹침 길이 iy, 한 열에 포함되는지 여부를 계산한다. 같은 유닛 또는 부모·자식 관계인 유닛은 이 분리 대상에서 제외한다.
method 7 · 세로
- 같은 방향으로 분리할 유닛 쌍을 연결 성분으로 묶는다.
- 스택 조건과 여백 문턱을 충족하면
verticalCorridor안에서placeRow로 함께 배치한다. - 스택 배치가 불가능하면 위·아래 여유에 맞춰 균형 이동 → 한쪽 이동 → 부분 이동 후보를 만든다.
- 검사 조건을 통과하는 이동을 채택한다. 짝 밀기는 클러스터마다 최대 20회 시도한다.
method 8 · 가로
- 유휴 여백 비율이 기본 문턱
0.5이상인지 확인한다. - 현재 좌표에서 가로 분리 대상과 좌우 이동 여유를 계산한다.
- 한쪽 또는 양쪽 이동 후보를 만들고 검사 조건을 통과한 결과를 채택한다.
- 실패한 쌍은 같은 실행에서 반복 시도하지 않는다. 전체 반복 상한은 20회다.
방향 구분이 모든 겹침의 해결을 보장하지는 않는다
동일한 좌표에서 세로·가로 조건은 겹치지 않는다. 하지만 7이 이동한 뒤 8이 다시 판별하므로 처리 대상은 실행 시점마다 달라진다. 여백 부족, 측정 누락, 부모·자식 관계, 결과 검사 때문에 이동하지 않는 쌍도 있다. v0.6의 “한 쌍을 정확히 한쪽이 처리한다”는 표현은 분류와 실제 해결을 구분해 읽어야 한다.
근거: method 7 방향 판별 · method 8 방향 판별 · method 7 · method 8
v0.6 이후 달라진 점
| 항목 | v0.6의 설명 | 현재 코드 |
|---|---|---|
| 등록 후보 | 단독 8 + 합성 8 = 16개 | 축소 없는 3+1+2+5+4+7+8을 추가해 17개. 연산자는 8개 그대로다. |
| 세로 짝 밀기 | method 4의 대칭 이동과 method 7의 여유 기반 이동이 중복됨 | method 7로 통합. method 4에는 밴드 분리만 남았다. |
| method 7 발동 조건 | 후보 전체에 유휴 비율 ≥ 0.5 적용 | 스택은 idleThreshold = 0.5, 짝 밀기는 nudgeThreshold = 0. 원안과 신규 겹침 조건은 유지한다. |
| 겹침 상수 | OVERLAP_EPS가 100과 1의 서로 다른 의미로 쓰임 | 겹침 최소 면적 OVERLAP_MIN_AREA = 100과 이동 단계의 증가 허용 오차 OVERLAP_GROWTH_EPS = 1로 이름을 구분했다. |
| 이동 계산 영역 | 실측 tight를 지표·게이트에 전달하는 흐름 중심 | placementBoxMap을 추가해 대상 선택·겹침 깊이·스택 높이·장애물 여유도 실제 글자 영역으로 계산한다. |
| 유닛 내부 겹침 | 주로 프레임 기반 예측으로 처리 | runMethod5Verified에서 실측으로 재배치한다. 폭을 바꾸면 다시 렌더하고, 유닛 내부가 모두 해결됐는지 확인한다. |
| 축소 전 확인 | 대표 조합의 마지막에 method 6 실행 | 검증 경로에서 축소 전 실제 렌더 판정을 추가했다. 이미 통과한 결과는 불필요한 축소를 피한다. |
| 외곽선 보정 후 겹침 | method 6 내부 재호출에서 7·8이 빠지는 구조 지적 | 그 재호출 범위는 여전히 3+1+2+5+4다. 별도로 공통 검증 루프가 새 측정값을 받아 refineMeasured로 7·8을 재실행한다. |
| SUCCESS 폰트 기준 | 최소 폰트 배율 = 1.00 | 0.90 이상. FAIL의 기본 하한 0.70과는 별개다. |
| 화면의 후보 선택 | 전체 후보 목록과 선택기 설계를 함께 설명 | 화면은 Adaptive Relayout / tidyLayout으로 단순화했다. 실험 후보는 내부 레지스트리에 유지한다. |
아직 남아 있는 중복과 한계
penetrationOf와 COLUMN_EPS는 여전히 method 7·8에 각각 정의돼 있다. 공통 함수로 추출된 것은 아니다. method 6의 동기 경로도 계속 프레임 대용 측정값을 사용한다. 따라서 예측 경로 전체가 실측 기반으로 바뀌었다고 설명하면 안 된다.
근거: 내부 후보 레지스트리 · method 4 · method 7 · 겹침 최소 면적 · 실측 점유 영역 · method 5 실측 검증 · 대표 조합·실측 검증 · 공통 외곽선 보정 · 최종 판정 · 화면 선택지
반복 상한과 실행 비용
v0.6의 1,177건 실행 빈도와 문서 크기는 과거 코퍼스의 측정값이다. 현재는 실제 렌더와 재측정이 추가됐으므로 당시 비율로 현재 병목을 단정할 수 없다. 여기서는 실행 코드에서 확인한 반복 범위를 정리한다.
| 구간 | 현재 반복 범위 | 비용을 읽는 방법 |
|---|---|---|
| method 1 ↔ 2 | method 2 최대 3회, method 1 최대 4회 | 3번의 가로 조정 뒤에도 변화가 있으면 세로 단계로 한 번 더 마무리한다. 단순히 “전체 최대 3회”라고 쓰면 부정확하다. |
| method 7 | 스택 배치 시도 후 클러스터별 짝 밀기 최대 20회 | 이동 시도마다 점유 영역과 겹침을 다시 계산한다. 20회는 문서 전체의 상한이 아니다. |
| method 8 | 가로 분리 반복 최대 20회 | 각 반복에서 남은 쌍을 재탐색하고, 한 쌍에 여러 이동 후보를 검사할 수 있다. |
| method 6 | 배율을 0.05씩 낮춘다. 기본 상대 하한 0.70이면 최대 6개 배율 단계 | 노드별 페이지 높이 하한이 더 엄격하면 더 일찍 끝난다. 각 시도에서 기본 조합 3+1+2+5+4을 다시 실행한다. 설정을 바꾸면 횟수도 달라진다. |
betterOf | 두 문서의 지표를 비교 | 함수 자체가 method 6을 실행하지는 않는다. 호출자가 비교할 두 결과를 만드는 데 추가 비용이 든다. |
| 공통 외곽선 보정 | 기본 최대 10라운드 + 반복 종료 후 최종 실측 | 내부 method 5 검증에도 렌더 호출이 있으므로 “렌더 최대 11회”로 해석하면 안 된다. |
1 ↔ 2는 바깥 네 겹이 한 번 돌 때마다 다시 돈다.
반대로 method 7·8은 method 6 안에 들어 있지 않다 — 축소가 끝난 뒤 공통 루프에서 따로 재실행된다.
계산량
leaf 수를 L이라 할 때 겹침 쌍 비교는 최대 O(L²) 규모다. placeRow는 정렬을 포함해 O(k log k)이며, 여백 재분배는 반복 하한 보정 비용이 있다. 전체 비용에는 이 계산들의 호출 횟수와 외곽선 처리·렌더 시간이 더해진다.
메모리와 복제
후보는 입력을 직접 바꾸지 않고 새 문서를 반환한다. 이동·확장·축소 시도마다 structuredClone 사본을 만들고, 두 경로 비교에서는 결과 문서들을 동시에 보관한다. 실제 메모리 사용량은 JSON 크기만으로 환산할 수 없다.
현재 실행 시간·메모리는 이 문서 갱신 과정에서 새로 벤치마크하지 않았다. 근거: 1↔2 반복 · method 7 · method 8 · method 6 · 두 경로 비교 · 공통 외곽선 보정 · 1차원 배치 · 여백 재분배
두 경로 비교와 전체 후보 선택
betterOf는 받은 두 문서를 비교하는 함수다. 등록 후보 17개를 모두 실행해 최선을 고르는 선택기는 아니다. 대표 조합에서는 여백 활용 단계를 거친 결과와 이를 생략한 결과를 비교하는 데 사용한다.
| 구분 | 현재 동작 |
|---|---|
| 단계별 검사 | 한 번의 이동·확장 결과를 채택할지 결정한다. 다른 쌍의 겹침 증가 등을 검사한다. |
betterOf | 두 경로의 결과를 여섯 지표로 비교한다. 판정 라벨, 유휴 여백, 총 이동 거리는 직접 비교하지 않는다. |
| 뷰어의 Adaptive Relayout | 현재 대표 조합 한 개를 연결한 표시 이름이다. 케이스마다 전체 후보를 자동 탐색한다는 뜻은 아니다. |
| 전체 후보 선택기 설계 | 여러 후보의 결과를 비교하는 별도 설계다. 현재 METHODS와 진입점에는 이를 실행하는 선택 후보가 등록돼 있지 않다. |
비교 결과의 보장 범위를 넓혀 해석하지 않는다
여섯 지표를 사전순으로 비교하므로 앞 지표가 개선되면 뒤 지표가 악화돼도 도전 경로를 고를 수 있다. “모든 지표가 나빠지지 않는다”, “항상 더 좋은 판정 라벨을 선택한다”, “전체 디자인 품질을 보장한다”는 의미는 아니다.
근거: 두 경로 비교 · 축소 전 비교 · 대표 조합·예측 · 화면 선택지 · 내부 후보 레지스트리
이동 가능한 여백 찾기
idleMarginRatio는 페이지 전체의 유휴 여백 비율이다. 실제 이동에는 “얼마나 비었는가”뿐 아니라 어느 방향으로 얼마나 움직일 수 있는가가 필요하다. idleSpace.ts가 다음 세 가지를 제공한다.
obstaclesFor
이동을 막는 노드의 점유 영역을 수집한다. 자기 유닛, 장식, 페이지 배경 등 제외 조건을 적용한다. method 7·8에서는 텍스트의 실제 영역이 반영된 지도를 넘긴다.
directionalSlack
상자 하나가 장애물과 페이지 경계에 닿기 전까지 이동할 수 있는 위·아래·왼쪽·오른쪽 거리를 구한다. 이 거리로 이동 후보를 만든다.
verticalCorridor
클러스터가 사용할 수 있는 연속된 세로 빈 구간을 찾는다. method 7은 이 구간에 유닛들을 placeRow로 배치할 수 있는지 확인한다.
idleMarginRatio는 페이지 전체가 얼마나 비었는가만 말한다.
실제로 움직이려면 어느 방향으로 얼마나가 필요해서 이 두 함수가 따로 있다.
문턱(0.5 · 0)을 넘어도 여기서 여유가 안 나오거나 결과 검사에 걸리면 문서는 그대로다.
현재의 여백 문턱
| 단계 | 공통 조건 | 여백 조건 |
|---|---|---|
| method 7 · 스택 배치 | 원안 존재 + 신규 겹침 존재 + 이동 가능한 점유 영역 | idleMarginRatio ≥ idleThreshold · 기본 0.5 |
| method 7 · 짝 밀기 | 위와 동일 | idleMarginRatio ≥ nudgeThreshold · 기본 0 |
| method 8 · 가로 이동 | 원안 존재 + 신규 겹침 존재 + 가로 분리 대상 | idleMarginRatio ≥ idleThreshold · 기본 0.5 |
이 문턱은 여백을 그 비율까지 줄이라는 목표가 아니다. 특정 이동 방법을 시도할 조건이다. 문턱을 통과해도 실제 이동 여유가 없거나 결과 검사에 실패하면 문서는 유지된다.
실측과 외곽선 보정
좌표를 쓰는 박스와 이동 여유를 재는 박스를 분리한다
| 데이터 | 쓰임 | 유효성 |
|---|---|---|
absBoxMap | 실제 노드 프레임. 부모·자식 관계와 좌표 쓰기의 기준 | 배치 그래프를 만들거나 translateNode로 좌표를 반영할 때 사용한다. |
tight + visualBoxMap | 렌더러가 측정한 글자 영역에 글머리 기호 등을 반영 | 프레임의 빈 공간과 실제 글자 영역을 구분한다. |
placementBoxMap | 텍스트는 visual box, 나머지는 프레임으로 구성한 이동 계산용 지도 | 텍스트를 측정하지 못했다면 null을 반환해 이동을 보류한다. 빈 텍스트는 점유 영역에서 제외한다. |
placementUnitBox | 유닛 전체가 차지하는 영역 | 배경 도형의 범위를 유지하면서, 도형 밖으로 나온 실제 글자도 포함한다. |
carryTightBoxes | 기존 실측값을 변경된 문서에 승계 | 노드 프레임의 폭·높이가 허용 오차 안에서 같은 값만 승계한다. 텍스트 내용이나 폰트 변경을 별도로 검사하는 함수는 아니므로 새 측정을 대신하지 않는다. |
frameBoxesAsTight | 실측 없이 프레임으로 계산하는 예측용 대체값 | method 6의 동기 경로 등에 남아 있다. 실제 측정 결과로 표시하면 안 된다. |
“실측을 주지 않음”과 “제공된 실측이 불완전함”은 다르다
method 7·8에 judge를 주지 않으면 프레임 대용 경로로 실행할 수 있다. 반면 실측을 전달했는데 크기 변경 등으로 승계가 끊기거나 측정이 누락되면, placementBoxMap은 그 글자를 빈 공간이나 프레임으로 임의 대체하지 않는다. 새 측정값이 생긴 뒤 이동을 재시도한다.
공통 검증 루프의 실제 순서
- 현재 문서를 렌더한다. 실제 글자 영역과 컨테이너 외곽선을 비교한다. 필요한 데이터가 완전하고 최종 판정을 통과하면 즉시 반환한다.
- 유닛 내부를 다시 확인한다.
runMethod5Verified가 글자 높이와 줄바꿈을 실측해 겹침을 줄인다. 변경됐다면 다음 라운드에서 다시 측정한다. - 유닛 간 이동을 다시 시도한다. 대표 조합의
refineMeasured가 새 tight로 method 7·8을 실행한다. 크기는 바꾸지 않으며, 이동한 결과도 다음 라운드에서 재렌더한다. - 필요하면 후보를 다시 실행한다. 같은 문서에는 한 번만 실행하고, 외곽선 보정이나 축소로 문서가 달라지면 다시 허용한다.
- 외곽선 안으로 위치를 보정하거나 도형을 키운다. 같은 위치에서 무한히 확장하지 않도록 기하 보정 단계를 제한한다.
- 해결되지 않은 텍스트만 줄인다. 0.05 단위로 줄이되 원안 대비 하한을 확인한다. 폰트가 바뀌면 다시 렌더한다.
- 해결되지 않아도 반복을 끝낸다. 기본 10라운드 후 최종 실측을 남긴다. 외곽선 문제 해결 여부와 전체 판정은 서로 다른 값이다.
외곽선 데이터가 없으면 공통 루프는 보정 없이 반환한다. fitActualTightToOutlines의 report.resolved는 외곽선 문제와 측정 누락에 관한 값이며 전체 겹침·가독성·여백 통과를 보장하지 않는다. 근거: 실측 점유 영역 · 유닛 점유 영역 · 실측값 승계 · method 5 실측 검증 · 새 실측 후 이동 보정 · 공통 외곽선 보정
최근 검증 기록
저장소의 2026-08-30 검증 보고서 기준
다음 값은 이번 문서 수정 중 새로 실행한 벤치마크가 아니다. 기준 커밋에 포함된 검증 보고서의 결과를 인용했다. 보고서는 전체 100개 중 평가 가능한 동일 88개를 비교하고, 12개는 제외했다고 명시한다. 원본 실행 JSON은 현재 작업트리에 없어 수치를 독립 재계산하지 않았다.
| 동일 88개 평가 범위 | SUCCESS | ACCEPTABLE | FAIL | UNKNOWN |
|---|---|---|---|---|
| 실측 점유 영역 적용 전 | 67 | 14 | 7 | 0 |
| 실측 점유 영역 적용 후 | 70 | 16 | 2 | 0 |
보고된 측정 시간: 2026-08-30 20:28:44~20:29:16 KST. 판정 하락 0건·신규 FAIL 0건. 이전 85건·96건·1,177건 결과와는 평가 범위 및 코드가 다르므로 직접 증감 비교하지 않는다.
실측 글자 영역으로 겹침을 줄인 5개 사례
| 케이스 | 변경 전 신규 겹침 | 변경 후 | 판정 | 최소 폰트 배율 |
|---|---|---|---|---|
5647291 | 3,167px² · 1쌍 | 0 | ACCEPTABLE | 1.00 |
5836322 | 6,102px² · 1쌍 | 0 | ACCEPTABLE | 1.00 |
6567992 | 9,069px² · 1쌍 | 0 | SUCCESS | 1.00 |
6720819 | 2,808px² · 1쌍 | 0 | ACCEPTABLE | 0.70 |
6478618 | 44,824px² · 4쌍 | 0 | SUCCESS | 1.00 |
남은 문제와 검증 한계
보고서의 잔여 FAIL은 6248263의 도형 간 추가 겹침 399px²와 6690122의 도형·이미지 추가 겹침 3,633px²다. 좁은 열, 장식선 교차, 문단 간격 등 시각적 문제도 일부 남아 있다. 지표 통과를 디자인 품질 전체의 통과로 해석하지 않는다.
같은 보고서의 테스트 결과는 7,915개 통과·8개 실패다. 실패 8개는 수정 전 코드에서도 재현됐다고 기록돼 있다. 이 문서 갱신 과정에서는 재배치 구현이나 해당 테스트를 변경하지 않았다.
출처와 재현 절차: 2026-08-30 검증 보고서
코드 지도
아래 링크는 모두 miricanvas-iui의 7b4354f62f79b66af80e0d05fb6cf12023431b75 커밋을 가리킨다. 작업트리의 인용 파일에 변경이 없음을 확인했으며, 줄 번호도 해당 파일에서 추출했다.
과거 문서와 현재 코드를 함께 읽을 때
v0.6은 2026-08-28의 구현·측정 기록이다. v0.7은 여기에 후보 수, 단계별 여백 조건, 실측 점유 영역, 축소 전 검증, 공통 외곽선 보정, 현재 판정 규칙을 반영했다. 이전 문서의 코드 주소나 측정값을 현재 코드에 그대로 적용하지 않는다.