← 목록으로

CSS `@supports`, 넌 날 속였어! 중첩 사용 시 발생하는 치명적인 오해

2026. 5. 10.

CSS @supports, 넌 날 속였어! 중첩 사용 시 발생하는 치명적인 오해

개발하면서 특정 CSS 기능 지원 여부를 확인해야 할 때, 우리는 @supports 룰을 애용합니다. 특정 속성이 브라우저에 따라 다르게 동작하거나 아예 지원하지 않을 때 유용하게 쓰이죠. 그런데 이 똑똑해 보이는 @supports가 때로는 우리를 심각하게 오도할 수 있다는 사실, 알고 계셨나요? 특히 CSS Nesting이 보편화되면서 그 오해의 폭이 더욱 커지고 있습니다.

처음 CSS Conditional Rules 명세에 따르면, @supports는 최상위 레벨이나 다른 조건부 그룹 룰 안에만 유효했어요. 하지만 새로운 CSS Nesting 명세는 이 영역을 확장해, 이제 @supports를 중첩된 스타일 룰 안에서도 사용할 수 있도록 명시적으로 허용하고 있습니다. 아주 편리해 보이죠?

하지만 여기에 함정이 있습니다. 시각적으로는 분명히 중첩되어 있어도, @supports 룰은 주변 셀렉터의 컨텍스트를 전혀 상속받지 않습니다. 브라우저는 여전히 이 룰을 마치 최상위 레벨에 있는 것처럼 평가해요. 이게 바로 개발자를 헷갈리게 만드는 지점입니다.

아래 코드를 볼까요?

.my-class {
  @supports (property: value) {
    /* ... */
  }
}

@supports 룰은 .my-class 스타일 룰 안에 분명히 들어있습니다. 그러나 이 @supports 조건은 .my-class 셀렉터에 상대적이지 않아요. 마치 루트 레벨에 작성된 것처럼 일반적이고 전역적인 방식으로 적용되죠. 개발자가 코드를 배치한 의도와 실제 동작 방식 사이의 불일치가 바로 중첩된 @supports를 오해의 소지가 다분하게 만드는 이유입니다.

더 구체적인 예시를 들어보겠습니다.

li::marker {
  @supports (content: " - ") {
    content: " - ";
    color: red;
  }
}

이 코드는 대부분의 브라우저에서 잘 작동하는 것처럼 보입니다. Chrome, Safari, Firefox 모두 ::marker를 지원하고, content: " - " 역시 일반적으로 지원하니까요. 하지만 여기서 미묘한 차이가 발생합니다. Safari는 ::marker 안에서 content 속성을 지원하지 않습니다.

위 코드를 실행하면 Chrome과 Firefox는 빨간색 " - "를 목록 마커로 렌더링합니다. 반면, Safari는 여전히 빨간색 원형 마커를 보여주죠.

가장 혼란스러운 부분은 바로 이것입니다. 선언이 해당 특정 컨텍스트에서는 실제로는 지원되지 않음에도 불구하고, @supports 조건은 성공적으로 통과한다는 점이에요. 제가 실무에서 이 부분을 테스트해 봤을 때, Safari에서 예상치 못한 결과가 나와 한참을 디버깅했던 기억이 납니다. @supports가 '된다'고 해도 실제 렌더링은 다를 수 있다는 걸 직접 경험한 순간이었죠.

솔직히 말해, 이는 브라우저가 중첩된 @supports 룰을 최상위 레벨로 "이동"시키거나 일반 컨텍스트로 "파싱"한다기보다는, @supports 자체의 정의 방식 때문일 가능성이 큽니다. 이 기능은 단순히 선언이 "일반적으로 유효한지"를 확인하지, 특정 셀렉터나 가상 요소 컨텍스트에서 문법적으로 유효한지까지는 검사하지 않습니다. 즉, @supports는 문맥을 전혀 보지 않는, '컨텍스트 블라인드' 상태인 셈입니다.

그렇다면 해결책은 없을까요? 몇 가지 아이디어를 생각해볼 수 있습니다.

한 가지 방법은 @supports를 확장하여 (또는 새로운 연산자나 함수를 도입하여) 독립적인 기능이 아닌, 조합을 검증할 수 있도록 만드는 것입니다. 예를 들면 이렇습니다.

@supports selector(::marker) and (content: " - ")

또는 다음과 같은 방식도 생각해볼 수 있습니다.

@supports selector(::marker) xand (content: " - ")

혹은 아예 룰 자체의 유효성을 검증하는 방식도 가능할 겁니다.

@supports rule(::marker { content: " - " })

이렇게 되면 선언이 특정 렌더링 컨텍스트 내에서 진정으로 작동하는지를 테스트할 수 있게 됩니다. 단순히 문법이 인식되는지 여부만 확인하는 현재의 방식보다는 훨씬 강력하겠죠.

또 다른 (더 이상적인) 해결책은 브라우저가 @supports 룰을 그것이 나타나는 스코프에 상대적으로 평가하는 것입니다. 하지만 이는 상당한 연산량을 필요로 할 수 있다고 우려할 수도 있습니다. 하지만 :has() 셀렉터에 대해서도 똑같은 우려가 있었지만, 지금은 얼마나 멋지게 작동하고 있나요! 충분히 실현 가능한 비전이라고 생각합니다.

물론 컨테이너 쿼리나 스타일 쿼리 같은 대안도 있긴 합니다만, 아직 부분적인 지원만 이루어지고 있고 (현재로서는) 선언이 아닌 사용자 정의 속성만 확인할 수 있다는 한계가 있습니다. 이들을 활용하면 도움이 될 수는 있지만, 중첩된 @supports가 가진 오해의 소지나 제한적인 본질을 완전히 해결해주지는 못합니다.

결론적으로, @supports는 CSS 기능 지원을 확인하는 데 유용한 도구임에 틀림없습니다. 하지만 중첩된 환경에서 사용할 때는 '컨텍스트 블라인드'라는 치명적인 약점을 항상 염두에 두어야 합니다. 브라우저와 CSS 명세가 이 부분을 개선하여, 개발자들이 더 예측 가능하고 안정적인 코드를 작성할 수 있기를 기대해봅니다. 그 전까지는 @supports가 성공했다고 해서 맹목적으로 믿지 말고, 실제 브라우저 테스트를 꼭 병행하는 현명함이 필요하겠습니다.


원문: https://dev.to/alvaromontoro/supports-lies-when-css-says-yes-but-browsers-say-lol-no-2bjh 수집일: 2026-05-10 01:44:43