Skip to content

Daily1Hour/PickMe-Style-Guide

Repository files navigation

스타일가이드

🛠️ 기술 스택

Storybook Module Federation
Vuejs React Chakra UI
Vite TypeScript JavaScript

💁 소개

이 프로젝트는 멀티 프레임워크 지원과 일관된 UI/UX 유지를 위한 공용 UI 컴포넌트 시스템입니다.

Vite 기반으로 빌드 및 서빙이 가능하며, 런타임에서 원격 컴포넌트를 로드해 패키징 없이 공유할 수 있습니다.
스토리북을 통해 자동화된 문서 생성, 실시간 UI 테스트, 디자인 시스템 연계를 통해 효율적인 개발과 유지보수를 제공합니다.

💡 주요 기능

  1. Module Federation을 활용한 컴포넌트 동적 제공

    기능 설명
    UI 색상 시스템 정의 일관된 디자인을 유지하기 위해 UI 색상 시스템을 정의하여 관리합니다.
    공용 UI 컴포넌트 제공 코드 중복을 최소화하고 캐싱을 활용하여 성능을 최적화한 공용 UI 컴포넌트를 제공합니다.
    컴포넌트 로딩 최적화 필요한 컴포넌트만 로드하여 번들 크기를 줄이고, 애플리케이션 성능을 향상시킵니다.
    Vite 기반 정적 서빙 Vite를 사용하여 빌드 후 정적 파일로 서빙하여 프론트엔드 애플리케이션을 독립적으로 배포합니다.
    원격 컴포넌트 로드 런타임에 원격 컴포넌트를 로드하여 패키징 없이 컴포넌트를 공유할 수 있습니다.
  2. Storybook을 활용한 컴포넌트 문서화

    기능 설명
    멀티 프레임워크 지원 각 프레임워크별로 빌드한 후, refs를 활용해 외부 스토리북과 연결합니다.
    컴포넌트 예시 및 변형 제공 각 컴포넌트의 사용 예시와 다양한 props 변형 사례를 제공합니다.
    자동화된 문서 생성 컴포넌트 정보를 바탕으로 자동으로 문서를 생성하여 관리합니다.
    실시간 UI 테스트 개발 중 실시간으로 UI를 테스트하여 즉각적인 피드백을 받을 수 있습니다.
    디자인 시스템 연계 디자인 시스템과 통합하여 일관된 UI/UX를 유지할 수 있도록 지원합니다.

📖 스토리북

@PickMe/Style-Guide/Storybook

🎨 색상 팔레트

palette

Primary #E27396
Secondary #B3DEE2
Tertiary #EAF2D7

📝 호스트 사용법

flowchart BT
    %% 스타일 및 컴포넌트 공유
    subgraph styleguide[@pickme/style-guide]
        subgraph react["/react-components"]
            styleguide/react/chakra-ui-system.jsx[chakra-ui-system.jsx]
            styleguide/react/components[Shared Components]
        end
        subgraph vue["/vue-components"]
            styleguide/vue/components[Shared Components]
        end
        subgraph styles["/styles"]
            styleguide/styles/global.ts[global.css]
        end
    end

    %% Microfrontend 루트 앱
    subgraph mfa-root[@pickme/mfa-root]
        mfa-root/microfrontend-layout.html[microfrontend-layout.html]
        mfa-root/index.ejs[index.ejs]
    end
    mfa-root/index.ejs -.-> styleguide/styles/global.ts

    %% Vue 앱
    subgraph report[@pickme/report]
        report/Components[Components]
    end
    report/Components -.-> styleguide/vue/components
    report:::delegate

    %% React 앱
    subgraph record[@pickme/record]
        record/ChakraProvider[ChakraProvider]
        record/Components[Components]
    end
    record/ChakraProvider -.-> styleguide/react/chakra-ui-system.jsx
    record/Components -.-> styleguide/react/components
    record:::delegate

    %% 대표 앱 표시
    classDef delegate stroke-width:3px;
Loading

EJS

