본문으로 바로 이동 페이지 설정으로 이동 메뉴로 이동
페이지 설정
  • 어떠한 의견도 좋습니다. 웨버스터디가 더 나은 모습이 되도록 의견을 보내주세요.

다중 CSS 스타일 시트와 우선 순위

최초 작성일
최종 수정일
이번 시간에는...
여러 CSS 파일들을 어떻게 사용하고 관리하는 지, link와 @import의 차이를 비교하여 보다 CSS를 최적화 할 수 있도록 합니다. CSS 파일들이 서로 충돌(겹침)이 일어날 때, 어떤 선택자가 우선되는 지 CSS 선택자의 우선 순위를 알아 봅니다.

이번 시간에는 하나의 웹 페이지에 여러 개의 스타일 시트를 사용하는 방법에 대해 다룹니다. 이를 통해서 사이트를 보다 가볍고, 효율적으로 관리 할 수 있도록 합니다. 그리고 추가적으로 CSS 선택자들의 우선 순위를 살펴 보도록 하겠습니다.

다중 스타일 시트 (Multiple Style Sheet)

개인이든, 사업자이든 홈 페이지를 제작하게 되면, 보통 여러 개의 웹 페이지를 가지게 됩니다. 그리고 이러한 웹 페이지에는 각 페이지에 맞는 스타일이 들어가게 됩니다. 만약 인트로 페이지, 본문 페이지, 사이트맵 페이지가 있다면, 각각에 들어가는 스타일들은 다를 것입니다.

여기서 만약 이 스타일들을 단 한 개의 스타일 시트 파일(CSS)로 만들어 관리를 한다고 합시다. 그러한 상황에서 검색엔진을 통해서 바로 본문 페이지에 오게 된 방문자가 있습니다. 그 방문자의 브라우저는 웹 페이지를 보여주기 위해서 CSS파일을 다운 받습니다. 하지만, 그 CSS 파일에는 본문 페이지에서 사용하는 스타일 뿐만 아니라 기타 다른 페이지들의 스타일들이 모두 들어있습니다. 만약 페이지가 많은 사이트라면, 그 CSS 파일의 용량은 매우 클 것입니다. 그에 따라, 그 방문자는 페이지를 여는데 오래 걸리는 것을 기다리지 못하고, 바로 페이지를 닫고 다른 웹 페이지로 떠날지 모릅니다.

이렇게 무거운 페이지가 아닌, 가볍고 효율적인 페이지를 위해서 보통 여러 개의 스타일 시트를 나눠서 사용 합니다. 공통으로 사용하는 시트, 해당 페이지에서만 사용하는 시트 등을 나누어 관리하게 되면, 해당 방문자에게 필요한 스타일 시트만 제공하면서, 웹 페이지는 보다 가벼워지며, 관리하기도 보다 쉬워집니다.

link 요소를 이용한 방법

이렇게 스타일 시트를 여러 개 사용하기 위한 방법으로는, 우리가 HTML의 head 요소에 넣어 사용했던 link 요소를 사용하면 됩니다. 이 방법은 아주 간단하게 link 요소를 추가로 더 넣어주면 끝 입니다. 다중 스타일 시트를 사용하는 데 무조건 추천하는 방법입니다.

@import를 이용한 방법

또 다른 방법은 CSS 파일 내에 '@import'를 사용하는 방법입니다. 이 방법은 요새는 거의 사용하지 않으며, 여러분에게도 권장하지 않는 방법입니다. 하지만, 먼저 어떻게 사용하는지 정도는 살펴보도록 하겠습니다. 우선 이 '@import'는 CSS 파일에 작성하며, 무조건 CSS 파일 내에서 선택자들 보다 먼저 선언되어야 합니다. 다음은 'article.css' 파일에 'initial.css'를 추가시킨 것 입니다.

이와 같이 문서 처음에 '@import'를 적고, 'url()' 안에 해당하는 CSS 파일의 주소를 적습니다. 이렇게 하면, 'link' 여러 개를 사용한 것처럼, 여러 스타일 시트를 불러 올 수 있습니다. 만약 문서 내에서 @import 보다 먼저 다른 내용이 있다면, 적용이 안될 수 있으므로 주의 해야 합니다. 이 '@import'를 사용한다면, 아마 HTML 페이지에서는 link 요소를 한 번만 사용해도 될 것입니다.

왜 @import보다 link를 권장 할까?

