특정 클래스의 스타일을 다른 클래스에서 그대로 물려받아 사용하고 싶을 때가 있습니다. (예: 기본 버튼의 형태를 물려받고 색상만 다른 에러 버튼)
@extend 키워드를 사용하면, 다른 선택자의 규칙을 상속받을 수 있습니다. 컴파일 시 중복되는 코드를 생성하지 않고 선택자들을 그룹화(, 로 연결)하여 CSS 용량을 최적화하는 데 도움을 줍니다.
// %를 붙이면 CSS로 컴파일되지 않는 추상 클래스가 됩니다.
%message-shared {
padding: 15px;
border: 1px solid #ccc;
border-radius: 8px;
}
.msg-success {
@extend %message-shared;
background-color: #d1fae5;
}
.msg-error {
@extend %message-shared;
background-color: #fee2e2;
}
/* 컴파일된 실제 CSS (선택자가 , 로 묶인 것을 확인하세요!) */
.msg-error, .msg-success {
padding: 15px;
border: 1px solid #ccc;
border-radius: 8px;
}
.msg-success {
background-color: #d1fae5;
}
.msg-error {
background-color: #fee2e2;
}
@extend를 사용할 때 일반 클래스를 상속할 수도 있지만, 주로 플레이스홀더(%)를 사용합니다. 두 방식의 컴파일 결과는 어떻게 다를까요?
.btn-base { padding: 10px; }
.btn-red {
@extend .btn-base;
color: red;
}
/* --- 컴파일 결과 --- */
.btn-base, .btn-red { padding: 10px; }
.btn-red { color: red; }
/* .btn-base가 단독으로 쓰이지 않아도
CSS 파일에 강제로 렌더링되어 용량을 차지합니다. */
%btn-base { padding: 10px; }
.btn-red {
@extend %btn-base;
color: red;
}
/* --- 컴파일 결과 --- */
.btn-red { padding: 10px; }
.btn-red { color: red; }
/* %btn-base 본체는 컴파일시 흔적 없이 사라지고,
오직 상속받은 클래스만 남습니다. (용량 최적화) */
하나의 클래스가 여러 개의 속성을 동시에 상속받을 수도 있습니다.
%box-shadow { box-shadow: 0 4px 6px rgba(0,0,0,0.1); }
%rounded-corner { border-radius: 12px; }
.custom-card {
@extend %box-shadow; // 여러 번 사용 가능
@extend %rounded-corner;
background-color: white;
}
중첩된(Nested) 구조 안에서 무분별하게 @extend를 사용하면, SCSS 컴파일러가 모든 가능한 경우의 수를 계산하여 콤마(,)로 묶어버립니다. 이로 인해 컴파일된 CSS 용량이 기하급수적으로 늘어나고 디버깅이 불가능해집니다.
/* 😱 아주 끔찍한 상황 예시 */
.admin-panel .btn { @extend .btn-primary; }
.user-dashboard .btn { @extend .btn-primary; }
.modal-window .action-btn { @extend .btn-primary; }
/* .btn-primary가 호버 상태(:hover) 등을 가지고 있다면?
컴파일 시 아래와 같이 무수한 선택자 조합이 탄생합니다. */
.btn-primary:hover,
.admin-panel .btn:hover,
.user-dashboard .btn:hover,
.modal-window .action-btn:hover {
background-color: darkblue;
}
/* 프로젝트 규모가 커질수록 이 콤마(,) 조합은 수십, 수백 줄로 뻥튀기됩니다! */
위에서 살펴본 선택자 폭발 부작용과 코드 순서 예측의 어려움 때문에, 최신 SCSS 가이드라인에서는 가급적 @extend의 사용을 지양하고 매개변수 활용이 가능한 @mixin을 사용할 것을 강력히 권장하고 있습니다. (레거시 코드를 읽기 위해 작동 원리만 이해해 두세요!)