디자이너, 기획자 없이 혼자서 프로젝트를 구상했기 때문에 미처 고려하지 못한 부분이 많았고 이런것들이 개발을 진행할수록 불편함이 커지기 시작했다.
그 중 하나가 버튼 컴포넌트인데, 공통 버튼 컴포넌트를 만들어놓고 디자인을 props 로 받아서 처리하다 보니 애플리케이션 전반에 사용된 버튼이 서로 다른 모양을 가지게 되었다.
그러다보니 버튼 컴포넌트는 점점 많은 props 를 받게 되었고, 공통 컴포넌트를 사용하는 의미가 무색해지는 상황이 발생했다..!
⭐️기존 버튼 컴포넌트의 문제점
예시) width, height, background, color .... 등 모든 스타일을 props 로 넣어주는 방식으로 구현
<CommonButton width="100px" height="40px" background="#3498db" color="#fff">확인</CommonButton>
<다양한 모습의 버튼들.jpg>
버튼(1) | 버튼(2) | 버튼(3) | 버튼(4) |
---|---|---|---|
![]() | ![]() | ![]() | ![]() |
우선 버튼을 체계적으로 관리하기 위해 다음과 같은 기준을 설정했다.
색상
정하기 크기
분류하기역할
분류하기애플리케이션 전반에 사용되고 있는 코드를 모아보니 중복되는 코드들이 있었고, 그 코드를 기본 스타일로 지정했다.
그리고 애플리케이션 전반에 통일감을 주기 위해 테마 파일인 theme.tsx 에 기준 색상을 명시하고 버튼의 색상을 동일하게 적용했다.
애플리케이션에 사용되고 있는 버튼을 모아보니 둥근버튼, 네모버튼, 특정 버튼(카카오 로그인), 취소버튼으로 나눌 수 있었고,
3,4 번 기준에 따라 스타일을 지정해주기 위해 아래와 같이 Role, Size 타입을 만들었다.
그리고 각 role, size 에 맞게 스타일을 지정했다.
export type Role = 'round' | 'kakao' | 'cancel'
export type Size = 'sm' | 'lg';
export const buttonRoleStyle = css<{ role: Role }>`
${({ role }) => {
if (role === 'round') {
return css`
border-radius: 10px;
`;
}
if (role === 'cancel') {
return css`
background-color: whitesmoke;
color: grey;
border-radius: 10px;
&:hover {
background-color: whitesmoke;
color: black;
}
`;
}
}}
`;
export const buttonSizeStyle = css<{ size: Size }>`
${({ size }) => {
if (size === 'sm') {
return css`
height: 35px;
`;
}
공통 버튼 컴포넌트에 버튼이 가지는 기본적인 스타일을 미리 정의하고, buttonRoleStyle 와 buttonSizeStyle 을 추가해줬다.
그럼 사용할때 role, size 만 props 에 넣어주면 해당 스타일을 가지는 버튼이 만들어진다.
const StyledButton = styled.button<{ fullWidth?: boolean; role: Role; size: Size }>`
display: inline-flex;
align-items: center;
justify-content: center;
width: ${(props) => (props.fullWidth ? '100%' : 'auto')};
border: none;
background-color: ${(props) => props.theme.palette.iconic};
color: white;
cursor: pointer;
font-size: 17px;
white-space: nowrap;
user-select: none;
-webkit-font-smoothing: antialiased;
font-family: ${(props) => props.theme.fonts.pretend};
font-weight: 600;
transition:
color 0.1s ease-in-out,
background-color 0.1s ease-in-out;
&:disabled {
opacity: 0.26;
cursor: not-allowed;
}
&:hover {
background-color: ${(props) => props.theme.palette.combi};
}
${buttonRoleStyle};
${buttonSizeStyle}
`;
사용할때는 아래와 같이 size, role 만 입력해주면 원하는 버튼의 모양을 사용할 수 있고, 모든 버튼이 동일한 모양으로 생성되기 때문에 일관성있는 버튼을 구현할 수 있게 되었다.
<Button size="sm" role="round">확인</Button>
이전 코드에서는 버튼을 사용하는 곳에서 스타일을 props 로 일일이 넣어주는 방식이었다면, 지금은 모든 로직을 공통 버튼 뒤로 숨기고 size, role 설정만으로 버튼을 구현할 수 있게 되었다.
따라서 이전 코드 보다는 가독성과 사용성이 좋아졌고, 전반적으로 일관성있는 버튼 구현이 가능해졌다.
혹시 새로운 모양의 버튼이 필요하다면, 새로운 role 과 그에 맞는 스타일만 작성해주면 손쉽게 공통 버튼 컴포넌트로 다양한 버튼을 구현할 수 있다.
/* 수정 전 코드 */
<CommonButton width="100px" height="40px" background="#3498db" color="#fff">확인</CommonButton>
/* 수정 후 코드 */
<Button size="sm" role="round">확인</Button>