성능 최적화 방법

jjyung·2022년 1월 6일
1

React

목록 보기
6/7
post-thumbnail

글을 작성하게 된 계기

현재 캘린더 프로젝트를 진행중인데 우리조는 리액트를 얼마나 잘 활용할지를 목표로 삼았다. 그러다보니 성능 최적화와 컴포넌트 분리에 대한 부분은 정말 중요하다고 판단이 되었고, 이 부분에 대해 공유하고 싶어 글을 적게 되었다.

성능 최적화란?

성능 최적화란 UI를 최적화하여 애플리케이션의 속도를 높이는 것을 의미한다. 아무래도 사용자 경험이 중요한데 로딩 속도가 느리다보면 사용성이 떨어진다고 판단할 수 밖에 없다 (물론 사용자가 느끼는 성능은 상당히 주관적일수 있다).

성능 최적화는 각종 비용을 최소화하는 측면에서 설명할 수 있는데, 이는 메모리의 사용량과 처리 시간에 따라 소모되는 리소스량이 달라지고 성능과 직결적인 영향을 미친다. 프론트엔드 개발자는 성능 개선을 위하여 최소한의 데이터와 최대한 빠른 시간에 화면을 그려내어 최적화된 사용자 경험을 제공해야한다.

성능 저하 요인

성능 최적화 방법을 찾기에 앞서 원인을 파악해보고자 한다. 아무래도 성능을 저하시키는 요인은 다양하게 존재하지만, 가장 대표적으로는 DOM의 Mutation을 예시로 들수있다. DOM mutation이 발생하다보면 성능 이슈가 생길 수 밖에 없고,그러다보면 사용자 경험이 저하될 수 있다는 문제점을 React 팀에서는 언급하며 오픈 소스를 공표했다. 다시 말하자면 돔을 조작하는 비용이 비싸다는 것을 알 수 있다.

그렇다면 이 돔 조작은 언제 발생하는가? 레이아웃이 바뀌거나 애니메이션이 발생하면 돔이 조작된다. 즉, 브라우저 렌더링 과정을 조금 더 자세히 살펴보면 이해가 잘 갈것이다.

left, right, top, bottom, position이 바뀌거나, height, width가 바뀌는 경우처럼 레이아웃이 아예 바뀌는 경우는 레이아웃을 다시 그리고 리페인트가 일어나게 된다. (물론 색상이 변경되거나 백그라운드가 변경되는것 처럼 레이아웃이 바뀌지 않는다면 레이아웃이 다시 그려지지 않아 리페인트만 발생한다.)

또한, 어떤 사이트에 이미지가 상당히 많다면 화면을 그려낼때 이미지를 다운받아야 하기때문에 시간이 상당히 오래걸린다. 우리가 어떤 사이트에 들어갔는데 이미지가 보이지않아 기다리며 답답했던 경험이 있을 것이다. 이런 사용성때문이라도 성능 최적화가 필요하다.

성능 최적화 방법

그래서 이런 문제점을 해결하고 성능을 최적화하는데 어떤 방법이 있을까? 성능 최적화에는 네트워크 최적화와 렌더링 최적화로 나눌 수 있다. 렌더링 최적화는 화면에 그려내거나 사용자와의 interaction 시간을 최적화 하는 방법을 다루고, 네트워크 최적화는 네이워크 서비스 품질을 의미한다. 네트워크 최적화에 대해서 조금 더 자세히 설명하자면 사이트의 대기 시간과 네트워크 보안 이슈같은 것들을 포괄한다.

우선, 성능 최적화 중 렌더링 최적화에 대해 말해보고자 한다. 렌더링 최적화를 위해서는 transition대신 transformation을 사용하는 방법이 있다. 모든 속성이 다시 레이아웃 단계를 거치는 것이 아니기때문에 대체 가능한 속성을 사용하는 것이 좋다.(리플로우라는 단어는 주로 파이어폭스 브라우저에서 사용하는 용어이다. 그래서 리플로우보다는 레이아웃이라는 단어가 더 일반적이라고 볼 수 있다. 사실 다시 레이아웃을 그리는 것과 리플로우는 같은 개념이다)

