Sass 기초와 활용

Sass 기초와 활용

2017 하드코딩하는사람들 오픈세미나


들어가며

강의 소개

안녕하세요. 황선수입니다.
'Sass 기초와 할용' 강의에 오신 것을 환영합니다.

본 강의는 교재와 결합도가 높습니다. 별도 프리젠테이션 자료나 판서 없이 본 교재를 중심으로 진행합니다. 교재를 읽기 전에 아래 내용을 참고하여 주시기 바랍니다.

  • Sass는 변수, 함수, 상속 등의 일반적인 프로그래밍 개념을 사용하여 코드를 작성한 뒤 기존 CSS 문법으로 컴파일해주는 전처리기입니다. 그래서 HTML, CSS는 알고 있는 것으로 가정하고 수업을 진행합니다.
  • 조건문, 반복문 등의 기본적인 프로그래밍 지식이 있으면 이해하는데 도움이 되지만 모른다고 해서 할 수 없는 것은 아닙니다.
  • 본 수업은 Sass 입문자(인턴/신입) 대상이므로 당장 실무에 활용하는 것보다는 각 기능을 숙지하고 사용해보는 것에 중점을 둡니다.
  • 다른 기술도 마찬가지겠지만, 수업을 듣고 나서 본인이 직접 해보면서 찾아보고 물어보면서 알아가는 것이 중요합니다.
  • 본 강의자료를 제작하는 과정에서 아래 도서를 참고하였습니다.
  • 본 강의자료는 '처음 시작하는 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만 다룬다.

이미지 출처: http://frontend.diffthink.kr/2016/09/scss.html

Sass의 특징

  • 가장 역사가 오래된 전처리기다.
  • Ruby 언어를 기반으로 동작한다. (성능개선을 위해 C언어로 이식된 Libsass도 있다.)
  • 기존 CSS 문법과 호환성이 높다.
  • 함수, 제어문까지 제공하며 완성도 높은 프로그래밍 언어처럼 동작한다.

설치하기

Ruby 설치

Ruby는 macOS에는 이미 설치되어 있다. Windows 사용자만 아래 방법으로 설치하면 된다.

http://rubyinstaller.org에 접속한다.


[Download] 링크를 클릭한다.

PC 환경에 맞는 버전(OS, 32bit/64bit)을 설치한다.


언어는 영어와 일본어를 선택할 수 있다. 일반적으로 영문판을 설치한다.

이용약관을 승인(accept)하고 다음(next)을 클릭한다.


설치할 때 모든 옵션에 체크한다.


완료한다.

Sass 컴파일러 설치


시작메뉴에서 명령 프롬프트 또는 cmd를 찾는다.

명령 프롬프트를 실행한다. ( macOS 사용자는 터미널을 실행한다.)


Sass 컴파일러 설치 명령문을 입력한다.

gem install sass

macOS에서 permission 오류가 발생하면 슈퍼 유저 권한으로 실행한다. 명령문 앞에 sudo를 붙이면 된다.

sudo gem install sass

macOS에서 Operation not permitted 오류가 발생하면 아래 방법을 시도한다.

sudo gem install -n /usr/local/bin sass

출처: http://stackoverflow.com/questions/32891965/error-while-executing-gem-errnoeperm-operation-not-permitted

gem은 Ruby에서 지원하는 패키지 매니저다. Sass 설치 명령문을 입력하면 자동으로 Sass 패키지의 최신 버전이 다운로드 되며 설치까지 진행된다.

어플리케이션을 사용하는 것도 좋지만, Sass의 동작방식에 대한 이해와 추후 Task Runner와의 연동 등을 위해서 Command Line에서 Sass를 사용해 보는 것을 추천한다. 공식 도큐먼트를 통해 보다 자세히 공부할 수 있다.

설치가 완료되었다면 정상적으로 컴파일 되는지 확인해 보자. 먼저 본인이 편하게 쓸 수 있는 에디터를 열어서 기본 테스트 환경을 준비한다.


컴파일 수행

Sass는 전처리도구로, CSS에 앞서서 작성해야 한다. 먼저 Sass 문서를 작성한 후, 컴파일 과정을 거쳐야 비로소 사용가능한 CSS 파일을 얻을 수 있다. Command Line을 통해 아래 명령문을 실행하여 Sass 파일을 CSS로 컴파일해 보자.

sass input.scss output.css

컴파일 자동수행 옵션 (--watch)

--watch는 단어 뜻처럼 변화를 주시하는 의미로, 이 옵션을 설정해 주면 컴파일 할 때마다 명령문을 입력하지 않아도 자동으로 컴파일 한다.

sass --watch input.scss:output.css

폴더 전체를 컴파일하려면 아래 명령문을 입력한다. 단, 이 때는 파일명이 _언더바로 시작하는 파일은 컴파일하지 않는다.

sass --watch src/scss:src/css

컴파일 스타일 옵션 (--style)

--style은 output 스타일에 대한 옵션으로 서로 다른 4가지 output 스타일을 제공한다.

  • :nested
  • :expanded
  • :compact
  • :compressed

SCSS 코드

.section{
	background: white;

	.title{
		color: green;
	}
	.description{
		text-align: center;
	}
	.description_list{
		margin: 20px 0;
		padding: 20px;
		border: 1px solid gray;
		dd{
			font-size: 15px;
			line-height: 20px;
		}
	}
}

:nested

기본 Sass 스타일로 아무런 옵션을 설정하지 않았다면 nested 스타일로 컴파일 된다. Sass 파일에서 대괄호로 그룹핑 한 가장 첫 번째 선택자를 기준으로 들여쓰기 되기 때문에 html 파일을 확인하지 않고도 어떤 구조인지 쉽게 알 수 있으며, 각 속성은 한 줄 씩 컴파일된다.

sass input.scss output.css --style nested

CSS 코드 (컴파일 결과)

.section {
  background: white;
}
  .section .title {
    color: green;
}
  .section .description {
    text-align: center;
}
  .section .description_list {
    margin: 20px 0;
    padding: 20px;
    border: 1px solid gray;
}
    .section .description_list dd {
      font-size: 15px;
      line-height: 20px;
}

:expanded

사용자가 선언한 순서대로 출력되는 일반적인 CSS 스타일로, 각 속성은 규칙 내에서 들여쓰기가 되며 한 줄 씩 컴파일된다.

sass input.scss output.css --style expanded

CSS 코드 (컴파일 결과)

.section {
  background: white;

}
.section .title {
  color: green;

}
.section .description {
  text-align: center;

}
.section .description_list {
  margin: 20px 0;
  padding: 20px;
  border: 1px solid gray;

}
.section .description_list dd {
  font-size: 15px;
  line-height: 20px;

}

:compact

:nested:expanded보다 공백이 적은 스타일로 모든 속성이 한 줄에 선언된다.

sass input.scss output.css --style compact

CSS 코드 (컴파일 결과)

.section{background:white}
.section .title{color:green}
.section .description{text-align:center}
.section .description_list{margin:20px 0;padding:20px;border:1px solid gray}
.section .description_list dd{font-size:15px;line-height:20px}

:compressed

최소한의 공백을 차지하는 스타일로 모든 속성 간의 공백과 줄 바꿈 없이 컴파일 된다. 압축 형태이기 때문에 유지 관리에는 어려움이 있으나 용량을 최소화하는 데 도움이 된다.

