Currently viewing the human version
Switch to AI version

PostCSS가 뭔데 그렇게 난리야?

PostCSS는 2015년에 러시아 개발자 Andrey Sitnik이 Evil Martians에서 만든 CSS 후처리기다. 처음에는 "아 또 새로운 개소리냐? Sass도 제대로 못 쓰는데 또 뭘 배우라고?"라고 생각했는데, 어쩔 수 없이 써보니까 이게 진짜 미친 도구였다.

JavaScript로 CSS 조작한다는 미친 아이디어

Sass나 Less는 온갖 새로운 문법 배워야 하는 전처리기다. 근데 PostCSS는 그 반대다 - 이미 짜놓은 CSS 파일을 JavaScript로 마음대로 변형시킨다. 미친 짓 같지만 실제로는 엄청 합리적이다.

/* 입력 CSS */
.example {
  display: flex;
  user-select: none;
}

/* PostCSS + Autoprefixer 출력 */
.example {
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
  -webkit-user-select: none;
     -moz-user-select: none;
      -ms-user-select: none;
          user-select: none;
}

왜 PostCSS가 이렇게 난리인가?

진짜로 빠르다, 개빠름
Sass 컴파일 기다리다가 유튜브 쇼츠 3개 보던 시절이 있었는데, PostCSS로 바꾸니까 딴 거 할 시간도 없이 바로 끝남. 우리 회사 프로젝트에서 Sass 빌드가 2분 넘게 걸리던 게 PostCSS로 40초대로 줄었다. 처음엔 "어? 망가진 건가?" 했는데 진짜로 빨라진 거였다. Evil Martians 개발자들이 허풍쟁이가 아니었구나.

필요한 거만 골라 쓰면 됨
Sass는 variables부터 mixins까지 온갖 기능이 다 들어있어서 번들 크기가 개같다. PostCSS는 autoprefixer만 필요하면 autoprefixer만 깔고, nesting 필요하면 nesting plugin만 추가하면 끝. 단순하고 깔끔하다.

plugin 개많아서 뭘 써야 할지 모르겠음
PostCSS plugin이 200개가 넘는다. 처음에는 "우와 선택지 개많네"라고 좋아했는데, 막상 고르려니까 개빡침. 공식 plugin 목록 보면서 한나절 동안 플러그인 문서 뒤지다가 이것저것 깔았다가 지웠다가 반복하다가... 결국 autoprefixer랑 cssnano만 남았다. 나머지는 뭔지도 모르겠고, 필요할 때 추가하기로 했는데 아직까지 추가 안 했음.

실제로 뭐 할 수 있냐고?

가장 많이 쓰는 건 이런 것들이다:

  • IE 때문에 vendor prefix 자동으로 박아주는 autoprefixer - 이거 없으면 진짜 못 산다
  • 파일 크기 줄여주는 cssnano - 설정 잘못하면 CSS 깨지니까 조심해라
  • 미래 CSS 문법 쓸 수 있게 해주는 postcss-preset-env - CSS4 기능 미리 써볼 수 있음
  • Sass처럼 중첩 쓸 수 있는 postcss-nesting
  • 안 쓰는 CSS 제거해주는 postcss-purgecss - Tailwind 쓸 때 필수

솔직히 autoprefixer랑 cssnano만 써도 본전은 뽑는다. 나머지는 필요할 때 추가로 깔면 됨.

한국에서 PostCSS 쓰면 좋은 점들

IE11 때문에 미칠 것 같은 사람들한테 추천
공공기관이나 금융권 해본 사람들은 안다. IE11이 얼마나 엿같은지. flexbox 하나 제대로 안 되고, grid는 꿈도 못 꾸고, CSS 변수는 존재조차 모르는 브라우저. PostCSS + autoprefixer 깔면 vendor prefix는 알아서 처리해주고, flexbox 버그도 postcss-flexbugs-fixes로 해결된다. 진짜 생명의 은인이다.

