스타일의 범위 국한시키기
React에서 CSS를 활용하여 스타일을 적용시키고 동적으로 할당하기도 했었다.
기본적인 React의 CSS 적용 방식은 import "./CSSFileName.css";
와 같이 사용한다.
해당 방식에는 한 페이지에서 여러 component들의 CSS 파일을 공유하여 모든 스타일들이 전역으로 사용하게 된다.
이는 DOM 어딘가에 명명한 class와 같은 이름을 가진 class가 존재한다면 해당 스타일이 그 대상에게까지 영향을 미친다는 것을 의미한다.
이는 기본적으로 스타일의 범위가 정해져 있지 않기 때문이다.
물론, CSS를 명명할 때 조금 신경만 쓴다면 꼭 문제가 되지는 않는다.
그것들은 결국 일반적인 CSS고 어떤 이름이라도 사용할 수 있기 때문이다.
그리고 선택하는 여러 요소들은 단지 스타일을 적용하고 싶은 component의 위치에서만 사용될 것이기 때문에 크게 문제되지 않는다.
하지만 대규모 프로젝트로 넘어가면 말이 달라진다.
잠재적으로 수많은 개발자들이 같은 공간에서 작업을 하는 경우, 같은 이름이 여러번 사용될 수도 있다.
그럴 경우 style이 다른 component에도 영향을 미칠 수 있다는 것을 의미한다.
물론 어떠한 개발자든 이런 상황을 피하고 싶을 것이다.
여기에 가장 일반적으로 피할 수 있는 방법 2가지를 소개한다.
Styled components package
styled components라고 검색하면 공식 웹페이지를 찾을 수 있을 것이다.
해당 페이지에서 styled components에 관한 모든 것을 배울 수 있을 것인데, 실제로 사용하고 싶다면 document를 깊게 살펴볼 필요가 있다.
styled components는 특정 style이 첨부된 component를 구축할 수 있도록 도와주는 package로 이 style이 첨부된 component에서만 영향을 미치며 다른 component에는 전혀 영향을 미치지 않는다.
간단하게 설명하자면, 사용을 하기 위해서는 다음 명령어로 package를 설치해야한다.
npm install --save styled-components
설치가 완료되었다면 독립적인 스타일로 만들고자 하는 component로 가서 아래와 같은 방식으로 코딩하면 된다.
import styled from 'styled-components'
const Button = styled.a`
/* This renders the buttons above... Edit me! */
display: inline-block;
border-radius: 3px;
padding: 0.5rem 0;
margin: 0.5rem 1rem;
width: 11rem;
background: transparent;
color: white;
border: 2px solid white;
&:hover{
color: red ;
}
/* The GitHub button is a primary button
* edit this to target it specifically! */
${props => props.primary && css`
background: white;
color: black;
`}
` ;
해당 예제는 홈페이지에 나와있는 예제로 styled-components는 HTML 내장 요소들을 전부 구현하고 있어서 모든 HTML tag들을 component 형태로 제작할 수 있다.
제작을 하는 과정에서 해당 component의 스타일을 위와 같은 방식으로 선언한다고 볼 수 있는데 중괄호{}가 없는 것은 그 component 자체의 스타일을, 자기 자신과 관련한 스타일은 &을 사용하여 지정할 수 있다.
또한 props을 활용하여 state나 값을 넘겨줄 수도 있다.
기존의 문제에 대한 해결점을 제시하는 좋은 package인 것은 맞으나 좋다는 것은 개인적인 취향이고 코딩하는 것은 선호도에 따라 다른 것이니 이번에는 다른 해결책을 제시해보겠다.
CSS module
사람에 따라서 CSS는 파일 형태로 분리하는 것을 좋아할 수도 있다.
이 방안은 기존의 방식을 고수하면서 사용할 수 있는 방안이다.
CSS 모듈은 브라우저에서 코드가 실행되기 전에 코드의 변환이 필요하기 때문에 해당 기능을 지원하도록 설정된 브라우저에서만 사용이 가능하다.
다행히도 Create React App으로 생성된 React project는 이미 CSS 모듈을 지원하도록 설정되있다.
Create React App의 공식 문서에서 CSS 모듈을 사용할 수 있는 방법을 배울 수 있다.
그 사용법은 아주 간단하다. 기존에 CSS를 import하는 방식에서 변화가 있다.
CSS 파일을 불러올 때의 명칭은 무엇이든 상관없지만 classes나 styles와 같이 의미하는 바가 명확한 이름으로 CSS 파일을 불러오며, CSS 파일 이름의 수정이 요구된다.
이름 중간에 .module을 추가하는데 이것은 기본적으로 CSS 모듈이 작동하도록 코드를 변환하라고 compiler process에게 보내는 신호다.
import React from 'react';
import styles from './Button.module.css';
const Button = props => {
return (
<button type={props.type} className={styles.button} onClick={props.onClick}>
{props.children}
</button>
);
};
export default Button;
사용을 위와 같이 하며, 바뀐 것이 있다면 className="button"
이 위와 같이 바꼈다는 것이다.
styles는 CSS에서 불러온 객체로, 그 객체 안에 property로 정의되는 모든 클래스를 가진다.
따라서 CSS파일에서 button 클래스를 추가했다면 CSS 모듈에서는 button property를 가지게 된 것이다.
이렇게 특별한 방법으로 적용하면 이전과 동일하게 잘 작동하는 것을 볼 수 있다.
chorme의 개발자 도구를 활용해 적용된 클래스 이름을 보면 이상한 클래스를 볼 수 있다.
해당 구조는 "component이름_class이름__고유한 해시값"으로 구성된다.
이런 방식으로 component마다 고유한 클래스 이름을 가지게 바뀌는 것이다.
이런 식으로 완전히 새로운 클래스 이름을 만들어낸다. 이 방법은 스타일을 유지하지만 건드리지 않고 새로운 이름으로 맵핑한다.
CSS 모듈의 개념은 CSS 파일에서 설정한 CSS 스타일의 범위가 파일에 불러오는(import하는) component로 한정[국한]한다.
아래는 이전 시간에 다뤘던 동적인 스타일링을 변환한 코드다.
// Normal CSS
<div className={`form-control ${!isValid && "invalid"}`}>
// CSS module
<div className={`${styles['form-control']} ${!isValid && styles.invalid}`}>
CSS module에서는 객체 property 형태로 받아오기 때문에 hyphen(-)과 같은 클래스는 위의 방법으로 진행해야한다.
큰 변화가 있다면 기존 문자열로 할당해주던 과정을 객체 형태로 넘겨준다는 것이다.
어떤 방식을 선호하냐에 따라 구현 방법은 크게 달라질 것이다.
필자는 개인적으로 스타일이 파일 형태로 나뉜 CSS module을 더 선호하며, 활용도가 높다고 느꼈다.
Spring JSP 형태로 코딩하다가 React로 넘어오니 너무나 많은 것들이 지원되기에 놀랐다.
개발자의 수고를 덜어주는 이런 기능들은 언제나 환영이다.