전처리기? 후처리기?

contability·2025년 10월 7일

전처리기? 후처리기?

CSS를 작성하다 보면 SCSS, PostCSS, Tailwind CSS 같은 용어들을 자주 접하게 된다. 이들이 무엇이고 왜 사용하는지, 그리고 어떤 관계인지 정리해보자.

1. 전처리기 (Preprocessor)

전처리기란?

CSS 전처리기는 브라우저가 이해하지 못하는 확장 문법으로 CSS를 작성하고, 빌드 타임에 순수 CSS로 변환하는 도구다. 대표적으로 SCSS/Sass, Less, Stylus 등이 있다.

"전(Pre) + 처리(Process)"라는 이름처럼, CSS를 생성하기 전에 미리 처리한다는 의미다.

// 작성: SCSS (브라우저가 이해 못함)
$primary-color: #3498db;
$spacing-unit: 8px;

.button {
  background: $primary-color;
  padding: $spacing-unit * 2;
  
  &:hover {
    opacity: 0.8;
  }
}
/* 컴파일 후: CSS (브라우저가 이해함) */
.button {
  background: #3498db;
  padding: 16px;
}

.button:hover {
  opacity: 0.8;
}

왜 전처리기를 사용하는가?

기본 CSS 문법으로는 불편한 부분들을 더 편하게 표현할 수 있다.

1. 변수 사용

색상, 폰트 크기, 간격 등을 변수로 관리할 수 있다. 일관된 디자인 시스템을 유지하고, 한 곳에서 값을 변경하면 전체에 반영된다.

$primary-color: #3498db;
$spacing-unit: 8px;

.button {
  background: $primary-color;
  padding: $spacing-unit * 2;
}

.card {
  border-color: $primary-color;
  margin: $spacing-unit;
}

2. 중첩 (Nesting)

HTML 구조를 반영하여 스타일을 중첩해서 작성할 수 있다. 가독성이 높아지고 선택자 반복을 줄일 수 있다.

.navigation {
  background: #333;
  
  ul {
    list-style: none;
    
    li {
      display: inline-block;
      
      a {
        color: white;
        text-decoration: none;
        
        &:hover {
          color: #3498db;
        }
      }
    }
  }
}

3. Mixins

재사용 가능한 스타일 블록을 만들 수 있다. 함수처럼 매개변수도 받을 수 있다.

@mixin flex-center {
  display: flex;
  justify-content: center;
  align-items: center;
}

@mixin box-shadow($color) {
  box-shadow: 0 2px 4px $color;
}

.container {
  @include flex-center;
  @include box-shadow(rgba(0, 0, 0, 0.1));
}

4. 파일 분할과 Import

스타일을 여러 파일로 나누고 조합할 수 있다. 컴포넌트별, 기능별로 관리하기 좋다.

@import 'variables';
@import 'mixins';
@import 'components/button';
@import 'components/card';
@import 'layout/header';

5. 연산

계산식을 사용하여 동적으로 값을 생성할 수 있다.

$base-spacing: 8px;

.sidebar {
  width: 100% / 3;
  padding: $base-spacing * 1.5;
  margin-top: $base-spacing / 2;
}

6. 함수와 제어문

조건문, 반복문 등을 사용하여 복잡한 스타일 로직을 구현할 수 있다.

@for $i from 1 through 5 {
  .margin-#{$i} {
    margin: #{$i}rem;
  }
}

// 생성 결과
// .margin-1 { margin: 1rem; }
// .margin-2 { margin: 2rem; }
// ...

실무적 장점

  • 유지보수성: 코드 중복이 줄어들고 수정이 용이하다
  • 확장성: 대규모 프로젝트에서 스타일을 체계적으로 관리할 수 있다
  • 생산성: 반복 작업을 줄이고 더 빠르게 작업할 수 있다
  • 팀 협업: 일관된 코딩 컨벤션을 적용하기 쉽다

전처리기가 필요 없는 경우

Tailwind CSS나 CSS-in-JS를 사용한다면 전처리기는 굳이 필요 없다. 전처리기의 장점(변수, 재사용, 중첩 등)을 이미 다른 방식으로 제공하기 때문이다.

Tailwind CSS 예시

// SCSS 없이 Tailwind만 사용
<button className="bg-primary px-4 py-2 hover:bg-primary-dark transition-opacity">
  버튼