언뜻 보면, @import가 CSS 파일 내에서 모두 해결하기 때문에, 더 깔끔해 보일 수도 있습니다. 하지만, @import는 안 좋은 부분들이 있습니다.

일단 @import는 관리를 어렵게 합니다. 물론 link나, @import나 여러 개의 스타일 시트를 사용하기에, 제작자가 관리를 하지 않는다면, 둘 다 어려워지는 것은 마찬가지 입니다. 하지만, @import의 경우는 파악하기가 좀 더 힘듭니다. 특히 @import로 넣은 스타일 시트 안에 또 다른 @import가 존재하고, 또 그 스타일 시트에 @import가 존재하는 식이라면, 스타일 시트를 파악하는 게 더 불편해집니다. 또한, 스타일 시트 내에서 병합이 일어나기 때문에, 만약 해당 페이지가 @import되는 스타일 시트가 불 필요할 지라도, 페이지가 필요한 스타일 시트만 선택할 수 없습니다.

또 다른 중요한 이유로는, 바로 웹 페이지의 로딩 속도를 늦추기 때문입니다. 기본적으로 웹 페이지에 접속하면, 일단 웹 브라우저는 html 파일이나, css 파일 이미지 등을 다운 받습니다. 보통 로딩의 상당 수는 이렇게 해당 파일들을 다운 받는데 소모 됩니다. 여기서 link@import간의 차이점이 발견되는데, link를 사용할 경우 파일을 병렬로 같이 받습니다. (다운로드의 요청이 거의 동시에 이루어 집니다.) 하지만 @import의 경우 우선 link된 파일을 받고, 그 다음 안에 @import된 스타일 시트를 받게 됩니다.

방법에 따른 css를 다운받는 시간을 비교한 모습
import를 이용한 방법은 import로 들여오는 css를 더 늦게 읽습니다

이렇게 되면, 아무래도 웹 페이지를 로딩하는데 지연이 생길 수 밖에 없습니다. 그렇기 때문에 지금은 @import 방식은 거의 사용하지 않으며, 여러 분들도 link 요소를 이용하시기 바랍니다.

스타일 시트를 무조건 여러 개로 나누는 것이 좋은 것일까?

아까 가벼운 웹 페이지와 효율적인 관리를 위해서 스타일 시트를 나누는 것이 좋다는 말씀을 드렸습니다. 그렇다면, 스타일 시트를 무조건 여러 개로 나누는 것이 더 좋을 까요? 일단 어감에서 예상 하셨듯이, 그렇지는 않습니다. 아마도 스타일 시트를 여러 개로 나누게 되면, 관리적인 측면에서는 편할 것이라 예상됩니다. (물론 관리할 수 있는 범위 내에서 잘 나누게 된다면 말입니다.) 하지만, 속도적인 측면에서 오히려 더 느려질 수 있습니다.

웹 브라우저가 파일들을 다운로드 받기 위해서는 먼저 서버에 파일을 요청해야 합니다. 문제는 이렇게 서버에 요청하는 것 역시, 무시하지 못 할 시간을 소요하게 됩니다. 때문에 같은 총 용량을 가졌더라도, 하나의 파일을 받는 것과 여러 개의 파일을 받는 것 중, 하나의 파일을 받는 것이 더 빠릅니다. (이런 이유로, 웹 페이지를 최적화 할 때 여러 이미지를 하나로 합치기도 합니다.) 그렇기 때문에, 무의미할 정도에 시트 분할은 오히려 속도에 악영향을 주게 됩니다.

이 스타일 시트를 나누는 것에 정답이 있는 것은 아닙니다. 예를 들어 만약 본문 페이지에 방문 했더라도, 대부분 그 다음 다른 페이지에 접속을 하게 된다면, 오히려 그 두 개의 페이지의 스타일 시트를 하나로 만드는 것이 더 나을 수도 있는 것입니다. 이 부분은 여러분들이 작업을 해보고 고민해 보면서 자연스럽게 작업하게 될 것입니다.

스타일의 우선 순위

일단 우리는 예전 '선택자 1' 시간에서 선택자들 간에는 우선 순위가 있다는 것을 간단히 배웠습니다. 사실 그 정도만 알고 있어도, 스타일 시트를 작성하고 적용하는데 큰 어려움은 없습니다. 하지만, 그럼에도 종종 우선 순위를 예상 못해서 스타일이 덮어 씌워지기도 합니다. 이번에는 이 우선 순위에 대해 좀 더 다루도록 하겠습니다.

