원문: All You Need To Know About CSS-in-JS
요약: 컴포넌트로 생각하기— 더이상 스타일시트의 묶음을 유지보수 할 필요가 없습니다. CSS-in-JS는 CSS 모델을 문서 레벨이 아니라 컴포넌트 레벨로 추상화합니다(모듈성).
스타일을 적용한 리액트 컴포넌트 예제
CSS-in-JS, Styled Components, Radium, Aphrodite와 같은 용어를 들어본 적이 있을겁니다. 당신은 "이런 게 왜 있지? 나는 CSS-in-CSS(.css파일에 작성한 CSS)에 완벽하게 만족하는데!"라며 이러지도 저러지도 못했을겁니다.
저는 이런 게 왜 있는지를 밝히기 위해 왔습니다. 최소한 개념과 존재 이유를 이해하기를 바랍니다. 그렇지만 CSS-in-JS를 사용할 의무는 없습니다. CSS-in-CSS을 편하게 사용해도 됩니다. 당신에게 가장 잘 맞고, 행복하게 해주는 것이 어떤 것이든지 그것이 최상의 해결책을 줄겁니다. 항상이요!
CSS-in-JS는 복잡하고 논란이 많은 주제입니다. 만약 당신이 생각하기에 괜찮은 것 같다면 열린 마음을 갖고 저울질해봐야한다고 생각합니다. 스스로에게 물어보세요. "이게 내 작업 흐름을 개선하는데 도움이 될까?" 결국, 중요한 것은 그것 뿐입니다. 당신을 더 행복하고 더 생산적으로 만들어 주는 도구를 사용하세요!
저는 항상 엄청 큰 스타일시트 폴더를 유지해야하는 것이 어색했습니다. 다른 방식을 시도하고 싶었죠. 새로운 스타일링 아이디어가 있는지 물어보는 여러 사람을 봤습니다. CSS-in-JS는 지금까지 최고의 컨셉입니다.
CSS-in-JS를 한 번 해봅시다.
CSS-in-JS가 무엇인가요?
JSS는 CSS보다 더 강력한 추상화입니다. JavaScript를 사용하여 스타일을 선언적이고, 유지보수 가능한 방식으로 설명합니다. JS를 CSS로 전환하는 고성능 컴파일러로, 런타임 및 서버 사이드에서 작동합니다. 이 코어 라이브러리는 낮은 레벨이며, 프레임워크에 구애받지 않습니다. 약 6KB(gzip압축과 minify함)이며 플러그인 API를 통해 확장 가능합니다.—출처
인라인 스타일과 CSS-in-JS는 같지 않다는 걸 기억하세요! 서로 다릅니다. 빠르게 데모를 볼 시간입니다!
인라인 스타일이 동작하는 방법
const textStyles = {
color: white,
backgroundColor: black
}
<p style={textStyles}>inline style!</p>
브라우저에서 DOM 노드를 다음과 같이 연결합니다:
<p style="color: white; backgrond-color: black;">inline style!</p>
CSS-in-JS이 동작하는 방법
import styled from 'styled-components';
const Text = styled.div`
color: white,
background: black
`
<Text>Hello CSS-in-JS</Text>
브라우저에서 DOM 노드를 다음과 같이 연결합니다:
<style>
.hash136s21 {
background-color: black;
color: white;
}
</style>
<p class="hash136s21">Hello CSS-in-JS</p>
차이점
약간의 차이점이 보이시나요? CSS-in-JS는 DOM의 상단에 <style>
태그를 추가했고, 인라인 스타일은 DOM 노드에 속성으로 추가했습니다.
왜 이문제가 중요할까요?
모든 CSS 기능을 JavaScript 이벤트 핸들러로 지정할 수 있는 것은 아닙니다. 많은 슈도 선택자(:disabled
, :before
, :nth-child
)도 불가능하고, html
, body
태그 등도 지원하지 않습니다.
CSS in JS를 사용하면, 손쉽게 모든 CSS의 힘을 그대로 누릴 수 있습니다. 실제 CSS가 생성되기 때문에, 당신이 생각할 수 있는 모든 미디어 쿼리, 슈도 선택자를 사용할 수 있습니다. 몇 라이브러리는( jss
나 styled-components
같은) 중첩 같은 CSS의 기본 기능이 아닌 것을 지원하기도 합니다!
그 둘이 어떻게 다른지에 대한 깊이있는 멋진 기사도 있습니다.
"CSS는 CSS에 작성하고 끝내세요."
그렇습니다. 아주 오랜 시간동안 그렇게 해왔습니다. 문제는 현대 웹은 페이지가아니라 컴포넌트로 작성되었다는 것입니다.
CSS는 컴포넌트 기반의 방식을 위해 만들어진 적이 한번도 없었습니다. CSS-in-JS는 이 문제를 정확하게 해결합니다. Vue로 이 문제를 아름답게 해결해보겠다고 외쳐도, Vue의 스타일은 컴포넌트의 상태(state)에 접근할 수 없습니다.
긴장을 풀어주는 돌을 그리는 밥 로스입니다.😄
CSS-in-JS를 사용하면 무슨 장점이 있나요?
- 컴포넌트로 생각하기— 더이상 스타일시트의 묶음을 유지보수 할 필요가 없습니다. CSS-in-JS는 CSS 모델을 문서 레벨이 아니라 컴포넌트 레벨로 추상화합니다(모듈성).
- CSS-in-JS는 JavaScript 환경을 최대한 활용하여 CSS를 향상시킵니다.
- "진정한 분리 법칙"—스코프가 있는 선택자로는 충분하지 않습니다. CSS에는 명시적으로 정의 하지 않은 경우, 부모 요소에서 자동으로 상속되는 속성이 있습니다. jss-isolate 플러그인 덕분에 JSS 규칙은 부모 요소의 속성을 상속하지 않습니다.
- 스코프가 있는 선택자—CSS는 하나의 전역 네임스페이스만 있습니다. 복잡한 애플리케이션 내에서 선택자 충돌을 피할 수 없습니다. BEM과 같은 네이밍 컨벤션은 한 프로젝트 내에서는 도움이 되지만, 서드파티 코드를 통합할 때는 도움이 되지 않습니다. JSS는 JSON으로 표현된 것을 CSS로 컴파일 할 때, 기본적으로 고유한 이름을 생성합니다.
- 벤더 프리픽스—생성된 CSS 규칙은 자동적으로 벤더 프리픽스가 붙어있으므로 생각할 필요가 없습니다.
- 코드 공유—JavaScript와 CSS사이에 상수와 함수를 쉽게 공유할 수 있습니다.
- 현재 화면에 사용중인 스타일만 DOM에 있습니다(react-jss).
- 죽은 코드 제거
- CSS 유닛 테스트!
CSS-in-JS를 사용하면 무슨 단점이 있나요?
- 학습 곡선(Learning curve)
- 새로운 의존성
- 신규 팀원이 코드베이스에 적응하기 어렵게 만듭니다. 프론트엔드를 처음 접하는 사람들은 "더" 많은 것을 배워야합니다.
- 현상 유지를 위한 도전 (꼭 단점은 아니다.)
장점이 단점을 크게 앞지릅니다— CSS-in-JS를 시도해봅시다! 잃을 것이 없습니다!
가장 인기있는 CSS-in-JS 라이브러리
널리 사용되는 CSS-in-JS 라이브러리에 대한 빠른 hello wolrd 예제를 제공합니다. 문법을 기반으로 가장 좋아하는 CSS를 선택하면 됩니다.
Styled Components
import React, { Component } from 'react';
import styled from 'styled-components';
const Title = styled.h1`
color: white;
`;
const Wrapper = styled.div`
background: black
`
class App extends Component {
render() {
return (
<Wrapper>
<Title>Hello World!</Title>
</Wrapper>
);
}
}
export default App;
JSS-React
import React from 'react'
import injectSheet from 'react-jss'
const styles = {
wrapper: {
background: 'black'
},
title: {
color: 'white'
}
}
const App = ({classes}) => (
<div className={classes.wrapper}>
<h1 className={classes.title}>
Hello JSS-React!
</h1>
</div>
)
export default injectSheet(styles)(App)
glamorous
import React from 'react'
import glamorous from 'glamorous'
const Wrapper = glamorous.div({
backgroundColor: 'black'
})
const Title = glamorous.h1({
color: 'white'
})
const App = () => (
<Wrapper>
<Title> Hello JSS-React!</Title>
</Wrapper>
)
export default App;
Radium (경고: 인라인 스타일을 사용함)
import React, { Component } from 'react';
import Radium from 'radium';
@Radium // decorator
class App extends Component {
render() {
const styles = {
wrapper: {
background: 'blue',
}
title: {
color: 'white'
}
};
return (
<div style={styles.wrapper}>
<h1 style={styles.title}>Hello Radium!</h1>
</div>
);
}
}
export default Radium(App);
참고: Radium은 데코레이터를 사용합니다!
Aphrodite
import React, { Component } from 'react';
import { StyleSheet, css } from 'aphrodite';
const styles = StyleSheet.create({
wrapper: {
backgroundColor: 'red'
},
title: {
backgroundColor: 'blue'
}
});
class App extends Component {
render() {
return (
<div className={css(styles.wrapper)}>
<h1 className={css(styles.title)}>Hello Aphrodite!<h1>
</div>;
)
}
}
Stylotron
import React, { Component } from 'react';
import { styled } from 'styletron-react';
const Wrapper = styled('div', {
backgroundColor: 'black'
})
const Title = styled('h1', {
color: 'white'
})
class App extends Component {
render() {
return (
<Wrapper>
<Title>Hello Styletron!<Titleh1>
</Wrapper>;
)
}
}
이것들은 핵심 기능을 보여주는 아주 간단한 예제입니다. 모든 라이브러리에는 훨씬 더 많은 기능이 포함되어있습니다. 예를 들면 테마, 동적 프로퍼티, 서버 사이드 렌더링 외에도 여러가지죠!
CSS-in-JS가 제공하는 모든 기능에 대해 깊이 있게 살펴보는 끝내주는 포스팅도 있습니다.
전체 리스트는 다음과 같습니다. 모든 라이브러리에대한 간략한 정보를 볼 수 있습니다.
싫든 좋든. CSS-in-JS는 사용해 볼 만한 자격이 있습니다!
CSS-in-JS가 당신에게 아닌 것 같다구요? 또 다른 옵션으로 CSS Modules가 있습니다.
읽어주셔서 감사합니다!