본문 바로가기
1주차

웹 성능 최적화 핵심 3가지

by maehwasoo 2025. 4. 11.

안녕하세요! 36기 YB 엄경호입니다. 😊

이전 글들에서 웹 성능의 중요성과 개별적인 최적화 기법들을 많이 보았습니다.

 

오늘은 사용자가 웹 페이지를 더 빠르게 느끼게 만드는 핵심적인 성능 최적화 기법 세 가지

Critical Rendering Path (CRP) 분석,

코드 스플리팅 (Code Splitting), 그리고

리소스 지연 로딩 (Lazy Loading) 에 대해 깊이 알아보겠습니다 !

 

빠른 로딩 속도는 사용자 경험을 극대화하고 이탈률을 줄이며, 검색 엔진 순위에도 긍정적인 영향을 미칩니다.


1. Critical Rendering Path (CRP) 최적화

✅  CRP란 무엇인가요?

Critical Rendering Path(핵심 렌더링 경로)는 브라우저가 HTML, CSS, JavaScript를 화면에 픽셀로 변환하는 일련의 단계를 의미합니다.

 

이 경로를 이해하고 최적화하는 것은 초기 페이지 로딩 속도를 개선하는 데 매우 중요합니다. (웹 브라우저의 작동 원리)

 

CRP 단계 요약:

  1. DOM 트리 생성: 브라우저가 HTML을 파싱하여 DOM(Document Object Model) 트리를 만듭니다.
  2. CSSOM 트리 생성: CSS를 파싱하여 CSSOM(CSS Object Model) 트리를 만듭니다.
  3. Render Tree 생성: DOM과 CSSOM을 결합하여 실제로 화면에 표시될 요소들로만 구성된 렌더 트리를 만듭니다 (display: none 등은 제외).
  4. Layout (Reflow): 렌더 트리의 각 노드의 정확한 위치와 크기를 계산합니다.
  5. Paint: 계산된 정보를 바탕으로 각 노드를 화면의 실제 픽셀로 변환합니다.
  6. Composite: 여러 레이어를 순서대로 합성하여 최종 화면을 그립니다.

 

✅  어떻게 최적화하나요?

CRP의 핵심은 렌더링 차단 리소스(Render-Blocking Resources)를 최소화하는 것입니다. 


주로 <head> 태그 안의 CSS와 동기적인 JavaScript가 해당됩니다.

 

  • CSS 최적화:
    • 미디어 쿼리 활용: 특정 조건(화면 크기, 인쇄 등)에서만 필요한 CSS는 해당 미디어 쿼리 내에서 로드하여 초기 렌더링 차단을 줄입니다. (<link rel="stylesheet" href="print.css" media="print">)
    • CSS 파일 크기 최소화: 불필요한 스타일 제거, 압축(Minification) 등을 통해 파일 크기를 줄입니다.
    • Critical CSS 인라이닝: 페이지 상단(Above-the-fold) 렌더링에 필수적인 CSS만 HTML <style> 태그 안에 인라인으로 포함시키고, 나머지 CSS는 비동기적으로 로드합니다.

 

  • JavaScript 최적화:
    • async 또는 defer 속성 사용: <script> 태그에 asyncdefer 속성을 추가하면 HTML 파싱을 차단하지 않고 스크립트를 다운로드/실행할 수 있습니다.
      • async: 다운로드 완료 즉시 실행 (but 순서 보장 X).
      • defer: HTML 파싱 완료 후, DOMContentLoaded 이벤트 전에 순서대로 실행.
    • 스크립트 위치: 가능하면 <body> 태그 끝부분에 스크립트를 위치시켜 DOM 생성을 방해하지 않도록 합니다.

 

  • 리소스 요청 수 줄이기: 여러 CSS나 JS 파일을 하나로 병합(Bundling)하여 HTTP 요청 수를 줄입니다. (but HTTP/2 이상에서는 효과가 줄어들 수 있음)

2. 코드 스플리팅 (Code Splitting)

✅  코드 스플리팅이란?

웹 애플리케이션이 커지면 JavaScript 번들 파일 크기도 함께 증가합니다.

큰 번들 파일은 다운로드와 파싱/실행 시간을 늘려 초기 로딩 성능을 저하시킵니다.

코드 스플리팅은 이 거대한 번들 파일을 여러 개의 작은 청크(Chunk)로 나누고, 필요한 시점에 필요한 코드만 로드하는 기법입니다.

 

