리액트 컴포넌트 스타일링 — CSS Modules로 CSS 스코프 적용하기

장효정·2025년 11월 26일

바닐라 CSS는 단순하고 협업에 좋지만, React에서 가장 큰 단점은 스타일이 전역 스코프를 가진다는 점이다. 즉, 한 컴포넌트의 CSS 파일에서 작성한 규칙이 다른 컴포넌트까지 영향을 줄 수 있다.
CSS Modules는 이 문제를 해결할 수 있는 방식이다. CSS는 그대로 쓰되, 클래스 이름을 자동으로 "파일 단위로 고유하게 변환"하여 각 컴포넌트에만 적용되도록 스코프를 만들어준다.

이 글에서는 CSS Modules의 동작 원리, 사용법, 장단점을 정리한다.

1. CSS Modules란?

CSS Modules는 CSS 파일에서 선언한 클래스 이름을 컴포넌트 단위로 고유하게 변환해주는 방식이다.

즉,

  • CSS는 그대로 작성
  • import 시 JS 객체로 받아서 className에 넣음
  • 컴포넌트 파일마다 완전히 유니크한 CSS 이름이 생성됨

이 방식으로 스타일 충돌 없이 CSS를 안전하게 사용할 수 있다.

2. CSS Modules 사용 방법

(1) 파일 이름을 module.css 형태로 변경

header.css → header.module.css

.module.css 이름이 빌드 툴에게 "이 파일은 CSS Modules 방식으로 처리해라"라고 알려주는 신호다.

(2) 컴포넌트에서 import 방식도 변경

import classes from './header.module.css';

여기서 classes 객체 안에는 CSS Modules에 의해 변환된 "고유 클래스 이름들"이 들어 있다.

(3) className에 적용하기

<p className={classes.paragraph}>Hello World</p>

예를 들어 CSS에 아래와 같이 작성했다면

.paragraph {
  text-align: center;
}

브라우저에서 렌더링된 HTML에는 아래와 같이 변경된 클래스가 붙는다.

<p class="paragraph_header__Xa2De">Hello World</p>

이렇게 고유한 클래스 이름이 생성되기 때문에 다른 컴포넌트에서 .paragraph를 선언해도 절대로 충돌하지 않는다.

3. CSS Modules 동작 방식 (중요 개념)

  1. 빌드 도구(Vite · Webpack 등)가 CSS 파일을 읽는다.
  2. 각 클래스명을 "파일 단위로 고유한 이름"으로 변환한다.
  3. 변환된 클래스명들을 하나의 JS 객체로 export한다.
  4. 컴포넌트는 이 객체에서 필요한 클래스만 꺼내 쓴다.
  5. HTML에는 변환된 실제 클래스명이 적용된다.

4. 기존 className 조건부 스타일링도 그대로 가능

CSS Modules를 사용해도 className은 문자열이므로 조건부 스타일링도 기존과 동일하게 사용 가능하다.

<p className={`${classes.paragraph} ${isActive ? classes.active : ''}`}>
  Hello!
</p>

여기서 classes.active 또한 고유한 문자열이기 때문에 충돌이 생기지 않는다.

5. CSS Modules 장단점

장점

1) 컴포넌트 단위 스코프

  • 전역 충돌이 완전히 사라짐

2) CSS는 그대로 사용 가능

  • CSS 문법을 그대로 유지하므로 진입 장벽이 낮음.

3) 협업 용이

  • CSS 파일 / 컴포넌트 파일이 역할 분리되어 유지보수가 쉬움

4) 조건부 스타일링도 자연스럽게 가능

  • JS 객체에서 클래스명을 가져오면 되므로 패턴이 동일함

단점

1) CSS 파일이 많아짐

  • 컴포넌트 단위로 파일을 나누면 파일은 많지만 파일 내용은 적은 CSS 파일들ㄹ이 늘어나기 쉬움

2) 여전히 CSS를 알아야 함

  • 기본 문법, 선택자, 플렉스, 그리드 등은 직접 작성해야 함

3) 전역 스타일이 필요할 때 다소 번거로움

  • 전역 reset, layout 스타일을 관리할 별도 파일이 필요함

0개의 댓글