Stylelint로 CSS 코드 품질 높이기

CSS 코드를 작성하다 보면 “이 속성 순서가 맞나?”, “컬러 값을 hex로 쓸까 rgb로 쓸까?”, “이 선택자는 너무 복잡한 거 아닌가?” 같은 고민을 하게 되는데요. 특히 여러 명이 함께 작업하는 프로젝트에서는 각자 선호하는 CSS 작성 스타일이 달라서 코드 리뷰 때마다 사소한 의견 차이로 시간을 낭비하기 일쑤입니다. 🤔

자바스크립트에는 ESLint라는 훌륭한 린터가 있어서 코드 품질을 자동으로 검사하고 일관된 스타일을 유지할 수 있는데요. CSS에도 이와 똑같은 역할을 해주는 도구가 있습니다. 바로 Stylelint입니다.

이번 글에서는 Stylelint가 무엇인지, 어떻게 설치하고 설정하는지, 그리고 실제 프로젝트에서 어떻게 활용할 수 있는지 차근차근 살펴보겠습니다.

Stylelint란 무엇인가?

Stylelint는 CSS를 위한 린터(linter)입니다. 린터는 소스 코드를 분석해서 잠재적인 오류, 버그, 스타일 위반 사항을 찾아내는 도구를 말하는데요. Stylelint는 CSS뿐만 아니라 SCSS, Sass, Less 같은 전처리기(preprocessor) 문법과 CSS-in-JS까지 폭넓게 지원합니다.

Stylelint를 사용하면 다양한 문제를 자동으로 감지할 수 있는데요. 오타나 잘못된 속성 이름 같은 실수를 잡아낼 수 있을 뿐만 아니라, 중복된 선택자나 덮어쓰기 문제까지 찾아냅니다. 접근성이나 성능에 영향을 줄 수 있는 패턴도 미리 경고해주기 때문에 팀 전체가 일관된 코딩 스타일을 유지하는 데 큰 도움이 됩니다.

ESLint가 자바스크립트 생태계에서 사실상 표준이 된 것처럼, Stylelint도 CSS 린팅 도구 중에서 가장 널리 쓰이고 있습니다. Google, GitHub, WordPress, Bootstrap 같은 유명 프로젝트들이 모두 Stylelint를 사용해서 CSS 코드 품질을 관리하고 있습니다.

Stylelint 설치하기

Stylelint는 npm 패키지로 제공되기 때문에 Node.js 기반 프로젝트라면 어디서든 쉽게 설치할 수 있습니다. 먼저 빈 프로젝트를 하나 만들고 Stylelint를 개발 의존성으로 설치해보겠습니다.

npm init -y
npm install -D stylelint stylelint-config-standard

여기서 stylelint는 린터 본체이고, stylelint-config-standard는 Stylelint에서 공식적으로 제공하는 추천 설정입니다. ESLint의 eslint:recommended 설정과 비슷한 역할을 한다고 보시면 됩니다.

설치가 끝나면 프로젝트 루트에 .stylelintrc.json 설정 파일을 만들어줍니다.

.stylelintrc.json
{
  "extends": ["stylelint-config-standard"]
}

이제 기본 설정이 완료되었습니다. 정말 간단하죠?

Stylelint 실행해보기

Stylelint가 어떻게 동작하는지 확인하기 위해 간단한 CSS 파일을 하나 만들어보겠습니다. 일부러 몇 가지 문제를 포함시켜서 Stylelint가 어떤 식으로 경고를 내는지 살펴보겠습니다.

style.css
.button {
  COLOR: #ff0000;
  padding: 10px;
  padding: 15px;
}

.button:hover {
  color: #00f;
}

#main-container {
  background-color: rgba(0, 0, 0, 0.5);
  width: 100%;
}

이제 터미널에서 Stylelint를 실행해봅니다.

npx stylelint "style.css"

그러면 다음과 같은 경고 메시지들이 출력됩니다.

결과
style.css
 2:3  Expected "color" to be "color"    property-case
 2:3  Unexpected unknown property "COLOR"  property-no-unknown
 4:3  Unexpected duplicate "padding"    declaration-block-no-duplicate-properties
 8:10  Expected "#00f" to be "#0000ff"    color-hex-length

Stylelint가 여러 문제를 찾아냈네요! 우선 2번 줄의 COLOR는 대문자로 쓰여서 property-case 규칙을 위반했습니다. CSS 속성은 소문자로 작성하는 것이 표준이거든요. 그리고 4번 줄에서는 padding 속성이 중복으로 선언되어 있어서 declaration-block-no-duplicate-properties 규칙에 걸렸습니다. 마지막으로 8번 줄의 #00f는 축약형 hex 컬러 코드인데, Stylelint 기본 설정에서는 전체 형식(#0000ff)을 권장합니다.