빌드 기다리다 커피 식는 문제 해결
Sass 빌드 기다리다가 동료랑 수다 떨고 있으면 언제 끝날지 모르겠더라. PostCSS로 바꾸고 나니까 빌드 끝나는 소리 들을 시간도 없이 바로 끝남. 컴포넌트 100개 넘는 프로젝트에서 특히 차이가 크다.

CI/CD 설정할 때 골치 안 아픔
Jenkins 설정하거나 GitHub Actions 파일 만들 때 PostCSS는 그냥 npm install 하고 돌리면 끝이다. Sass처럼 Ruby 환경 맞춰야 하거나, 이상한 의존성 때문에 삽질할 일이 없다.

요즘 신규 프로젝트 만들면 거의 다 PostCSS다. Next.js, Nuxt.js, SvelteKit 전부 PostCSS 기본으로 깔려있고, Vite, Webpack 같은 번들러도 당연히 지원한다. Tailwind CSS 쓰려면 PostCSS 없으면 아예 안 돌아가고, CSS Modules도 PostCSS 기반이다. 이제 선택의 문제가 아니라 그냥 기본이다.

PostCSS vs Sass vs Less - 2025년 비교

기능

PostCSS

Sass

Less

언어

JavaScript

Dart (주), Ruby (구버전)

JavaScript

타입

후처리기

전처리기

전처리기

성능

개빠름

답답함 (빌드 기다리다 딴 일함)

뭐... 그냥

문법

표준 CSS + 확장

고유 문법 (.scss/.sass)

CSS-like 문법

변수

Plugin 필요

내장 ($var)

내장 (@var)

Nesting

Plugin 필요

내장

내장

Mixin

Plugin 필요

내장 (@mixin)

내장 (.mixin())

함수

Plugin 필요

내장 + 커스텀

내장 + 커스텀

조건문

Plugin 필요

내장 (@if/@else)

내장 (when())

반복문

Plugin 필요

내장 (@for/@each)

제한적

Autoprefixer

Plugin

별도 도구 필요

별도 도구 필요

CSS 최적화

cssnano

별도 도구 필요

별도 도구 필요

미래 CSS

preset-env

안됨

안됨

Ecosystem

200+ 공식 plugin

제한적

제한적

Webpack 통합

기본 지원

sass-loader

less-loader

Vite 통합

기본 지원

기본 지원

기본 지원

Next.js 통합

기본 엔진

추가 설정

추가 설정

Tailwind CSS

기본 방식

호환

호환

TypeScript 지원

완전 지원

완전 지원

완전 지원

Source Maps

완전 지원

완전 지원

완전 지원

개발자 도구

postcss-reporter

제한적

제한적

IDE 지원

VS Code 확장

VS Code 확장

VS Code 확장

러닝 커브

헷갈림 (플러그인 지옥)

개빡침 (문법 새로 배움)

쉬움

유지보수

활발함

활발함

글쎄... 누가 아직 쓰나?

대기업 사용

구글, 페북, 트위터

샵파이, 부트스트랩

앤트 디자인 (이거는 써본 적 없어서 모름)

PostCSS 실전 활용법 - 내가 삽질한 걸 다 털어놓음

PostCSS 도입하면서 겪은 멘탈붕괴와 야근을 다 정리했다. 금요일 밤 10시에 autoprefixer 때문에 IE에서 레이아웃 박살나서 새벽까지 삽질한 사람이면 공감할 거다.

"5분이면 된다"는 거짓말

1. 기본 설치

npm install -D postcss postcss-cli autoprefixer

2. postcss.config.js 생성

module.exports = {
  plugins: [
    require('autoprefixer')
  ]
}

3. 즉시 써먹을 수 있는 CSS

/* input.css */
.card {
  display: flex;
  user-select: none;
  backdrop-filter: blur(10px);
}

/* 자동으로 prefix 추가됨 */
.card {
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
  -webkit-user-select: none;
     -moz-user-select: none;
      -ms-user-select: none;
          user-select: none;
  -webkit-backdrop-filter: blur(10px);
          backdrop-filter: blur(10px);
}

