Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(design-systems-for-developers): 디자인 시스템 구축하기 #7

Merged
merged 21 commits into from
Nov 15, 2022

Conversation

minzzang144
Copy link
Owner

Design Systmes For Developers

팀에게 비주얼 리뷰를 요청해보자.

@vercel
Copy link

vercel bot commented Nov 14, 2022

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Updated
storybook-get-started ✅ Ready (Inspect) Visit Preview Nov 15, 2022 at 6:26AM (UTC)

Copy link
Owner Author

@minzzang144 minzzang144 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

디자인 시스템 구축하기

지속적 통합(CI)과 비주얼 리뷰를 통한 협업

비주얼 리뷰는 UI의 기능과 미학을 확인하는 과정으로 UI 개발 및 QA 진행 시 모두 필요합니다.

대부분의 개발자들은 코드 퀄리티를 향상하기 위해 다른 개발자들로부터 피드백을 주고받는 과정인 코드 리뷰에 익숙합니다. UI 컴포넌트는 코드를 시각적으로 표현하기 때문에 UI/UX와 관련한 피드백을 주고받을 때 비주얼 리뷰는 필수적입니다.

node_modules 삭제하기. 패키지 재설치하기. 로컬 저장소 비우기. 쿠키 삭제하기. 만약 이러한 행동들에 대해 어디서 들어본 듯 하다면, 여러분들은 팀메이트들이 최신 코드를 사용하도록 만든다는 게 얼마나 고된 일인지 알고 있을 것입니다. 팀원들의 개발 환경이 완전히 동일하지 않은 이상 실제 버그와 로컬 개발 환경에서만 발생하는 이슈를 구분하기는 너무나 어렵습니다.

다행히도 프런트엔드 개발자로서, 우리는 '브라우저'라는 공통적인 컴파일 목표를 갖고 있습니다. 능숙한 팀들은 비주얼 리뷰를 위한 공통적인 참조 사항으로 스토리북(Storybook)을 온라인으로 발행하기도 합니다. 이는 로컬 개발 환경이 내재한 문제점들을 피해가게 해줍니다. (기술 지원팀 일은 쉽지 않은 게 사실입니다).

클라우드 내에서 작업 리뷰하기

UI 컴포넌트가 URL을 통해 접근 가능해지면 관계자들은 UI가 어떻게 보이고 느껴질지 본인의 브라우저라는 익숙한 환경에서 확인할 수 있습니다. 다시 말해 개발자, 디자이너, PM이 로컬 개발 환경에서의 문제점과 씨름할 일이 없고, 스크린샷을 돌려 볼 필요가 없으며, 예전 UI를 참고할 필요도 없어진다는 얘기입니다.

스토리북 퍼블리싱하기

스토리북 관리자들이 만든 무료 퍼블리싱 서비스인 크로마틱(Chromatic) 을 통해 비주얼 리뷰의 예를 살펴보겠습니다. 이는 여러분이 클라우드에 스토리북을 안전하게 그리고 안정적으로 배포하고 호스트 할 수 있게 해줄 뿐만 아니라, 스토리북을 정적 사이트로 만들고 다른 호스팅 서비스에 배포하기 도 상당히 수월하게 해줍니다.

  1. 첫 단계는 chromatic.com 에 가셔서 깃허브 계정으로 로그인 하는 것입니다.
  2. 크로마틱에서 디자인 시스템 저장소를 선택합니다. 이 작업은 뒷단에서 접근 권한을 동기화하고 PR 체크 기능을 설치해줍니다.
  3. npm을 통해 크로마틱 패키지를 설치합니다. yarn add --dev chromatic
  4. 설치되었으면 아래 커맨드를 실행해 스토리북을 빌드(build)하고 배포합니다. (크로마틱 웹사이트에서 제공되는 project-token을 사용해야 합니다) npx chromatic --project-token=<project-token>
  5. 위 링크를 복사한 후 새로운 브라우저 창에 붙여넣어 발행된 스토리북을 살펴봅니다. 로컬 스토리북 개발환경이 온라인에서 그대로 구현된 것을 볼 수 있습니다. 이는 여러분의 팀이 실제로 렌더링 된 UI 컴포넌트들을 리뷰하는 과정을 원활하게 합니다. 마치 로컬 개발환경에서 리뷰하듯이 말입니다. 아래는 여러분이 크로마틱에서 보게 될 결과입니다.

