본문으로 건너뛰기

안동민 개발노트

본문 시작

CSS 전처리기 (Sass) 입문

SCSS의 변수·중첩·믹스인·extend·부분 파일을 사용하고 컴파일 결과가 표준 CSS가 되는 흐름을 익힙니다.

우리는 지금까지 순수 CSS(Vanilla CSS)만으로 웹 페이지를 스타일링하고, 고급 기법으로 코드 효율을 높이는 방법을 학습했습니다.

CSS 변수와 calc() 함수는 CSS 유연성을 크게 향상시켰지만, 여전히 순수 CSS만으로는 대규모 프로젝트에서 반복 작업을 줄이거나 복잡한 로직을 처리하는 데 한계가 있습니다.

예를 들어, 반복되는 CSS 속성을 줄이거나 함수처럼 재사용 가능한 스타일 묶음을 만들고, 선택자를 중첩해 부모-자식 관계를 시각적으로 표현하는 것은 순수 CSS에서는 어렵습니다.

여기서 등장하는 것이 바로 CSS 전처리기(CSS Preprocessor)입니다.

CSS 전처리기는 CSS를 더 강력하게 만들어주는 스크립트 언어로, 작성한 코드를 컴파일(Compile)해 브라우저가 이해할 수 있는 표준 CSS로 변환해 줍니다.

이 덕분에 변수, 중첩, 믹스인(함수), 상속 같은 개념을 CSS에 도입해 개발 생산성과 유지보수성을 높일 수 있습니다.

가장 널리 사용되는 CSS 전처리기에는 Sass(Syntactically Awesome Style Sheets), Less, Stylus 등이 있습니다.

이 장에서는 Sass를 중심으로, 표준 CSS와 가장 유사한 문법을 가진 SCSS(Sassy CSS)를 사용해 전처리기의 핵심 기능을 학습합니다.

HTML 다이어그램: /docs/webBasic/ch4/ch4-4/1.html

전처리기란 무엇이며 왜 필요한가?

CSS 전처리기(CSS Preprocessor): CSS를 확장하는 스크립트 언어입니다.

개발자가 전처리기 문법으로 코드를 작성하면, 전처리기가 이를 일반적인 CSS 코드로 변환(컴파일)해 줍니다.

브라우저는 이 변환된 CSS 파일을 해석하여 웹 페이지를 렌더링합니다.

필요성

변수(Variables): 색상, 폰트 크기 등 자주 사용되는 값을 변수로 정의하여 한 곳에서 관리할 수 있습니다.

(순수 CSS 변수보다 기능이 강력하고 이전 버전의 브라우저도 지원)

중첩(Nesting): HTML 구조처럼 CSS 선택자를 중첩하여 작성할 수 있어 코드의 가독성이 향상됩니다.

믹스인(Mixins): 반복적으로 사용되는 CSS 속성 묶음을 함수처럼 정의하여 필요할 때마다 호출하여 사용할 수 있습니다.

상속(Inheritance) / 확장(Extend): 특정 선택자의 스타일을 다른 선택자에 상속시켜 코드 중복을 줄일 수 있습니다.

부분 파일(Partials) 및 임포트(Import): CSS 파일을 여러 작은 파일로 분리하고, 필요한 곳에서 @import 규칙으로 불러와 관리할 수 있습니다.

이는 SMACSS와 같은 CSS 아키텍처를 구현하는 데 매우 유용합니다.

연산(Operations): 사칙연산은 물론, 색상 함수 등 다양한 함수를 사용하여 복잡한 계산을 수행할 수 있습니다.


Sass (SCSS 문법) 설치 및 사용 준비

Sass는 Ruby 또는 Node.js 환경에서 실행됩니다.

현대 웹 개발에서는 Node.js 기반의 Dart Sass(sass 패키지)를 사용하는 것이 표준입니다.

구세대 Sass 구현체는 신규 프로젝트에서 사용하지 않는 것이 좋습니다.

설치 과정 (Node.js 및 npm 필요)