ESLint처럼 Stylelint도 자동 수정 기능을 제공합니다. --fix 옵션을 붙여서 실행하면 고칠 수 있는 문제는 자동으로 수정됩니다.

npx stylelint "style.css" --fix

파일을 다시 열어보면 대문자 속성이 소문자로 바뀌고, 축약된 컬러 코드가 전체 형식으로 변환되어 있을 겁니다. 다만 중복된 padding 속성 같은 경우는 자동으로 제거할 수 없기 때문에 개발자가 직접 수정해야 합니다.

설정 파일 자세히 알아보기

Stylelint 설정 파일은 ESLint와 비슷한 구조를 가지고 있습니다. .stylelintrc.json, .stylelintrc.js, .stylelintrc.yaml 같은 형식으로 만들 수 있고, package.json 파일의 stylelint 속성에 설정을 넣을 수도 있습니다.

가장 기본적인 설정 옵션들을 하나씩 살펴보겠습니다.

extends 옵션

extends 옵션은 기존에 만들어진 설정을 가져와서 기반으로 사용할 때 씁니다. 처음부터 모든 규칙을 일일이 설정하는 건 너무 번거롭기 때문에 대부분 공개된 설정을 확장해서 사용합니다.

.stylelintrc.json
{
  "extends": ["stylelint-config-standard"]
}

stylelint-config-standard 외에도 다양한 공개 설정이 있습니다. 예를 들어 SCSS를 사용한다면 stylelint-config-standard-scss를, CSS-in-JS를 쓴다면 stylelint-config-styled-components 같은 설정을 사용할 수 있습니다.

plugins 옵션

플러그인은 Stylelint의 기본 규칙 외에 추가 규칙을 사용하고 싶을 때 설치합니다. 예를 들어 CSS 속성 순서를 자동으로 정렬하고 싶다면 stylelint-order 플러그인을 사용할 수 있습니다.

npm install -D stylelint-order
.stylelintrc.json
{
  "extends": ["stylelint-config-standard"],
  "plugins": ["stylelint-order"],
  "rules": {
    "order/properties-alphabetical-order": true
  }
}

이렇게 설정하면 CSS 속성들이 알파벳 순서대로 정렬되어 있지 않으면 경고를 내게 됩니다.

rules 옵션

rules 옵션은 개별 규칙을 세밀하게 제어할 때 사용합니다. 기본 설정에서 제공하는 규칙을 덮어쓰거나 완전히 끌 수 있습니다.

.stylelintrc.json
{
  "extends": ["stylelint-config-standard"],
  "rules": {
    "color-hex-length": "short",
    "selector-class-pattern": "^[a-z][a-zA-Z0-9]*$",
    "declaration-no-important": true
  }
}

