본문 바로가기

Issues/frontend

(디자인 시스템) Storybook 과 TailwindCSS 디자인 시스템 구축

 

최근 개발팀의 인원이 증가하고, 버전 관리가 복잡해짐에 따라 프론트엔드 개발에서 공통적인 요소를 사전에 정의하고 활용하는 필요성이 더욱 커졌습니다.

 

현재 프론트엔드 개발자는 총 5명, 백엔드 개발자는 3명으로 구성되어 있으며, 여러 버전을 동시에 개발해야 하는 상황에서 효율적인 협업과 일관성 유지가 중요한 과제로 대두되었습니다. 이러한 필요성을 해결하기 위해 디자인팀과의 협의를 통해 디자인 시스템을 도입하기로 결정했습니다.

 

처음에는 디자인 시스템에 디자인 토큰 개념까지 적용해 프로젝트에 사용하고자 했으나, 초기 도입 시점에서는 예상보다 큰 실익을 얻지 못한다고 판단했습니다. 대신 TailwindCSS를 기반으로 한 Storybook을 설정하여 가장 작은 단위의 요소를 공통으로 정의하고, 점진적으로 디자인 시스템의 범위를 확장해 나가기로 했습니다. 이를 통해 빠르게 일관된 UI를 구축하면서도 디자이너와 개발자 간의 협업 효율성을 극대화할 수 있게 되었습니다.

 

1. 기본 디자인 컴포넌트 설정

 

디자인팀과 개발팀은 Figma를 통해 제공된 기본 컴포넌트들을 기반으로 디자인 시스템을 정의했습니다. 빠르고 효율적인 시스템 구축과 프로젝트 적용을 목표로 하여, 최소한의 단위로 컴포넌트를 설정했으며, 초기 정의된 컴포넌트 목록은 다음과 같습니다:

 

Header, Base, Dot, Scale, Tab, Button, Input, InputDropdown, DatePicker, ToothNumber

 

이 컴포넌트들은 Storybook을 통해 다양한 상태와 변형(variants)을 체계적으로 관리하고, 팀 내에서 쉽게 공유할 수 있도록 하였습니다. Storybook은 각 컴포넌트를 독립적으로 테스트하고, 여러 스토리를 통해 다양한 상태와 스타일을 시각적으로 확인할 수 있는 환경을 제공합니다. 이를 통해 개발자들은 일관성 있는 디자인을 유지하면서도 재사용 가능한 컴포넌트를 효율적으로 관리하고 프로젝트에 적용할 수 있습니다.

 

이 접근 방식은 컴포넌트의 상태 변화와 변형을 시각적으로 확인하고, 개발과 디자인 간의 커뮤니케이션을 개선하여, 궁극적으로 일관성 있는 사용자 경험을 제공하는 데 기여합니다.

 

2. 컴포넌트 디자인 요소 추출

2.1 Button 컴포넌트 정의

 

Button 컴포넌트는 대부분의 UI에서 중요한 역할을 담당하기 때문에, 이를 디자인 시스템의 첫 번째 구성 요소로 정의하였습니다.

디자인팀에서 정해준 Button 컴포넌트의 variant는 "primary"와 "secondary" 두 가지입니다.

 

Button 컴포넌트에서 추출한 주요 props는 다음과 같습니다.

 

(1) 버튼 크기 및 폰트 크기

designSize prop을 사용하여 버튼의 크기와 폰트 크기를 조절합니다. 버튼의 너비와 높이는 designSize에 따라 달라지며, 다양한 화면 크기에서도 일관된 버튼 스타일을 유지할 수 있도록 설계하였습니다. 지원하는 크기는 xssmmdlgxl2xl 입니다.

 

(2) 버튼 라벨

label prop을 사용하여 버튼의 텍스트를 정의합니다. 이는 버튼의 주요 내용을 전달하는 역할을 합니다.

 

(3) 위험 표시

danger prop은 boolean 값을 가지며, 버튼이 위험한 작업을 수행할 수 있음을 사용자에게 시각적으로 알리는 역할을 합니다. 예를 들어, 삭제와 같은 위험한 작업의 경우 danger를 true로 설정하여 버튼 스타일을 경고 색상으로 변경할 수 있습니다.

 

(4) 아이콘 정보

아이콘은 버튼에 시각적 요소를 추가하여 더 나은 사용자 경험을 제공합니다. iconInfo prop은 "src"와 "alt" 속성을 포함하여 아이콘의 경로와 대체 텍스트를 정의합니다.

 

(5) 아이콘 위치 설정

아이콘의 유무 및 위치는 사용자 경험에서 중요한 요소 중 하나입니다. 이를 위해 icon prop을 추가하여 아래와 같이 세 가지 경우를 지원합니다.

 

** 아이콘 없음: 기본 버튼 스타일.

** 아이콘 앞에 위치(leading): 버튼 텍스트 앞에 아이콘이 위치하는 경우.

** 아이콘 뒤에 위치(trailing): 버튼 텍스트 뒤에 아이콘이 위치하는 경우.

 

(6) 버튼 활성화 상태