</button>

CSS-in-JS 예시 (styled-components)

// SCSS 없이 styled-components 사용
const Button = styled.button`
  background: ${props => props.theme.colors.primary};
  padding: ${props => props.theme.spacing[2]};
  
  &:hover {
    opacity: 0.8;
  }
`;

2. 후처리기 (Postprocessor)

PostCSS란?

PostCSS는 이미 작성된 CSS를 JavaScript 플러그인으로 변환/처리하는 도구다.

전처리기: SCSS → CSS
PostCSS: CSS → 처리된 CSS

CSS가 작성된 후(Post)에 추가 처리를 하기 때문에 "후처리기"라고 부른다.

주요 PostCSS 플러그인

1. Autoprefixer

브라우저 호환성을 위한 벤더 프리픽스를 자동으로 추가한다.

/* 작성 */
.box {
  display: flex;
  transform: scale(1.5);
  user-select: none;
}

/* 처리 후 */
.box {
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
  -webkit-transform: scale(1.5);
  -ms-transform: scale(1.5);
  transform: scale(1.5);
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  user-select: none;
}

2. cssnano

CSS를 압축하고 최적화한다.

/* 작성 */
.box {
  color: #ffffff;
  margin: 10px 10px 10px 10px;
}

/* 처리 후 */
.box{color:#fff;margin:10px}

3. postcss-preset-env

미래의 CSS 문법을 현재 브라우저에서 사용 가능하게 변환한다.

/* 작성 (CSS Nesting - 미래 문법) */
.box {
  & .inner {
    color: red;
  }
}

/* 처리 후 (현재 브라우저 지원) */
.box .inner {
  color: red;
}

PostCSS 설정 예시

// postcss.config.js
module.exports = {
  plugins: {
    'postcss-import': {},           // CSS 파일 import 처리
    'postcss-nesting': {},          // CSS 중첩 문법 지원
    'tailwindcss': {},              // 유틸리티 클래스 생성
    'autoprefixer': {},             // 벤더 프리픽스 추가
    'cssnano': {},                  // CSS 압축
  }
}

왜 PostCSS를 사용하는가?

  1. 브라우저 호환성: 자동으로 벤더 프리픽스 추가
  2. 최적화: 압축, 중복 제거, 사용하지 않는 스타일 제거
  3. 미래 문법 사용: 최신 CSS 명세를 현재 사용 가능
  4. 확장성: 필요한 플러그인만 선택해서 사용

2-1. Tailwind CSS

Tailwind CSS와 PostCSS의 관계

Tailwind CSS는 PostCSS 플러그인으로 구현된 유틸리티 CSS 프레임워크다.

PostCSS = 플랫폼/엔진

  • CSS를 JavaScript로 조작할 수 있는 기반 시스템
  • 그 자체로는 아무 일도 안 한다
  • 플러그인을 통해 기능을 확장한다

Tailwind CSS = PostCSS 플러그인 중 하나

  • PostCSS 위에서 동작하는 특정 목적의 도구
  • "유틸리티 클래스 생성"이라는 명확한 목표가 있다

즉, Tailwind는 PostCSS라는 플랫폼을 이용해서 자신들의 목적에 맞는 도구를 만든 것이다.

Tailwind CSS 동작 방식

<!-- 작성: HTML 클래스 -->
<div class="bg-blue-500 p-4 hover:bg-blue-600"></div>
/* PostCSS 입력 */
@import "tailwindcss";
/* PostCSS (Tailwind 플러그인) 처리 후 */
.bg-blue-500 {
  background-color: #3b82f6;
}

.p-4 {
  padding: 1rem;
}

.hover\:bg-blue-600:hover {
  background-color: #2563eb;
}

Tailwind에서 커스텀 스타일 작성

Tailwind를 사용해도 복잡한 스타일이 필요할 때가 있다. 이때 SCSS 없이도 @layer 디렉티브로 해결할 수 있다.

/* global.css */
@import "tailwindcss";

@layer components {
  .custom-animation {
    animation: slide-in 0.3s ease-out;
  }
  
  .btn-primary {
    @apply bg-blue-500 text-white px-4 py-2 rounded hover:bg-blue-600;
  }
}

@layer utilities {
  @keyframes slide-in {
    from { transform: translateX(-100%); }
    to { transform: translateX(0); }
  }
}

Tailwind 4에서는 테마 변수도 간편하게 정의할 수 있다:

@theme {
  --color-primary: #3498db;
  --color-secondary: #2ecc71;
  --spacing-unit: 8px;
}

3. 전체 빌드 과정

CSS가 개발 환경에서 프로덕션까지 가는 전체 과정을 단계별로 살펴보자.

작성 → 전처리기 → CSS → 후처리기 → 최종 CSS → 브라우저

단계별 상세 과정

1단계: 개발자가 작성

개발자는 편의를 위해 SCSS 같은 전처리기 문법으로 스타일을 작성한다.

// src/styles/main.scss
$primary: #3498db;
$spacing: 8px;

.card {
  background: $primary;
  padding: $spacing * 2;
  
  .title {
    font-size: 1.5rem;
    
    &:hover {
      opacity: 0.8;
    }
  }
}

2단계: 전처리기 컴파일

빌드 도구(Webpack, Vite 등)가 SCSS를 순수 CSS로 변환한다.

/* 중간 결과: 컴파일된 CSS */
.card {
  background: #3498db;
  padding: 16px;
}

.card .title {
  font-size: 1.5rem;
}

.card .title:hover {
  opacity: 0.8;
}

3단계: PostCSS 처리

컴파일된 CSS를 PostCSS 플러그인들이 순차적으로 처리한다.

3-1. Autoprefixer (벤더 프리픽스 추가)

.card {
  background: #3498db;
  padding: 16px;
}

.card .title {
  font-size: 1.5rem;
}

.card .title:hover {
  opacity: 0.8;
}

3-2. cssnano (압축 및 최적화)

/* 최종 결과: 압축된 CSS */
.card{background:#3498db;padding:16px}.card .title{font-size:1.5rem}.card .title:hover{opacity:.8}

4단계: 브라우저 전달

최종 생성된 CSS 파일이 HTML에 연결되어 브라우저로 전달된다.

<!DOCTYPE html>
<html>
<head>
  <link rel="stylesheet" href="/dist/main.min.css">
</head>
<body>
  <div class="card">
    <h2 class="title">제목</h2>
  </div>
</body>
</html>

빌드 도구 설정 예시

실제 프로젝트에서는 빌드 도구가 이 과정을 자동화한다.

Webpack 설정

// webpack.config.js
module.exports = {
  module: {
    rules: [
      {
        test: /\.scss$/,
        use: [
          'style-loader',      // 3. CSS를 DOM에 주입
          'css-loader',        // 2. CSS를 JS로 변환
          'postcss-loader',    // 1-2. PostCSS 처리
          'sass-loader',       // 1-1. SCSS → CSS 컴파일
        ]
      }
    ]
  }
};

PostCSS 설정

// postcss.config.js
module.exports = {
  plugins: [
    require('autoprefixer'),    // 벤더 프리픽스 추가
    require('cssnano')({        // CSS 압축
      preset: 'default',
    }),
  ]
};

Vite 설정

// vite.config.js
import { defineConfig } from 'vite';

export default defineConfig({
  css: {
    preprocessorOptions: {
      scss: {
        // SCSS 옵션
      }
    },
    postcss: {
      plugins: [
        require('autoprefixer'),
        require('cssnano'),
      ]
    }
  }
});

실제 빌드 로그 예시

# npm run build 실행 시

✓ Building CSS...
  - Compiling SCSS files...           (전처리기)
  - Processing with PostCSS...        (후처리기)
    ├─ autoprefixer                   (브라우저 호환성)
    ├─ cssnano                        (압축)
    └─ purgecss                       (미사용 CSS 제거)
  
✓ Build complete!
  - main.css: 245 KB → 28 KB (88% 감소)

이렇게 여러 단계를 거쳐 개발자가 작성한 스타일이 최적화되어 브라우저로 전달된다.

결론

  • 전처리기 (SCSS): 편한 문법으로 작성 → CSS 생성
  • 후처리기 (PostCSS): 완성된 CSS → 최적화/변환/호환성 처리
  • Tailwind CSS: PostCSS 플러그인으로 구현된 유틸리티 CSS 프레임워크

현대 웹 개발에서는 Tailwind나 CSS-in-JS를 사용하면 전처리기가 필요 없고, PostCSS는 대부분의 프로젝트에서 자동으로 설정되어 백그라운드에서 동작한다.

0개의 댓글