모던 CSS들의 장단점

Jeris·2023년 6월 2일
4

CSS

목록 보기
1/1

Vanilla CSS

CSS3

  • CSS3(Cascading Style Sheets 3)는 웹 문서의 스타일과 레이아웃을 꾸미기 위한 style sheet 언어인 CSS의 최신 버전입니다.

Pros

  • 웹 표준(Web Standard): CSS는 웹 표준으로 채택되어 있습니다. 모든 웹 브라우저에서 지원되며, 호환성 문제가 적습니다.
  • 학습 곡선(Learning Curve): CSS는 단순하고 직관적인 문법을 가지고 있어 학습 곡선이 상대적으로 낮습니다.
  • 성능(Performance): 별도의 전처리 단계나 컴파일 과정이 필요하지 않으므로 추가적인 연산이 발생하지 않습니다.

Cons

  • 재사용성(Reusability): CSS3에서는 @rules, variables, calc() 함수 등의 기능을 도입하여 코드의 재사용성을 높이긴 했지만 기능이 상대적으로 부족하여 대부분의 재사용 패턴을 구현하기에는 어려움이 있습니다.
  • 중첩(Nesting): Vanilla CSS는 중첩을 지원하지 않습니다.
  • 모듈화(Modularity): CSS의 모듈화는 클래스 이름 규칙을 따르는 것에 크게 의존하는데, CSS의 전역적인 특성으로 인해 클래스 이름 충돌의 위험이 있습니다.
  • 반복적인 문법(Repetitive Syntax): CSS의 상속과 우선 순위 규칙 때문에 반복적인 코드 작성을 요구하여 생산성이 떨어지고 실수할 가능성이 높아집니다.
  • 컴파일-타임 체크(Compile-Time Checks): CSS는 컴파일 타임에서의 오류나 오타를 체크하지 않아 예기치 않은 스타일 오작동을 일으킬 수 있습니다.
  • 전처리기(preprocessor): Vanilla CSS는 전처리기 기능을 제공하지 않습니다.

CSS Pre/Post-processor

CSS 전처리기(CSS preprocessor)

  • CSS를 개선하기 위해 만들어진 스크립팅 언어로, CSS로 컴파일되는 확장된 CSS 문법을 사용합니다.
  • CSS 전처리기는 변수, 함수, 믹스인, 계산, 중첩과 같은 강력한 기능을 제공하여 CSS의 가독성을 높이고 코드의 재사용성을 향상시킵니다.
  • Sass, Less, Stylus 등이 있습니다.

Sass(Syntactically awesome style sheets)

  • Sass.scss.sass 두 가지 문법을 지원합니다.
    • .scss는 CSS와 유사한 구문을 사용하며, 기존 CSS 파일에서 Sass로 쉽게 변환할 수 있습니다.
    • .sass는 들여쓰기로 구문을 표현하며, 세미콜론이나 중괄호를 사용하지 않아 더 간결한 문법을 가지고 있습니다.
// .scss

// Variables
$font-stack:    Helvetica, sans-serif;
$primary-color: #333;
$box-colors:    red, blue, green;

// Mixin
@mixin border-radius($radius) {
  -webkit-border-radius: $radius;
     -moz-border-radius: $radius;
      -ms-border-radius: $radius;
          border-radius: $radius;
}

// Extend
%message-shared {
  border: 1px solid #ccc;
  padding: 10px;
  color: $primary-color;
}

// Nesting
body {
  font: 100% $font-stack;
  color: $primary-color;
  .container {
    width: 100%;
  }
}

// if-else statement
@mixin text-color($lightness) {
  @if lightness($lightness) > 30 {
    color: #000;
  } @else {
    color: #fff;
  }
}

.message {
  @extend %message-shared;
  border-color: $primary-color;
  @include text-color($primary-color);
}

// for statement
@for $i from 1 through 3 {
  .item-#{$i} { width: 2em * $i; }
}

// each statement
@each $box-color in $box-colors {
  .box-#{index($box-colors, $box-color)} {
    background: $box-color;
    @include border-radius(5px);
  }
}
// .sass

// Variables
$font-stack:    Helvetica, sans-serif
$primary-color: #333
$box-colors:    red, blue, green

// Mixin
=border-radius($radius)
  -webkit-border-radius: $radius
     -moz-border-radius: $radius
      -ms-border-radius: $radius
          border-radius: $radius

// Extend
%message-shared
  border: 1px solid #ccc
  padding: 10px
  color: $primary-color

// Nesting
body
  font: 100% $font-stack
  color: $primary-color
  .container
    width: 100%

// if-else statement
=text-color($lightness)
  @if lightness($lightness) > 30
    color: #000
  @else
    color: #fff

