LogoSEO Jing
  • All Posts
  • SEO Jing
  • KD Team
  • CLab CoreTeam
  • Study

Contact Me

© 2026 SEOJing. All rights reserved.

DevLogSEO JingInsight

디자인 시스템을 구축할 때 주의할 점

2026년 3월 14일·4분 읽기

디자인 시스템이란

컴포넌트, 디자인 토큰(색상·간격·타이포그래피), 규칙을 하나의 패키지로 통일해서 여러 앱에서 일관된 UI를 만드는 체계다. 이 프로젝트에서는 packages/ui가 그 역할을 한다.


파일 구조 — 컴포넌트 단위로 폴더 분리

packages/ui/src/
├── paper/
│   ├── paper.tsx          ← 컴포넌트 본체
│   ├── paper.types.ts     ← 타입 정의
│   ├── paper.constants.ts ← 디자인 토큰 매핑
│   ├── paper-error.tsx    ← 에러 바운더리
│   ├── paper.stories.tsx  ← Storybook 스토리
│   └── index.ts           ← 배럴 export
└── index.ts               ← 패키지 진입점

이렇게 하면: - 컴포넌트끼리 의존성이 명확 - 타입·상수·스토리가 함께 있어서 찾기 쉬움 - index.ts 배럴로 외부에서 import {Paper} from "@app/ui" 가능


디자인 토큰 — CSS 변수로 관리

globals.css의 @theme 블록에 색상·간격·폰트·애니메이션을 정의하고, 컴포넌트에서는 Tailwind 유틸리티로 참조한다. 하드코딩된 값 대신 토큰을 쓰면 테마 변경이 한 곳에서 가능.


컴포넌트 API 설계 — props를 제한된 프리셋으로

ts
export const PAPER_PADDINGS: Record<string, string> = {
  none: "p-0",
  sm: "p-3",
  md: "p-6",
  lg: "p-8",
  xl: "p-12",
};

사용자가 임의 값을 넣는 게 아니라 padding="md" 같은 프리셋을 선택하게 한다. 일관성이 보장되고, 타입 자동완성도 된다.


유의할 점

서버 컴포넌트 vs 클라이언트 컴포넌트

Next.js(vinext) 환경에서 "use client"를 붙이면 해당 컴포넌트와 그 하위 트리가 클라이언트 번들에 포함된다. 디자인 시스템에서는:

  • useState, useEffect 등 훅이 필요한 컴포넌트만 "use client" - 순수 렌더링 컴포넌트(ArticleHeader, Subtitle, Paragraph 등)는 서버 컴포넌트로 유지

CSS 애니메이션에서 transform 충돌

같은 요소에 두 개의 애니메이션을 걸면 둘 다 transform을 건드릴 때 마지막 것만 적용된다. 해결법: - 별도 DOM 레이어로 분리 (바깥 div에 이동, 안쪽 div에 회전) - 또는 하나의 키프레임에 모든 transform을 합침

Tailwind v4 @theme 토큰과 클래스 매핑

-animate-elliptic-in: ...으로 등록하면 animate-elliptic-in 클래스가 자동 생성된다. 키프레임 이름과 토큰 이름이 일치하지 않아도 되지만, 토큰 값 안에서 참조하는 키프레임 이름은 @keyframes 정의와 정확히 일치해야 한다.


Skeleton 구조

tsx
function PaperSkeleton() {
  return (
    <div className="mx-2 animate-pulse rounded-lg bg-gray-200 dark:bg-gray-800">
      <div className="aspect-[1/1.414] w-full" />
    </div>
  );
}

실제 콘텐츠가 로딩되기 전에 보여주는 뼈대(placeholder) UI다. 콘텐츠와 비슷한 형태를 가진 회색 박스에 animate-pulse를 적용한다.

로딩 방식사용자 경험
아무것도 안 보임"고장났나?"
스피너"로딩 중이구나"
Skeleton"곧 콘텐츠가 채워지겠구나" — 체감 로딩 시간 감소

Skeleton은 최종 레이아웃과 같은 공간을 미리 차지하므로 레이아웃 시프트(CLS)가 없다. React Suspense의 fallback으로 연결하면 콘텐츠 로딩 중에는 스켈레톤이 보이다가, 로딩 완료 시 실제 컴포넌트로 교체된다.

포스트 목록

/SEOJing/devLog/insight
파일 10개, 폴더 0개
엄청난 피드백생각보다 어려웠던 댓글, 완독 로컬스토리지디자인 시스템을 구축할 때 주의할 점폰트는 왜 메인 페이지에서만 적용이 안되고 있었을까?MDX DOM 트리 파싱하기MDX 관련 이슈 노트결국 Node.js 까지 와버렸다전체적인 플로우Storybook으로 디자인 시스템 테스팅하기MDX가 뭘까?