FE 지식_4. 브라우저 렌더링 최적화

Derek·2021년 5월 25일
4

FE_knowledge

목록 보기
4/5
post-thumbnail

앞선 게시물에서 브라우저가 어떤 단계를 통해서 렌더링을 하는지 알아보았습니다.

그렇다면,

🧏‍♂️ 그 렌더링을 잘했다고 소문나기 위해선 어떻게 해야할까?

에 대해서 다루어 보려고 합니다. 브라우저 렌더링 최적화를 고민해보자구요.

그 전에, 알아두어야 하는 점이 하나 있습니다.

rendering 은 엔진이 다 그렸다고 끝나는 것이 아닙니다.


Rendering, 그 후

렌더링이 마치고 나서는, 추가적인 작업이 필요할 수 도 있습니다.

그렇다면, 필요할 때는 언제이고, 추가적인 작업은 또 무엇?

추가적인 작업은, ReflowRepaint 라고 합니다.

Reflow

Reflow 의 정의를 알아보기 전에, 언제 이 친구가 수행되는지 알아보죠.

특정 액션이나 이벤트로 인해

  1. HTML 요소의 크기나 위치가 변동되었을 때.

  2. 레이아웃 수치가 변동되었을 때.

이 두 가지 상황에 의해서 영향을 받는 노드들은 다시 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 속성을 업데이트 합니다.



이렇게 렌더링 과정과, 간단하게 최적화까지 다뤄보았습니다.

잘못된 내용이 있다면 댓글로 알려주세요 :)


출처) https://boxfoxs.tistory.com/408
출저) https://falsy.me

profile
Whereof one cannot speak, thereof one must be silent.

0개의 댓글