프론트엔드/성능 최적화

로딩 성능 최적화 - 프리 로딩

정현우12 2023. 4. 28. 17:55

컴포넌트 Preloading

Lazy Loading의 단점

예를 들어 이미지 모달을 레이지 로딩하도록 변경하면,

모달 보기 버튼 클릭시에 모달 관련 코드를 불러온다.

따라서 불러오는데 시간이 좀 걸리게 된다.

이 클릭 전에 미리 알고 로드해놓으면 사용자 입장에서 끊김 없이 느껴질 것이다. (레이지 로딩의 단점을 개선)

컴포넌트 Preload 타이밍

  1. 버튼 위에 마우스를 올려놨을 때
  2. 최초 페이지 로드 후 모든 컴포넌트 마운트 끝났을 때

최적화하기

1. 버튼 위에 마우스를 올려놨을 때

const handleMouseEnter = () => {
    const component = import('./components/ImageModal')
 }

<ButtonModal onClick={() => { setShowModal(true) }} onMouseEnter={handleMouseEnter}>올림픽 사진 보기</ButtonModal>

mouseEnter를 활용해 사용자가 버튼 위에 마우스를 올리면 해당 컴포넌트를 미리 로드하도록 한다.

버튼 위에 마우스를 올리고 클릭하기까지 약 0.1~0.2초의 갭이 있기 때문에 클릭전 미리 컴포넌트가 로드되고, 사용자는 끊김 없이 이미지 모달을 볼 수 있다.

2. 최초 페이지 로드 후 모든 컴포넌트 마운트 끝났을 때

만약 컴포넌트 코드 크기가 커서 1초 이상의 오랜 시간이 걸린다면 이 방법을 사용하는 것이 좋다.

useEffect(() => {
    const component = import('./components/ImageModal') 
}, [])

useEffect에 deps로 빈 배열을 줘서 최초 페이지 로드 후 컴포넌트가 마운트 끝났을 때 컴포넌트를 로드하도록 한다.

최적화 코드 리팩토링 하기

여러 컴포넌트를 프리로드 해야 하는 경우 매번 import 직접 쓰기는 번거롭고 가독성도 안 좋다.

팩토리 패턴을 사용해서 함수를 구현해서 쓴다.

function lazyWithPreload(importFunction) {
    const Component = React.lazy(importFunction)
    Component.preload = importFunction
    return Component
}

const ImageModal = lazyWithPreload(() => import('./components/ImageModal'))

useEffect(() => {
    ImageModal.preload()
}, [])

가독성도 좋고 쓰기도 편하다.

이미지 Preloading

이미지의 경우 불러오는 데 시간이 오래 걸려서 화면 상의 레이아웃이 찌그러지는 경우가 많이 생긴다.

컴포넌트처럼 이미지도 미리 불러놓으면 레이아웃이 찌그러지는 문제를 해결할 수 있다.

최적화하기

useEffect(() => {
    const img = new Image()
    img.src='[이미지 주소]'
}, [])

Image 객체 생성하고 src를 주면 그 시점에 이미지를 불러온다. 이를 활용해서 특정 시점에 이미지를 먼저 불러오도록 할 수 있다.

결과

불러온 이미지는 캐시되어서 (GET 요청은 기본적으로 캐시) 다음 번에 이미지 필요할 때 빠르게 불러와서 레이아웃이 찌그러지지 않는다.

커다란 이미지 같은 경우만 캐시하는 식으로 잘 선택할 필요가 있다. 많은 이미지를 프리로드할 경우 성능상에 문제가 생길 수 있다. 성능과 레이아웃 찌그러짐을 잘 고려해서 결정해야 한다.