현재 사용법 (2026-09-10,
6fbaee7f): 공통 화면·디자인 시스템 · 기능 마스터. 아래는 작성 당시의 변경 설명이며 현재 전체 동작·재측정 결과를 뜻하지 않습니다.
DS 문서 전면 개편과 대화 표면 부품화 (2026-09-09)
디자인 시스템 문서 사이트의 왼쪽 메뉴가 전부 한글로 바뀌고 문서마다 조작 가능한 미리보기가 붙습니다. 제품 화면에서는 메신저와 AI 어시스턴트의 말풍선·입력줄이 같은 모양으로 통일되고, 채팅 입력줄의 전송·첨부 버튼이 사각형에서 원형으로 돌아옵니다.
직관 — 두 갈래의 근본 원인은 동일합니다
문서 작업과 코드 작업이 한 브랜치에 섞여 있지만 원인은 하나입니다. 규격의 정본이 있어야 할 자리에 없었습니다. 색 규칙은 문서가 아니라 에이전트 규칙 파일에 있었고, 어시스턴트·신고 UI의 규칙은 남의 문서 안에 세 들어 있었으며, 말풍선의 색과 여백은 디자인 시스템 CSS가 아니라 공용 마크업 조각의 <style> 블록에 있었습니다. 정본이 흩어져 있으면 사본이 생기고, 사본은 정본이 바뀌어도 따라오지 않습니다.
배경 — 용어와 지금 동작
디자인 시스템 문서는 docs/ko/design-system/** 의 VitePress 사이트입니다. 사람이 읽는 동시에 코딩 에이전트가 그 UI를 만들기 전에 반드시 읽어야 하는 문서이기도 합니다. 각 페이지 상단에는 접힌 「규칙 (강제)」 블록이 있고, 여기 적힌 것이 그 UI의 강제 규격입니다. CLAUDE.md 와 .claude/rules/frontend/design-system-docs.md 는 규칙 내용을 갖지 않고 어느 문서를 읽어야 하는지만 가리킵니다.
Playground 는 옵션을 골라 실제 design-system.css 로 렌더된 결과와 그 조합의 코드를 함께 보는 미리보기입니다. 사본으로 그리지 않고 실제 클래스를 쓰는 것이 원칙입니다.
파셜은 packages/components/html/*.html 의 공용 마크업 조각으로, 여러 앱이 빌드 시점에 include 로 끌어다 씁니다. 메신저 파셜(messenger-content.html)은 첫머리에 <style> 블록을 갖고 있는데, 이 블록은 어느 CSS 레이어에도 속하지 않아 Tailwind 유틸리티와 앱 CSS를 모두 이깁니다. 따라서 여기 값이 있으면 정본이 조용히 밀립니다.
대화 화면은 세 곳에 있습니다. 직원 앱의 전체화면 메신저, 나머지 일곱 앱의 떠 있는 채팅 위젯, 그리고 admin 의 AI 어시스턴트 도크입니다. 셋은 한 화면에 나란히 뜰 수 있습니다.
말풍선 정의가 오던 곳
변경 전
변경 후
세 정의가 서로 달랐습니다. 「내 말풍선」의 주황이 파셜에서는 #ea580c, 어시스턴트에서는 --color-primary(#f66014) 였습니다. employee-app 의 사본은 문서 순서에서 파셜에 밀려 한 번도 화면에 그려지지 않았고, 그 사이 값까지 갈라져 있었습니다.
#ea580c 가 고른 색이 아니라 잔재라는 근거는 커밋 이력에 있습니다. 2026-04 일괄 「design-system refresh」 커밋에서 들어왔고, 뒤이은 토큰화 커밋이 그것을 --ds-ext-…(팔레트에 자리가 없는 색에 붙이는 접두사)로 바꿨으며, 지금도 레거시 hr-* 스케일에만 있고 DS 색으로 등록된 적이 없습니다.
강제 규칙이 있던 곳
변경 전
변경 후
개념 흐름별 변경
대화 표면을 DS 부품 한 벌로 만듭니다
design-system.css 에 .ds-chat-panel(패널 껍데기) · .ds-bubble(말풍선) · .ds-composer(입력줄) · .ds-presence(접속 표시 점)를 신설하고 세 곳의 정의를 여기로 모았습니다. 파셜과 앱 CSS 에는 다시 쓰지 말라는 주석만 남깁니다.
패널 껍데기도 두 벌이었습니다. 높이 600/560, 모서리 rounded-2xl/rounded-16(같은 값의 다른 철자), 그림자 shadow-2xl(Tailwind 기본)/shadow-popover(DS 토큰), 테두리 neutral-200/neutral-100, 그리고 화면 상한 가드의 유무가 갈려 있었습니다.
말풍선 폭은 상속을 열어 두었습니다. 스피너의 축이 inherits: false 로 상속을 막은 것과 반대인데, 말풍선은 한 목록 안의 것을 한꺼번에 조정하는 것이 정상 사용법이기 때문입니다. 메시지 목록에 --ds-bubble-max 를 한 번 얹으면 안쪽이 전부 따라옵니다(기본 75%, 어시스턴트 도크만 85%).
사각형으로 렌더되던 원형 버튼을 되돌립니다
메신저 입력줄의 전송·첨부 버튼은 rounded-full 을 달고 있었지만, 모든 <button> 의 모서리를 4px !important 로 강제하는 blanket 규칙에 걸려 모난 사각형으로 렌더되고 있었습니다. !important 로 맞불을 놓거나 <div role="button"> 으로 우회하지 않고, 그 규칙이 읽는 --ds-btn-radius 변수를 요소에 세워 이깁니다.
낮은 화면에서 잘리던 채팅 패널을 고칩니다
채팅 패널은 600px 고정에 bottom: 104px 이었고 화면 상한 가드가 없었습니다. 세로 704px 미만이면 패널 머리가 잘립니다. 1280×720 노트북에서 브라우저 크롬을 빼면 실제 뷰포트가 그 아래입니다. 어시스턴트에만 있던 가드를 껍데기에 넣어 양쪽에 적용했습니다.
문서가 없던 컴포넌트에 페이지를 냅니다
AiAssistant 와 CsReport 는 공용 컴포넌트인데 자기 문서가 없었습니다. 규칙이 없던 것이 아니라 채팅 FAB 문서 안에 얹혀 있었습니다. 사이드바에서 찾을 수 없고, 어시스턴트 규칙을 채팅 문서에서 찾아야 했습니다. 세 쪽을 냈습니다 — AiAssistant · CsReport · 대화 UI. 규칙은 복사가 아니라 옮겼고, 채팅 문서에는 가리키는 한 절만 남깁니다.
Foundations 를 컴포넌트 문서와 같은 규격으로 맞춥니다
컴포넌트 22쪽 중 21쪽이 쓰는 골격(설명 한 줄 → 배지 한 줄 → Playground → 규칙(강제) → 탭)을 Foundations 는 한 쪽도 쓰지 않았습니다. 8쪽의 상단을 맞추고 7쪽에 탭을 씌웠습니다. 다만 토큰 참조 표 6쪽에는 Interactive playground 제목을 붙이지 않았습니다 — 조작할 데모가 없는데 그 제목을 달면 사실과 다릅니다.
색 규칙은 문서로 이관했습니다. 색만 강제 규칙이 에이전트 규칙 파일에 있어, 정작 색상 문서에는 규칙 블록이 없었습니다. 아이콘 문서는 두 쪽이 따로 있었고 둘 다 「사용 규칙」을 갖고 있었는데, 한쪽의 레지스트리 표는 실제 171종 중 31종만 담은 낡은 스냅샷이었습니다. 표를 지우고 빌드 시점에 레지스트리를 렌더하는 갤러리로 대체했습니다.
메뉴 이름과 미리보기 용어를 정리합니다
왼쪽 메뉴가 영문과 한글을 섞어 쓰고 있었습니다. 기준을 「메뉴는 한글, 코드 심볼은 페이지 제목에 병기」 로 정했습니다. 메뉴는 읽는 곳이지 검색하는 곳이 아니므로, 심볼은 제목이 지킵니다(# 페이지 헤더 (PageHeader)). 약어와 제품명(LNB · AI · Figma · iframe · Table 1/2)은 번역 대상이 아니라 그 자체가 이름이므로 그대로 둡니다.
같은 것을 두 이름으로 부르던 것도 정리했습니다. 31쪽은 Interactive playground, 패턴 5쪽은 「라이브 미리보기」였습니다. 뒤엣것을 앞으로 맞추되 옛 앵커(#live-preview)는 호환용 표식으로 살려 두어 기존 링크가 동작합니다.
문서 데모가 옛 색을 그리고 있었습니다
메신저 문서의 데모가 옛 클래스와 하드코딩 6색 사본을 들고 있었습니다. 「파셜의 하드코딩을 그대로 보여 준다」는 이유로 둔 것인데, 정본이 생긴 순간 그 사본은 정본이 바뀌어도 따라오지 않는 옛 그림이 됩니다. 실제로 제품은 새 색인데 문서만 옛 색이었습니다. 정본 클래스로 바꾸고 사본 색은 지웠습니다.
왜 더 간단한 방법을 쓰지 않았는가
말풍선 색을 맞추는 가장 간단한 방법은 어시스턴트 쪽을 #ea580c 로 바꾸는 것이었습니다. 그렇게 하지 않은 이유는 위의 커밋 이력입니다. 그 색은 DS 팔레트에 등록된 적이 없고, 맞추면 등록되지 않은 색을 정본으로 승격시키게 됩니다.
원형 버튼도 !important 한 줄이면 이깁니다. 그러나 저장소의 모서리 규칙은 ds-r-* 라는 정식 축을 이미 갖고 있고, 그 축이 읽는 변수를 세우는 것이 문서화된 탈출구입니다. !important 를 늘리면 다음 사람이 또 !important 로 이겨야 합니다.