Skip to content

Latest commit

 

History

History
256 lines (192 loc) · 9.4 KB

File metadata and controls

256 lines (192 loc) · 9.4 KB

SEED Design - 기술 상세

기술 스택

  • 런타임/패키지 관리: Bun
  • UI 라이브러리: React
  • 타입 시스템: TypeScript
  • 패키지 빌드: bunchee, vite
  • 문서 플랫폼: Next.js, Fumadocs, Storybook
  • 린트/포맷: Biome

버전 정보는 문서에 중복 기재하지 않는다. 버전 확인은 루트 package.json과 각 워크스페이스의 package.json을 단일 소스로 사용한다.

공통 규칙

TypeScript

  • any, as unknown 사용 금지 (명시적 승인 없이)
  • 타입 import는 항상 type 키워드 사용
  • 동적 import보다 정적 import 우선

테스트 작성

  • 생성기·변환기가 만든 문자열은 조각(toContain)이 아니라 전체 일치로 검증한다. 조각 단언은 헤더가 빠지거나 행이 누락돼도 통과한다.
  • 배열 멤버십(expect(ids).toContain(id))은 toContain이 올바른 매처다. 위 규칙은 문자열 부분 일치에만 적용된다.
  • 생성물이나 외부 패키지 데이터를 유닛 테스트의 입력으로 쓰지 않는다. 그 데이터가 바뀌면 검증 대상이 멀쩡해도 테스트가 깨진다. 순수 함수를 export해 합성 입력으로 검증하고, 실데이터를 지나는 테스트는 데이터에 묶이지 않는 파생값(섹션 목록 등)만 전체 일치로 본다.
  • 유닛 테스트에서 네트워크를 타지 않는다. 모듈 스코프에서 비동기 초기화를 발사하면 그 모듈을 import하는 모든 테스트가 함께 요청을 보낸다.

패키지 관리

  • 항상 bun 사용 (npm/yarn 금지)
  • package.json 직접 수정 금지 - bun add 패키지명으로 설치

생성 파일 직접 수정 금지

  • packages/css/vars/, packages/css/recipes/ → rootage, qvism-preset에서 생성
  • packages/qvism-preset/src/vars/ → rootage에서 생성
  • 수정 필요 시 원천 파일 수정 후 bun generate:all 실행

아키텍처 개요

SEED Design은 디자인 토큰 → 스타일 → 컴포넌트 파이프라인을 따른다.

[Figma] → [rootage YAML] → [qvism-preset] → [css] → [react]
           ↓                ↓               ↓
         토큰 정의        Recipe 정의      CSS 생성    React 컴포넌트

생성 파이프라인

단계 입력 출력 명령어
1. Figma 동기화 Figma 변수 rootage YAML bun figma:sync
2. Rootage 생성 rootage YAML css/vars, qvism-preset/src/vars bun rootage:generate
3. Qvism 생성 qvism-preset recipes css/recipes bun qvism:generate
4. 전체 생성 - rootage, qvism, docs 산출물 bun generate:all

핵심 패키지 관계

rootage (YAML 정의)
    ↓ generate
qvism-preset (Recipe 정의) + css/vars (토큰)
    ↓ generate
css (CSS 파일 + 타입)
    ↓ import
react (스타일드 컴포넌트) ← react-headless (로직)
패키지 역할 소스/생성
rootage 디자인 토큰/컴포넌트 스키마 (YAML) 소스
qvism-preset 스타일 Recipe 정의 소스 (일부 생성)
css CSS/타입 생성물 생성
react-headless Headless UI 로직 소스
react 스타일드 React 컴포넌트 소스

주요 명령어

빌드/생성

명령어 설명
bun generate:all 전체 코드 생성 (rootage + qvism + docs)
bun rootage:generate Rootage에서 타입/변수 생성
bun qvism:generate qvism-preset에서 CSS 생성
bun packages:build 모든 패키지 빌드
bun headless:build react-headless 빌드

테스트

수정한 경로에 해당하는 테스트만 돌린다. 전체 실행은 커밋 직전 한 번이면 충분하다.

수정 경로 명령어
packages/react-headless/ bun headless:test
packages/react/ bun react:test
packages/lynx-react/ bun test:lynx-react
packages/cli/ bun test packages/cli
packages/rootage/, ecosystem/rootage/ bun rootage:test
tools/rootage-cdn/ bun --filter @seed-design/rootage-cdn test && bun --filter @seed-design/rootage-cdn typecheck && WRANGLER_LOG_PATH=/tmp/wrangler-rootage-dry-run.log bun --filter @seed-design/rootage-cdn wrangler:dry-run
ecosystem/qvism/ bun test ecosystem/qvism
docs/ bun docs:test
전체 bun test:all

