주다훤 블로그

CSSOM

브라우저가 CSS를 자바스크립트로 조작할 수 있도록 객체 구조로 표현한 CSS 객체 모델
CSSOM

CSSOM은 브라우저가 CSS를 자바스크립트로 조작할 수 있도록 객체 구조로 표현한 CSS 객체 모델입니다.

CSS 객체 모델(CSSOM)

CSS 객체 모델(CSS Object Model, CSSOM)CSS 스타일 정보를 자바스크립트가 제어할 수 있도록 객체로 표현한 것이다. 영어로는 주로 약어 CSSOM으로 표현하고, 한국어로는 씨에스에스 오엠 또는 씨솜이라고 읽는다.

DOM은 HTML 문서를, BOM은 브라우저 환경을 객체 구조로 표현한 것이라고 했다. CSSOM은 같은 원리를 CSS에 적용한 것이다.

CSSOM은 왜 필요할까?

DOM은 문서의 구조를 알고 있다. <h1>, <div>, <p> 같은 요소가 어디에 있는지는 안다. 하지만 그 요소가 어떻게 보여야 하는지는 모른다.

style.css
h1 {
  color: red;
  font-size: 32px;
}
 
.hidden {
  display: none; /* 화면에 표시하지 않음 */
}

이런 스타일 정보는 CSS 파일에 담겨 있다. 브라우저가 이 CSS를 해석해서 "h1은 빨간색이고 32px이다", ".hidden 클래스가 붙은 요소는 화면에 표시하지 않는다"는 것을 알아야 한다.

그 해석 결과를 객체 구조로 정리한 것이 바로 CSSOM이다.

CSSOM 트리

DOM과 마찬가지로, CSSOM도 트리 구조로 구성된다.

브라우저는 CSS를 파싱할 때 다음 순서를 따른다.

  1. CSS 파일(또는 <style> 태그)을 읽는다.
  2. 각 규칙을 파싱하여 선택자와 속성으로 분리한다.
  3. 이를 트리 구조로 구성한다. 상위 요소의 스타일이 하위 요소에 상속되는 구조다.

CSSOM 트리 이미지 출처

스타일 상속

CSSOM 트리에서 중요한 특징은 상속(Inheritance) 이다.

style.css
body {
  font-size: 16px;
  color: #333;
}
 
p {
  font-weight: bold; /* 직접 지정 */
  /* 지정되지 않은 속성은 상위 요소로부터 상속받음(font-size: 16px) */
}

이 경우 <p>font-weight: bold를 직접 지정받지만, font-sizebody로부터 상속받아 16px이 적용된다. 이런 상속 관계가 트리 구조로 표현되기 때문에, 브라우저는 각 요소의 최종 스타일을 빠르게 계산할 수 있다.

HTML 파싱 중 style를 만나면

DOM 글에서 HTML 파싱 중 <script>를 만나면 HTML 파싱이 멈춘다고 했다. CSS도 비슷한 문제가 있다.

<style> 태그나 <link rel="stylesheet">로 불러온 CSS는 보통 HTML 파싱 자체를 항상 멈추게 하지는 않지만, 화면을 그리는 데 필요한 CSSOM과 렌더 트리 생성을 늦출 수 있어서 render-blocking 리소스로 작동한다. 즉, <script>는 주로 파싱을 멈추고, <style>은 주로 초기 렌더링을 늦춘다고 이해하면 된다.

<style> 태그가 병목이 되는 이유는 브라우저가 화면을 그리기 전에 DOM뿐 아니라 CSSOM도 함께 필요하기 때문이다. CSS가 아직 다운로드되지 않았거나 파싱이 끝나지 않았다면, 브라우저는 요소를 어떻게 그려야 할지 확정할 수 없어서 첫 화면 표시가 늦어진다. 특히 CSS 파일이 크거나 많거나, 첫 화면과 무관한 스타일까지 한꺼번에 로드하면 사용자는 빈 화면을 더 오래 보게 된다.

[해결 방법]

media-query.html
<!-- 항상 렌더 차단 -->
<link rel="stylesheet" href="style.css" />
 
<!-- 인쇄할 때만 적용 — 화면 렌더링을 차단하지 않는다 -->
<link rel="stylesheet" href="print.css" media="print" />

요약하면 CSS는 필요한 것만 먼저, 스크립트는 가능한 파싱을 막지 않게 배치하는 것이 가장 기본적인 최적화다. 이 외에도 번들 크기 최적화나 미디어 쿼리 활용 등 다양한 최적화 방법이 있다.


참고. CSSOM API

자바스크립트에서 CSSOM에 접근할 수 있는 대표적인 API를 정리한다.

document.styleSheets

현재 문서에 적용된 모든 스타일시트 목록을 반환한다.

styleSheets
console.log(document.styleSheets);
// StyleSheetList { 0: CSSStyleSheet, 1: CSSStyleSheet, length: 2 }

CSSStyleSheet 객체 안에는 cssRules라는 속성이 있어서, 개별 CSS 규칙에 접근할 수 있다.

cssRules
const sheet = document.styleSheets[0];
console.log(sheet.cssRules);
// CSSRuleList { 0: CSSStyleRule, 1: CSSStyleRule, ... }

getComputedStyle

특정 요소에 최종적으로 적용된 스타일을 가져온다. 상속, 캐스케이딩, 기본값이 모두 반영된 결과다.

getComputedStyle
const h1 = document.querySelector('h1');
const style = window.getComputedStyle(h1);
 
console.log(style.fontSize);  // "32px"
console.log(style.color);     // "rgb(51, 51, 51)"

element.style과의 차이

element.style인라인 스타일만 반영한다. CSS 파일이나 <style> 태그에서 적용된 스타일은 포함하지 않는다.

element-style
const h1 = document.querySelector('h1');
 
// CSS 파일에서 color: red를 지정했더라도
console.log(h1.style.color); // "" (빈 문자열)
 
// getComputedStyle은 최종 결과를 반환한다
console.log(getComputedStyle(h1).color); // "rgb(255, 0, 0)"
API범위용도
element.style인라인 스타일만스타일 직접 설정
getComputedStyle()최종 계산된 스타일현재 적용된 스타일 조회
document.styleSheets모든 스타일시트CSS 규칙 조회·수정

자세한 내용: MDN CSSOM