이러한 요청을 편하게 해결하기 위해 등장한 개발 방법이 바로 Component Driven Development (CDD) 다. 이러한 방법을 사용한다면 레고처럼 조립해 나갈 수 있는 부품 단위로 UI 컴포넌트를 만들어 나가는 개발을 진행할 수 있다.
실제 CDD방법을 활용하여 UI를 구축하는 사이트의 예시
이러한 문제점들을 해결하기 위해 CSS 전처리기(CSS Preprocessor) 라는 개념이 등장했다.
CSS 전처리기(CSS Preprocessor)란 CSS가 구조적으로 작성될 수 있게 도움을 주는 도구로 우리가 흔히 CSS 문서를 작성할 때는 많은 반복적인 작업을 요구하고 Color 값을 찾는 일, tag를 닫는 일 등 번거로운 작업 역시 포함이 되어있다.
그뿐만 아니라 클래스의 상속과 같은 사항으로 점점 CSS 문서는 양이 많아져 유지관리에 많은 영향을 끼치게 되었다. 이런 CSS의 문제점들을 프로그래밍 개념(변수, 함수, 상속 등)을 활용하여 해결할 수 있다.
하지만 이 CSS 전처리기(CSS Preprocessor) 자체만으로는 웹 서버가 인지하지 못하기 때문에 각 CSS 전처리기에 맞는 Compiler를 사용해야 하고 컴파일을 하게 되면 실제로 우리가 사용하는 CSS 문서로 변환이 된다.
이를 통해 CSS 파일들을 잘 구조화할 수 있게 되었고, 최소한 CSS 파일을 몇 개의 작은 파일로 분리할 수 있는 방법이 생기게 됐다.
CSS 전처리기 중에서 가장 유명한 SASS
는 Syntactically Awesome Style Sheets의 약자로 CSS를 확장해 주는 스크립팅 언어이다.
하지만 얼마 지나지 않아서 SASS가 ‘CSS의 구조화’를 해결해 주는 것의 장점
보다 다른 문제들을 더 많이 만들어낸다는 것이 밝혀졌다.
결국 우리는 전처리기(preprocessor)가 내부에서 어떤 작업을 하는지는 알지 못한 채, 스타일이 겹치는 문제를 해결하기 위해 단순히 계층 구조를 만들어 내는 것에 의지하게 되었고, 그 결과 컴파일된 CSS의 용량은 어마어마하게 커지게 되었습니다.
이러한 CSS 전처리기의 문제를 보완하기 위해 BEM, OOCSS, SMACSS 같은 CSS 방법
론이 대두되었고, 각각의 장단점이 있으나 결국 세 방법론 모두 같은 지향점을 가지고 있다.
이런 CSS 방법론들은 같이 일하는 팀 동료들의 팀워크와도 연결되기 때문에 여러 팀원이 함께 작업하는 상황에서 CSS 작성에 있어서 방법들을 규칙으로 정해두는 것은 매우 중요한 요소라고 할 수 있다.
대표적인 CSS 방법론으로는 BEM이 있다. BEM이란 Block, Element, Modifier로 구분하여 클래스명을 작성하는 방법이며, Block, Element, Modifier 각각은 —와 __로 구분한다.
클래스명은 BEM 방식의 이름을 여러 번 반복하여 재사용할 수 있도록 하며 HTML/CSS/SASS 파일에서도 더 일관된 코딩 구조를 만들어 준다.하지만 이러한 방법론들에서도 문제점이 발생하기 시작합니다. 클래스명 선택자가 장황해지고, 이런 긴 클래스명 때문에 마크업이 불필요하게 커지며, 재사용하려고 할 때마다 모든 UI 컴포넌트를 명시적으로 확장해야만 했다.
또한 SASS와 BEM도 고치지 못했던 몇 가지 문제들은 언어 로직 상에 진정한 캡슐화(encapsulation : 객체의 속성과 행위를 하나로 묶고 실제 구현 내용 일부를 외부에 감추어 은닉하는 개념)의 개념이 없다는 것이었고, 이로 인해 개발자들이 유일한 클래스명을 선택하는 것에 의존할 수밖에 없다.
애플리케이션으로 개발 방향이 진화하면서 컴포넌트 단위의 개발은 캡슐화의 중요성을 불러왔고, 결국 CSS도 컴포넌트 영역으로 불러들이기 위해 CSS-in-JS를 사용해여 이 문제를 해결할 수 있었다.
Styled-Component는 기능적(Functional) 혹은 상태를 가진 컴포넌트들로부터 UI를 완전히 분리해 사용할 수 있는 아주 단순한 패턴을 제공한다.
CSS 코드를 다룰 때 다음과 같은 불편함 느낀적이 있다.
이 외에도 여러가지 어려움이 있을 수 있는데, 이런 불편함을 CSS를 컴포넌트화 시킴으로써 해결해주는 라이브러리가 바로 React 환경에서
사용 가능한 Styled Components
다.
Styled Components는 앞서 배운 CSS in JS 라는 개념이 대두되면서 나온 라이브러리이다. 기존에 HTML, CSS, JS 파일로 쪼개서 개발하던 방법에서, React 등의 라이브러리의 등장으로 컴포넌트 단위 개발이 주류가 되었지만, CSS는 그렇지 못했다는 점에서 출발한 개념이죠.
CSS in JS 라이브러리를 사용하면 CSS도 쉽게 Javascript 안에 넣어줄 수 있으므로, HTML + JS + CSS까지 묶어서 하나의 JS파일 안에서 컴포넌트 단위로 개발할 수 있게 된다. 이런 CSS in JS 라이브러리 중에서 현재 가장 인기 있는 라이브러리가 바로 Styled Components
입니다.
# with npm
$ npm install --save styled-components
# with yarn
$ yarn add styled-components
{
"resolutions": {
"styled-components": "^5"
}
}
import styled from "styled-components"
Styled Components로 컴포넌트를 만드는 방법은 다음과 같다.
Templete Literals
문법을 사용하기 때문에 따옴표가 아닌 백틱을 사용한다.컴포넌트를 선언한 후 styled.태그종류를 할당하고, 백틱 안에 기존에 CSS를 작성하던 문법과 똑같이 스타일 속성을 작성해주면 된다. 이렇게 만든 컴포넌트를 React 컴포넌트를 사용하듯 리턴문 안에 작성해주면 스타일이 적용된 컴포넌트가 렌더되는 것을 확인할 수 있습니다.
Styled Component로 만든 컴포넌트도 React 컴포넌트처럼 props를 내려줄 수 있다. 내려준 props 값에 따라서 컴포넌트를 렌더링하는 것도 가능하다.
Styled Components는 템플릿 리터럴 문법( ${ }
)을 사용하여 JavaScript 코드를 사용할 수 있고, props를 받아오려면 props를 인자로 받는 함수를 만들어 사용하면 된다.
위 코드의 경우는 삼항연산자
를 활용해 <Button>
컴포넌트에 skyblue 라는 props가 있는지 확인하고, 있으면 배경색으로 skyblue를, 없을 경우 white를 지정해주는 코드이다. 이 코드에 따라 렌더링된 <Button>
컴포넌트는 아래 그림과 같다.
props의 값을 통째로 활용해서 컴포넌트 렌더링에 활용할 수도 있다.
똑같이 삼항연산자를 사용하고 있지만, 이번에는 props.color 가 없다면 white
를, props.color 가 있다면 props.color의 값
을 그대로 가져와서 스타일 속성 값으로 리턴해주고 있는 것을 볼 수 있다. 그 결과, color 라는 이름으로 받은 props의 값으로 배경색이 지정된 것을 확인할 수 있다.
스타일을 컴포넌트로 만들 수 있다는 것은 좋지만, 전역에 스타일을 설정하고 싶을 땐 Styled Components에서 createGlobalStyle 함수
를 사용한다.
import { createGlobalStyle } from "styled-components";
const GlobalStyle = createGlobalStyle`
button {
padding : 5px;
margin : 2px;
border-radius : 5px;
}
3 이렇게 만들어진 <GlobalStyle>
컴포넌트를 최상위 컴포넌트에서 사용해주면 전역에 <GlobalStyle>
컴포넌트의 스타일이 적용됩니다.
function App() {
return (
<>
<GlobalStyle />
<Button>전역 스타일 적용하기</Button>
</>
);
}