Skip to content

현재 사용법 (2026-09-10, 6fbaee7f): 공통 화면·디자인 시스템 · 기능 마스터. 아래는 작성 당시의 변경 설명이며 현재 전체 동작·재측정 결과를 뜻하지 않습니다.

모달 문서 통합 — 이어서 하기 (2026-09-08 기준) ​

새 세션에 이 문서를 붙여 넣고 「이어서 진행」이라고 하면 됩니다.

무엇을 하려는가 (사용자 지시) ​

모달 문서를 한 페이지로 통합한다. 지금 사이드바에 모달과 패널 폼이 따로 있는데, 패널 폼은 모달의 한 종류(패널 모달)라 별개 메뉴로 보일 이유가 없다.

  1. patterns/모달 한 페이지로 합친다 — patterns/panel-form.md 를 흡수
  2. 그 안에서 모달 3종을 탭으로 구분 — 컨펌 다이얼로그 · 일반 모달 · 패널 모달
  3. 각 탭에 Playground. 「라이브 예시로 볼 수 있게」 한다 — 클릭하면 뷰어 영역에 딤이 깔리고 실제로 뜬 모습을 확인할 수 있어야 한다(지금처럼 카드만 덩그러니 놓지 말 것)
  4. 필요하면 속성 패널을 뷰어 오른쪽이 아니라 아래로 내린다
  5. 사용 가이드도 타입별로 그 탭 안에 둔다
  6. 유실 0 을 더블 체크한다

사용자가 동의한 방향(별건): 두 직원 패널의 저장은 갈라야 맞고 뷰는 공유해야 맞다. 지금은 둘 다 복사돼 있는 것이 문제다. 이번 통합은 문서 통합이고, 코드 리팩터링은 별건이다.

지금 상태 ​

브랜치 design/docs-DS-review-improvements (origin 동기화됨). 마지막 커밋 8072c447.

docs/ko/design-system/patterns/modal.md        848줄   ← 흡수하는 쪽
docs/ko/design-system/patterns/panel-form.md   199줄   ← 흡수될 쪽 (오늘 신설)

주의: panel-form.md 는 오늘 만들어진 페이지다. 원래는 두 직원 패널 문서에 흩어져 있던 공유 규칙을 한곳으로 모은 것이라, **그 안의 문장 대부분이 이미 「옮겨진 것」**이다. 이번에 또 옮기므로 두 번 옮겨진 문장이 생긴다 — 유실 확인을 특히 꼼꼼히 할 것.

오늘 이 브랜치에서 이미 한 일 (배경) ​

  • 컴포넌트 문서 준비중 10 → 0 (인증 5종 · Segment · PermissionDeniedModal · 두 패널 · MyInfoForm · Messenger)
  • AddEmployeeWizard/EditEmployeeWizard → AddEmployeePanel/EditEmployeePanel 로 개명 (2026-07 에 단계 게이트가 사라졌는데 이름만 남아 있었음). 문서도 양식 마법사 → 패널 폼
  • 인증 폼 4개의 라벨 간격·글자·필드 높이를 로그인 기준으로 통일
  • 모달 ↔ 패널 폼 양방향 링크를 냈다 (이번 통합으로 그 링크는 없어질 것)

페이지 구조 (현재) ​

## 모달은 3종입니다 {#kinds}
## 새 모달을 만들 때 {#new-modal}       ### 1~4 (#new-modal-guards)
## 라이브 예시                          #dialog-demo · (일반) · #panel-demo   ← <DemoConfirmDialog> · <DemoPanelModal>
## 단일 출처
## 규칙                                 ### 1 표시 · 2 닫기(#close) · 3 스크롤잠금 · 4 폭(#width-scale)
                                        ### 5 타이포(#typo) · 6 상태 · 7 푸터(#footer-emphasis) · 8 피커(#pickers)
