아카이브 · 당시 기준

2026-10-26 보관. 1.0.0 → 1.1.0 · MINOR: miricanvas-iui origin/main 04585231 재대조, Stage bit 설명과 제목 링크 추가 본문과 자동 동기화 표는 보관 당시 내용입니다.

현재 기준과 원본 보기 → · 보관 목록

← 미리디 기술 사전 / Visual Summary

ALGORITHM CLASS2026-10-18 origin/main 대조 · 저자 홍지혜(jhhong) · 이전판

comp-frame 검색과 대치
Rust 실행 기준

검색 실행은 Rust, 색인·공통 계약·클라이언트·화면은 TypeScript가 맡는다. 2026-10-17 고정 소스로 tier·중첩·대치 정책과 표·나눠 담기를 함께 읽는다.

§0

현재 실행 지도: Rust 검색과 TypeScript 대치

comp-frame은 사용자 내용이 기존 디자인의 어느 슬롯에 들어갈지 검색 단계에서 미리 계산한다. 2026-10-12 이후 검색·랭킹·중첩·Content Threading은 Rust 서버만 구현한다. 브라우저가 후보 DB를 직접 조회하고 TS 검색을 실행한다는 이전 설명은 현재 경로가 아니다.

사용자 글 / Visual Summary → 서버 생성·문서 검색 → Query Frame ↔ 색인 Frame → binding·검사·순위 → 클라이언트 대치 → 렌더
구분무엇을 바꾸나
Tier 1·2·3검색할 카테고리: 요청 type / 자기 행 fallback / 종단 하나
Stage 0·1·2같은 카테고리 안에서 슬롯 모양 비트 차이 0 / 1 / 2
N1~N5중첩 구조와 노드별 카테고리를 어느 순서로 포기하나
0군·1군사용자 지정 종류 결과 / 추천 결과. Tier와 다른 축

코드 근거 · 문서 한 번 요청

코드 근거 · TS 검색 제거 기록

§1

입력과 출력: 검색 결과는 아직 렌더가 아니다

공개 ComponentSearchClient.search는 raw-text 또는 visual-summary를 받는다. 원문 경로는 생성·검색·병합·랭킹을 서버가 한 요청 안에서 끝낸다. entries에는 단일 후보와 여러 컴포넌트의 묶음 후보가 함께 들어올 수 있다.

출력읽는 법
binding실제 sheet_id와 사용자 글. 표·차트 grid는 matrix를 함께 갖는다
blank / preserve미대치 슬롯의 분류. preserve도 최종 원문 보존 확정은 아니다
outside_text / inside_unbound_text선택된 경계 밖 / 경계 안의 미매핑 글
threading.pages여러 장으로 나눠 담은 경우의 장별 binding. 상위 binding은 첫 장
meta / tier / matched_category검색·배제·투영을 진단하는 정보. 운영 품질 점수와 다르다

제품은 별도 백엔드에서 받은 searchKey·활성 componentVersion을 전달하고, 디자인 문서를 component.uuid로 받아 buildReplacement에 넣는다. 검색 통과 후에도 실제 렌더의 겹침·잘림·문장 의미를 확인해야 한다.

코드 근거 · 제품 호출 흐름

§2

Frame v5: 사용자 글과 디자인 슬롯의 공통 계약

질의 Frame은 넣을 글을, 색인 Frame은 실제 노드 주소와 글 용량을 담는다. units는 항목, fields는 label·value·items 등의 슬롯, satellites는 공통 머리말, dataset은 표·차트 데이터다. aliases는 같은 물리적 칸의 다른 필드 이름이며 한 노드를 두 번 채우는 허가가 아니다.

현재 FRAME_VERSION = 5다. 적재 측 buildIisFrame은 IIS 구조 대응을 실제 노드와 연결하고, 만들 수 없으면 규칙 기반 Frame을 시도한다. 표 셀 지도와 표 기하도 색인에 들어간다. Frame 스키마 버전, IIS 발행분, 제품 componentVersion, 서버 배포 버전을 혼동하지 않는다.

