본문으로 건너뛰기

pubmap 02. 페이지 variants와 전체 선택 모드

·6 min read·2 / 2

pubmap에 두 조각을 이어 붙였다. query string으로 분기되는 화면을 IA(페이지 구조) 노드로 펼치는 variants, 그리고 지난 편 저녁에 착수해뒀던 granularity 'all'(전체 선택) 모드다.

같은 pathname, 다른 화면 — variants를 자식 노드로 펼쳤다

같은 pathname이라도 ?category=art&tab=1처럼 query로 화면이 갈리는 경우가 있다. 이런 화면을 각각 기준 페이지의 자식 노드로 펼쳐서 별도 iframe 썸네일로 렌더링하게 했다.

설정에서는 페이지 하나에 variants 배열을 선언한다.

{
  path: '/ai-agent',
  title: 'AI Agent',
  variants: [
    { title: '전체', query: { category: 'all' } },
    { title: '아트', query: { category: 'art', tab: 1 } },
  ],
}

타입으로는 IAPageVariant를 추가했다 — { title, query: Record<string, value | value[]> } 형태다. URL을 만드는 variantPath()는 base path에 이미 붙어 있는 query와 hash를 보존하면서 variant query를 병합한다. variant에 선언한 key만 base의 같은 key를 덮어쓰고, 배열 값은 append로 다중 파라미터를 지원한다.

검증 규칙도 같이 넣었다. 외부 페이지(external)에는 variants를 금지하고, variant title은 필수, 펼쳐진 path는 seen set으로 중복을 검사한다. playground의 /chat 2종과 README에 사용 예시를 반영했다.

별도 노드 타입이 아니라 "자식 노드로 펼치기"를 골랐다

variants를 별도 노드 타입으로 만들지 않았다. normalize 단계(설정을 내부 표현으로 정리하는 단계)에서 자식 노드로 평탄화되기 때문에, 캔버스/뷰어/인스펙터는 variants의 존재를 몰라도 된다. 하위 레이어 변경이 0이다.

query 병합 시맨틱은 "variant가 선언한 key만 덮어쓰고 나머지는 보존"으로 정했다. base path에 이미 ?foo=1이 붙어 있는 경우를 자연스럽게 처리하기 위해서다. hash도 분리했다가 재부착한다.

URL 조작은 문자열 치환으로 하면 안 됐다. hash 분리 → pathname/search 분리 → URLSearchParams 병합 → 재조립 순서로 해야 기존 query, hash, 배열 값 같은 엣지케이스가 새지 않았다.

'all' 모드는 드릴다운보다 먼저 분기시켰다

granularity(블록 선택 단위의 세밀도)를 'all' | 'section' | 'unit'으로 확장하고, PageViewer에 "전체" 토글 버튼을 달았다. 휴리스틱이든 인스펙터든 'all'이면 무조건 doc.body를 반환한다 — hover/드릴다운 로직을 타지 않고 항상 페이지 전체를 선택한다.

resolveBlock이 항상 body를 반환하도록 드릴다운보다 앞에서 분기시켰다. 드릴다운 상태 머신에 'all'을 섞지 않아 복잡도를 격리하기 위해서다. SelectionPanel 라벨도 전체/섹션/유닛 3단으로 갱신했다.

새 granularity를 추가해 보니 분기 지점이 세 곳(휴리스틱, 인스펙터 resolve, 패널 라벨)에 흩어져 있었다. granularity별 동작을 한 곳에서 정의하는 구조로 리팩터링할 여지가 남았다.

캔버스에서는 오히려 뺐다

React Flow의 <Controls><MiniMap>을 관련 스타일과 함께 제거했다. 툴 UI를 더 단순하게 가져가기 위해서다. 기능을 빼는 결정도 개선이다 — 지난 편의 시스템 UI 개편 방향과 일관되게 유지했다.

variants는 실무 IA(카테고리 탭, 필터 상태별 화면)를 표현하는 데 꼭 필요했던 조각이다. 화면설계서의 "같은 페이지, 다른 상태"를 미니맵에서 그대로 볼 수 있게 됐다.

남은 작업은 variants 검증이다. type-check와 E2E(variant 노드 렌더, 썸네일 URL 확인)를 돌린 뒤 커밋한다. granularity 분기 로직의 응집도 개선도 검토 대상이다. 그다음이 Phase 3다 — 블록 선택과 Figma 링크를 로컬 컴패니언 서버로 보내 publish 스킬을 구동하고 파일을 쓰는 흐름. 브라우저 단독으로는 파일 쓰기가 안 되니, 다음 편에서는 이 로컬 서버를 다룬다.