1편 - [Web Programming/Frontand Challenge] - 웹 페이지의 랜더링 과정 1편
참고 블로그 : http://12bme.tistory.com/140
1편에서 웹 페이지의 랜더링 순서를 1단계부터 5단계 까지 알아보았다.
이번 2편에서는 리플로와 리페인트에 대해 알아보겠다.
.
.
레더링이 모두 완료된 상태에서 ( 페인트까지 끝낸 상태 ) 스타일이 바뀌거나
새로 나타나는 노드가 있다면...? 또는 데이터 변경으로인해 ( ex. AJAX ) 다시 표시해 주어야하는 일이 생긴다면?
아마 다시 스타일을 적용하고 ( 랜더 트리 작업 ) 페인트 해주어야 할 것이다.
이럴 경우에 발생하는 것이 리플로와 리페인트이다.
리플로 ( Reflow )란?
변경이 생긴 랜더 트리에 대해 유효성 확인을 하고 노드의 크기와 위치를 다시 계산하는 작업이다.
랜더 트리 작업과 레이아웃 처리를 다시 하는 것 같다.
리페인트 ( Repaint )란?
변경된 노드를 화면에 업데이트 하여 표시해주는 것을 의미 한다.
리플로가 발생 했을 때, 색 변경등 단순 스타일 변경이 일어날 시 발생합니다.
다시 계산되고 뿌려주는 작업이니 당연히 처리 비용이 발생 되고 ( 리플로우가 리페인트 보다 비용이 높다. )
많이 발생할 시 웹 페이지를 표시하는데에 시간이 걸려 사용자가 불편함을 느낄 수 있다. 😒
따라서, 이를 어떤 방법으로 줄이는지 알아 보자.
소개된 방법으로는 총 5가지가 있다.
① 작업 그루핑
항상 이름을 보면 대충 어떤건지 알 수 있는 것 같다.
작업 그루핑은 비슷한 형태의 작업을 묶어 실행 되도록 해주는 것이다.
참고한 블로그의 코드 예제를 보면 이해 하기 쉽다.
1 2 3 4 5 6 7 | function change() { var width = document.getElementById("layer1").style.width; document.getElementById("layer2").style.width = width; var height = document.getElementById("layer3").style.height; document.getElementById("layer4").style.height = height; } 출처: http://12bme.tistory.com/140 [명확함은 충일함에서 나온다.] | cs |
위의 코드를 보면 스타일 정보 요청 후 스타일을 변경하고 있다.
이렇게 코드를 사용할 경우 동일한 형태의 작업이 두번 반복되면서 리플로가 여러번 발생할 수 있다.
따라서, 아래 처럼 비슷한 역할을 하는 코드를 묶어주도록 순서를 바꾼다.
1 2 3 4 5 6 7 | 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; } 출처: http://12bme.tistory.com/140 [명확함은 충일함에서 나온다.] | cs |
② 실행 사이클
참고 블로그를 읽으면서 가장 뭔소린지 몰랐다 ㅎ... "이벤트 루프 모델"을 몰라서 ^^..( 부끄 😣 )
http://eine.tistory.com/40 사이트에서 또 참고해서 공부했다 ㅎ... 머리가 나빠서 재깍재깍 이해를 못하는지라 세번정도 읽었다.
랜더링 참고 사이트에서는 ' 이러한 실행 사이클로 인해 타이머를 사용하면 수차례의 리플로와 리페인트가 발생 될 수 있다. ' 라고 적혀있다. 이벤트 루프 모델 설명을 보면 바로 이해가 되니 넘어가겠다!
( 타이머 함수를 사용함으로써 중복 발생이 일어나기에 타이머를 사용하지 말라라고 적어 논것 같다. )
③ 노출 제어를 통한 리플로 최소화 방법
③ - ① display 속성
앞에서 잠깐 언급을 했던 것 같은데 ( 🤔..? )
display 속성이 none이라면 화면에 보여지지 않는 친구가 되므로 랜더 트리를 만들 때 포함이 되지 않는다.
이를 이용한 방법이다.
1 2 3 4 5 6 7 8 9 10 | var element = document.getElementById("box1"); for(var i=50; i<100; i++) { element.style.width = i + "px"; } for(i=1; i<=50; i++) { element.style.borderWidth = i + "px"; } 출처: http://12bme.tistory.com/140 [명확함은 충일함에서 나온다.] | cs |
위의 코드와 같이 box1의 크기를 변경하게 된다면 값이 변경이 될 때마다! 리플로와 리페인트가 발생한다. ( 아주 나쁨..! )
만약 위의 코드를 아래와 같이 변경 한다면..?
1 2 3 4 5 6 7 8 9 10 11 12 13 | var element = document.getElementById("box1"); element.style.display = "none"; for(var i=50; i<100; i++) { element.style.width = i + "px"; } for(i=1; i<=50; i++) { element.style.borderWidth = i + "px"; } element.style.display = "block"; 출처: http://12bme.tistory.com/140 [명확함은 충일함에서 나온다.] | cs |
이럴 경우 리플로, 리페인트가 display block시점 ( 보여지는 시점에 ) 한번만 일어나게 된다. 👍
③ - ② 노드 복제
변경하고싶은 요소의 노드를 복제 후 복제된 노드를 변경하는 방법니다.
맨처음 노드 복제 후 > 스타일 변경 > 대체
1 2 3 4 5 6 7 8 9 10 | var element = document.getElementById("box1"); var clone = element.cloneNode(true); // 원본 노드를 복제한다. for(var i=0; i < 100; i++) { clone.style.width = i + "px"; } // 변경된 복제 노드를 DOM 트리에 반영하기 위해 기존 노드와 치환한다. parentNode.replaceChild(clone, element); 출처: http://12bme.tistory.com/140 [명확함은 충일함에서 나온다.] | cs |
③ - ③ createDocumentFragment() 메서드 사용
함수 설명 : https://www.w3schools.com/jsref/met_document_createdocumentfragment.asp
- 위와 동일한 구조
④ 캐싱
컴정과인 나에겐 이제 이름만 봐도 알 것 같은 방법이다..😤
캐싱은 별도의 변수에 자주 사용하는 값을 저장하는 방법이다.
특정 속성과 메소드를 사용하기만 해도 리플로가 발생 된다.
( 따로 첨부하지 않았지만 참고 블로그에 보시면 리플로 발생 메소드가 정리 되어 있습니다. 그중에 하나가 scrollWidth )
아래의 코드에서 scrollWidth 를 호출할 때마다 리플로가 계속 발생하고 있다.
1 2 3 4 5 | for(condition) { el.style.width = el.scrollWidth + "px"; el.style.left - el.scrollLeft + "px"; } 출처: http://12bme.tistory.com/140 [명확함은 충일함에서 나온다.] | cs |
아래처럼 변수에 담아 리플로가 한번만 발생하도록 사용하자.
⑤ CSS 규칙
자바스크립트에서 자주 스타일의 속성값을 변경할텐데 이 때 요소의 개수가 많아질수록 랜더링 성능이 저하 될 수 있다.
이런 경우에는 각 요소에 하나하나 접근하기 보다는 css 규칙을 만들어 바꿔주는 것이 좋다.
*주의할 점*은 대상 요소의 수가 많지 않을 경우 오히려 개별 요소에 접근해 처리하는 방식이 더 빠르다.
( 항상 규칙이 빠르지 않다. )
1 2 3 4 5 6 7 8 9 | document.getElementsByTagName("head")[0].appendChild(document.createElement("style")); var oStyle = document.styleSheets[document.styleSheets.length - 1]; if(oStyle.addRule) { // 인터넷 익스플로러의 경우 oStyle.addRule("div", "background-color:green"); } else { // 그 밖의 바라우저 oStyle.insertRule("div {background-color:green;}", 0); } 출처: http://12bme.tistory.com/140 [명확함은 충일함에서 나온다.] | cs |
'~ 2024.08' 카테고리의 다른 글
[ 정보처리기사/산업기사 ] 데이터베이스 실무 응용 핵심 정리 (0) | 2018.10.06 |
---|---|
ajax ( Asynchronos Javascript And Xml )를 사용해보자! (0) | 2018.09.29 |
웹 페이지의 랜더링 과정 1편 (2) | 2018.09.23 |
SVG ( Scalabe Vector Graphic ) 이미지를 사용해보자! (0) | 2018.09.22 |
캐러셀 ( carousel ) 만들기 / 반응형 슬라이드 만들기 (8) | 2018.09.19 |