코드 근거 · packages/comp-frame-shared/src/frame.ts

코드 근거 · packages/comp-frame-index/src/frame/component-frame.ts

§3

Tier와 projection: 원래 카테고리의 행을 따른다

Tier현재 Rust 규칙
1type의 성립 조건을 통과한 카테고리. alternatives는 읽지 않는다
2원래 type의 fallback 행을 순서대로. 각 도착지는 원본 내용에서 projection한 뒤 성립 검사
3List·LongFormTextLayout·HighlightedMessage 중 내용으로 고른 종단 하나. 이미 앞 군에 있으면 생략

예: Timeline → Steps → Staircase → List. Steps의 행으로 갈아타지 않고 Timeline의 행을 끝까지 본다. 날짜 전용 필드를 못 읽는 도착지에서는 P3이 날짜를 items로 옮긴다. P2는 읽지 않는 params를 제거하고 P4/P5/P6은 데이터 형태를 바꾸며 P7은 관계의 설명을 옮긴다. 관계 전체의 의미가 언제나 무손실이라는 보장은 아니다.

P8은 폐기됐다. 상한 15인 카테고리에 17항목을 억지로 접어 맞추지 않는다. 이후 align이 상세 문장을 한 슬롯에 합치는 일, 여러 장으로 나눠 담는 일은 별개의 처리다. 생성기가 처음부터 읽지 않는 필드에 내용을 쓰면 fallback P3이 자동 구제한다는 보장도 없다(B-33).

코드 근거 · rust/comp-pass/crates/comp-frame-core/src/query_frame.rs

코드 근거 · rust/comp-pass/crates/comp-frame-core/src/visual_summary/summary_projection.rs

§4

Stage와 필터: 슬롯 모양을 넓혀도 데이터 종류는 유지한다

후보는 서버 메모리 스냅샷에서 카테고리·중첩 카테고리·unit 수·dataset 종류·shape bits·용량 하한으로 먼저 좁힌다. Stage 0은 모양 비트가 같고, Stage 1·2는 각각 정확히 1·2비트 차이다. 20비트 가운데 앞 17개만 완화하며 dataset과 extraGrids는 하드 조건으로 남는다.

이것은 정확한 배치 일치나 최종 가독성 검사가 아니다. 제목 글자 수에 맞춘 사전 하한은 후보를 줄이는 근사 조건이고, 본문과 실제 줄바꿈·슬롯 대응은 후속 배정과 용량 검사가 본다. 과거 DB의 gc_passed 옵션은 현재 검색의 품질 통과와 같지 않으며 해당 컬럼 제거 마이그레이션이 존재한다.

코드 근거 · rust/comp-pass/crates/comp-frame-core/src/filter.rs

코드 근거 · rust/comp-pass/crates/comp-frame-core/src/shape.rs

코드 근거 · packages/comp-frame-index/sql/2026-09-22-drop-gc-passed.sql

§5

후보 수집: 첫 존재 tier는 기본적으로 전량 검사한다

9월 판의 “모든 카테고리는 목표 수 ×4까지만 스캔” 설명은 바뀌었다. 현재 첫 번째로 존재하는 tier는 하드 필터 통과 행을 전부 검사하고, 승인 후보 전체에서 순위를 매긴다. tier1_max_candidates=0은 무제한이다. 원래 tier 1이 비면 tier 2가 이 첫 tier 취급을 받을 수 있다.

설정 / 상태현재 의미
top_n = 50최종 정렬·중복 제거 후 반환 상한
min_candidates = 500첫 tier 이후의 누적 승인 목표
tier_targets = [50,50]tier 처리가 끝난 뒤 하위 tier로 내려갈지 보는 누적 승인 문턱
tier1_max_candidates = 0첫 존재 tier의 승인 상한 없음. 양수를 주면 그 상한에서 자를 수 있다
CATEGORY_SCAN_MULTIPLIER = 4첫 tier 이후 카테고리의 스캔 예산 배율
FETCH_PAGE_SIZE = 1000후보 처리 페이지 상한. 현재는 메모리 풀 안에서 읽는다