지속적 통합

지속적 통합(CI)은 현대 웹 앱을 관리하기 위한 실질적인 수단입니다. 이는 여러분이 코드를 push할 때 테스트, 분석, 배포와 같은 행동을 제어할 수 있게 합니다. 우리는 단순 반복 노동으로부터 우리 자신을 구제하기 위해 이러한 방법을 사용할 것입니다.

우리는 어느 정도 까지는 무료인 GitHub Actions를 사용할 것입니다. 이러한 원리는 다른 CI 서비스들에도 적용됩니다.

디렉토리의 최상위에 .github 디렉토리를 추가합니다. 그리고 나서 workflows 라는 다른 디렉토리를 만듭니다.

아래처럼 chromatic.yml 이라는 파일을 생성합니다. 이는 우리의 CI 프로세스가 작동되도록 지시하게 만들어 줍니다. 지금은 작은 것부터 시작하고, 점차 발전시켜 나갈 것입니다.

# Name of our action
name: 'Chromatic'
# The event that will trigger the action
on: push

# What the action will do
jobs:
  test:
    # The operating system it will run on
    runs-on: ubuntu-latest
    # The list of steps that the action will go through
    steps:
      - uses: actions/checkout@v1
      - run: yarn
        #👇 Adds Chromatic as a step in the workflow
      - uses: chromaui/action@v1
        # Options required for Chromatic's GitHub Action
        with:
          #👇 Chromatic projectToken, see https://storybook.js.org/tutorials/design-systems-for-developers/react/ko/review/ to obtain it
          projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN }}
          token: ${{ secrets.GITHUB_TOKEN }}

문서화를 통하여 디자인 시스템 도입을 촉진하기

전문적인 프런트엔드 은 디자인 시스템이 얼마나 채택되었는지를 성공의 척도로 삼고 있습니다. 디자인 시스템 사용을 통한 개발 비용 절감이라는 이점을 완벽하게 누리기 위해서는 컴포넌트가 널리 사용되어야만 합니다. 그렇지 않으면 이게 다 무슨 소용이겠습니까?

문서화는 힘든 작업입니다.

UI를 공동으로 개발하는 작업환경에서 문서화가 매우 ​​중요하다는 것은 명백한 사실입니다. 문서는 팀이 공통 UI 컴포넌트를 언제 어떻게 사용해야 하는지 배울 때 도움이 됩니다. 그런데 문서화에는 왜 그렇게 큰 노력이 필요할까요?

이전에 문서를 만들어본 경험이 있다면, 사이트 구조나 테크니컬 라이터(writer)와의 논쟁 같은 문서화가 아닌 작업에 시간을 많이 소모한 적이 있을 것입니다. 그리고 문서를 배포했다 하더라도 신기능을 개발하면서 문서 유지보수까지 병행하기란 정말 지치는 일이었을 것입니다.

대부분의 문서는 생성되는 즉시 구식이 되어 버립니다. 구식이 된 문서는 디자인 시스템의 컴포넌트에 대한 신뢰를 약화시키기 때문에, 개발자가 존재하는 컴포넌트를 재사용하는 대신 새 컴포넌트를 만들어 사용해 버리는 상황을 초래합니다.

요구 사항

우리의 문서화 작업은 기존에 문서를 만들고 유지하는 데에 동반되었던 어려움을 타파할 수 있는 새로운 방식이어야만 합니다. 우리가 달성해야 할 가치는 다음과 같습니다.

🔄최신 상태 유지를 위한 최신 프로덕션 코드 사용
✍️글쓰기를 용이하게 하기 위한 마크다운과 같은 친숙한 쓰기 도구를 사용
⚡️유지보수 시간 단축을 통해 팀이 글쓰기에만 집중 가능한 환경 조성
📐상용구 기능을 제공하여 개발자가 공통 패턴을 재작성 하는 것을 방지
🎨맞춤형 기능을 제공하여 유난히 복잡한 유즈 케이스 및 컴포넌트를 위한 유용성 제공
스토리북(Storybook)을 사용하게 되면 다양한 컴포넌트 종류를 이미 문서화된 스토리(story)로 접할 수 있기 때문에 시작이 수월한 편입니다. 스토리는 컴포넌트가 주어지는 다양한 입력(props)에 따라 어떻게 작동할지 보여주기 때문입니다. 스토리는 프로덕션 컴포넌트를 사용하기 때문에 작성하기 쉽고 자체 업데이트도 가능합니다. 또한 스토리는 이전 테스트 장에서 언급되었던 도구를 사용하여 회귀 테스트를 할 수도 있습니다.