버튼의 활성화/비활성화를 제어하기 위해 disabled prop을 추가하였습니다. 사용자가 특정 작업을 수행하지 못하도록 하기 위해 disabled 상태를 명확히 표시하며, 이로 인해 사용자는 버튼을 사용할 수 없는 경우를 직관적으로 알 수 있습니다.

 

 

Storybook을 통한 버튼 스토리 정의

Storybook을 사용하여 Button 컴포넌트의 다양한 변형을 정의하고, 이를 통해 팀원들이 개발 중에도 각 상태를 쉽게 테스트할 수 있도록 하였습니다. 스토리북은 해당 컴포넌트 안에 다양한 **다양한 스토리 변형(variants)**을 설정할 수 있다. 각각의 스토리는 컴포넌트의 다른 상태나 스타일을 보여주는데 사용한다.

 

export const Primary: Story = {
  args: {
    primary: true,
    label: "Button",
  },
};

export const Secondary: Story = {
  args: {
    label: "Button",
  },
};

 

 

라벨이나 danger 등은 DesignButton에서 상속을 받아 실제 서비스 컴포넌트에서 구현할 수 있다.

 

 

2.2 Input 컴포넌트 정의

Input 컴포넌트는 사용자가 데이터를 입력할 수 있는 폼 요소입니다. 주요 props는 다음과 같습니다:

  1. 입력 타입
    • type prop을 통해 텍스트, 숫자, 비밀번호 등 다양한 입력 타입을 설정할 수 있습니다.
  2. placeholder
    • placeholder prop을 사용하여 입력 필드에 가이드 텍스트를 표시할 수 있습니다.
  3. 값 제어
    • valueonChange props를 통해 입력값을 제어할 수 있으며, 이를 통해 폼 데이터와의 동기화를 유지합니다.

2.3 InputCheckbox 컴포넌트 정의

InputCheckbox 컴포넌트는 사용자가 하나 이상의 옵션을 선택할 수 있는 체크박스 요소입니다. 주요 props는 다음과 같습니다:

  1. 체크 여부
    • checked prop을 사용하여 체크박스의 현재 상태를 제어합니다.
  2. 값 제어
    • onChange prop을 통해 사용자가 체크박스를 클릭할 때 실행될 콜백 함수를 설정합니다.
  3. 라벨
    • label prop을 통해 체크박스 옆에 표시될 텍스트를 정의합니다.

2.4 InputDropdown 컴포넌트 정의

InputDropdown 컴포넌트는 사용자가 선택하거나 직접 입력할 수 있는 폼 요소입니다. 주요 props는 다음과 같습니다:

  1. 옵션 목록
    • options prop을 통해 선택 가능한 옵션들을 정의합니다.
  2. 선택된 값
    • selectedValue prop을 통해 현재 선택된 값을 나타내고, 사용자 상호작용에 따라 업데이트됩니다.
  3. 값 변경 핸들러
    • onChange prop을 사용하여 선택된 값이 변경될 때 실행될 콜백 함수를 정의합니다.

2.5 InputPassword 컴포넌트 정의

InputPassword 컴포넌트는 비밀번호 입력을 위해 사용됩니다. 주요 props는 다음과 같습니다:

  1. 값 제어
    • valueonChange props를 통해 입력값을 제어하며, 이를 통해 폼 데이터와의 동기화를 유지합니다.
  2. placeholder
    • placeholder prop을 사용하여 비밀번호 입력 필드에 가이드 텍스트를 표시할 수 있습니다.
  3. 비밀번호 표시 토글
    • showPasswordToggle prop을 사용하여 사용자가 입력한 비밀번호를 가시적으로 확인할 수 있는 기능을 추가할 수 있습니다.

2.6 InputRadio 컴포넌트 정의

InputRadio 컴포넌트는 사용자가 여러 옵션 중 하나를 선택할 수 있는 라디오 버튼 요소입니다. 주요 props는 다음과 같습니다:

  1. 선택된 값
    • selected prop을 사용하여 현재 선택된 옵션을 제어합니다.
  2. 값 변경 핸들러
    • onChange prop을 통해 사용자가 라디오 버튼을 클릭할 때 실행될 콜백 함수를 설정합니다.
  3. 라벨
    • label prop을 통해 라디오 버튼 옆에 표시될 텍스트를 정의합니다.

 

3. 디자인 시스템 구축을 통한 성과

디자인 시스템 도입 초기에는 공통 컴포넌트와 관련된 일관성을 유지하는 것이 주요 목표였습니다. 특히 Storybook을 활용하여 개발 중 발생할 수 있는 다양한 UI 문제를 사전에 발견하고, TailwindCSS로 빠르게 스타일을 일관되게 적용함으로써 개발 속도를 크게 향상시킬 수 있었습니다.

디자이너와 개발자가 동일한 언어를 사용하며 협업할 수 있는 환경을 조성하여, 디자인 시안과 실제 결과물 간의 괴리를 줄였으며, 이를 통해 프로젝트의 품질을 높이는 결과를 얻었습니다. 점진적으로 컴포넌트의 범위를 확장하면서 보다 복잡한 UI 컴포넌트들도 재사용 가능한 방식으로 관리하고, 일관된 사용자 경험을 제공할 수 있게 되었습니다.