sass input.scss output.css --style compressed

CSS 코드 (컴파일 결과)

.section{background:white}.section .title{color:green}.section .description{text-align:center}.section .description_list{margin:20px 0;padding:20px;border:1px solid gray}.section .description_list dd{font-size:15px;line-height:20px}

코드 맵핑 (--sourcemap)

--sourcemap은 CSS와 mapping 되는 Sass의 정보를 알려주는 옵션이다. 컴파일을 하면 (CSS 파일명).map 파일이 자동 생성되고, 컴파일 된 CSS 파일 가장 하단에 mapping 된 파일의 정보를 나타내는 주석이 생긴 것을 확인 할 수 있다.

/*# sourceMappingURL=파일명.css.map */

이 옵션은 개발자 도구에서 요소 검사를 할 때 SCSS 파일명, 코드 line number 등의 정보를 나타내주기 때문에 디버깅하기 쉽다.


--sourcemap 옵션 제거하기

이 옵션은 기본 설정되어 있기 때문에 .map 파일을 삭제해도 컴파일 할 때마다 계속해서 생겨난다. 만약 옵션을 제거하기 원한다면 맨 처음 컴파일 할 때부터 다음과 같이 명령문을 입력해 주면 된다.

sass --watch input.scss:output.css --sourcemap=none

캐시 (--cache)

--cache는 Sass 템플릿 작업 및 여러 import 파일들을 더욱 빠르게 처리할 수 있도록 캐시된 파일을 보관하는 옵션이다. Sass의 기본 옵션으로 컴파일을 하면 .sass-cache라는 폴더가 자동 생성되고 관련 cache 파일이 저장된다.

--cache 옵션 제거하기

만약 이 옵션을 제거하기를 원한다면 맨 처음 컴파일 할 때부터 다음과 같이 명령문을 입력해 주면 된다.

sass --watch input.scss:output.css --no-cache

시작하기

프로젝트 규모가 커지고 오랜 유지 보수 기간을 거칠수록 CSS 코드 역시 거대해지는 경우가 많다. 복잡한 선택자와 무수한 속성, 그리고 다양한 값 사이에는 분명 명확하게 명시되지 않은 규칙이 많을 것이고, 이것은 CSS의 로직을 더욱 파악하기 어렵게 만든다. 심지어 CSS 파일 하나에 엄청나게 긴 코드가 있는데 짤막한 주석으로 코드 그룹을 분리한다면 코드의 구성을 파악하기는 여간 쉽지 않을 것이다.

여기서 다행인 점은 Sass는 의미 있고 간결한 CSS 코드 작성을 가능하게 해준다는 것이다. 선택자를 간단하면서도 짜임새 있게 표현할 수 있고 값 사이의 규칙을 작성할 수 있으며 모듈화 한 CSS를 여러 파일로 나누어 관리할 수도 있다.


불러오기 (@import)

이미지 출처: http://poiemaweb.com/sass-css-extention

CSS에는 현재 파일에 다른 CSS 파일을 불러오는 @import라는 속성이 있다. 이 속성을 사용하면 의도에 따라 코드를 잘게 쪼개어 효율적으로 유지 보수할 수 있는 방법을 찾을 수 있다. 하지만 @import로 선언되어 있는 CSS마다 http 요청을 발생하므로 웹 페이지 성능 저하의 원인이 된다 하여 사용을 지양하고 있다.

Sass에도 다른 파일을 불러올 수 있는 @import가 있다. CSS의 @import와 다른 점은 Sass 파일은 @import가 선언된 부모 Sass 파일을 단 하나의 CSS로 생성할 수 있다는 점이다. 이 방법을 사용하면 CSS 파일 하나만 작성한 듯한 효과를 주고 동시에 성능에 영향을 주지 않고 코드를 여러 파일로 나누어 관리할 수도 있다. 물론 import 된 파일에서 정의된 내용은 부모 Sass 파일에서도 사용할 수 있다.

아래와 같은 형태로 선언할 수 있다.

@import 'espresso';
@import 'espresso.scss';
@import 'scss/espresso';
@import 'scss/espresso.scss';

여러 파일을 import 할 때에는 선언한 순서와 동일하게 CSS 코드가 생성되기 때문에 CSS 우선순위를 고려하여 선언하도록 한다.

_espresso.scss와 같은 형태로 파일명 앞에 _(언더바)를 붙이면 해당 파일은 .css로 컴파일하지 않는다.


중첩 규칙

Sass는 HTML을 작성하듯이 선택자의 정의 안에 자식 선택자를 정의할 수 있다. 이와 같은 중첩 규칙으로 Sass를 작성한다면 부모 선택자가 반복해서 작성하지 않아도 되기 때문에 중첩이 많아지더라도 코드의 레이아웃을 간결하게 해준다. 중첩이 깊어지더라도 코드의 레이아웃을 보다 깔끔하게 해주어 가독성이 높아지므로 CSS를 정리하기도 편리해 진다.

SCSS 코드

.section{
	background: white;

	.title{
		color: green;
	}
	.description{
		text-align: center;
	}
	.description_list{
		margin: 20px 0;
		padding: 20px;
		border: 1px solid gray;
		dd{
			font-size: 15px;
			line-height: 20px;
		}
	}
}

CSS 코드 (컴파일 결과)

.section{background:white}
.section .title{color:green}
.section .description{text-align:center}
.section .description_list{margin:20px 0;padding:20px;border:1px solid gray}
.section .description_list dd{font-size:15px;line-height:20px}

부모 선택자 참조 (&)

선택자 대신 &기호를 쓰는 방법이 있다. &는 현재 작성 중인 정의의 부모를 참조한다. &가 유용한 이유는 가상 클래스, 가상 요소, 속성 선택자, class나 id 셀렉터를 사용하기에 매우 편리하기 때문이다.

부모 선택자 참조 사용 예시

SCSS 코드

.espresso {
	color: red;

	&:hover {
		color: orange; // 가상 클래스
	}
	&::after {
		color: yellow; // 가상 요소
	}
	&[id="text"] {
		color: green; // 속성 선택자
	}
	&.americano {
		color: blue; // 클래스 선택자
	}
	&#cappuccino {
		color: purple; // 아이디 선택자
	}
}

CSS 코드 (컴파일 결과)

.espresso{color:red}
.espresso:hover{color:orange}
.espresso::after{color:yellow}
.espresso[id="text"]{color:green}
.espresso.americano{color:blue}
.espresso#cappuccino{color:purple}

접두사로 부모 선택자 참조 사용 예시

SCSS 코드

.give_me_a {
	&-espresso {
		color: red;
	}
	.please &-americano {
		color: orange;
	}
}

CSS 코드 (컴파일 결과)

.give_me_a-espresso{color:red}
.please .give_me_a-americano{color:orange}

깊은 중첩에서 부모 선택자 참조 사용 예시

중첩이 깊어졌을 때 사용하는 &는 바로 상위에 있는 부모 선택자가 아니라, 최상위 선택자로부터 조합된 선택자가 된다는 것을 유의해야 한다.

SCSS 코드

.espresso {
	color: red;

	.cappuccino {
		color: orange;

		.latte {
			color: green;

			.a_class {
				.b_class {
					.c_class {
						.d_class {
							&.last {
								color: yellow;
							}
						}
					}
				}
			}
		}
	}
}