또는, 모듈 번들링, 트리 쉐이킹, 코드 스플리팅, 메모이제이션을 사용하여 문제를 개선할 수 있다. 모듈 번들링을 통해 쪼개었던 코드를 하나로 합쳐주면서 렌더링을 한 번만 할 수 있게 해주었다. 트리 쉐이킹 또한 필요하지 않은 코드를 제거할 수 있다. 예를 들어 로다쉬 API를 사용했을때 전체를 가져오는 것이 아니라 필요한 부분만 가지고 오며 성능이 개선될 수 있다.


(22.01.18 추가) Render Tree 형성 과정과 로딩 시간

렌더 트리 형성 과정

  1. DOM 트리의 루트에서 시작해 노드 각각을 읽으며 표시한다.
    -> 이 때 메타 태그, 스크립트 태그등은 제외된다.
    -> display:none같으 요소는 렌더 트리에서 누락 (단, opacity나 visibility:hidden은 그려짐)

  2. 각 노드에 일치하는 CSSOM 규칙 찾아 적용

  3. 표시된 노드를 콘텐츠 및 계산된 스타일과 함께 레이아웃->페인팅

렌더링 경로 최적화

  • 로딩이 1초 길어질 경우 연간 자그마치 1.6조달러 손실이 발생한것으로 아마존에서는 산출
  • 즉, 웹 로딩의 속도와 성능 최적화는 IT 기업 매출에 큰 영향을 미침

(22.01.08 추가) 레이아웃 다시그리는 요인 정리

  1. Resizing the window
  2. Adding/removing a stylesheet
  3. Content Changes(text in an input box)
  4. Activation of Css pseudo (:hover)
  5. DOM mutation
  6. offsetWidth and offsetHeight
  7. style attribute

invasiveness layout (layout 일으키는 요소)

-> width, height, padding, margin, left, right, display, border-width, border, top, position, float, font-size, font-weight, overflow-y....

layout 최소화 하는 법

  1. 최대한 DOM 구조 상 끝단에 위치한 노드에 추가
  2. animation이 들어간 element는 가급적 position:fixed / absolute로 지정
    • 다른 요소에 영향을 끼치지 않아 해당 요소만 reflow 발생
  3. JS 통해 스타일링시 가급적 한번에 처리
  4. 인라인 스타일 최대한 배제
  5. 테이블 레이아웃 피하기 (넓이를 계산하다보니 렌더링 느려짐 -> 꼭 사용해야할 때 table-layout:fixed 사용하기)
  6. will-change 검토하기
    • 변화가 예상되는 요소를 브라우저에게 미리 알려준다.
    • 다만 너무 많이 사용하지말고, 애니메이션 동작이 끝난 후 기본 상태로 되돌리기
    • auto : 기본값으로 브라우저 최적화 실시하지 않음
    • scroll-position : 스크롤 할 때 엘리먼트의 위치가 변경될 것을 알려줌.
    • contents : 엘리먼트의 컨텐츠가 변경될 것을 알려줌. (렌더링 결과를 캐시하지 않고 변경될때마다 처음부터 렌더링)
    • : 변경하고 싶은 속성을 사용 (opacity, transform, top, left, right, bottom)
  7. transition(left, right...)대신 transform: translateY 사용하기

결론

성능 최적화적인 측면에서보면 네트워크와 노트북 모두 렌더링 최적화로 나눌 수 있다는 것을 처음 알았다. 그리고 프로젝트를 진행할 때 꼭 라이트 하우스도 직접적으로 변경해보아야겠다는 생각을 했다

Word Cited

  1. reflow-google docs
  2. animation reflow
  3. Reflow 최적화 방법
  4. CSS Layout 발생시키는요소
  5. Render 트리 형성 과정과 CRP
profile
🏃‍♀️movin' forward, developer

0개의 댓글