CSS 스타일링 접근법: 7가지 방법론의 비교와 활용

민준·2024년 12월 21일
1

1. Global CSS

CSS파일하나의 모든 셀랙터를 정의한것!, 전통적인 CSS 파일 방식으로, 모든 스타일이 전역으로 적용됩니다.

Selector 원시 방식 : 외부에 정의된 CSS 파일을 통해 import 하여 HTML Selector 로 일일히 적용 방식

Inline 방식 : <div style={**{ borderColor: ‘red’, … }**} /> : 객체라 React 리렌더 성능 이슈
= React 에서 style 내 객체가 매 렌더링마다 다르게 인식되어 매번 DOM 계산을 통한 성능 저하 발생

  • 파일에 선언된 클래스나 ID는 모든 HTML 요소에 영향을 미칠 수 있음.
  • 선택자 충돌을 막기위해 BEM(Block Element Modifier) 사용
  • 선택자 충돌이 혹여나 발생한다면 !important 를 통해 특정 선택자의 우선순위를 강하게 주장
  • 하나의 Global CSS 가 모든 페이지의 CSS 를 관할하기때문에 번들사이즈가 커도 너무 큼
  • 이름 충돌 가능성이 높음, 유지보수 어려움(대규모 프로젝트에서 특정 스타일의 영향 범위를 파악하기 어려움)
body {
  font-family: Arial, sans-serif;
}
.btn {
  color: white;
  background: blue;
}

2. CSS Modules

CSS파일을 컴포넌트별(각 페이지)로 분리하고, 각 스타일이 해당 컴포넌트(각 페이지) 내에서만 적용되도록 처리

현대 방법 (적은 선호) - Global CSS 는 단 하나의 CSS 파일이라면, Modules 는 각 페이지마다의 CSS 파일

  • 선택자 충돌이 발생하지 않는다 (No Collisions) - 각 페이지마다 CSS 가 로컬 Scope 를 갖기때문
  • Next.js 사용 시 해당 컴포넌트 혹은 페이지가 import 하는 CSS 를 알 수 있어 Code Splitting (엔트리포인트 기준으로 나눌수 있다) 가능
  • composes 문법을 통해 타 CSS Modules 의 선택자 정의를 가져와 확장할 수 있다.
  • 하지만, 여전히 No Programmatic Features (Loop, Mixin 등과 같은 확장 문법들 사용 불가능)
  • 설정(webpack 등)이 필요하며, 글로벌 스타일 정의가 복잡해질 수 있음.
/* Button.module.css */
.btn {
  color: white;
  background: blue;
}
import styles from './Button.module.css';

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

3. CSS Preprocessor

CSS의 확장 언어로, 변수, 중첩, 조건문, 함수 등과 같은 기능을 제공

현대 방법 (적은 선호) - 컴파일러를 통해 SCSS, SASS, LESS 등의 CSS 확장 문법지원 언어를 CSS 로 컴파일

  • 더 강력한 기능으로 코드 재사용성과 유지보수성 향상.
  • CSS작성 후 컴파일 과정이 필요
  • Next.js 사용한다면 SASS 컴파일러를 npm 으로 설치후 .css 확장자 파일을 .scss 로 변환만 하면됨
    • 모든 Programmatic Features (Loop, Mixin 등과 같은 확장 문법) 모두 훌륭하지만
    • 새로운 언어를 배워야한다는 점과, JS 로직과 완전히 분리되어있기에 유저 인터랙션에 따른 조작이 힘듬
$primary-color: blue;

.btn {
  color: white;
  background: $primary-color;

  &:hover {
    background: darken($primary-color, 10%);
  }
}

4. CSS-in-JS

CSS를 자바스크립트 코드 내에서 정의하는 방식

Selector 없이 JS 내 CSS 사용 : styled.div** border-color: red; ** (@Media 등 CSS 문법)

현대 방법 (큰 선호) - JS 로직을 그대로 사용하고, CSS 문법을 그대로 사용할 수 있어서 양측의 장점을 다 가짐

  • 컴포넌트와 스타일을 함께 작성 가능.

  • 동적 스타일링(프로퍼티 기반으로 동적으로 스타일 조정).

  • Styled Components, Emotion 등이 존재하나 현재 Emotion 이 표준 (MUI 내 선택 및 사용, SSR 최적)

    • 유저 인터렉션에 따라 JS 로직을 통해 동적 CSS 적용이 가능하고 (Dynamic Styles)
    • CSS 의 부족한 No Programmatic Features 단점을 다양한 JS 의 Programmatic Features 로 보완
    • 자연스럽게 CSS 추가 파일 생성없이 JS 파일 안에 CSS 를 정의하다보니 자연스럽게 Scoped Styles
  • Next.js 사용한다면 자체 제공하는 Styled JSX 라는 CSS-in-JS 솔루션을 사용할 수 있다.