CSS 코드 (컴파일 결과)

.espresso {
	color: red;
}
.espresso .cappuccino {
	color: orange;
}
.espresso .cappuccino .latte {
	color: green;
}
.espresso .cappuccino .latte .a_class .b_class .c_class .d_class.last {
	color: yellow;
}

접미사로 부모 선택자 참조 사용 예시

SCSS 코드

.latte {
	.cappuccino & {
		font-size: 11px;
	}
}

CSS 코드 (컴파일 결과)

.cappuccino .latte{font-size:11px}

중첩 사용 시 유의사항

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에서는 메인 컬러를 변수에 담아 사용하는 곳에 컬러 값 대신 변수를 선언해 준다. 메인 컬러가 변경된다면 변수를 선언한 곳에서 컬러 값만 변경해 주면 파일을 일일이 뒤지지 않고도 손쉽게 메인컬러를 변경할 수 있다. 이렇게 변수는 유지 관리를 편리하게 만들어 주는 이점이 있다.


SCSS 코드

$color-basic: #0000ff;

.latte{
	color: $color-basic;
	border: 10px solid darken($color-basic, 20%);

	&:hover{
		color: lighten($color-basic, 30%);
		border: 10px solid darken($color-basic, 10%);
	}
}
.americano{
	background-color: rgba($color-basic, 0.3);
}

CSS 코드 (컴파일결과)

