이미지 갤러리에서 사진을 넘길 때 줌 상태가 유지되면 사용자 경험에 혼란을 줄 수 있습니다. 이전 이미지에서 확대한 상태로 다음 이미지로 넘어가면, 새 이미지의 동일한 부분(위치)이 확대되어 보이게 되는데, 이는 사용자가 원하는 결과가 아닐 수 있습니다. 이 글에서는 React에서 react-zoom-pan-pinch
라이브러리를 사용하여 이미지 전환 시 줌 상태를 효과적으로 초기화하는 방법을 소개합니다.
문제 상황
이미지 갤러리에서 다음과 같은 문제가 발생할 수 있습니다:
- 사용자가 이미지를 확대한 상태에서 다음 이미지로 넘어갈 때 줌 레벨이 유지됨
- 이미지 전환 시 확대된 상태로 인해 새로운 이미지의 중요한 부분이 보이지 않을 수 있음
- 일관된 사용자 경험을 위해 각 이미지는 처음 보여질 때 항상 전체 이미지가 보이는 상태여야 함
실패한 해결 방법 : key 속성을 활용한 줌 상태 초기화
초기화가 이루어 지나 컴포넌트가 다시 생성되며 마운트 되기 때문에 사진 전환시에 딜레이가 생겨 중간중간 빈 화면이 보이는 문제가 발생했습니다. 이는 사용자에게 불편을 줄 수 있어 다른 방법을 사용하기로 결정했습니다.
해결 방법: useRef와 useEffect를 활용한 줌 상태 초기화
react-zoom-pan-pinch
라이브러리를 사용할 때, 이미지가 변경될 때마다 줌 상태를 초기화하는 가장 효과적인 방법은 다음과 같습니다:
import { memo, useEffect, useRef } from "react";
import { ReactZoomPanPinchRef, TransformWrapper } from "react-zoom-pan-pinch";
import { ImageData } from "../../api/imageApi";
import ZoomControls from "./ZoomControls";
import ImageRenderer from "./ImageRenderer ";
interface TransformViwerProps {
currentImageSrcMetadata?: ImageData;
isLoaded: boolean;
}
const TransformViwer = ({
currentImageSrcMetadata = {
id: 0,
src: "",
alt: "",
},
}: TransformViwerProps) => {
// TransformWrapper의 메서드에 접근하기 위한 ref 생성
const transformRef = useRef<ReactZoomPanPinchRef | null>(null);
// 이미지 ID가 변경될 때마다 줌 상태 초기화
useEffect(() => {
if (transformRef.current && transformRef.current.resetTransform) {
// 애니메이션 없이 빠르게 리셋
transformRef.current.resetTransform(0);
}
}, [currentImageSrcMetadata.id]); // 이미지 ID가 변경될 때만 실행
return (
<TransformWrapper
initialScale={1}
initialPositionX={0}
initialPositionY={0}
disablePadding={true}
onInit={(ref) => {
// 컴포넌트 초기화 시 ref 저장
transformRef.current = ref;
}}
>
{({ zoomIn, zoomOut, resetTransform }) => (
<div className="absolute inset-0 w-full h-full">
<ZoomControls
zoomIn={zoomIn}
zoomOut={zoomOut}
resetTransform={resetTransform}
/>
<ImageRenderer imageMetadata={currentImageSrcMetadata} />
</div>
)}
</TransformWrapper>
);
};
// 메모이제이션으로 불필요한 리렌더링 방지
export default memo(TransformViwer);
구현 방법 상세 설명
1. useRef로 TransformWrapper 인스턴스 참조하기
const transformRef = useRef<ReactZoomPanPinchRef | null>(null);
useRef
훅을 사용하여 TransformWrapper
컴포넌트의 메서드에 접근할 수 있는 참조를 생성합니다. 이 참조를 통해 줌 상태를 제어할 수 있습니다.
2. onInit 콜백으로 참조 저장하기
onInit={(ref) => {
transformRef.current = ref;
}}
TransformWrapper
의 onInit
콜백은 컴포넌트가 마운트될 때 호출됩니다. 이 시점에 제공되는 ref
객체를 통해 zoomIn
, zoomOut
, resetTransform
등의 메서드에 접근할 수 있습니다. 우리는 이 ref
를 transformRef.current
에 저장합니다.
3. useEffect로 이미지 변경 감지 및 줌 상태 초기화
useEffect(() => {
if (transformRef.current && transformRef.current.resetTransform) {
// 애니메이션 없이 빠르게 리셋
transformRef.current.resetTransform(0);
}
}, [currentImageSrcMetadata.id]);
useEffect
훅을 사용하여 currentImageSrcMetadata.id
가 변경될 때마다 줌 상태를 초기화합니다. 파라미터 0
은 애니메이션 지속 시간(밀리초)으로, 0
으로 설정하면 즉시 초기화됩니다. 이는 이미지 전환 시 깜빡임을 최소화하기 위한 설정입니다.
4. memo로 불필요한 리렌더링 방지
export default memo(TransformViwer);
memo
를 사용하여 컴포넌트를 메모이제이션함으로써 props가 변경되지 않았을 때 불필요한 리렌더링을 방지합니다. 이는 성능 최적화에 중요합니다
결론
react-zoom-pan-pinch
라이브러리의 공식 홈페이지를 들어가 탐색하며 원하는 기능을 구현할 수 있었습니다.
깜빡임도 없고 사진 전환시에 전체 모습을 볼 수 있게 하여 사용자의 편의성을 증진시켰습니다.
'개발 > 기록' 카테고리의 다른 글
React JSX에서의 0 처리 특징 (0) | 2025.03.26 |
---|---|
zoom & swipe image Viewer: zoom, reset 에러 해결 (0) | 2025.03.25 |
제네릭 타입 선언시 nerver와 void의 차이 (0) | 2025.03.01 |
유용한 css (0) | 2025.02.24 |
nextjs 쿠키 설정 의문 (0) | 2025.02.24 |