## 모바일 (풀페이지 변형) {#mobile}      ### #ios-zoom · #mobile-impl
## 상세(읽기전용) 모달 {#detail}
## 패널 모달 {#panel}                   ### 단일출처 · 사이즈 · 구조 · 중첩 자식과 ESC 가드
## 컨펌 다이얼로그 {#dialog}             ### 단일출처 · 쓰는 법 · #dialog-keyboard · #dialog-choice
                                        ### #dialog-padding · #dialog-title · 규칙(강제)
## 예외 · ## 급여 적용 현황(#hr-system-status) · ## 어디서 쓰이나 · ## 목표 & 로드맵

panel-form.md 199줄 ​

## 두 위저드 {#members}        ← 제목 문구가 낡음(위저드→패널). 통합 때 정리
::: details 규칙 (강제)
<DocTabs>
  #guide     ## 셸 구조 {#shell} · 자유 이동 {#free-nav} · 필수 누락 표시 {#dots}
             ## 닫기 가드 {#close-guard} · ESC 층 {#esc}
  #variants  ## 주소 검색 {#address} · 주민등록번호 {#rrn} · 알림 팝업 {#notice}
  #changes   ## 검토 필요 사항 {#open-questions} · 변경 이력 {#changelog}

통합 후 목표 구조 (제안) ​

# 모달
한 줄 안내 + 표기줄
## 모달은 3종입니다 {#kinds}            ← 유지. 표에서 각 탭으로 링크
## Interactive playground {#playground}
   <DemoModalPlayground />              ← 신설. 3종을 탭으로, 클릭하면 딤 + 실제 표시
::: details 규칙 (강제) · 코딩 에이전트용   ← 3종 공통 + 종류별을 한 곳에
<DocTabs id="modal-docs">
  #common     공통 — 표시/닫기/스크롤잠금/폭/타이포/푸터/피커/모바일/상세 (기존 ## 규칙 전체)
  #dialog     컨펌 다이얼로그 — 기존 #dialog 절 전체
  #modal      일반 모달 — 기존 #new-modal + #width-scale 중 일반 모달 몫
  #panel      패널 모달 — 기존 #panel + **panel-form.md 전체**
  #adoption   어디서 쓰이나 · 급여 적용 현황 · 예외
  #changes    검토 필요 사항 · 목표 & 로드맵 · 변경 이력

탭 이름과 배치는 확정 아님. 먼저 사용자에게 이 골격을 보여 주고 승인받을 것.

Playground 요구사항 (핵심) ​

지금 DocPlayground 는 카드를 그냥 스테이지에 놓는다. 사용자가 원하는 것은 **「띄운 모습」**이다.

  • 3종을 Playground 안의 축(select)으로 고른다
  • 버튼을 누르면 뷰어 영역에 딤이 깔리고 그 위에 모달이 뜬다 — 실제 화면처럼
  • 딤은 뷰어 영역 안에만(전체 화면을 덮으면 문서를 못 읽는다). position: absolute + 뷰어에 relative
  • 속성 패널은 뷰어 아래로. DocPlayground 에 이미 그 레이아웃이 있다 — doc-playground__layout--stacked (지금은 「모아보기」 탭에서만 켜짐). stacked 를 prop 으로 열어 이 페이지에서 항상 켜지게 하는 것이 가장 작은 변경이다
  • 기존 데모를 버리지 말 것: DemoConfirmDialog.vue(컨펌 3종 · 타이틀 on/off · 여백 28 가이드 · 반환값 표시) · DemoPanelModal.vue 가 이미 있다. 새 Playground 는 이 둘을 감싸는 어댑터로 만드는 편이 안전하다

