브라우저 렌더링 과정(완전 간단 설명)
자세한 설명은 아래 있습니다~!
https://heedonguri.tistory.com/113
1. DOM 트리와 CSSOM 트리 생성
2. DOM 트리와 CSSOM을 가지고 렌더 트리 생성
3. 생성된 렌더트리를 이용해서 레이아웃 계산
4. 계산된 값들을 기반으로 화면에 요소들을 그림
3번 과정을 다시 수행하는 것이 reflow이고 4번 과정을 다시 수행하는 것이 repaint이다.
Reflow와 Repaint
만약 스타일이나 DOM을 변경하는 경우에 리플로우가 발생하여 렌더트리를 재생성하고,
생성된 렌더트리를 기반으로 리페인트가 발생한다.
- Reflow
- 요소의 위치나 크기를 다시 계산하는 것
🤔 언제 발생하는데?
- DOM 요소의 기하학적 속성이 변경될 때
- 브라우저의 크기(viewport)가 변경될 때
- JS에서 DOM API 사용할 때(DOM 추가, 제거, 업데이트)
- Repaint
- 요소의 스타일을 재적용하는 것
🤔 언제 발생하는데?
- 리플로우가 발생했을 때
- 요소의 스타일이 변경될 때
visibility:hidden, background-color, outline 등의 스타일 변경은 repaint만 일으키는 속성이다.
Reflow와 Repaint 최소화
reflow와 repaint 과정을 피하는게 브라우저 최적화 하는 방법 중 하나이다.
- 애니메이션 요소의 위치를 absolute로 설정
애니메이션으로 요소의 위치를 변경할 때, 주변 요소의 위치도 변경되어 리플로우가 여러 번 발생한다.
하지만 애니메이션이 적용된 요소를 absolute로 설정한다면 주변 요소에 영향을 주지 않을 수 있다.
-visiblity 사용
visibility, display 둘 다 요소를 화면에 보이게하는 여부를 결정한다는 점에서 비슷하다.
visibility: hidden은 화면에서 공간은 차지하지만 우리 눈에 안보이는 것이고,
display:none은 공간도 차지하지 않는다는 점이 차이점이다.
공간을 차지하지 않는다는 말은 렌더트리에 포함되지 않는다는 뜻이고
따라서 display의 속성에 따라 영역이 생겼다 없어졌다 하면서
주변 요소의 위치와 크기에도 영향을 주기 때문에 reflow와 repaint가 발생한다.
하지만 visibility는 공간은 차지하지만 눈에만 보이지 않는 것이기 때문에
크기나 위치가 변하지 않아 repaint만 발생한다.
- DOM 속성 변경 코드 모아두기
JS로 DOM의 속성을 변경할 때, 코드 순서에 따라 reflow 횟수를 줄일 수 있다.
const el1 = document.querySelector('.target-first');
el1.style.width = '10px';
const el2 = document.querySelector('.target-second');
el2.style.width = '10px';
const el3 = document.querySelector('.target-third');
el3.style.width = '10px';
위의 코드에서는 reflow가 3번 발생한다.
const el1 = document.querySelector('.target-first');
const el2 = document.querySelector('.target-second');
const el3 = document.querySelector('.target-third');
el1.style.width = '10px';
el2.style.width = '10px';
el3.style.width = '10px';
위의 코드에서는 reflow가 1번만 발생한다.
이렇게 reflow 횟수에 차이가 나는 이유는 브라우저의 리플로우 처리 방식 때문이다.
브라우저는 변경할 요소가 있으면 큐에 저장해뒀다가 일정 시간이 지나거나 큐에 작업이 쌓이면 reflow를 실행한다.
따라서 DOM을 수정하는 코드를 모아두면 큐에 쌓여있다가 한 번에 처리되기 때문에 reflow 횟수를 줄일 수 있다.
- Reflow를 유발하는 메서드는 별도로 저장해서 사용
DOM 속성 변경 코드를 모아두는 것과 비슷한 방법이다.
for(let i=1; i<10; i++){
div.style.left = (div1.getBoundingClientRect().left + i) + 'px';
}
위처럼 사용한다면 반복문이 돌 때마다 매번 reflow가 발생한다.
let {left} = div1.getBoundingClientRect();
for(let i=1; i<10; i++){
div.style.left = (left + i) + 'px';
left += i;
}
하지만 위의 코드로 변경하면 한 번 호출한 후, 변수에 저장해서 사용할 수 있게 된다.
- virtual DOM
DOM의 스타일이 변경될때마다 리렌더링 되는 것은 비효율적인 작업이다.
리액트나 뷰를 사용중이라면 virtual DOM이 이런 비효율을 해결해준다.
virtual DOM은 저장된 DOM과 현재 DOM을 비교하여 변경된 부분만 실제 DOM에 반영하기 때문에
모든 DOM에 영향을 주지 않고 필요한 DOM만 바꾸기 때문에 불필요한 재렌더링을 막아준다.
어떤 CSS 속성이 reflow와 repaint를 일으키는지 궁금하다면 아래의 사이트를 참고해보자.
'WEB' 카테고리의 다른 글
웹 레이아웃 (0) | 2024.07.31 |
---|---|
Border vs Outline (0) | 2024.07.31 |
브라우저 렌더링 과정 (0) | 2024.07.03 |
XSS (0) | 2024.07.02 |
CSRF (0) | 2024.07.02 |