const ImageWrap = styled.div`
width: 100%;
padding-bottom: 56.25%; // 16:9 비율
position: relative;
`;
const Image = styled.img`
cursor: pointer;
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
`;
aspect-ratio 사용.wrapper {
width: 100%;
aspect-ratio: 16 / 9;
}
.image {
width: 100%;
height: 100%;
}
단,
aspect-ratio는 일부 구형 브라우저에서 호환성 문제가 있을 수 있음
react-lazyload 라이브러리를 사용하여 이미지가 화면에 진입할 때 로드import LazyLoad from "react-lazyload";
<LazyLoad offset={1000}>
<img src={imageUrl} alt="이미지" />
</LazyLoad>
| 항목 | LazyLoad | Intersection Observer |
|---|---|---|
| 브라우저 호환성 | 좋음 | 최신 브라우저 중심 |
| 사용성 | 다양한 콘텐츠 타입 지원 (이미지, 비디오 등) | 네이티브 지원, 유연한 설정 가능 |
| 단점 | 의존성 추가 | 구형 브라우저 미지원 가능성 |
상황에 따라 적절한 도구를 선택할 것
useSelector로 가져오는 값이 "객체"나 "배열"일 경우, 참조값이 바뀌면 항상 리렌더링 발생const { photos, loading } = useSelector((state) => ({
photos: state.photos.data,
loading: state.photos.loading,
}));
→ 이 경우 매 렌더링마다 새로운 객체를 생성하기 때문에 === 비교가 false
useSelector로 가져오기const modalVisible = useSelector(state => state.modal.visible);
const bgColor = useSelector(state => state.modal.bgColor);
shallowEqual 사용import { useSelector, shallowEqual } from 'react-redux';
const { modalVisible, bgColor } = useSelector(
state => ({
modalVisible: state.modal.visible,
bgColor: state.modal.bgColor,
}),
shallowEqual
);
const { photos } = useSelector((state) => ({
photos: state.photos.data.filter(photo => photo.category === category),
}));
const { category, allPhotos } = useSelector(state => ({
category: state.category,
allPhotos: state.photos.data,
}));
const photos = category === "all"
? allPhotos
: allPhotos.filter(photo => photo.category === category);
getAverageColorOfImage)가 너무 느림const averageColorCache = {};
export const getAverageColorOfImage = (imgUrl) => {
if (averageColorCache[imgUrl]) {
return averageColorCache[imgUrl];
}
const averageColor = calculateAverageColor(imgUrl); // 고비용 연산
averageColorCache[imgUrl] = averageColor;
return averageColor;
};
동일한 인풋에 대해 반복 연산을 피하고 캐시된 결과를 재사용
메모리 사용량이 증가할 수 있으므로 반복 호출이 예상되는 고비용 함수에만 적용