유실 0 확인 절차 (반드시) ​

  1. 옮기기 전에 두 파일의 문단을 뽑아 둔다
    bash
    python3 - <<'PY'
    import re, pathlib
    for f in ("modal","panel-form"):
        s = pathlib.Path(f"docs/ko/design-system/patterns/{f}.md").read_text()
        paras = [p.strip() for p in re.split(r"\n\s*\n", s) if p.strip()]
        pathlib.Path(f"/tmp/{f}-before.txt").write_text("\n---\n".join(paras))
        print(f, len(paras), "문단")
    PY
  2. 옮긴 뒤 통합본에 그 문단이 글자 그대로 있는지 기계 대조. 없는 것은 한 줄씩 사유를 대야 한다
  3. 앵커 보존 — 아래 앵커는 다른 문서가 참조한다. 통합 후에도 전부 살아 있어야 한다
    modal:      #kinds #new-modal #new-modal-guards #close #width-scale #typo
                #footer-emphasis #pickers #mobile #ios-zoom #mobile-impl #detail
                #panel #panel-demo #dialog #dialog-demo #dialog-keyboard #dialog-choice
                #dialog-padding #dialog-title #hr-system-status
    panel-form: #members #shell #free-nav #dots #close-guard #esc #address #rrn
                #notice #open-questions #changelog
    panel-form.md 를 지우면 그 URL 이 죽는다 → 리다이렉트 대신 참조하던 곳을 modal#앵커 로 고칠 것. 참조처는 아래 「연결된 곳」 참고
  4. 검증 스크립트(아래) 로 죽은 앵커 0 · 페이지 간 링크 0건 깨짐 확인
  5. cd docs && pnpm build + 루트 pnpm build(23/23)

연결된 곳 (panel-form 을 가리키는 문서) ​

bash
grep -rn "panel-form\|패널 폼" docs/ko --include="*.md" | grep -v resources/changelog.md

2026-09-08 기준: patterns/modal.md(내가 오늘 넣은 tip) · components/forms/add-employee-panel.md · components/forms/edit-employee-panel.md · components/forms/my-info-form.md · components/feedback/permission-denied-modal.md. changelog 는 이력이므로 고치지 않는다.

사이드바 ​

docs/.vitepress/config.mts 의 Patterns 그룹에서 패널 폼 항목을 제거한다(모달만 남김). 지금 값:

{ text: "모달", link: "/ko/design-system/patterns/modal" },
{ text: "패널 폼", link: "/ko/design-system/patterns/panel-form" },   ← 삭제

이 레포에서 쓰는 검증 도구 ​

세션마다 새로 만들어야 한다(스크래치패드에 있었음). 다음을 본다 — Playground 렌더 · 페이지 내 죽은 앵커 0 · 탭 렌더 · 숨은 탭 앵커 직접 접속 · 초기화 · 모아보기 스크린샷 · 375px 가로 넘침 · 콘솔 에러.

node verify-doc.mjs <경로> <미리보기셀렉터> <앵커,앵커,…>

