Theme in React JS

최근 인터넷에서 남자와 여자의 색상 구별법에 대해 읽은 적이 있었다. 여성이 남성보다 색깔의 더 세분화하여 인지한다는 내용이었다.

나는 웹 개발자로 16년간 일하고 있다.

최근 10여 년간은 프런트엔드 분야에서 일하고 있다. 프런트엔드는 백엔드개발자와 디자이너 사이에서 일하게 되는 경우가 많다.

그러다 보니 자연스럽게 남자와 여자 간의 색상 민감도 차이를 백엔드 개발자에게서 느끼고 있다. 그렇다고 백엔드 개발자를 비난하고자 하는 의도는 아니다.

다만 프론트엔드 개발자가 고민하는 것에 대해 일종의 존중을 해주었으면 하는 생각이 들었다.

프론트엔드 개발자라면 색상에 대해 민감해질 수 밖에 없다. 사용자가 웹 애플리케이션 혹은 웹사이트(편의상 웹애플리케이션이라 하자)를 구별하는 핵심요소는 Layout(레이아웃), Color(색상), Font(글꼴)라 말할 수 있기 때문이다. 최근에는, HTML에서 다양한 애니메이션 효과를 가미하는 일이 어렵지 않아 져서 핵심요소로 애니메이션도 포함할 수 있지만 여기서는 접어 두기로 하겠다.

Color

그중에서도 Color(색상)는 가장 중요하다고 말할 수 있다. 색상에 따라 웹 애플리케이션의 성격이 결정되고 때로는 서비스의 성패가 결정될 수도 있다.

다음의 이미지에서 보듯이 브랜드가 나타내려 하는 핵심가치와 Identity를 색상에서 찾는 사례는 손쉽게 찾을 수 있다.

출처 : https://www.helpscout.net/blog/psychology-of-color/

이렇게 중요한 색상을 웹 애플리케이션에서 다루기 위해서는 CSS를 이용하는 것이 가장 효과적이다. 대부분의 웹 애플리케이션은 HTML 을 이용하여 개발하게 되는데. HTML 노드의 스타일을 다루는 데에 가장 좋은 방법은 CSS이고 상상하는 거의 모든 스타일을 표현할 수 있다. (안 되는 거 빼곤 다 된다.)

CSS, SASS

CSS는 매우 잘 만들어진 뷰시스템이다. 하지만 프론트엔드개발자, 백엔드개발자, 디자이너를 포함한 모든 IT 종사자들은 웬만한 근성 없이는 CSS를 완벽히 만들 수 없다는 사실을 잘 알고 있다.

CSS에서 변수나 함수를 사용할 수 없으므로 반복적인 타이핑의 수가 많아지고 수정을 해야 할 때 많은 변경을 해야 하기 때문이다.

출처 : https://orezytivarg.github.io/css-evolution-from-css-sass-bem-css-modules-to-styled-components/

우리 인류는 이런 어려움을 해결하는 방법을 고안해냈다. 바로 SASS, SCSS, LESS와 같은 전처리기들이다. 나의 경우엔 2013년 무렵 처음 이러한 기술에 대해 알게 되었고 열광했다. CSS를 만드는데 변수, 함수 더 나아가 반복문을 사용할 수 있다니. 그냥 가능하다는 사실만으로도 행복했다. 처음에는 LESS를 이용해보고 그다음엔 SCSS로 갈아타게 되었다. 나는 LESS나 SCSS를 2014년부터 현재까지 계속 사용하고 있고 앞으로도 사용할 것 같다. 아마도 극히 예외적인 상황을 제외하고는 CSS를 직접 사용하는 일은 없을 것 같다.

Styled Components

