데보션앱 소개페이지 바로가기
로그인 선택

신고하기

CLOSE
신고사유 (대표 사유 1개)
상세내용 (선택)
0/200
  • 신고한 게시글은 더 이상 보이지 않습니다.
  • 이용약관과 운영정책에 따라 신고사유에 해당하는지 검토 후 조치됩니다.
  • 허위 신고인 경우, 신고자의 서비스 이용이 제한될 수 있으니 유의하시어 신중하게 신고해 주세요.
(이 회원이 작성한 모든 댓글과 커뮤니티 게시물이 보이지 않고, 알림도 오지 않습니다.)

미리보기

커뮤니티

      1,234

      badge 23.06.15

      글 등록

      카테고리를 선택해주세요.

      DEVOTEE를 활성화 시키면
      지금 작성한 커뮤니티 글에 대해 1개의 댓글을 달아줍니다.

      버튼을 누르면 글 수정 시 ChatGPT가 작성한 댓글이 수정됩니다.

      임시저장함에 저장되었습니다. 저장일시 : 2022.5.17 14:29:08

      임시저장함

      제목을 선택하시면 이어서 작성이 가능하며,
      최대 20건까지 저장합니다.
      컨텐츠 유형, 제목, 저장일시, 삭제로 이뤄진 임시저장 목록
      컨텐츠 유형 제목 저장일 삭제

      데보션 블로그 게재 요청

      CLOSE
      • *
      • *

      본인인증

      효율적인 데보션 서비스 이용 및
      고객님의 소중한 개인정보보호를 위해
      본인인증을 진행해주세요. 본인인증 미 진행 시 로그인이 제한됩니다.
      본인인증 실패

      본인인증 로그인에 실패하였습니다.
      회원이 아니시거나 본인인증 등록이
      완료되지 않은 사용자입니다.

      회원정보 연결

      OpenLab 2기 - 웹 프론트엔드 성능 최적화 : 5번째 스터디 (4장 CLS, React-Dev-Tool )

      clcl6084 24.11.12
      439 3 0
      DEVOTEE 요약
      본 블로그는 웹 프론트엔드 성능 최적화 스터디의 경험을 공유하며, 특히 이미지 갤러리 최적화 및 CLS, React Developer Tools 사용법을 설명합니다. 이미지의 차원을 지정하여 CLS 문제를 해결하고, React Developer Tools를 통해 컴포넌트 구조 및 렌더링 성능을 분석하는 방법을 소개합니다. 이 과정을 통해 효과적이고 유익한 스터디 경험을 강조하며, 발표 및 블로그 작성이 지식 확장에 어떻게 기여했는지를 이야기합니다.
      DEVOTEE 추천 블로그

      안녕하세요. 이정민입니다.


      웹 프론트엔드 성능 최적화 스터디에 참여하게되어 영광이였습니다.

      제가 조사하고 발표했던 부분에 대해서 블로그로 작성하게 되었습니다.

      저희 교재 4장의 이미지 갤러리 최적화의 CLS부분과, 뒷부분에 나오게될 React-Dev-Tool을 톺아보았습니다.

      이미지 갤러리 최적화

      메인 화면

      이미지 클릭

      main

      image-click

      네번째 장은 이미지 간단한 이미지 갤러리입니다. 헤더를 통해서 이미지들을 필터링합니다. 이미지를 클릭하면 평균 픽셀값을 계산하면 오버레이로 띄어줍니다.

      CLS (Cumulative Layout Shift ) 발생요인

      CLS 발생

      퍼모먼스 측정

      이번장에서는 위와 같이 lighthouse를 통해서 CLS가 발생하는 것을 명확히 알 수 있고, performance Tab을 통해서도 확인 할 수 있습니다.


      CLS는 아래와 같은 요인들로 발생하는데요, 이번 장에서는 이미지에 치수가 들어가 있지않아 발생하는 경우에 대해 다룹니다.

      • 광고, 임베드와 같은 동적 컨텐츠

      • 애니메이션

      • 웹 폰트

      • 치수가 없는 이미지 - ✅ 이번장

      치수가 없는 이미지에 대한 대응

      치수가 정확하게 한 사이즈로만 렌더링이 된다면, 문제는 간단하게 해결될 것입니다.

      <img src="/image/url.png" alt="placeholder" width="300px" height="300px" />

      이렇게 먼저 width와 height 속성을 추가하면 브라우저가 이미지를 가져오기전에 공간을 먼저 할당해 놓기때문에, Reflow가 최소화될 것입니다.


      하지만 반응형 웹 디자인의 도입으로 width와 height를 생략하고 아래와 CSS로 이미지 크기를 제어하고자 하기 시작합니다.

      img {
        width: 100%;
        height: auto;
      }

      하지만 이미지 크기가 지정되지 않으므로 브라우저에서 다운로드를 시작하고 크기를 확인할 때까지는 공간을 할당할 수 없게됩니다.

      이런 상황때문에 비율이라는 개념이 들어오게 되는데, 크기 중 하나를 알면 브라우저가 관련 영역에 충분한 공간을 잡아 줄 수 있습니다.

      둘중에 하나만이라도 특정값을 명시해놓으면 브라우저는 이를 기반으로 이미지의 비율을 추가합니다.

      <!-- 16:9 비율을 위한 width, height 설정 -->
      <img src="devocean.png" width="640" height="360" alt="Devocean open lab" />

      하지만 저희는 자동으로 계산되는 것보다 디자인이 나온대로 대응을 해주어야합니다.

      저희가 원하는 비율로 나오게끔 해야하는 거죠. 대부분의 경우 반응형으로 디자인이 설계가 되어있고, 이미지의 비율이 그와 맞지않을때가 많습니다.


      교재에서는 두가지 방식을 제안합니다.

      Padding-hack 기법

      Aspect Ratio 프로퍼티 사용

      padding-hack

      aspecct-ratio

      오래된 브라우저에서도 호환성이 좋고, 원하는 비율을 직접 설정가능합니다. 하지만 유지보수가 어렵고, 코드가 길어질 수 있습니다.

      코드가 간결하고 직관적이며, 요소가 비율을 유지하면서 자동으로 조정됩니다. 비교적 최신 CSS라서 오래된 브라우저는 지원이 안될 수도 있기 때문에 폴리필을 고려해야합니다.

      각각의 트레이드오프가 있는 것 같아서, 개인적으로 좋아하는 Radix UI에서는 어떻게 적용하고 있는지 궁금해서 찾아봤습니다.

      Aspect Ratio라는 래퍼 컴포넌트에서는 Padding-hack 기법을 통해서 구현되있는 것을 확인할 수 있었어요. 아무래도 호환성 때문인 것 같습니다.

      const AspectRatio = (props, forwardedRef) => {
        const { ratio = 1 / 1, style, ...aspectRatioProps } = props;
        return (
          <div
            style={{
              position: "relative",
              width: "100%",
              paddingBottom: `${100 / ratio}%`,
            }}
          >
            <Primitive.div
              {...aspectRatioProps}
              ref={forwardedRef}
              style={{
                ...style,
                position: "absolute",
                top: 0,
                right: 0,
                bottom: 0,
                left: 0,
              }}
            />
          </div>
        );
      };

      ⚛️ React Dev Tool 톺아보기

      dev-tool

      앞장에서 사용한 network, performance, lighthouse 특히 performance는 써본적 없을 수 있지만 프론트엔드 개발자라면 써본적이있는 React Developer Tools를 이번 챕터에서 다룹니다.

      하지만 safari나 지원하지 않는 브라우저에서는 패키지를 다운받아 사용할 수 있습니다. ( 특히 React native )

      다운로드 및 사용법

      # yarn
      yarn global add react-devtools
      
      # npm
      npm install -g react-devtools
      
      # 실행
      react-devtools

      global로 설치한다음 react-devtools 커맨드를 입력해서 실행합니다.

      usage2

      위와 같이 실행이되고, React Native같은 경우는 이 가이드이 가이드에 따라서 진행하시면 될 것 같습니다.

      그 외, safari 환경에서 실행해야하는 경우는 위에서 요구하는 script 태그를 본문에 넣어주면 해당 응용 애플리케이션에서 실행이 됩니다.

      <!DOCTYPE html>
      <html lang="en">
          <head>
            <script src="http://localhost:8097"></script>
            <title>React App</title>
            <body></body>
      </html>

      ⚛️ Components

      • 컴포넌트 계층 구조를 시각적으로 확인

      • 컴포넌트 상태와 프롭스 조회 및 조작

      • 컴포넌트 훅 검사 가능 ex) useState, useMemo

      function App() {
        return (
          <ErrorBoundary fallback={'Error...'}>
            <Suspense fallback={'Loading...'}>
              <Child>
            </Suspense>
          </ErrorBoundary>
        )
      }

      컴포넌트 탭에서가면 우측상단에 디버그 아이콘이 최대 5개까지 확장되는 것을 보실 수 있습니다. 모르시고 넘어갈 수 있어서 각각 어떤 버튼인지 보겠습니다.


      위와 같은 코드가 있다고 가정했을 때 총 버튼이 5개가 생깁니다.


      image

      • 1️⃣ Error Toggle: Error 상태를 활성화하여 화면에 "Error..." 메시지를 표시합니다.

      • 2️⃣ Suspense Toggle: Suspense를 활성화하여 화면에 "Loading..." 메시지를 표시합니다.

      • 3️⃣ Jump to Elements: 선택한 컴포넌트를 개발자 도구의 Elements 탭으로 이동합니다.

      • 4️⃣ Log Component Info: 현재 컴포넌트의 Props, Hooks, Nodes를 console에 출력합니다.

      • 5️⃣ View Source Code: 소스맵을 통해 컴포넌트의 원본 코드로 바로 접근합니다.

      그리고 최근에는 서버컴포넌트도 지원이 된다고 합니다 ~ !

      server

      ⚛️ Profiler

      • 컴포넌트 렌더링 시간 측정 및 시각화

      • Flame Graph와 Ranked Chart를 통해 렌더링 비용 확인

      • Timeline을 통해 렌더링 이벤트와 CPU 사용량 분석

      • 각 렌더링 이벤트의 원인 확인 (props, state 변경 등)

      • 불필요한 리렌더링 감지 (컴포넌트의 과도한 재렌더링 파악)

      profiler


      간단하게 4개만 정리해보았습니다.

      1️⃣ FlameGraph

      2️⃣ Ranked

      flamGraph

      ranked

      컴포넌트가 렌더링에 걸린 시간을 시각적으로 표현하여, 어떤 컴포넌트가 가장 많은 렌더링 시간을 차지하는지 쉽게 확인할 수 있습니다. 컴포넌트를 클릭하면 오른쪽 패널에 해당 구성 요소의 props및 state이 커밋 시점의 정보가 표시됩니다.

      순위가 매겨진 차트 뷰는 단일 커밋을 나타냅니다. 차트의 각 막대는 React 구성 요소(예: App, Nav)를 나타냅니다. 차트는 렌더링하는 데 가장 오래 걸린 구성 요소가 맨 위에 오도록 정렬됩니다.

      3️⃣ Timeline

      4️⃣ Commit Page

      timeline

      commit page

      컴포넌트의 렌더링 이벤트와 그에 소요된 시간을 시간순으로 시각화하여 보여줍니다. 이를 통해 특정 시점에서 어떤 작업이 이루어졌는지, 또 어떤 컴포넌트가 성능 병목을 일으켰는지 파악할 수 있습니다.

      React는 렌더와 커밋 두 단계로 동작합니다. 커밋이 일어나 시점을 기준으로 각 막대는 하나의 커밋을 의미합니다.

      렌더 단계란 ?

      DOM에 필요한 변경 사항을 결정하고, render 호출 및 이전 렌더와 비교합니다.

      커밋 단계란 ?

      렌더 단계에서 결정된 변경 사항을 적용하며, 이 과정에서 componentDid Mount, componentDidUpdate 라이프사이클 메서드가 호출됩니다.

      Profiler Component ( 번외 )

      프로그래밍 방식으로도 React 트리의 렌더링 성능을 측정할 수 있습니다.

      import React, { Profiler } from 'react';
      
      function onRenderCallback(
        id, // Profiler의 "id" prop에 전달된 값
        phase, // "mount" (처음 렌더링) 또는 "update" (재렌더링)
        actualDuration, // 해당 업데이트에 소요된 렌더링 시간
        baseDuration, // 메모이제이션 없이 렌더링하는 데 걸리는 예상 시간
        startTime, // 렌더링이 시작된 시점
        commitTime, // 렌더링이 커밋된 시점
        interactions // 렌더링과 관련된 상호작용들
      ) {
        console.log({ id, phase, actualDuration, baseDuration, startTime, commitTime, interactions });
      }
      
      function MyComponent() {
        return (
          <Profiler id="test-app" onRender={onRenderCallback}>
            <div>프로파일링할 컴포넌트 내용</div>
          </Profiler>
        );
      }
      id: test-app, phase: update, actualDuration: 5.30ms, baseDuration: 8.00ms, startTime: 8482.50ms, commitTime: 8487.90ms

      느낀점

      막상 현업에서는 백오피스 업무를 많이 다루다보니, 최적화에 관련되서 공부할 기회가 없었습니다. 그렇게 지원해서 운좋게 합류하게 되었는데요.

      스터디를 통해 좋은 분들을 많이 알아가고, 본인들마다 맡으신 부분을 아무래도 다른 팀원들보다 조사도 많이하시고 준비하신걸 쏙-쏙 먹여주시니

      일반적인 북스터디보다 훨씬 유익하고 밀도가 있다고 생각했습니다.


      최적화 외 프론트엔드관련 토픽과 프로님들이 현업에서 어떻게 하셨는지 경험을 곁들여서 말씀해주시는게 너무 좋았던 것 같았습니다.

      책을 보면서 단편적으로 알게된 지식들도 많았지만 발표 준비 및 블로그를 작성하면서 많은 파생지식들을 얻게 되는 것 같아서 머리에 오래 남는 것 같아 좋았습니다.


      주변 지인한테 담 기수 넣어보라구 해야겠습니다 ! 읽어주셔서 감사합니다.

      댓글 0

      DEVOTEE를 활성화 시키면
      지금 작성한 댓글에 AI가 댓글을 달아줍니다.

      clcl6084 님의 최신 블로그

      더보기

      DEVOTEE 추천 블로그

      동영상 기고하기