[JS] 이미지 업로드 기능 구현시 주의할 것

게코젤리·2023년 3월 24일
0
post-custom-banner
const [attachment, setAttachment] = useState<string>('');
// input 파일 업로드
const onFileChange = (event: React.ChangeEvent<HTMLInputElement>) => {
    const fileList = event.target.files;
    if (!fileList?.[0]) {
      setAttachment('');
      return;
    }
    const file = fileList[0];
    const reader = new FileReader();
    reader.onloadend = () => {
      const result = reader.result;
      setAttachment(result as string);
    };
    reader.readAsDataURL(file);
  };
// storage와 firestore에 업로드
useEffect(() => {
    if (!attachment) {
      return;
    }

    const user = auth.currentUser;
    if (user) {
      const fileRef = ref(
        storageService,
        `user/userPhoto/${user.uid}/${uuidv4()}`
      );
      uploadString(fileRef, attachment, 'data_url')
        .then(async (response) => {
          const url = await getDownloadURL(response.ref);
          const userRef = doc(db, 'users', user.uid);
          await updateDoc(userRef, { userPhoto: url });
        })
        .catch((error) => {
          console.error(error);
        });
    }
  }, [attachment]);
// 이미지 삭제
const deleteUserPhoto = async () => {
    const user = auth.currentUser;
    if (user) {
      const userRef = doc(db, 'users', user.uid);
      const userData = await getDoc(userRef);
      // Storage 삭제
      if (userData.data()?.userPhoto) {
        const photoRef = ref(storageService, userData.data()?.userPhoto);
        await deleteObject(photoRef);
      }
      // Firestore의 userPhoto url 삭제
      await updateDoc(userRef, { userPhoto: '' });
      setAttachment('');
    }
  };

return (
	//...
  <AddPhoto>
    <Btn as="label" htmlFor="attach-file">
      이미지 업로드
      {/* <Btn>이미지 업로드</Btn> */}
    </Btn>
    <input
      id="attach-file"
      type="file"
      accept="image/*"
      onChange={onFileChange}
      ref={fileInput}
      />
  </AddPhoto>
  <Btn onClick={deleteUserPhoto}>이미지 삭제</Btn>
)

위 코드에서 내가 기대한 동작은 다음과 같다.
1. onFileChange에서 image.png의 url을 attachment에 저장함
2. attachment가 바뀌었으므로 userEffect가 실행되어 storage에 업로드
3. deleteUserPhoto에서 attachment을 ''으로 바꿈
4. onFileChange에서 image.png의 url을 attachment에 저장함
5. attachment가 바뀌었으므로 userEffect가 실행되어 storage에 업로드

그런데 5번이 되지 않았다. 얼핏 생각하기에 2번과 동일한 상황이므로 똑같이 이미지가 업로드 되어야 한다.

문제는 input이었다. 처음 input에서 image.png를 불러오면 해당 값이 저장된다. 그리고 다시 같은 image.png를 불러오려고 해도 onChange 이벤트가 발생하지 않는다. 이러한 동작은 브라우저 최적화의 일환으로, 사용자가 실수로 동일한 파일을 선택했을 때 불필요한 이벤트 발생을 방지하기 위한 것. 따라서 onFileChange 함수에서event.target.value = ''를 추가하면 간단히 해결할 수 있다.

post-custom-banner

0개의 댓글