현실적인 Plugin 구성 - 삽질 끝에 찾은 황금 조합

최소한 이것들은 깔아라 (모든 프로젝트)

module.exports = {
  plugins: [
    require('autoprefixer'),           // vendor prefix 자동 추가
    require('cssnano')({               // 프로덕션 최적화
      preset: 'default'
    })
  ]
}

좀 더 제대로 쓰려면 (프로덕션 프로젝트)

module.exports = {
  plugins: [
    require('postcss-import'),         // @import 처리
    require('postcss-nesting'),        // CSS nesting 지원
    require('postcss-custom-properties'), // CSS 변수 fallback
    require('autoprefixer'),
    require('cssnano')
  ]
}

대기업급 구성 (삽질 마스터용)

module.exports = {
  plugins: [
    require('postcss-import'),
    require('postcss-mixins'),         // Sass-like mixin
    require('postcss-simple-vars'),    // Sass-like 변수
    require('postcss-nesting'),
    require('postcss-preset-env')({    // 미래 CSS 기능
      stage: 0,
      features: {
        'nesting-rules': false // 중복 방지
      }
    }),
    require('autoprefixer'),
    process.env.NODE_ENV === 'production' ? require('cssnano') : null
  ].filter(Boolean)
}

주요 Framework별 통합

Next.js (기본 지원)

// next.config.js
module.exports = {
  experimental: {
    // PostCSS는 기본 활성화됨
  }
}

// postcss.config.js만 만들면 자동 적용

Vite

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

export default defineConfig({
  css: {
    postcss: './postcss.config.js'
  }
})

Webpack

// webpack.config.js
module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          'style-loader',
          'css-loader',
          'postcss-loader'  // postcss-loader 추가
        ]
      }
    ]
  }
}

한국 개발환경에서 자주 터지는 문제들

개발하다가 진짜로 멘붕온 경험들을 정리했다. 특히 IE11 때문에 밤샌 사람들은 공감할 거다.

1. IE11 지옥 - "IE 때문에 또 터졌다"
공공기관 프로젝트에서 IE11 때문에 3일 동안 삽질한 결과물이다. CSS 변수 쓸 때마다 IE에서 안 보이는 거 진짜 짜증났는데, 이렇게 해결했다:

// IE11 때문에 밤샌 결과물
module.exports = {
  plugins: [
    require('postcss-custom-properties')({
      preserve: true,
      fallback: true     // CSS 변수 fallback 생성
    }),
    require('autoprefixer')({
      overrideBrowserslist: ['> 0.5%', 'last 2 versions', 'IE 11']
    }),
    require('postcss-flexbugs-fixes')  // IE flexbox 버그 수정
  ]
}

2. 한글 폰트 로딩 지옥 - "왜 3초나 걸려?"
첫 로딩에 폰트 때문에 깜빡거리는 FOIT(Flash of Invisible Text) 현상. 특히 한글 폰트는 크기가 커서 더 심하다.

/* postcss-font-display plugin으로 해결 */
@font-face {
  font-family: 'Noto Sans KR';
  src: url('./fonts/NotoSansKR.woff2');
  /* 자동으로 font-display: swap; 추가됨 */
}

3. 빌드 성능 문제 - "왜 이렇게 느려?"
가끔 Node.js 버전 바뀌면서 PostCSS가 갑자기 느려지는 경우가 있다. 대용량 CSS 파일 처리할 때 메모리 부족으로 빌드가 터지는 경우도 있고:

Error: FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory

이런 에러 나면 node --max-old-space-size=8192 옵션으로 해결되긴 하는데, 근본적으로는 이런 식으로 설정하면 좀 나아진다:

// 대용량 CSS 때문에 멘탈 터졌을 때 쓰는 설정
module.exports = {
  plugins: [
    require('postcss-import')({
      skipDuplicates: true  // 중복 import 방지 (메모리 절약)
    }),
    require('postcss-url')({
      url: 'inline',
      maxSize: 10,          // 10kb 이하만 inline (용량 조절)
      fallback: 'copy'
    })
  ]
}

