HTML과 CSS를 사용하여 웹 페이지를 제작할 때 중요하게 생각해야 하는 것은 무엇일까요?
최종적으로는 디자인 가이드나 기획서 등 산출물을 바탕으로 동일한 화면을 출력하는 것일 텐데요
이 과정에서 좀 더 최적화된 웹 페이지를 만들어내는 것 또한 중요한 과제일 것입니다.
1. 소개
웹페이지에서는 종종 불필요한 작업이 일어납니다.
예를 들면 문서의 한 곳에서 수정이 발생하더라도 이를 처리하는 브라우저는 문서 전체를 작업 범위로 간주하기 때문에
나머지 영역에 대한 불필요한 계산 작업을 합니다.
수정이 어떤 범위 내에 있어야 하는지 브라우저에 알릴 방법이 없기 때문입니다.
소개해드릴 CSS Containment Module은 웹페이지에서 선택된 하위 트리를 문서의 나머지 영역과 분리하는 기능을 갖고 있습니다.
이때 분리된 하위트리는 독립적으로 사용될 수 있어서 브라우저는 불필요한 작업을 하지 않을 수 있고
이로 인해 웹페이지의 최적화 및 성능 향상을 가져올 수 있습니다.
CSS에서는 [contain]이라는 이름의 속성으로 사용됩니다.
selector {contain:none | strict | content | [ size || layout || style || paint ]}
CSS 표기법은 위와 같으며 몇 가지 속성값으로 상황에 맞게 활용할 수 있습니다.
2. 속성값
2-1. layout
selector {contain: layout}
해당 속성값은 contain 요소의 layout에 대한 분리를 설정합니다.
layout이 분리된 contain 요소는 외부의 어떠한 요소에도 영향을 받을 수 없고 줄 수도 없는 상태가 됩니다.
이를 통해 페이지를 배치할 때 브라우저는 contain 요소의 내용을 병렬 배치할 수 있고
화면에 우선적으로 보이지 않아도 되는 경우에(화면 밖에 위치하거나, 가려져 있거나) 레이아웃을 지연 시키거나 더 낮은 우선순위에서 배치할 수 있습니다.
아래와 같은 div 구조가 있습니다.
<div class="box_wrap"> <div class="box"> <div class="inner">inner_box</div> </div> <div class="box contain_layout"> <div class="inner">inner_box</div> </div> </div>
각 요소에 대한 position 값의 기준은 최상위 [div.box_wrap]을 기준으로 합니다.
그리고 [div.inner] 요소를 absolute를 사용하여 우측으로 위치시킵니다.
.inner { positon: absolute; right: 0 }
이때의 [div.inner] 요소는 최상위 [div.box_wrap] 요소에 기준으로 이동하지만
contain 요소는 position static 값을 갖더라도 독립적인 상태가 된 것을 볼 수 있습니다.
테스트 경로 : https://codepen.io/witblog/pen/WqBLOg
2-2. paint
selector {contain: paint}
해당 속성값은 contain 요소의 paint에 대한 분리를 설정합니다.
이 경우 contain 요소의 하위 자손이 분리된 paint 영역 외부에는 표현 될 수 없으며 이에 따라서 contain 요소가 화면의 밖에 위치하거나 보이지 않는 상태라면 하위 자손은 표현되지 않습니다.
overflow visible 상태라도 overflow hidden이 된 것처럼 하위 자손은 paint가 분리된 외부 영역으로 표현되지 않습니다.
테스트 경로 : https://codepen.io/witblog/pen/ydWGow
2-3. size
selector {contain: size}
해당 속성값은 contain 요소의 size에 대한 분리를 설정합니다.
이 경우 contain 요소의 크기는 하위 자손에 대해 독립적인 상태로 내부의 크기에 대한 검사를 하지 않고 바로 레이아웃 할 수 있습니다. 특별한 사이즈를 설정하지 않았을 경우 0픽셀로 렌더링됩니다.
그리고 앞서 설명된 paint 속성값과 같이 사용된다면 내부 콘텐츠가 노출되지 않을 수도 있습니다.
테스트 경로 : https://codepen.io/witblog/pen/EBzGwa
2-4. style
selector {contain: style}
해당 속성값은 contain 요소의 style에 대한 분리를 설정합니다.
이 경우 contain 요소와 하위 요소들 이상의 영향을 미칠 수 있는 속성의 경우 해당 효과가 contain 요소를 벗어나지 않습니다.
<div class="wrap"> <h1>title</h1> <h1>title</h1> <h1>title</h1> <h1>title</h1> </div> <div class="wrap" style="contain:style"> <h1>contain title</h1> <h1>contain title</h1> <h1>contain title</h1> <h1>contain title</h1> </div>
.wrap { counter-reset: section; } h1::before { content: counter(section) ". "; counter-increment: section; }
예시와 같이 style 봉쇄가 적용된 contain 요소는 증가 값이 제한 적용되는 것을 확인할 수 있습니다.
테스트 경로 : https://codepen.io/witblog/pen/vqwvem
2-5. 조합형
앞서 설명된 속성값들을 조합하여 활용할 수 있습니다.
selector {contain: content} /* layout, paint */
[content] 값은 size, style을 제외한 layout, paint 값이 적용됩니다.
layout과 paint 봉쇄 효과는 크지 않고 대부분의 콘텐츠들에 충돌하지 않기 때문에 안전하게 적용 할 수 있는 값입니다.
그러나 size에 대한 기능을 포함하지 않기 때문에 contain 요소는 내부 컨텐츠 크기에 계속 반응을 해야 하며
레이아웃 무효화 현상이 트리 위로 깊숙이 침투하는 것을 방지할 수는 없습니다.
selector {contain: strict} /* layout, paint, size */ selector {contain: strict style} /* all */
이러한 부분들에 대해 좀 더 엄격한 기능을 적용하기 위해서는
[strict] 값을 활용하여 더 많은 효과를 적용할 수 있습니다.
3. 성능 비교
아래 단순한 구조의 div 요소 5000개가 있습니다.
이 중에서 한 개 div 요소의 텍스트 내용을 변경하고 reflow를 발생시켜서 브라우저가 페이지를 계산하는 시간을 비교해보겠습니다.
<div class="wrap"> <div class="box" id="check_area">box</div> <div class="box">box</div> <div class="box">box</div> <div class="box">box</div> ... 5000개 </div>
만약 contain 속성의 분리 기능이 적용되지 않는다면
브라우저는 나머지 4999개의 div 요소에 대해 체크를 하면서 많은 시간이 소비될 것입니다.
구분 | contain:none | contain:stric |
비교 | ||
시간 | 3 ~ 6ms | 0.3 ~ 1.9ms |
테스트 경로 : https://codepen.io/witblog/pen/wLbRrj
contain 속성을 사용하기 전과 후의 차이가 적게는 2배에서 많게는 10배 정도까지 시간 차이가 발생하였습니다.
ms의 단위는 실제 분간이 될 정도의 큰 숫자는 아니지만
거대하고 많은 리소스가 포함된 페이지에서는 테스트 보다 더 많은 성능 최적화를 발생시킬 수 있습니다.
4. 브라우저 지원 범위
CSS Containment Module은 지난 4월 30일 후보 권고안 단계가(https://www.w3.org/TR/css-contain-1/) 된 상태로
현재는 일부 브라우저에서만 테스트 가능합니다.
https://caniuse.com/#search=contain
0개의 댓글