앞선 게시물에서 브라우저가 어떤 단계를 통해서 렌더링을 하는지 알아보았습니다.
그렇다면,
🧏♂️ 그 렌더링을 잘했다고 소문나기 위해선 어떻게 해야할까?
에 대해서 다루어 보려고 합니다. 브라우저 렌더링 최적화를 고민해보자구요.
rendering 은 엔진이 다 그렸다고 끝나는 것이 아닙니다.
Rendering
, 그 후렌더링이 마치고 나서는, 추가적인 작업이 필요할 수 도 있습니다.
그렇다면, 필요할 때는 언제이고, 추가적인 작업은 또 무엇?
추가적인 작업은, Reflow
와 Repaint
라고 합니다.
Reflow
Reflow
의 정의를 알아보기 전에, 언제 이 친구가 수행되는지 알아보죠.
특정 액션이나 이벤트로 인해
HTML
요소의 크기나 위치가 변동되었을 때.
레이아웃 수치가 변동되었을 때.
이 두 가지 상황에 의해서 영향을 받는 노드들은 다시 Layout
계산하기 단계를 다시 거칩니다.
function reflow() { document.getElementById('content').style.width = '600px'; }
이와 같이 레이아웃을 변경하므로, Reflow
가 일어납니다.
Layout
계산하기 단계 단계가 궁금하시다면, 여기를 누르면 해당 내용을 확인 할 수 있습니다.결론은)
Rendering Tree
의 노드들중 영향받은 노드들은 브라우저 내 어디에 위치할 건지 다시 계산합니다.
Repaint
reflow
단계만 거쳐서는 실제 화면에 반영되진 않습니다.
브라우저 렌더링 4번째 단계 처럼 다시 그림을 그려야, 브라우저에 수정내용이 반영됩니다.
그 단계가, Repaint
라고 합니다.
🔥 하지만 무조건
Reflow
가 일어나야Repaint
가 수행되는 건 아닙니다.
CSS
속성이 변경된다면, Reflow
를 수행할 필요가 없습니다.그 예로는) background-color
, visibiity
속성이 있겠네요.
Reflow
, Repaint
?결론부터 말하자면)
Reflow
,Repaint
연산을 줄여야 브라우저를 효율적으로 렌더링 합니다.
그 연산을 최소화하는 방법이 무엇이 있는지 코드 라인으로 정리해보겠습니다.
CSS
업데이트하기.// bad
const body = document.body;
body.style.width = '50px';
body.style.height = '100px';
// good
const body = document.body;
body.style.cssText = 'width: 50px; heigh: 100px;';
첫번째 케이스는 2번 Reflow
가 일어나므로, 리렌더링이 아래 경우보다 한번더 일어납니다.
innerHTML
한번만 사용하기.이 케이스는 상당히 많이 보이며, 충분히 쉽게 해결할 수 있습니다.
toDoData.forEach((rawData, index) => rawData.isCompleted ?
todoLists.innerHTML += `<s>${index + 1}. ${rawData.text}</s></br>` :
todoLists.innerHTML += `${index + 1}. ${rawData.text}</br>`;
상단 코드는 toDoData
라는 배열을 모두 순회합니다.
👉 매번 innerHTML
를 조작하기 때문에, Reflow
가 굉장히 많이 일어납니다.
아래처럼 바꾸면 상당히 효율적이겠죠.
let todoDataHTMLString = ''
this.todoData.forEach((rawData, index) => {
todoDataHTMLString += rawData.isCompleted
? `<s>{index + 1}.${rawData.text}</s>`
: `${index + 1}. ${rawData.text}</br>`
})
todoLists.innerHTML = `
<h3>ToDo List</h3>
${todoDataHTMLString}`
todoDataHTMLString
변수를 하나 설정하여, 한번에 innerHTML
속성을 업데이트 합니다.
이렇게 렌더링 과정과, 간단하게 최적화까지 다뤄보았습니다.
잘못된 내용이 있다면 댓글로 알려주세요 :)