.latte{color:#0000ff;border:10px solid #000099}
.latte:hover{color:#9999ff;border:10px solid #0000cc}
.americano{background-color:rgba(0, 0, 255, 0.3)}

$color-basic이라는 변수에 컬러 값을 담아 여러 곳에서 다양하게 사용했다. 변수와 별개로 Sass의 기능 중 하나인 darken, lighten 기능을 활용하면 컬러에 다양한 변화를 주어 사용할 수 있다. 또한 RGB 값을 일일이 쓰지 않고 컬러 값만 입력해도 알아서 변환된다.


지역 변수와 전역 변수

변수의 유효 범위는 정의한 선택자 중첩 안에서 제한된다. 선택자 안에 선언됐다면 지역변수, 아무 중첩에도 속하지 않았다면 파일 어느 곳에서든지 사용할 수 있는 전역 변수가 된다.

전역 변수 SCSS 코드

$size: 12px;

.latte{
	width: $size;

	.americano{
		width: $size;
	}
}
.cappuccino{
	width: $size;
}

전역 변수 CSS 코드 (컴파일결과)

.latte{width:12px}
.latte .americano{width:12px}
.cappuccino{width:12px}

지역 변수 SCSS 코드

.latte{
	$size: 12px;

	width: $size;

	.americano{
		width: $size;
	}
}
.cappuccino{
	width: $size;
}

지역 변수 CSS 코드 (컴파일결과)

Error: Undefined variable: "$size".

지역 변수 예제에서는 오류가 났다. 왜냐하면 .latte 안에서 선언한 $size 변수는 지 역 변수이기 때문에 .latte 안에서만 사용할 수 있다. 따라서 .cappuccino에 사용한 $size 변수는 정의되지 않아서 오류가 나는 것이다.


수정한 지역 변수 SCSS 코드

.latte{
	$size: 12px;

	width: $size;

	.americano{
		width: $size;
	}
}
.cappuccino{
	$size: 10px;

	width: $size;
}

수정한 지역 변수 CSS 코드 (컴파일결과)

.latte{width:12px}
.latte .americano{width:12px}
.cappuccino{width:10px}

.cappuccino 안에서 $size 변수에 값을 지정하니 오류 없이 컴파일 된다. .latte 안에 정의한 $size: 12px이라는 값은 .cappuccino에 영향을 주지 않고 .cappuccino에 정의한 값은 .latte에 영향을 주지 않는다.


interpolation: #{ }

변수를 선택자와 속성 사이에서 사용하는 경우가 많다. 그때 $variable-name으로 그대로 적용하면 오류가 발생할 수 있다. 변수 주위에 다른 요소가 있다면 Sass는 변수를 CSS로 처리하려 하기 때문이다. 이 때 변수를 사용하기 위해 #{ }를 사용하면 된다. #{ }은 변수를 변수 그대로 사용할 수 있게 한다.

SCSS 코드

$date: "20160929";

.sp_land{
	background-image:url(http://static.land.naver.net/static/mobile/#{$date}/sp_ic.png);
}

CSS 코드 (컴파일결과)

.sp_land{
	background-image:url(http://static.land.naver.net/static/mobile/20160929/sp_ic.png)
}

List

List는 하나의 변수에 여러 값을 담는 것이다. 기존 CSS에도 이미 있는 형태이다. margin: 1px 0 2px 3px;이나 font-family: tahoma, arial, sans-serif;와 같은 형태이다. $list-name: (value1, value2, value3) 형태로 선언한다. 값과 값 사이는 콤마로 구분하거나 공백으로 구분한다. 아래는 list를 활용한 실무에서도 유용하게 사용할 수 있는 코드로 벤더프리픽스를 편하게 붙이는 @mixin이다. @mixin@each 문에 대해서는 이후에 계속 설명한다.

SCSS 코드

$vendors: webkit, moz, ms, o;

@mixin vender-prefix($name, $value) {
	@each $vendor in $vendors {
		-#{$vendor}-#{$name}: $value;
	}
	#{$name}: $value;
}

.list_test {
	@include vender-prefix(box-sizing, border-box);
	@include vender-prefix(border-radius, 50%);
}

CSS 코드 (컴파일결과)

.list_test{
	-webkit-box-sizing:border-box;
	-moz-box-sizing:border-box;
	-ms-box-sizing:border-box;
	-o-box-sizing:border-box;
	box-sizing:border-box;
	-webkit-border-radius:50%;
	-moz-border-radius:50%;
	-ms-border-radius:50%;
	-o-border-radius:50%;
	border-radius:50%
}

Map

Map은 키를 모든 유형의 값과 연결하는 자료 구조이다. 키는 어떤 자료 유형도 될 수 있다. Map은 괄호( )로 묶여 있고 쉼표(,)로 구분해야 한다. Key와 value가 한 쌍이 되어 선언된다.

Map은 $map-name: (key1: value1, key2: value2, key3: value3) 형태로 선언한다. Map은 Sass 스크립트 기능을 사용하여 조작할 수 있다. map-get, map-merge, @each와 함께 다양하게 사용된다.

프로젝트에서 같은 구조에 배경 색상만 달라진다면 CSS에서는 각각 배경 색상을 넣어줘야 했다. 하지만 Sass에서는 Map과 이후에 배울 @each를 사용하면 편리하게 해결할 수 있다.

SCSS 코드

$espresso: (
	'americano': #391919,
	'latte': #aa9f7d,
	'cappuccino': #887e61,
	'macchiato': #d0b76a,
	'mocha': #804c2a,
);

@each $name, $color in $espresso {
	.coffee_#{$name} {
		background-color: $color;
	}
}

CSS 코드 (컴파일결과)

.coffee_americano{background-color:#391919}
.coffee_latte{background-color:#aa9f7d}
.coffee_cappuccino{background-color:#887e61}
.coffee_macchiato{background-color:#d0b76a}
.coffee_mocha{background-color:#804c2a}

Mixin

Mixin은 CSS에서 반복적으로 사용하는 스타일을 mixin을 통해 재사용할 수 있는 스타일로 정의한다. 단순하게 CSS 규칙만을 적용할 수도 있지만, 인자를 활용하면 반복되는 CSS 속성을 mixin을 통해 다양한 곳에서 한 가지 규칙으로 적용할 수 있다. 이것은 mixin을 정의한 곳에서 mixin을 사용한 다양한 위치에 있는 스타일을 제어할 수 있으므로 관리 상의 이점도 있다. 다음에 나오는 예제를 통해 mixin을 어떻게 사용하고 실제 코드에 어떻게 적용할 수 있을지 알아보자. @mixin mixin 이름{속성: 속성값}으로 정의한다. mixin은 부모 선택자 참조(&)를 포함할 수 있다.

Mixin을 호출하는 방법은 @include mixin 이름으로 정의한다. @include를 사용하여 mixin의 이름과 인자 값을 전달하면 사용한 규칙에 mixin에 정의한 스타일이 포함된다.


SCSS 코드

@mixin setImageMask {
	position: relative;

	&:after{
		position: absolute;
		top: 0;
		bottom: 0;
		left: 0;
		right: 0;
		border: 10px solid #000;
		opacity: 0.2;
		content: '';
	}
}

.thumbnail{
	@include setImageMask;
	width: 200px;
	height: 200px;
	background-size: cover;
	background-position: 50% 0;
}

CSS 코드 (컴파일결과)

.thumbnail {
	position: relative;
	width: 200px;
	height: 200px;
	background-size: cover;
	background-position: 50% 0;
}
.thumbnail:after {
	position: absolute;
	top: 0;
	bottom: 0;
	left: 0;
	right: 0;
	border: 10px solid #000;
	opacity: 0.2;
	content: '';
}

Mixin은 어느 중첩에 속하지 않고 루트에서 곧바로 사용할 수 있으며 mixin 안에 다른 mixin을 넣을 수 있다.

SCSS 코드

@mixin setImageMaskRotate {
	@include setImageMask;
	@include rotate;
}
@mixin setImageMask {
	position: relative;

	&:after{
		position: absolute;
		top: 0;
		bottom: 0;
		left: 0;
		right: 0;
		border: 10px solid #000;
		opacity: 0.2;
		content: '';
	}
}
@mixin rotate {
	transform: rotate(45deg);
}

인자

함수를 사용할 때 괄호 안에 적는 값을 '인자' 혹은 '매개 변수'라고 한다. Mixin의 편리한 점은 인자를 활용할 때이다. 같은 속성을 사용하지만 속성 값만 달라지는 경우 매번 같은 코드를 적어주는 것이 불필요하게 느껴질 것이다. 이 때 인자를 활용한다면 편리하게 코드를 재활용할 수 있을 것이다. 인자를 활용한 mixin을 사용할 때에는 인자의 순서를 mixin의 인자 순서와 맞추어 사용해야 한다.

SCSS 코드

@mixin center($width, $height) {
	position: absolute;
	top: 50%;
	margin-top: - $height / 2;
	left: 50%;
	margin-left: - $width / 2;
	height: $height;
	width: $width;
}

.ex_box_1{
	@include center(100px, 100px);
	background-color: pink;
}
.ex_box_2{
	@include center(300px, 100px);
	background-color: orange;
}

CSS 코드 (컴파일결과)

.ex_box_1 {
	position: absolute;
	top: 50%;
	margin-top: -50px;
	left: 50%;
	margin-left: -50px;
	height: 100px;
	width: 100px;
	background-color: pink;
}
.ex_box_2 {
	position: absolute;
	top: 50%;
	margin-top: -50px;
	left: 50%;
	margin-left: -150px;
	height: 100px;
	width: 300px;
	background-color: orange;
}

키워드 인자

일반적으로 정해진 순서대로 인자를 적어야 하지만 Mixin은 인자의 이름과 값을 함께 적는다면 순서는 상관이 없다. 조금 더 복잡해 보일지도 모르겠지만 코드를 읽었을 때 이해하기는 더 쉬울 것이다. 또한 인자가 여러 개일 경우, 그 값을 보다 쉽게 입력할 수 있기 때문에 좀 더 편하게 Mixin을 사용할 수 있다.

SCSS 코드

.ex_box_3{
	@include center($height:100px, $width:200px);
	background-color: violet;
}

인자의 기본값

SCSS 코드

@mixin center($width:150px, $height:150px) {
	position: absolute;
	top: 50%;
	margin-top: - $height / 2;
	left: 50%;
	margin-left: - $width / 2;
	height: $height;
	width: $width;
}
.ex_box_4{
	@include center;
	background-color: black;
}

키워드 인자와 기본값을 이용한 실무예제

SCSS 코드

@mixin setAbsolute($top:null,$right:null,$bottom:null,$left:null) {
	position: absolute;
	top: $top;
	left: $left;
	right: $right;
	bottom: $bottom;
}

$buffer: 20px;

.area{
	@include setAbsolute($top:0,$bottom:0,$right:$buffer);
}

이상진. 네이버 블로그 PC 개편, NHN Technology Services, 2017.

CSS 코드 (컴파일결과)

.area{
	position: absolute;
	top: 0;
	right: 20px;
	bottom: 0;
}

변수 인자

Mixin의 인자가 1개일 때도 있지만 1개 이상일 경우도 있을 수 있다. 그때는 Mixin 인자명뒤에...을 추가하여 인수 값을 여러 개 받아올 수 있다.

SCSS 코드

@mixin americano ($margins...) {
	margin: $margins;
}
.give {
	@include americano (5px);
}
.me{
	@include americano (5px 10px);
}
.a {
	@include americano (5px 10px 15px);
}
.latte {
	@include americano (5px 10px 15px 20px);
}

CSS 코드 (컴파일결과)

.give {
	margin: 5px;
}
.me {
	margin: 5px 10px;
}
.a {
	margin: 5px 10px 15px;
}
.latte {
	margin: 5px 10px 15px 20px;
}

@content

Mixin에 정의되지 않은 스타일을 @content 지시 문이 추가로 스타일을 넣을 수 있게 해 준다. 이러한 추가 스타일은 Mixin을 사용하는 곳에서 넣을 수 있다.

아래를 보면 .americano에서 Mixin을 사용하면서 추가한 속성이 합쳐 져 컴파일 된 것을 볼 수 있다. Mixin을 정의하면서 기본적으로 설정한 스타일이 있다면 합쳐져 컴파일이 될 것이다. 반응형 작업을 하면서 많이 접하게 될 media 쿼리 구문을 Mixin 이름만으로 간단하게 사용할 수 있어 편리하다.

SCSS 코드

@mixin mq {
	@media all and (max-width:600px) {
		@content;
	}
}
.mixin_media {
	width: 100%;
	height: 100%;
	background-color: pink;
	@include mq {
		background-color: green;
	}
}

CSS 코드 (컴파일결과)

.mixin_media {
	width: 100%;
	height: 100%;
	background-color: pink;
}
@media all and (max-width: 600px) {
	.mixin_media {
		background-color: green;
	}
}

예제

실무에서 모바일 환경으로 작업을 할 때 아래와 같이 mixin을 만들어두고 사용하면 편리하다.

@mixin mq($point) {
	@if $point == pc {
		@media (min-width: 1025px) { @content; }
	}
	@else if $point == tablet {
		@media (min-width: 768px) { @content; }
	}
	@else if $point == onlytablet {
		@media (min-width: 768px) and(max-width: 1024px) { @content; }
	}
	@else if $point == mobile  {
		@media (max-width: 767px)  { @content; }
	}
	@else if $point == mobilesmall  {
		@media (max-width: 320px)  { @content; }
	}
	@else if $point == portrait  {
		@media screen and (orientation:portrait) { @content; }
	}
	@else if $point == landscape  {
		@media screen and (orientation:landscape) { @content; }
	}
	@else if $point == landscapeSmall {
		@media (orientation:landscape) and(max-width: 767px) { @content; }
	}
}

Extend

@extend는 같은 형태에서 약간의 변형이 생겼을 경우에 유용하게 사용할 수 있다. Sass를 사용하지 않았을 때 다중 클래스를 사용하거나 CSS에서 공통으로 사용하는 속성을 모아 선언하기도 했을 것이다. @extend는 직접 공통된 속성을 모아 선언하던 것을 편리하게 사용할 수 있게 한다. @extend의 사용 방법은 @extend class명 또는 @extend %placeholder명으로 선언하여 사용한다. @extend는 중첩 안에 여러 개를 선언해도 된다. 여러 개를 선언할 때 쉼표로 구분하여 사용할 수도 있다.

@Extend

SCSS 코드

.americano {
	font-size: 12px;
	text-align: center;
	color: #fff;
	background-color: #453621;
}
.americano_ice {
	@extend .americano;
	background-color: #152378;
}

CSS 코드 (컴파일결과)

.americano, .americano_ice {
	font-size: 12px;
	text-align: center;
	color: #fff;
	background-color: #453621;
}
.americano_ice {
	background-color: #152378;
}

%Placeholder

.americano_ice 클래스에는 .americano에 선언된 속성들이 모두 포함되어 있다. class 형식만 @extend 할 수 있는 것이 아니라, 공통된 속성을 따로 선언하여 가져와 사용할 수도 있다. 공통된 속성을 따로 선언한 것을 %placeholder라고 한다.

SCSS 코드

%water {
	line-height: 100px;
	font-size: 20px;
	text-align: center;
	color: #fff;
}
.americano {
	@extend %water;
	background-color: #453621;
}
.americano_ice {
	@extend %water;
	background-color: #152378;
}

CSS 코드 (컴파일결과)

.americano, .americano_ice {
	line-height: 100px;
	font-size: 20px;
	text-align: center;
	color: #fff;
}
.americano {
	background-color: #453621;
}
.americano_ice {
	background-color: #152378;
}

%placeholder는 사용하지 않는 한 CSS로 출력되지 않는다.


예제

실무 프로젝트에서 사용하면 편리한 %placeholder의 예시이다. 여러 개로 분리되어 있는 SCSS 파일에서 한 가지의 공통된 속성을 사용해야 할 때 %placeholder를 적절히 사용한다면 매우 효과적일 것이다.

SCSS 코드

// 태그 숨김 처리
%blind {
	position: absolute;
	clip: rect(0 0 0 0);
	width: 1px;
	height: 1px;
	margin: -1px;
	overflow: hidden;
}
// 한 줄 말줄임 처리
%ellipsis {
	overflow: hidden;
	display: block;
	text-overflow: ellipsis;
	white-space: nowrap;
}
// float 해제
%clearFloat {
	zoom: 1;

	&:after {
		content: '';
		display: block;
		clear: both;
	}
}

.blind{ @extend %blind; }
.hide{ @extend %blind; }
.hidden{ @extend %blind; }

.ellipsis{ @extend %ellipsis; }
.ell{ @extend %ellipsis; }

.section{
	article{ @extend %clearFloat; }
	h1{ @extend %clearFloat; }
}

CSS 코드 (컴파일결과)

.blind, .hide, .hidden {
	position: absolute;
	clip: rect(0 0 0 0);
	width: 1px;
	height: 1px;
	margin: -1px;
	overflow: hidden;
}
.ellipsis, .ell {
	overflow: hidden;
	display: block;
	text-overflow: ellipsis;
	white-space: nowrap;
}
.section article, .section h1 {
	zoom: 1;
}
.section article:after, .section h1:after {
	content: '';
	display: block;
	clear: both;
}

extend의 한계

@extend는 다양하게 적용할 수 있지만 그렇지 않은 경우가 있다. 자식 선택자와 인접 선택자는 @extend 되지 않는다.

SCSS 코드

// 오류 발생
.latte_1 {
	@extend .americano .espresso;
}
.latte_2 {
	@extend .americano + .espresso;
}

또한 @media 내에서 스코프 밖에 있는 클래스 또는 placeholder@extend로 참조할 수 없다. @media에서도 @extend가 된다면 CSS의 용량이 커지기 때문에 이를 제한한다. 같은 @media 블록 안에서는 적용할 수 있다.

SCSS 코드

@media screen and (min-width: 768px) {
	.espresso {
		background-color: #391919;
	}
	.latte {
		@extend .espresso;

		color: #887e61;
	}
}

다음은 오류다.

SCSS 코드

.espresso {
	background-color: #391919;
}
@media print {
	.latte {
		@extend .espresso;

		color: #887e61;
	}
}

오류 메시지

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로는 선택자 안에 미디어 쿼리를 사용할 수 있기 때문에 좀더 관리하기 편하다.

SCSS 코드

.americano {
	width: 300px;
	@media screen and (orientation: landscape) {
		width: 500px;
	}
}

CSS 코드 (컴파일결과)

.americano {
	width: 300px;
}
@media screen and (orientation: landscape) {
	.americano {
		width: 500px;
	}
}

또한 미디어 쿼리끼리 중첩하면 그 조건이 and 연산자로 이어져 컴파일 된다.

SCSS 코드

@media screen {
	.americano {
		@media (orientation: landscape) {
			width: 500px;
		}
	}
}

CSS 코드 (컴파일결과)

@media screen and (orientation: landscape) {
	.americano {
		width: 500px;
	}
}

부모 밖으로 나오기 (@at-root)

중첩 구조 안에서 부모에 종속되지 않고, 하나의 선택자로 단독 선언하고 싶을 때 사용한다. @at-root에 중첩을 사용하면 여러 선택자를 한꺼번에 묶어 부모 밖으로 빠져 나올 수 있다.

SCSS 코드

.parent {
	@at-root {
		.child1 { color: red; }
		.child2 { color: blue; }
	}
	.step-child { color: yellow; }
}

CSS 코드 (컴파일결과)

.child1 {
	color: red;
}
.child2 {
	color: blue;
}
.parent .step-child {
	color: yellow;
}

@at-root (without: ...)과 @at-root (with: ...)

@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-positionbackground-size 값을 2로 나눠서 입력했을 것이다. 하지만 Sass의 나누기 연산자를 사용하면 자동으로 계산하여 CSS로 컴파일 할 수 있다.

SCSS 코드

$espresso: 300px;

.mocha {
	background-size: ($espresso / 2) auto;
}

CSS 코드 (컴파일결과)

.mocha {
	background-size: 150px auto;
}

이러한 모든 계산을 컴퓨터가 수행하게 하는 것이 곧 프로그래밍이며 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가 다르다


숫자

숫자로는 모든 연산을 할 수 있다. 하지만 아래의 경우에는 컴파일 되지 않는다.

  • pxem처럼 단위가 서로 일치하지 않을 경우
  • 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 코드 (컴파일결과)

.cappuccino {
	font: 10px/20px;
	font: 1.25em;
	padding: 9px;
	width: 500px;
	bottom: 9px;
	right: 7px;
	top: 10px;
}

사칙연산, 변수, 함수에서 /를 CSS 문법 그대로 사용하고 싶다면 #{ }를 사용한다.

SCSS 코드

.macchiato {
	$font-size: 10px;
	$line-height: 20px;
	font: #{$font-size}/#{$line-height};
}

CSS 코드 (컴파일결과)

.macchiato {
	font: 10px/20px;
}

제어문

같은 스타일이 여러 번 반복될 때 복사와 붙여넣기를 하느라 시간을 낭비한 적이 있을 것이다. 제어문을 적절히 사용하면 요소의 개수와 상관없이 특정한 조건에 따라 자동으로 CSS가 작성되도록 할 수 있다. 조건에 따라 다른 Sass 식을 실행 해야 한다면 @if를 사용하고, 유사한 식을 반복 실행해야 한다면 @for, @each, @while을 사용한다. 제어문을 잘 다룰 수 있다면 본인의 상황에 특화된 mixin 혹은 함수를 만들 수 있는 것은 물론이고 좀 더 수준 높은 Sass를 작성할 수 있을 것이다.

조건문 (@if)

if는 '만약 ~라면 ... 하라'는 가정을 나타낼 때 쓰는 단어로, 프로그래밍에서는 조건에 따라 결과 값을 다르게 주고 싶은 경우에 사용한다. 조건을 어떻게 만드느냐에 따라서 다양한 상황에 모두 적용할 수 있는 만능 mixin 혹은 함수를 만들 수 있다. 개념 자체는 어렵지 않지만 Sass 스크립트를 사용하기 위해서 꼭 알아야 할 문법이다.

if 조건문의 진행


if else 조건문의 진행

if elseif 조건문의 진행

이미지 출처: http://tcpschool.com/php/php_control_condition


사용 방법

조건문은 '@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로 지정되어 있기 때문에 입력하지 않는다면 자동으로 한 줄 말 줄임이 된다.

SCSS 코드

@mixin ellipsis ($lines: 1) { // 인자 값의 기본 값은 1
	@if ($lines == 1) {
		overflow:hidden;
		text-overflow:ellipsis;
		white-space:nowrap;
	} @else {
		display: -webkit-box;
		overflow: hidden;
		text-overflow: ellipsis;
		-webkit-line-clamp: $lines;
		-webkit-box-orient: vertical;
	}
}
.latte {
	@include ellipsis();
	// @include ellipsis(1);
	// @include ellipsis; // 괄호는 생략 가능
}
.vanilla {
	@include ellipsis(3);
}

CSS 코드 (컴파일결과)

.latte {
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}
.vanilla {
	display: -webkit-box;
	overflow: hidden;
	text-overflow: ellipsis;
	-webkit-line-clamp: 3;
	-webkit-box-orient: vertical;
}

반복문 (@for)

for는 '~하는 동안'이라는 뜻을 가지고 있으며, 프로그래밍에서는 지정한 횟수만큼 실행문을 반복하여 유사한 코드를 여러 개 만들기 위해 사용한다. 클래스에 넘버링을 하거나, nth-* 선택자를 사용하는 경우, 속성 값이 일정한 규칙으로 증감하는 경우에 유용하게 사용할 수 있다.

@for를 사용하기 위해서 고민해야 할 것은 "몇 번 반복을 할 것인가?"와 "반복을 할 때마다 실행문의 어떤 값을 어떻게 변경할 것인가?" 이다. 변수를 사용하지 않고 단순히 같은 코드를 반복하는 경우는 없을 것이다. 클래스 혹은 값을 일정하게 변화하면서 반복할 수 있기 때문에 실행문에서 변수를 어떻게 사용할지도 함께 고민해야 한다.

for 반복문의 진행

이미지 출처: TCP School.com


사용 방법

반복문은 실행과 동시에 시작 숫자부터 끝 숫자까지 카운트 되며 차례대로 변수에 저장된다. 시작 숫자가 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; }
}

CSS 코드 (컴파일결과)

.latte1 {background-position: 0 0}
.latte2 {background-position: 0 -10px}
.latte3 {background-position: 0 -20px}
...
.latte49 {background-position: 0 -480px}
.latte50 {background-position: 0 -490px}

(예제) @for와 @if를 이용한 제어문

이미지 출처: http://kr.freeimages.com/photo/digits-square-icons-set-1242082

SCSS 코드

.digit_area button{
	width: 126px; height: 126px;
	background-image: url(../img/digits_square_icons.jpg);
	@for $i from 0 through 11 {
		&.digit_#{$i} {
			@if $i <= 3 {
				 background-position:(-156px * $i) 0;
			} @else if $i <= 7 {
				 background-position:(-156px * ($i - 4)) -144px;
			} @else if $i <= 11 {
				 background-position:(-156px * ($i - 8)) -287px;
			}
		}
	}
}

CSS 코드 (컴파일결과)

.digit_area button {
	width: 126px; height: 126px;
	background-image: url(../img/digits_square_icons.jpg);
}
.digit_area button.digit_0 { background-position: 0px 0; }
.digit_area button.digit_1 { background-position: -156px 0; }
.digit_area button.digit_2 { background-position: -312px 0; }
.digit_area button.digit_3 { background-position: -468px 0; }
.digit_area button.digit_4 { background-position: 0px -144px; }
.digit_area button.digit_5 { background-position: -156px -144px; }
.digit_area button.digit_6 { background-position: -312px -144px; }
.digit_area button.digit_7 { background-position: -468px -144px; }
.digit_area button.digit_8 { background-position: 0px -287px; }
.digit_area button.digit_9 { background-position: -156px -287px; }
.digit_area button.digit_10 { background-position: -312px -287px;}
.digit_area button.digit_11 { background-position: -468px -287px;}

반복문 (@each)

Sass 반복문 중에서 가장 강력한 힘을 발휘하는 것이 바로 @each이다. 앞에서 알아본 @for 반복문은 규칙적으로 값이 변해야 한다는 한계가 있지만, @eachlist 혹은 map에 대한 이해만 있다면 어떤 상황에서도 코드를 반복하여 작성하지 않아도 될 만큼 유용하다.

굳이 listmap의 형태로 저장한 이유가 바로 이 @each를 사용하기 위해서라고 해도 과언이 아니다. 따라서 @each에 대해 알아보기 전에 listmap에 대해서 다시 한 번 살펴보도록 하자.

Lists

다른 프로그래밍 언어에서 '배열(Array)'을 접한 적이 있다면 쉽게 이해할 수 있을 것이다. 일반적으로 하나의 데이터를 저장하기 위해서 변수를 사용하는데, 여러 개의 데이터를 저장할 때에는 보통 list 혹은 뒤이어 설명할 map이라는 형식으로 저장한다.

개념을 이해하기 위해서 간단한 예를 들어보자. 'Red, Green, Blue, Cyan, Magenta, Yellow, Black' 총 7개의 색을 변수에 저장해서 사용하려고 한다. 단순히 $color1부터 $color7까지 각각 저장할 수 있겠지만, 아래와 같이 데이터들을 연관된 것끼리 모아 하나의 변수에 저장함으로써 좀 더 편하게 관리할 수도 있다.

SCSS 코드

$rgb: #ff0000, #00ff00, #0000ff;
$cmyk: #00ffff, #ff00ff, #ffff00, #000000;

Map

map의 사용 목적과 방법은 리스트와 굉장히 유사하다. 가장 큰 차이점은 각 값마다 매칭된 키가 있기 때문에, 동적으로 접근할 수 있다는 점이다. 또한 CSS에는 없는 Sass만의 고유 문법이며 많은 양의 데이터를 컨트롤 하기 위해서는 반드시 알아야 한다.

SCSS 코드

$rgb: (red: #ff0000, green: #00ff00, blue: #0000ff);
$cmyk: (cyan: #00ffff, magenta: #ff00ff, yellow: #ffff00, black: #000000);

@each의 사용 방법

@eachlist 안의 데이터들을 차례로 변수에 대입하며 반복을 진행한다. 따라서 카운트 되는 숫자만 변수에 대입하는 @for와 달리, 별도로 반복 횟수를 지정해 줄 필요가 없다. 실행문에 사용할 변수와 그에 대입될 데이터들을 순서대로 적어주기만 하면 된다.

/* 실행문에 하나의 변수만 사용 */
@each $<변수> in <list 혹은 map> {
	<실행문>
}
  • <변수>: 나열된 다양한 값을 순차적으로 대입.
  • <list 혹은 $map>: 데이터를 직접 나열(list) 하거나, Sass 스크립트의 map 사용.
  • <실행문>: 반복 실행 및 $<변수> 활용 가능.

@for와 크게 다른 점으로는 실행문에 여러 개의 변수를 사용할 수 있다는 점이다. list 안에 또 다른 list를 하나의 값으로 넣으면 되는데, 이때 n번째 변수는 리스트를 하나씩 돌면서 n번째 데이터의 값을 저장한다.

만약 변수를 단 두 개만 사용한다면 list 보다 map을 사용하는 것이 더 편할 것이다. 또한 listmap으로 대체할 수 있으며 map은 모든 값을 key에 저장한다. 따라서 key와 값을 각각 변수에 담아서 사용할 수 있다.

SCSS 코드

/* 실행문에두개이상의변수사용 */
@each $<변수-1>, $<변수-2>, ... $<변수-n> in (<list 혹은 map>), (<list 혹은 map>), ... (<list 혹은 map>) {
	<실행문>
}
  • <변수>: 나열된 다양한 값을 순차적으로 대입.
  • <list 혹은 $map>: (값-1, 값-2, 값-3), (값-1.1, 값-2.2, 값-3.3), ... (값-1.n, 값-2.n, 값-3.n).
  • <실행문>: 반복 실행 및 $<변수> 활용 가능.

(예제) 리스트를 사용한 기본적인 @each 반복문

SCSS 코드

@each $coffee in espresso, americano, latte, mocha {
	.#{$coffee}-icon {
		background-image: url('/images/#{$coffee}.png');
	}
}
/* 리스트를 변수로 저장해서 사용해도 무관하다. */
$coffees : espresso, americano, latte, mocha;
@each $value in $coffees {
	.#{$value}-icon {
		background-image: url('/images/#{$value}.png');
	}
}

CSS 코드 (컴파일결과)

.espresso-icon {
	background-image: url('/images/espresso.png');
}
.americano-icon {
	background-image: url('/images/americano.png');
}
.latte-icon {
	background-image: url('/images/latte.png');
}
.mocha-icon {
	background-image: url('/images/mocha.png');
}

(예제) 여러 개의 변수를 이용한 @each 반복문

SCSS 코드

@each $coffee, $taste, $color in (espresso, dark, #372000), (americano, mild, #6d4b1a), (latte, soft, #9f7a45), (mocha, sweet, #f3f3f3) {
	.#{$coffee}-icon {
		background: $color url('/images/#{$taste}.png') no-repeat 0 0;
	}
}

CSS 코드 (컴파일결과)

.espresso-icon {
	background: #372000 url("/images/dark.png") no-repeat 0 0;
}
.americano-icon {
	background: #6d4b1a url("/images/mild.png") no-repeat 0 0;
}
.latte-icon {
	background: #9f7a45 url("/images/soft.png") no-repeat 0 0;
}
.mocha-icon {
	background: #f3f3f3 url("/images/sweet.png") no-repeat 0 0;
}

(예제) 맵을 사용한 @each 반복문

SCSS 코드

$coffees : (strong: espresso, mild: americano, soft: latte, sweet: mocha);

@each $key, $value in $coffees {
	.#{$key}-icon {
		background-image: url('/images/#{$value}.png');
	}
}

CSS 코드 (컴파일결과)

.strong-icon {
	background-image: url("/images/espresso.png");
}
.mild-icon {
	background-image: url("/images/americano.png");
}
.soft-icon {
	background-image: url("/images/latte.png");
}
.sweet-icon {
	background-image: url("/images/mocha.png");
}

(실무 예제) 부동산 주변편의시설 버튼

네이버 부동산, NAVER Corporation, 2017.


SCSS 코드

/* map */
$map-bus-color : #20af83;
$map-metro-color : #73c74d;
$map-hospital-color : #55b7ff;
$map-medi-color : #4887ff;
$map-parking-color : #71798d;
$map-mart-color : #ff9558;
$map-convenience-color : #b672f8;
$map-washing-color : #36cadc;
$map-beauty-color : #ff7cb0;
$map-repair-color : #8d6e63;
$map-bank-color : #3f498c;
$map-office-color : #00695c;
$map-infant-color : #ffb657;
$map-preschool-color : #ff9558;
$map-school-color : #f86b59;
$map-view-color : #73c74d;
$map-gate-color : #55b7ff;
$map-appear-color : #ffb657;
$map-convin-color : #b672f8;
$map-edu-color : #f86b59;
$map-life-color : #3f498c;
$map-transport-color : #20af83;
$map-etc-color : #ff7cb0;

/* 지도 버튼 */
$map-btns: (
	bus: (color: $map-bus-color),                 // 버스정류장
	metro: (color: $map-metro-color),             // 지하철역
	hospital: (color: $map-hospital-color),       // 종합병원
	medi: (color: $map-medi-color),               // 병원,약국
	parking: (color: $map-parking-color),         // 주차장
	mart: (color: $map-mart-color),               // 마트
	convenience: (color: $map-convenience-color), // 편의점
	washing: (color: $map-washing-color),         // 세탁소
	repair: (color: $map-repair-color),           // 열쇠,구두수선
	bank: (color: $map-bank-color),               // 은행
	office: (color: $map-office-color),           // 관공서
	infant: (color: $map-infant-color),           // 어린이집
	preschool: (color: $map-preschool-color),     // 유치원
	school: (color: $map-school-color),           // 학군
	schoolpoi: (color: $map-school-color),        // 학교
	beauty: (color: $map-beauty-color)            // 미용실
);

/* 주변 편의시설 */
@each $map, $value in $map-btns {
	.layer_btn_#{$map} {
		background-color: map-get($value, color);
		color: white;
	}
}

주선미. 네이버 부동산 모바일, NHN Technology Services, 2017.


(실무 예제) 부동산 대중교통 레이블

네이버 부동산, NAVER Corporation, 2017.


SCSS 코드

/* 지하철 */
$map-subways-bg: (
	s1: (bg-color: #003499),   // 1호선
	s2: (bg-color: #38b149),   // 2호선
	s3: (bg-color: #f36f34),   // 3호선
	s4: (bg-color: #2d9ede),   // 4호선
	s5: (bg-color: #893bb6),   // 5호선
	s6: (bg-color: #8f490e),   // 6호선
	s7: (bg-color: #606d00),   // 7호선
	s8: (bg-color: #e71e6e),   // 8호선
	s9: (bg-color: #b6971d),   // 9호선
	s100: (bg-color: #edb217), // 분당선
	s101: (bg-color: #71b8e5), // 공항
	s103: (bg-color: #6cb7b7), // 중앙
	s104: (bg-color: #2fbc9e), // 경의
	s107: (bg-color: #77c371), // 에버라인
	s108: (bg-color: #26a97f), // 경춘선
	s109: (bg-color: #a8022d), // 신분당선
	s110: (bg-color: #ff8e00), // 의정부
	s111: (bg-color: #edb217), // 수인선
	s112: (bg-color: #2673f2), // 경강선
	s22: (bg-color: #ffb95a),  // 인천2호선
	s71: (bg-color: #fa5f2c),  // 부산,대구1호선
	s72: (bg-color: #37b42d),  // 부산,대구2호선
	s73: (bg-color: #bf9f1e),  // 부산,대구3호선
	s74: (bg-color: #2d9ede),  // 부산,대구4호선
	s51: (bg-color: #37b42d)   // 광주,대전1호선
);
$map-subways-bd: (
	s21: (bd-color: #5191cf, font-color:#4489cb), // 인천1호선
	s79: (bd-color: #893bb6, font-color:#893bb6), // 부산김해
);
.subway_type{
	@each $map, $value in $map-subways-bg {
		&--#{$map}{
			background-color: map-get($value, bg-color);
			color: #fff;
		}
	}
	@each $map, $value in $map-subways-bd {
		&--#{$map}{
			border: 1px solid map-get($value, bd-color);
			color: map-get($value, font-color);
		}
	}
}

주선미. 네이버 부동산 모바일 개편, NHN Technology Services, 2017.


map-get

map 데이터 세트에 매핑되어 있는 특정 값을 가져오기 위해 map-get을 사용한다.

SCSS 코드

/* 위 예제를 간소화 */
$map-subways-bd: (
	s1: (bd-color: #5191cf, font-color:#4489cb),
	s2: (bd-color: #893bb6, font-color:#893bb6),
);
.subway_type{
	@each $map, $value in $map-subways-bd {
		&--#{$map}{
			border: 1px solid map-get($value, bd-color);
			color: map-get($value, font-color);
		}
	}
}

CSS 코드 (컴파일결과)

.subway_type--s1{
	border: 1px solid #5191cf;
	color: #4489cb;
}
.subway_type--s2{
	border: 1px solid #893bb6;
	color: #893bb6;
}

함수 (@function)

함수는 코드를 한데 묶어 놓고 필요할 때마다 호출하여 사용하며, 인자 값을 전달할 수 있다는 점이 mixin과 유사하다. 그 생김새와 사용 방법이 비슷해 보이기 때문에 둘 중에서 어떤 것을 사용할지 결정하는 일이 어려울 지도 모른다.

@function과 @mixin 비교

SCSS 코드

/* 함수 */
@function size($num) {
	@return #{$num}px;
}
.coffee { font-size: size(10); }

/* mixin */
@mixin size($num) {
	font-size: #{$num}px;
}
.latte { @include size(10); }

앞의 두 코드 모두 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의 기술적인 측면을 알아보았다. 이번 장에서는 업무를 진행하기에 앞서 정해두면 좋은 약속에 대해 설명한다.

Sass는 그 기능만으로도 노동을 줄이는 데에 많은 도움이 되지만 프로젝트의 기획과 디자인, 추후 코드의 유지보수 편의까지 고려할 때 가장 빛을 발한다. 프로젝트에 사용되는 색상이나 공간, 폰트의 종류나 행간 등을 변수로 정의하여 스타일 가이드로 활용하거나 손쉽게 값을 변경하여 커스터마이징하여 사용 가능한 테마 형태로 제공할 수도 있다. 몇 천 줄씩 작성된 CSS를 컴포넌트 별로 분리하여 코드의 가독성을 높힐 수도 있고 자주 사용되는 스타일을 작성해두고 새 프로젝트의 시작 시에 활용할 수도 있다.

때로는 과하게 Sass를 사용함으로 '굳이 Sass를 사용해야 하는가?'에 대한 논쟁이 벌어지기도 했지만 도구의 사용성에 대한 논란은 대부분 기획 단계의 문제일 뿐 도구의 잘못으로 보기는 어렵다. 비교적 적은 인원이 제작하는 블로그 테마나, 많은 사람들이 사용 가능하도록 공들여 제작된 부트스트랩 등의 UI 프레임워크를 분석해 보면 Sass를 기획적인 측면으로 활용할 때에 얻을 수 있는 이점을 학습하는 데 도움이 된다.

조현석. Sass 기초와 활용. p.17, NHN Technology Services, 2016.


기본 구조화

아래는 당사 Sass 컨벤션에서 권장하는 폴더 및 파일 구조이다.

  • scss
    • 서비스명.scss
    • common
      • _base.scss
      • _variables.scss
      • _placeholders.scss
      • _mixins.scss
    • import

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 파일에 작성한다. 추후 수정 시 효과적으로 대응이 가능하며 일관성 유지에 도움이 된다.

// _variables.scss

// font
$font-family-sans-serif:-apple-system,'Helvetica Neue','Apple SD Gothic Neo',NanumBarunGothic,sans-serif;
$font-family-helvetica:'Helvetica Reguler';

// layout
$iPhone6-size: 375px;
$iPad-size: 768px;
$width-max-size: 1024px;

// color
$naver-color: #00c73c;
$primary-color: #57a0f6;
$background-color: #e6e7e8;
...

황선수. 네이버 부동산 모바일 개편, NHN Technology Services, 2017.


마치며

Sass는 본 교재에서 다루는 내용 외에도 많은 기능이 있습니다. 하지만 본 강의는 Sass 입문자 대상이기 때문에 다소 개념이 어렵거나 실무에서 자주 사용하지 않는 내용은 제외하였습니다. 추후 심화 과정 등을 통해 더 좋은 모습으로 다시 찾아 뵙겠습니다.

본 교재에 대한 문의사항이나 건의사항이 있으면 hwangsunsoo@naver.com 으로 보내주시기 바랍니다.

여러분의 앞날에 무궁한 발전이 있기를 기원합니다.
부디 강녕하시고 건승하시고 대업을 이루십시오.
고맙습니다.

황선수 배상

휴식시간