진짜 성능 어떤가? - 뻥 안 치고 실제 경험

빨라지긴 빨라진다. 우리 회사 프로젝트에서 Sass 빌드가 1분 10초 걸렸는데, PostCSS로 바꾸고 25초로 줄었다. Evil Martians가 성능 자랑하는 게 허풍이 아니었다.

근데 프로젝트마다 차이가 개판이다. 간단한 CSS 몇 개짜리 프로젝트면 별 차이 없고, 컴포넌트 500개 넘는 대형 프로젝트에서야 확실히 체감된다. 특히 Jenkins 같은 CI에서 빌드할 때 시간 차이가 확연하다.

자주 터지는 에러들과 해결법

Plugin 로딩 순서 문제

Error: Cannot read property 'forEach' of undefined
    at processor.process.plugins.forEach (/node_modules/postcss/lib/processor.js:36:35)

아 이거 진짜 짜증난다. postcss-import를 제일 위에 안 두고 중간에 껴넣어서 생기는 문제다. postcss-import는 무조건 첫 번째에 두고 다시 돌려봐라.

Windows 경로 문제

Error: PostCSS plugin postcss-import: Didn't find ./styles.css in [
    C:\Users\개발자\매우긴경로
ode_modules\...
]

Windows에서 PATH 길이 제한 때문에 터지는 경우가 있다. 프로젝트를 C:\dev 같은 짧은 경로로 옮기거나 절대경로로 바꿔라.

Plugin 버전 충돌

Error: Plugin "postcss-preset-env" requires PostCSS 8.1.0 but we have PostCSS 7.0.36

이거 진짜 짜증난다. npm ls postcss로 버전 확인하고 package.json에서 ^8.0.0으로 명시해라.

프로덕션 장애 경험담 - 진짜 실화
작년 12월에 cssnano 때문에 프로덕션에서 CSS 애니메이션이 전부 뒤져버린 적이 있다. cssnano가 우리 커스텀 keyframes를 "중복이네?" 하면서 알아서 삭제해버렸다. 금요일 6시에 배포하고 집에 갔는데 토요일 오전에 팀장한테 "애니메이션 다 망가졌는데 뭐 했냐?" 전화 받고 개빡침.

// 이 설정 때문에 주말에 회사 나가서 롤백함
cssnano({
  preset: ['default', {
    discardDuplicates: true  // 이 새끼가 문제였음
  }]
})

결국 discardDuplicates: false로 해결했는데, 그 2시간 동안 고객센터에서 "웹사이트 이상하다" 전화 폭탄 맞았다. 그날부터 프로덕션 배포는 목요일까지만 하기로 팀 룰 정했음.

DevOps 통합 팁

Jenkins Pipeline

stage('CSS Build') {
  steps {
    sh 'npm ci'
    sh 'npx postcss src/**/*.css --dir dist/'
  }
}

GitHub Actions

- name: Build CSS
  run: |
    npm ci
    npx postcss src/**/*.css --dir dist/

- name: Cache PostCSS
  uses: actions/cache@v3
  with:
    path: node_modules/.cache/postcss
    key: postcss-${{ hashFiles('postcss.config.js') }}

내가 실제로 쓰는 플러그인들

신규 프로젝트 (진짜 필수만)

  1. autoprefixer - 이거 없으면 IE 때문에 죽음
  2. cssnano - 번들 크기 때문에 필수
  3. postcss-preset-env - 미래 CSS 쓰고 싶으면
  4. postcss-import - 파일 분리 안 하면 코드 지옥

Sass에서 넘어갈 때

  1. postcss-simple-vars - $variable 그리운 사람들용
  2. postcss-nesting - 중첩 없으면 못 산다
  3. postcss-mixins - @mixin 중독자용
  4. postcss-sass - 점진적 이전 할 때