행을 읽은 수, 배정·용량 검사를 통과한 수, fingerprint 중복 제거 후 반환 수는 서로 다르다. 통과 수가 0이면 다음 공급을 볼 수 있지만, 통과 행이 같은 Frame으로 중복되면 최종 카드 수가 적을 수 있다. 최신 메타의 tier1_fetched_rows·tier1_exhausted로 첫 tier를 어디까지 읽었는지도 확인한다.

코드 근거 · rust/comp-pass/crates/comp-frame-pool/src/search.rs

코드 근거 · packages/comp-frame-shared/search-defaults/options.json

§6

N1~N5: 코드의 단계와 실제 공급을 나눠 본다

단계역할
N1구조와 종류를 유지해 exact 검색
N2중첩 모양을 유지하며 노드별 자기 행 fallback 조합 검색
N3부모 한 층을 벗겨 자식 묶음을 검색
N4필요하면 부모 벗기기를 반복
N5자식 내용을 글로 평탄화. Hierarchy는 부모 벗기기 대신 이 경로

현재 구현은 Rust nested_search.rs다. N1 결과가 있으면 반환하는 실제 분기가 있다. 위키 D-7의 과거 이종중첩 공급 제외를 근거로 최신 풀의 N1이 “언제나 0”이라고 쓰지 않는다. N2의 조합 수, 검색 대상 풀, 성공 여부를 따로 확인한다. 부모 내용·관계 설명의 보존과 형제 순서도 함께 검사해야 한다.

코드 근거 · rust/comp-pass/crates/comp-frame-core/src/nested_search.rs

§7

배정과 용량: 성공 후보를 먼저 정의한다

align은 질의 슬롯과 디자인 슬롯을 맞추어 binding·blank·preserve·내용 손실을 만든다. 랭커는 이 배정을 비용 계산보다 먼저 실행한다. content_loss > 0 후보는 제외한다. 내용이 남았다는 계산만으로 원문 의미 전체가 보존됐다고 보장하지는 않으므로 원본 → projection → Frame → binding을 추적한다.

표는 별도 조건이 있다. native 표의 확장이 공간 예산을 넘으면 검색에서 제외하고, 측정할 기하가 없는 표는 tableUnmeasured로 낮춘다. 글상자 표는 dataset.cells의 IIS 셀 지도에 맞춰 셀별로 배정할 수 있다. matrix라는 이유만으로 모든 후보를 native Chart로 취급하지 않는다.

코드 근거 · rust/comp-pass/crates/comp-frame-core/src/align.rs

코드 근거 · rust/comp-pass/crates/comp-frame-core/src/rank.rs

코드 근거 · rust/comp-pass/crates/comp-frame-core/src/table_fit.rs

코드 근거 · packages/comp-frame-index/src/frame/cellMapFrame.ts

§8

순위: 온전함, tier, 표현, 비용을 분리한다

기본 rank_mode=tier_pool·clean_first=above_tier에서는 사용자 내용이 아닌 잔여가 0인지 → tier → fallback 순서 → 꾸밈 선호 → 비용 → 단독 태그와 나머지 동점 규칙 순으로 비교한다. 조회된 tier 2의 온전한 후보가 tier 1의 잔여 있는 후보보다 앞설 수 있다. 조회하지 않은 후보를 정렬이 찾아 주지는 않는다.

같은 fingerprint 묶음에서는 잔여 0인 후보를 대표로 바꾸고 다시 정렬한다. unauthored_count는 임시 문구 대상 등을 세는 구현 지표다. Marker·비내용 역할·구조 토큰처럼 원문 보존이 정당한 노드는 잔여 비용과 이 계수에서 빠진다. 사람의 의미 평가를 대체하는 완성도 점수는 아니다.