✅  왜 필요한가요?

  • 초기 로딩 속도 개선: 사용자가 처음 페이지에 접속했을 때 필요한 최소한의 코드만 로드하여 TTI(Time To Interactive)를 단축시킵니다.
  • 리소스 효율성 증대: 당장 사용하지 않는 코드까지 로드하는 낭비를 줄입니다.

 

✅  어떻게 구현하나요?

최신 자바스크립트와 모듈 번들러(Webpack, Vite, Rollup 등)를 사용하면 비교적 쉽게 구현할 수 있습니다.

  • 동적 import() 문법: 표준 JavaScript 문법으로, 프로미스(Promise)를 반환하며 필요한 시점에 모듈을 비동기적으로 로드합니다.
// button 클릭 시 large-module.js 로드 
button.addEventListener('click', async () => { 
	try { 
    	const module = await import('./large-module.js'); 
        module.doSomething(); 
        } catch (error) { 
        	console.error('모듈 로딩 실패:', error); 
        } 
	});

 

  • 모듈 번들러 활용:
    • Webpack: optimization.splitChunks 설정을 통해 자동으로 코드 중복을 제거하고 청크를 분리할 수 있습니다.
      동적 import()도 지원합니다.
    • Vite: 기본적으로 동적 import()를 지원하며, Rollup 기반으로 효율적인 코드 스플리팅을 수행합니다.
    • React/Vue 등 프레임워크: React.lazy(), Vue의 비동기 컴포넌트 등 프레임워크 자체에서 코드 스플리팅을 위한 기능을 제공합니다.

3. 리소스 지연 로딩 (Lazy Loading)

✅  지연 로딩이란?

지연 로딩은 페이지 로딩 시점에 당장 필요하지 않은 리소스(특히 이미지, 비디오, iframe) 의 로딩을 실제로 화면에 보여지기 직전까지 지연시키는 기법입니다.

 

✅  왜 유용한가요?

  • 초기 페이지 로드 시간 단축: 화면 밖에 있는 이미지까지 처음부터 로드하지 않아 초기 로딩이 빨라집니다.
  • 데이터 절약: 사용자가 스크롤하여 보지 않는 이미지/리소스는 로드되지 않아 데이터 사용량을 줄일 수 있습니다. (특히 모바일 환경에서 더욱 중요 !)
  • 서버 부하 감소: 초기 요청 리소스 수가 줄어 서버 부담을 덜 수 있습니다.

 

✅  어떻게 구현하나요?

  • 이미지 및 iframe 네이티브 지연 로딩: 가장 간단한 방법은 HTML <img><iframe> 태그에 loading="lazy" 속성을 추가하면 브라우저가 알아서 지연 로딩을 처리해줍니다. (이는 대부분의 최신 브라우저에서 지원합니다 !)
  • <img src="image.jpg" loading="lazy" alt="설명" width="200" height="200"> <iframe src="https://example.com" loading="lazy" title="예시"></iframe>
  • Intersection Observer API 활용: loading="lazy"가 지원되지 않는 리소스나 더 복잡한 로직(예를 들면 특정 컴포넌트 지연 로딩)을 구현할 때 사용합니다.
    요소가 뷰포트에 들어왔는지 감지하여 콜백 함수를 실행시키는 API입니다.
const lazyImages = document.querySelectorAll('img.lazy'); 
// data-src 속성에 실제 이미지 경로 저장 

const observer = new IntersectionObserver((entries, observer) => { 
	entries.forEach(entry => { 
    	if (entry.isIntersecting) { 
        	const img = entry.target; 
            img.src = img.dataset.src; // 실제 이미지 로드 
            img.classList.remove('lazy'); 
            observer.unobserve(img); // 감지 중단 
            } 
        }); 
    }); 
    
    lazyImages.forEach(img => { 
    	observer.observe(img); 
    });

🏁 마무리하며

오늘 살펴본 Critical Rendering Path 최적화, 코드 스플리팅, 지연 로딩은 웹 페이지의 로딩 속도와 사용자 경험을 크게 향상시킬 수 있는 강력한 기법들입니다.

 

개인적으로 프로젝트 초기부터 성능을 염두에 두고 개발하는 습관을 들이고, 테스팅 도구를 활용하여 꾸준히 성능을 측정하고 개선해나가는 것이 중요하다고 생각합니다.

 

읽어주셔서 감사합니다!


참고하면 좋은 자료 !