Node.js 설치 확인: 터미널/명령 프롬프트에서 node -vnpm -v를 입력하여 버전이 표시되는지 확인합니다.

(설치되어 있지 않다면 Node.js 공식 홈페이지에서 설치)

프로젝트 폴더 생성 및 이동
mkdir my-sass-project
cd my-sass-project
npm 프로젝트 초기화
npm init -y

(package.json 파일이 생성됩니다.)

Sass 컴파일러 설치
npm install -g sass # 전역 설치 (어디서든 sass 명령 사용 가능)
# 또는
npm install --save-dev sass # 프로젝트 내 설치 (프로젝트에서만 사용)

여기서는 편의상 전역 설치를 권장합니다.

Sass 컴파일 명령

SCSS 파일(*.scss)을 표준 CSS 파일(*.css)로 컴파일하는 기본적인 명령입니다.

sass input.scss output.css

자동 컴파일 (Watch Mode): 파일을 저장할 때마다 자동으로 컴파일되도록 watch 모드를 사용하는 것이 개발에 훨씬 편리합니다.

sass --watch input.scss:output.css
# 예시: sass --watch scss/main.scss:css/style.css

이 명령을 실행하면 터미널은 계속 대기 상태가 되고, input.scss 파일에 변경이 감지될 때마다 output.css를 자동으로 업데이트합니다.


Sass (SCSS) 핵심 기능

HTML 다이어그램: /docs/webBasic/ch4/ch4-4/2.html

이제 SCSS의 주요 기능들을 살펴봅시다.

변수 (Variables)

CSS 변수와 유사하지만, Sass 변수는 $foo: value; 형식으로 선언하며, 컴파일 시점에 값이 결정되어 브라우저 호환성을 신경 쓸 필요가 없습니다.

/* _variables.scss (보통 별도의 파일로 관리) */
$primary-color: #3498db;
$text-color: #333;
$font-stack: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
$base-padding: 15px;

/* style.scss */
body {
    font-family: $font-stack;
    color: $text-color;
    background-color: #f0f2f5;
}

.button {
    background-color: $primary-color;
    padding: $base-padding;
    color: white;
    border: none;
    border-radius: 5px;
}

중첩 (Nesting)

HTML 구조처럼 CSS 선택자를 중첩하여 작성하여 코드의 계층 구조를 명확하게 보여줍니다.

/* SCSS */
nav {
    ul {
        margin: 0;
        padding: 0;
        list-style: none;

        li {
            display: inline-block;
            margin-right: 10px;

            a {
                display: block;
                padding: 5px 10px;
                text-decoration: none;
                color: #333;

                &:hover { /* 부모 선택자(&) */
                    background-color: lightgray;
                }
            }
        }
    }
}

컴파일된 CSS:

/* CSS */
nav ul {
    margin: 0;
    padding: 0;
    list-style: none;
}
nav ul li {
    display: inline-block;
    margin-right: 10px;
}
nav ul li a {
    display: block;
    padding: 5px 10px;
    text-decoration: none;
    color: #333;
}
nav ul li a:hover {
    background-color: lightgray;
}
  • & (부모 선택자 참조): 중첩된 규칙 내에서 부모 선택자를 참조할 때 사용합니다. :hover, ::before 등 가상 클래스/요소나 클래스 조합 시 유용합니다.

믹스인 (Mixins)

재사용 가능한 CSS 코드 블록을 정의하는 기능입니다.

함수처럼 인자를 받아 동적인 스타일을 생성할 수도 있습니다.

@mixin으로 정의하고, @include로 사용합니다.

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

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

.container {
    @include flex-center; /* 믹스인 사용 */
    min-height: 200px;
    background-color: #f9f9f9;
}

.card {
    width: 200px;
    height: 150px;
    background-color: white;
    @include border-radius(10px); /* 인자와 함께 믹스인 사용 */
    box-shadow: 0 2px 5px rgba(0,0,0,0.1);
}

컴파일된 CSS:

/* CSS */
.container {
    display: flex;
    justify-content: center;
    align-items: center;
    min-height: 200px;
    background-color: #f9f9f9;
}