기본 가중치 정본에는 비용 키 23개와 threading 전용 가중치 2개가 있다. 초기값과 과거 튜닝 이력이 섞여 있으므로 값의 크기나 합계만으로 다른 알고리즘보다 우수하다고 말하지 않는다.

코드 근거 · rust/comp-pass/crates/comp-frame-core/src/rank.rs

코드 근거 · rust/comp-pass/crates/comp-frame-core/src/rank.rs

코드 근거 · packages/comp-frame-shared/search-defaults/weights.json

§9

실제 대치: 안팎 모두 같은 판단으로 채운다

현재 화면과 제품 SDK는 공유 buildNodeTextMap을 쓴다. 순서는 binding → blank → preserve → 안쪽 잔여 → 바깥 잔여 → 제목 구제다. 이미 사용자 글을 받은 노드를 뒤 단계가 덮지 않는다.

조건 (위에서 먼저 적용)최종 처리
Marker 또는 Decoration·Separator·Annotation원문 유지
blank/preserve의 unit 필드임시 문구
vs, TAM/SAM/SOM, 숫자가 아닌 한 글자, 빈 글 등 구조 토큰원문 유지
일반 숫자·글·원문 미상임시 문구

문서 제목이 안쪽 title binding에 없으면 바깥 Title 후보를 우선해 한 곳을 고른다. Title이 없을 때도 Marker·비내용 역할은 후보에서 제외한다. 선택되지 않은 공통 부제·설명은 일반 글이면 임시 문구가 된다. 상세 대조와 실제 정책으로 다시 계산한 예시는 역할별 텍스트 대치에 있다.

코드 근거 · packages/comp-frame-shared/src/nodeTextPolicy.ts

§10

9월 진단을 현재 결함 목록으로 복사하지 않는다

이전 판은 TS 검색에서 F01~F09를 합성 재현하고 핵심 테스트 470개를 기록했다. 그 결과는 당시 커밋의 검증이다. 이후 Rust 이전, 첫 tier 전량 스캔, 정렬 비교, 내용 보존과 대치 정책 변경이 들어왔으므로 동일한 번호를 최신 결함으로 재선언하지 않는다.

옛 주장이번 판의 처리
첫 tier도 ×4까지만 훑는다현재 기본 전량 검사로 교체
N1은 언제나 후보 0코드는 검색을 실행하며 실제 풀 상태는 미측정
preserve·경계 밖은 원문 유지공통 노드 정책으로 교체
threading은 두 종이고 제목 구제를 끈다네 종 프로파일·제목 구제 유지로 교체
도형 글자는 양쪽 모두 Text와 같다aippt의 SVG 지원과 iui 벤더 Text 한정의 차이를 명시

현재 의심을 재현하려면 최신 Rust 함수와 같은 입력·풀·옵션을 고정하고 실행해야 한다. 이번 문서 갱신은 과거 테스트 수를 새로운 실행 결과로 재표시하지 않는다.

§11

Content Threading과 지정 종류 검색

현재 나눠 담기 프로파일은 List·Steps·QnACard·TableOfContents다. 서버가 직접 배치 → 탐색용 질의 → 여러 장 계획 → 장별 검사·재정렬을 한다. 상위 binding은 첫 장이며 다음 장은 장별 데이터로 바꿔 그린다. 기본 장수 상한은 64다.

threading 및 original_size_verified 결과는 원본 크기를 기준으로 배치한다. 제목 구제는 유지되며, 임시 문구는 원래 셀의 용량과 요청에서 쓴 언어별 문구 표를 기준으로 고른다. 검색 때와 렌더 때 다른 문구 표를 쓰면 맞음 보장이 깨진다.

사용자가 generationTypes를 지정한 경우는 별도 0군·1군 검색이다. 지정 종류의 0군을 tier1_only로 먼저 찾고 부족할 때 추천 1군을 찾는다. 이 군 번호는 Tier 1~3이나 Stage 0~2가 아니다.

코드 근거 · rust/comp-pass/crates/comp-frame-core/src/threading/profile.rs