스타일 시트의 우선 순위

우선 다중 스타일 시트를 사용했을 때, 스타일 시트간의 우선 순위는 어떨까요?

사실 다중 스타일 시트라고 해서, 스타일 시트간 우선 순위는 특별히 없습니다. 그냥 스타일 시트들을 펼쳐서 하나의 시트라고 생각하시면 편합니다.

각 CSS 파일 내에서 아마도 같은 우선 순위를 가진 선택자라면, 아래에 들어가있는 CSS의 선택자로 덮어 씌워질 것입니다. 당연히 같은 급의 선택자라면, 나중에 선언된 선택자가 우선합니다.

하지만, 우리가 link@import 등으로 넣은 스타일 시트 말고도, 브라우저가 자체적으로 내장된 스타일 시트가 있고, 사용자가 브라우저에서 넣을 수 있는 스타일 시트가 있습니다. 일단, 브라우저가 자체적으로 내장한 스타일 시트는 우리가 CSS가 없는 HTML 파일을 열었을 때, H1 요소의 글씨가 크게 보이고, a 요소에 파란 색이 들어가 보이는 기본적으로 내장된 스타일 시트를 말합니다. 그리고 사용자가 넣는 스타일 시트는 대부분의 사용자가 알지도 못하지만, 보통 브라우저 옵션에서 기본적인 서체를 바꾸거나 할 수 있으며, IE 같은 경우는 별도의 스타일 시트를 넣을 수도 있습니다. (다른 브라우저도 부가기능이나, 파일을 특정 폴더에 넣는 방식 등으로 지원하고 있으니, 관심 있으신 분들은 추가적으로 더 검색해 보시기 바랍니다.)

이러한 '브라우저의 기본 스타일 시트', link 등으로 삽입된 '제작자의 스타일 시트', 마지막으로 '사용자가 추가한 스타일 시트' 간에는 우선 순위가 존재 합니다. 일단은 이 스타일 시트간의 우선 순위를 먼저 살펴보겠습니다.

스타일 속성의 우선 순위 (숫자가 높을 수록 높습니다.)
우선 순위 속성 선언 종류 부가 설명
1(낮음) User Agent 선언 브라우저의 기본 스타일 시트
2 사용자 선언 (일반) 사용자의 스타일 시트
3 제작자 선언 (일반) 제작자가 넣은 스타일 시트
4 제작자 선언 (중요) 제작자가 넣은 시트 중 중요 표시한 속성
5(높음) 사용자 선언 (중요) 사용자가 넣은 스타일 시트 중 중요 표시한 속성

여기서 보면, 사용자 선언이나 제작자 선언 까지는 알겠는데, 일반과 중요가 있다는 것은 처음 보셨을 것입니다. 여기서 일반 선언은 기본적으로 작성된 CSS를 말합니다. 그리고 중요 선언은 그 작성된 CSS 안에서 !important라는 것을 해당 속성 값 바로 다음에 작성해 주는 것입니다. 다음과 같이 작성합니다.

여기서 보면, p 선택자를 두 번 써서 겹치게 썼기 때문에, 스타일은 아래 속성들로 덮어 씌어야 합니다. 다음과 같이요

font-size: 12px;
color: red;
line-height: 1.5;
font-size: 14px;
color: blue;

하지만 저기 color: red 다음에 !important를 넣어 줌으로써, 이 속성은 중요 속성이 되었습니다. 그렇게 되면 중요 속성은 다른 일반 스타일 속성들 그 무엇보다 우선하게 되므로, 글자 색은 빨간 색으로 출력됩니다. 이 중요 속성은 심지어 style="color:red;"같은 HTML 요소에 속성으로 추가한 스타일 보다도 우선합니다.

하지만, !important는 우선 순위가 매우 높은 만큼, 이 속성을 덮어 씌우기 위해서는 또 다른 !important가 필요하게 되므로 응급한 상황이 아니라면, 이 '중요 선언'은 자제하시기 바랍니다.

선택자의 우선 순위