.message
  @extend %message-shared
  border-color: $primary-color
  +text-color($primary-color)

// for statement
@for $i from 1 through 3
  .item-#{$i}
    width: 2em * $i

// each statement
@each $box-color in $box-colors
  .box-#{index($box-colors, $box-color)}
    background: $box-color
    +border-radius(5px)

Pros

  • 변수(Variable): 변수를 사용하여 스타일 속성의 값을 일괄적으로 관리할 수 있으며, 코드의 가독성과 유지 보수성을 향상시킵니다.
  • 중첩(Nesting): CSS의 중첩 기능을 확장하여 스타일 코드를 구조화할 수 있어 가독성을 높입니다.
  • 믹스인(Mixin): @mixin mixinName(params), @include mixinName(args) 형태로 믹스인을 사용하여 재사용 가능한 스타일 코드 블록을 정의하고 삽입할 수 있어, 반복적인 코드 작성을 줄이고 스타일의 재사용성을 높일 수 있습니다.
  • 상속(Extend): @extend .className 형태로 CSS의 상속 개념을 지원하여 스타일 속성을 상속할 수 있습니다. 이를 사용하면 스타일 코드의 중복을 최소화하고 스타일 규칙을 간결하게 작성할 수 있습니다.
  • 조건문과 반복문(if-else, for, each statement): 조건문과 반복문을 통해 동적인 스타일 코드를 작성할 수 있어 유연한 스타일링이 가능합니다.

Cons

  • 반복적인 문법(Repetitive Syntax): SCSS는 CSS와 마찬가지로 상속과 우선 순위 규칙을 따라야 하기 때문에 반복적인 코드 작성이 필요할 수 있습니다.
  • 컴파일 오버헤드(Compile Overhead): Sass 파일을 컴파일하여 변경 사항을 확인하기 위해 개발자들은 Sass 파일을 컴파일해야 합니다.
  • 코드 복잡성(Code Complexity): Sass의 기능과 편의성은 유용하지만, 과도하게 사용하면 코드의 가독성을 저해하고 복잡성을 증가시킬 수 있습니다. 적절한 네이밍 규칙, 구조화, 주석 등을 사용하여 코드의 가독성과 유지 보수성을 유지해야 합니다.

CSS 후처리기(CSS postprocessor)

  • CSS 파일을 컴파일한 후, 컴파일된 CSS에 추가적인 변환, 최적화 또는 기능을 적용하는 도구입니다. 후처리기는 전처리된 CSS 코드를 분석하고 변경하여 최종 CSS 파일을 생성하는 단계에서 사용됩니다.
  • 보통 CSS 전처리기도 CSS 후처리기의 기능을 포함합니다.
  • PostCSS, Stylecow, CssNext 등이 있습니다.

PostCSS

  • CSS를 변형하기 위해 JavaScript 플러그인을 사용하는 도구입니다.
  • JavaScript 기반의 도구로, CSS를 최신 기술과 브라우저 호환 가능한 형식으로 자동으로 변환해줍니다.
    • CSS에 문제가 있는지 사전에 확인하여 에러 로그를 제공합니다.
    • 최신 CSS 기술들을 브라우저에서 호환 가능한 형태로 자동 변환해줍니다.
/* Autoprefixer 플러그인을 사용하여 벤더 프리픽스 자동 추가 */

/* 입력 CSS */
.button {
  transition: transform 0.3s;
  user-select: none;
}

/* PostCSS 처리 후 */
.button {
  -webkit-transition: -webkit-transform 0.3s;
  transition: -ms-transform 0.3s;
  transition: transform 0.3s;
  -webkit-user-select: none;
     -moz-user-select: none;
      -ms-user-select: none;
          user-select: none;
}
/* CSS 변수 사용 */

/* 입력 CSS */
:root {
  --primary-color: #ff0000;
}