결론: PostCSS 쓸 만하다. Sass보다 빠르고, plugin도 많다. 단점은 처음에 뭘 깔아야 할지 몰라서 삽질하는 것. 그래도 한 번 설정하면 계속 우려먹을 수 있어서 투자 가치는 있다.

다만 팀에 Sass 고수가 있고, 기존 코드도 Sass로 멀쩡하게 돌아간다면 굳이 건드릴 필요 없다. "돌아가는 코드 건드리면 죽는다"는 개발자의 철칙을 잊지 말자.

PostCSS 자주 묻는 질문

Q

PostCSS vs Sass - 왜 갈아타야 함?

A

Sass 나쁘다는 거 아니다. 근데 PostCSS가 확실히 빠르다. Evil Martians 말이 거짓말이 아니었고, 실제로 써보니까 빌드 시간이 반토막 났다. 그리고 어차피 autoprefixer 같은 거 쓰려면 PostCSS 깔려있어야 해서 결국 둘 다 쓰게 된다. 그럼 처음부터 PostCSS로 통일하는 게 낫지 않냐?

Q

기존 Sass 프로젝트 PostCSS로 옮기는 게 현실적임?

A

가능하긴 하다. postcss-sasspostcss-scss plugin 깔면 기존 .scss 파일을 그대로 쓸 수 있다. 천천히 PostCSS plugin으로 갈아치우면 된다. 근데 mixin 엄청 많이 쓰는 프로젝트면 시간 좀 걸린다. 조급하게 하지 말고 여유롭게.

Q

IE11 지원됨?

A

당연히 된다. autoprefixerpostcss-custom-properties 조합으로 IE11까지 완벽하게 돌아간다. 공공기관이나 금융권 프로젝트에서도 문제없이 쓰고 있으니까 걱정 말아라.

Q

PostCSS 설정 복잡하지 않음?

A

처음엔 귀찮다. Sass는 모든 기능이 다 들어있어서 바로 쓸 수 있는데, PostCSS는 plugin 하나하나 골라야 한다. 근데 한 번 설정해두면 계속 우려먹을 수 있고, 쓸데없는 기능 안 깔아서 성능도 좋아진다.

Q

TypeScript와 함께 쓸 수 있어?

A

완전히 가능하다. PostCSS는 CSS를 처리하는 도구이고, TypeScript는 JavaScript를 처리하는 도구라서 충돌할 이유가 없다. Next.js + TypeScript + PostCSS 조합이 2025년 표준 스택이다.

Q

CSS-in-JS (styled-components, emotion)와 PostCSS를 함께 써도 되나?

A

된다. emotion은 내부적으로 PostCSS를 활용한다. styled-components도 PostCSS plugin과 함께 쓸 수 있다. 단, CSS-in-JS를 쓴다면 PostCSS의 장점이 줄어들 수 있다.

Q

Tailwind CSS와 PostCSS는 무슨 관계야?

A

Tailwind CSS는 PostCSS plugin으로 구현되어 있다. PostCSS 없이는 Tailwind를 쓸 수 없다. @tailwind base, @tailwind components 같은 directive들이 PostCSS로 처리된다.

Q

빌드 시간이 Sass보다 빠르다는 게 진짜야?

A

진짜다, 개빠름. 벤치마크도 있고 우리 프로젝트에서 실제로 체감했다. 다만 CSS 파일 3개짜리 토이 프로젝트면 별 차이 없다. 컴포넌트 100개 넘는 프로젝트에서 확실히 차이 난다.솔직히 처음엔 "어차피 거기서 거기 아니야?" 했는데 Jenkins에서 빌드 시간이 반으로 줄어드니까 CI/CD 전체 파이프라인이 빨라져서 배포할 때마다 기분이 좋다.

Q

PostCSS plugin 개발은 어려워?

A

생각보다 간단하다. CSS AST를 조작하는 방식이라 JavaScript 할 줄 안다면 금방 배울 수 있다. Plugin 개발 가이드도 잘 되어 있다.

