본문으로 바로가기

효율적인 CSS 작성 방법

category StyleSheet/CSS 2016. 5. 20. 09:19

효율적인 CSS 작성하기

이 글은 CSS 코드를 최적화하는 방법을 제공합니다. 

특히, 선택자를 효율적으로 작성하는 방법에 대해 집중적으로 다룹니다. 

CSS 명세는 브라우저가 어떻게 스타일 시스템을 구현하는지에 대해 정해두지 않았습니다. 

이 때문에 브라우저마다 스타일 시스템 엔진이 다릅니다. 

널리 사용되는 오픈소스 엔진인 Gecko와 Webkit은 비슷한 알고리즘으로 스타일 시스템을 구현하고 있으므로 장점과 단점이 비슷합니다. 

따라서 이 문서에 있는 팁은 실제 웹 문서에서 유용할 것입니다.





스타일 엔진은 어떻게 스타일 규칙을 분류하는가?!

스타일 엔진은 다음 4개의 카테고리로 스타일 규칙을 분류합니다. 

ID 규칙, Class 규칙, Tag 규칙, Universal 규칙, 이 4개의 규칙들은 스타일 규칙을 적용하는데 기본적인 역할을 하므로 이해하는것이 중요합니다. 

다음 문단부터 키 선택자라는 용어를 사용하도록 하겠습니다. 

키 선택자란 선택자의 마지막 선택자(선택되는 엘리먼트를 가리키는)를 의미합니다.


예를들어, 다음과 같은 규칙에서 키 선택자는 img, p 그리고 title입니다.

css
a img, div > p, h1 + [title] { … }


ID 규칙

첫번째 카테고리는 ID 선택자를 키 셀렉터로 가지는 규칙들로 이루어집니다.

예제 :

css
button#backButton {…} /* 이건 ID 규칙이다. */
#urlBar[type="autocomplete"] {…} /* 이것도 ID 규칙이다. */
treeitem > treerow > treecell#myCell:active {…} /* 이것도 ID 규칙이다. */


Class 규칙

어떤 규칙의 키 선택자에 class가 명시되어 있으면 이건 Class 규칙에 속합니다.

예제 :

css
button.toolbarButton {…} /* Class 규칙 */
.fancyText {…}	/* Class 규칙 */
menuitem > .menu-left[checked="true"] {…} /* Class 규칙 */


Tag 규칙

어떤 규칙의 키 선택자에 class와 ID가 명시되지 않고 tag가 있다면 이 규칙은 Tag 규칙에 속합니다.

예제 :

css
td {…} /* Tag 규칙 */
treeitem > treerow {…} /* Tag 규칙 */
input[type="checkbox"] {…} /* Tag 규칙 */


Universal 규칙

위에서 언급한 세개의 규칙에 속하지 않는 모든 규칙은 여기(Universal)에 속합니다.

예제 :

css
[hidden="true"] {…} /* universal 규칙 */  
* {…}  /* universal 규칙 */
tree > [collapsed="true"] {…} /* universal 규칙 */




스타일 엔진은 어떻게 특정 엘리먼트에 규칙을 적용하는가?!

스타일 엔진은 키 셀렉터로부터 시작하여 왼쪽으로 이동하면서 엘리먼트가 규칙에 적합한지 확인합니다. 

만약 엘리먼트가 이 규칙에 적합하거나 적합하지 않다는게 확인되면 멈추게 됩니다. 


가장 기본적인 개념은 규칙 필터링입니다. 

위에서 소개한 4개의 규칙 카테고리는 관계없는 규칙을 제거하기 위함입니다.(따라서 스타일 엔진은 엘리먼트와 관계없는 규칙을 매칭하는데 시간을 낭비하지 않을 수 있다). 


성능을 비약적으로 향상시키는 방법은 바로 이것입니다. 

주어진 엘리먼트가 적합한지 확인하는데 고려해야할 규칙의 수가 적을수록 성능이 좋아지는 것입니다. 


예를 들어, 어떤 엘리먼트가 ID를 가지고 있다고 가정해 봅니다. 

스타일 엔진은 이 엘리먼트의 ID와 같은 ID를 가지는 ID 규칙만을 적용할지 말지 확인할 것입니다. 

스타일 엔진은 이 엘리먼트의 class에 해당하는 Class 규칙만을 적용할지 말지 확인할 것입니다. 

Tag 규칙도 이 엘리먼트의 태그에 해당하는 규칙만이 확인될 것이고, Universal 규칙은 모두 확인될 것입니다.




효율적인 CSS를 작성하기 위한 지침

universal 규칙을 피하라.

  • 선택자가 universal 규칙에 속하지 않는지 확인하라.


ID 규칙에 쓸모없는 태그나 클래스를 붙이지 말라.

  • 만약 어떤 규칙이 키 선택자로 ID 선택자를 가지면 여기에 부차적인 태그를 붙이지 말라. ID는 고유하므로 여기에 태그를 붙이는 것은 매칭 작업을 더디게 만든다.