.button {
  color: var(--primary-color);
  background-color: var(--secondary-color, #000000);
}

/* PostCSS 처리 후 */
.button {
  color: #ff0000;
  background-color: #000000;
}
/* CSS Nano 플러그인을 사용하여 CSS 파일 최적화 */

/* 입력 CSS */
.button {
  color: #ff0000;
  font-size: 16px;
  margin: 10px 20px;
}

/* PostCSS 처리 후 */
.button{color:red;font-size:16px;margin:10px 20px}

Pros

  • 최적화(Optimization): 다양한 최적화 플러그인을 제공하며, 중복된 스타일 규칙을 병합하거나 사용하지 않는 스타일 규칙을 제거하여 CSS 파일의 크기를 줄일 수 있습니다.
  • 확장성(Extensibility): 다양한 플러그인을 사용하여 CSS 파일을 처리할 수 있으며, 사용자가 원하는 기능을 확장하고 커스텀할 수 있습니다.
  • 유연성(Flexibility): 플러그인 기반으로 동작하기 때문에 많은 수의 플러그인을 활용하여 원하는 기능을 추가하거나 수정할 수 있습니다.
  • 생태계(Ecosystem): 다양한 플러그인이 개발되어 있어서 다양한 기능을 활용할 수 있습니다. CSS 전처리기의 기능뿐만 아니라, 벤더 프리픽스 자동 추가, CSS 변수 사용, 미디어 쿼리 정리 등 다양한 작업을 처리할 수 있습니다.
  • 성능(Performance): 내장된 최적화 기능을 제공하며, 여러 최적화 플러그인을 사용하여 CSS 파일의 크기를 줄이고 불필요한 코드를 제거할 수 있습니다. 이는 웹 페이지의 로딩 속도를 향상시키고, UX를 개선할 수 있습니다.

Cons

  • 추가적인 빌드 단계(Additional Build Step): 컴파일된 CSS 파일을 분석하고 변환하는 과정이 필요하므로, 개발 과정에서 추가적인 빌드 단계가 필요합니다. 이에 따라 개발자가 빌드 도구나 태스크 러너 설정을 추가로 구성해야 할 수 있습니다.
  • 설정 복잡성(Configuration Complexity): 사용자 지정 설정이나 플러그인을 통해 동작을 조정할 수 있습니다. 초기 설정과 플러그인 조합에 대한 학습 곡선이 있을 수 있으며, 일부 플러그인의 호환성 문제가 발생할 수도 있습니다.
  • 디버깅(Debugging): 생성된 최종 CSS 코드는 컴파일된 상태로 되돌릴 수 없으므로, 디버깅이나 스타일 수정을 위해 원본 소스 코드에 접근하기 어려울 수 있습니다. 따라서 디버깅을 위한 추가 도구와 방법을 활용해야 합니다.

방법론(Methodologies)

BEM(Block Element Modifier)

  • CSS 클래스 네이밍 규칙을 정의하여 웹 개발에서 스타일 코드의 일관성과 유지보수성을 높이는 방법론입니다.
  • .block__element--modifier 형태를 사용합니다.
  • Block: 그 자체로 의미 있는 독립형 엔티티입니다.
    • header, container, menu, checkbox, input
  • Element: 독립적인 의미가 없으며 의미론적으로 블록에 연결된 블록의 일부입니다.
    • item, caption, title, size, color
  • Modifier: 블록 또는 요소의 플래그입니다. 모양이나 동작을 변경하는 데 사용합니다.
    • disabled, highlighted, checked, fixed, big, yellow
.card {
    /* Block level styling here... */
}

.card__image {
    /* Element level styling here... */
}

.card__content {
    /* Element level styling here... */
}

.card__title {
    /* Element level styling here... */
}

.card__description {
    /* Element level styling here... */
}

.card__button {
    /* Element level styling here... */
}

.card__button--primary {
    /* Modifier level styling here... */
}

Pros

  • 일관성(Consistency): 클래스 네이밍을 구조화하고 일관성 있게 작성하여 코드를 읽기 쉽게 만듭니다. 각 block, element, modifier에 대한 클래스 이름이 명확하게 정의되어 스타일 충돌을 방지합니다.
  • 모듈화(Modularity): 블록 스타일은 페이지의 다른 요소에 의존하지 않기 때문에, cascading 문제를 일으키지 않습니다.
  • 재사용성(Reusability): 독립적인 블록들을 다양한 방법으로 구성하고, 이를 효율적으로 재사용함으로써 유지해야 할 CSS 코드의 양이 줄어듭니다.
  • 구조(Structure): BEM 방법론은 CSS 코드에 간단하고 이해하기 쉬운 견고한 구조를 제공합니다.

Cons

  • 클래스 이름의 길이(Length of Class Name): BEM은 클래스 이름을 구조적으로 작성하기 때문에 길어질 수 있습니다. 긴 클래스 이름은 코드 가독성을 저해할 수 있으며, 작성해야하는 코드의 양이 늘어날 수 있으며, HTML 파일의 크기를 늘릴 수 있습니다.

CSS 모듈(CSS Modules)

  • CSS 모듈은 모든 클래스 이름과 애니메이션 이름이 기본적으로 로컬로 범위가 지정된 CSS 파일입니다.
  • 모든 URL(url(...))과 @imports는 모듈 요청 형식입니다.
  • CSS 모듈은 ICSS 또는 Interoperable CSS라는 low-level interchange 형식으로 컴파일되지만 일반 CSS 파일처럼 작성됩니다.
/* styles.css */
:global(.global-class) {
  color: blue;
}

.title {
  composes: global-class;
}
// App.js
import styles from './styles.css';

function App() {
  return <h1 className={styles.title}>Hello, world!</h1>;
}

Pros

  • 지역 범위(Local Scope): 클래스 이름을 고유한 이름으로 변환하여 스타일 규칙이 컴포넌트의 범위 내에서만 적용되도록 보장합니다. 이를 통해 클래스 이름 충돌을 방지하고 스타일이 컴포넌트에 국한되어 개별 컴포넌트의 스타일링을 쉽게 유지하고 이해할 수 있습니다.
  • 모듈화(Modularity): 컴포넌트 기반 스타일링을 용이하게 만듭니다. 각 컴포넌트의 스타일을 개별적으로 관리하고 재사용할 수 있습니다.
  • 클래스 이름 자동화(Automatic Class Name Generation): 고유한 클래스 이름을 자동으로 생성합니다. 이는 클래스 이름 작성에 대한 부담을 줄이고, 일관된 클래스 이름 규칙을 유지할 수 있도록 도와줍니다.
  • 재사용성(Reusability): 스타일 코드를 재사용 가능한 모듈로 만들어줍니다. 이는 다른 컴포넌트에서 동일한 스타일 규칙을 사용할 수 있으며, 스타일의 일관성과 중복된 코드를 줄여줍니다.

Cons

  • 툴 의존성(Tool Dependency): CSS Modules를 사용하기 위해서는 지원하는 빌드 도구나 프레임워크에 대한 설정이 필요합니다. 프로젝트 환경에 따라 추가적인 툴 의존성이 발생할 수 있으며, 이를 설정하고 관리하는 것이 필요합니다.
  • 클래스 이름 가독성(Class Name Readability): CSS Modules에서 생성된 고유한 클래스 이름은 자동으로 생성되기 때문에, 의미 있는 클래스 이름 작성에 대한 제약이 생길 수 있습니다. 일부 개발자들에게는 클래스 이름의 가독성이 낮아질 수 있다는 단점으로 인식될 수 있습니다.
  • 동적 스타일링(Dynamic Styling): CSS Modules는 컴파일 시점에 스타일이 결정되기 때문에 동적인 스타일링을 구현하기에는 제약이 있을 수 있습니다. 일부 동적인 스타일링 시나리오를 처리하기 위해 추가적인 작업이 필요할 수 있습니다.
  • 전역 스타일링(Global Styling): 전역 스타일이나 애니메이션 등을 관리하기 어려울 수 있습니다. CSS 모듈의 로컬 스코핑 기능은 :global 구문을 사용해야 하는 유형의 스타일링에서 복잡성이 발생할 수 있습니다.

CSS Frameworks

Tailwind CSS

  • 반응형 웹 애플리케이션을 빠르고 효율적으로 개발하기 위해 만들어진 프레임워크입니다.
  • CSS 유틸리티 클래스를 사용하여 커스텀 디자인 시스템을 구축하고 컴포넌트를 구성하는 방식으로 작동합니다.
<figure
  class="md:flex bg-slate-100 rounded-xl
         p-8 md:p-0 dark:bg-slate-800"
 >
  <img
    class="w-24 h-24 md:w-48 md:h-auto
           md:rounded-none rounded-full mx-auto"
    src="/sarah-dayan.jpg"
    alt=""
    width="384"
    height="512"
  />
  <div class="pt-6 md:p-8 text-center md:text-left space-y-4">
    <blockquote>
      <p class="text-lg font-medium">
        “Tailwind CSS is the only framework that I've seen scale
        on large teams. It’s easy to customize, adapts to any design,
        and the build size is tiny.</p>
    </blockquote>
    <figcaption class="font-medium">
      <div class="text-sky-500 dark:text-sky-400">
        Sarah Dayan
      </div>
      <div class="text-slate-700 dark:text-slate-500">
        Staff Engineer, Algolia
      </div>
    </figcaption>
  </div>
</figure>

Pros

  • 유틸리티 기반 디자인(Utility-based Design): 다양한 재사용 가능한 유틸리티 클래스를 제공하여 빠르고 효율적으로 디자인을 구축할 수 있습니다.
  • 커스터마이징(Customizing): 개발자가 Tailwind CSS를 커스터마이즈하여 자신만의 디자인 시스템을 생성할 수 있습니다.
  • 반응형(Responsiveness): 반응형 디자인을 지원하기 위한 유틸리티 클래스를 제공합니다.
  • 생산성 향상(Increased Productivity): 사전 정의된 유틸리티 클래스를 사용하여 스타일을 적용하므로, CSS를 작성하는 시간과 노력을 크게 절약할 수 있습니다.
  • 일관성(Consistence): 사전 정의된 클래스를 사용하여 컴포넌트를 구성하고 스타일을 적용함으로써 개발자들은 일관성 있는 디자인 원칙을 적용하고 디자인 시스템을 관리할 수 있습니다.
  • 생산성(Productivity): 사전 정의된 유틸리티 클래스를 활용하여 CSS를 작성하는 시간과 노력을 절약할 수 있습니다.
  • 유연성과 확장성(Flexibility and Extensibility): 커스터마이즈 가능한 클래스를 제공하여 프로젝트에 맞게 스타일을 조정할 수 있습니다.
  • 최적화: 작은 파일 크기로 제공되며, 필요한 유틸리티 클래스만 사용하도록 권장합니다.

Cons

  • 클래스 오버로딩(Class Overloading): 클래스 이름이 길어지고 복잡해지면 코드의 가독성이 감소할 수 있습니다. 적절한 네이밍 컨벤션과 구조를 유지하고, 필요한 경우 커스텀 클래스를 작성하여 클래스 오버로딩을 최소화할 수 있습니다.
  • 학습 곡선(Learning Curve): 기존의 CSS 작성 방식과는 다른 접근 방식을 가지고 있기 때문에 처음에는 유틸리티 클래스를 이해하고 적절하게 활용하는 데 시간이 걸릴 수 있습니다.
  • 파일 크기(File Size): 사전 정의된 많은 유틸리티 클래스를 포함하고 있기 때문에 CSS 파일의 크기가 커질 수 있습니다. 이는 초기 로딩 시간과 대역폭 사용량을 약간 증가시킬 수 있습니다. 그래서 Tailwind CSS는 트리 쉐이킹(tree shaking)과 CSS 압축 기능을 제공하여 사용하지 않는 클래스를 제거하고 파일 크기를 최적화할 수 있습니다.
  • 클래스 오버라이딩(Class Overriding): 유틸리티 클래스는 우선순위가 높아서 개발자가 직접 작성한 클래스나 다른 스타일링 기법을 덮어쓸 수 있습니다.

Pure CSS

// 버튼 스타일링
<button class="pure-button">클릭하세요</button>
// 그리드 레이아웃
<div class="pure-g">
  <div class="pure-u-1-2">왼쪽</div>
  <div class="pure-u-1-2">오른쪽</div>
</div>
// 폼 요소 스타일링
<form class="pure-form">
  <input type="text" placeholder="이름">
  <input type="email" placeholder="이메일">
  <button class="pure-button pure-button-primary">제출</button>
</form>
// 반응형 네비게이션
<nav class="pure-menu pure-menu-horizontal">
  <ul class="pure-menu-list">
    <li class="pure-menu-item"><a href="#" class="pure-menu-link"></a></li>
    <li class="pure-menu-item"><a href="#" class="pure-menu-link">소개</a></li>
    <li class="pure-menu-item"><a href="#" class="pure-menu-link">서비스</a></li>
    <li class="pure-menu-item"><a href="#" class="pure-menu-link">연락처</a></li>
  </ul>
</nav>
  • 경량화된 CSS 프레임워크로서, 기본적인 스타일링과 레이아웃 요소를 제공하고, 반응형 웹 디자인을 지원합니다.

Pros

  • 경량화(Lightweight): 크기가 매우 작아 웹 페이지의 로딩 속도를 향상시킵니다. 모든 모듈을 사용하더라도, 압축과 Gzip을 적용한 상태에서도 3.5KB로 매우 경량화되어 있습니다.
  • 모바일 최적화(Mobile Optimization): 모바일 기기에 최적화되어 있으며, 작은 파일 크기와 간결한 코드로 모바일 환경에서 성능을 향상시킵니다.
  • 간결화(Simplicity): 복잡하지 않고 직관적인 방식으로 사용할 수 있습니다.
  • 모듈화(Modularity): 다양한 모듈로 구성되어 있어 필요한 모듈만 선택하여 사용할 수 있습니다. 이는 필요한 기능에 맞게 커스터마이즈하고, 불필요한 코드를 제거하여 파일 크기를 더욱 줄일 수 있습니다.

Cons

  • 기능(functionality): 경량화를 위해 필요한 기능만을 제공하기 때문에 다른 CSS 프레임워크나 라이브러리에 비해 기능이 제한적일 수 있습니다.
  • 디자인 커스터마이징(Design customization): 간결한 디자인과 기본적인 스타일링을 제공하며, 디자인의 자유도나 다양성은 상대적으로 제한될 수 있습니다.

CSS-in-JS

Styled Components

  • JavaScript 파일 내에서 CSS 스타일을 태그명을 선언하며 정의할 수 있는 CSS-in-JS 라이브러리입니다.
// Create a Title component that'll render an <h1> tag with some styles
const Title = styled.h1`
  font-size: 1.5em;
  text-align: center;
  color: #BF4F74;
`;

// Create a Wrapper component that'll render a <section> tag with some styles
const Wrapper = styled.section`
  padding: 4em;
  background: papayawhip;
`;

// Use Title and Wrapper like any other React component – except they're styled!
render(
  <Wrapper>
    <Title>
      Hello World!
    </Title>
  </Wrapper>
);

Pros

  • 컴포넌트 스코프 스타일링(Component Scope Styling): 스타일은 고유한 스코프를 가지므로, CSS 클래스 이름 충돌을 방지하고 스타일이 예상대로 적용될 수 있도록 합니다.
  • 동적 스타일링(Dynamic Styling): JavaScript의 전체 기능을 활용하여 스타일을 동적으로 생성하고 적용할 수 있습니다.
  • 자동 벤더 접두사 추가(Automatic vendor prefixing): CSS 벤더 접두사를 추가하여 크로스 브라우징 이슈를 최소화합니다.
  • 서버 사이드 렌더링 지원(SSR support): 서버 사이드 렌더링을 지원하므로, 초기 페이지 로드 시간을 줄이고 SEO를 향상시킬 수 있습니다.
  • 기능(Functionality): ThemeProvidercreateGlobalStyle 같은 기능들을 활용할 수 있습니다.

Cons

  • 성능(Performance): 스타일이 런타임에 생성되고 적용되므로, 유저 인터랙션이 많을 경우 성능에 영향을 미칠 수 있습니다.
  • 가독성(Readability): CSS를 JavaScript 안에 작성하면 코드가 어색하게 보일 수 있고, CSS와 JavaScript가 혼합되면 코드를 이해하고 관리하는데 어려움이 있을 수 있습니다.

Emotion

  • JavaScript 파일 내에서 CSS 스타일을 정의할 수 있는 CSS-in-JS 라이브러리입니다.
  • styled-components처럼 사용할 수 있는 모듈도 제공합니다.
import { css } from '@emotion/css'

const color = 'white'

render(
  <div
    className={css`
      padding: 32px;
      background-color: hotpink;
      font-size: 24px;
      border-radius: 4px;
      &:hover {
        color: ${color};
      }
    `}
  >
    Hover to change color.
  </div>
)
import styled from '@emotion/styled'

const Button = styled.button`
  padding: 32px;
  background-color: hotpink;
  font-size: 24px;
  border-radius: 4px;
  color: black;
  font-weight: bold;
  &:hover {
    color: white;
  }
`

render(<Button>This my button component.</Button>)

Pros

  • 컴포넌트 스코프 스타일링(Component Scope Styling): 스타일은 고유한 스코프를 가지므로, CSS 클래스 이름 충돌을 방지하고 스타일이 예상대로 적용될 수 있도록 합니다.
  • 동적 스타일링(Dynamic Styling): JavaScript의 전체 기능을 활용하여 스타일을 동적으로 생성하고 적용할 수 있습니다.
  • 자동 벤더 접두사 추가(Automatic vendor prefixing): CSS 벤더 접두사를 추가하여 크로스 브라우징 이슈를 최소화합니다.
  • 서버 사이드 렌더링 지원(SSR support): 서버 사이드 렌더링을 지원하므로, 초기 페이지 로드 시간을 줄이고 SEO를 향상시킬 수 있습니다.
  • 기능(Functionality): ThemeProviderGlobal 같은 기능들을 활용할 수 있습니다.
  • 최적화(Optimization): 여러 최적화 기법을 사용하여 성능을 향상시킵니다. 예를 들어, 중복된 스타일을 자동으로 병합하고, 동적 스타일을 정적 스타일로 분리하는 등의 방법을 사용합니다.
  • 유연성(Flexibility): string 또는 object 스타일을 작성할 수 있습니다. 또한 prop에 기반한 스타일을 쉽게 작성할 수 있습니다.
  • CSS Sourcemap: 스타일이 정의된 위치를 쉽게 찾을 수 있습니다.
  • 레이블링(Labeling): 개발 모드에서 클래스 이름에 컴포넌트 이름을 추가하여 개발자 도구에서 디버깅을 쉽게 만들어줍니다.

Cons

  • 성능(Performance): 스타일이 런타임에 생성되고 적용되므로, 유저 인터랙션이 많을 경우 성능에 영향을 미칠 수 있습니다.
  • 가독성(Readability): CSS를 JavaScript 안에 작성하면 코드가 어색하게 보일 수 있고, CSS와 JavaScript가 혼합되면 코드를 이해하고 관리하는데 어려움이 있을 수 있습니다.

Styled JSX

  • JavaScript 파일 내에서 CSS 스타일을 정의할 수 있는 CSS-in-JS 라이브러리입니다
  • Next.js에 빌트인되어있어 Next.js 프로젝트에서 별도의 설치 없이 사용할 수 있습니다.
export default function ExampleComponent() {
  return (
    <div className="example">
      Hello, world!
      <style jsx>{`
        .example {
          color: blue;
        }
      `}</style>
    </div>
  );
}

Pros

  • 컴포넌트 스코프 스타일링(Component Scope Styling): 스타일은 고유한 스코프를 가지므로, CSS 클래스 이름 충돌을 방지하고 스타일이 예상대로 적용될 수 있도록 합니다.
  • 동적 스타일링(Dynamic Styling): JavaScript의 전체 기능을 활용하여 스타일을 동적으로 생성하고 적용할 수 있습니다.
  • 자동 벤더 접두사 추가(Automatic vendor prefixing): CSS 벤더 접두사를 추가하여 크로스 브라우징 이슈를 최소화합니다.
  • 서버 사이드 렌더링 지원(SSR support): 서버 사이드 렌더링을 지원하므로, 초기 페이지 로드 시간을 줄이고 SEO를 향상시킬 수 있습니다.
  • 전체 CSS 지원(Full CSS Support): 기존 CSS 문법을 그대로 사용할 수 있습니다.

Cons

  • 의존성(Dependency): Styled JSX는 React와 Next.js에 의존적이며, 다른 프레임워크나 라이브러리에서는 사용할 수 없습니다.
  • 가독성(Readability): CSS를 JavaScript 안에 작성하면 코드가 어색하게 보일 수 있고, CSS와 JavaScript가 혼합되면 코드를 이해하고 관리하는데 어려움이 있을 수 있습니다.

Linaria

  • JavaScript 파일 내에서 CSS 스타일을 정의할 수 있는 빌드 타임에 CSS 파일을 생성하는 Zero-runtime CSS-in-JS 라이브러리입니다
  • Emotion과 비슷하게 코드를 작성합니다.
import { css } from '@linaria/core';
import { modularScale, hiDPI } from 'polished';
import fonts from './fonts';

// Write your styles in `css` tag
const header = css`
  text-transform: uppercase;
  font-family: ${fonts.heading};
  font-size: ${modularScale(2)};

  ${hiDPI(1.5)} {
    font-size: ${modularScale(2.5)};
  }
`;

// Then use it as a class name
<h1 className={header}>Hello world</h1>;
import { styled } from '@linaria/react';
import { families, sizes } from './fonts';

// Write your styles in `styled` tag
const Title = styled.h1`
  font-family: ${families.serif};
`;

const Container = styled.div`
  font-size: ${sizes.medium}px;
  color: ${props => props.color};
  border: 1px solid red;

  &:hover {
    border-color: blue;
  }

  ${Title} {
    margin-bottom: 24px;
  }
`;

// Then use the resulting component
<Container color="#333">
  <Title>Hello world</Title>
</Container>;

Pros

  • 컴포넌트 스코프 스타일링(Component Scope Styling): 스타일은 고유한 스코프를 가지므로, CSS 클래스 이름 충돌을 방지하고 스타일이 예상대로 적용될 수 있도록 합니다.
  • 동적 스타일링(Dynamic Styling): Zero-runtime이지만 내부적으로 CSS 변수를 사용하고 있어서 CSS를 새로 만들지 않고 CSS 변수만 수정하여 스타일을 동적으로 생성하고 적용할 수 있습니다.
  • 자동 벤더 접두사 추가(Automatic vendor prefixing): CSS 벤더 접두사를 추가하여 크로스 브라우징 이슈를 최소화합니다.
  • 서버 사이드 렌더링 지원(SSR support): 서버 사이드 렌더링을 지원하므로, 초기 페이지 로드 시간을 줄이고 SEO를 향상시킬 수 있습니다.
  • Zero-runtime: 별도의 런타임 라이브러리 없이 작동하므로 번들 크기에 대한 부담이 줄어듭니다.
  • 성능(Performance): 런타임에 스타일을 생성하지 않기 때문에 성능이 뛰어납니다.
  • 전체 CSS 지원(Full CSS Support): 기존 CSS 문법을 그대로 사용할 수 있습니다.
  • React Binding: 동적 prop 기반 스타일 사용, 백그라운드에서 CSS 변수 사용이 가능합니다.
  • CSS Sourcemap: 스타일이 정의된 위치를 쉽게 찾을 수 있습니다.

Cons

  • 동적 스타일링 제한(Limited Dynamic Styling): 빌드 타임에 CSS를 추출하기 때문에, 런타임에 동적으로 스타일을 변경하는 것이 제한될 수 있습니다.
  • 설정(Setup): 다른 CSS-in-JS 라이브러리에 비해 설정이 더 복잡할 수 있습니다.
  • 가독성(Readability): CSS를 JavaScript 안에 작성하면 코드가 어색하게 보일 수 있고, CSS와 JavaScript가 혼합되면 코드를 이해하고 관리하는데 어려움이 있을 수 있습니다.

vanilla-extract

  • TypeScript와 JavaScript 파일 내에서 CSS 스타일을 정의할 수 있는 빌드 타임에 CSS 파일을 생성하는 Zero-runtime CSS-in-JS 라이브러리입니다

Pros

  • 컴포넌트 스코프 스타일링(Component Scope Styling): 스타일은 고유한 스코프를 가지므로, CSS 클래스 이름 충돌을 방지하고 스타일이 예상대로 적용될 수 있도록 합니다.
  • 동적 스타일링(Dynamic Styling): JavaScript의 전체 기능을 활용하여 스타일을 동적으로 생성하고 적용할 수 있습니다.
  • 자동 벤더 접두사 추가(Automatic vendor prefixing): CSS 벤더 접두사를 추가하여 크로스 브라우징 이슈를 최소화합니다.
  • 서버 사이드 렌더링 지원(SSR support): 서버 사이드 렌더링을 지원하므로, 초기 페이지 로드 시간을 줄이고 SEO를 향상시킬 수 있습니다.
  • 기능(Functionality): createThemeglobalStyle 같은 기능들을 활용할 수 있습니다.
  • Zero-runtime: 별도의 런타임 라이브러리 없이 작동하므로 번들 크기에 대한 부담이 줄어듭니다.
  • 성능(Performance): 런타임에 스타일을 생성하지 않기 때문에 성능이 뛰어납니다.
  • 타입 안전성(Type Safety): TypeScript와 통합되어 타입 안전성을 제공하여 스타일 오류를 컴파일 타임에 잡아내는 데 도움이 됩니다.

Cons

  • 동적 스타일링 제한(Limited Dynamic Styling): 빌드 타임에 CSS를 추출하기 때문에, 런타임에 동적으로 스타일을 변경하는 것이 제한될 수 있습니다.
  • 설정(Setup): 다른 CSS-in-JS 라이브러리에 비해 설정이 더 복잡할 수 있습니다.
  • 가독성(Readability): CSS를 JavaScript 안에 작성하면 코드가 어색하게 보일 수 있고, CSS와 JavaScript가 혼합되면 코드를 이해하고 관리하는데 어려움이 있을 수 있습니다.

결론

프로젝트의 특성과 요구사항에 따라 CSS 기술은 개발 생산성과 성능에 중점을 두고 선택하려 합니다. 기본적으로 React와 Next.js 프로젝트를 많이 경험할 것이라 예상합니다. 개인적으로 이미 만들어진 스타일인 Bootstrap과 같은 CSS 프레임워크는 번들 사이즈라던지 여러 모로 선호하지 않습니다. 다음은 저의 기준에 따른 CSS 기술 선택의 가이드라인입니다.

  • 소규모 프로젝트: 프로젝트가 단순하여 CSS-in-JS의 기능들이 필요하지 않고, 개발 생산성이 크게 떨어지지 않을 경우, 런타임 오버헤드 없이 작성할 수 있는 Vanilla CSS, CSS Preprocessors, CSS Modules 등을 활용하려 합니다.
  • 동적 스타일링이 적고 성능이 중요한 프로젝트: 유저 인터랙션이 많아 런타임 오버헤드가 성능에 영향을 줄 수 있는 프로젝트에서는, 프로젝트에 필요한 기능들을 가진 Zero-runtime CSS-in-JS 라이브러리 중에서 팀이 쉽게 익힐 수 있는 라이브러리를 선택하려 합니다.
  • 동적 스타일링이 많고 성능에 큰 영향을 미치지 않는 프로젝트: CSS-in-JS 중에서도 Styled-Components, Emotion, Styled-JSX 중에서 프로젝트에 필요한 기능이 가장 많고 팀이 쉽게 배울 수 있는 라이브러리를 선호합니다.
    • Emotion이 styled-components와 비슷한 기능을 제공하면서 더 우월한 것으로 보여, 개인적으로는 Emotion을 선호합니다.
    • Styled-JSX는 아직 써보지 않았지만 Next 프로젝트에서 경험해보고 불편함이 안느껴진다면 빌트인되어 있는 Styled-JSX도 고려해볼만 한 것 같습니다.
  • 동적 스타일링이 많고 성능도 중요한 프로젝트: CSS-in-JS 기술 중에서 성능 비교를 하고 학습 곡선을 고려하여 선택하려고 합니다.
  • CSS Postprocessors는 모던 CSS 라이브러리에 내장되어 있는 경우가 많은 것 같습니다.

Reference

profile
job's done

0개의 댓글