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)를 사용해 전처리기의 핵심 기능을 학습합니다.
전처리기란 무엇이며 왜 필요한가?
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 -v와 npm -v를 입력하여 버전이 표시되는지 확인합니다.
(설치되어 있지 않다면 Node.js 공식 홈페이지에서 설치)
mkdir my-sass-project
cd my-sass-projectnpm init -y(package.json 파일이 생성됩니다.)
npm install -g sass # 전역 설치 (어디서든 sass 명령 사용 가능)
# 또는
npm install --save-dev 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) 핵심 기능
이제 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 */
.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;
}-
@extend는placeholder선택자(%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;
}