[리팩토링] 일관성있는 버튼 컴포넌트로 탈바꿈하기

D uuu·2024년 4월 26일
0

project

목록 보기
10/10

기존 코드의 문제점

디자이너, 기획자 없이 혼자서 프로젝트를 구상했기 때문에 미처 고려하지 못한 부분이 많았고 이런것들이 개발을 진행할수록 불편함이 커지기 시작했다.
그 중 하나가 버튼 컴포넌트인데, 공통 버튼 컴포넌트를 만들어놓고 디자인을 props 로 받아서 처리하다 보니 애플리케이션 전반에 사용된 버튼이 서로 다른 모양을 가지게 되었다.

그러다보니 버튼 컴포넌트는 점점 많은 props 를 받게 되었고, 공통 컴포넌트를 사용하는 의미가 무색해지는 상황이 발생했다..!


⭐️기존 버튼 컴포넌트의 문제점

  • 일관된 크기나 모양에 대한 기준이 없다.
    👉프로젝트 전체적으로 일관성이 떨어지고, 사용자 경험에도 좋지 못한 문제가 있었다.
  • 모든 스타일을 props 로 받아서 처리한다.
    👉버튼을 사용할 때 매번 많은 props를 설정해야하는 번거로움을 초래했다.
예시)  width, height, background, color .... 등 모든 스타일을 props 로 넣어주는 방식으로 구현

<CommonButton width="100px" height="40px" background="#3498db" color="#fff">확인</CommonButton>

<다양한 모습의 버튼들.jpg>

버튼(1)버튼(2)버튼(3)버튼(4)

리팩토링 하기

우선 버튼을 체계적으로 관리하기 위해 다음과 같은 기준을 설정했다.

  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>
profile
배우고 느낀 걸 기록하는 공간

0개의 댓글

관련 채용 정보