본 강의자료는 '처음 시작하는 Sass'를 상당부분 인용하였습니다. 저자 분들께 이 지면을 빌어 고마움을 전합니다. 이 도서는 본 강의보다 심화적인 내용을 담고 있으므로 읽어보시면 Sass를 보다 잘 이해하는데 도움이 됩니다. (본 강사는 해당 출판사와 아무런 관련이 없습니다.)
그럼, 이제부터 Sass에 대해 함께 알아보겠습니다. (이하 경어체를 생략합니다.)
이해하기
서문
문서를 꾸미는 보조 역할을 하던 CSS는 시간이 지날수록 웹 개발에서 중요한 역할을 차지하게 됐다. 특히 CSS2 이후 오랜 공백을 깨고 CSS3가 등장하면서 CSS를 통해 더욱 많은 표현이 가능하게 된 것이 큰 계기가 되었다. 배경 이미지를 자르고 구조를 나누어 표현했던 둥근 테두리는 속성 하나로 손쉽게 적용할 수 있게 되었으며, Javascript나 서버 단에 의지했던 수많은 선택자도 CSS3 이후에는 CSS만으로 처리할 수 있게 되었다.
하지만 여전히 스타일을 정의하고 속성을 적용하는 방식은 매우 단순한 수준에 머무르고 있어, 반복되는 코드의 입력을 줄이려는 여타 개발 언어들과는 사뭇 다른 아쉬움을 남기고 있다. 특히 과거와 다르게 CSS의 활용 범위가 커지고 웹 사이트의 규모가 거대해지면서 1,000 라인쯤은 쉽게 넘기는 코드가 작성되고 있으며, 이에 따라 이 코드들을 더욱 효율적으로 관리해야 할 필요성이 강조되고 있다.
다행히 이러한 안타까운 현실에서 웹 개발자를 구원해줄 한 줄기 빛이 생겨났는데, Sass를 필두로 좀 더 편리하고 효율적으로 CSS를 작성 할 수 있도록 도움을 주는 전처리기들이 바로 그 구원자들이다. 그 가운데서도 Sass는 가장 큰 인기를 얻고 있으며 많은 웹 개발자의 찬사를 받고 있다.
정대영. 처음 시작하는 Sass. p.5, 한빛미디어, 2016.
CSS 전처리기
Sass는 CSS 전처리기(preprocessor)의 한 종류이다. CSS 전처리기는 변수, 함수, 상속 등의 일반적인 프로그래밍 개념을 사용하여 코드를 작성한 뒤 기존 CSS 문법으로 컴파일 해주는 방식을 취한다. Sass 문법에 맞추어 .scss 파일을 작성한 뒤 컴파일 명령문을 통해 브라우저가 이해할 수 있는 .css가 컴파일 되는 방식이다. 전처리기로는 Sass, Less, Stylus가 있지만 본 강의에서는 Sass만 다룬다.
기본 Sass 스타일로 아무런 옵션을 설정하지 않았다면 nested 스타일로 컴파일 된다. Sass 파일에서 대괄호로 그룹핑 한 가장 첫 번째 선택자를 기준으로 들여쓰기 되기 때문에 html 파일을 확인하지 않고도 어떤 구조인지 쉽게 알 수 있으며, 각 속성은 한 줄 씩 컴파일된다.
--cache는 Sass 템플릿 작업 및 여러 import 파일들을 더욱 빠르게 처리할 수 있도록 캐시된 파일을 보관하는 옵션이다. Sass의 기본 옵션으로 컴파일을 하면 .sass-cache라는 폴더가 자동 생성되고 관련 cache 파일이 저장된다.
--cache 옵션 제거하기
만약 이 옵션을 제거하기를 원한다면 맨 처음 컴파일 할 때부터 다음과 같이 명령문을 입력해 주면 된다.
sass --watch input.scss:output.css --no-cache
시작하기
프로젝트 규모가 커지고 오랜 유지 보수 기간을 거칠수록 CSS 코드 역시 거대해지는 경우가 많다. 복잡한 선택자와 무수한 속성, 그리고 다양한 값 사이에는 분명 명확하게 명시되지 않은 규칙이 많을 것이고, 이것은 CSS의 로직을 더욱 파악하기 어렵게 만든다. 심지어 CSS 파일 하나에 엄청나게 긴 코드가 있는데 짤막한 주석으로 코드 그룹을 분리한다면 코드의 구성을 파악하기는 여간 쉽지 않을 것이다.
여기서 다행인 점은 Sass는 의미 있고 간결한 CSS 코드 작성을 가능하게 해준다는 것이다. 선택자를 간단하면서도 짜임새 있게 표현할 수 있고 값 사이의 규칙을 작성할 수 있으며 모듈화 한 CSS를 여러 파일로 나누어 관리할 수도 있다.
CSS에는 현재 파일에 다른 CSS 파일을 불러오는 @import라는 속성이 있다. 이 속성을 사용하면 의도에 따라 코드를 잘게 쪼개어 효율적으로 유지 보수할 수 있는 방법을 찾을 수 있다. 하지만 @import로 선언되어 있는 CSS마다 http 요청을 발생하므로 웹 페이지 성능 저하의 원인이 된다 하여 사용을 지양하고 있다.
Sass에도 다른 파일을 불러올 수 있는 @import가 있다. CSS의 @import와 다른 점은 Sass 파일은 @import가 선언된 부모 Sass 파일을 단 하나의 CSS로 생성할 수 있다는 점이다. 이 방법을 사용하면 CSS 파일 하나만 작성한 듯한 효과를 주고 동시에 성능에 영향을 주지 않고 코드를 여러 파일로 나누어 관리할 수도 있다. 물론 import 된 파일에서 정의된 내용은 부모 Sass 파일에서도 사용할 수 있다.
여러 파일을 import 할 때에는 선언한 순서와 동일하게 CSS 코드가 생성되기 때문에 CSS 우선순위를 고려하여 선언하도록 한다.
_espresso.scss와 같은 형태로 파일명 앞에 _(언더바)를 붙이면 해당 파일은 .css로 컴파일하지 않는다.
중첩 규칙
Sass는 HTML을 작성하듯이 선택자의 정의 안에 자식 선택자를 정의할 수 있다. 이와 같은 중첩 규칙으로 Sass를 작성한다면 부모 선택자가 반복해서 작성하지 않아도 되기 때문에 중첩이 많아지더라도 코드의 레이아웃을 간결하게 해준다. 중첩이 깊어지더라도 코드의 레이아웃을 보다 깔끔하게 해주어 가독성이 높아지므로 CSS를 정리하기도 편리해 진다.
Sass를 처음 사용할 때 가장 흥미를 느낄 수 있는 부분이 바로 중첩이다. 적용하기 편하고 규칙이 단순해 보이기 때문이다. 그렇기 때문에 남용되기 쉬워 불필요 한 코드가 증가하는 문제점도 있다. 중첩의 사용은 생성된 선택자의 형태를 고려하여 사용하는 것이 중요하다. 자칫 무분별하게 중첩을 사용하면 불필요한 선택자가 생성되기 때문이다.
본격적으로 사용하기
변수
데이터 타입
숫자
1, 10px
문자열
'americano', "latte", cappuccino
색상
blue, #000000, rgba(0,0,0,.5)
불리언
true, false
널
Null
리스트
1px 2px 0 1px (값과 값 사이를 공백으로 구분)
helvetica, arial, sans-seriff (값과 값 사이를 콤마','로 구분)
맵
Key1:value1, key2:value2
변수 알아보기
변수는 할당한 값을 CSS 파일로 출력하는 것을 말한다. 변수는 CSS와 비교하여 Sass의 편리한 점 중 하나이다. Sass에서 변수 선언은 $기호를 붙여 $변수명:변수값과 같은 형태로 선언하면 된다. 프로젝트에서 공통으로 사용하는 컬러값이나 기본폰트가 설정되어 있지만 몇몇 요소에서 재선언하여 사용해야하는 폰트 값에 사용할 수 있을 것이다. 그 외에도 변수는 무궁무진하게 활용된다.
제작하려는 사이트에 주로 사용하게 되는 메인 컬러가 있다고 해 보자. CSS에서는 메인 컬러가 사용되는 여러 곳에 작성을 해줘야 할 것이다. 그러다 이런저런 이유로 메인 컬러가 변경되었다면 CSS에서는 사용된 곳을 찾아 가면서 일일이 컬러를 바꿔줘야 한다. (물론 한 번에 찾아 바꾸기를 할 수도 있다.)
Sass에서는 메인 컬러를 변수에 담아 사용하는 곳에 컬러 값 대신 변수를 선언해 준다. 메인 컬러가 변경된다면 변수를 선언한 곳에서 컬러 값만 변경해 주면 파일을 일일이 뒤지지 않고도 손쉽게 메인컬러를 변경할 수 있다. 이렇게 변수는 유지 관리를 편리하게 만들어 주는 이점이 있다.
$color-basic이라는 변수에 컬러 값을 담아 여러 곳에서 다양하게 사용했다. 변수와 별개로 Sass의 기능 중 하나인 darken, lighten 기능을 활용하면 컬러에 다양한 변화를 주어 사용할 수 있다. 또한 RGB 값을 일일이 쓰지 않고 컬러 값만 입력해도 알아서 변환된다.
지역 변수와 전역 변수
변수의 유효 범위는 정의한 선택자 중첩 안에서 제한된다. 선택자 안에 선언됐다면 지역변수, 아무 중첩에도 속하지 않았다면 파일 어느 곳에서든지 사용할 수 있는 전역 변수가 된다.
.cappuccino 안에서 $size 변수에 값을 지정하니 오류 없이 컴파일 된다. .latte 안에 정의한 $size: 12px이라는 값은 .cappuccino에 영향을 주지 않고 .cappuccino에 정의한 값은 .latte에 영향을 주지 않는다.
interpolation: #{ }
변수를 선택자와 속성 사이에서 사용하는 경우가 많다. 그때 $variable-name으로 그대로 적용하면 오류가 발생할 수 있다. 변수 주위에 다른 요소가 있다면 Sass는 변수를 CSS로 처리하려 하기 때문이다. 이 때 변수를 사용하기 위해 #{ }를 사용하면 된다. #{ }은 변수를 변수 그대로 사용할 수 있게 한다.
List는 하나의 변수에 여러 값을 담는 것이다. 기존 CSS에도 이미 있는 형태이다. margin: 1px 0 2px 3px;이나 font-family: tahoma, arial, sans-serif;와 같은 형태이다. $list-name: (value1, value2, value3) 형태로 선언한다. 값과 값 사이는 콤마로 구분하거나 공백으로 구분한다. 아래는 list를 활용한 실무에서도 유용하게 사용할 수 있는 코드로 벤더프리픽스를 편하게 붙이는 @mixin이다. @mixin과 @each 문에 대해서는 이후에 계속 설명한다.
Mixin은 CSS에서 반복적으로 사용하는 스타일을 mixin을 통해 재사용할 수 있는 스타일로 정의한다. 단순하게 CSS 규칙만을 적용할 수도 있지만, 인자를 활용하면 반복되는 CSS 속성을 mixin을 통해 다양한 곳에서 한 가지 규칙으로 적용할 수 있다. 이것은 mixin을 정의한 곳에서 mixin을 사용한 다양한 위치에 있는 스타일을 제어할 수 있으므로 관리 상의 이점도 있다. 다음에 나오는 예제를 통해 mixin을 어떻게 사용하고 실제 코드에 어떻게 적용할 수 있을지 알아보자. @mixin mixin 이름{속성: 속성값}으로 정의한다. mixin은 부모 선택자 참조(&)를 포함할 수 있다.
Mixin을 호출하는 방법은 @include mixin 이름으로 정의한다. @include를 사용하여 mixin의 이름과 인자 값을 전달하면 사용한 규칙에 mixin에 정의한 스타일이 포함된다.
함수를 사용할 때 괄호 안에 적는 값을 '인자' 혹은 '매개 변수'라고 한다. Mixin의 편리한 점은 인자를 활용할 때이다. 같은 속성을 사용하지만 속성 값만 달라지는 경우 매번 같은 코드를 적어주는 것이 불필요하게 느껴질 것이다. 이 때 인자를 활용한다면 편리하게 코드를 재활용할 수 있을 것이다. 인자를 활용한 mixin을 사용할 때에는 인자의 순서를 mixin의 인자 순서와 맞추어 사용해야 한다.
일반적으로 정해진 순서대로 인자를 적어야 하지만 Mixin은 인자의 이름과 값을 함께 적는다면 순서는 상관이 없다. 조금 더 복잡해 보일지도 모르겠지만 코드를 읽었을 때 이해하기는 더 쉬울 것이다. 또한 인자가 여러 개일 경우, 그 값을 보다 쉽게 입력할 수 있기 때문에 좀 더 편하게 Mixin을 사용할 수 있다.
Mixin에 정의되지 않은 스타일을 @content 지시 문이 추가로 스타일을 넣을 수 있게 해 준다. 이러한 추가 스타일은 Mixin을 사용하는 곳에서 넣을 수 있다.
아래를 보면 .americano에서 Mixin을 사용하면서 추가한 속성이 합쳐 져 컴파일 된 것을 볼 수 있다. Mixin을 정의하면서 기본적으로 설정한 스타일이 있다면 합쳐져 컴파일이 될 것이다. 반응형 작업을 하면서 많이 접하게 될 media 쿼리 구문을 Mixin 이름만으로 간단하게 사용할 수 있어 편리하다.
@extend는 같은 형태에서 약간의 변형이 생겼을 경우에 유용하게 사용할 수 있다. Sass를 사용하지 않았을 때 다중 클래스를 사용하거나 CSS에서 공통으로 사용하는 속성을 모아 선언하기도 했을 것이다. @extend는 직접 공통된 속성을 모아 선언하던 것을 편리하게 사용할 수 있게 한다. @extend의 사용 방법은 @extend class명 또는 @extend %placeholder명으로 선언하여 사용한다. @extend는 중첩 안에 여러 개를 선언해도 된다. 여러 개를 선언할 때 쉼표로 구분하여 사용할 수도 있다.
.americano_ice 클래스에는 .americano에 선언된 속성들이 모두 포함되어 있다. class 형식만 @extend 할 수 있는 것이 아니라, 공통된 속성을 따로 선언하여 가져와 사용할 수도 있다. 공통된 속성을 따로 선언한 것을 %placeholder라고 한다.
Error: You may not @extend an outer selector from within @media.
You may only @extend selectors within the same directive.
미디어쿼리 (@media)
@media는 반응형 웹을 만들 때 사용하며 width, height, orientation 등의 조건들과 함께 쓰이는 점까지 CSS 미디어 쿼리 문법과 같다.
Sass로 작성했을 경우에 가장 큰 특징은 중첩 규칙을 적용하여 좀 더 편리하게 사용할 수 있다는 점이다. CSS로는 @media (<조건>){<선택자{스타일}>} 형식으로 미디어 쿼리 문구 안에 선택자와 스타일을 정의하기 때문에, 선택자를 중복으로 적어야만 했다. 하지만 Sass로는 선택자 안에 미디어 쿼리를 사용할 수 있기 때문에 좀더 관리하기 편하다.
@at-root는 기본적으로 중첩된 '선택자'에서만 적용되기 때문에 @media와 같은 구문으로 중첩되어 있을 경우에는 빠져 나올 수 없다. 따라서 선택자 뿐만 아니라 중첩된 구문까지 어떤 경우에라도 적용하기 위해서는 @at-root (without: ...)를 사용한다.
여러 구문으로 중첩이 되어 있다면 @at-root (without: media supports)처럼 띄어쓰기로 구별하여 사용하며, 구문뿐만 아니라 선택자까지 모든 중첩 구조에서 한번에 빠져 나오기 위해서는 @at-root (without: all)을 사용한다.
하지만 몇 가지만 선택하여 중첩하고 싶다면 제외할 것들을 나열하는 것보다 @at-root (with: ...)로 중첩할 구문만 골라서 포함하는 것이 좋다. 예를 들어 @at-root (with: rule)를 사용하면 선택자 중첩만 유지하고, 나머지 모든 구문에서는 빠져 나온다. 따라서 구문 중첩이 없을 경우에 사용하는 @at-root와 같다.
처음 시작하는 Sass. p.123, 한빛미디어, 2016.
전문적으로 사용하기
연산
아마도 지금까지 레티나 디스플레이에 대응하려면 매번 background-position과 background-size 값을 2로 나눠서 입력했을 것이다. 하지만 Sass의 나누기 연산자를 사용하면 자동으로 계산하여 CSS로 컴파일 할 수 있다.
이러한 모든 계산을 컴퓨터가 수행하게 하는 것이 곧 프로그래밍이며 Sass 역시 좀 더 효율적으로 사용하려면 '연산'은 필수다.
연산자의 종류
프로그래밍에서 사용하는 연산자는 계산의 순서나 기호까지도 이미 알고 있는 것과 크게 다르지 않다. Sass에서도 다른 프로그래밍 언어와 같은 연산자를 사용한다. 다른 언어와 차이가 있다면 숫자로 된 색상 값이나 문자로 된 속성 값 등에도 연산을 사용할 수 있으며, 각각의 경우에서 사용하는 연산자가 다르다는 점이다.
사칙 연산자
기본적인 수학 규칙인 덧셈과 뺄셈보다 곱셈과 나눗셈을 먼저하고 괄호를 사용한 계산을 가장 우선시한다.
+
a + b
a 더하기 b
-
a - b
a 빼기 b
*
a * b
a 곱하기 b
/
a / b
a 나누기 b
나머지 연산자
나누기로 '몫'을 구한다면, 나머지 연산은 이름 그대로 '나머지'를 구할 수 있다.
%
a % b
a를 b로 나눈 나머지
비교/일치 연산자
결과 값이 다양하게 나오는 사칙/나머지 연산은 속성 값을 계산할 때 사용한다. 하지만 값의 크기를 비교하고 값이 일치하는지를 알아보는 비교/일치 연산은 '참'인지 '거짓'인지만을 판단한다. 따라서 속성 값을 계산하기 위한 '조건'으로 사용하기 때문에 숫자, 문자할 것 없이 모든 타입의 연산이 가능하다.
<
a < b
a가 b보다 작다
>
a > b
a가 b보다 크다
<=
a <= b
a가 b보다 작거나 같다
>=
a >= b
a가 b보다 크거나 같다
프로그래밍에서 '같다'를 나타내는 일치 연산자는 우리가 생각하는 등호(=)와 달리, 등호 두 개를 붙여야 한다는 점(==)을 기억하자.
==
a == b
a와 b가 같다
!=
a != b
a와 b가 다르다
숫자
숫자로는 모든 연산을 할 수 있다. 하지만 아래의 경우에는 컴파일 되지 않는다.
px과 em처럼 단위가 서로 일치하지 않을 경우
10px * 10px과 같이 넓이나 부피를 구하는 연산을 할 경우 (CSS에는 넓이를 표현하는 단위가 없다.)
나누기와 /
/는 나누기 연산자이지만 CSS 문법으로는 font: font-size/line-height와 같이 속성 값을 분리할 때 사용한다. 컴파일러는 기본적으로 CSS 문법을 우선으로 하기 때문에 상황에 따라 Sass가 아닌 CSS로 인식할 때가 있다. 따라서 다음 경우에 해당하면 나누기 연산자로 사용할 수 있다.
괄호로 묶여 있을 경우
사칙 연산의 일부로 사용되었을 경우
함수에 의해 리턴 되거나, 변수로 저장된 값일 경우
SCSS 코드
.cappuccino {
// CSS로 사용
font: 10px/20px;
// 나누기 연산자로 사용
font: (10em/8); // 괄호로 묶임
padding: 4px + 10px/2px; // 사칙 연산의 일부
$width: 1000px;
width: $width/2; // 변수로 저장된 값
bottom: floor(19px/2); // 함수: 소수점 이하 버림
right: ceil(19px/3); // 함수: 소수점 이하 올림
top: round(19px/2); // 함수: 소수점 이하 반올림
}
같은 스타일이 여러 번 반복될 때 복사와 붙여넣기를 하느라 시간을 낭비한 적이 있을 것이다. 제어문을 적절히 사용하면 요소의 개수와 상관없이 특정한 조건에 따라 자동으로 CSS가 작성되도록 할 수 있다. 조건에 따라 다른 Sass 식을 실행 해야 한다면 @if를 사용하고, 유사한 식을 반복 실행해야 한다면 @for, @each, @while을 사용한다. 제어문을 잘 다룰 수 있다면 본인의 상황에 특화된 mixin 혹은 함수를 만들 수 있는 것은 물론이고 좀 더 수준 높은 Sass를 작성할 수 있을 것이다.
조건문 (@if)
if는 '만약 ~라면 ... 하라'는 가정을 나타낼 때 쓰는 단어로, 프로그래밍에서는 조건에 따라 결과 값을 다르게 주고 싶은 경우에 사용한다. 조건을 어떻게 만드느냐에 따라서 다양한 상황에 모두 적용할 수 있는 만능 mixin 혹은 함수를 만들 수 있다. 개념 자체는 어렵지 않지만 Sass 스크립트를 사용하기 위해서 꼭 알아야 할 문법이다.
조건문은 '@if로 시작하며 @else if로 추가하고 @else로 빠져 나온다'고 기억하면 쉬울 것이다. 직접 컴파일 해보고 @if, @else if, @else를 언제 어떻게 사용해야 하는지 살펴보도록 하자.
SCSS 코드
/* 모두 출력 */
.chocolate {
@if true {content:'첫 번째 @if true';}
@if true {content:'두 번째 @if true';}
@if true {content:'세 번째 @if true';}
}
/* 모두 출력 안 됨 */
.latte {
@if false {content:'첫 번째 @if false';}
@else if false {content:'두 번째 @else if false';}
@else if false {content:'세 번째 @else if false';}
}
/* 마지막 else만 출력 */
.mocha {
@if false {content:'첫 번째 @if false';}
@else if false {content:'두 번째 @else if false';}
@else {content:'세 번째 @else';}
}
CSS 코드 (컴파일결과)
/* 모두 출력 */
.chocolate {
content: '첫 번째 @if true';
content: '두 번째 @if true';
content: '세 번째 @if true';
}
/* 모두 출력 안 됨 */
/* 마지막 else만 출력 */
.mocha {
content: '세 번째 @else';
}
@if만으로 여러 개의 조건을 추가했을 경우: 그것들은 모두 별개의 조건문이다. 즉, @if의 개수가 곧 조건문의 개수라고 볼 수 있기 때문에 앞에서 결과가 참이더라도 결국엔 가장 마지막에 만족하는 조건문으로 덮어 쓰여 진다.
다른 조건을 @else if로 추가했을 경우: 앞에서 결과가 참이라면 뒤에 오는 조건들은 모두 무시하고 조건문을 빠져 나온다. 따라서 조건이 여러 개일 경우에는 @if는 한 번만 사용하고 그 뒤에 오는 조건들은 @else if를 사용하는 것이 좋다.
@if와 @else if를 사용한 앞선 조건이 모두 거짓일 경우: 결국 아무런 조건 식이 없는 @else를 만나 무조건 실행하고 조건문을 빠져 나온다.
조건이 한 개일 경우
조건이 두 개일 경우
조건이 세 개 이상일 경우
@if <조건식> { }
@if <조건식> { } @else { }
@if <조건식> { } @else if <조건식> { } ... @else if <조건식> { } @else { }
예제
말 줄임과 관련된 CSS는 굉장히 자주 사용하는 스타일이기 때문에 mixin으로 만들기 적합하다. 하지만 말 줄임을 한 줄만 할 것인지 n번째 줄에 할 것인지에 따라 입력해야 하는 속성이 달라진다. 물론 두 개의 mixin을 만들어서 사용해도 훌륭하지만, @if를 사용하면 하나의 mixin 안에 조건을 나누어 속성을 다르게 줄 수 있다.
ellipsis라는 mixin에 몇 줄을 말 줄임할 것인지 $lines 인자 값으로 넘겨 준다. 인자 값이 1일 경우와 그렇지 않을 경우로 조건을 나눈 것을 확인할 수 있다. 2이상 값을 입력하면 @else 기본 값이 1로 지정되어 있기 때문에 입력하지 않는다면 자동으로 한 줄 말 줄임이 된다.
for는 '~하는 동안'이라는 뜻을 가지고 있으며, 프로그래밍에서는 지정한 횟수만큼 실행문을 반복하여 유사한 코드를 여러 개 만들기 위해 사용한다. 클래스에 넘버링을 하거나, nth-* 선택자를 사용하는 경우, 속성 값이 일정한 규칙으로 증감하는 경우에 유용하게 사용할 수 있다.
@for를 사용하기 위해서 고민해야 할 것은 "몇 번 반복을 할 것인가?"와 "반복을 할 때마다 실행문의 어떤 값을 어떻게 변경할 것인가?" 이다. 변수를 사용하지 않고 단순히 같은 코드를 반복하는 경우는 없을 것이다. 클래스 혹은 값을 일정하게 변화하면서 반복할 수 있기 때문에 실행문에서 변수를 어떻게 사용할지도 함께 고민해야 한다.
반복문은 실행과 동시에 시작 숫자부터 끝 숫자까지 카운트 되며 차례대로 변수에 저장된다. 시작 숫자가 1이고 끝 숫자가 10라면 변수에는 1부터 10까지 차례대로 대입되며 총 10회 반복한다. 시작 숫자가 10이고 끝 숫자가 1이더라도 그 결과는 같다. 다만 변수에 역순으로 숫자가 대입된다는 차이가 있을 뿐이다.
시작 숫자와 끝 숫자 사이에 이상, 이하를 의미하는 through 혹은 초과, 미만을 의미하는 to를 사용할 수 있다. to를 사용하면 끝 숫자를 카운트 하지 않기 때문에 혼란스러울 수 있어 대부분의 Sass 개발자는 through를 사용한다.
SCSS 코드
@for $<변수> from <시작> through <끝> {
<실행문>
}
@for $<변수> from <시작> to <끝> {
<실행문>
}
<변수>: 시작부터 끝 숫자를 하나씩 대입.
<시작>/<끝>: 카운트의 시작/끝이 되는 숫자로, 음수를 포함한 정수를 직접 입력하거나 결과 값이 정수인 Sass 스크립트 식.
through: "크거나 같다(이상)", "작거나 같다(이하)".
to: "크다 (초과)", "작다 (미만)".
<실행문>: 반복 실행 및 $<변수> 활용 가능.
예제
프로젝트를 진행하다 보면 width와 height 값이 같은 아이콘 여러 개를 sprite 이미지로 만들어 사용하는 경우가 종종 있다. 아마도 아이콘의 개수만큼 CSS를 복사하여 붙인 후, 일정한 간격으로 증가하는 background-position 값만 고쳐서 작성했을 것이다. 유지 보수를 위해 중간에 아이콘 하나가 빠지게 된다면 또 한 줄씩 수정해야 하기 때문에 시간 낭비가 아닐 수 없다. 선택자로 넘버링 혹은 nth-*로 클래스를 구별하기만 한다면 background-position은 @for 반복문을 사용할 수 있는 가장 좋은 예일 것이다.
클래스를 1부터 50까지 넘버링하고 아이콘을 y 축으로 10px 간격으로 배치하여 sprite 이미지를 만든 경우를 예로 들어 보았다. background-position의 y 값은 0부터 시작하여 -10px씩 줄어들어 가장 아래에 있는 아이콘의 position-y 값은 -500px이 될 것이다. 따라서 position-y 값 대신 -10px * $i를 사용하여, 0부터 50까지 반복하며 자동으로 값이 변하게 한 것을 볼 수 있다. 또한 클래스의 넘버링을 위해 인터폴레이션으로 변수를 사용한 것도 쉽게 이해할 수 있을 것이다.
SCSS 코드
@for $i from 1 through 50 {
.latte#{$i} { background-position:0 -10px * $i + 10px; }
}
Sass 반복문 중에서 가장 강력한 힘을 발휘하는 것이 바로 @each이다. 앞에서 알아본 @for 반복문은 규칙적으로 값이 변해야 한다는 한계가 있지만, @each는 list 혹은 map에 대한 이해만 있다면 어떤 상황에서도 코드를 반복하여 작성하지 않아도 될 만큼 유용하다.
굳이 list나 map의 형태로 저장한 이유가 바로 이 @each를 사용하기 위해서라고 해도 과언이 아니다. 따라서 @each에 대해 알아보기 전에 list와 map에 대해서 다시 한 번 살펴보도록 하자.
Lists
다른 프로그래밍 언어에서 '배열(Array)'을 접한 적이 있다면 쉽게 이해할 수 있을 것이다. 일반적으로 하나의 데이터를 저장하기 위해서 변수를 사용하는데, 여러 개의 데이터를 저장할 때에는 보통 list 혹은 뒤이어 설명할 map이라는 형식으로 저장한다.
개념을 이해하기 위해서 간단한 예를 들어보자. 'Red, Green, Blue, Cyan, Magenta, Yellow, Black' 총 7개의 색을 변수에 저장해서 사용하려고 한다. 단순히 $color1부터 $color7까지 각각 저장할 수 있겠지만, 아래와 같이 데이터들을 연관된 것끼리 모아 하나의 변수에 저장함으로써 좀 더 편하게 관리할 수도 있다.
앞의 두 코드 모두 font-size: 10px;로 동일하게 컴파일 되지만 분명히 다르게 동작한다.
mixin은 이미 속성에 대한 값을 정의하여 완성된 CSS를 컴파일 하는 것을 목적으로 한다. 따라서 매개변수로 넘겨 받은 10px이라는 값을 font-size가 아닌 다른 속성에 사용하기 위해서는 매개 변수를 추가하거나 또 다른 mixin을 만들어야 한다. 반면에 함수는 매개 변수가 적용된 '값'만 리턴한다. 따라서 다른 속성이나 클래스는 물론이고 또 다른 함수까지 그 값이 필요한 곳이라면 어디든지 사용할 수 있다.
즉 CSS를 한 글자씩 타이핑 하지 않고 @include라는 키워드로 간단하게 불러오고 싶다면 mixin을 사용한다. 하지만 일정한 행위 또는 특정한 동작을 수행하도록 설계된 로직이 필요하다면, 특히 모든 프로젝트에 걸쳐서 다양한 용도로 사용하고 싶다면 함수를 사용한다.
사용 방법
Sass가 제공하는 함수 외에 프로젝트 내에서도 사용자가 직접 정의하여 사용할 수 있다. 전역 변수에 접근은 물론이고 변수를 인자로 받을 수 있는 점까지 mixin과 유사하다. 값을 전달한다는 점이 함수의 가장 큰 특징이며, 함수를 호출한 곳에서 그 값을 사용하기 위해서는 함수 내에 @return을 사용해야 한다. @return을 만나면 함수를 빠져 나가기 때문에, 그 아래에 있는 코드들은 모두 무시한다.
자주 사용하는 Sass 함수
모든 함수를 외워서 사용할 수는 없기 때문에 Sass-lang 사이트에 있는 Sass 함수 문서를 참고한다. Sass가 제공하는 함수는 색상(RGB, HSL, 투명도), 문자열, 숫자, 리스트, map, 선택자 관련 함수들과 그 밖의 여러 기능을 하는 내장함수가 있다. 필요할 때마다 찾아서 쓰도록 하자.
Sass 함수 문서: http://www.sass-lang.com/documentation/Sass/Script/Functions.html
공통적으로 사용하기
지금까지 Sass의 기술적인 측면을 알아보았다. 이번 장에서는 업무를 진행하기에 앞서 정해두면 좋은 약속에 대해 설명한다.
Sass는 그 기능만으로도 노동을 줄이는 데에 많은 도움이 되지만 프로젝트의 기획과 디자인, 추후 코드의 유지보수 편의까지 고려할 때 가장 빛을 발한다. 프로젝트에 사용되는 색상이나 공간, 폰트의 종류나 행간 등을 변수로 정의하여 스타일 가이드로 활용하거나 손쉽게 값을 변경하여 커스터마이징하여 사용 가능한 테마 형태로 제공할 수도 있다. 몇 천 줄씩 작성된 CSS를 컴포넌트 별로 분리하여 코드의 가독성을 높힐 수도 있고 자주 사용되는 스타일을 작성해두고 새 프로젝트의 시작 시에 활용할 수도 있다.
때로는 과하게 Sass를 사용함으로 '굳이 Sass를 사용해야 하는가?'에 대한 논쟁이 벌어지기도 했지만 도구의 사용성에 대한 논란은 대부분 기획 단계의 문제일 뿐 도구의 잘못으로 보기는 어렵다. 비교적 적은 인원이 제작하는 블로그 테마나, 많은 사람들이 사용 가능하도록 공들여 제작된 부트스트랩 등의 UI 프레임워크를 분석해 보면 Sass를 기획적인 측면으로 활용할 때에 얻을 수 있는 이점을 학습하는 데 도움이 된다.
Sass는 CSS와 마찬가지로 위에서 아래로 읽기 때문에 다른 파일에서도 사용할 수 있도록 공용 파일들을 우선적으로 @import한다.
// 서비스명.scss
// 모든 파일에서 공통적으로 접근해야 하는 내용을 담은 파일은 우선적으로 @import 해준다.
@import 'common/_base';
@import 'common/_variables';
@import 'common/_placeholders';
@import 'common/_mixins;
컴포넌트 단위 구조화
파일명, 클래스명을 컴포넌트 단위로 구성하면 .map파일이 없어도 수정해야 할 위치를 쉽게 알 수 있다. 또한 주석을 통해 시작 지점에 해당 컴포넌트의 이름이나 정보를 명시해두면 코드 파악이 용이하다.
scss
서비스명.scss
common
import
_layout.scss
_icon.scss
_main.scss
_gnb.scss
전역 변수 작성
자주 사용하거나 잦은 변경이 예상되는 값들을 변수로 만들어 _variables.scss 파일에 작성한다. 추후 수정 시 효과적으로 대응이 가능하며 일관성 유지에 도움이 된다.