<!DOCTYPE html>
<html lang="ko">
    <head>
        <meta charset="UTF-8" />
        <title>Host</title>
        <meta
            http-equiv="Content-Security-Policy"
            content="style-src 'unsafe-inline' https: localhost:*;"
        />
        <meta name="importmap-type" use-injector />

        <% if (isLocal) { %>
        <script type="injector-importmap">
            {
                "imports": {
                    "@styleguide": "//localhost:9001/pickme-style-guide.js"
                }
            }
        </script>
        <% } %>

        <script src="https://cdn.jsdelivr.net/npm/import-map-overrides@4.1.0/dist/import-map-overrides.js"></script>
    </head>
    <body>
        <script>
            window.importMapInjector.initPromise.then(() => {
                import("@styleguide").then((module) => module.get("./global"));
            });
        </script>
    </body>
</html>

Vite

// vite.config.js
import { defineConfig } from "vite";
import federation from "@originjs/vite-plugin-federation";

export default defineConfig({
    plugins: [
        federation({
            name: "host-app",
            remotes: {
                "@styleguide": "http://localhost:9001/pickme-style-guide.js",
            },
            shared: ["react", "react-dom", "@chakra-ui/react"],
        }),
    ],
});
  • 스타일시트
// index.js
import("@styleguide/global");
  • 컴포넌트
// page.js
import { Button, Item } from "@styleguide/react";

📂 폴더 구조

열기
PickMe-Style-Guide
├─ .github
│  └─ workflows # 깃헙 액션 워크플로어 프로세스
│     ├─ deploy-aws-s3.yml # AWS S3로 페이지로 배포
│     ├─ deploy-gh-pages.yml # 깃헙 페이지로 배포
│     └─ vite-build.yml # Vite로 빌드
├─ .env # 환경변수
├─ .prettierrc # 포맷터 설정
├─ .storybook # 스토리북 설정
│  └─ main.ts # 애드온 설정 및 외부 스토리북 연결
├─ stories # 루트 스토리북
│  └─ Welcome.mdx # 소개 스토리
├─ src
│  ├─ main.js # index.html 대신 빈 진입점
│  ├─ styles # 공용 스타일
│  │  ├─ global.css
│  │  └─ global.js
│  ├─ react-components # React용 컴포넌트
│  │  ├─ .storybook # 스토리북 설정
│  │  │  ├─ main.ts
│  │  │  └─ preview.tsx # chakra-ui 프로바이더 설정
│  │  ├─ index.js # 컴포넌트 제공 아웃풋
│  │  ├─ Button.jsx # (*.jsx/tsx) 컴포넌트
│  │  ├─ Button.stories.tsx # (*.stories.tsx) 스토리
│  │  ├─ chakra-ui-system.jsx
│  │  ├─ Container.stories.tsx
│  │  ├─ Container.tsx
│  │  ├─ Drawer.stories.tsx
│  │  ├─ Drawer.tsx
│  │  ├─ IconButton.jsx
│  │  ├─ IconButton.stories.tsx
│  │  ├─ Item.stories.tsx
│  │  ├─ Item.tsx
│  │  ├─ List.stories.tsx
│  │  ├─ List.tsx
│  │  ├─ PaginateController.stories.tsx
│  │  └─ PaginateController.tsx
│  ├─ shared # 서드파티 컴포넌트
│  │  └─ chakra-ui
│  │     ├─ close-button.tsx
│  │     └─ drawer.tsx
│  └─ vue-components # Vue용 컴포넌트
│     ├─ .storybook # 스토리북 설정
│     │  ├─ main.ts
│     │  └─ preview.ts
│     ├─ index.js # 컴포넌트 제공 아웃풋
│     ├─ bleed.stories.ts
│     └─ bleed.vue
├─ README.md
├─ tsconfig.json # 타입스크립트 설정
├─ types.d.ts # Module Federation 리모트 타입 정의
└─ vite.config.js # Module Federation 플러그인 사용

🚀 실행 방법

Storybook 실행

$ npm install
# 환경변수 PUBLIC_URL= (배포 url)
$ npm run storybook

로컬 개발 서버 실행

$ npm run storybook:vue
$ npm run storybook:react
# 환경변수 PUBLIC_URL= (빈값처리)
$ npm run storybook

Module Federation 리모트 실행

$ npm install
$ npm run dev