배워서 남 주자

[styled-components] 공통 UI 컴포넌트 및 theme 기능

미래에서 온 개발자 2023. 4. 6. 17:28

프로젝트를 진행하면서 공통 UI 컴포넌트를 제작해서 사용했고, 그 중 대표적인 UI 컴포넌트가 버튼이었다. 먼저 프로젝트 진행 과정 중 버튼 컴포넌트의 변천사를 간단하게 정리한 다음, 프로젝트가 끝난 후 새로 알게 된 스타일 컴포넌트의 theming 기능을 적용해 보는 과정까지 기록하고자 한다. 

 

 

1. styled-components로만 만든 버튼

프론트 팀원 중에서 한 분이 공통 ui 컴포넌트 제작을 맡아주셨다. 처음 만든 공통 ui 버튼 컴포넌트는 활성화/비활성화 느낌으로 두 종류의 다른 색상의 버튼을 컴포넌트명을 달리 해서 사용하는 방식이었다. 

 

 

이후 다음의 두 가지 이유에서 해당 컴포넌트의 리팩토링 필요성을 느꼈다.

  • 기본 파란색 버튼과 회색 버튼이 아닌 다른 색상의 버튼이 필요해졌다. (카카오톡 로그인, 네이버 로그인 버튼 등 기업 theme 색상의 버튼) 이때마다 S_ButtonYellow, S_ButtonGreen 등을 계속 만들어나가는 방식은 비효율적이라고 생각했다.
  • onClick 등 버튼의 기본 동작까지 제어할 수 있는 컴포넌트면 더 범용적으로 사용할 수 있다는 생각이 들었다. 

 

 

2. addStyle이라는 props를 받아서 다양한 색상 및 너비를 가질 수 있는 버튼

위의 두 가지 사항을 충족할 수 있는 버튼 컴포넌트로 리팩토링을 했다. 기존 버튼 컴포넌트가 단순 스타일 컴포넌트였다면 리팩토링한 버튼 컴포넌트는 스타일 속성을 addStyle이라는 props로 받아서 색상과 너비 등을 컴포넌트 선언부가 아닌 사용부에서 부여할 수 있는 리액트 컴포넌트로 만들었다. 

 

 

컴포넌트 사용부에서 버튼 컴포넌트를 다음과 같이 호출해서 사용한다. 

<S_Button addStyle={{ width: '48%' }} onClick={handleJoinRequest}>
	가입신청
</S_Button>
<S_Button
	addStyle={{
		width: '48%',
		backgroundColor: 'var(--gray100)',
		color: 'var(--gray400)',
		hoverBgColor: 'var(--gray200)'
	}}
	onClick={alertPreparingService}
>
	문의하기
</S_Button>

버튼 이미지 캡처 화면

 

 

3. styled-components에서 제공하는 theming 기능 사용하기

스타일 컴포넌트에서 자체적으로 제공하는 <ThemeProvider> wrapper 컴포넌트를 사용하면 addStyle 같은 props를 내려보내지 않고도 하나의 컴포넌트로 다양한 색상과 너비의 컴포넌트를 만들 수 있다. 

JSX를 리턴하는 리액트 컴포넌트로 공통 ui 버튼 컴포넌트를 만들면 button 요소의 기본 속성을 지정하고자 하는 경우 공통 컴포넌트 안에 일일이 그 자리를 만들어줘야 한다. (예: type='button', type='submit' 등) 하지만 ThemeProvider를 사용하면 원하는 스타일 속성은 커스터마이징이 가능하면서 동시에 버튼 요소의 모든 속성을 자유롭게 쓸 수 있다.

 

다만, defaultProps에서 theme에 두 가지 이상의 속성이 있는 경우에는 한 가지 속성만 theme props으로 내려보내면 작동하지 않기 때문에 defaultProps에서 일부 속성만 커스터마이징한 컴포넌트를 사용하고 싶은 경우에도 일일이 전체 theme 속성을 지정해줘야 한다. 

 

* 아래의 stackblitz 에서 직접 코드를 확인해 볼 수 있다. 

 

styled-components theming - StackBlitz

A create-react-app project based on react and react-dom.

stackblitz.com

 

📚 참고자료

 

styled-components: Advanced Usage

Theming, refs, Security, Existing CSS, Tagged Template Literals, Server-Side Rendering and Style Objects

styled-components.com