스토리 작성, 문서 생성

스토리북 Docs 애드온(addon)을 사용하면 기존 스토리에서 기본 설정을 가져와서 유지 관리 시간을 절감할 수 있는 풍부한 문서 자료를 생성할 수 있습니다. 빌드챕터(Controls 및 Actions)에서 다룬 애드온들과 마찬가지로 Docs 애드온도 각 스토리북 설치에 포함하고 설정될 수 있으므로 좋은 문서를 작성하는 데에만 집중할 수 있습니다.

스토리 북을 열 때마다 두 개의 탭이 표시됩니다. -

🖼️ "Canvas" 탭은 컴포넌트 개발 환경입니다.
📝 "Docs" 탭은 컴포넌트 문서를 보여줍니다.

문서 확장

컴포넌트의 기능을 설명하는 메타 데이터를 추가하는 것으로 시작하세요.

  • componentSubtitle
    export default 내에서 parameters.componentSubtitle 을 추가하여 컴포넌트 제목을 문서화 할 수 있습니다.
  • JSDoc
    JSDoc을 첨가하여 컴포넌트 설명을 문서화 할 수 있습니다.
  • propTypes 주석 추가 | Typescript 인터페이스 주석 추가
Avatar.propTypes = {
  /**
    Use the loading state to indicate that the data Avatar needs is still loading.
    */
  loading: PropTypes.bool,
  /**
    Avatar falls back to the user's initial when no image is provided.
    Supply a `username` and omit `src` to see what this looks like.
    */
  username: PropTypes.string,
  /**
    The URL of the Avatar's image.
    */
  src: PropTypes.string,
  /**
    Avatar comes in four sizes. In most cases, you'll be fine with `medium`.
    */
  size: PropTypes.oneOf(Object.keys(sizes)),
};

인터페이스 역시 마찬가지로 동일하게 작동한다.

  • parameters.docs
    스토리에 대한 설명을 문서화합니다.

Markdown/MDX를 사용한 Supercharge 문서화

Markdown은 텍스트 작성을 위한 직관적인 서식입니다. MDX를 사용하면 Markdown 내에서 대화형 코드(JSX)를 사용할 수 있습니다. 스토리북 Docs는 MDX를 사용하여 개발자가 문서 렌더링 방식을 완벽하게 제어할 수 있도록 합니다.

새로운 src/Avatar.stories.mdx 파일을 만들고 세부 정보를 제공합니다. Avatar.stories.js 파일을 제거하고 mdx 파일에 스토리를 다시 생성합니다.

import { Canvas, Meta, Story } from "@storybook/addon-docs";

import { Avatar } from "./Avatar";

<Meta
  title="Design System/Avatar"
  component={Avatar}
  argTypes={{
    loading: {
      control: "boolean",
      description:
        "Use the loading state to indicate that the data Avatar needs is still loading.",
      table: {
        type: { summary: "boolean" },
        defaultValue: { summary: false },
      },
    },
    username: {
      description:
        "Avatar falls back to the user’s initial when no image is provided. Supply a `username` and omit `src` to see what this looks like.",
      table: {
        defaultValue: {
          summary: "loading",
        },
      },
    },
    src: {
      description: "The URL of the Avatar's image.",
      table: {
        defaultValue: {
          summary: null,
        },
      },
    },
    size: {
      description:
        "Avatar comes in four sizes. In most cases, you’ll be fine with `medium`.",
      table: {
        defaultValue: {
          summary: "medium",
        },
      },
    },
  }}
/>

# Avatar

## 사용자 또는 조직을 나타내는 이미지를 표시합니다.

특정 사용자에게 액션이나 콘텐츠를 제공하기 위해 Avatar를 사용합니다. 

Avatar를 사용할 때는 사용자 이름이 _항상_ Avatar의 옆이나 툴팁에 보입니다.

export const Template = (args) => <Avatar {...args} />;

<Story
  name="standard"
  args={{
    size: "large",
    username: "Tom Coleman",
    src: "https://avatars2.githubusercontent.com/u/132554",
  }}
>
  {Template.bind({})}
</Story>

### Sizes