하지만 웹 애플리케이션 개발환경의 변화는 추억을 남겨둘 시간을 허락하지 않았다. 영원할 줄만 알았던 jQuery 통일시대는 갑작스러운 AngularJS의 출현과 그 뒤를 이어 탄생한 ReactJS로 인해 jQuery는 점점 쇠락의 길을 걷게 되었다. 나의 경우엔 ReactJS를 사용하기로 했다. VueJS나 AngularJS도 훌륭하지만 개발하는 동안의 만족감이나 트랜드를 보아 ReactJS를 사용하기로 결정하였다. (작년 이맘때 썼던 글에서도 한번 이야기했었다. https://medium.com/chequer/vanillajs-es6-reactjs-typescript-2de2e7a764a5)

ReactJS의 가장 매력적인 부분 중에 하나는 로직과 템플릿(뷰)를 통합 개발한다는 점이다. 과거에는 분리해서 개발하는 것이 미덕이었지만. 템플릿의 각 DOM 요소를 컴포넌트로 만들어 배치하는 방법으로 개발을 하다 보면 자연스럽게 생각이 바뀌게 된다. 아무튼, ReactJS로 컴포넌트를 개발하다 보면 컴포넌트 안에 해당 컴포넌트에 필요한 모든 요소를 담아두고 패킹하고 싶어진다. 또한, 실 서비스 배포 시 bundle에 사용되지 않는 요소를 제거하고 필요한 내용만 담는 (Tree Shaking) 작업을 위해서도 컴포넌트를 깔끔하게 패킹하는 일은 필요하다.

styled-components 사용예

Styled Components를 이용하여 컴포넌트를 만들면 render 함수 안에서 JSX 태그를 마치 HTML dom과 같이 작성할 수 있어 컴포넌트 스타일링작업이 편리하고 깔끔해져서 개발자의 만족감이 높아지게 된다.

게다가 https://www.styled-components.com/docs/advanced#theming 에서 확인할 수 있듯이 Theme을 이용할 수 있다.

theme.js
Styled Components Theme Provider

theme.js 파일을 만들고 ThemeProvider의 props으로 전달하면 styled 컴포넌트 선언부에서 props.theme.primary_color로 사용할 수 있게 된다.

Theme

서론에서 언급했듯이 프런트엔드 개발자의 가장 큰 고민 중에 하나는 웹 애플리케이션의 Theme를 어떻게 만들 것 인가이다. 그중에서도 Theme Color를 어떻게 선언하고 그것에 맞게 개발을 하는 것이 좋을까?

Styled Components에서 이미 Theme 사용법을 알려주고 있기 때문에 웹애플리케이션을 Styled Components만으로 만든다면 고민할 필요가 없다. 프론트엔드 개발자는 색상의 이름을 어떻게 결정할지 작명소에 다녀오는 것으로 필요한 일이 끝났다고 할 수 있다.

하지만 웹 애플리케이션을 개발하는데 모든 컴포넌트를 다 직접 만들 필요는 없다. 세상에는 개인의 만들 수 없을 만큼 훌륭한 UI Framework들이 너무도 많기 때문이다.

Bootstrap, Material-UI, Semantic UI, AntDesign 등의 UI Framework들을 이용하면 프런트엔드 개발자는 많은 시간을 절약할 수 있고 게다가 대부분은 직접 만든 것보다 품질이 우수하다.

나의 경우에 앞서 언급한 UI Framework들을 모두 경험해 보았고 현재는 AntDesign을 이용하고 있고 앞으로도 이용할 생각이다.

Ant Design을 선택한 이유

그렇다면 많은 UI Framework들중에서 Ant Design(줄여서 antd라고 하자)를 선택하게 되었을까?

  • ReactJS + Typescript로 개발되어 있다.
  • 제공되는 컴포넌트의 종류가 다양하고 기능이 다양해서 복잡한 웹 애플리케이션 개발이 가능하다.
  • Styled Components와 함께 사용하는데에 문제가 없다.
  • 문서화가 잘 되어 있다.
  • 벌써 Star수가 34,000개 이상이다.

Ant Design theme system

antd는 LESS를 기본 CSS 시스템으로 테마를 제공하고 있다. 아쉽게도 Styled Components를 사용하고 있지 않다. 범용적으로 사용되는 UI Framework가 Styled Components를 사용하기는 쉽지 않았을 것으로 예상된다.

antd-theme.less

테마 변수의 통합관리

Styled Components와 antd를 함께사용하면서 테마를 사용하려면 테마변수가 분리되어 있어서 너무도 불편하다. theme.js 파일의 “primary_color”와 antd-theme.less 파일의 “@primary-color”는 같은 색상인데 색상을 변경하기 위해 2번의 작업을 해주어야 하기 때문이다.

사실 겨우 2번의 작업 이면 되는일이다.

과거의 나라면 근성으로 매번 변경이 있을 때마다 2번씩 파일을 고치고 있을 것 같다. 하지만 현재의 나에겐 용납할 수 없는 일이다.

그럼 어떻게 1번의 변경으로 변수를 변경할 수 있게 할 수 있을까?

처음에는 less파일에 css-moduls에서 지원하는 :export를 이용하여 ThemeProvider에서 이용할 수 있는 변수를 만들어 사용하는 방법을 시도 했다가. 지저분한 몇가지의 상황을 겪게되어 다음의 방법을 결정 하게 되었다.

theme.js(ts로 나중에 변경) 파일이 변경 될 때마다 node를 이용하여 less파일을 만들어 LESS에서 변수를 변경 하도록 하는 방식이다.

generate-less-var.ts를 만들고 package.json scripts에 몇줄을 추가해 주었다.

이렇게 해두고 npm start해주면 시작할 때 한번 theme.js 파일을 theme-vars.less파일로 만들어주고 theme.js 파일은 fs.watchFile에 의해 감시되다가 변경이 되면 theme-vars.less파일로 만들어 주게 된다.

React Component에서는 Styled Component를 이용하면서 테마변수를 다음과 같이 사용 할 수 있게되고

antd에서는 theme-vars.less 파일에서 정의된 테마변수로 CSS가 빌드 되어 테마를 변경하게 된다.

마지막으로 Styled Components안에서 theme의 색상사용을 좀더 유연하게 하기 위해서 LESS나 SCSS에서 처럼 색상을 조절하는 방법에 대해 소개하고 글을 마감하려 한다.

“#000000” 이 테마에서 결정한 색상이라면 컴포넌트 안에서 색을 그대로 사용하지 않고 약간 밝게 또는 약간 어둡게 변경해서 사용하고 싶을 때가 있다. 이럴 때 color(https://www.npmjs.com/package/color)를 이용하면 좋다.

color 패키지를 기본으로 사용하면 다소 장황하게 되는데. color-util을 만들어서 래핑하여 사용하면 더욱 간결하게 이용할 수도 있다.

끝으로

이 글에서는 다루고 있지 않지만. CSS Custom Properties(https://developer.mozilla.org/en-US/docs/Web/CSS/--*)를 이용하는 방법으로 테마를 만드는 실험도 해 보았다. 하지만 IE에서 사용할 수 없는 문제와 antd 의 CSS를 모두 재작성해야 하는 문제로 포기하게 되었다. 하지만 멀지 않은 미래에는 가능할 것으로 생각된다. 하루빨리 환경이 변해서 좀 더 역동적이게 테마를 변경할 수 있게 되기를 바래본다.

다음글 : https://medium.com/chequer/themes-in-react-js-for-vietnam-friends-100ccb334bcb 맨 아래쪽을 보시면 CSS만으로 테마를 변경하는 데모를 보실 수 있습니다.