Q

회사에서 PostCSS 도입 반대하면 어떻게 설득함?

A

아 이거 진짜 짜증난다. "기존 Sass 잘 돌아가는데 왜 또 새로운 거 배워야 하냐?" 이런 소리 개많이 들었다. 그럴 때는 "어차피 autoprefixer 쓰려면 PostCSS 깔려있다"고 말해라. "우리 이미 PostCSS 쓰고 있었다는거 알아?"라고 하면 당황함.그래도 안 되면 "Next.js, Tailwind, Vite 다 PostCSS다. 이거 안 쓰면 신기술 못 쓴다"고 해라. 보통 이때쯤 되면 관리자들이 "아 그래? 그럼 써라" 한다.진짜 완고한 팀이면 "새 프로젝트에서만 시험삼아 써보자"고 제안해라. 기존 코드 안 건드리니까 위험부담 없고, 빌드 속도 차이 한 번 보면 바로 납득한다.

Q

Webpack과 Vite 중에 어느 쪽이 PostCSS와 더 잘 맞아?

A

둘 다 PostCSS를 완벽 지원한다. Vite가 좀 더 빠르고 설정이 간단하지만, Webpack이 더 세밀한 제어가 가능하다. 프로젝트 규모와 팀 상황에 따라 선택하면 된다.

Q

PostCSS 러닝 커브가 높다는데?

A

plugin 생태계를 이해하는 데 시간이 걸릴 수 있다. 하지만 기본적인 autoprefixer + cssnano 조합으로 시작해서 점진적으로 plugin을 추가해나가면 된다. Sass 배우는 것보다는 쉽다.

Q

CSS Modules와 PostCSS는 어떤 관계야?

A

CSS Modules은 PostCSS plugin으로 구현된다. React나 Vue에서 CSS Modules 쓸 때 PostCSS가 뒤에서 돌고 있는 거다.

Q

프로덕션 환경에서 PostCSS 쓰기 안전해?

A

Google, Wikipedia, Tailwind 등 많은 주요 서비스들이 프로덕션에서 사용하고 있다. npm에서 매주 1억 회 이상 다운로드되고 있고, 주요 프레임워크들이 기본으로 쓰고 있으니까 안정성은 검증된 셈이다. 근데 솔직히 말하면 어떤 도구든 프로덕션에서 쓰기 전에는 충분히 테스트해봐야 한다.

Q

PostCSS를 안 써도 되는 경우는?

A

매우 간단한 정적 사이트나 CSS가 거의 없는 프로젝트라면 굳이 안 써도 된다. 하지만 대부분의 현대적인 웹 프로젝트에서는 PostCSS를 쓰는 게 이득이다.

Q

PostCSS 쓰면 Sass 파일들 다 갈아엎어야 함?

A

아니다. postcss-sass plugin 깔면 기존 .scss 파일 그대로 쓸 수 있다. 천천히 PostCSS로 이전하면 됨. 조급하게 하지 말고.

Q

기존 프로젝트에 몰래 적용할 방법 없음?

A

있다. autoprefixer부터 시작해라. 이건 이미 대부분 프로젝트에서 쓰고 있어서 아무도 모른다. 그 다음에 cssnano 추가하고, 빌드 속도 빨라진 걸 자랑해라.

Q

팀에서 반대하는데 어떻게 설득함?

A

"우리 이미 PostCSS 쓰고 있었다는 거 알아? autoprefixer가 PostCSS야"라고 해라. Next.js나 Tailwind 쓰고 있으면 더 쉽다. "이미 쓰고 있는데 활용 안 하는 게 더 바보 아니야?"

Q

Node 버전 바뀌면 또 터지나?

A

가끔 터진다. Node 18.2.0에서 PostCSS 메모리 문제 있었고, Node 16에서 17로 올릴 때도 plugin 호환성 문제 있었다. 그래서 Node 버전 올리기 전에 테스트 꼭 해봐라.

북마크 해둘 만한 링크들