브라우저가 웹 페이지를 표시하는 과정은 네트워크 관점과 렌더링 관점에서 나눠서 설명할 수 있다.
- 네트워크 관점에서는 브라우저가 서버로부터 필요한 리소스를 요청하고 다운로드하는 과정
- 렌더링 관점에서는 다운로드한 리소스를 사용해 브라우저가 화면에 웹 페이지를 그리는 과정
네트워크 관점
웹 페이지를 로드하는 과정은 브라우저가 서버로부터 필요한 리소스를 다운로드하는 네트워크 통신 단계입니다. 주요 단계는 다음과 같습니다:
1) URL 입력 및 DNS 조회
사용자가 웹 브라우저 주소창에 URL을 입력하면, 브라우저는 먼저 DNS 조회를 통해 해당 URL의 도메인 이름을 IP 주소로 변환합니다. 이 IP 주소는 웹 서버가 위치한 곳을 나타냅니다.
2) TCP 연결 및 SSL 핸드셰이크
브라우저는 서버와 TCP 연결을 맺습니다. 웹사이트가 HTTPS를 사용하는 경우, SSL/TLS 핸드셰이크를 통해 암호화된 통신 채널을 설정합니다.
3) HTTP 요청
TCP 연결이 완료되면 브라우저는 서버에 HTTP(S) 요청을 보냅니다. 이 요청은 사용자가 방문하려는 페이지에 대한 정보(예: HTML 파일)를 요구합니다. 서버는 이 요청을 받고, 응답으로 HTML 문서를 브라우저에 보냅니다.
4) 리소스 요청 (CSS, JS, 이미지 등)
HTML 문서를 받은 후, 브라우저는 추가적인 리소스(CSS 파일, 자바스크립트 파일, 이미지 등)가 필요한지 파악합니다. 이를 위해 HTML 문서를 파싱하여 해당 리소스들에 대한 추가 HTTP 요청을 서버에 보냅니다.
5) 응답 처리
서버로부터 받은 모든 리소스는 브라우저의 캐시에 저장되고, 이를 바탕으로 렌더링을 시작합니다. 네트워크 관점에서 중요한 점은 요청 및 응답이 비동기로 이루어진다는 점입니다. 즉, HTML 문서를 읽는 동안에도 다른 리소스를 병렬적으로 다운로드할 수 있습니다.
**CRP(Critical Rendering Path)**는 렌더링 과정 중에서도 최대한 빠르게 웹 페이지가 사용자에게 표시되는 데 중요한 단계들에 초점을 맞춘 개념이다. 즉, CRP는 초기 로드 성능을 최적화하기 위한 과정에 중점을 둔다.
CRP의 주요 단계
CRP는 브라우저가 웹 페이지를 렌더링할 때 거치는 필수적인 단계를 포함한다. 각 단계는 다음과 같다.
1. HTML 파싱과 DOM 트리 생성
브라우저가 서버에서 HTML 파일을 받아오면 이를 파싱하여 DOM(Document Object Model) 트리를 생성한다. DOM은 웹 페이지의 각 요소를 노드로 변환한 트리 구조로, HTML 문서의 논리적인 표현이다. <html>, <body>, <div> 같은 태그들이 트리의 각 노드로 변환된다.
이 과정에서 중요한 점은, 만약 <script> 태그를 만나면 DOM 생성이 중단된다는 것이다. JavaScript는 DOM을 수정할 수 있기 때문에, 먼저 실행되어야 하기 때문이다.
2. CSS 파싱과 CSSOM 트리 생성
HTML 파싱이 진행되는 동시에, CSS 파일도 파싱되어 CSSOM(CSS Object Model) 트리가 생성된다. CSSOM은 HTML의 스타일 정보를 표현한 트리이다. 이 단계에서 브라우저는 스타일 규칙을 DOM 요소에 적용할 준비를 한다.
CSS 파일이 모두 로드되고 파싱되기 전까지는 브라우저가 렌더링을 시작하지 않는다. CSS는 웹 페이지의 레이아웃을 결정하는 중요한 요소이기 때문이다.
3. 렌더 트리 생성
브라우저는 DOM 트리와 CSSOM 트리를 결합하여 렌더 트리(Render Tree)를 생성한다. 렌더 트리는 화면에 실제로 표시될 요소들만 포함한다. 예를 들어, display: none;으로 설정된 요소는 렌더 트리에 포함되지 않는다.
이 렌더 트리는 브라우저가 화면에 무엇을 표시할지 결정하는 역할을 한다.
4. 레이아웃 계산
렌더 트리가 완성되면 브라우저는 각 요소가 화면에서 어느 위치에 배치될지, 그리고 그 요소의 크기가 얼마나 되는지를 계산한다. 이 과정을 레이아웃 단계라고 하며, ‘reflow’라고도 불린다.
레이아웃 계산은 웹 페이지의 각 요소가 화면에 어떻게 배치될지를 정하는 과정으로, 사용자가 실제로 보는 레이아웃을 결정하는 중요한 단계이다.
5. 페인팅 (Painting)
레이아웃이 완료되면, 브라우저는 화면에 요소들을 실제로 그리기 시작한다. 이 단계를 페인팅이라고 하며, 각 요소의 시각적 속성(색상, 배경, 텍스트 등)을 화면에 표시한다.
이 과정은 픽셀 단위로 화면에 그림을 그리는 단계로, 사용자가 실제로 웹 페이지를 보는 시점이다.
6. 컴포지팅 (Compositing)
브라우저는 마지막으로 각 요소를 레이어로 분리하고, 이 레이어들을 합성하여 화면에 표시한다. 복잡한 애니메이션이나 3D 변환은 별도의 레이어에서 처리되며, 이러한 레이어들이 하나로 결합되어 최종 화면이 렌더링된다.
DOM 트리와 렌더 트리의 차이
DOM 트리 (Document Object Model)
DOM 트리는 브라우저가 HTML 문서를 파싱하여 생성하는 트리 구조로, HTML 문서의 모든 요소를 포함한다. HTML의 각 태그는 DOM 트리의 노드가 되며, 이 노드를 통해 자바스크립트나 CSS가 웹 페이지를 조작할 수 있다. DOM 트리에는 보이지 않는 요소들도 포함되며, HTML 문서 전체를 나타낸다.
렌더 트리 (Render Tree)
렌더 트리는 브라우저가 DOM 트리와 CSSOM(CSS Object Model) 트리를 기반으로 생성하는 트리이다. 렌더 트리는 화면에 실제로 표시될 요소들만 포함한다. display: none; 같은 속성으로 화면에 표시되지 않는 요소들은 렌더 트리에 포함되지 않는다. 렌더 트리는 각 요소가 어떻게 그려질지에 대한 정보(위치, 크기, 스타일)를 바탕으로 만들어진다.
차이점
- DOM 트리는 HTML 문서의 모든 요소를 포함하며, 웹 페이지의 구조와 내용을 정의한다.
- 렌더 트리는 화면에 실제로 표시될 요소들만 포함하며, 요소들의 스타일과 레이아웃 정보를 바탕으로 페이지를 렌더링하는 데 사용된다.
DOM이란 무엇일까?
간단히 말하면 DOM은 HTML이나 XML 문서를 브라우저에서 트리 구조로 표현한 모델입니다.
DOM(Document Object Model)은 웹 페이지의 구조화된 문서를 나타내는 객체 기반의 표현이다. HTML이나 XML 문서를 트리 구조로 표현하며, 이 트리 구조를 통해 자바스크립트나 다른 프로그래밍 언어가 문서의 요소에 접근하고, 이를 수정하거나 삭제, 추가할 수 있다.
DOM은 브라우저가 HTML 문서를 파싱하여 구조화된 트리로 변환하는 과정에서 생성되며, 개발자는 DOM API를 사용하여 문서의 요소에 접근할 수 있다. 즉, DOM은 문서의 시각적 요소를 표현하는 것뿐만 아니라, 자바스크립트가 문서와 상호작용하는 방식의 기초가 된다.
DOM의 주요 기능:
노드 접근: DOM은 문서 내의 각 요소를 **노드(Node)**로 표현하며, 이를 통해 각 요소에 접근하고 조작할 수 있다.
문서 조작: DOM API를 통해 요소의 텍스트, 속성, 스타일을 수정하거나 새로운 요소를 추가할 수 있다.
이벤트 처리: DOM은 웹 페이지에서 발생하는 다양한 이벤트(클릭, 입력 등)를 처리하는 인터페이스도 제공한다.
Document
└── html
├── head
│ └── title
│ └── "Sample Page"
└── body
├── h1
│ └── "DOM 구조"
└── p
└── "이것은 DOM 트리의 예시입니다."
CRP 최적화 방법
CRP를 최적화하는 것은 페이지 로딩 시간을 단축하고, 더 나은 사용자 경험을 제공하기 위해 중요하다. 이를 위해 몇 가지 방법이 있다.
1. CSS와 JavaScript 최적화
CSS와 JavaScript는 렌더링을 차단할 수 있다. 이를 해결하기 위해 CSS 파일을 최소화하고 병합하여 로딩 시간을 단축해야 한다. 또한, JavaScript는 비동기적으로 로드하여 렌더링을 막지 않도록 해야 한다. async 또는 defer 속성을 사용하면 JavaScript 로딩으로 인해 렌더링이 지연되는 것을 방지할 수 있다.
2. 리소스 요청 최소화
페이지 로딩 속도를 개선하려면 중요한 리소스는 우선적으로 로드하고, 그렇지 않은 리소스는 나중에 로드하는 것이 좋다. 예를 들어, 이미지나 폰트 같은 리소스는 lazy-loading을 사용해 필요할 때만 로드할 수 있다. 또한, CDN(Content Delivery Network)을 사용하여 리소스 로딩 속도를 높일 수 있다.
3. 페인트 성능 향상
CSS 애니메이션이나 복잡한 스타일링은 브라우저의 페인트 성능에 영향을 미친다. 복잡한 레이아웃이나 스타일링을 피하고, GPU 가속을 사용하는 CSS 속성(예: transform, opacity)을 사용하면 성능을 크게 향상시킬 수 있다.
defer와 async 속성의 차이
async
async 속성은 스크립트가 비동기적으로 로드되도록 한다. 스크립트를 비동기로 로드하면, 브라우저는 HTML 파싱을 계속 진행하면서 스크립트를 다운로드하고, 다운로드가 완료되면 즉시 실행한다. 이 과정에서 HTML 파싱과 스크립트 실행이 병렬로 진행되지만, 스크립트 실행 순서는 보장되지 않는다. 즉, async 스크립트는 먼저 다운로드가 완료된 스크립트가 먼저 실행된다.
- 장점: 페이지 로딩 시간을 줄일 수 있다.
- 단점: 스크립트 실행 순서가 중요할 경우 적합하지 않다.
defer
defer 속성은 스크립트가 비동기적으로 로드되지만, HTML 파싱이 완료된 후에 스크립트가 실행되도록 보장한다. 즉, HTML 문서가 완전히 파싱된 후에 스크립트가 실행되며, 여러 defer 스크립트가 있을 경우 순차적으로 실행된다. defer는 script 태그를 body 하단에 두는 것과 비슷한 효과를 내지만, HTML 파싱 중에도 스크립트를 비동기적으로 다운로드하므로 전체 로딩 속도를 더 최적화할 수 있다.
- 장점: 스크립트 실행 순서를 보장하면서 HTML 파싱을 방해하지 않는다.
- 단점: 단순한 스크립트 로딩에는 async보다 덜 효율적일 수 있다.
차이점 정리
- async: 스크립트가 HTML 파싱과 병렬로 로드되며, 다운로드가 완료되면 즉시 실행된다. 스크립트 실행 순서는 보장되지 않는다.
- defer: 스크립트가 비동기로 로드되지만, HTML 파싱이 끝난 후 순차적으로 실행된다.
브라우저 렌더링 과정 요약:
- URL 입력 → DNS 조회( IP 주소를 찾기) → TCP/TLS 연결: 브라우저가 서버와 안전한 통신을 위한 연결을 설정
- HTTP 요청 → 서버 응답: 브라우저가 서버에 페이지를 요청하고, 서버는 해당 리소스(HTML, CSS, JS)를 브라우저에 응답.
- HTML, CSS, JS 로드 → 파싱: 브라우저는 HTML을 파싱해 DOM 트리를, CSS를 파싱해 CSSOM 트리를 만들고, 이를 결합해 렌더 트리를 생성.
- 레이아웃 계산 → 페인팅: 브라우저는 요소들의 위치와 크기를 계산한 후, 화면에 그린다.
- 컴포지팅 및 화면 출력: 레이어를 조합해 최종 화면을 사용자에게 표시.
브라우저 렌더링 과정은 HTML과 CSS를 파싱하여 DOM과 CSSOM 트리를 생성하고, 이를 바탕으로 화면에 표시할 렌더 트리를 만들고, 레이아웃과 페인트를 수행한 뒤, 최종적으로 화면에 렌더링하는 과정이다.
** 랜더링 과정중에 추가적인 현상들 **
1) 리플로우(Reflow) & 리페인트(Repaint)란?
리플로우는 브라우저가 웹 페이지의 레이아웃을 다시 계산하는 과정이다. 웹 페이지의 구조나 스타일이 변경되어 요소들의 위치나 크기를 재계산해야 할 때 리플로우가 발생한다. 리플로우는 DOM 트리와 CSSOM 트리를 바탕으로 다시 레이아웃을 계산하는 작업으로, CPU와 메모리 자원이 많이 사용되기 때문에 성능에 영향을 미친다.
리페인트는 요소의 시각적 스타일이 변경되어 화면에 다시 그려야 할 때 발생하는 과정이다. 예를 들어, 요소의 배경색, 글자 색상 등이 변경되면 리페인트가 일어난다. 이 과정에서는 요소의 크기나 위치가 변경되지 않고 시각적인 변화만 화면에 반영된다. 리플로우보다는 자원 소모가 적지만, 빈번한 리페인트 역시 성능 저하를 일으킬 수 있다.
리플로우는 언제 일어날까?
- 요소의 크기나 위치가 변경될 때 (예: width, height, padding, margin 등).
- DOM 구조가 변경될 때 (예: 요소 추가, 삭제).
- 브라우저 창의 크기를 조절할 때 (창 크기에 따라 레이아웃이 달라지는 경우).
- 폰트 크기가 변경되었을 때.
리페인트는 언제 일어날까?
- 요소의 시각적 속성이 변경될 때 (예: color, background-color, visibility 등).
- 단순한 스타일 변화가 발생할 때 (레이아웃이 변경되지 않는 시각적 속성).
2) script 태그를 body 하단에 위치시키는 이유
script 태그를 body 태그 하단에 위치시키는 이유는 페이지 로딩 성능을 향상시키기 위함이다.
브라우저는 HTML 문서를 위에서부터 아래로 순차적으로 파싱한다. 만약 script 태그가 페이지의 상단에 위치해 있으면, 브라우저는 자바스크립트를 실행하기 위해 HTML 파싱을 중단하고, 스크립트를 다운로드하고 실행한 후에 다시 파싱을 진행하게 된다. 이로 인해 페이지 로딩이 지연될 수 있다.
반면, script 태그를 body의 하단에 위치시키면 브라우저는 먼저 HTML을 모두 파싱하고 DOM 트리를 완성한 후에 자바스크립트를 실행하게 된다. 이 방식은 사용자에게 더 빠르게 콘텐츠를 표시할 수 있도록 돕는다.
3) 강제 동기 레이아웃(Forced Synchronous Layout)
강제 동기 레이아웃은 브라우저가 레이아웃 계산을 즉시 강제로 수행해야 하는 상황을 의미한다. 일반적으로 브라우저는 레이아웃 작업을 효율적으로 수행하기 위해 한 번에 여러 요소를 처리하려고 한다. 하지만 JavaScript가 DOM을 조작하면서 브라우저의 최신 레이아웃 정보를 필요로 하는 경우, 브라우저는 그 즉시 레이아웃을 다시 계산하게 된다. 이 상황을 강제 동기 레이아웃이라고 부른다.
강제 동기 레이아웃이 발생하는 경우
강제 동기 레이아웃은 JavaScript 코드에서 DOM의 레이아웃 정보를 요청할 때 발생한다. 예를 들어, JavaScript에서 아래와 같은 레이아웃 정보에 접근하면 브라우저는 최신 레이아웃을 계산해야 한다.
- offsetWidth, offsetHeight
- scrollTop, scrollHeight
- getComputedStyle()
이러한 속성이나 메서드를 호출할 때 브라우저는 즉시 DOM을 다시 계산하여 최신 레이아웃 정보를 제공해야 하므로 강제로 레이아웃 계산을 동기적으로 실행한다. 이로 인해 성능이 저하될 수 있다.
성능에 미치는 영향
강제 동기 레이아웃은 DOM을 조작하는 코드의 흐름을 방해하며, 특히 DOM을 자주 읽고 쓸 때 성능 저하를 일으킬 수 있다. 이러한 현상이 누적되면 웹 페이지가 느려지고, 렌더링이 지연될 수 있다.
4) 레이아웃 쓰레싱(Layout Thrashing)
레이아웃 쓰레싱은 DOM을 반복적으로 읽고 쓰는 작업이 교차하면서 브라우저가 계속해서 레이아웃을 재계산하는 현상을 말한다. 이는 성능 저하의 주요 원인 중 하나로, 특히 반복적으로 DOM의 레이아웃 정보를 읽고 그에 따라 DOM을 수정하는 상황에서 발생한다.
레이아웃 쓰레싱이 발생하는 과정
레이아웃 쓰레싱은 JavaScript 코드가 DOM을 자주 읽고 쓰는 작업을 섞어서 수행할 때 발생한다. 예를 들어:
- DOM 요소의 레이아웃 속성을 읽음 (예: element.offsetHeight).
- 그 값을 기반으로 DOM의 스타일을 수정함 (예: element.style.height = '100px').
- 다시 DOM 요소의 레이아웃 속성을 읽음 (예: element.offsetWidth).
이런 흐름이 반복되면 브라우저는 각 DOM 수정마다 레이아웃을 다시 계산해야 하며, 이를 통해 레이아웃 쓰레싱이 발생하게 된다. 이는 CPU와 메모리 자원을 과도하게 사용하여 성능 저하를 일으킨다.
레이아웃 쓰레싱 해결 방법
레이아웃 쓰레싱을 방지하기 위한 일반적인 방법은 DOM 읽기와 쓰기 작업을 구분하는 것이다. 즉, DOM에서 레이아웃 정보를 읽는 작업을 먼저 모두 수행한 후, DOM을 수정하는 작업을 별도로 처리하는 방식이다.
예시)
잘못된 방식 (레이아웃 쓰레싱 발생 가능):
element.style.width = element.offsetWidth + 10 + 'px';
element.style.height = element.offsetHeight + 10 + 'px';
개선된 방식 (레이아웃 쓰레싱 방지):
const width = element.offsetWidth;
const height = element.offsetHeight;
element.style.width = width + 10 + 'px';
element.style.height = height + 10 + 'px';
레이아웃 쓰레싱의 성능 영향
레이아웃 쓰레싱은 성능 저하를 유발하며, 특히 반복적인 DOM 조작을 할 때 큰 문제가 된다. 쓰레싱을 줄이면 웹 페이지의 성능을 크게 개선할 수 있다.
따라서, 레이아웃 쓰레싱을 피하려면 DOM에 접근하거나 조작할 때 최적화된 방식으로 처리하는 것이 중요하다.
5) Render Blocking
Render Blocking은 브라우저가 HTML을 파싱할 때, 특정 리소스(특히 CSS나 JavaScript)가 로드될 때까지 렌더링을 중단하는 현상을 말한다. 렌더링 중단이 발생하면, 웹 페이지가 사용자에게 늦게 표시되거나, 불완전한 상태로 표시될 수 있다. 이러한 현상을 막기 위해 다양한 최적화 방법이 있다.
Render Blocking을 막기 위한 방법들:
- CSS의 최적화
- CSS 파일 최소화: 불필요한 공백이나 주석을 제거하여 파일 크기를 줄인다.
- CSS 파일 병합: 여러 개의 CSS 파일을 하나로 병합해 HTTP 요청 수를 줄인다.
- 필요한 CSS만 로드: 페이지마다 필요한 CSS만 로드하고, 불필요한 CSS는 나중에 로드하거나 제거한다.
- Critical CSS 인라인화: 페이지의 주요 스타일(critical CSS)을 HTML 내부에 직접 인라인화하여, 초기 렌더링을 방해하지 않게 한다.
- JavaScript의 최적화
- defer 속성 사용: script 태그에 defer 속성을 추가하여, HTML 파싱이 완료된 후에 JavaScript가 실행되도록 한다.
- async 속성 사용: async 속성을 사용해 JavaScript를 비동기적으로 로드하고, 렌더링을 차단하지 않도록 한다.
- 필요한 JavaScript만 로드: 페이지마다 필요한 스크립트만 로드하고, 나머지는 나중에 로드하거나 lazy-loading을 활용한다.
- 리소스 로딩 최적화
- 리소스 압축: HTML, CSS, JavaScript 파일을 Gzip이나 Brotli와 같은 압축 방식으로 전송하여 로딩 속도를 높인다.
- HTTP/2 사용: HTTP/2 프로토콜을 사용하면 한 번의 연결로 여러 리소스를 동시에 다운로드할 수 있어 렌더링 차단을 줄일 수 있다.
6) CLS
CLS (Cumulative Layout Shift)는 웹 페이지가 로딩되는 동안 시각적 요소가 예기치 않게 이동하는 현상을 측정하는 지표이다. 사용자가 웹 페이지를 보는 중에 버튼, 이미지, 텍스트 등 시각적 요소가 갑작스럽게 위치를 변경하면, 사용성에 큰 영향을 미칠 수 있다. CLS는 이러한 레이아웃 이동이 얼마나 발생했는지에 대한 점수를 나타낸다.
CLS 개선을 위한 방법:
- 이미지 크기 명시: 이미지를 삽입할 때 width와 height 속성을 명시하여, 이미지가 로드되기 전에도 공간을 차지하게 만들어 레이아웃 이동을 방지한다.
- 비디오 크기 명시: 비디오 요소도 마찬가지로 크기를 미리 설정해 예기치 않은 레이아웃 이동을 막는다.
- 동적으로 삽입되는 콘텐츠 제어: 광고나 팝업처럼 동적으로 삽입되는 요소는 CSS에서 고정된 공간을 할당하거나, 로딩 후 레이아웃이 변경되지 않도록 한다.
- 웹 폰트 최적화: 웹 폰트 로드 중 텍스트가 갑자기 다른 폰트로 바뀌면서 레이아웃이 이동하는 문제를 방지하기 위해, font-display: swap 속성을 활용해 텍스트가 일시적으로 시스템 폰트로 표시되도록 한다.
7) FOUT & FOIT
FOUT (Flash of Unstyled Text)
FOUT는 웹 페이지 로딩 중 웹 폰트가 로드되기 전, 텍스트가 시스템 폰트로 잠깐 표시되는 현상이다. 웹 폰트가 완전히 로드되면 텍스트는 다시 지정된 폰트로 변경된다. FOUT는 사용자가 페이지 로딩 중에도 텍스트를 볼 수 있게 하지만, 폰트가 바뀌는 시각적 변화가 발생한다.
FOIT (Flash of Invisible Text)
FOIT는 웹 페이지 로딩 중 웹 폰트가 로드될 때까지 텍스트가 보이지 않는 현상이다. 폰트가 완전히 로드될 때까지 텍스트는 보이지 않다가, 폰트가 로드되면 한 번에 표시된다. 이로 인해 사용자는 텍스트가 늦게 나타나는 것처럼 느낄 수 있다.
웹 폰트를 빠르게 로드하기 위한 방법:
- font-display 속성 사용: font-display CSS 속성을 사용하면 텍스트의 로딩 방식을 제어할 수 있다. 예를 들어, font-display: swap을 사용하면 웹 폰트가 로드되기 전 시스템 폰트를 먼저 표시하고, 웹 폰트가 로드되면 그 폰트로 교체한다. 이를 통해 FOIT를 방지하고 FOUT를 완화할 수 있다.
- 서버 폰트 최적화: 웹 폰트를 서빙하는 서버를 최적화하여 폰트 로딩 속도를 높인다. CDN을 활용하거나 HTTP/2를 사용하면 여러 리소스를 동시에 빠르게 다운로드할 수 있다.
- 웹 폰트 파일 크기 줄이기: 웹 폰트 파일을 서브셋팅하여 실제 필요한 글자만 포함하고, 불필요한 글리프나 언어 파일을 제거하여 폰트 크기를 줄인다.
- Preload 사용: <link rel="preload"> 태그를 사용해 웹 폰트를 미리 로드하여 폰트 로딩 시간을 단축할 수 있다. 이를 통해 사용자가 처음 페이지를 열었을 때 폰트가 빠르게 적용될 수 있다.
8) 렌더링 성능을 측정할 수 있는 기준은 무엇일까?
웹 페이지 렌더링 성능을 평가하는 데에는 여러 가지 측정 기준이 있다. 렌더링 성능은 페이지가 사용자에게 표시되는 시간과 상호작용 가능한 상태가 되는 시간을 기준으로 평가할 수 있다.
렌더링 성능 측정의 주요 지표:
- First Contentful Paint(FCP):
- FCP는 웹 페이지에서 첫 번째 텍스트나 이미지 콘텐츠가 화면에 표시되는 시점을 측정한다. 사용자 경험에서 매우 중요한 지표로, 페이지가 얼마나 빠르게 콘텐츠를 로드하는지를 확인할 수 있다.
- Largest Contentful Paint(LCP):
- LCP는 페이지에서 가장 큰 콘텐츠 요소(예: 이미지, 동영상, 텍스트 블록)가 표시되는 시간을 측정한다. 이는 사용자가 페이지를 완전히 볼 수 있는 시점을 평가하는 중요한 지표다.
- Time to Interactive(TTI):
- TTI는 페이지가 로드되고 나서 사용자가 상호작용할 수 있는 상태가 되는 시점을 측정한다. 즉, 버튼을 클릭하거나 스크롤할 수 있을 때까지의 시간을 나타낸다.
- Cumulative Layout Shift(CLS):
- CLS는 페이지의 요소가 의도치 않게 움직이는 정도를 측정하는 지표다. 페이지 로딩 중 레이아웃이 갑작스럽게 변경되면 사용자가 혼란스러울 수 있기 때문에, 낮은 CLS 값이 중요하다.
- Total Blocking Time(TBT):
- TBT는 메인 스레드가 차단된 시간을 측정하는 지표로, 페이지가 얼마나 오랫동안 응답하지 않는지를 평가한다. 이 지표는 사용자가 페이지를 사용하는 동안 얼마나 부드럽게 반응하는지를 나타낸다.
9) Tree 구조
Tree 구조는 어떤 특성을 갖고 있는 자료구조인가?
트리(Tree)는 계층적 구조를 나타내는 자료구조로, 각 요소는 노드(Node)로 표현되며, 노드는 부모 노드(Parent Node)와 하나 이상의 자식 노드(Child Node)를 가질 수 있다. 트리의 최상단에 위치한 노드는 루트 노드(Root Node)라 하며, 자식이 없는 노드는 **리프 노드(Leaf Node)**라고 한다.
트리 구조의 주요 특성:
계층적 구조: 트리는 루트 노드에서 시작해 자식 노드로 뻗어나가는 구조로, 부모-자식 관계가 명확하다.
재귀적 구조: 트리는 자기 자신과 같은 구조를 포함하는 재귀적 특성을 가진다. 즉, 트리의 각 노드는 또 다른 서브트리(Subtree)를 구성할 수 있다.
연결성: 트리의 각 노드는 부모와 자식 노드를 통해 연결된다. 루트에서 특정 노드까지의 경로는 유일하다.
사이클 없음: 트리는 사이클이 없는 연결 그래프이다. 즉, 노드 간에 순환 구조가 존재하지 않는다.
트리 구조의 예시:
DOM 트리: HTML 문서가 트리 구조로 변환되어 요소들 간의 계층적 관계를 나타낸다.
이진 트리(Binary Tree): 각 노드가 최대 두 개의 자식을 가지는 트리.
검색 트리(Search Tree): 키 값을 기준으로 정렬된 트리로, 검색, 삽입, 삭제가 빠르다.
Tree 구조의 시간 복잡도는 어떻게 될까?
트리 구조에서의 시간 복잡도는 주로 트리의 **깊이(depth)**와 노드의 개수에 따라 달라진다. 트리 구조의 대표적인 연산과 그에 따른 시간 복잡도는 다음과 같다.
탐색(Search):
**이진 탐색 트리(Binary Search Tree)**에서 탐색 시간 복잡도는 트리의 깊이에 의해 결정된다. 균형이 잘 잡힌 트리(예: AVL 트리)에서는 **O(log n)**의 시간이 걸리며, 한쪽으로 치우친 경우(비균형 트리)에는 최악의 경우 **O(n)**의 시간이 걸린다.
삽입(Insertion):
트리의 삽입도 마찬가지로 트리의 깊이에 비례하므로, **O(log n)**에서 O(n) 사이의 시간이 걸린다.
삭제(Deletion):
삭제 또한 트리의 깊이에 따라 시간이 결정되며, **O(log n)**에서 **O(n)**의 시간 복잡도를 가진다.
균형 트리와 비균형 트리:
균형 트리(Balanced Tree): 트리의 모든 노드가 고르게 분포한 트리로, 깊이가 최소화되어 **O(log n)**의 시간 복잡도를 보장한다.
비균형 트리(Unbalanced Tree): 한쪽으로 치우쳐 있는 트리로, 이 경우 트리의 깊이가 **O(n)**이 될 수 있다.
'기타' 카테고리의 다른 글
프로그래밍의 3대 원칙 (8) | 2024.09.22 |
---|---|
vscode Prettier 설정 (0) | 2024.04.18 |
구글 계정 로그인 구현 (OAuth) (0) | 2023.06.22 |
웹팩(WebPack)이란? (0) | 2023.05.22 |
캐시(Cache)/캐시전략 이란? (0) | 2023.02.28 |