코드 근거 · rust/comp-pass/crates/comp-pass-logic/src/threading_search.rs

코드 근거 · src/comp-frame/useUnifiedSearch.ts

§12

직접 설명해 보기

첫 존재 tier에서 500개가 승인되면 기본 검색은 즉시 멈출까?

아니다. 첫 존재 tier의 기본 승인 상한은 0(무제한)이다. 전량 검사 후 tier 문턱을 보고 하위 tier 진행 여부를 정한다. 첫 tier 이후에는 min_candidates가 적용된다.

preserve에 있는 20%는 반드시 원문으로 남을까?

아니다. 일반 숫자+단위는 임시 문구 대상이다. Marker 역할이나 구조 토큰 등 먼저 적용되는 보존 조건과 실제 필드를 확인한다.

단어장에 있는 카테고리면 생성기도 모두 쓸까?

아니다. 규약 v0.5.6 인식 45종과 생성 허용 36종은 다른 집합이다. 그 위에 지정 종류·공급 버전 등 실행 설정이 얹힌다.

검색과 렌더의 결과가 다르면 어디부터 볼까?

원본 입력 → projection → Query Frame → binding → nodeTextPolicy → 대치 페이로드 → 실제 렌더 순서로 처음 달라지는 곳을 찾는다. 서버 버전·componentVersion·threading 장 번호·언어별 임시 문구 표를 함께 남긴다.

§13

색인 버전과 도형 글자: 현재 코드와 과거 측정의 경계

iui.comp_frames의 한 행은 디자인 전체가 아니라 IIS 경계 노드 하나를 나타낼 수 있다. 검색용 컬럼은 Frame에서 파생한 카테고리·모양·용량·버전 등이며, Rust 서버는 추출한 스냅샷을 읽는다. frame_version=5와 제품 버전 3.0, 내부 발행분 2.6 같은 이름은 같은 축이 아니다.

2026-10-02 제공된 DB 측정(재측정하지 않음): 전체 226,952행, 발행분 2.5의 113,614행·96,538 DO, 도형 속 글자 8,418개·3,357 DO라는 숫자는 당시 기록이다. 지금의 행 수·커버리지나 최신 적재 완료를 뜻하지 않는다.

소스 차이가 남아 있다. aippt의 rlsc.ts:isTextBearingNode는 Text 또는 문자열 content가 있는 SVG를 읽는다. iui의 벤더 extractTextSlots와 적재 Frame 빌더는 Text를 기준으로 한다. 따라서 “aippt에서 도형 글자 대응”을 “comp-frame 모든 슬롯에 반영 완료”로 확대하지 않는다. 데이터 재적재도 별도 확인해야 한다.

코드 근거 · packages/comp-frame-shared/src/eregion/visual-summary/rlsc.ts

aippt SVG 판정

코드 근거 · packages/comp-frame-index/src/frame/component-frame.ts

§14

출처와 검증 범위

갱신 2026-10-17. iui bcd1d0218766cbba3a174d1819ab218d613e626f, wiki a0f8b01961db9396206b1ddf097c66cb44bde137, aippt e6ffa4bdf65ec76f3d3031dc566f3fc7c19eade1의 origin/main 고정 파일을 읽었다. 모든 코드 줄 링크는 git archive 스냅샷에서 확인했다. 로컬 브랜치나 미커밋 변경을 구현 완료로 포함하지 않았다.

위키 spec·design·reference는 9월 학습판 이후 변경이 없지만 실행 구현은 크게 달라졌다. 규약의 alternatives·P8·중첩 정책과 코드의 실제 동작을 분리했다. 이번 작업에서 운영 DB·서비스 배포·실제 렌더 품질이나 전수 회귀 테스트를 새로 측정한 것은 아니다.

전체 개념 수업과 50문항은 학습 페이지, 생성 원본과 고정 코드 지도는 강의자료에 있다. 이전 판의 상세 F01~F09·실험 수치는 보관본에서 당시 근거로 읽는다.