경계선은 하나다. 검색·매칭·생성은 서버, 레이아웃·대치·노드편집은 브라우저.
서버는 완성된 화면을 주지 않고 componentKey 와 시그니처 파일 URL만 돌려준다 —
큰 컬럼은 브라우저가 따로 받아 온다.
사용자 입력에서 시작해 해시를 만들고, 검색을 오케스트레이션하고, 돌아온 후보로 대치와 auto-layout 을 직접 수행한 뒤 노드트리에 커밋한다. 계산은 전부 브라우저 안에서 끝난다.
visualizationParts 를 병렬 hybridSearch 로 태우고 로깅 부수효과를 합성한다.
77줄짜리 얇은 헬퍼이고, 실제 스트림은 _core/streams.ts 가 만든다.
import { forkJoin, map, type Observable, tap } from 'rxjs'; /** * `visualizationParts` 의 병렬 hybridSearch + 각 part 결과에 대한 * `Logger.logSummary` / `Logger.setDebugMetadata` 부수효과 합성. * `visualizeFromText` / `revisualize` 처럼 정상 진입점이 공유하는 패턴이라 추출. */ export const createSearchParallelWithLog$ = (...)
MORDOR 계열 엔드포인트들. prefix 만 봐도 어느 서비스 소관인지 구분된다.
아래 경로는 miricanvas-api-kit 의 route 정의에서 그대로 확인한 값이다.
| 엔드포인트 | 하는 일 | route 정의 |
|---|---|---|
POST /template/api/v1/ai/text-visualization/generate |
서머리 · 시멘틱쿼리 생성 | PostTextVisualizationGenerateV1 |
POST /template/api/components/signatures/search 핵심 |
시그니처 후보 검색 · 매칭 (해시는 서버) | PostComponentsSignatureSearch |
GET /template/api/ai/presentation/component/smart-blocks |
smartblock 검색 | getComponentAIPresentationSmartBlocks |
POST /template/api/components/recallsearch |
Recall Search V2 — hybrid · embedding | PostComponentsRecallSearch |
POST /process/api/ai/chat/{serviceName} |
스트리밍 아웃라인 에이전트 (application/ndjson) |
StartAiChatStream |
/worker/api/aigeneration/* |
aippt 이미지 생성 · 이력 · 피드백 (비동기 워커) | ai-presentation/* (다수) |
POST /template/api/templates/style-metadata/query/bulk |
템플릿 스타일 메타데이터 → styleMetadataFileUrl |
GetTemplateStyleMetadata |
{storyline} 은 경로 이름이 아니다
route 정의의 path 파라미터는 {serviceName} 이고,
storyline 은 그 예시 값이다
(serviceName.openapi({ example: 'storyline' })).
원본 도식의 /process/api/ai/chat/{storyline} 표기는 이 점에서 오해를 부른다.
"서버는 후보키 + 시그니처 파일만 반환한다"는 이 어댑터 한 곳에서 확인된다.
응답에는 URL 만 있고, textMap · textNodeRoles 는 브라우저가 따로 fetch 한다.
/**
* comp-sign 검색 파이프라인의 서버 단계(POST /template/api/components/signatures/search)
* 어댑터. 백엔드 응답을 파이프라인이 쓰는 내부 형태로 변환하고,
* 대용량 컬럼(text_map·text_node_roles)의 파일 URL 을 fetch 한다.
* 응답 스키마가 바뀌면 adaptSearchResponse 만 고치면 뒤쪽(랭킹·대치)은 영향 없다.
*/
scoreFeatures 로 먼저 하고, 실제 파일은 고른 후보만 받는다.
| 층 | 파일 | 패키지 |
|---|---|---|
| 검색 진입·오케스트레이션 | TextVisualizationService.ts | miricanvas-legacy |
| 병렬 검색 | _core/searchParallel.ts | miricanvas-legacy |
| 서버 응답 어댑터 | _core/compSignSearch.ts | miricanvas-legacy |
| 대치 4단계 | buildMappedComponentSheetJson.ts:108 | engine/editor |
| 대치 커맨드 | CmdReplaceComponentBySignature…ts:95 | engine/editor |
| 캔버스 반영 | ComponentItemReplaceCommand.ts | engine/editor |
| SmartBlock auto-layout | AbstractSmartBlockLayoutWithChildrenStrategy.ts | engine/editor |
| API route 정의 | miricanvas-api-kit/src/endpoints/api/ | miricanvas-api-kit |
| 패키지 | 무엇 | web-2 에서 쓰는 곳 |
|---|---|---|
| comp-sign | 해시 · 랭킹 · 대치 페이로드 · 공간 정돈 | 검색 파이프라인 전 구간 |
| color-mapper | recolorComponent · buildColorProfile | TemplateStyleMapper |
| theme-registry | ThemeRegistry 타입 · AIP 테마 경로 | style_replacement/colorMapping.ts |
iui 는 DB 를 참조하지 않는다 — 외곽선 같은 데이터가 필요하면 호출자가 조회해 넘긴다
(build-replacement.ts 의 vt2 옵션 주석).
런타임 경로에는 없다. 검색의 재료인 시그니처와 RLSC 를 오프라인에서 만드는 쪽이라, "후보가 왜 이것뿐인가"를 거슬러 올라갈 때 보는 저장소다 (Eregion 전체 아키텍처).
서머리 생성 · 시그니처/시멘틱 검색 · 해시 매칭 · aippt 생성. 결과는 componentKey + 시그니처 파일 URL만.
comp-sign 해시·랭킹 · 색상/내용/이미지 대치 · SmartBlock auto-layout · Page 빌드 / 노드트리 커밋.
텍스트 흘리기 · 폰트 오토핏 · 재레이아웃은 preview iframe 안의 렌더러가 한다.
끄는 레버는 shrinkConfigs 하나뿐이고 줄바꿈·재레이아웃은 그래도 일어난다 —
이것이 정렬 문제의 배경이다.