게시글 작성 페이지_기능_이미지 업로드하기
사용자가 로컬 시스템에서 이미지를 선택하고 업로드 전에 미리 볼 수 있는 이미지 업로더를 만들게 되었다.
목표 |
FileReader로 이미지 미리보기 생성하기 |
이미지 입력을 사용자 친화적으로 만들기 |
useState Hook로 이미지 상태 관리하기 |
const [imgPath, setImgPath] = useState(null);
useState Hook를 통해 업로드된 이미지의 상태를 관리한다. 브라우저에서 이미지를 바로 렌더링해 미리보기하는 기능을 어떻게 구현할지 고민했는데, 비슷한 기능을 구현한 사례에서 FileReader를 사용해 base64 형식으로 변환하는 방법을 알게 되었다.
◆ FileReader API
FileReader는 자바스크립트에서 제공하는 API로, 선택한 이미지, 텍스트 파일 등을 읽어서 처리할 수 있게 한다. 브라우저에서 파일을 읽는 기능이 있어 업로드하고 싶은 파일을 클라이언트 측에서 미리보기 하는 방식에 유용하게 쓸 수 있다. FileReader의 주요 메서드를 살펴보자.
- readeAsDataURL(file) : 파일을 base64 형식의 데이터 URL로 읽어오고, 이를 통해 이미지 파일을 읽어서 바로 <img> 태그에 넣어주면 미리보기 기능을 구현할 수 있다.
- readAsText(file) : 파일을 텍스트로 읽어서 처리할 때 사용한다.
- readAsArrayBuffer(file) : 파일을 ArrayBuffer 형식으로 읽는다.
사용자가 파일을 선택하면 FileReader 객체를 생성하고, 파일을 읽는 메서드를 호출한다. onloadend 이벤트 핸들러를 통해 파일을 처리하는 데이터를 제공하고, 이미지 파일 미리보기 등에 사용할 수 있다.
const ImageUploader = ({ onImageChange }) => {
const [imgPath, setImgPath] = useState(null);
const previewImage = (e) => {
const file = e.target.files[0];
if (file) {
const reader = new FileReader();
reader.onloadend = () => {
setImgPath(reader.result);
};
reader.readAsDataURL(file);
onImageChange(file);
}
};
이미지가 선택되지 않았을 때 Placeholder로 '이미지 업로드'가 보이도록 만들었다.
<label> 태그로 input 창을 커스텀할 수 있는데, label htmlFor와 연동할 input의 id를 일치시키면 된다.
return (
<>
<LabelImage htmlFor="photo">
{imgPath ? <Photo src={imgPath} alt="이미지 업로드" /> : <Placeholder>이미지 업로드</Placeholder>}
</LabelImage>
<input type="file" id="photo" accept=".png, .jpeg, .jpg" onChange={previewImage} style={{ display: 'none' }} />
</>
);
LabelImage 컴포넌트는 클릭 시 파일 입력을 트리거함으로써 기본으로 제공되는 파일 입력 기능보다 사용자 경험 면에서 더 나은 방향이 될 수 있다. 서버에 이미지를 업로드하기 위해 부모 컴포넌트가 이미지 파일에 접근할 수 있도록 onImageChange prop을 컴포넌트에 추가했다.
ImageUploader 컴포넌트로 분리해서 이 기능을 관리했는데, 상태 관리와 파일 처리를 깔끔하고 사용자 친화적으로 개선하는 방법에 대해 배울 수 있었다.
'스파르타코딩클럽 > 과제' 카테고리의 다른 글
[Next.js + TypeScript] 리그 오브 레전드 정보 도감 만들기 (0) | 2024.12.11 |
---|---|
[React 아웃소싱 프로젝트] 지도에 커스텀 오버레이 생성하기 (1) | 2024.12.02 |
[뉴스피드 프로젝트] 1일차 - 기획 단계 (1) | 2024.11.15 |
[React 숙련] 1주차_React Router Dom (1) | 2024.11.08 |
[React 개인과제_입문 주차] (기록용) (0) | 2024.11.01 |