Skip to content

Latest commit

 

History

History
401 lines (365 loc) · 36.8 KB

backlog.md

File metadata and controls

401 lines (365 loc) · 36.8 KB

DDS 백로그

우선순위순. 항목을 시작하면 상태를 진행 중으로, 끝나면 완료로 갱신하고 필요 시 하위 항목을 쪼갠다. 스펙 근거는 design-system.ko.md의 §번호로 표기.

상태: 대기 / 진행 중 / 완료 / 보류


P1 — Phase 1: 토큰 파이프라인과 첫 소비자

1. 토큰 빌드 파이프라인 (@devslab/dds-tokens) — 완료 (2026-08-13)

스펙 §2. 레포를 pnpm 워크스페이스로 전환하고 packages/dds-tokens 생성. Style Dictionary v4로 tokens/*.json에서 한 소스 → 전 산출물 생성:

  • dist/tokens.css — CSS 커스텀 프로퍼티 (--dds-color-bg-brand: …), 라이트 기본 + [data-theme="dark"] 다크 매핑 (서브트리 고정 가능 — D-003)
  • dist/tailwind/ — Tailwind v4 @theme CSS + v3 preset.js(+.cjs) (색 이름은 시맨틱 경로 유지, spacing은 TW 기본 그리드 위임 — D-004)
  • dist/tokens.ts — TypeScript 상수 (RN·런타임용, +tokens.js/tokens.d.ts)
  • dist/ionic.css — Ionic 테마 변수 매핑 (--ion-color-primary 등)
  • CI (GitHub Actions): 빌드 + JSON 스키마 검증 + 문서·토큰 값 불일치 검사 (pnpm verify — 라이트/다크 패리티, 참조 해석, docs/preview 드리프트)
  • 완료 기준 충족: pnpm build 한 번으로 4개 산출물, CI 초록. 결정 기록 D-001~D-005 (docs/decisions.md).

2. CSS 컴포넌트 레이어 (@devslab/dds-css) Core 6종 — 완료 (2026-08-13)

스펙 §2, §4. preview/index.html에 프로토타입된 스타일을 클래스 기반 패키지로 정식화. 토큰 CSS 변수만 참조(하드코딩 금지 — check-css.mjs가 hex/rgb/hsl/color-mix를 CI에서 기계 차단, D-007).

  • Button (primary/secondary/ghost/danger × sm/md/lg × 전 상태 §4.2 — loading은 aria-busy, danger 텍스트는 신규 color.text.on-status D-006)
  • TextField (라벨·헬프·에러 — aria-invalid 훅 포함)
  • Badge (brand + 상태 4종, 색 단독 신호 방지 도트)
  • Spinner / Skeleton (모션 감소 대응 — 스피너는 감속, 스켈레톤은 정지)
  • Dialog (+ 딤 오버레이, 네이티브 <dialog>/::backdrop 겸용)
  • Toast (리전 + 상태 도트 + 진입 모션)
  • 각 컴포넌트 접근성 체크 (§6) + do/don't 문서 (§4.4) — docs/components.md + .ko.md
  • 시각검증: preview/components.html (라이트/다크 트윈 + 루트 토글 — [data-theme="light"] 되고정은 D-003 개정) 브라우저 실측 — variant·size· 상태·hover(brand-hover 실측)·focus 링(2px/offset 2px)·테마 고정 확인.

3. AskLinq에 적용 (첫 소비자) — 완료 (2026-08-13)

스펙 8장 Phase 1. asklinq 레포의 위젯·SSR 페이지가 dds-tokens/dds-css를 소비하도록 전환. 기존 teal(#14b8a6)을 cyan으로 수렴.

  • 참고: 이 작업의 전사(前史) 문서는 asklinq 레포에서 이 레포로 이동됨
  • 토큰 소비 + 브랜드 정리 (asklinq#195 → 같은 날 D-051로 개정): cyan 수렴은 소유자 반려("홈페이지랑 같은 색") → 멀티 브랜드로 확정 (dds D-010, 스펙 3.1 개정) — AskLinq는 제품 teal 유지, 뉴트럴·상태는 vendored DDS 토큰에서(관리자/가입/메일 slate→zinc 리테마), 파비콘 마크는 on-brand 규칙대로 zinc.950. 테넌트 저장색 불변.
  • 멀티브랜드 CSS 규약 확정 (2026-08-15, D-012): 제품이 매핑 CSS 를 소유하고 dds 는 data-brand 규약 + "덮어도 되는 여섯 토큰"만 문서화(스펙 §3.1). preview/components.html 에 asklinq·booklinq × 라이트·다크 4조합 실측 패널 — booklinq 의 흰 전경은 on-brand 규칙의 예외가 아니라 적용례(teal.700 위 약 5.5:1).
  • dds-css 클래스 소비는 미착수 — asklinq 관리자/위젯 CSS는 자체 체계 (admin/styles.ts 등)라 클래스 교체는 별도 리팩토링. 토큰 값 수렴이 Phase 1의 목적(색 한 소스)이며, 컴포넌트 레이어 전환은 실익이 생길 때.

P2 — 확장

4. 쇼케이스 사이트 — 완료 (2026-08-13)

preview/ + brand/를 GitHub Pages(또는 org 허브 devslab-kr.github.io에 링크)로 배포. 장기적으로 Storybook 도입 검토 (스펙 4.4의 스토리 요구사항).

  • 쇼케이스 배포 — GitHub Pages 대신 devslab.kr에 실어서 (devlab.kr#31): repo 공개 없이 공개 URL 확보. preview/index.html → devslab.kr/dds/, preview/components.html → /dds/components.html (페이지 손 사본 + sync 스크립트 — 산출물 사본이 아니라 D-044 뒤에도 그대로). brand/는 사이트 자체 /brand 페이지가 대체. /brand의 design system 블록에서 링크. preview를 고치면 devlab.kr에서 node scripts/sync-dds-showcase.mjs 재실행 필요. (2026-08-15 devlab.kr#34로 icons.html 추가 — sync 스크립트가 이제 페이지·에셋·rewrite 배열 구조라 페이지가 늘어도 배열만 고치면 된다.)
  • Storybook 정적 사이트의 공개 배포만 미배포로 남음 — "DDS 공개 여부" 결정에 종속(로컬 pnpm storybook으로 충분, 소유자 배포 보류 선택).
  • Storybook 도입 (pnpm storybook / build-storybook, html-vite — React 비의존, D-008): Core 6종 전 variant·size·상태 스토리 + Foundations 토큰 표(생성된 tokens.js에서 렌더 — 드리프트 불가) + 테마 툴바(data-theme 스위치). CI가 storybook build를 검증. 매니저 UI는 DDS 브랜드 테마(zinc 다크 크롬 + cyan, .storybook/manager.js — 값은 tokens.js에서, 선택 하이라이트는 on-brand 규칙 준용 cyan.700).
  • 배포 보류 — GitHub Pages는 private repo에서 플랜 제한으로 거부됨 (editor-ruler에서 실증). "DDS 공개 여부"(아래 미해결 질문)가 정해져야 진행. 공개 전환 시: pages.yml 추가 + storybook-static 배포 + org 허브 링크.

5. 다크모드 토글 표준화 — 대기

devslab.kr과 동일한 localStorage 'theme' 키 + data-theme 속성 패턴을 dds-css의 공식 스니펫으로 문서화 (허브 README에 기존 구현 있음).

6. 아이콘 파이프라인 (@devslab/dds-icons) — 완료 (2026-08-15)

스펙 §3.7(D-013으로 개정). 단일 SVG 소스 → 파일·스프라이트·path 데이터 맵.

  • packages/dds-icons 신설. 코어 40종(업스트림 22 + 내비 글리프 18종 신규 제작: chevron/arrow 4+2, close, search, plus, minus, menu, more-horizontal, trash, edit, download, upload, external-link, refresh) + devslab.kr 전용 site- 7종(svg/site/).
  • scripts/check-icons.mjs — 24 그리드·currentColor·라운드 캡·세트별 스트로크(1.6/1.8)·색 리터럴 금지·body의 stroke/fill 오버라이드 금지· kebab 이름·dist 드리프트를 CI에서 기계 차단. (실제로 site-mobile· site-sun의 중복 stroke 속성을 잡아냈다.)
  • 스펙 §3.7 개정 — 스트로크 1.5 → 1.6 코어 / 1.8 site(D-013). 이름은 AskLinq 위젯 키와 1:1이라 변경 금지.
  • preview/icons.html 갤러리(라이트/다크 트윈, 24 그리드 상자 표시, 16·20·24·32 크기) 실측.
  • 프레임워크 컴포넌트 codegen은 미착수(의도) — 스펙 §2대로 그 프레임워크 제품이 생길 때.
  • 쇼케이스 배포 완료 (2026-08-15, devlab.kr#34): https://devslab.kr/dds/icons.html 라이브. sync 스크립트를 페이지·에셋· rewrite 배열 구조로 바꿔 icons.html + dist/icons.js를 싣고, /brand의 design system 블록에 > ./dds --icons 링크 추가(ko·en). 세 쇼케이스 페이지는 서로 상호 링크(#15).

7. Composite 컴포넌트 확충 — 완료 (2026-08-15)

스펙 §4.3 v1 인벤토리의 나머지 13종을 dds-css에 반영 (업스트림 시안 upstream/dds-css/src/ 기반, 하우스 스타일로 재작성).

  • IconButton, Textarea, Select, Checkbox/Radio, Switch, Chip, Avatar, Divider, Card, ListRow, Tabs, Tooltip(웹), EmptyState — 총 20종 (dds.css 번들 21파일). 문서 docs/components(.ko).md 19섹션, preview/components.html 라이트/다크 트윈, 스토리 4파일 추가.
  • 시안 대비 교정: ① Card의 [data-theme="dark"] 분기 제거(컴포넌트는 테마로 분기하지 않는다 — Dialog/Toast와 같이 elevation 토큰 그대로), ② Tooltip이 text.primary를 배경으로 쓰던 것을 신규 시맨틱 페어 bg.inverse/text.on-inverse로 교체(D-011), ③ 체크박스 disabled가 라벨·박스 양쪽에서 opacity를 곱해 두 번 흐려지던 것 수정, ④ ListRow 제목/부제에 display:block(span 마크업에서 한 줄로 붙던 실버그 — 브라우저 실측이 발견), ⑤ Select 셰브론 수직 정렬을 flex 정렬 의존에서 top:50% 기준으로.
  • BottomSheet은 의도적 제외 (지시서 2번): 웹 Modal ↔ 네이티브 BottomSheet 역할 매핑만 문서화하고 네이티브 구현은 Phase 3(네이티브 소비자가 생길 때).
  • 시각검증: 1280·375 양 폭에서 라이트/다크 트윈 실측 — 포커스 링(키보드 Tab), 행 높이 균일(60px), 긴 제목 말줄임, 가로 오버플로 0.

8. 홈페이지 /brand 페이지 마무리 — 완료 (2026-08-13)

jlc488/devlab.kr의 claude/brand-page 브랜치(별도 세션이 작업)를 리뷰. brand/index.html 시안과 대조 — 특히 로고 설명 문구가 구버전("건축 도면") 이면 "코드 블록을 쌓아 SaaS의 골격을 세우는 아키텍처 설계"로 교체 확인. 장기적으로 devslab.kr 자체도 dds-tokens를 소비하도록 전환.

  • 브랜치 리뷰·머지 (devlab.kr#29) — 로고 문구가 실제로 구버전이었고 ko/en 모두 교체. 실제 명함 앞면 4종(2인×2테마) 추가, 뒷면은 직통 번호+vCard QR이라 공개 웹 미게재(소유자 요청 반영, 개인정보).
  • devslab.kr의 dds-tokens 소비 전환 (devlab.kr#30, D-009 — vendored 사본 + sync 스크립트): body·electric 스케일·시맨틱 유틸리티가 토큰 한 소스, ThemeProvider가 class+data-theme 동시 스위치, ::selection on-brand 규칙 적용(기존 흰 글자 2.3:1 수정).
  • devslab.kr npm 소비 전환 (devlab.kr#114, 2026-11-03, D-044 — D-009 폐기): @devslab/dds-{tokens,css,icons,react} 정확 핀 0.29.2, 빌드 시 scripts/dds-assets.mjs가 node_modules에서 public/dds/*· palette.json 생성(gitignore), 옛 사본·sync-dds-tokens.mjs 삭제, Dependabot 주간 bump. check-consumers에서 devslab 제거. 남은 사본은 asklinq apps/api/src/dds/tokens.ts 하나(그 레포 몫).

9. 폰트 전략 확정 — 웹 완료 (2026-10-05)

Geist/Geist Mono 셀프호스팅 여부, Pretendard 서브셋, RN 번들 전략. 결정을 docs/decisions.md에 기록.

  • 웹: D-033 — @devslab/site-kit/fonts.css + fonts/(Geist·Geist Mono는 fontsource 문자권 서브셋, Pretendard는 저작자의 동적 서브셋 92개), face 이름 = 토큰 이름. 네 제품의 자체 사본 걷어내기는 각 레포 몫.
  • RN(네이티브 번들) 전략 — 네이티브 앱이 생길 때.

12. site-kit 국기 로케일 피커 — 완료 (2026-09-02)

D-017. LocaleMenu variant="flag" + 국기 데이터 14개. 첫 소비자 TraceLinq 랜딩.

13. site-kit 브라우저 번들에서 국기 아트워크 분리 — 완료 (2026-09-08)

D-020. TraceLinq 랜딩의 클라이언트 메인 청크가 dist/solid.js 통째(138 KB)만큼 컸던 것 — tree-shaking이 아니라 국기 SVG 115 KB가 SiteHeader에 딸려 온 것. 스프라이트 + <use>, 서버만 본문 작성, 브라우저는 동적 청크(서버 HTML 없을 때만). pnpm check의 최소 소비자 게이트(fixtures/bundle-probe)가 회귀를 막는다.

  • 남은 것: 서버 HTML의 본문 ~115 KB/페이지 → <img src> + 소비자 정적 서빙 (API 변경, D-020 재검토 시점).

14. 콘솔 컴포넌트를 DDS로 (Phase A) — 완료 (2026-09-12)

D-021~D-023. VisionLinq 콘솔이 DDS 토큰·CSS만 쓰고 dds-solid 컴포넌트는 0회, @tanstack/solid-table은 설치만 되고 표 12개가 수제였던 것(소유자 지시, 2026-09-12)에서 시작한 두 단계 계획의 1단계만 — 새 패키지·컴포넌트를 DDS에 짓고 검증했을 뿐, VisionLinq 쪽 소비 전환은 아직 손대지 않았다.

  • @devslab/dds-table 신설 — DataTable 컴포넌트, @tanstack/solid-table@9.2.4 정확히 고정. 정렬은 타입(sort: "client" | { statedOrder })이 정하고, 페이징은 링크, 컬럼 접기는 CSS, 라벨은 전부 필수 prop(D-021).
  • dds-css에 .dds-table* 스킨 + .dds-visually-hidden 유틸리티.
  • dds-solid에 createStatusPill(닫힌 도메인 throw / 열린 도메인 원문 렌더, D-022)과 ConsoleShell(내비 레일 + 페이지 헤더, 문구·라우팅은 제품 몫).
  • compatibility-canary가 실제로 /table 라우트를 하이드레이션까지 실행 + first-party(@devslab/*) 의존성은 workspace: 프로토콜이면서 정확한 링크 버전이어야 통과하도록 의존성 게이트 강화(D-023).
  • docs/decisions.md D-021~D-023, packages/dds-table/README(.ko).md, changeset(dds-table/dds-solid/dds-css minor — fixed 그룹에 dds-table 추가되어 전체 트레인이 함께 오른다).
  • 다음(Phase B, 미착수): VisionLinq 콘솔의 수제 표 12개를 DataTable로, 레일 셸을 ConsoleShell로, 상태 배지를 StatusPill로 전환 — 이 계획의 §Phase B(4개 PR)가 실행 순서. npm view @devslab/dds-table version이 0.11.0을 찍기 전에는 시작할 수 없다(그 전 작업은 커밋 금지된 로컬 pnpm.overrides가 필요). → 이후 VisionLinq에서 진행됨(VL-058, visionlinq#56~#59) — 남은 제품 쪽 규칙은 아래 15번.

15. 콘솔 테이블 규칙 4종을 DDS로 — 완료 (2026-09-13)

D-025. VisionLinq가 DataTable로 옮긴 뒤에도 product-shell.css에 남겨 둔 표 규칙을 일반형으로 table.css에:

  • 셀 안 <code> 13px 모노.
  • 행 액션 32px·줄바꿈 금지·액션 셀 세로 패딩 4px(크기 수식자 무관 — 패딩까지 정함).
  • 밀집 표의 --sm 버튼·행 액션 24px(VisionLinq .console-copy 전용 규칙의 일반형) + --sm 버튼을 담은 셀(밀도 무관) 패딩 4px — 스크린샷 검토에서 기본 밀도의 복사 버튼 행이 53px로 튀어나온 것을 보고 넓힘.
  • 긴 래퍼(--tall)의 분리 테두리.
  • 거친 포인터에서 44px 하한 재선언 — 위 규칙이 button.css를 특이도로 이기므로.
  • 소스 계약(tests/dds-table-contracts.test.mjs) + 실제 캐스케이드 기하(tests/browser/table.spec.ts, fine/coarse 두 포인터, verify:foundation에 편입). main의 CSS로 돌리면 4개 실패, 거친 포인터 블록을 빼면 터치 테스트 실패 확인.
  • 카나리 /table 라우트는 행 액션·밀집·긴 래퍼를 렌더하지 않고 dds.css도 로드하지 않아 시각 확인 대상이 아니다 — 브라우저 픽스처가 대신한다.
  • 다음(VisionLinq, 별도 세션): 릴리스 후 @devslab/* 올리고 규칙 1·2·4와 dense 복사 버튼 규칙 삭제(.dds-table .console-id는 유지), 유닛·하네스·1440/390 스크린샷 확인.

16. site-kit 한 언어 랜딩·사업자 정보 바닥글 — 완료 (2026-09-24)

D-029. FM덴탈서비스 랜딩 리뷰에서 kit으로 못 그리는 9건을 선택 props로:

  • 헤더 locale 선택, 브랜드 링크 이름(SiteBrand.label), 빈 이름이면 푸터 <strong> 없음.
  • 좁은 화면 메뉴: Esc로 닫고 버튼으로 포커스, 링크를 따라가면 닫힘(버튼은 유지, 안쪽이 처리한 Esc는 무시).
  • 터치 44px 링크, 720px 이하 메뉴 44px 줄, 닫힌 좁은 헤더 첫 줄 64px.
  • 섹션 scroll-margin(--site-header-block-size), 히어로 키커 자간·굵기 사용자 속성.
  • 푸터 details·linksLabel, SiteLink.emphasis.
  • 헤더·푸터가 brand·details를 한 번만 읽음 — 개발 빌드 하이드레이션 테스트로 고정.
  • 테스트: 컴포넌트 16개(옛 코드에서 실패 확인), 소스 계약, 개발 빌드 하이드레이션(메모 제거 시 실패 확인), 브라우저 기하 마우스·터치·터치 넓은 화면(main CSS에서 실패 확인).
  • 사전 리뷰(5개 관점, 확인된 지적 15건) 반영: 브랜드 링크 44px, 새 탭·수정 키·aria-modal Esc에서 메뉴 유지, 푸터 기준선 정렬, details 여백, 워드마크 로고 크기, 모든 소비자 기본값·타입 변경 문서화.
  • 다음(BookLinq·TraceLinq, 올릴 때): 휴대폰 헤더 89px → 65px — 375px 시각 확인. BookLinq는 MarketingFrame의 SiteHeaderProps를 & { locale: LocaleState }로 좁혀야 타입 검사가 통과.
  • 다음(fm-dental, 별도 세션): 랜딩 구현 때 이 버전을 쓴다 — 워드마크 logo + name: "" + label, locale 없음, details에 사업자 정보·주소, linksLabel, 개인정보처리방침 emphasis, 랜딩 뿌리에 --site-hero-eyebrow-tracking: 0.

17. site-kit 분석 동의(옵트인) — 완료 (2026-10-05)

D-034. 허용 전에는 구글에 닿는 것이 없다 — 코어 매니저·쿠키·Consent Mode·기록 도구, Solid 바·설정 대화상자·바닥글 "쿠키 설정", TanStack consent head.

  • 테스트: 코어(소스 단계, 변이 5종으로 확인), 컴포넌트 jsdom + axe, SSR·실제 라우터 head, 개발 빌드 하이드레이션, 브라우저(nonce CSP·390/1280·라이트/다크·포커스 가둠·같은 무게).
  • BookLinq 적용에서 나온 결함 둘(2026-10-06, D-034 추가): 루트가 선언한 동의 export 10개가 실행 시 undefined → 배럴을 export *로, 릴리스 검사가 tarball의 선언 대 실제 export를 진입점마다 비교. 긴 라벨이 390px 세 칸에서 단어 중간에 끊김 → 공백에서만 줄바꿈(한국어 keep-all), 바 너비 36rem 이하에서 세로로 쌓기, 한 줄 경계 60rem — 6개 언어 × 320–1280px 브라우저 테스트. 소유자 결정으로 바 문구를 짧게, "자세히 보기"는 제품 방침의 이용 통계 절로 가는 필수 learnMoreHref, 설정은 한 줄씩 + 취소·선택 저장.
  • 다음(제품마다): 0.17.0으로 올릴 때(필수 prop·새 메시지 키라 minor) learnMoreHref 넘기기, 방침의 그 절에 전체 고지(Google Analytics 4·Google LLC·미국 이전·보관 기간·광고 미사용·철회 방법), 다른 로케일을 같은 톤으로 + learnMore·cancel 키.
  • 다음(제품마다, 각 레포): gtm → consent 옮기기, ConsentBanner + 바닥글 consentSettings, /api/consent 엔드포인트 + consent_records 마이그레이션 + 3년 정리 작업, 개인정보처리방침에 동의 기록 보관 기간, GTM 콘솔의 GA4 태그 "추가 동의 필요: analytics_storage".
  • 다음(devslab.kr): 정적 내보내기라 head는 기본값만, 매니저가 하이드레이션 뒤 로드(README "Solid 없이"). 백엔드가 없으므로 기록을 어디에 둘지 소유자 결정 필요.

18. site-kit React 진입점 — 진행 (2026-11-09)

D-045. @devslab/site-kit/react: 국기 LocaleMenu, 헤더·푸터·테마·셸·레이아웃·섹션 원시, Solid와 같은 클래스·마크업(테스트로 고정).

  • 국기 본문 조건부 export(서버=본문, 브라우저=스텁), 하이드레이션 무패치, 번들 게이트, Next.js 16 실측.
  • React ConsentBanner — 대화상자 원시 결정 필요(dds-react 비의존 유지).
  • RequestAccessForm React판, Next.js Metadata 어댑터.
  • Solid dist/*.d.ts의 ../core/*.mjs 경로 결함(타입이 any로 풀림).
  • admin.devslab.kr 정책 v3 클라이언트(코어) + PolicyDocument(react·solid) — JeongsanNow·qoqo 사본에서 추출, Qooroo가 세 번째 소비자.
  • (고려사항, 언젠가) React 제품에서 Solid 설치 걷어내기 — styles.css가 dds-css를 직접 import, dds-solid를 선택 피어로. Solid 제품 설치 방식이 바뀌므로 소유자 결정 필요(D-045).
  • 마케팅 헤더와 TopNav 통합 여부 — dds-css 마케팅 변형으로 네 프레임워크 함께(별도 결정).
  • 다음(제품): Qooroo 랜딩이 첫 소비자 — 발행 후 .site-brand__lockup으로 마크+워드마크.

P3 — 모바일 이후

10. 모바일 방향 결정: RN vs Ionic — 해소 (2026-11-10, D-048)

실제 소비자가 Kotlin·Jetpack Compose 였다 — 아래 19번으로 진행. RN·Ionic 패키지는 여전히 그 프레임워크 제품이 생길 때만. 아래는 원래 적어 둔 내용.

스펙 §8 Phase 3. 네이티브 성능·제스처 필요 → RN(dds-native 구현), 웹 코드 재사용 우선 → Ionic(기존 ionic.css + dds-css 재사용, 신규 패키지 불필요). 결정을 decisions.md에 기록. 그 전에 모바일 패키지를 미리 만들지 않는다 — 소비자 없는 구현은 썩는다.

11. 릴리스 파이프라인 — 보류 (패키지 2개 이상 생기면)

스펙 §7. changesets 기반 lockstep semver, deprecation 정책(minor 1개 경고 후 major 제거) 자동화.


19. 안드로이드 네이티브 (kr.devslab:dds-android-tokens, dds-compose) — 진행 중 (2026-11-10)

D-048. 가이드 mobile-native.ko.md, 설계 docs/superpowers/specs/2026-11-10-dds-android-native-design.ko.md.

  • 0.1.0 값: tokens/native.json, 생성기, 어긋남 검사, hex 금지 검사 (pnpm run check).
  • 0.1.0 테마: Material3 대응표, 브랜드 여섯 색 주입과 대비 검사, 글자 8종, Pretendard 정적 글꼴, 큰 글자 모드.
  • 0.1.0 모션: 화면 내용 진입, 목록 순차 등장, 움직임 줄이기, 스플래시 넘겨주기, 겹쳐 그리는 진행 표시줄, 정지 자리 표시, 당겨서 새로고침. 가이드 §2가 정산나우·Qooroo의 디테일을 규칙 + 코드 + 확인 방법으로 담는다.
  • 0.1.0 브랜드 덮어쓰기: 웹과 같은 여섯 토큰을 색 리소스로(XML·Compose 공통), 대비 검사. (0.6.0에서 바탕 셋과 대비 예외를 더했다, D-053.)
  • catalog 앱과 에뮬레이터 캡처 확인, 로컬 Maven 배포, CI·릴리스 워크플로.
  • Maven Central 첫 배포 0.2.0 (2026-11-11) — android-v0.2.0 태그, 릴리스 워크플로 통과, kr.devslab:dds-android-tokens·kr.devslab:dds-compose 0.2.0 확인. 조직 Maven 시크릿은 이 저장소에 열려 있다. 조직 프로필 README에 행 추가(devslab-kr/.github#38).
  • 0.2.0 부품: DdsButton, DdsIconButton, DdsTextField, 선택 3종, DdsCard·DdsSection, DdsListRow, DdsNotice(종류별 아이콘), DdsBadge, DdsTopBar·DdsBottomBar·DdsNavRail, 진행 표시·자리 표시, DdsPullRefresh, DdsEmptyState, DdsDialog. 캡처에서 나온 규칙 둘을 부품에 넣는다: 아래 탭 라벨은 한 줄 말줄임, 한 줄에 들어가지 않는 버튼 묶음은 세로로.
  • 0.2.0 스플래시: 실물 기기(Android 17) 여섯 번 측정에서 로고 없는 프레임 0회 — 덮개가 그리기까지 맡는 안은 만들지 않았다. 아이콘 없는 스플래시(런처 밖 실행)에서는 로고를 날리지 않는다(splashShowedMark).
  • 0.2.0 아이콘: dds-icons SVG → Compose ImageVector 생성, 어긋남 검사.
  • 어두운 화면 위험·정보색 대비(D-049, 2026-11-11): red.300·blue.300으로 4.5:1 통과. 웹 토큰과 안드로이드 0.2.1.
  • 오류용 "원 안 X" 아이콘(웹 dds-icons에 추가하면 안드로이드에도 생성된다) — 지금 위험 안내는 X 아이콘.
  • 0.3.0 부품(2026-11-11): 검색칸, 선택칸, 이름·값 한 줄, 화면 안 탭, 아래 시트, 메뉴, 토스트. 뒤로 가기·종료 규칙 (DdsBackHandler), 탭 전환 깜빡임 수정, 낭독기·테스트에 원문 전달(readAs).
  • 0.4.0(2026-11-11): 앞으로·뒤로 이동의 페이드 제거, 떠나는 화면을 비우지 않고 비활성으로 알림 (LocalDdsScreenActive), 검색칸 적용 버튼 — 정산나우의 실물 폰 측정에서.
  • 아직 없는 부품: 날짜·시간 선택(가이드 §12).
  • DdsSelectField는 시트로 열린다. 붙어서 열리는 드롭다운 방식이 필요한지(정산나우는 기존 드롭다운 유지).
  • 당겨서 새로고침: 접근성 ScrollBy로 맨 위를 넘기면 표시가 반쯤 남는다(손가락으로는 재현 안 됨).
  • 0.5.0 접근성(2026-11-11): 입력칸·선택칸 한 요소화와 오류 알림, 안내 메시지 종류, 진행 중 버튼, 목록 행, 검색칸 지우기, 진행 표시줄 이름, 화면 이름, 탭·다이얼로그·칩. 기기 테스트 22개(가이드 §8.1). 당겨서 새로고침의 낭독기용 동작은 닿을 수 없어 뺐다(보이는 새로고침 버튼을 둔다).
  • 폰에서 TalkBack으로 직접 듣기 — 기기 테스트는 전달되는 정보를 고정하지만 실제 음성은 아무도 듣지 않았다.
  • 접근성 남은 것: 시트가 열릴 때 첫 초점, 키보드 초점 순서(상단 바·내용·아래 바), 스플래시 덮개 아래 가리기, 목록 행 끝의 긴 내용이 제목을 밀어내는 것, 아래 탭 라벨 말줄임.
  • 컨트롤 테두리 3:1과 어두운 화면 안내 글귀(D-050, 2026-11-11): border.control, zinc.450·zinc.550. 웹과 안드로이드 0.5.0.
  • 움직임 되살리기(D-051, 2026-11-11, 0.5.0): 화면이 바뀌는 동안 두 화면을 겹쳐 두어 탭(150ms)과 앞으로·뒤로(100ms) 페이드가 돌아왔다 — Navigation 3 NavDisplay에는 ddsScreenChange, 화면을 직접 바꾸는 앱에는 DdsScreenHost. Navigation 3에서 뒤로 가기 밀기가 재생되지 않던 버그 수정. 칩·버튼 누름·입력칸 테두리·탭 라벨 색 전환(100ms), 탭 밑줄 슬라이드(200ms). 기기 테스트 NavDisplayOnDeviceTest 5개, MotionOnDeviceTest 9개, RebuiltWindowTest 2개.
  • 스플래시 덮개가 걷힐 때 로고가 어두워지던 것(2026-11-12, 0.5.0): 도착 자리가 없을 때 덮개와 로고를 따로 흐려서 중간에 덮개 바탕이 로고에 25% 섞였다(정산나우가 실물 폰에서 확인). 한 장으로 합쳐서 걷는다. 기기 테스트 SplashOverlayOnDeviceTest 2개(에뮬레이터). 정산나우의 실물 폰에서도 로고 밝기가 그대로였다.
  • 0.5.0 화면 전환을 실물 폰에서 프레임 단위로 녹화(2026-11-12, 정산나우, 접힌 화면·어두운 화면): 탭·열기· 뒤로에서 비는 프레임 없음, 뒤로 갈 때 내용이 앞쪽에서 밀려 들어옴. 가이드 §2.3 "0.5.0 실물 폰 측정".
  • 0.5.0을 실물 폰에서 재지 못한 것 — 뒤로 쓸어 넘기기(예측형 뒤로 가기. 정산나우 폰은 버튼 3개 방식), 접고 펴기·돌리기의 프레임, 펼친 세로, 밝은 화면. 펼친 가로(933×704dp)는 정산나우가 Maven Central의 0.5.0으로 전체 연결 테스트 88건과 "탭을 바꾸는 동안 빈 프레임 없음" 검사를 통과시켰다(2026-11-12). 녹화해서 프레임으로 본 것은 아니다.
  • 0.6.0 제품이 정하는 색(D-053, 2026-11-12) — 배포했다(#145, android-v0.6.0). 대비 예외를 조합별로 적기(dds_allow_contrast_*, DdsContrastPair), 바탕 셋(dds_color_bg_default·_subtle· _elevated), 채운 보조 버튼과 Plain 버튼, 그림자 없는 메뉴·끝 맞춤(DdsMenuAlign.End)· DdsMenuDivider. 단위 79개, 기기 74개(에뮬레이터 74개 실행, 실패 없음, 건너뜀 없음. 실물 폰 74개 실행, 실패 없음, 2개 건너뜀). 카탈로그 Colors 탭 "Product colors". 설계 docs/superpowers/specs/2026-11-12-dds-android-product-colors-design.ko.md.
  • 0.6.0에서 미룬 것 — ① 공개 API 호환 검사(API 덤프)가 빌드에 없다. 0.6.0은 DdsBrandColors와 DdsMenu에 인자를 더했다. ② 테스트 APK의 targetSdk가 26이라 시스템 대화상자가 떠서 화면 캡처가 어두워진다(그림자 검사가 둔해진다). ③ 메뉴의 색 값 자체를 보는 검사 둘은 에뮬레이터에서만 돈다(폰의 캡처는 눈 보호 필터로 물들어 건너뛴다). ④ 폰에서 화면 캡처를 쓰는 메뉴 테스트 다섯이 같은 날 두 번 실패했다 — 캡처에 페이지 대신 회색이 찍혔다. 다시 돌리니 통과했다. 원인은 찾지 못했다. 정산나우의 테스트가 같은 폰을 쓰고 있어, 한 번은 그쪽 앱이 앞에 떠 있는 채로 돌려 21개가 실패했다. 폰을 나눠 쓰는 규칙이 필요하다. ⑤ 리소스 덮어쓰기를 별도 앱에서 시험하지 않았다. 테스트의 대역(가짜 언어 폴더)은 DDS가 values-night에 정한 색에서 실제 앱과 다르게 동작한다. ⑥ 확인하지 못한 것: 오른쪽에서 왼쪽 기기 언어, 폰의 다른 창 크기에서 전체 테스트, 제품 페이지에서 레일·시트·다이얼로그의 픽셀, 제품 바탕 위의 컨트롤 테두리 3:1.
  • 입력칸 요청(정산나우) — 글자의 사본을 남기지 않는 입력칸, 초점이 가면 화면 안으로 끌어오기 (bring-into-view), 최소 줄 수(minLines). 그리고 단계 화면의 틀.
  • 세그먼트 컨트롤(0.8.0, #149, 2026-11-13) — DdsSegmentedControl·DdsSegment. Qooroo의 명함 종류 토글이 웹 SegmentedControl 모양을 골라서(소유자) 그 웹 규칙을 터치 크기 그대로 옮겼다. 가이드 §12, 변경 기록 0.8.0. 고른 면은 0.8.1에서 bg.raised(어두운 zinc.800), 그림자 1단계로 확정(D-054, §10의 20번). 0.9.0에서 고른 면이 미끄러져 옮겨 간다(D-055, 웹 함께). 다음: Qooroo가 앱의 사본 DdsStyleSegmented를 이것으로 바꾼다.
  • 화면 틀(0.7.0) — 배포했다(#147, android-v0.7.0, 2026-11-13). 정산나우가 로컬 빌드로 옮겨 배포 전에 확인했다. 앱의 모든 화면을 DDS 부품으로 옮기고, 475×751·704×933·933×704에서 밝은·어두운 화면으로(475×751은 글자 200%도) DdsFrameCheck와 assertSameLines로 쟀다 — 1dp 넘게 어긋난 시작선이 없었다. 펼친 폰의 전체 연결 테스트에서 DDS 탓의 실패는 없었다. 거기서도 확인하지 못한 것: 폰을 실제로 가로로 돌린 것, TalkBack, 접힌 폰의 전체 테스트. DdsAppFrame, 새 DdsScaffold, DdsBodyColumn·ddsBody·ddsBodyLines, 본문 선에 서는 DdsTopBar (onBack, 두 줄 제목), DdsCenteredColumn·DdsCenteredTitle, DdsPaneList·DdsPaneItem, 새 꾸러미 dds-compose-testing(DdsFrameCheck). 기기 테스트 전체 실물 폰 접은 화면(1248x1972) 170개, 펼친 화면(2448x1848) 174개 실행, 실패 0, 건너뜀 2. 카탈로그를 새 틀로 옮기고 Layout 쪽을 더했다. 가이드 §13, 변경 기록 0.7.0, D-052. 배포는 정산나우가 로컬 빌드로 옮겨 폰의 창 세 가지에서 확인한 뒤. 인계 메모: 공유 노트 dds-android-0.7.0-consumer.md. 확인하지 못한 것: 뒤로 밀기, 진짜 옆쪽 구멍, 오른쪽에서 왼쪽 기기 언어, 화면 분할, 따로 만든 앱에서 테스트 꾸러미, TalkBack. 원래 요청 — 정산나우 요청(2026-11-11, 11-12 추가): 본문 최대 폭·넓은 화면 기준·고정 목록 폭 숫자, 창 폭 분류, 화면 틀(하단 탭 / 고정 왼쪽 레일 / 고정 목록), 본문 기둥, 본문에 맞춘 상단 줄, 시작선 검사 도우미. 넓은 화면의 고정 목록과 좁은 화면의 "목록 → 화면 → 뒤로"가 같은 목록 하나에서 나오게 한다(정산나우가 이렇게 정했다). 소유자가 정한 것: 옆 여백 16/24, 중간 폭(600~839)은 레일만, DDS 틀 부품이 메뉴를 그리는 방식, 검사 도우미는 새 꾸러미로. 설계: docs/superpowers/specs/2026-11-12-dds-android-screen-frame-design.ko.md. 배포는 정산나우가 실물 폰의 창 세 가지에서 확인한 뒤에 한다. 정산나우는 틀을 커밋했고(7f6f3b3) 실물 폰의 창 세 가지(펼친 세로·펼친 가로·접힌)에서 확인했다(밝은 화면과 일반 폰 폭은 아직). 요청서: 공유 노트 dds-android-frame-request-2026-11-11.md.
  • 한 가지 일만 하는 화면(0.7.0, 화면 틀과 함께 만들었다 — 배포 대기) — 로그인 전·잠금. 가운데 묶음(폭 최대 400dp, 넘치면 위에서부터 스크롤), 가운데 정렬 제목은 줄 길이를 고르게. 정산나우 JnGateColumn·JnGateTitle(fb40b66).
  • 스플래시 로고가 가는 길을 화면이 고르기(모션 요청, 0.7.0 이후 후보) — 시간, 곡선, 떠나기 전 멈춤. 지금은 300ms 고정이라 정산나우는 로그인 전 화면에서 직접 그렸다(1d8a124).
  • 화면 덩어리가 차례로 도착하는 값(모션 요청, 0.7.0 이후 후보) — ddsAppear의 목록용 30ms 간격은 화면 하나의 큰 덩어리 서너 개에는 너무 빨랐다(정산나우 소유자 판단). 목록용과 따로 간격·시간·오르는 거리를 정한다.
  • 입력칸 세 건(화면 틀 다음, 정산나우 요청 2026-11-12) — ① 글자 사본을 갖지 않는 입력칸: DdsTextField·DdsSearchField는 value: String 방식이라 포커스를 잃거나 키보드가 입력을 마무리할 때 옛 값이 새 값을 덮을 수 있다(정산나우에서 6.999가 6이 된 결함. DDS 부품에서 재현해 보지는 않았다). TextFieldState를 받는 형태가 필요하고, 번호 칸은 저장 꾸러미에 넣지 않을 수 있어야 한다. ② 칸 이름·칸· 아래 한 줄을 한 묶음으로 보이게 끌어오기(키보드가 뜨면 이름과 오류 문구가 잘린다). ③ 여러 줄(minLines). 정산나우 JnTextField·JnFieldBlock(42ae9d8).
  • 단계로 하는 화면의 틀(화면 틀 다음, 정산나우 요청 2026-11-12) — 단계 수는 상단 줄 안에, 단계 줄은 바로 아래 4dp, 이전·다음은 아래 고정 48dp, 키보드가 떠도 제자리. 정산나우 JnWizardFrame(195ea13). 화면 틀의 barReserve가 이것을 위한 자리다.
  • 채운 버튼 위의 포커스 링이 채움색에 묻힌다(웹 공통).
  • 정산나우·Qooroo를 0.2.0 부품으로 옮기기(각 레포에서).
  • 웹 규칙에 없어 정해야 하는 것 13가지 — 가이드 mobile-native.ko.md §10. 소유자가 DDS 규칙으로 정하면 tokens/native.json이나 명세를 고친다(메인 색에서 나머지를 정하는 법, 터치 화면 높이, 정지 자리 표시, 카드 그림자, 큰 글자 표, 아래 탭 선택 표시 등).
  • 어두운 화면 상태색 대비 — 위험 3.62:1, 정보 4.07:1 (스펙 §6은 4.5:1). 웹도 같은 값. 토큰 변경이라 전 제품에 영향 — 소유자 결정 필요.
  • 소비자 전환(각 저장소): 정산나우 → Qooroo(자기 브랜드 여섯 색) → EDS 치과(Kotlin Multiplatform이라 값만).

미해결 질문 (오너 확인 필요)

  • 로고 스토리: brand/index.html의 마크 해석("코드 블록 + 아키텍처 설계")은 형태를 보고 붙인 것. 실제 제작 의도가 따로 있으면 교체.
  • DDS 공개 여부: 해소 (2026-08-31, D-015) — 레포 공개 + 공개 npm @devslab/* 배포, DevsLab Source-Available License 1.0 적용(오픈소스 아님). 남은 오너 액션: ① GitHub 레포 Public 전환, ② 레포 시크릿 NPM_TOKEN 확인, ③ dds-v* 태그 푸시로 릴리스 워크플로 가동.
  • 브랜드 페이지 i18n 범위: devslab.kr의 14개 로케일을 /brand에도 전부 적용할지, ko/en만 유지할지.

참고 링크

Vue 공통 패키지 — 진행 중 (2026-10-22)

EDS Desktop 실사용 Button·Icon·Input·DatePicker부터 dds-vue에 승격하고 배포한다. 공통 달력 CSS는 CSS 계층에 두고, React 브리지는 제거한다. 초기 0.27.0 배포 후 사용자 요청으로 컴포넌트 목록을 선제 확장하고, 별도 dds-table-vue를 준비한다. 검증과 공개 배포 완료 시 상태를 갱신한다.