css
button#backButton {…} /* 나쁨 */
.menu-left#newMenuIcon {…} /* 나쁨 */
#backButton {…} /* 좋음*/
#newMenuIcon {…} /* 좋음 */


예외: 만약 여러가지 다른 스타일을 위해 ID가 지정된 엘리먼트의 class가 동적으로 바뀌고 이 class가 ID가 지정되지 않은 다른 엘리먼트와 공유될 경우에는 클래스 선택자가 필요하다.


Class 규칙에 쓸모없는 태그를 붙이지 말라

이전 내용이 여기에도 적용됩니다. class는 한 문서에서 여러번 사용되지만 태그보다 그 수가 적습니다. 

하나의 관례는 class 이름에 적용할 태그 이름을 포함시키는 것입니다. 그러나 이러면 유연성을 잃게 됩니다. 

예를 들어, 디자인이 바뀌어 태그 이름이 달라지는 경우 class 이름을 모두 변경해야 합니다. (의미가 있는 이름을 사용하는 것이 최선이다. 이것은 분리된 스타일시트를 사용하는 이유이기도 하다.)

css
treecell.indented {…} /* 나쁨 */
.treecell-indented {…} /* 좋음 */
.hierarchy-deep {…} /* 최선 */


가장 명확한 규칙을 적용하라

성능이 저하되는 가장 큰 이유는 Tag 규칙에 속하는 규칙이 너무 많이 때문입니다. 

엘리먼트에 클래스를 추가함으로써 Tag 규칙에 속하는 규칙을 Class 규칙에 속하는 규칙으로 바꿀 수 있습니다. 

이는 같은 태그를 가진 다른 규칙을 매칭하는데 낭비되는 시간을 줄여줄 수 있습니다.

css
treeitem[mailfolder="true"] > treerow > treecell {…} /* 나쁨 */
.treecell-mailfolder {…} /* 좋음 */


자손 선택자를 피하라

자손 선택자는 CSS에서 가장 속도가 느린 선택자입니다. 이것은 끔찍하게 느립니다. 

특히 Tag 규칙이나 Universal 규칙에 속할 경우에는 말할 필요조차 없습니다. 

흔히 자식 선택자로 대체할 수 있습니다. 

예를 들어 자손 선택자는 속도가 너무 느려 파이어폭스 사용자 인터페이스 CSS에서 제거되었습니다. 

여러분의 웹 페이지를 이같이 변경하려는건 좋은 생각일 것입니다.

css

treehead treerow treecell {…} /* 나쁨 */ 
treehead > treerow > treecell {…} /* 개선되었지만 여전히 나쁨 (다음 지침을 보라) */


Tag 규칙은 자식 선택자를 절대로 포함하지 말라

Tag 규칙에 속하는 규칙에 자식 선택자를 함께 사용하지 말라. 

이것은 매칭하는데 소요되는 시간을 그 엘리먼트가 등장하는 만큼 비약적으로 증가시키게 됩니다.(특히 그 규칙이 매칭될 것 같이 보일 때)

css
treehead > treerow > treecell {…} /* 나쁨 */
.treecell-header {…} /* 좋음 */


자식 선택자를 사용할 때에 항상 주의하라

자식 선택자를 사용할 때에 항상 주의하라.

가능하다면, 피하라.

특히 RDF 문서와 메뉴에서 자식 선택자는 자주 사용된다.

css
treeitem[IsImapServer="true"] > treerow > .tree-folderpane-icon {…} /* 나쁨 */ 

REF 속성은 템플릿에서 중복되게 할 수 있다는 것을 기억하라! 이것의 이점을 살려라. RDF 속성을 자식 XUL에 대해 중복되게하고 선택자를 간소화하라.

css
.tree-folderpane-icon[IsImapServer="true"] {…} /* 좋음 */


상속을 사용하라 

어떤 속성들이 상속되는지 배우고 사용하라.

예를들어, XUL 위젯은 부모의 list-style-image나 font 규칙을 자식 엘리먼트에 대해 적용합니다. 

자식 엘리먼트들에 대해 이 규칙을 적용하는건 시간낭비입니다.

css
#bookmarkMenuItem > .menu-left { list-style-image: url(blah) } /* 나쁨 */
#bookmarkMenuItem { list-style-image: url(blah) }/* 좋음 */

위의 예처럼 상속되는 속성을 알고 있다면 class 규칙이 id 규칙으로 변환될 수 있습니다. 

위의 "나쁜 규칙"은 모든 .menu-left가 #bookmarkMenuItem에 속하는지 확인하게 합니다. 

만약 여러개의 메뉴가 있다면 이는 매우 느립니다. 

반면 "좋은 규칙"은 엘리먼트가 #bookmarkMenuItem인지 아닌지만 확인하게 됩니다.


-moz-image-region을 사용하라! 

여러개의 이미지를 하나의 이미지에 담고 그것을 -moz-image-region 로 선택하는 것이 각 이미지를 각각의 파일에 넣는 것보다 훨씬 빠릅니다.



Jaehee's WebClub



[출처] MDN https://developer.mozilla.org/ko/docs/Web/CSS/Writing_Efficient_CSS#Avoid_the_descendant_selector.21