
웹사이트 속도가 느리면 사이트 이용자가 기다리지 못하고 이탈할 확률이 높아지므로 SEO에도 매우 안 좋은 영향을 미친다.
이제부터 웹사이트 속도를 빠르게 하는 방법 중 마지막, 네 번째, 프론트엔드 최적화 에 대해 알아보자.
렌더링 성능 개선, 자바스크립트 최적화, CSS 최적화 방법을 집중적으로 알아보자.
렌더링 성능 개선 전략
렌더링 성능은 브라우저가 HTML, CSS, JavaScript를 처리해 화면을 출력하는 속도를 의미한다.
웹사이트 렌더링 속도를 빠르게 하기 위한 프론트엔드 최적화 전략을 세워보자.
- 레이아웃 스래싱 방지
- 브라우저가 DOM의 레이아웃을 여러 번 계산해야 하는 상황을 의미한다. 예를 들어, CSS 스타일을 변경하거나 DOM 요소의 크기를 변경하면 브라우저는 레이아웃을 다시 계산해야 한다. 이 과정이 반복되면 성능이 저하된다.
- JavaScript에서 DOM 스타일을 반복적으로 읽고 쓸 때 JavaScript requestAnimationFrame 활용하여 브라우저가 효율적으로 렌더링을 처리하도록 한다.
- 리페인트 최소화
- 웹 페이지에서 어떤 요소의 색깔이나 모양이 바뀔 때 브라우저가 그 요소를 다시 그리는 과정을 리페인트라고 한다. 예를 들어, 버튼의 색깔을 바꾸면 브라우저는 그 버튼을 다시 그려야 하는데 이렇게 자주 리페인트가 발생하면 페이지가 느려질 수 있다.
- CSS transform과 CSS opacity를 사용할 때 브라우저는 GPU를 사용해서 더 빠르고 부드럽게 요소를 그릴 수 있다.
- 컴포지터 스레드 활용
- 웹 브라우저가 최종적으로 화면에 보여줄 내용을 조합하는 작업을 수행하는 스레드다. 이 스레드는 레이아웃과 렌더링 작업이 끝난 후 최종 이미지를 화면에 그리는 역할을 한다. 이 스레드를 잘 활용하면 애니메이션이 더 부드럽고 빠르게 작동한다.
- CSS will-change: transform;을 사용하면, 브라우저는 해당 요소를 별도의 레이어에서 작업하므로 레이아웃을 재계산하거나 리페인트를 줄일 수 있도록 도와주고 애니메이션이 더 부드럽고 전체 페이지 성능이 향상된다.
프론트엔드 최적화 – JavaScript
- 스크립트 로딩 전략
- 비동기 로딩(Async)
- 브라우저가 HTML의 구조를 읽으면서 스크립트를 다운로드하고, 다운로드 완료 즉시 HTML의 구조를 읽는 것을 멈추고 스크립트를 실행한다. 스크립트가 독립적이고 순서가 중요하지 않을 때(예: 광고, 분석) 사용한다.
<script src="app.js" async></script>
- 지연 로딩(Defer)
- HTML 파싱 완료 후 스크립트를 실행한다.
<script src="analytics.js" defer></script>
- 비동기 로딩(Async)
- 코드 분할(Code Splitting)
코드 분할과 동적 임포트를 사용하여 웹 애플리케이션의 성능을 개선하고, 필요한 코드만 로드하여 초기 로딩 시간을 줄일 수 있다.
<script type="module">
import('./module.js').then(module=>module.init());
</script>사용된 코드 설명<script type=”module”>:브라우저에게 이 스크립트가 ES 모듈이라는 것을 알린다. ES 모듈은 JavaScript의 모듈 시스템으로 다른 스크립트에서 내보낸 기능이나 변수를 가져올 수 있다.import(‘./module.js’):module.js 파일을 동적 임포트한다. 일반적인 import와 다르게 동적 임포트는 코드가 실행될 때까지 모듈을 로드하지 않는다. 필요할 때만 모듈을 가져오고 실행한다..then(module => module.init()):import가 성공적으로 완료되면 반환된 모듈을 사용하여 init 함수를 실행한다. 이 함수는 module.js 파일 내에 정의된 함수로 모듈이 로드된 후에 수행할 작업을 담고 있다. - 이벤트 핸들러 최적화
- 이벤트 버블링을 활용한 위임 패턴 적용
- 부모 요소에 이벤트 핸들러를 등록하여 자식 요소의 이벤트를 처리하는 방법. 이 방법으로 메모리 사용을 줄이고 동적으로 생성되는 요소에 대해서도 이벤트 처리가 가능하다.
document.getElementById('parent').addEventListener('click', function(event) {
if (event.target.matches('.child')) {
console.log('Child element clicked:', event.target);
}
}); - 스크롤/리사이즈 이벤트에 쓰로틀링 적용
- 스크롤 및 리사이즈 이벤트와 같은 자주 발생하는 이벤트의 호출 빈도를 제한하여 성능을 개선하는 방법. 100ms마다 한 번만 이벤트 핸들러가 실행되도록 설정할 수 있다.
let lastExecutionTime = 0;
function throttle(callback, limit) {
return function() {
const now = Date.now();
if (now - lastExecutionTime >= limit) {
lastExecutionTime = now;
callback.apply(this, arguments);
}
};
}
window.addEventListener('scroll', throttle(function() {
console.log('Scroll event triggered');
}, 100));
- 이벤트 버블링을 활용한 위임 패턴 적용
프론트엔드 최적화 – CSS
- 렌더 차단 CSS 제거
렌더 차단 CSS는 브라우저가 웹 페이지를 렌더링(화면에 표시)하기 전에 반드시 다운로드하고 처리해야 하는 CSS 파일을 의미한다.
이러한 CSS 파일이 많거나 크기가 크면, 페이지 로딩 속도가 느려질 수 있다.
사용자는 페이지가 완전히 로드될 때까지 기다려야 하므로 사용자 경험이 저하된다.
rel=”preload” 사용
<link> 태그에 rel=”preload” 속성을 사용하여 CSS 파일을 미리 로드할 수 있다.
따라서 페이지의 초기 로딩을 방해하지 않으면서 필요한 CSS 파일을 빠르게 로드할 수 있게 해준다.
<link rel="preload" href="styles.css" as="style" onload="this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="styles.css"></noscript>사용된 코드 설명rel=”preload”:브라우저에게 이 리소스를 미리 로드하라고 지시한다.as=”style”:로드하는 리소스의 유형을 지정한다.onload=”this.rel=’stylesheet'”:CSS 파일이 로드된 후, rel 속성을 stylesheet로 변경하여 CSS가 적용되도록 한다.<noscript>:자바스크립트를 사용할 수 없는 경우를 대비하여 기본적인 스타일 시트를 로드한다.JavaScript로 비동기 로딩
<script>
function loadCSS(href) {
var link = document.createElement("link");
link.rel = "stylesheet";
link.href = href;
document.head.appendChild(link);
}
window.onload = function() {
loadCSS("styles.css");
};
</script>사용된 코드 설명loadCSS:새로운 <link> 요소를 생성하고 해당 CSS 파일의 경로를 설정한 후 문서의 <head>에 추가한다.window.onload:페이지가 완전히 로드된 후 CSS 파일을 로드한다.내부 스타일 시트 삽입
중요한 CSS 스타일을 HTML 문서의 <head> 섹션에 내부 스타일 시트로 삽입하여 페이지가 빨리 열리도록 할 수 있다.
<style>/*중요한 CSS 스타일*/</style>
<link rel="preload" href="styles.css" as="style" onload="this.rel='stylesheet'"> - CSS 선택자 효율화
복잡한 CSS 선택자는 지양하고 가능한 한 간단하게 만들자.
나쁜 예 좋은 예 .nav ul li a .nav-link div#header #header - GPU 가속 속성 활용
CPU 대신 GPU를 사용하여 그래픽 및 애니메이션을 더 빠르게 실행하는 기술이다.
translateZ(0)은 3D 변환을 지정하는 함수다.
요소를 Z축 방향으로 0만큼 이동시키는 것을 의미하지만 0만큼이니 아무 효과가 없고 브라우저가 해당 요소를 GPU 가속 모드로 처리하게 만들 뿐이다.
브라우저가 해당 요소를 별도의 레이어로 처리하게 되어 GPU에서 처리하기 때문에 웹 페이지 성능을 향상 시킬 수 있고 애니메이션 품질을 개선할 수 있다.<style>.animate{transform:translateZ(0);}</style>
성능 측정 도구 활용법
- Chrome DevTools Performance Tab
- Chrome 브라우저에 내장된 개발자 도구 중 하나로, 웹 페이지의 성능을 분석하고 최적화 하는 데 사용된다.
- 페이지 로딩 시간, 렌더링 성능, 이벤트 처리 등을 시각적으로 분석할 수 있다.
- CPU 사용량, 메모리 소비, 이벤트 핸들러 호출 등을 모니터링 할 수 있다.
- 특정 작업이 얼마나 시간이 걸리는지 세부적으로 확인할 수 있어서 성능 병목 현상을 찾아내는 데 유용하다.
- Lighthouse
- Chrome DevTools에 통합된 오픈 소스 자동화 도구이며 웹 페이지의 성능, 접근성, SEO 등을 평가하는 데 사용된다.
- 페이지 성능 점수를 제공하고 최적화 권장 사항을 제시한다.
- PWA(Progressive Web App) 관련 점검도 포함되어 있다.
- 결과를 HTML, JSON 형식으로 저장하거나 공유할 수 있다.
- Web Vitals
- Google이 제안한 핵심 웹 성능 지표다. 사용자 경험을 평가하는 데 중요한 지표를 제공한다.
- LCP (Largest Contentful Paint), 페이지의 주요 콘텐츠가 얼마나 빨리 로드되는지 측정한다.
- FID (First Input Delay), 사용자가 페이지에 처음 상호작용 할 때까지의 지연 시간을 측정한다.
- CLS (Cumulative Layout Shift), 페이지 로딩 중 레이아웃이 얼마나 자주 변경되는지 측정해서 사용자 경험의 안정성을 평가한다.
렌더링 성능 개선은 단순한 기술적 개선이 아닌 비즈니스 성과로 직결된다.
위에서 제시한 프론트엔드 최적화 기법을 바로 적용해 사용자 경험을 향상 시키자.