CSS @scope는 선택자 규칙이 적용될 DOM 영역을 지정하는 at-rule입니다. 시작 선택자로 범위의 root를 정하고 필요하면 끝 선택자로 범위 경계를 제한할 수 있습니다. 이렇게 하면 컴포넌트 안에만 적용할 규칙을 표현하기 쉬워지지만, 스코프가 선택자 특이성을 자동으로 낮추거나 다른 CSS 규칙을 격리하는 것은 아닙니다.

카드 스코프의 root와 제외되는 중첩 영역을 보여 주는 도식

스코프는 선택자 매칭 범위를 제한하며 상속을 차단하지 않습니다.

1. 시작점과 선택적 끝점

@scope (.card) { ... }는 .card와 일치하는 요소를 스코프 root로 삼고, 블록 안의 선택자를 해당 범위에서 매칭합니다. 시작 root 자체도 규칙 매칭의 대상이 될 수 있습니다. limit에 일치하는 요소 자체와 그 자손은 해당 스코프에서 제외됩니다. 이는 중첩 카드 내부에 바깥 컴포넌트 규칙이 새어 들어가는 것을 막는 데 사용할 수 있습니다.

스코프는 DOM 관계에 기반한 경계이지 별도의 shadow tree나 스타일 격리 환경이 아닙니다. 스코프 밖에서 선언된 규칙과 출처, 중요도, 레이어, 특이성 등 cascade 기준은 계속 작동합니다. 따라서 기존 CSS를 @scope로 감쌌다고 전역 선택자나 다른 스코프와의 충돌이 자동으로 사라진다고 기대해서는 안 됩니다.

2. 특이성과 scoping proximity

@scope의 시작 선택자 특이성은 내부 선택자에 자동으로 더해지지 않습니다. 다만 명시적인 :scope는 의사 클래스 특이성을 더합니다. 두 선언의 다른 cascade 기준이 같을 때 스코프가 겹치면 scoping proximity가 규칙을 가르는 기준이 될 수 있습니다. 대상 요소로부터 가장 가까운 scope root를 가진 선언이 우선할 수 있지만, 이 비교는 cascade의 앞선 출처·중요도·레이어·특이성 단계를 통과한 뒤에만 의미가 있습니다.

따라서 “가장 가까운 스코프가 항상 이긴다”는 설명은 불완전합니다. 더 높은 출처 우선순위나 중요도, cascade layer, 특이성 차이가 먼저 승자를 결정할 수 있습니다. 디버깅할 때는 개발자 도구에서 적용된 선언을 확인하고, scope root까지의 관계뿐 아니라 전체 cascade 순서를 함께 살펴봅니다.

3. 중첩 컴포넌트와 범위 경계

끝 선택자는 외부 컴포넌트의 규칙이 내부 컴포넌트에 미치는 범위를 제한할 수 있습니다. 예를 들어 카드 목록에서 바깥 .card scope를 지정하고 중첩 .card를 limit으로 설정하면 내부 카드가 바깥 범위에 포함되지 않게 만들 수 있습니다. 단, 내부 컴포넌트 자체 규칙이나 더 구체적인 선택자가 어떤 결과를 내는지는 별도로 확인해야 합니다.

이 방식은 컴포넌트 CSS를 읽기 쉽게 하고 전역 클래스 이름 충돌을 줄이는 데 도움을 줄 수 있지만, 스타일 캡슐화와 동일하지 않습니다. 예를 들어 color는 limit 요소와 그 자손에도 상속될 수 있습니다. 선택자 매칭을 제한해도 상속은 차단되지 않습니다. 실제 DOM의 중첩 구조와 scope limits가 기대한 경계를 만드는지 테스트해야 합니다.

4. 전문가 관점: 적용 범위를 선언하고 검증하기

현재 인용한 CSSWG 문서는 작업 중인 Editors Draft다. 여기서는 @scope 바로 아래에 중첩된 &를 :where(:scope)처럼 정의한다. 이 규칙을 안정된 W3C Recommendation으로 표현하지 않는다.

도입할 때는 root와 limit을 명확한 컴포넌트 경계에 맞추고, 중첩 컴포넌트에서 어떤 규칙이 매칭되는지 확인합니다. 이는 cascade 순서를 단순화한 설명입니다. 앞선 기준이 같을 때 specificity 다음에 scoping proximity를 비교하고, 그래도 같으면 선언 순서를 비교합니다. 브라우저 지원이 필요한 환경은 지원 범위를 확인하고 대체 스타일을 준비합니다. @scope는 선택자 범위를 문서화하는 유용한 도구이며, cascade 자체를 대체하는 기능은 아닙니다.

출처