CSS를 참조하는 링크는 왜 HTML 상단에 위치해야 할까?

Bosees·2021년 11월 2일
0

WEB_Programming

목록 보기
1/5

Intro🧐


개발을 공부하는 대표적인 방법 중 가장 쉬우면서 빠르고 당연하게 선행되는 게 바로 다른 사람의 코드 스타일을 보고 배우는 방법이다. 유튜브에서 동영상을 보고 배우는 클론 코딩 이라던가, 책을 통해서 배우는 다른 사람의 코드들도 역시 암묵적인 규칙안에 각자의 코드 스타일이 조금씩 녹아 들어있다. 나도 마찬가지로 개발하면서 다른 사람의 코드를 모방하고 응용 하던 중, 궁금 했었던 것 중 하나인 HTML 내에 JavaScript를 참조하는 태그 혹은 CSS를 참조하는 태그들의 위치가 사람마다 다르다는 것에 초점을 두고 궁금증을 해결하려고 한다.

웹브라우저의 동작원리


브라우저의 동작 원리를 간단하게 설명하자면 도메인 서버와 통신하여 호스트의 IP를 찾고 해당 IP를 가진 서버와 TCP 연결을 맺는다.
이후 연결이 맺어지면 브라우저는 서버로부터 필요한 리소스들을 다운로드하게 되는데 이 순간이 내가 오늘 궁금증을 풀어줄 수 있는 순간이다.

브라우저가 리소스를 다운로드 할 때는 먼저 방문 페이지에 HTML을 서버에 요청해 다운로드 하게 되는데. 브라우저는 HTML의 구문 분석(parsing)하면서 HTML에 참조된 CSS, JavaScript, 이미지, 폰트 등의 하위 리소스들을 차례대로 다운로드하여 최종적으로 브라우저가 이해할 수 있는 렌더 트리(Render Tree)를 구성하게 된다.

이때 브라우저가 작동하는 순서를 다시 한번 정리해본다면

1. 맨 처음 HTML을 다운로드하여 파싱 하면서 DOM(Document Object Model)트리를 만들어간다.

2. HTML을 파싱 하던 중에 CSS를 참조하는 링크 태그를 만나게 되면 DOM과 비슷하게 CSS 리소스를 다운로드하고 구문 분석기가 CSSOM 트리를 만들게 된다.

여기서 중요한 점은 동작 스레드가 다르기 때문에 싱글 스레드처럼 HTML의 파싱 과정이 잠시 멈추는 게 아니라 개별적으로 멀티 스레드처럼 생성하게 된다.

3. 그 이후 DOM tree와 CSSOM tree를 병합하는 과정에서 레이아웃 이라던지 스타일시트의 속성값 등을 계산해 렌더 트리를 생성하게 된다.

여기서 한가지 변수가 있는데 바로 JavaScript이다.
JavaScript는 DOM tree에 접근할 수 있는 DOM API가 있는데, 이미 파싱된 DOM tree 나 CSSOM tree를 언제든지 변경 시킬 수 있기 때문이다.

HTML 구문 분석기는 파싱 도중 JavaScript 참조하는 태그를 만나면 자바스크립트를 다운받고 수행이 완료되기 전까지 DOM tree의 생성 작업을 중단한다.

하지만 이 시점에서 특정 CSS에 대한 구문 분석 처리 및 CSSOM 생성 작업이 진행 중이라면 JavaScript가 변경하려는 스타일 시트가 아직 생성되지 않았을 수도 있다. 그러므로 CSSOM이 생성이 완료되기 전까지 JavaScript는 수행을 중단시킨다. 만약 원하는 스타일 시트가 생성되기도 전에 JavaScript가 수정하려는 경우 스크립트 오류가 발생하여 만들고자 하는 웹페이지가 생성되지 않는다.

결론적으로 렌더링에 있어 CSS가 자바스크립트보다 더 높은 우선순위를 가질수밖에 없다.

이러한 경우를 피하려면 HTML이 파싱되는 과정 중 CSS를 참조하는 태그를 최대한 빨리 만나야 하고, JavaScript는 HTML 내부에서 아래쪽에 위치하도록 하여 이 시간적인 차이를 최대한 벌려놓는다. 이러한 배치는 렌더링의 성능과 밀접하게 관여하는 일이기도 하니 지켜주는게 가장 바람직하다고 볼 수 있다.

그런데도 요즘에는 JavaScript 태그 안에 defer와 async 옵션을 주어서 조금 더 브라우저가 렌더링 할 수 있는 우선순위를 개발자 쪽에서 지정해주는 방법이 있다.

결론😤


CSS가 상단에 있는 이유는 렌더링이 되는 타이밍과 밀접한 관계가 있고 성능에도 영향을 끼칠 수 있기 때문이다.
앞으로 개발을 할 때는 Javascript를 아래쪽에 배치하거나 상단에 배치하는 경우 Async와 defer 옵션을 주어서 렌더링이 되는 타이밍을 결정해줄 필요가 있다.
무지성으로 그냥 쓰는 게 아닌 원리를 알고 다른 사람에게 이해시켜줄 수 있는 개발자가 되기 위해 좀 더 탐구심을 갖고 공부해야겠다.

참조: 루비페이퍼<웹 성능 최적화 기법>

profile
블록체인 프론트엔드 개발자

0개의 댓글