CSS를 오래 작성하다 보면 반드시 마주치는 문제가 있습니다. 바로 스타일 우선순위 충돌입니다. 외부 라이브러리의 스타일이 내 스타일을 덮어쓰거나, 컴포넌트 스타일이 글로벌 스타일과 충돌하는 상황 말이죠. 이를 해결하기 위해 !important를 남발하다 보면 코드는 금방 엉망이 됩니다.
CSS @layer는 이 문제를 우아하게 해결하는 현대적인 방법입니다.
CSS 캐스케이드 복습
브라우저가 어떤 스타일을 적용할지 결정하는 순서는 다음과 같습니다.
- 출처 (브라우저 기본값 < 작성자 스타일 < 사용자 스타일)
- 레이어 순서 ← @layer가 여기에 개입
- 명시도 (specificity)
- 작성 순서
@layer 기본 사용법
레이어를 선언하고 각 레이어에 스타일을 배치합니다. 나중에 선언된 레이어가 더 높은 우선순위를 갖습니다.
/* 레이어 순서 먼저 선언 (선택 사항이지만 권장) */
@layer reset, base, components, utilities;
@layer reset {
*, *::before, *::after { box-sizing: border-box; margin: 0; }
}
@layer base {
body { font-family: sans-serif; color: #333; }
a { color: blue; }
}
@layer components {
.card { border: 1px solid #e5e7eb; border-radius: 0.75rem; }
.btn { padding: 0.5rem 1rem; border-radius: 0.4rem; }
}
@layer utilities {
.text-center { text-align: center; }
.mt-4 { margin-top: 1rem; }
}
이 예시에서 우선순위는 utilities > components > base > reset 순입니다.
외부 라이브러리 다루기
@layer의 진짜 강점은 외부 CSS를 레이어에 넣는 것입니다. 레이어 안의 스타일은 레이어 밖의 스타일보다 항상 낮은 우선순위를 갖습니다.
/* Bootstrap을 레이어에 가두기 */
@import url('bootstrap.css') layer(bootstrap);
/* 이제 내 스타일이 항상 Bootstrap을 이깁니다 */
.btn {
background-color: #6891f8; /* !important 없이도 적용됨 */
}
레이어 밖의 스타일은 모든 레이어보다 높은 우선순위를 가집니다. 즉, 레이어에 넣지 않은 내 커스텀 스타일은 항상 이깁니다.
중첩 레이어
레이어 안에 레이어를 만들 수도 있습니다. 디자인 시스템 구조화에 유용합니다.
@layer components {
@layer base {
.btn { padding: 0.5rem 1rem; }
}
@layer variants {
.btn-primary { background-color: #6891f8; color: white; }
.btn-danger { background-color: #ef4444; color: white; }
}
/* variants > base */
}
실전: Tailwind + 커스텀 CSS
Tailwind CSS와 함께 사용하면 유틸리티 클래스가 컴포넌트 스타일을 덮어쓰는 문제를 깔끔하게 해결할 수 있습니다.
/* Tailwind를 레이어에 가두기 */
@import "tailwindcss" layer(tailwind);
/* 내 컴포넌트 스타일 (레이어 밖 → 항상 이김) */
.card {
border-radius: 1rem;
box-shadow: 0 4px 16px rgba(0,0,0,0.1);
}
브라우저 지원
Chrome 99+, Firefox 97+, Safari 15.4+ 이상에서 지원합니다. 2022년부터 모든 모던 브라우저가 지원하므로 실무에서 사용해도 안전합니다.
@layer는 CSS 우선순위를 명시적으로 관리하는 도구입니다. 레이어 순서를 선언부에서 한 번에 제어하고, 외부 라이브러리는 레이어 안에 가두세요.
!important와의 이별을 선언할 시간입니다.
레이어 이름 규칙과 아키텍처
@layer를 효과적으로 관리하려면 처음부터 명확한 이름 규칙과 레이어 순서를 정의해야 합니다. ITCSS(Inverted Triangle CSS) 방법론과 함께 사용하면 좋습니다.
/* 전역 styles/layers.css에서 레이어 순서 선언 (가장 먼저 임포트) */
@layer
reset, /* 브라우저 기본 스타일 초기화 */
tokens, /* 디자인 토큰 (색상, 타이포, 간격) */
base, /* 기본 HTML 요소 스타일 */
vendors, /* 외부 라이브러리 */
layout, /* 페이지 레이아웃 구조 */
components, /* 재사용 UI 컴포넌트 */
utilities, /* 유틸리티 클래스 */
overrides; /* 일회성 덮어쓰기 */
/* 각 레이어에서 선언 */
@layer reset {
*, *::before, *::after { box-sizing: border-box; }
body { margin: 0; }
}
@layer tokens {
:root {
--color-primary: oklch(58% 0.22 264);
--space-4: 1rem;
}
}
DevTools에서 레이어 디버깅
Chrome DevTools 122+에서 @layer를 시각적으로 확인하고 디버깅할 수 있습니다.
- Elements 패널 → Styles 탭 — 적용된 스타일 옆에 레이어 이름이 표시됩니다. 어느 레이어의 규칙이 적용됐는지 한눈에 파악 가능
- 레이어 순서 확인 — "Cascade Layers" 섹션에서 현재 페이지의 레이어 순서와 각 레이어의 규칙 수 확인
- 오버라이드 추적 — 취소선이 그어진 스타일에서 어느 레이어가 어느 레이어를 덮어쓰는지 추적
@layer와 !important의 상호작용
!important는 레이어 시스템에서 예상과 반대로 동작합니다. 이 규칙을 이해하지 못하면 디버깅이 매우 어려워집니다.
@layer base, theme, utilities;
@layer base {
p { color: blue !important; } /* !important는 레이어 순서를 역전시킴 */
}
@layer utilities {
p { color: red; } /* 일반 선언은 utilities가 이김 */
}
/* 결과: base의 !important가 utilities의 일반 선언을 이김
즉 p 색상 = blue */
레이어 시스템에서 !important는 레이어 우선순위를 역전시킵니다. 낮은 레이어의 !important가 높은 레이어의 일반 선언을 이기게 됩니다. 이 때문에 레이어 내부에서 !important 사용은 최소화하는 것을 강력히 권장합니다.
기존 프로젝트 마이그레이션 전략
@layer 없이 운영 중인 기존 프로젝트를 단계적으로 마이그레이션하는 방법입니다.
- 1단계 — 외부 라이브러리만 레이어로 감싸기:
@layer vendors { @import 'bootstrap.css'; } - 2단계 — 기존 커스텀 CSS를
@layer overrides { }로 래핑 (레이어 없는 코드보다 낮은 우선순위) - 3단계 — 새로 추가하는 코드는 적절한 레이어에 배치
- 4단계 — 기존 코드를 점진적으로 적절한 레이어로 분류
한꺼번에 마이그레이션하면 예상치 못한 스타일 변경이 발생할 수 있습니다. 레이어 없는 코드는 레이어 있는 코드보다 항상 높은 우선순위를 가지므로, 기존 코드를 임의의 레이어에 넣으면 우선순위가 낮아질 수 있습니다.
@layer가 실제로 해결하는 문제
@layer가 도입되기 전, CSS 프로젝트가 커질수록 개발자들이 가장 자주 겪는 고통은 특이성(Specificity) 전쟁이었습니다. Bootstrap 같은 CSS 프레임워크를 사용하면서 특정 스타일을 덮어쓰려면 더 높은 특이성의 선택자를 작성하거나 !important를 남발해야 했습니다. 이것이 쌓이면 CSS는 점점 예측 불가능해지고, 한 곳을 수정하면 예상치 못한 곳이 깨지는 일이 반복됩니다. @layer는 이 문제를 구조적으로 해결합니다. 레이어 선언 순서가 곧 우선순위가 되기 때문에, 특이성이 낮은 선택자라도 더 높은 레이어에 있으면 이깁니다. 이 덕분에 컴포넌트 스타일을 단순하게 유지하면서도 필요한 곳에서 확실하게 재정의할 수 있습니다.
디자인 시스템을 구축하는 팀에서 @layer의 효과가 특히 큽니다. 기본 토큰 레이어, 컴포넌트 레이어, 테마 레이어, 페이지별 오버라이드 레이어처럼 계층을 명확히 나누면, 어떤 스타일이 어디서 오는지 즉시 파악할 수 있습니다. 새로운 팀원이 합류했을 때도 레이어 구조를 이해하면 전체 CSS 아키텍처를 빠르게 파악할 수 있어 온보딩이 쉬워집니다. 2024년 이후 모든 주요 브라우저에서 @layer를 지원하므로, 신규 프로젝트에서는 처음부터 레이어 아키텍처를 설계에 포함하는 것을 강력히 권장합니다.