bun test:alltest:unit(루트 bun test에서 packages/lynx-react만 제외)과 test:lynx-react(typecheck + vitest)를 합친 것이다. bun rootage:test가 함께 실행하는 bun rootage:validate는 여기 포함되지 않으므로, rootage YAML을 수정했으면 bun rootage:test를 따로 돌린다. 이 validator는 미사용 schema property를 정리할 수 있으므로 실행 뒤 git diff로 의도한 변경만 남았는지 확인한다.

테스트 환경: bunfig.toml[test].preloadscripts/happydom.ts(DOM 환경)와 scripts/testing-library.ts를 로드한다. 후자가 @testing-library/jest-dom 매처를 등록하고 afterEach(cleanup)을 전역으로 걸어주므로, 테스트에서 cleanup()을 직접 호출하지 않는다.

개발

명령어 설명
bun --filter @seed-design/docs dev 문서 사이트 개발 서버
bun --filter @seed-design/docs storybook Storybook 실행
bun figma:sync Figma에서 토큰 동기화

린트/포맷

명령어 설명
bun biome format --fix 코드 포맷 정리
bun lint:knip 미사용 코드 검사

Rootage 스키마 구조

토큰 파일 (*.yaml)

kind: Tokens
metadata:
  id: color
  name: Color
data:
  collection: color
  tokens:
    $color.palette.gray-00:
      values:
        theme-light: "#ffffff"
        theme-dark: "#000000"

컴포넌트 스키마 (components/*.yaml)

kind: ComponentSpec
metadata:
  id: component-name
  name: Component Name
data:
  schema:
    slots:           # 컴포넌트 파츠별 속성
      root: { ... }
      label: { ... }
    variants:        # variant, size, layout 등
      variant: { values: { ... } }
      size: { values: { ... } }
  definitions:       # 상태별 실제 값
    base: { ... }
    variant=brandSolid: { ... }

Recipe 시스템 (qvism-preset)

기본 구조

import { componentName as vars } from "../vars/component";
import { defineRecipe } from "../utils/define";
import { active, disabled, focus, pseudo } from "../utils/pseudo";

const recipe = defineRecipe({
  name: "component-name",
  base: { /* 기본 스타일 */ },
  variants: {
    variant: { brandSolid: { ... }, neutralWeak: { ... } },
    size: { small: { ... }, medium: { ... } },
  },
  compoundVariants: [ /* 조합 스타일 */ ],
  defaultVariants: { variant: "brandSolid", size: "medium" },
});

Pseudo 선택자

선택자 용도 비고
active hover/pressed 모바일 우선이므로 hover보다 권장
disabled 비활성
focus 포커스
focusVisible 키보드 포커스
loading 로딩 중
checked 체크됨 Checkbox 등
selected 선택됨 Tab 등

React 컴포넌트 패턴

단일 컴포넌트 (ActionButton 등)

import { recipe } from "@seed-design/css/recipes/component";
import { Primitive } from "@seed-design/react-primitive";

export const Component = React.forwardRef<HTMLElement, Props>((props, ref) => {
  const className = recipe({ variant, size });
  return <Primitive.element ref={ref} className={className} {...props} />;
});

복합 컴포넌트 (Checkbox 등)

// Headless에서 로직 가져옴
import { CheckboxRoot, CheckboxControl } from "@seed-design/react-checkbox";

// Styled 컴포넌트에서 스타일 적용
export const Checkbox = { Root, Control, HiddenInput, ... };

버전 관리

  • Changesets 사용: .changeset/ 디렉토리
  • bun changeset - 변경사항 기록
  • bun version - 버전·잠금파일을 업데이트하고 같은 Version Packages commit에 Rootage JSON 생성. Rootage package 범위만 생성하며 각 패키지의 package.json·CHANGELOG.md, changeset, lockfile, packages/rootage/__generated__/** 밖의 변경은 거부
  • bun release - 패키지 빌드 및 npm 배포
  • PR에서 /snapshot - pkg.pr.new 패키지 snapshot을 게시하고 packages/rootage/** 변경이 있으면 exact PR head용 Rootage CDN URL도 생성. snapshot은 stable 포인터를 변경하지 않으며 PR 종료 30일 뒤 정리

릴리스 브랜치 Fast-forward

  • minor → dev, major → dev PR에서 저장소 쓰기 권한이 있는 사용자가 /ff-merge 댓글을 남기면 dev를 PR head로 fast-forward한다.
  • GitHub의 rebase merge를 사용하지 않는다. 기존 커밋과 SHA를 유지한 채 dev ref만 force: false로 갱신한다.
  • PR이 열려 있고 초안이 아니며 두 브랜치가 갈라지지 않은 경우에만 실행한다. 실행 중 SHA가 바뀌면 병합하지 않고 최신 상태에서 다시 실행하도록 안내한다.
  • 실행 결과와 이전·이후 SHA는 GitHub Actions Summary에서 확인한다. 실패한 경우 명령 댓글의 👎 반응과 PR 댓글에서도 원인을 확인할 수 있다.

환경 변수

변수 설명 필수
FIGMA_ACCESS_TOKEN Figma API 토큰 figma:sync