코드로 만드는 Design System

김유경
김유경
Sep 26 · 14 min read

들어가기 전

  • 저희는 글로벌 학술 논문 검색 웹 서비스(Scinapse)를 만들고 있어서 언어는 영어이고, PC 사용자가 주를 이루고 있습니다.
  • 팀에 Product Designer는 두 명, Client(Front End) Developer도 두 명이 있습니다.
  • 클라이언트 개발은 React + Typescript를 이용합니다.

어떤 상황이었는데?

디자이너 그리고 개발자 모두 버튼 및 다른 컴포넌트들의 시스템화를 위해 노력하지 않았던 것은 아닙니다. 디자인 팀은 2년 전쯤부터 버튼 및 폼, 리스트 등 공통으로 많이 사용되는 컴포넌트들을 스케치 심볼로 만들어서 관리했습니다. 하지만 라이브러리 및 파일 동기화가 어렵게 느껴지면서 점점 각자 디자인을 하게 되었고, 완전히 동일하지는 않지만, 암묵적으로 비슷한 스타일의 버튼들을 각자 디자인하기 시작합니다.

상황 파악을 위해 모아본 서비스 내 다양한 버튼들

어떻게 해결할까?

이번 개선 프로젝트에서는 프론트팀과 디자인팀의 버튼 컴포넌트에 대한 이해를 동기화시키고 추후 관리가 잘 될 수 있도록 하는 것이 필수라 생각했고 이를 위한 해결 방안을 팀원들과 논의해 보았습니다. 해결책은 디자인 팀이 주도해서 컴포넌트를 설계하고 유지 관리하는 방식이었습니다.

구현 시작!

버튼 대통합에 실패하지 않는 컴포넌트를 만들기 위해 중심적으로 생각했던 요소들은 다음과 같습니다.

  1. 버튼의 스타일을 조작 할 수 있는 variation에 제한을 두어 같은 목소리를 낼 수 있어야 한다.
  2. 적용의 방식이 기존에 버튼을 만드는 방식과 크게 다르지 않게 구현하여 migration과 실제 사용이 쉬워야 한다.

01. 버튼 스타일 구현하기

처음에 버튼을 설계하기 위해 현재 사용되고 있는 버튼들을 참고하여 상태와 스타일을 어떤 식으로 정규화/추상화시킬 것인지 고민해 보았습니다. 주로 사용하고 있던 버튼들의 모습을 잘 살펴보고 뭉쳐보니 버튼의 스타일은 크게 3가지 카테고리의 조합으로 표현할 수 있었습니다.

위 : 사이즈에 따라 달라지는 버튼/ 아래 : 각 버튼에 대한 Padding 가시화
variant 값에 따라 달라지는 버튼 스타일
동일한 outlined 버튼에서 color에 따라 달라지는 버튼의 모습

코드로 구현하기

구현을 하기위해서 각 카테고리에 해당하는 요소를 props 로 지정하여 ClassName에 넣고, CSS 클래스 선택자를 이용해 스타일을 조정했습니다.

받은 props들을 className으로 조합하는 코드
button 태그에 위에서 만든 className을 넣어주는 코드

02. 아이콘 버튼 만들기

하지만 위 props들(size, variant, color)의 조합만으로는 아이콘의 위치와 유무 여부는 넘겨줄 수 없었습니다. 이 또한 props로 넘겨줄 수도 있지만 넘겨줄 props가 너무 많아지고 기존에 버튼을 만들던 모습과 많이 다른 형태로 컴포넌트를 사용해야 했습니다. 저는 이 이슈를 해결하기 위해 props를 새로 받지 않고 props.children 매서드를 사용하여 아이콘 버튼을 구현했습니다.

버튼 컴포넌트를 실제로 사용하여 Leading Icon Button을 만드는 예시
아이콘 버튼 Variation

03. 버튼 상태 표현하기

Google material design guide의 버튼 상태
  • hover : 마우스를 버튼위에 올려놓은 상태
  • pressed : 버튼을 탭하여 누른 상태
  • disabled : 클릭(동작)이 불가능한 상태
  • loading : 통신시의 로딩 상태
contained blue 버튼의 상태 값들

이제 loading 상태만 해결하면 됩니다..!

loading상태를 만들 때는 약간의 이슈가 있었습니다. 버튼이 text의 길이에 따라서 자동으로 변하게 하기위해서 버튼 container의 패딩값으로 버튼의 총 너비가 결정되었는데 loading상태를 위해 버튼 내부의 요소들(아이콘과 Text)를 스피너로 갈아끼우면 버튼의 총 width가 스피너 크기에 맞춰 줄어들 수 밖에 없었습니다.

로딩시에 내부 요소들(아이콘, 텍스트)을 스피너로 바꿔 넣었을 때 발생하는 문제
문제가 해결된 로딩 버튼

04. 버튼 기능 통합하기

저는 <button/> 태그 만을 고려하여 버튼을 제작하였지만, 현재 사용되고 있는 버튼들은 용도에 따라 <a/> 와 <link/> 태그들도 사용하고 있었습니다. 해당 케이스들도 지금까지 만들었던 버튼에 통합하기 위한 작업이 필요했고, 해당 작업은 클라이언트 팀의 도움을 받아 진행했습니다.

실제 제품에 반영 해보자

이제 실제 프로덕트에 적용해 나가면서, 놓친부분은 없는지 테스트 해보아야합니다. 저희는 적용의 첫걸음으로 프로덕트에서 글로벌하게 쓰이면서 고대의 유물처럼 남아있던 가입 모달의 버튼들을 교체해보았습니다. 실제로 이용되던 버튼을 교체해보니 동작이나 스타일 등에서 어색한 점들이 발견되어 사소한 수정과정들을 거쳤습니다. 아래는 교체된 버튼들의 before(좌)/after(우) 모습입니다.

교체된 Header의 버튼
교체된 가입 모달 버튼

데모 페이지

위 컴포넌트들을 쉽게 보고 원하는 형태의 버튼의 코드를 바로 복사할 수 있는 데모 페이지도 간단하게 만들어 보았습니다. 옵션을 선택하면 해당 옵션의 조합으로 나오는 버튼이 보여지고, 아래에는 그 버튼에 대해 작성해야하는 코드가 만들어집니다.

데모 페이지 : https://scinapse.io/ui-demo

버튼 데모 페이지 캡쳐본

다음은 뭘 해볼까?

버튼 컴포넌트 하나를 정규화 하는데에도 아주 많은 고려요소가 있었던 것 같습니다. 하지만 이렇게 정교하게 설계해 두었으니 서비스를 구현하는데 걸리는 시간과 디자인-클라이언트간 QA 핑퐁 작업이 많은 부분 줄어들것입니다. 그리고 그 변화는 벌써 느껴지기 시작했습니다.

팀 프론트엔드 개발자의 긍정적 피드백

도움 받은 자료들

    김유경

    Written by

    김유경

    안녕 날 소개하지 직업은 Designer 전공은 Electrical Engineering 취미는 Drink

    Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
    Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
    Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade