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

신고하기

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

미리보기

커뮤니티

      1,234

      badge 23.06.15

      글 등록

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

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

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

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

      임시저장함

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

      데보션 블로그 게재 요청

      CLOSE
      • *
      • *

      본인인증

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

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

      회원정보 연결

      OpenLab 2기 - 웹 프론트엔드 성능 최적화 : 4번째 스터디 (3장-2, 이미지 & 동영상 최적화)

      Teus 24.11.01
      184 4 0
      DEVOTEE 요약
      Teus는 웹 프론트엔드 성능 최적화를 위해 이미지를 JPG에서 WebP로 변환하고 Lazy Loading을 적용하여 이미지 로딩 시간을 개선하는 방법을 설명합니다. 또한, 동영상 파일의 크기를 줄이기 위해 MP4를 WebM으로 포맷 변환하고 FFMpeg를 사용하여 동영상의 비트레이트와 해상도를 조정하는 방식을 소개합니다. 이러한 방법을 통해 웹사이트의 이미지와 동영상 파일의 최적화를 달성할 수 있습니다.
      DEVOTEE 추천 블로그

      안녕하세요. Teus입니다.


      저는 이번에 FrontEnd 웹 성능 최적화 수업의 스터디원으로 참여 중 입니다.

      이번에 3장의 웹사이트 최적화, 이미지&동영상 최적화 부분을 다뤄 보겠습니다.


      0. 개발환경 구축

      소스코드주소

      소스코드의 경우 node의 옛버전으로 되어 있습니다.


      때문에 node 14버전을 wsl ubuntu 상에 별도로 설치하고, wsl ubuntu상에서 서버를 실행 시켰습니다.

      image.png


      1. 문제점 1. 이미지

      페이지에 들어가면, 페이지 중 중간에 3개의 이미지가 위치합니다.

      image.png

      해당 이미지는 실제 화면에서는 300x300 의 사이즈의 작은 이미지 입니다.

      image.png

      하지만, 실제 서버에서는 3840x3840의 사이즈로, 너무 거대한 이미지가 http를 통해서 넘어오고 있었습니다.

      image.png

      이때 HTTP msg에 이미지를 binary형태로 담아서 보내게 됩니다.

      image.png


      2. 문제점 1 해결방안

      웹페이지의 이미지 전송 최적화를 위해서

      1. 이미지의 해상도를 낮춘다

      2. 이미지의 포맷을 바꿔서 물리적인 파일 크기를 줄인다.

      이때 원본 이미지의 해상도를 낮추면, 당연하게 이미지 파일의 물리적인 용량은 줄어듭니다.

      이미지 포맷을 바꾸는 경우, 파일의 화질을 일부 손해보더라도, 비슷한 느낌으로 파일의 용량을 줄이는 방법이 됩니다.

      대표적인 포맷으로 PNG, JPS, WebP가 있습니다.

      기준

      서열

      사이즈

      PNG>JPG>WebP

      화질

      PNG>WebP>JPG

      호환성

      PNG>KPS>WebP

      WebP가 적당한 중도를 달리며, 적절한 이미지 포맷인것 같지만

      하나의 약점이 바로 호환성 입니다.

      https://caniuse.com/

      확인 결과 다행히 최신 브라우저에서는 모두 지원을 해 줍니다.

      image.png

      이제 WebP가 좋은것은 알았으니, 기존 JPG Image를 WebP로 변환해 보겠습니다.


      3. 문제점 1 해결하기

      그래서 우리는

      1. 이미지를 jpg -> WebM 변환하기

      2. lazy loading 적용하기

      순서로 개선을 진행해 보겠습니다.

      1. 이미지 jpg -> WebM변환하기

      책에서는 기본적으로 아래 사이트를 이용해서, GUI기반으로 이미지를 변환할 수 있다고 알려줍니다.

      https://squoosh.app/

      하지만 영원한건 없듯, 해당 사이트가 언제 사리지는 것 일지 모르는 일일터

      그래서, ChatGPT의 도움을 받아서, NodeJS를 가지고 이미지를 변환하는 방법을 찾아 보았습니다.

      image.png

      const sharp = require("sharp");
      
      async function convert(inputPath, outputPath, width, height) {
          try{
              await sharp(inputPath)
              .resize(width, height)
              .toFormat("webp")
              .toFile(outputPath)
          } catch (error) {
              console.log(error)
          }
      }
      
      const input_path = "main-items.jpg"
      const out_path = "main-items.webp"
      convert(input_path, out_path, 600, 600)

      그러면 아래와 같이 webp로 변환된 파일을 확인할 수가 있습니다. 그리고, 상당히 용량이 줄었습니다.

      image.png

      2. 이미지 LazyLoading & Web호환성 챙겨가기

      webP의 경우 위에서 말했듯, 브라우저 마다 호환성 문제가 발생할 수 있습니다.

      그래서, webP를 사용할 때는 <img> 태그가 아니라 <picture> 태그를 사용하게 됩니다.

      <picture>태그는 태그 내에 <img>, <source> 태그를 배치시키고, 브라우저가 현 상황에서 가장 적합한 source를 골라서 랜더링하게 맡겨줍니다.

      대신, 브라우저가 <source>중에 가능한 선택지가 없을 경우, 맨 하단에 있는 <img> 태그를 사용하게 됩니다.

      <img src={props.image}/>
      🔽 🔽 🔽 🔽 🔽 🔽 🔽 🔽 🔽 🔽 🔽 🔽 🔽 🔽 🔽 🔽 🔽
      <picture>
          <source data-srcset = {props.webp} type = "image/webp"/>
          <img data-src = {props.image} ref = {imgRef} />
      </picture>

      그리고 여기서 src와 srcset을 바로 집어넣지 않고, data-srcset에 집어넣는 것을 확인할 수 있는데

      해당 태그들은 src, srcset property에 실제 값이 들어오면 Image를 loading하기 시작합니다.

      이때 이미지 source를 지정할 때 src와 srcset을 사용할 수가 있습니다. src와 srcset의 차이점은, srcset같은 경우 사용자 화면의 dpi, 스크롤 등에 따른 조건부 랜더링을 통해서 사용자 환경에 맞는 이미지를 제공할 수가 있습니다.

      실제 <img> tag에 data-src로 property를 줄경우, src가 아니라 별도의 데이터로 빠져서 저장되는것을 확인할 수 있습니다.

      image.png

      그 다음 Intersection Observer의 callback에 datset-src => src로 치환을 진행시켜서

      해당 이미지에 사용자가 가까워지면, 해당 시점이 Loading을 시작하게 만듭니다.

      function Card(props) {
          useEffect(()=>{
              ...
              const target = entry.target
              const previousSibling = target.previousSibling
              target.src = target.dataset.src
              previousSibling.srcset = previousSibling.dataset.srcset
          }, [])
      ...
      }

      이렇게 처리해 줄 경우

      1. 이미지 로딩의 절대적인 시간이 빨라진다.

      2. 이미지 로딩이 필요한 시점에만 진행된다

      를 통해서 웹페이지의 이미지 서빙을 최적화할 수 있습니다.


      4. 문제점 2. 동영상

      해당 예제에서 이미지는 최적화 되었지만

      페이지 최 상단에 배경화면에서 동영상 컨텐츠가 재생되고 있습니다.

      image.png

      동영상의 경우 React 자체적으로 chunking을 진행한 뒤 초기 부분을 전달하고, 나머지 부분을 전달합니다.

      image.png

      하지만 원본 동영상의 크기가 너무 커서, chunking이 된 상태에서도 긴 시간이 소요되는것을 확인 할 수 있습니다.


      4. 문제점 2 해결하기

      이미지 때와 마찬가지로 동영상도 Format변경 및 bitrate를 수정 할겁니다.

      기본 동영상은 MP4로 되어 있지만, MP4 -> webm 포맷 변경을 통해서 용량이 감소된 상태로 만들 수 있습니다.

      (당연히, MP4대비 webm이 호환성은 안좋습니다)

      이때 두개이상의 동영상 소스를 사용해서 호환성을 챙길 때

      <picture>와 유사하게 <video>를 사용합니다.

      <video>
          <source src = {video_webm} type = "video/webm"/>
          <source src = {video} type = "video/mp4"/>
      </video>

      동영상 역시 GUI기반으로 이미지를 변환할 수 있다고 알려줍니다.

      https://www.media.io/video-converter.html

      하지만 영원한건 없습니다.

      이번는 ubuntu의 ffmpeg을 활용해서 동영상을 변환하는 코드를 확인할 수 있습니다.(w/ ChatGPT)

      (윈도우 같은경우는 별도로 ffmpeg를 깔아야 합니다)

      sudo apt-get install ffmpeg

      그리고, 동영상이 있는 폴더로 이동하여 아래 명령어를 실행시켜 줍니다.

      cd 동영상이있는-folder
      ffmpeg -i input.mp4 -c:v libvpx -crf 10 -b:v 1000k output.webm
      General Options
      -i input.mp4: specifies the input file
      -c:v libvpx: specifies the video codec to use (in this case, VP8)
      -c:a libvorbis: specifies the audio codec to use (in this case, Vorbis)
      -f output.webm: specifies the output file format (in this case, WebM)
      
      Video Options
      -crf 10: sets the quality of the video encoding (lower values result in higher quality, but larger files)
      -b:v 500k: sets the video bitrate (in this case, 500 kbps)
      -s 640x480: sets the resolution of the output video (in this case, 640x480)
      -aspect:v 16:9: sets the aspect ratio of the output video (in this case, 16:9)

      이렇게 실행시켜 주면

      아래처럼 인코딩 후 변환되어 작은 용량을 차지하는 파일을 확인할 수 있습니다.

      image.png

      댓글 0

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

      Teus 님의 최신 블로그

      더보기

      DEVOTEE 추천 블로그

      동영상 기고하기