웹페이지의 속도를 결정하는 요소 중에서 렌더링 차단 리소스가 있습니다.
최대한 사용자에게 빠르게 웹페이지의 모습을 보여주려면 이 요소는 꼭 제거해둬야 합니다.
렌더링 차단 리소스를 측정하는 방법
우선 내 웹페이지에 렌더링 차단 리소스가 얼마만큼 있는지 알아보려면 측정을 해야합니다.
크롬,파이어폭스 같은 브라우저로 접속해 개발자모드의 네트워크탭으로 가서 일일히 측정할 수도 있지만, 편리한 건 역시 [**구글**]에서 제공하는 PageSpeed Insights입니다.
여기로 접속하셔서 측정해볼 웹페이지의 주소를 입력하고 분석을 누르면 끝입니다.
그리고 위의 사진처럼 렌더링 차단 리소스가 나옵니다.
이 골치아픈 리소스를 찾았으니, 이제 이 리소스의 실체를 알아볼 때입니다.
렌더링 차단 리소스란?
사용자가 웹페이지를 열면 사이트는 운영자가 작성해둔 코드를 위에서 아래로 읽습니다.
그게 HTML, CSS, JAVASCRIPT건 뭐건 간에 그렇습니다.
그런데 코드를 읽는 중에 중요한 내용이 있다면 읽는 걸 멈추고 그걸 먼저 구현합니다.
그 '중요한 것'이 바로 렌더링 차단 리소스입니다.
2가지 요소가 렌더링을 차단합니다.
- CSS
- JAVASCRIPT
제가 앞서 랜더링 차단 리소스는 꼭 제거해야한다고 했습니다.
하지만 여기까지 읽으신 분이라면 이런 생각이 들 겁니다.
[기본*아니, 중요한 거라면서 제거하라니, 이거 모순아니냐?*]
옳은 생각입니다. 하지만 렌더링 차단 리소스 제거가 꼭 CSS와 JAVASCRIPT를 제거한다는 것을 뜻하지 않습니다.
기본 원리는 제가 이전에 설명했던 레이지로드와 놀라울 정도로 흡사합니다.
위의 사진은 사용자가 제 블로그에 접속했을 때 처음으로 보는 모습입니다.
그런데 사용자가 윗부분만 보고 있을텐데, 굳이 밑에 부분에 해당하는 CSS와 JAVASCRIPT를 작동시켜야할까요?
자바스크립트 렌더링 차단 제거 하기
자바스크립트는 주로 DOM을 조작하는 기능이나, 부가적인 요소를 제공합니다.
자바스크립트로 강제로 레이아웃을 짜거나, 상단에 필수적인 ELEMENT 요소를 추가하는 게 아니라면 즉시 발동해야할 이유는 적습니다.
그렇기 때문에 극히 예외적인 경우를 제하면 자바스크립트를 HEAD가 아니라 BODY에 둬야합니다. 그것도 BODY의 가장 마지막에 둬야합니다.
<html>
<head>
.....
<body>
......
<script src="script.js"></script>
</body>
....
</head>
</html>
하지만 유감스럽게도 이건 로딩속도 개선일 뿐이지 렌더링 차단은 여전합니다.
그럴 때 사용되는 게 ASYNC(비동기)와 DEFER(지연)입니다.
사용법은 몹시 간단합니다.
<script src="script.js"> // 기존 사용
<script src="script.js" async> // 비동기
<script src="script.js" defer> // 지연
자바스크립트를 불러오는 태그에 [**async**]나 [**defer**]을 붙여놓으면 됩니다. 이것만으로도 렌더링블록이 되지 않습니다.
그림으로 표현하면 이렇습니다.
async로 처리하면 HTML과 자바스크립트가 동시에 진행됩니다.
defer로 처리하면 HTML이 끝난 후에 자바스크립트가 진행됩니다. async와 defer 둘 중에선 async쪽이 더 빠릅니다.
그래서 특수한 케이스가 아니라면 async로 하면 됩니다.
주의할 점
자바스크립트는 발동 순서가 중요합니다. A란 요소를 정의가 되어있어야 작동한다면 A란 요소를 먼저 정의하도록 하게 해야 합니다.
그렇기 때문에 가장 먼저 발동시켜야할 자바스크립트라면 async나 defer로 지연하면 안 됩니다.
[참고*물론 이런 케이스는 극히 드물고, 설령 이렇게 자바스크립트를 짜두셨다면 비효율적인 행동이므로 다른 해결방식을 찾으셔야 합니다.*]
대중적으로 많이 이용되는 자바스크립트 파일 중에서 이런 경우에 해당되는 건 jquery 파일입니다.
이 녀석을 지연로드하게 되면 jquery가 작동하지 않으니 주의하셔야 합니다.
또한 HTTPS2가 아닌 환경이라면 서버에 요청횟수를 줄여야 하는데 자바스크립트들을 모아 한 파일로 만드는 게 유용합니다.
제가 사용하는 티스토리 블로그는 HTTPS/2가 아니기 때문에 코드가 작동하도록 순서대로 파일에 집어 넣고 JS 파일로 만들면 됩니다.
그리고 HTTPS2 환경인 워드프로세스 블로그를 하신다면 용도마다 JS 파일을 분리하신다음 순서대로 로딩되도록 잘 조합하시면 됩니다.
그리고 가장 중요한 점입니다.
inline으로 제대로 동작하던 코드인데, 이걸 파일에 넣어 불러왔을땐 작동을 안하는 케이스가 있습니다.
바로 [**DomcontentLoaded**] 이벤트죠.
이럴 땐 헬프함수를 써야합니다.
window.addEventListener('DOMContentLoaded' function () {
코드내용
}) // 기존의 코드
var DOMReady = function(callback) { // 헬프함수
document.readyState === "interactive" || document.readyState === "complete" ? callback() : document.addEventListener("DOMContentLoaded", callback);
};
DOMReady(function () {
코드내용
})//정의된 헬프 함수를 이용한 코드
이렇게 하시면 무난하게 async로 자바스크립트의 렌더링 차단을 해결할 수 있습니다.
또, 이런 방법만 있는 것도 아닙니다.
경우에 따라서 사용자가 특정행동을 했을 때에만 발동하는 코드가 있을 겁니다.
예를 들면 스크롤을 일정 거리 아래로 내렸을 때 발동한다거나, 특정 element가 보일때 발동한다거나, 특정 링크에 마우스를 올릴때 발동한다거나, 이런 것들이죠.
이럴 땐 그런 자바스크립트를 미리 넣을 필요가 없습니다.
addeventlistener이벤트를 이용해, 특정 조건이 되면 해당하는 script 파일을 만들어서 head에 appendchild로 붙여넣으면 되지요.
CSS에서 렌더링 차단 리소스를 제거 하기
그렇다면 CSS에서는 어떻게 해야할까요?
유감스럽지만 자바스크립트처럼 100% 없애는 방법은 없습니다. 왜냐하면 HTML로 뼈대를 세우고, 그 뼈대의 모양을 정해주는 게 CSS이기 때문입니다.
위의 사진을 보시면 더 잘이해가 되실 겁니다.
만약 CSS가 비동기적으로 로딩된다면 헤더와 메인의 자리가 정해진 후, CSS로 높이가 300이 주어지면 헤더가 밑으로 팽창할 겁니다.
그러면 메인은 당연히 밑으로 밀려나고, 리플로우(엘리먼트의 높이,위치등을 다시 계산해 그리는 현상)가 일어나서 성능누수가 심하게 일어납니다.
따라서 CSS가 있으면 일단 HTML을 그리던것을 멈추고, 처음부터 높이 300으로 지정된 채 입력되는 게 효율적입니다.
그렇다면 CSS에서 렌더링차단을 제거하는 방법은 뭘까요?
위대한 개발자들은 해결책을 내놓는데, 그게 바로 크리티컬 CSS입니다.
크리티컬 CSS 작업은 간단합니다.
- 크리티컬한(중요한) CSS와 논-크리티컬한(별로 안 중요한) CSS를 분리합니다.
- 중요한 CSS는 HTML의 HEAD에 inline으로 작성합니다.
- 중요하지 않은 CSS는 비동기적으로 처리합니다.
이렇게 되면 비동기적으로 처리되는 CSS의 양만큼, 렌더링 차단은 줄어들게 됩니다.
참고로 CSS를 비동기적으로 처리하는 방법은 간단합니다.
<link href="style.css" rel="preload" as="style" onload="this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="style.css"></noscript> // 방법1
<link rel="stylesheet" href="/path/to/my.css" media="print" onload="this.media='all'; this.onload=null;">
<noscript><link rel="stylesheet" href="/path/to/my.css"></noscript> // 방법2
href는 CSS 파일의 경로로 채워두시면 되고, 원리를 설명하자면 rel에 preload라고 쓰면서 빨리 다운받은 후, 다운로드가 완료되면 onload이벤트를 통해 rel을 stylesheet로 바꿔 적용되게 하는 겁니다.
noscript의 경우엔 자바스크립트가 블락되었을 때 사용되는 겁니다.
혹은 media를 print로 바꿔서 로딩을 막고 적용하는 방법들을 쓰는 분들도 계셨는데, 둘 중에 어느 코드가 우월한지 저는 모르겠습니다.
다만 이 기법에서 주의할 점이 있습니다. 세심하게 중요한 CSS와 중요하지 않은 CSS를 분리하면 초기 레이아웃 구성에 필요한 CSS가 적용되지 않으면서 방문자가 FOUC[Flash Of Unstyle Content]현상을 경험할 수도 있습니다.
한 마디로 css가 적용되지 않은 상태의 element를 보게 되면서 속칭 '깨진화면'을 일정시간 보게 된다는 것이죠.
특히 페이지마다 중요한 CSS가 다른 경우가 많습니다.
그렇기 때문에 최대한 넓게 중요한 CSS를 선정하는 게 중요합니다.
마지막 요약하기
자바스크립트는 JS 파일로 만들어서 async나 defer로 지연로드 해야 합니다.
CSS는 중요한 CSS와 중요하지 않은 CSS를 분리한 후 크리티컬CSS 방식을 사용합니다.
각 방법엔 주의사항이 있으므로 꼼꼼하고 신중하게 접근해야 합니다.
'그외 > 유용한 정보' 카테고리의 다른 글
파일이름 일괄변경 프로그램 다크네이머(DarkNamer) 사용법 리뷰 (2) | 2020.10.11 |
---|---|
웹페이지의 로딩 속도 최적화를 해 줄 크리티컬 CSS 개념을 알아봅시다. (4) | 2020.10.06 |
무료 게임을 뿌리는 에픽게임즈에 가입하는 방법 (0) | 2020.09.28 |
폴리필 (polyfill) 사용법 알아보기. feat IE11 (6) | 2020.09.26 |
티스토리 블로그에 사용할 레이지로드 주입기 (17) | 2020.09.23 |