위 설정은 hex 컬러 코드를 축약형(#fff)으로 쓰도록 강제하고, 클래스 이름은 camelCase 패턴을 따르도록 하며, !important 사용을 금지합니다.

규칙 값으로는 true, false, null 외에도 문자열이나 배열을 넘길 수 있습니다. 각 규칙마다 허용하는 옵션이 다르므로 Stylelint 공식 문서를 참고하시면 좋습니다.

ignoreFiles 옵션

린트를 실행할 때 제외하고 싶은 파일이나 디렉터리가 있다면 ignoreFiles 옵션을 사용합니다.

.stylelintrc.json
{
  "extends": ["stylelint-config-standard"],
  "ignoreFiles": ["node_modules/**", "dist/**", "build/**"]
}

또는 .stylelintignore 파일을 만들어서 무시할 경로를 나열할 수도 있습니다. .gitignore 파일과 똑같은 문법을 사용합니다.

.stylelintignore
node_modules
dist
build
*.min.css

NPM 스크립트로 등록하기

매번 터미널에서 npx stylelint 명령어를 입력하는 건 번거롭습니다. package.json 파일에 스크립트를 추가해두면 훨씬 편리하게 사용할 수 있습니다.

package.json
{
  "scripts": {
    "lint:css": "stylelint \"**/*.css\"",
    "lint:css:fix": "stylelint \"**/*.css\" --fix"
  }
}

이제 npm run lint:css 명령으로 프로젝트 전체의 CSS 파일을 검사할 수 있고, npm run lint:css:fix로 자동 수정까지 한 번에 처리할 수 있습니다.

만약 SCSS나 다른 전처리기를 사용한다면 패턴을 그에 맞게 수정하면 됩니다.

package.json
{
  "scripts": {
    "lint:css": "stylelint \"**/*.{css,scss}\"",
    "lint:css:fix": "stylelint \"**/*.{css,scss}\" --fix"
  }
}

Git 훅으로 강제하기

팀 프로젝트에서는 모든 개발자가 코드를 커밋하기 전에 Stylelint를 실행하도록 강제하는 것이 좋습니다. 그래야 스타일이 통일되지 않은 CSS가 코드베이스에 섞이는 걸 막을 수 있거든요.

ESLint 포스팅에서 소개했던 것처럼 huskylint-staged를 사용하면 Git 커밋 시점에 자동으로 린트를 실행할 수 있습니다.

npm install -D husky lint-staged
npx husky init

그다음 .husky/pre-commit 파일을 만들어줍니다.

.husky/pre-commit
#!/usr/bin/env sh
npx lint-staged

마지막으로 package.json 파일에 lint-staged 설정을 추가합니다.

package.json
{
  "lint-staged": {
    "*.css": "stylelint --fix"
  }
}

이제 CSS 파일을 수정하고 git commit을 실행하면 자동으로 Stylelint가 돌아가고, 문제가 발견되면 커밋이 거부됩니다. 💥

실제로 테스트해보겠습니다. 일부러 잘못된 CSS를 작성하고 커밋을 시도해보면 다음과 같이 오류가 발생합니다.

결과
$ git add .
$ git commit -m "Add button styles"

 Preparing lint-staged...
 Running tasks for staged files...
 package.json 1 file
 *.css 1 file
 stylelint --fix [FAILED]
 Skipped because of errors from tasks.
 Reverting to original state because of errors...
 Cleaning up temporary files...

 stylelint --fix:

style.css
 2:3  Unexpected duplicate "padding"    declaration-block-no-duplicate-properties

1 problem (1 error, 0 warnings)

중복된 padding 속성을 제거하고 다시 커밋하면 이번에는 성공합니다.

ESLint, Prettier와 함께 사용하기

실제 프로젝트에서는 JavaScript 린팅을 위해 ESLint를, 코드 포맷팅을 위해 Prettier를 함께 사용하는 경우가 많습니다. Stylelint도 이 도구들과 매끄럽게 통합할 수 있습니다.

Prettier와 충돌을 피하려면 stylelint-config-prettier를 설치합니다. 이 설정은 Prettier와 겹치는 Stylelint 규칙들을 꺼주는 역할을 합니다.

npm install -D stylelint-config-prettier
.stylelintrc.json
{
  "extends": [
    "stylelint-config-standard",
    "stylelint-config-prettier"
  ]
}

extends 배열에서 stylelint-config-prettier를 맨 마지막에 두는 것이 중요합니다. 그래야 다른 설정의 규칙들을 제대로 덮어쓸 수 있거든요.

이제 Prettier는 코드 포맷팅(들여쓰기, 줄바꿈, 공백 등)을 담당하고, Stylelint는 CSS 문법과 패턴 검사를 담당하도록 역할이 분리됩니다. ESLint와 Prettier를 함께 쓰는 방식과 정확히 같은 구조입니다.

VS Code 확장 프로그램

터미널에서 매번 명령어를 실행하는 것보다 코드 편집기에서 실시간으로 경고를 보여주면 훨씬 편리하겠죠? VS Code를 사용한다면 공식 Stylelint 확장 프로그램을 설치하는 것을 강력히 권장합니다.

VS Code 마켓플레이스에서 “Stylelint”를 검색하거나 이 링크에서 직접 설치할 수 있습니다.

설치 후 VS Code 설정(settings.json)에 다음 항목을 추가하면 파일을 저장할 때마다 자동으로 수정이 적용됩니다.

settings.json
{
  "editor.codeActionsOnSave": {
    "source.fixAll.stylelint": true
  },
  "stylelint.validate": ["css", "scss"]
}

이제 CSS 파일을 편집하면 실시간으로 밑줄이 그어지면서 문제를 알려주고, 저장하는 순간 자동으로 고쳐집니다. 정말 편리하죠! 👍

SCSS와 CSS-in-JS 지원

Stylelint는 순수 CSS뿐만 아니라 SCSS, Sass, Less 같은 전처리기와 styled-components, Emotion 같은 CSS-in-JS 라이브러리까지 지원합니다.

SCSS를 사용한다면 stylelint-config-standard-scss를 설치하면 됩니다.

npm install -D stylelint-config-standard-scss
.stylelintrc.json
{
  "extends": ["stylelint-config-standard-scss"]
}

이 설정은 stylelint-config-standard를 기반으로 하면서 SCSS 전용 규칙들을 추가로 제공합니다. 예를 들어 @mixin, @include, @extend 같은 SCSS 문법을 올바르게 검사할 수 있습니다.

styled-components를 사용하는 React 프로젝트라면 다음 패키지들을 설치합니다.

npm install -D stylelint-config-styled-components stylelint-processor-styled-components
.stylelintrc.json
{
  "processors": ["stylelint-processor-styled-components"],
  "extends": [
    "stylelint-config-standard",
    "stylelint-config-styled-components"
  ]
}

이제 JavaScript 파일 안에 있는 CSS 코드도 Stylelint가 검사할 수 있습니다.

유용한 규칙 모음

Stylelint는 수백 가지 규칙을 제공하는데요. 그중에서도 실제로 유용하게 쓸 수 있는 규칙 몇 가지를 소개하겠습니다.

색상 표기법 통일하기

프로젝트에서 색상을 hex로 쓸지 rgb로 쓸지 통일하고 싶다면 다음 규칙을 사용합니다.

{
  "rules": {
    "color-named": "never",
    "color-no-hex": true
  }
}

color-named: "never"red, blue 같은 이름 있는 색상 사용을 금지하고, color-no-hex: true는 hex 컬러 코드 사용을 금지합니다. 이렇게 하면 모든 색상을 rgb() 또는 rgba()로만 작성하게 됩니다.

선택자 복잡도 제한하기

지나치게 복잡한 선택자는 CSS 성능과 유지보수에 악영향을 미칩니다. 선택자의 깊이를 제한하고 싶다면 다음 규칙을 씁니다.

{
  "rules": {
    "selector-max-specificity": "0,4,0",
    "selector-max-compound-selectors": 3,
    "selector-no-qualifying-type": true
  }
}

selector-max-compound-selectors: 3은 선택자를 3단계까지만 허용합니다. 예를 들어 .header .nav .menu .item처럼 4단계로 중첩된 선택자는 경고를 받게 됩니다.

속성 순서 정렬하기

CSS 속성을 항상 일정한 순서로 정렬하면 코드를 읽기 훨씬 쉬워집니다. stylelint-order 플러그인을 사용하면 속성 순서를 강제할 수 있습니다.

npm install -D stylelint-order stylelint-config-recess-order
.stylelintrc.json
{
  "extends": ["stylelint-config-standard", "stylelint-config-recess-order"]
}

stylelint-config-recess-order는 Bootstrap과 같은 프로젝트에서 사용하는 속성 순서 규칙을 제공합니다. 포지셔닝 관련 속성을 먼저 쓰고, 박스 모델, 타이포그래피, 시각 효과 순서로 정렬됩니다.

CI에서 Stylelint 실행하기

로컬에서 Stylelint를 강제하는 것도 중요하지만, GitHub Actions나 GitLab CI 같은 CI 환경에서도 검사를 돌려야 완벽한 품질 관리가 가능합니다. 개발자가 Git 훅을 우회하거나 실수로 건너뛸 수 있기 때문이죠.

GitHub Actions를 사용한다면 .github/workflows/lint.yml 파일을 만들어줍니다.

.github/workflows/lint.yml
name: Lint

on: [push, pull_request]

jobs:
  stylelint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-node@v3
        with:
          node-version: '18'
      - run: npm ci
      - run: npm run lint:css

이제 코드를 푸시하거나 Pull Request를 만들 때마다 자동으로 Stylelint가 실행되고, 문제가 있으면 CI가 실패하면서 머지를 막아줍니다.

마치며

지금까지 Stylelint를 사용해서 CSS 코드 품질을 높이는 방법을 살펴봤습니다. Stylelint를 도입하면 오타나 실수를 조기에 발견할 수 있고, 팀 전체가 일관된 CSS 스타일을 유지할 수 있으며, 코드 리뷰에서 스타일 논쟁에 시간을 낭비하지 않아도 됩니다.

처음에는 설정이 번거롭게 느껴질 수도 있지만, 한번 셋업해두면 그 이후로는 자동으로 코드 품질이 관리되기 때문에 투자할 만한 가치가 충분합니다. 특히 ESLintPrettier와 함께 사용하면 자바스크립트부터 CSS까지 프로젝트 전체의 코드 품질을 체계적으로 관리할 수 있습니다.

CSS 코드 품질이 고민이라면 지금 당장 Stylelint를 프로젝트에 추가해보시는 건 어떨까요? 생각보다 훨씬 쉽게 시작할 수 있을 겁니다. 😊

This work is licensed under CC BY 4.0 CC BY

Discord