본문 바로가기
프론트엔드/CSS 심화

CSS-in-JS

by 학습하는 청년 2024. 4. 18.

최종 수정 : 2025-06-04

CSS-in-JS

자바스크립트 코드로 CSS를 작성하는 방식이다. Styled Components가 이에 해당한다.


■ 장점

  • 컴포넌트 기반 스타일링: 컴포넌트 단위로 나누어서 스타일링을 할 수 있어서 CSS 클래스 이름이 충돌하지 않는다.
  • 동적 스타일링: JavaScript 변수나 props를 사용해 조건부 스타일링이 쉽고, 런타임에 스타일을 동적으로 변경할 수 있다.
  • 스코프 격리: 자동으로 고유한 클래스명을 생성해 CSS 충돌을 방지하고, 전역 네임스페이스 오염을 막는다.
  • 타입 안정성: TypeScript와 함께 사용할 때 스타일 속성에 대한 타입 체크와 자동완성을 제공한다.
  • 빌드 최적화: 사용하지 않는 스타일을 자동으로 제거하고, 코드 스플리팅과 함께 필요한 스타일만 로드할 수 있다.
네임스페이스 오염 (Namespace Pollution)
CSS에서 클래스명이나 ID가 겹쳐서 의도하지 않은 스타일이 적용되는 문제

■ 단점 및 한계

  • 런타임 오버헤드: 스타일을 런타임에 자바스크립트를 통해 생성하고 주입하므로 성능상 부담이 있을 수 있다. CSS나 Sass에 비해서 추가적인 연산이 발생하며, 렌더링 속도도 훨씬 느려지는 부작용이 있다.
  • 번들 크기 증가: CSS-in-JS 라이브러리 자체가 번들에 포함되어 크기가 커진다.
  • 서버사이드 렌더링 복잡성: SSR 환경에서 하이드레이션 불일치나 FOUC(Flash of Unstyled Content) 문제가 발생할 수 있다.
  • 개발자 도구 제한: 생성된 클래스명으로 인해 디버깅이 어려울 수 있다.
  • 컴포넌트 라이브러리와 충돌: 컴포넌트 라이브러리를 사용할 때 오류가능성이 커진다.
    ex) Material-UI / And Design / Chakra UI / Bootstrap
    1) 컴포넌트 라이브러리가 자체 CSS-in-JS 사용
    2) 프로젝트에서 다른 CSS-in-Js 라이브러리 사용
    3) 두 시스템이 서로 다른 방식으로 스타일을 주입해서 충돌
    4) SSR 시 하이드레이션 순서 문제로 스타일 적용 순서 꼬임

런타임 오버헤드 (Runtime Overhead)
프로그램이 실행되는 동안 추가로 발생하는 성능 부담을 말한다.
FOUC (Flash of Unstyle Content)
페이지가 로드될 때 스타일이 적용되지 않은 상태로 잠깐 보이는 현상

SSR에서 CSS-in-JS 사용 시
1. 서버에서 HTML 생성 (스타일 없음)
2. 브라우저가 HTML 받아서 표시 (스타일 없음)
3. JavaScript 로드되어 CSS 생성 / 적용 (스타일 적용)

2번과 3번 사이에 스타일 없는 콘텐츠가 '번쩍' 나타났다가 사라진다.

import styled from 'styled-components';

const Button = styled.button`
  background-color: #ededed;
  border: none;
  border-radius: 8px;
`;

function App() {
  return (
    <div>
      <h1>안녕 Styled Components!</h1>
      <Button>확인</Button>
    </div>
  );
}

export default App;

Styled Components는 컴포넌트를 만들면서 바로 해당 컴포넌트의 스타일을 작성한다. 마치 JSX로 컴포넌트를 만드는 것처럼 리액트스럽게 CSS를 쓰는 방식이다. 편리함 덕분에 개발 속도도 빨라질 것이다.

 

또한, 스타일 재사용이 필요한 상황에서는 클래스가 아니라 JavaScript 변수를 만든다.

import { css } from 'styled-components';

const shadow20 = css`
  box-shadow: 0 10px 15px rgba(0, 0, 0, 0.2);
`;

const shadow40 = css`
  box-shadow: 0 10px 15px rgba(0, 0, 0, 0.4);
`;
-------------------------------------
import { shadow20 } from '../shadows';

const Card = styled.div`
  ${shadow20}
  ...(다른 CSS 코드)
`;

export default Card;

네스팅(Nesting) 문법

CSS 규칙 안에서 CSS 규칙을 만드는 것을 말한다.

 

& 선택자

부모 선택자를 의미한다.

 

컴포넌트 선택자

${ComponentName} 같이 컴포넌트 자체를 템플릿 리터럴 안에 넣어주면 된다.


styled() 함수

Styled Components로 만들어진 컴포넌트를 상속한다.

import styled from 'styled-components';

const SIZES = {
  large: 24,
  medium: 20,
  small: 16,
};

const Button = styled.button`
  background-color: #6750a4;
  border: none;
  color: #ffffff;
  font-size: ${({ size }) => SIZES[size] ?? SIZES['medium']}px;
  padding: 16px;

  ${({ round }) =>
    round
      ? `
      border-radius: 9999px;
    `
      : `
      border-radius: 3px;
    `}

  &:hover,
  &:active {
    background-color: #463770;
  }
`;

export default Button;
-------------------------------------------------
import styled from 'styled-components';
import Button from './Button';

const SubmitButton = styled(Button)`
  background-color: #de117d;
  display: block;
  margin: 0 auto;
  width: 200px;

  &:hover {
    background-color: #f5070f;
  }
`;

function App() {
  return (
    <div>
      <SubmitButton>계속하기</SubmitButton>
    </div>
  );
}

export default App;

css 함수

스타일 재사용. 함수를 삽입하지 않은 단순한 문자열이라면 일반적인 템플릿 리터럴을 사용해도 되지만, CSS 함수를 사용하도록 습관화하는 것을 권장한다.

const boxShadow = `
  box-shadow: 0 5px 15px rgba(0, 0, 0, 0.2);
`;

-------- css 함수화 ---------
const boxShadow = css`
  box-shadow: 0 5px 15px rgba(0, 0, 0, 0.2);
`;

 


참고 자료

https://fe-developers.kakaoent.com/2022/220210-css-in-kakaowebtoon/

 

카카오웹툰은 CSS를 어떻게 작성하고 있을까? | 카카오엔터테인먼트 FE 기술블로그

다음 글 초보 웹 개발자를 위한 자바스크립트 빌드 툴과 SWC

fe-developers.kakaoent.com

https://junghan92.medium.com/%EB%B2%88%EC%97%AD-%EC%9A%B0%EB%A6%AC%EA%B0%80-css-in-js%EC%99%80-%ED%97%A4%EC%96%B4%EC%A7%80%EB%8A%94-%EC%9D%B4%EC%9C%A0-a2e726d6ace6

 

(번역) 우리가 CSS-in-JS와 헤어지는 이유

원문: https://dev.to/srmagura/why-were-breaking-up-wiht-css-in-js-4g9b

junghan92.medium.com

 

'프론트엔드 > CSS 심화' 카테고리의 다른 글

Stylelint  (0) 2024.05.25
Tailwind CSS  (0) 2024.04.18
CSS Modules  (0) 2024.04.18
Sass(SCSS)  (0) 2024.04.18
CSS 클래스 이름 설정 : BEM(Block Element Modifier)  (0) 2024.04.18

댓글