참고: https://12bme.tistory.com/140
리액트 따라 만들기를 하다가 동시성의 원리가 궁금해져서 따로 알아본 것들에 대하여 의식의 흐름대로 정리합니다.
맨날 이런거 저런거 찾아보다가 정작 원래 하려고 했던 것들의 진행이 늦어집니다 ㅠ
참고한 블로그의 글은 개발을 시작하고 나서 읽은 기술과 관련된 글 중에 최고네요,, 정말 하나같이 몰랐던 내용들 ( 아무도 알려주지 않았던)이 가득합니다.. 여러번 읽어도 좋을 것 같다.
브라우저의 렌더링 과정
- 돔 요소와 스타일에 기반을 둔 레이아웃 계산
- 계산 요소의 화면 표현 (페인팅)
먼저 html 테그들을 파싱해서 돔트리를 구성함
css를 한데 모아 cssom 이라는 트리 구조의 스타일 구조체를 생성함
이 둘을 한데 모아 레이아웃을 계산 => 렌더 트리를 생성함 -> 이후에 실제 화면에 요소들을 그림
그러면 js코드들을 통한 interaction은 언제 적용 되는거지..? 페인팅 이전? 이후? --> 이후에 실행이 되는게 맞죠!
왜나면 서버사이드 렌더링 공부할때 알았거든요 ㅋㅋ (서버에서 페인팅이 끝난 html과 실행해야할 js를 내려주면 이후에 js가 실행되면서 interaction이 등록됨 이 사이의 시간에서 사용자에게는 완성된 화면이 보여지지만 실제 상호작용은 불가능)
프론트엔드의 성능을 올리려면 결국 리플로우의 횟수를 줄여야 함.
리페인트도 비용이 발생하기는 하지만, 단순 css 변경 과 같은 리페인트의 비용은 리 플로우에 비하면 매우 적음
대표적으로 리플로우가 많이 발생하는 경우
- DOM 노드의 변경: 추가, 제거 업데이트
- DOM 노드의 노출 속성을 통한 변경: display:none은 리플로와 리페인트를 발생시키지만 비슷한 속성인 visibility:hidden은 요소가 차지한 영역을 유지해 레이아웃에 영향을 주지 않으므로 리페인트만 발생시킵니다.
- 스크립트 애니메이션: 애니메이션은 DOM 노드의 이동과 스타일 변경이 짧은 시간 내에 수차례 반복해 발생되는 작업입니다.
- 스타일: 새로운 스타일시트의 추가 등을 통한 스타일 정보 변경 또는 기존 스타일 규칙의 변경
- 사용자의 액션: 브라우저 크기 변경, 글꼴 크기 변경 등
크롬 | 사파리 에서는 개발자 도구를 통해서 렌더링 과정을 확인 할 수 있음.
크롬에서는 렌더링 처리는 세 단계로 나뉨
- Recalculate Style: 요소의 스타일값을 재계산하는 단계
- Layout: 리플로가 발생한 단계
- Paint: 변경된 요소를 화면에 표현하는 단계
렌더 트리의 변경으로 인한 리플로우와 리페인트는 비용이 비싸서 성능 저하를 유발 합니다.
브라우저는 이 작업을 최적화 하기 위해서 이 작업들의 실행 순서를 조정하거나 작업을 모아서 한번에 처리하는 방식을 사용 함.
관련 작업을 큐(queue)에 쌓고 일정 시간 또는 일정 수의 작업이 쌓인 이후에 배치로 관련 작업을 한 번에 처리해서 여러 번 발생할 수 있는 리플로를 한 번으로 줄인다.
그런데, 브라우저는 값의 반환을 요청 받으면 최신의 값을 리턴하기 위해서 이러한 최적화를 중단하고 즉시 큐에 쌓인 것들을 실행시키는데 이 과정에서 추가적인 리플로가 발생 할 수 있음.
최적화를 중단시키는 메소드의 리스트
결국, 리플로를 줄이기 위해서는
- 작업 그루핑
- 비슷한 형태의 작업끼리 묶어서 실행하면 리플로를 줄일 수 있음 아래와 같이 특정 요소의 스타일을 얻고
- 그 스타일을 다른 요소에 적용할때, 작업을 묶어서 리플로를 줄일 수 있다!
function change() {
var width = document.getElementById("layer1").style.width;
var height = document.getElementById("layer3").style.height;
document.getElementById("layer2").style.width = width;
document.getElementById("layer4").style.height = height;
}
//출처: https://12bme.tistory.com/140 [길은 가면, 뒤에 있다.]