Logo

React 컴포넌트 CSS 스타일링 기본

React 공식 레퍼런스에 따르면 React에서는 명확한 스타일링 가이드를 제공하지 않는데요.

React does not have an opinion about how styles are defined.

그도 그럴 것이 현재 CSS 기술 자체가 사용되는 방식이 워낙 다양하기 때문에 React에서 꼭 찝어 어느 방식을 따르라고 얘기하기가 조심스러울 것입니다.

그래서 이번 포스팅에서는 React 컴포넌트를 별도의 CSS-in-JS 라이브러리 없이 순수하게 CSS로만 스타일하는 가장 기본적인 방법을 알아보겠습니다.

Inline Style

가장 간단하고 쉬운 방법은 해당 React 컴포넌트에 CSS 인라인 스타일(inline style)을 바로 적용하는 것입니다. 일반적인 웹페이지에서 인라인 스타일을 적용할 때 처럼 HTML 엘리먼트의 style 속성을 이용하면 됩니다.

하지만 React는 자바스크립트로 작성하기 때문에 웹페이지에서 인라인 스타일을 적용할 때와 약간의 차이점이 있습니다.

  • style 속성값에 일반 문자열이 아닌 자바스크립트 객체가 할당되야 합니다.
  • CSS 속성명이 케밥 케이스(kebab case)이 아닌 카멜 케이스(camel case)로 작성되야 합니다.

예를 들어, 버튼 엘리먼트에 간단한 인라인 스타일을 적용해보겠습니다. CSS 속성이 정의된 객체를 버튼 엘리먼트의 style 속성에 넘겨주면 됩니다.

white1rem과 같은 자바스크립트에는 존재하지 않는 키워드는 스트링 값으로 인식되도록 쿼테이션 기호로 감싸줘야 합니다. 그리고 font-size와 같이 중간에 대시 기호(-)가 들어간 속성명은 fontSize와 같이 카멜 케이스로 바꿔줘야 합니다.

import React from "react";

const btnStyle = {
  color: "white",
  background: "teal",
  padding: ".375rem .75rem",
  border: "1px solid teal",
  borderRadius: ".25rem",
  fontSize: "1rem",
  lineHeight: 1.5,
};

function Button() {
  return <button style={btnStyle}>Inline</button>;
}

인라인 스타일은 CSS에서도 그렇듯이 React에서도 유지 보수나 성능 상으로 이유로 권장되지 않는 방법입니다. 직접 사용해보면 매번 CSS 속성명을 케밥 케이스로 바꿔줘야 하는 것도 번거롭고, 무엇보다 :hover와 같은 pseudo class도 사용할 수 없다는 치명적인 제약도 있습니다. 하지만 개발 중에 임시로 스타일을 빠르게 적용해볼 때 꽤 유용하기 때문에 소개해드렸습니다.

External Stylesheet

다음으로 소개시켜드릴 방법은 별도의 파일에 스타일을 정의해놓고, React 컴포넌트 파일에서 해당 CSS 파일을 임포트합니다. 그 다음, 엘리먼트의 className 속성을 이용해서 외부 파일에 정의된 스타일을 맵핑시켜주는 것입니다.

보통 CSS를 직접 작성하지 않고 Bootstrap과 같은 외부 CSS 라이브러리를 사용할 때 자주 쓰이는 방법인데요.

예를 들어, Button.css 파일에 다음과 같이 스타일을 정의합니다.

.btn {
  color: white;
  background: teal;
  padding: 0.375rem 0.75rem;
  border: 1px solid teal;
  border-radius: 0.25rem;
  font-size: 1rem;
  line-height: 1.5;
}

그리고 버튼 컴포넌트가 작성된 Button.js 파일에서 다음과 같이 위 CSS 파일을 임포트합니다. 이때 속성명을 class 대신에 className를 사용해야 한다는 것의 주의하세요. (class는 자바스크립트에서 클래스 정의 용도로 사용되는 키워드이기 때문입니다.)

import React from "react";
import "./Button.css";

function Button() {
  return <button className="btn">External</button>;
}

CSS Modules

위에서 소개한 외부 스타일시트를 사용하는 방법은 React 앱의 규모가 커짐에 따라 CSS 클래스 이름이 겹치게 될 가능성이 커지게 됩니다. 기본적으로 글로벌 네임 스페이스(global namespace)를 사용하기 때문에, 만약 2개의 CSS 파일에 동일한 클래스에 대한 스타일이 정의되어 있다면, 해당 클래스가 적용된 엘리먼트는 2개의 스타일에 모두 영향을 받게 됩니다.

이 문제를 해결하기 위한 방법으로 각 CSS 파일에 고유의 네임 스페이스를 부여해주는 CSS 모듈(CSS Modules)이라는 기법이 있습니다. React 컴포넌트에 CSS 모듈을 통해서 스타일을 적용하는 방법은 다음과 같습니다.

  • 외부 스타일 시트를 작성할 때, .css 확장자가 아닌 .module.css 확장자를 사용해야 합니다.
  • React 컴포넌트 파일에서 임포트할 때, 임포트된 CSS 모듈의 이름을 명시적으로 지정해줍니다. (import modlue_name from "./my/style.module.css";)
  • 엘리먼트의 className 속성을 할당해줄 때, 해당 클래스가 어느 CSS 모듈 소속인지 알려줍니다. (module_name.class_name)

예를 들어, Button.module.css 파일을 생성하고, 위 섹션에서 작성한 Button.css 파일의 내용을 그대로 복사해 넣습니다.

그 다음, Button.module.css 파일을 임포트할 때, CSS 모듈명을 styles라고 지정해줍니다. 그리고 버튼 엘리먼트의 className 속성에, 그냥 btn이 아닌 styles.btn을 넘겨줍니다.

import React from "react";
import styles from "./Button.module.css";

function Button() {
  return <button className={styles.btn}>Module</button>;
}

export default Button;

브라우저에서 페이지 소스 보기를 해보면 실제 클래스 이름이 다음과 같이 설정 되었음 알 수 있습니다.

<button class="_src_module_Button_module__btn">Module</button>

이렇게 CSS 모듈을 사용하면, 각 CSS 파일마다 고유한 네임 스페이스를 부여해주기 때문에, 각 React 컴포넌트는 완전히 격리된 스타일을 보장받습니다. 따라서, 다른 CSS 파일에 btn 클래스에 대한 스타일이 정의가 되어 있더라도, 이 CSS 파일에 있는 btn 클래스는 영향을 받지 않게 됩니다.

마치면서

이상으로 간단한 예제를 통해서 React 컴포넌트를 CSS 만으로 스타일하는 가장 기본적인 3가지 방법을 살펴보았습니다. 간단한 React 앱에서는 이 정도 방법으로 충분하겠지만, 실제 React 프로젝트에서는 Styled Components와 같은 CSS-in-JS 라이브러리나 Tailwind와 같은 유티리티 클래스 라이브러리가 많이 사용되고 있습니다.

Tailwind에 관련 포스팅은 Tailwind 태그를 통해서 쉽게 만나보세요!

Styled Components와 관련 포스팅은 StyledComponents 태그를 통해서 쉽게 만나보세요!