.card {
    width: 200px;
    height: 150px;
    background-color: white;
    -webkit-border-radius: 10px;
    -moz-border-radius: 10px;
    border-radius: 10px;
    box-shadow: 0 2px 5px rgba(0,0,0,0.1);
}
  • @mixin은 특히 벤더 프리픽스(vendor prefix)가 필요한 속성(transform, transition, animation 등)을 효율적으로 관리하는 데 매우 유용합니다.

상속/확장 (@extend)

하나의 선택자의 CSS 속성을 다른 선택자에게 상속시키는 기능입니다.

코드 중복을 줄이는 데 사용됩니다.

/* SCSS */
.message {
    padding: 10px;
    border: 1px solid #ccc;
    border-radius: 5px;
}

.message--success {
    @extend .message; /* .message의 모든 스타일을 상속받음 */
    background-color: #d4edda;
    color: #155724;
    border-color: #c3e6cb;
}

.message--error {
    @extend .message;
    background-color: #f8d7da;
    color: #721c24;
    border-color: #f5c6cb;
}
컴파일된 CSS
/* CSS */
.message, .message--success, .message--error { /* 선택자들이 그룹화됨 */
    padding: 10px;
    border: 1px solid #ccc;
    border-radius: 5px;
}

.message--success {
    background-color: #d4edda;
    color: #155724;
    border-color: #c3e6cb;
}

.message--error {
    background-color: #f8d7da;
    color: #721c24;
    border-color: #f5c6cb;
}
  • @extendplaceholder 선택자(%placeholder-name)와 함께 사용될 때 더 강력합니다. placeholder@extend될 때만 CSS로 컴파일되어 불필요한 클래스를 생성하지 않습니다.

    %common-button-style {
        padding: 10px 15px;
        border-radius: 5px;
        cursor: pointer;
    }
    
    .btn-submit {
        @extend %common-button-style;
        background-color: blue;
        color: white;
    }

부분 파일 (Partials) 및 임포트 (@import)

CSS 파일을 여러 개의 작은 모듈로 분리하여 관리하고, @import 규칙을 사용하여 다른 SCSS 파일로 가져올 수 있습니다.

부분 파일은 파일명 앞에 언더스코어(_)를 붙여서 명명합니다 (예: _variables.scss).

언더스코어는 해당 파일이 독립적으로 CSS로 컴파일되지 않고, 다른 SCSS 파일에 임포트될 용도로 사용됨을 의미합니다.

/* _variables.scss */
$font-size-base: 16px;
$color-main: #3498db;

/* _mixins.scss */
@mixin button-style {
    padding: 10px 20px;
    border-radius: 5px;
}

/* style.scss (메인 파일) */
@import 'variables'; /* _variables.scss 파일을 가져옴 (언더스코어 생략 가능) */
@import 'mixins';   /* _mixins.scss 파일을 가져옴 */

body {
    font-size: $font-size-base;
    color: $color-main;
}

.my-button {
    @include button-style;
    background-color: $color-main;
    color: white;
}

이러한 모듈화는 SMACSS와 같은 CSS 아키텍처를 구현하는 데 매우 효과적입니다.

연산 (Operations)

Sass는 숫자, 색상 등 다양한 타입의 값에 대한 산술 연산을 지원합니다.

/* SCSS */
$base-font-size: 16px;
$line-height: 1.5;
$margin-unit: 10px;

body {
    font-size: $base-font-size;
    line-height: $line-height;
}

.box {
    width: 100px + 50px; /* 150px */
    height: 200px / 2; /* 100px */
    padding: $margin-unit * 2; /* 20px */
    margin: $margin-unit - 5px; /* 5px */
    font-size: $base-font-size * 1.2; /* 19.2px */
}

/* 색상 연산 */
$color-primary: #3498db;
$color-darker: darken($color-primary, 10%); /* 더 어두운 색상 */
$color-lighter: lighten($color-primary, 15%); /* 더 밝은 색상 */

.header {
    background-color: $color-darker;
    color: white;
}
.footer {
    background-color: $color-lighter;
}

이어서 보기