23.06.15
DEVOTEE를 활성화 시키면
지금 작성한 커뮤니티 글에 대해 1개의 댓글을 달아줍니다.
버튼을 누르면 글 수정 시 ChatGPT가 작성한 댓글이 수정됩니다.
| 컨텐츠 유형 | 제목 | 저장일 | 삭제 |
|---|
본인인증 로그인에 실패하였습니다.
회원이 아니시거나 본인인증 등록이
완료되지 않은 사용자입니다.
안녕하세요. Teus입니다.
저는 이번에 FrontEnd 웹 성능 최적화 수업의 스터디원으로 참여 중 입니다.
이번에 3장의 웹사이트 최적화, 이미지&동영상 최적화 부분을 다뤄 보겠습니다.
소스코드의 경우 node의 옛버전으로 되어 있습니다.
때문에 node 14버전을 wsl ubuntu 상에 별도로 설치하고, wsl ubuntu상에서 서버를 실행 시켰습니다.
페이지에 들어가면, 페이지 중 중간에 3개의 이미지가 위치합니다.
해당 이미지는 실제 화면에서는 300x300 의 사이즈의 작은 이미지 입니다.
하지만, 실제 서버에서는 3840x3840의 사이즈로, 너무 거대한 이미지가 http를 통해서 넘어오고 있었습니다.
이때 HTTP msg에 이미지를 binary형태로 담아서 보내게 됩니다.
웹페이지의 이미지 전송 최적화를 위해서
이미지의 해상도를 낮춘다
이미지의 포맷을 바꿔서 물리적인 파일 크기를 줄인다.
이때 원본 이미지의 해상도를 낮추면, 당연하게 이미지 파일의 물리적인 용량은 줄어듭니다.
이미지 포맷을 바꾸는 경우, 파일의 화질을 일부 손해보더라도, 비슷한 느낌으로 파일의 용량을 줄이는 방법이 됩니다.
대표적인 포맷으로 PNG, JPS, WebP가 있습니다.
기준 | 서열 |
|---|---|
사이즈 | PNG>JPG>WebP |
화질 | PNG>WebP>JPG |
호환성 | PNG>KPS>WebP |
WebP가 적당한 중도를 달리며, 적절한 이미지 포맷인것 같지만
하나의 약점이 바로 호환성 입니다.
확인 결과 다행히 최신 브라우저에서는 모두 지원을 해 줍니다.
이제 WebP가 좋은것은 알았으니, 기존 JPG Image를 WebP로 변환해 보겠습니다.
그래서 우리는
이미지를 jpg -> WebM 변환하기
lazy loading 적용하기
순서로 개선을 진행해 보겠습니다.
책에서는 기본적으로 아래 사이트를 이용해서, GUI기반으로 이미지를 변환할 수 있다고 알려줍니다.
하지만 영원한건 없듯, 해당 사이트가 언제 사리지는 것 일지 모르는 일일터
그래서, ChatGPT의 도움을 받아서, NodeJS를 가지고 이미지를 변환하는 방법을 찾아 보았습니다.
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로 변환된 파일을 확인할 수가 있습니다. 그리고, 상당히 용량이 줄었습니다.
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가 아니라 별도의 데이터로 빠져서 저장되는것을 확인할 수 있습니다.
그 다음 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
}, [])
...
}이렇게 처리해 줄 경우
이미지 로딩의 절대적인 시간이 빨라진다.
이미지 로딩이 필요한 시점에만 진행된다
를 통해서 웹페이지의 이미지 서빙을 최적화할 수 있습니다.
해당 예제에서 이미지는 최적화 되었지만
페이지 최 상단에 배경화면에서 동영상 컨텐츠가 재생되고 있습니다.
동영상의 경우 React 자체적으로 chunking을 진행한 뒤 초기 부분을 전달하고, 나머지 부분을 전달합니다.
하지만 원본 동영상의 크기가 너무 커서, chunking이 된 상태에서도 긴 시간이 소요되는것을 확인 할 수 있습니다.
이미지 때와 마찬가지로 동영상도 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.webmGeneral 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)이렇게 실행시켜 주면
아래처럼 인코딩 후 변환되어 작은 용량을 차지하는 파일을 확인할 수 있습니다.
DEVOTEE를 활성화 시키면
지금 작성한 댓글에 AI가 댓글을 달아줍니다.