import styled from 'styled-components';

const Button = styled.button`
  color: white;
  background: ${props => props.primary ? 'blue' : 'gray'};
`;

function App() {
  return <Button primary>Click me</Button>;
}

5. Tailwind CSS (CSS Framework 로 분류)

유틸리티 클래스 기반의 CSS 프레임워크로, 사전에 정의된 클래스들을 조합하여 스타일링

Selector 원시 방식 : HTML 혹은 React Component(JSX) 내 CSS 유틸리티 클래스 바로 명시

현대 방법 (큰 선호) - 유틸리티 클래스 라이브러리. 미리 CSS 정의된 선택자에 해당하는 클래스명을 조합해 개발

  • 참고로 Tailwind CSS 를 CSS Framework 로 설명하기는하나 후술할것과는 조금 좁은 의미의 프레임워크
    • 어떤 프론트엔드 개발에서든 추가적인 설치 및 설정과 툴 사용을 요구한다는 단점이 있지만
    • CSS 를 직접 작성하는것보다 CSS 의미론적인 유틸리티 클래스를 사용하는게 직관적이고 개발이 빠르다
      • IDE IntelliSence 가 자동으로 어떤 클래스를 사용하면 되는지, 자동완성 및 코드 추천을 해주기때문
    • 사용한 클래스를 제외하고 모든 미사용 유틸리티 클래스를 지우고(Purge) 번들링하여 번들 사이즈 축소
    • 모든 사람이 이 방식을 좋아하는건 아니다 HTML 이 더러워진다는 단점도 분명하고
    • 미리 만들어진 Component 를 제공하지 않기때문에 필요한 컴포넌트들을 우리가 다 만들어 써야한다
<button class="bg-blue-500 text-white px-4 py-2 rounded">Click me</button>

6. UI Framework

스타일뿐만 아니라 UI 구성 요소(Button, Modal 등)와 동작을 포함한 패키지.

현대 방법 (큰 선호) - Bootstrap 자체 제작 컴포넌트와 CSS 디자인 시스템을 함께 제공

  • CSS와 JavaScript를 모두 포함. 빠른 프로토타이핑, 풍부한 UI 컴포넌트
  • Pre-built Component 미리 (디자인 시스템으로) 자체적으로 제작되어진 컴포넌트를 제공
  • 자체 디자인 시스템을 기반으로 만들어졌기때문에, 디자인 시스템 내 변수만 바꾸면 쉽게 테마 제작 가능
  • 생각보다 Pre-built Component 를 그대로 사용할일은 없고, Wrapper Component 를 만들어야함
  • 사용하지 않는 Pre-built Component 들과 CSS 정의들을 모두 번들링하기에 번들 사이즈가 너무 크다
import { Button } from '@mui/material';

function App() {
  return <Button variant="contained" color="primary">Click me</Button>;
}

7. Component Library

UI 프레임워크와 유사하지만, 특정 디자인 체계를 준수하며, 독립된 컴포넌트 제공.

현재 방법 (큰 선호) - Mantine, Ant, Material Design, Chakra UI, Chadcn 많이 들어본것들이 이에 해당

  • Tailwind 같은 프레임워크와 조합 가능.
  • 자체 제작 컴포넌트를 제공하긴하는데, 컴포넌트 제공에 주안점을 두고 CSS 는 최대한 무색무취로 제공
    • 개발자가 자체적으로 원하는 디자인을 적용하여 커스터마이징하여 사용하기 수월하다.
import { Box, Button } from '@chakra-ui/react';

function App() {
  return (
    <Box>
      <Button colorScheme="blue">Click me</Button>
    </Box>
  );
}

요약

방식주요 특징사용 사례
Global CSS전역 스타일, 네임스페이스 충돌 가능소규모 프로젝트, 간단한 웹사이트
CSS Modules로컬 스코프 클래스, 컴포넌트 단위 스타일링React/Vue 프로젝트
CSS Preprocessor변수, 중첩 등 강력한 기능 제공대규모 프로젝트, 팀 협업 환경
CSS-in-JS동적 스타일링, 컴포넌트와 스타일 통합Styled-components, Emotion 사용 시
Tailwind CSS유틸리티 클래스, 빠른 프로토타이핑Atomic Design 추구 프로젝트
UI Framework스타일 + 동작 포함한 UI 구성 요소 제공Bootstrap, Material UI 사용 시
Component Library독립된 구성 요소로 UI 구성, 특정 디자인 체계 준수Chakra UI, Fluent UI 사용 시

0개의 댓글