함정 (오늘 실제로 밟은 것)

  • 문서 탭을 [role="tab"] 으로 잡으면 Segment 데모 자신의 탭까지 눌린다 → .doc-tabs__tab 으로 좁힐 것
  • 예전 주소 유지용 빈 <span> 앵커는 박스가 0 이라 「숨음」으로 오판된다 → offsetParent 로 흐름 여부를 볼 것
  • Playwright 는 /tmp 에서 모듈을 못 찾는다 → 스크래치패드에 node_modules 심링크
  • docs 에는 Tailwind 가 없다. ds-tailwind-shim.css 가 흉내 내며, Tailwind v4 기준이어야 한다 (space-y-* 는 앞 형제의 아래 여백이다. v3 식 > * + * 로 적으면 여백이 입력칸에 얹혀 DS 의 맨몸 input{margin:0} 에 눌려 0px 로 보인다 — 오늘 실제로 이 실수를 했다)
  • shim 이 실제 앱과 같은지 기계 대조 가능하다: admin 을 빌드해 apps/admin/dist/assets/*.css 를 프로브 페이지에 물리고, docs 쪽은 design-system.css + ds-token-bridge.css + shim 3개를 물려 같은 클래스의 계산값을 비교한다(오늘 157개 대조 → 실질 어긋남 0). @theme 블록은 브라우저가 무시하므로 브리지를 빠뜨리면 안 된다

작업 순서 (제안) ​

  1. 골격을 사용자에게 보여 주고 승인 — 탭 구성·순서·이름
  2. DocPlayground 에 stacked prop 추가(기본 false, 이 페이지만 true)
  3. DemoModalPlayground.vue 신설 — 3종 축 + 「띄우기」 버튼 → 뷰어 안 딤 + 모달. 기존 DemoConfirmDialog · DemoPanelModal 을 감싸 재사용
  4. modal.md 를 DocTabs 구조로 재배치 (문구는 그대로, 위치만)
  5. panel-form.md 내용을 패널 탭으로 흡수하고 파일 삭제
  6. 참조 5곳을 modal#앵커 로 수정
  7. 사이드바에서 패널 폼 제거
  8. 유실 0 대조 · 앵커 전수 · 링크 검사 · 빌드
  9. resources/changelog.md 갱신 (DS 문서를 고치면 반드시 같이 갱신 — 사용자 지시)

이 레포 규칙 (계속 지킬 것) ​

  • 산문은 한국어. 커밋은 영문 Conventional Commits 제목 + 한글 본문
  • 기존 문구는 바꾸지 말고 위치만 옮긴다. 수정이 필요하면 항목별로 사용자 확인
  • 내용 없는 탭은 만들지 않는다
  • 새 !important 금지. 하드코딩 hex 금지(토큰 사용)
  • 커밋 전 게이트: check:icons · check:modals · check:dialogs · check:spinners
  • git 계정 mirangpark-doris. gh 는 GH_TOKEN=$(gh auth token --user mirangpark-doris)
  • 사용자 가이드(docs/ko/guides/)는 외부 PM 팀 납품물 — 고치기 전 반드시 확인받을 것
  • 사용자는 비개발자다. 단계별 검증과 시각 변화에 민감하고, 「진행」 같은 짧은 신호로 답한다. 추측하지 말고 재서 답할 것 — 오늘 두 번(입력 여백 원인, 45곳 주장) 추측으로 틀렸다

아직 안 한 것 (이 브랜치 백로그) ​

  • PR 미생성. 커밋 21개가 origin 에 올라가 있다. PR 본문에는 **「사용자 가이드는 외부 원고를 직접 고쳤으므로 콸 리뷰 필요」**를 별도로 명시해야 한다(커밋 29c95e58)
  • 🟡 부분 2개 — AiAssistant · CsReport (chat-widget 에 FAB 배치 계약만 있음)
  • 패턴·기초 스텁 8개 — toast · app-chrome · embed-iframe · notification-flow · motion · accessibility · principles · getting-started · figma-tokens
  • 두 직원 패널의 공통 함수 29개(그중 14개는 완전 복사본)를 공용으로 빼는 리팩터링 — 별건
  • <input> 에 직접 margin 유틸을 준 4파일(눌려서 무시됨) — 별건

진행 상황 (2026-09-08 2차 세션 종료 시점) ​

전부 미커밋. 아래 상태에서 이어서 하면 된다.

인계문에서 틀렸던 것 (측정으로 정정) ​

인계문실제
modal.md 앵커21개26개 — #mini-modal-legacy #modal-demo #white-dim #dialog-spacing #text-color 가 빠져 있었음
panel-form 참조처5곳4곳 — permission-denied-modal.md 에는 panel-form 링크가 없다(「위저드」라는 낱말만 씀)

사용자에게 승인받은 결정 ​

  1. 탭은 5개 — 공통 · 컨펌 다이얼로그 · 일반 모달 · 패널 모달 · 적용·이력. ## 규칙 §1~§8 은 「§4 그대로」식 번호 참조가 문서 곳곳에 있어 쪼개지 않고 공통 탭에 통째로 뒀다.
  2. 일반 모달 데모를 실제 DS 클래스로 다시 씀. 예전 인라인 데모(.modal-demo-* 사본)가 타이틀↔본문 16px(표는 24) · 본문↔푸터 24px(표는 32)로 8px씩 어긋나 있었다.
  3. Playground 는 각 탭 맨 위(페이지 상단이 아니라). 그래서 문구 3곳을 고쳤다 — 「라이브 예시」 절 안내 · 패널 모달의 「페이지 상단 …」 · 컨펌 다이얼로그의 「페이지 상단 …」.
  4. ## 두 위저드 {#members} → ### 두 패널 {#members} (제목만. 본문의 「위저드」 약 20곳은 그대로 — 백로그).
  5. 패널 모달 tip 마지막 줄 「…규칙은 거기입니다」 → 「…규칙은 아래 패널 폼입니다」 (+ 「이 페이지가」→「이 절이」 — 안 고치면 틀린 문장이 됨).

한 것 ​

  • DocPlayground.vue — stacked prop 추가(속성 패널을 뷰어 아래로). 기본 false.
  • DemoPlainModal.vue 신설 — 일반 모달. 실제 .ds-modal__header/__body/__footer 사용.
  • DemoModalPlayground.vue 신설 — kind="dialog|modal|panel" 어댑터. 기존 데모 셋을 감싼다.
  • DemoConfirmDialog.vue — props(controls/presetId/titleOn/danger/guides) 추가. controls: false 면 자체 조작 막대를 감춘다(속성 패널이 대신 짐).
  • DemoPanelModal.vue — section prop 추가.
  • modal.md 848 → 945줄. panel-form.md 흡수 후 git rm.
  • 참조 수정: add-employee-panel(5) · edit-employee-panel(5) · my-info-form(5) · resources/changelog.md(3 — 이력 문장은 그대로 두고 링크 대상만 바꿨다. 안 고치면 빌드가 죽는다).
  • 사이드바 패널 폼 제거 · design-system/index.md 의 Patterns 예시 낱말 「패널 폼」→「모달」.

검증 결과 ​

  • 유실 0 — 원본 두 파일의 비어 있지 않은 줄 전수 대조. modal 122줄 · panel-form 17줄이 「없음」으로 나오는데 전부 사유가 있다: 승인된 문구 수정 5건 · 링크 재지정 · ##→### 강등 8건 · DocTabs 구조 줄 · 인라인 일반 모달 데모(HTML 48 + script 9 + style 58줄, DemoPlainModal.vue 로 대체).
  • 앵커 38개 전부 살아 있음(기존 37 + 신설 #panel-form). 숨은 탭 앵커도 URL 직접 접속으로 열린다.
  • 페이지 내 죽은 앵커 0 · 375px 가로 넘침 0 · 콘솔 에러 0 · cd docs && pnpm build 통과.
  • 대조/검증 스크립트: 스크래치패드 merge/assemble.py · merge/verify.mjs (Playwright 는 node_modules/.pnpm/playwright@1.60.0/node_modules 를 심링크해야 import 된다).

남은 것 ​

  1. 🔴 일반 모달 Playground 의 카드가 투명하게 렌더된다 (스크린샷 merge/pg-modal.png). 컨펌 다이얼로그 카드는 정상으로 흰색이고 둘 다 같은 bg-white 유틸을 쓴다. 측정된 사실: design-system.css 의 .ds-modal 은 border-radius: 8px + 그림자만 갖고 배경은 갖지 않는다 — 흰색은 bg-white 가 낸다. 두 카드의 계산값을 비교하는 것부터 시작할 것.
  2. 루트 pnpm lint:check && pnpm build(23/23) 미실행.
  3. resources/changelog.md 에 이번 통합 항목 추가 — 아직 안 함(DS 문서 수정 시 필수).
  4. 커밋 분할 · PR 생성(본문에 「사용자 가이드는 외부 원고를 직접 고쳤으므로 콸 리뷰 필요」 명시 — 커밋 29c95e58).