이번에는 실질적으로 CSS를 만드는 웹 제작자의 스타일 시트 안에서의 우선 순위를 살펴 보도록 하겠습니다. 이 선택자간의 우선 순위를 정하는 시스템에는 a,b,c,d 네 단계가 있습니다. 이 중 a가 가장 급이 높고 순차적으로 b, c, d 순이며, 선택자마다 해당 급의 숫자가 매겨집니다. 이 급은 올림픽에서 금, 은, 동을 가지고 국가의 순위를 내는 것과 비슷합니다. 아무리 금 0개, 은 100개를 획득한 나라보다 금 1개를 딴 나라가 순위가 높듯이, b의 숫자가 아무리 높더라도, a의 숫자가 높은 게 우선되는 식입니다.

해당 a, b, c, d에 숫자를 높이는 규칙은 다음과 같습니다.

a
CSS의 선택자가 아닌, 요소에 직접 style 속성으로 스타일을 주는 경우에만 숫자가 1이 됩니다.
b
선택자 중에서 id 선택자(#abc)의 개수만큼 숫자가 올라갑니다. (예를 들어 '#a'이면 1이되고, '#a #b'가 되면 2가 됩니다.)
c
선택자 중에서 클래스 선택자(.abc)를 포함한, 요소의 속성을 이용한 선택자(아직 다루진 않았습니다) 그리고 가상 클래스(pseudo-class) 선택자(a:link)의 개수 만큼 숫자가 올라갑니다.
d
요소 명(p, h1 같은 요소 자체의 이름)으로 준 선택자가상 요소(pseudo-element) 선택자(아직 다루진 않았습니다)의 개수 만큼 숫자가 올라갑니다.

다음은 이해를 돕기 위해 예시를 도표로 만들어 보았습니다. 괜히 도표가 수학적으로 보여서 복잡해 보일 수도 있지만, 그냥 참고만 하시면서 이해하고 넘어가기 바랍니다.

선택자의 우선 순위 단계 예제
선택자 단계 점수 해설
a b c d
* 0 0 0 0 '*' 선택자는 아무런 우선 순위를 가지지 않습니다.
style="color:red;" 1 0 0 0 a에 숫자를 가질 수 있는 것은 직접 요소에 style 속성을 통한 방법 뿐입니다. 때문에, 이 속성을 CSS에서 덮어씌우기 위한 방법은 !important 밖에 없습니다.
h1 0 0 0 1 h1(d) : h1은 요소 이름이므로 d
div a:hover 0 0 1 2 div(d) + a(d) + :hover(c)
div p + p 0 0 0 3 div(d) + p(d) + p(d)
#list li 0 1 0 1 #list(b) + li(d)
.abc a:link 0 0 2 1 .abc(c) + a(d) + :link(d)
#test div.abc 0 1 1 1 #test(b) + div(d) + .abc(c)

지금 이런 도표를 보고서 순간 머리가 멍해지셨을지 모르겠습니다. 사실 실제로는 이렇게 까지 정확하게 외우실 필요까진 없습니다. 이것은 어디까지나 선택자의 우선 순위의 계산 방식을 분명히 설명하다 보니, 이런 도표까지 보여드리게 된 것입니다. 이 내용은 어디까지나 참고만 하셔도 작성하는데 큰 문제는 없으니, 이것에 너무 스트레스 받으시지 않기 바랍니다. 이 정도의 내용은 작업을 하다가, 우선 순위 때문에 의외의 결과가 나왔을 때, 확인 차 참고하시는 정도로 보시면 됩니다.

요점 정리
  • 여러 CSS를 넣는 방법으로 link태그를 쓰는 방법과 CSS파일 내에 @import를 쓰는 방법이 있음.
  • 하지만 @import는 관리를 어렵게 하고, 페이지의 로딩 속도를 지연 시킴.
  • CSS 파일을 너무 여러개로 쪼개는 것은 그만큼 서버에 요청하는 횟수를 늘려, 로딩 속도에 지연을 가져옴.
  • CSS 선택자의 우선 순위는 [브라우저 스타일 < 사용자 일반 스타일 < 제작자 일반 스타일 < 제작자 강제 스타일 < 사용자 강제 스타일] 순
  • 강제 스타일은 속성 값 뒤에 !important를 붙여서 표현. 사용 자제 권장.
  • 선택자의 우선 순위는 a, b, c, d 단계 점수를 조합하여 결정.
  • 보통 요소에 style 속성으로 직접 주는 것이 가장 높음
  • 그 다음으로 #id 같은 아이디 선택자
  • 보통 그 다음은 .class 같은 클래스 선택자
  • 그리고 태그 선택자와 :hover같은 상태 선택자 순

이 글이 유용하셨다면 친구들에게 공유 해주세요.