Tech/ReactJS

Grid 아이템 이미지 로딩 후 리플로우 이슈 해결

닝닝깅 2024. 5. 6. 19:44

📌 문제상황

// 실제 코드는 부가적인 기능으로 코드가 복잡하여 최대한 간소화한 코드를 예시로 사용했다

<div className="grid grid-cols-3">
  {[1, 2, 3].map((_) => (
    <div>
      <img className="w-full aspect-square object-cover" />
      <p>이름</p>
      <p>가격</p>
    </div>
  ))}
</div>;

- Grid 배치로 크기를 자동으로 설정한 grid 아이템 이미지의 로딩 전후로 리플로우 발생 이슈 발견

- w-full 과 aspect-square로 높이와 너비 비율을 설정했다고 생각했기 때문에 리플로우 없이 로딩 될 것이라 생각했지만, 예상과는 다른 동작 결과를 보임

 

 

📌 원인 분석

=>  aspect ratio을 1:1로 세팅해둔 것이 높이를 설정한 것이라 생각한 게 문제

 

- 높이가 명시적으로 정해진 것이 아니기 때문에 브라우저는 이미지를 로드하기 전까지 높이를 정확하게 알 수 없음. 즉, 이미지 로드 후에만 높이를 조정할 수 있음

- 그래서 비율을 1:1로 잡아놨다고 하더라도 비율 계산을 할 수가 없게 됨 

 

 

📌 해결 방법 고민

방법1 ) 명시적 이미지 크기 설정

- grid minmax를 활용하여 min-width를 설정

- 이미지 크기를 명시적으로 나타내는 효과를 냄

= > 한계 : 리플로우가 적어지긴 했지만 여전히 발생하고, 이미지의 비율도 무너지게 됨

 

방법 2) 이미지 로드 전까지 스켈레톤 UI 사용

- 초기값이 true인 로딩 state를 만들고 로딩 완료된 후 값이 false로 되도록 이미지 onLoad 핸들러에 등록 

- 로딩값이 true인 동안 스켈레톤 UI 대체

=> 한계 : grid 아이템마다 state를 생성해야 하므로 렌더링 성능 저하 고려

 

방법 3) 별도의 이미지 컨테이너로 레이아웃 미리 설정

과정 : 이미지를 div태그로 감싸 이미지가 로드 되기 전 먼저 레이아웃 고정

=> ✅ 선택

 

 

📌 문제 해결

이미지가 로딩 되기 전까지 컨테이너가 미리 공간을 차지하고 있어서 리플로우가 더이상 발생하지 않는 것을 확인하였다.

<div className="grid grid-cols-3">
  {[1, 2, 3].map((_) => (
    <div>
      <div className="w-full aspect-square">
        <img className="w-full h-full object-cover" />
      </div>
      <p>이름</p>
      <p>가격</p>
    </div>
  ))}
</div>;