코드스피츠 스터디 - CSS Rendering 3화 중 CSSOM (feat. CSS IN JS)

Soye Park·2023년 2월 8일
0
post-thumbnail

히카맹 선생님의 코드스피츠 강의를 들으며 자바스크립트에 대한 이해를 높이기 위해 스터디를 하게 되었다. 이 포스팅은 그에 대한 정리글이다.

들어가면서

CSSOM 이라는 걸 코드스피츠를 통해서 처음 듣게 되었는데, 직접적으로 마주한 적이 한번도 없어 아마 숱한 CSS IN JS 라이브러리들의 내부 로직에 사용되지 않았을까 하는 생각이 들어 겸사겸사 같이 찾아보았다. 보지 않았다고 없는 것이 아니라는 옛 격언들이 와닿는 순간이었다.

고양이 발 엑스레이 사진

마치 고양이 발 엑스레이 같이..

CSSOM(CSS Object Model)

CSSOM은 JS에서 CSS를 조작할 수 있는 API 집합

  • CSSOM을 통해 사용자는 CSS스타일을 “동적”으로 읽고 수정할 수 있다 (정의 : MDN)
  • W3C 명세서

위는 MDN에서의 개념적 설명인데, 그냥 쉽게, 말그대로 JS를 통해 CSS를 조작할 수 있는 API 인 것.
이는 JS를 통해 HTML을 조작하는 DOM API 와 유사하게 보인다.

CSSOM 구조도

위는 CSSOM의 구조인데, CSSOM은 크게는 <style> 태그라고 볼 수 있다. 맞다. 우리가 CSS를 "내부 스타일 시트"로 작성한다고 했을 때 사용하는 그 <style> 태그이다.

가장 중요한 것은 Style DOM Element 속의 sheet 인데 JS를 통해 동적으로 수정할 수 있게 해주는 API가 이 Sheet 내부에 들어있다.

CSSOM 의 장점이 뭔데..?

JS로 CSS 조작하는 방법

일단 JS로 CSS를 조작하는 방법은 크게 두가지가 있다.

  1. DOM의 style을 직접적으로 조작하는 것
<body>
  <div class="test">테스트 중</div>
  <script>
    const el = document.querySelector(".test");
    el.style
  </script>
</body>
  1. CSSOM을 조작하는 것
<style id="s"></style>
<body>
  <div class="insert">인서트 룰</div>
  <script>
    // CSSOM 직접 조작
    const style = document.querySelector("#s");
    const sheet = style.sheet;
    const rules = sheet.cssRules;
    sheet.insertRule(".insert{color: skyblue}", rules.length);
  </script>
</body>

이 두가지 방법의 가장 큰 차이는 1번은 DOM에 Inline 스타일을 추가하는 것이고 2번은 document의 styleSheet를 직접적으로 조작한다는 점이다.


그렇다면 이 둘 중 아무거나 쓰면 될까? 대답은 "아니다."

단도직입적으로 inline 스타일 방식인 전자는 지양하고 후자를 지향해야하는데 이것은 웹의 렌더링 성능 차이가 있기 때문.

우선 inline 방식의 경우 브라우저가 웹페이지를 그릴 때 레이아웃을 계산하기 위해 추가로 리플로우를 발생시키게 되는데 이럴 경우 계속해서 리렌더가 일어날 수도 있는 등 성능적으로 이슈가 발생할 수 있다. 그런 이유로 inline 방식의 CSS사용을 지양하는데 js로 css를 조작할 경우 DOM에 직접 style을 조작하게 되면 결과적으로 inline 방식으로 CSS를 조작하게 되어 성능 이슈가 생길 수 밖에 없다.

그렇기 때문에 훨씬 더 적은 자원을 요구하는 CSSOM 조작방식을 지향하는 것.

아래는 위에 있던 두가지 방법의 코드로 스타일을 적용했을 때인데, DOM을 직접 조작했을 때는 요소에 직접적으로 inline style이 적용된 것을 확인할 수 있다.

