CSS 중복 선택자 병합하는 방법

CSS 파일에 같은 선택자가 여러 번 선언되어 있으면, 실제로 화면에 적용되는 값은 그중 가장 나중에 적힌 값입니다.
이 사실을 몰라도 코드는 돌아가지만, 파일이 길어지고 여러 사람이 나눠서 손을 대다 보면 어느 선언이 "진짜 적용되는 값"인지 눈으로 찾기 어려워집니다. 이 글은 중복 선택자가 왜 생기는지, 손으로 찾는 법과 자동으로 하나로 합치는 법을 함께 정리합니다.
요약 ① 완전히 동일한 선택자가 여러 번 선언되면, 같은 속성끼리는 소스 코드상 더 나중에 나온 값이 최종 적용됩니다. ② 도구 없이도 grep·sort·uniq 같은 텍스트 명령이나 브라우저 개발자 도구의 취소선 표시로 중복 선언을 직접 찾을 수 있습니다. ③ 이 병합 방식은 사용하지 않는 CSS(dead code)를 지우는 기능과는 다르며, 동일 선택자의 중복 선언을 하나로 합치는 데 한정됩니다.
중복 선택자는 왜 생기나
가장 흔한 경우는 여러 명이 나눠서 작업한 CSS 파일을 하나로 합칠 때입니다. 각자 작업 파일에 .btn이라는 선택자를 따로 만들어 쓰다가, 빌드 과정에서 파일들을 이어 붙이면 같은 선택자가 파일 안에 여러 번 남습니다.
오래 유지보수된 프로젝트에서도 같은 일이 생깁니다. 기존 규칙을 지우지 않고 파일 맨 아래에 새 규칙만 계속 추가해온 경우, .card나 .header 같은 자주 쓰는 선택자가 파일 상단·중단·하단에 각각 다른 속성으로 흩어져 있게 됩니다.
이 상태에서 문제는 코드가 안 돌아가는 게 아니라, 어떤 선언이 실제로 적용되는지 코드만 봐서는 바로 알기 어렵다는 점입니다. 세 번 선언된 .btn 중 어느 것이 최종 스타일인지 확인하려면 파일 전체를 순서대로 읽어야 합니다.
도구 없이 직접 확인하는 방법
CSS의 캐스케이드(cascade) 규칙에 따르면, 특정성(specificity)이 같은 선택자들 사이에서는 소스 코드상 더 나중에 나온 선언이 이깁니다. 완전히 동일한 선택자를 여러 번 쓴 경우가 바로 이 경우에 해당하므로, 같은 속성이 중복 선언됐다면 파일에서 더 아래쪽에 적힌 값이 최종 적용값입니다.
파일 전체에서 중복 선택자를 눈으로 찾는 방법은 세 가지입니다.
1. 텍스트 명령으로 찾기
선택자가 한 줄에 하나씩 단순하게 적혀 있는 CSS라면, 터미널에서 아래처럼 확인할 수 있습니다.
grep -oE '^[^{}]+\{' style.css | sed 's/[{ ]*$//' | sort | uniq -d
이 명령은 {로 끝나는 줄에서 선택자 부분만 뽑아 정렬한 뒤, 두 번 이상 나온 선택자만 골라 보여줍니다. 다만 이 방식은 한 줄에 여러 선택자가 붙어 있는 압축(minified) CSS나 Sass·Less의 중첩 문법에는 그대로 쓸 수 없어서, 파일을 먼저 정리된 형태로 펼쳐둬야 합니다.
2. 브라우저 개발자 도구로 찾기
요소를 검사(Inspect)하면 Styles 패널에 그 요소에 적용되는 모든 규칙이 순서대로 나열되고, 나중 규칙에 덮어써진 속성은 취소선으로 표시됩니다. 다만 이 방법은 지금 검사 중인 요소 하나에 한정되므로, 파일 전체를 훑어보는 용도는 아닙니다.
3. 린터로 지속적으로 감지하기
스타일시트 코드 품질을 점검하는 오픈소스 도구 Stylelint에는 중복 선택자를 감지하는 규칙(no-duplicate-selectors)이 포함되어 있습니다. 프로젝트에 린터를 설정해두면 새 중복이 생길 때마다 알려주는 방식으로도 관리할 수 있습니다.
저희 도구로 확인하기.
CSS 코드를 붙여넣으면 중복 선택자를 찾아 하나로 병합해 보여줍니다. 설치나 가입이 필요 없습니다.

자주 헷갈리는 부분
중복 선택자 병합과 자주 섞이는 개념들이 있습니다. 표로 구분하면 이렇습니다.
| 상황 | 겹치는 대상 | 최종 적용값 |
|---|---|---|
| 완전히 동일한 선택자를 두 번 선언 | 선택자 문자열 자체 | 같은 속성이면 더 나중에 선언된 값 |
| 다른 선택자지만 특정성이 같아 같은 요소에 적용 | 특정성이 같은 서로 다른 선택자 | 소스 순서상 더 나중 규칙 |
| 특정성이 다른 선택자(예: 클래스 선택자 vs id 선택자) | 특정성이 다른 선택자 | 특정성이 더 높은 규칙(순서와 무관) |
한 가지 더 구분할 점은, 병합 대상은 어디까지나 같은 속성이 충돌할 때뿐이라는 것입니다. 서로 다른 속성이라면 충돌 없이 하나의 선언부 안에 그대로 합쳐집니다. 예를 들어 .btn에 color가 한 번, padding이 한 번 따로 선언되어 있었다면 두 속성 모두 살아남고, 값이 바뀌는 것은 같은 속성이 서로 다른 값으로 중복 선언됐을 때뿐입니다.
또한 이 방식은 사용하지 않는 CSS를 지워주는 기능과는 다릅니다. HTML에서 실제로 쓰이는 선택자인지 판단해서 죽은 코드를 제거하는 작업은 별도의 분석이 필요하며, 중복 선택자 병합은 "같은 선택자가 여러 번 있는가"만 봅니다.
정리
- 완전히 동일한 선택자가 여러 번 선언되면, 같은 속성끼리는 소스 코드상 더 나중에 나온 값이 최종 적용됩니다.
- grep·sort·uniq 조합이나 브라우저 개발자 도구의 취소선 표시로 중복 선언을 도구 없이도 직접 찾을 수 있습니다.
- Stylelint의
no-duplicate-selectors같은 린터 규칙을 설정해두면 새로 생기는 중복을 지속적으로 감지할 수 있습니다. - 서로 다른 속성은 충돌 없이 그대로 합쳐지며, 값이 바뀌는 경우는 같은 속성이 중복 선언됐을 때뿐입니다.
- 중복 선택자 병합은 사용하지 않는 CSS를 지우는 작업과는 별개입니다.
CSS 코드를 붙여넣으면 중복 선택자를 찾아 하나로 병합해 보여줍니다. 설치나 가입이 필요 없습니다.
자주 묻는 질문
중복 선택자가 있으면 실제로 어떤 값이 적용되나요?
CSS 캐스케이드 규칙상, 특정성이 같은 선택자들 사이에서는 소스 코드상 더 나중에 나온 선언이 적용됩니다. 완전히 동일한 선택자를 여러 번 쓴 경우 특정성이 같으므로, 같은 속성이 중복 선언됐다면 파일에서 더 아래쪽에 적힌 값이 최종값입니다.
서로 다른 속성이면 어떻게 되나요?
충돌하지 않습니다. color와 padding처럼 서로 다른 속성(키)으로 각각 선언되어 있었다면, 병합 시 두 속성 모두 하나의 선언부 안에 그대로 남습니다. 값이 바뀌는 경우는 같은 속성이 여러 번 다른 값으로 선언됐을 때뿐입니다.
도구를 쓰지 않고도 큰 CSS 파일에서 중복을 찾을 수 있나요?
가능합니다. 선택자가 한 줄에 하나씩 단순하게 적힌 파일이라면 grep -oE '^[^{}]+\{' 파일명 | sed 's/[{ ]*$//' | sort | uniq -d 같은 명령으로 두 번 이상 나온 선택자를 뽑아낼 수 있습니다. 압축된 CSS나 중첩 문법에는 그대로 쓸 수 없어 파일을 먼저 펼쳐둬야 하는 제약이 있습니다.
사용하지 않는 CSS 코드(dead code)도 함께 제거되나요?
아닙니다. 이 작업은 동일한 선택자가 여러 번 선언된 것을 하나로 합치는 중복 제거에 한정됩니다. 실제로 HTML·JS에서 그 선택자가 쓰이고 있는지를 판단해 사용하지 않는 규칙 자체를 지우는 것은 별도의 분석 영역입니다.
