LCP(Largest Contentful Paint)와 한판승부 - 눈물의 삽질(2)
h2 프로토콜로 이미지를 전달했음에도 불구하고, 나의 LCP는 전혀 개선되지 않았다. 오히려, Lighthouse를 돌릴때 마다 더 하락하는 경우도 있었다. 이 페이지의 구조는 이미지가 object-fit: cover 되는 형태여서, 당연히 LCP 객체는 CDN에서 받아온 저 이미지인줄 알고있었다. 그리고 오락가락 하긴 했지만, 개발자 도구의 Performance 탭에서는 LCP 객체가 image라고 말하고 있었다. 그래서 이미지만 빨리 로딩시켜주면 한방에 끝날 줄 알았지만, 오히려 새로운 난관의 시작이었던 것이다.
그렇게 절망을 하고, '오늘은 여기까지' 하고 컴퓨터를 종료하고 저녁으로 온 버거킹을 리갈하이 드라마를 보면서 먹고있었는데, 다 먹고나니 문득 이런 생각이 들었다. '이미지를 전부 다 없애도 느리게 나올까?'. 그래서 당장 컴퓨터를 켜고 <picture> 전부를 주석처리 하기 시작했다. 그 결과..
생각보다 다이나믹한 변화가 없었다. 물론 LCP가 1.3s 나 개선된것은 좋은 것이지만, 여기에는 이미지가 한개도 로딩되어져있지 않다. 즉, 내가 쓰고있는 스크립트만 LCP를 매우 많이 잡아먹고 있다는 것이다. 사진은 없지만, 모든 이미지들을 전부 http/2로 바꿔서 전송해주었다. 근데 놀랍게도, http/2를 사용하라는 경고문은 사라지지 않더라. 시간도 1.5초에서 1.3초로 줄은 것 뿐, 큰 변화가 없었다. 물론 모든 파일들을 http/2로 전송해야 의미가 있긴 하겠지만, 예상했던 것과는 달라서 적잖은 충격 + 배신감을 느꼈다.
사실 기성품 라이브러리의 사용이, 페이지 Performance 측면에서 별로 좋지 않은 것을 몰랐던 것이 아니다. 그래서 이전에 페이지를 꾸며주었던 Bootstrap4를, 라이브러리 다이어트를 하기 위해 더이상 사용하지 않기로 했다. 하지만 페이지 설계상 절대 뺄 수 없던 라이브러리가 있었는데, 그것이 바로 fullpage.js 이다.
fullPage scroll snapping. Create full screen pages fast and simple
Mouse wheel snap to sections. Fast and simple to use.
alvarotrigo.com
이전에 1.4만원 정도 할때 라이선스를 미리 사두어서, 안쓰기도 아까워서 이번에도 이친구를 쓸 수 밖에 없었다. bootstrap의 navbar는 어찌어찌 비슷하게 구현해 놓았지만, fullpage는 정말 구현하기가 힘들어서 다이어트를 포기하고 있었다. 그리고 그것이 화살이 되어 돌아왔다.
이 라이브러리는 무조건 사용하는 것을 전제로, LCP를 개선할 수 있는 방법을 찾아야만 했다. 그래서 (이제는 맹신은 하지 않지만) Lighthouse 선생님께 여쭤보니, render-blocking resource 를 제거하고, 안쓰는 js 도 제거하라고 하셨다. 참고로 저 js 파일은 구글 애널리틱스 4 파일이라서, 지울수는 없었다. 대신, 로딩을 좀 늦게 해주는 방법을 썼다. 다음의 블로그에 따르면, 파일의 끝에서 로딩된다고 해도, 0.2초의 차이밖에 나지 않는다고 한다. 대신, 페이지 로딩중에 나가는 사용자는 추적이 불가능 하다고한다.
구글 태그매니저를 통한 구글 애널리틱스 실행 속도 비교
구글 태그매니저는 굉장히 편리한 도구 입니다. 구글 애널리틱스를 사용하기 위해서는 페이지의 소스에 접근 할 수 있는 권한이 있어야 하고 이를 수정할 수 있어야 하는데 사실 개발자가 아닌
05log.tistory.com
Lighthouse 쌤한테 받은 성적표대로 해보려고, 저 0.6s 를 차지하는 render-blocking resource들을 제거하려고 했는데, 사실 나는 웹이 어떻게 rendering이 되는지 조차도 잘 몰랐던 것이다. 그래서 처음에는 '저 css랑 js를 없애면 어떻게 로딩하라는거야' 라는 생각으로 계속 무시했었는데, 이참에 한번 제대로 조사해보았다.
렌더링 차단 JavaScript 및 CSS
브라우저에서 콘텐츠를 렌더링하려면 먼저 HTML 마크업을 DOM 트리로 구문 분석해야 합니다. HTML 파서는 외부 스타일시트( <link rel="stylesheet">) 또는 동기 JavaScript 태그( <script src="main.js">)를 만나면 일시 중지됩니다.
출처 : https://web.dev/optimize-lcp/#render-blocking-resources
그렇다. 가뜩이나 바쁜 친구한테, 열심히 렌더링하고있는데 파일을 계속 던져주다보면, 느려지는게 당연할 것이다. stylesheet나 js 에는 DOM 객체가 수정될 수 있는 코드가 들어가있을테니 말이다. 해결방안은 다음과 같다.
CSS의 경우
- CSS를 축소
- 중요하지 않은 CSS의 로딩을 늦추기
- 중요한 CSS는 즉시 로딩
JS의 경우
- <head>에 넣지 않기
- defer or async 속성으로 나중에 로딩시키기
교과서적인 해결방안이지만, 라이브러리를 쓰고있는 상황에서는 해결책을 생각하기가 매우 힘들었다. 그래서 fullpage.js로 렌더링된 페이지의 구조를 생각하면서, fullpage.js가 렌더링 된 상태와 동일한 첫 페이지를 만들기 위해 코드를 수정했다. 그리고 해당 js파일은 body 태그에 넣어주었다.
fullpage.js 의 작동방식을 간단히 소개하자면, div#fullpage 객체 내에 div.section 객체들을 넣으면, section 객체 하나당 화면 전체를 사용하게 해주도록 수정해준다. 그래서 라이브러리가 로딩이 안되었어도, 마치 로딩이 된 것처럼 하기 위해 메인의 첫번째 이미지를 100vh높이로 해주고, 배경색을 하얀색으로 칠해 뒤에 있는 다음 페이지들의 글씨가 보이지 않도록 하였다. 즉, fullpage.js 파일의 처리 전과 후 모두, LCP는 동일한 것이다!
그리하여, 드디어 메인 페이지를 성불시킬 수 있었다. 물론 아직 http/1.1을 사용중인 파일도 있고, fullpage.js 는 lazyloading 되어있지만 css 파일은 아니어서, 속도 개선의 여지는 남아있다. 이 다음은 node.js 연습하는 셈 치고, html의 전처리와 사진, 폰트 등의 최적화 동작을 해주는 코드를 짜보려고한다. 포트포워딩이 맨날 안되는 6년된 공유기도 새것으로 교체받았으니, 이제는 당분간 휴가중이었던 라즈베리파이를 신나게 괴롭히기로 결정했다.