복합 선택자와 키 선택자
CSS를 사용할 때 #nav와 같은 단일 선택자를 사용할 수도 있지만, #nav > *와 같은 복합 선택자를 사용할 수도 있다. 이러한 복합 선택자를 읽는 순서는 사람과 브라우저가 다르다. 사람의 경우 왼쪽에서 오른쪽으로 선택자를 읽지만 브라우저는 오른쪽에서 왼쪽으로 읽는다. 이는 복합 선택자의 왼쪽에서 오른쪽으로 탐색을 하는 방식이 오른쪽에서 왼쪽으로 탐색을 하는 방식보다 빠르기 때문이다. 왜 그런지는 이 글에서 자세히 설명되어있다.
해당 글을 요약하자면, 왼쪽에서 오른쪽으로 탐색을 하는 방식을 사용할 경우 DOM 트리의 상위 레벨에서 하위레벨로 탐색을 진행한다(Top-down 방식). 즉, DOM 요소와 매치되는 선택자들을 찾는데 집중한다. 반면 선택자의 오른쪽에서 왼쪽으로 탐색하는 방식을 사용할 경우 DOM 트리의 하위 레벨에서 상위레벨로 탐색을 진행한다(Bottom-up 방식). 즉, DOM 요소와 매치되지 않는 선택자들을 제거하는데 집중한다. DOM 트리와 CSS 선택자의 특성상 후자가 더 좋은 성능을 낸다. 이러한 이유로 브라우저는 오른쪽에서 왼쪽으로 선택자를 읽기 때문에, "왼쪽으로 오른쪽으로 탐색을 할 것이다"라고 가정하고 작성한 CSS 코드의 경우 생각했던 것과는 달리 비효율적인 경우가 많다.
#nav > * {...}
위의 선택자를 사용하여 왼쪽에서 오른쪽으로 탐색을 진행할 경우, ID에 해당하는 DOM 요소를 먼저 선택한 후 모든 자식들을 선택하기 때문에 괜찮은 선택자라고 생각할 수 있다. 하지만 실제로 선택자는 오른쪽에서 왼쪽으로 탐색을 수행하기 때문에 코드 작성시 생각했던 것과는 달리 실제로는 모든 DOM 요소를 선택한 후, 부모가 #nav인 DOM 요소들만 찾는 방식으로 동작하므로 위의 선택자는 매우 비효율적이다(실제 브라우저에서는 최적화된 알고리즘을 사용하기 때문에, 모든 DOM 요소를 선택한 다음 부모가 #nav인 DOM 요소들을 찾는 것 보다는 빠르게 동작할 것이라 생각된다(추측)
[출처] http://epicdevs.com/11
[참고] http://stackoverflow.com/questions/5797014/why-do-browsers-match-css-selectors-from-right-to-left
실무 1년만에 알게 된 사실. 브라우저에서 CSS 선택자는 오른쪽에서 왼쪽으로 읽힌다. 난 당연히 왼쪽에서 오른쪽일거라고 생각했었는데 그동안 짜온 코드가 비효율적이었던 것이다. 처음 배울 때부터 바깥부터 안쪽으로 탐색해 들어가듯이 설명을 들어서 일까? 지금껏 table tbody tr td {} 이 짓(!) 들은 그냥 td {} 였어도 무방한 것 들이었다. 물론 CSS 충돌을 방지하기 위해서는 어느 정도 필요한 것 들이었지만 그간 과하게 쓴 건 아닌지 되돌아 보게 되었다. 아무튼 지금이라도 알게 되어 정말 다행이다.
+소름 돋는 사실 발견.
막 퍼블리싱을 배우던 때(2013.10.18)에 이미 스크랩 해뒀던 내용이다. 스크랩만 해놓고 꼼꼼히는 읽지 않았던 모양이다.
막상 실무에서 보다보면 복합선택자를 자주 쓸 수 밖에 없는데, 이는 습관인 것 같다. 아래와 같은 코드에서는 선택자만 읽어보아도 마크업이 어떻게 되어있는지 대강 알 수 있다.
.community_list ul { margin:0 auto; width:1280px; height:170px; overflow:hidden; }
.community_list ul li { float:left; padding:20px 20px 20px 0; text-align:center; }
.community_list ul li:first-child { margin-left:310px; }
.community_list ul li a img { margin-top:20px; height:60px; }
.community_list ul li a p { margin:10px 0 0; font-size:14px; color:#000; }
.community_list ul li a:hover { border:3px solid #00a99d; transition:border 0.2s ease 0s; }
.community_list ul li a:hover p { color:#00a99d; transition:color 0.2s ease 0s; }
풀어서 쓰는것이 코드 유지보수에 있어서 나을 것이라고 판단했기 때문이다. 코드가 길어짐은 당연히 사이트 로딩 속도에 영향을 주므로 적당히 해야 함이 늘 관건이다. 습관이라는 것이 참 무서운 것 같다. 더군다나 사수가 딱히 없는 상황에서 코드 리팩토링을 스스로 해야함은 늘 한계가 있다.
'개발일지 > 2015' 카테고리의 다른 글
[JS] 프레임워크와 라이브러리 차이점(Framework vs Library) (2) | 2015.02.25 |
---|---|
[티스토리] Syntaxhighlighter 옵션 값 (0) | 2015.02.25 |
[N-MET] CSS Sprites Generator (0) | 2015.02.23 |
[면접질문] front-end 개발자 인터뷰 문제 - CSS 영역 (0) | 2015.02.23 |
[CSS] 벤더 프리픽스를 꼭 사용해야 하나요? (0) | 2015.02.23 |