4 가지 크기가 지원됩니다.

<Story name="sizes">
  <div>
    <Avatar
      size="large"
      username="Tom Coleman"
      src="https://avatars2.githubusercontent.com/u/132554"
    />
    <Avatar
      size="medium"
      username="Tom Coleman"
      src="https://avatars2.githubusercontent.com/u/132554"
    />
    <Avatar
      size="small"
      username="Tom Coleman"
      src="https://avatars2.githubusercontent.com/u/132554"
    />
    <Avatar
      size="tiny"
      username="Tom Coleman"
      src="https://avatars2.githubusercontent.com/u/132554"
    />
  </div>
</Story>

### 기본값

`src` prop에 이미지가 제공되지 않으면 Avatar는 이니셜을 표시합니다.

Avatar가 이미지에 접근할 수 없는 상황은 지양해야 합니다.

<Story name="initials">
  <div>
    <Avatar username="Tom Coleman" />
    <Avatar username="Dominic Nguyen" />
    <Avatar username="Kyle Suss" />
    <Avatar username="Michael Shilman" />
  </div>
</Story>

### Loading

로딩 상태는 이미지 또는 사용자 이름이 로드 중일 때 사용됩니다.

<Story name="loading">
  <div>
    <Avatar size="large" loading />
    <Avatar size="medium" loading />
    <Avatar size="small" loading />
    <Avatar size="tiny" loading />
  </div>
</Story>

### Playground

Canvas 탭에서 Controls 애드온으로 이 스토리를 실험해보세요.

<Canvas>
  <Story
    name="controls"
    args={{
      loading: false,
      size: "tiny",
      username: "Dominic Nguyen",
      src: "https://avatars2.githubusercontent.com/u/263385",
    }}
  >
    {Template.bind({})}
  </Story>
</Canvas>

스토리북은 대화식 미리 보기, 인자 테이블 등과 같은 미리 만들어진 컴포넌트인 “Doc Blocks” 와 함께 제공됩니다. 기본적으로 자동 생성된 문서 페이지에 적용되어 있습니다. 그뿐만 아니라 개별 사용을 위해 추출할 수도 있습니다. 우리의 목표는 모든 것을 직접 다시 작업하지 않고 맞춤형 Avatar의 문서를 생성하는 것이므로, 가능한 곳에서는 Doc Blocks를 재사용하도록 합시다.

ArgsTable과 doc block을 추가하고 초기 스토리를 Preview로 래핑(wrapping) 하겠습니다.

import { ArgsTable, Canvas, Meta, Story } from "@storybook/addon-docs";

# 이전과 동일한 내용

<Canvas>
  <Story
    name="standard"
    args={{
      size: "large",
      username: "Tom Coleman",
      src: "https://avatars2.githubusercontent.com/u/132554",
    }}
  >
    {Template.bind({})}
  </Story>
</Canvas>

<ArgsTable story="standard" />

모든 디자인 시스템에는 표지가 함께 제공됩니다. 스토리북 Docs에서는 MDX를 사용하여 개별 페이지를 만들 수 있습니다.

import { Meta } from "@storybook/addon-docs";

<Meta title="Design System/Introduction" />

# 스토리북 디자인 시스템을 배우는 방법 소개

스토리북 디자인 시스템을 배우는 방법은 전체 [스토리북 디자인 시스템](https://github.com/storybookjs/design-system/)의 일부입니다., 우수사례 기술을 사용하여 디자인 시스템을 작성하고 게시하는 방법을 배우는 데 관심이 있는 사람들을 위한 학습 리소스로 만들어졌습니다.

[스토리북 배우기](https://learnstorybook.com)에서 자세히 알아보기.

@minzzang144
Copy link
Owner Author

스토리북 CI & CD 배포 중 babel-loader 패키지 버전이 모노레포에서 모두 동일하게 적용되지 않는 문제점을 확인했다.
npm ls babel-loader // -> 이 명령어를 사용하여 모노레포 전체 구성에서 babel-loader의 패키지 버전을 각각 확인할 수 있다

해결 방법은 모든 패키지에서 babel-loader의 버전을 일치시키는 것이다. 하지만 github-action에서는 패키지 버전을 일치시키기 위해 수동으로 수정하는 것을 하지 말기를 권장했다. 따라서 해당 링크를 참고하여 resolutions 속성을 추가하여 해결할 수 있었다.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant