상품 등록을 위해 상품 이미지를 업로드 해야하는 경우 어떻게 업로드하고 미리볼 수 있는지 알아보고자 합니다.
// 전체 코드 중에서 이미지 업로드에 관련된 코드만 가져왔습니다.
export default function ProductAdd() {
const [product, setProduct] = useState({
...
image: "",
...
});
const inputImgRef = useRef(null);
const handleImgChange = () => {
const file = inputImgRef.current.files[0];
if (!file) {
return;
}
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onloadend = () => {
setProduct({ ...product, image: reader.result });
};
};
const onClickInput = () => {
inputImgRef.current.click();
};
return (
<ProductImg>
<label htmlFor="image">상품 이미지</label>
<ProductImgInputContainer>
<input
type="file"
id="image"
name="image"
accept=".jpg,.jpeg,.png,.gif"
ref={inputImgRef}
onChange={handleImgChange}
/>
<ProductImgInputBtn type="button" onClick={onClickInput}>
<img src={imgUploadBtn} alt="이미지 추가하기" />
</ProductImgInputBtn>
{product.image && (
<ProductImgPreview
src={product.image}
alt="상품 미리보기"
onClick={onClickInput}
/>
)}
</ProductImgInputContainer>
</ProductImg>
);
}
<ProductImgInputBtn type="button" onClick={onClickInput}>
<img src={imgUploadBtn} alt="이미지 추가하기" />
</ProductImgInputBtn>
그래서 위의 코드를 추가해서 원하는 이미지 파일을 이용해 이미지를 추가할 수 있는 버튼을 만들었습니다.
(+)input에 display: none을 추가하여 기존의 파일 선택 버튼이 보이지 않도록 해줌.
input의 accept 속성
을 통해 파일의 종류를 제한할 수 있습니다.
.jpg, .jpeg, .png, .gif
image/jpg, image/jpeg, image/png
와 같이 파일의 종류와 서브타입을 지정할 수 있습니다.onClickInput
ProductImgPreview과 ProductImgInputBtn의 onClick 이벤트로 onClickInput 함수가 실행되는데, 이 함수는 inputImgRef를 통해 파일 입력 요소에 대한 참조를 얻어옵니다. 이미지 업로드 버튼이나 사용자가 이미지 미리보기 영역(이미지가 업로드되어 미리보기가 된 경우에도 이미지를 수정할 수 있도록 추가해주었음)을 클릭할 경우, inputImgRef.current.click()을 호출하여 파일 입력 요소의 클릭 이벤트를 강제로 발생시키는 역할을 합니다.
handleImgChange
const handleImgChange = () => {
const file = inputImgRef.current.files[0]; // 파일 입력 요소에서 사용자가 선택한 파일 객체를 가져옵니다.
if (!file) { // 파일 객체가 없는 경우 함수 종료(예: 사용자가 취소 버튼을 누른 경우)
return;
}
const reader = new FileReader(); // 파일 객체가 존재하면, FileReader 객체를 생성하여 선택한 이미지 파일을 읽습니다.
reader.readAsDataURL(file); // 파일을 데이터 URL 형식으로 읽어옵니다. 이렇게 하면 이미지 파일을 Base64 형식의 문자열로 인코딩할 수 있습니다.
reader.onloadend = () => {
setProduct({ ...product, image: reader.result }); // setProduct 함수를 호출하여 이미지 프리뷰에 표시할 이미지 데이터를 업데이트해주는 작업을 수행합니다.
};
};
if(!file) { return; }
{product.image && (
<ProductImgPreview
src={product.image}
alt="상품 미리보기"
onClick={onClickInput}
/>
)}
{product.image && (...)}
는 product 객체가 이미지 데이터를 가지고 있을 경우에만 미리보기 이미지가 나타나도록 하는 조건문입니다.