DOM 조작과 CSSOM 조작의 차이


결국 그럼 장점은 속도뿐? ㄴㄴ

아니다. CSSOM을 직접적으로 조작한다는 말은 DOM요소가 당장 없더라도 해당 요소에 대해 미리 스타일을 적용해둘 수 있다는 얘기이기도 하다.
그러므로 스타일링을 말그대로 조금 더 "동적"으로 할 수 있다는 장점이 큰 것.

😀 정리하자면 CSSOM 직접 조작 방식의 장점은

  1. DOM의 Style을 직접 조작하는 것보다 빠르다.
  2. DOM요소가 없더라도 미리 스타일을 적용해둘 수 있다.

CSSOM.. 왜인지 CSS IN JS랑 맞닿아있을 거 같아..

CSS IN JS가 뭔데?

CSS를 다루는 방법은 module 방식에서 최근에는 SCSS와 같은 CSS 전처리기부터 emotion, styled-components 와 같은 CSS in JS 라이브러리로 변화해왔다.

여기서 지금 다룰 CSS in JS 란 이름 그대로 자바스크립트로 다루는 CSS 라고 생각하면 된다.


다양한 방식의 CSS IN JS 라이브러리들

CSS IN JS 라이브러리는 정말 다양하게 나와있는데, 그 구현 방식도 제각각 다르다. 유명한 라이브러리들 중 몇가지의 방식을 나열해보자면 아래와 같다.

  1. cssStyleSheet가 추가되는 방식의 "emotion"
  2. cssStyleRule이 추가 또는 변경되는 방식의 "styled-components" 와 "react-jss"

살짝 이상..?한 styled-components

사실 다른 CSS IN JS도 사용해보고자 하였으나... 밤이 늦어 우선 styled-components만 가지고 한번 테스트해보고 나머지는 블로그 자료들을 좀 찾아봤다.

근데 styled-components로 테스트를 해보던 중 내가 찾았던 정보와는 다른 방식으로 작동하는 걸 볼 수 있었는데

에엥? 왜 DOM에 직접적으로 조작하지? 에에엥?

찾아보니..

styled-components의 경우 development 모드에서는 DOM의 style을 직접적으로 조작하는 방식을 쓴다고 한다.
production mode일 때는 공부한 것과 같이 CSSOM을 조작하는 방식!




번외

아 또 블로그들과 MDN과 공식문서 등을 보며 와리가리 움직이다 보니까 CSSOM에 대해서 가장 많은 내용을 언급한 게 있었다... CSSOM 트리에 대한 얘기였는데 그것도 짧게 같이 정리를 해두자면

CSSOM TREE

  1. CSSOM은 결국 DOM Tree와 매칭되어 Render Tree를 형성해야하므로 Tree구조를 가지게 된다.
  2. 만약 CSS가 없는 노드의 경우 (혹은 display : hidden인 경우) 그 노드는 생략됨

Render Tree의 Render 까지의 실행 순서

  1. DOM Tree + CSSOM Tree = Render Tree 탄생
  2. DOM Tree 상의 루트부터 시작해 노드 순회 (Hidden 노드는 생략)
  3. 각 DOM 노드와 일치하는 CSSOM 노드의 규칙을 DOM노드에 적용
  4. 렌더링 - - -

마치며...

좀 더 디테일하게 정리하고 싶은데 이건 아무래도 너무 방대한 얘기가 될 것 같다. 기억이 더 희석되기 전에 한번 정리하는 것이 나을 것 같아 하긴 했는데, 다시 한번 봐야할 것 같다. 추후 정리할 게 더 있으면 새로 추가 포스팅 예정.


참고
JS로 다루는 CSS, CSS-in-JS (feat. CSSOM)
우리가 몰랐던 styled-components 동작원리

profile
응애FE개발자/ 블로그 이전 : https://soyeah-log.vercel.app/

0개의 댓글