[React.js] 이미지 업로드 버그

hyejinJo·2023년 3월 24일
0

React

목록 보기
3/9
post-thumbnail

제로초의 NodeBird 강의 프로젝트를 직접 리뉴얼 하는중에 이미지 업로드와 관련된 버그를 발견했다.
(게시물 작성 중 이미지를 업로드하는 기능은 type 이 file 인 input 에 onChange 이벤트를 걸고 업로드 리듀서가 디스패치되는 구조)

게시물을 작성하기 위해 “react” 라는 이미지를 올렸다가, 해당 이미지를 제거하고 다시 그 이미지를 불러오려 할 때 불러오지 않는다. 이때 “vue” 라는 새로운 이미지를 불렀다가 제거 후 다시 “react” 이미지를 부르니 잘 불러졌다.

또 이미지가 업로드된 상태에서 이미지업로드 버튼을 눌렀다가 “취소” 를 누르면 기존에 업로드된 이미지가 사라져버린다.

버그를 요약하면 다음과 같이 두 가지이다.

  1. 바로 직전에 제거한 이미지를 다시 불러오려 할 때 불러오지 않음

  2. “취소” 버튼을 누르면 기존에 불렀던 이미지가 사라짐. (이미지들의 경로를 모아놓은 배열인 imagePaths 에서 해당 이미지 경로가 사라짐)

모든 시도를 해보았지만 해결이 되지않아 해당 강의를 다시 찾았고, 마침 나의 1번 오류 상황과 같은 질문, 그리고 그에 대한 답변도 발견했다.

답변

“onChange가 호출되지 않네요. 파일이 기존 파일이랑 달라지지 않아서 onChange가 실행이 안 됩니다. 이 때는 input에 key를 넣어 강제 리렌더링하면 됩니다. key는 imagePath.join() 이런거 넣으시면 됩니다.”

답변이 굉장히 담백했는데, 문제가 해결된 구체적인 원인과 과정이 궁금해서 다음과 같이 정리를 해보았다.

⇒ input 의 입력값이 바뀌어야 onChange 가 실행되는데, 이미지가 제거되는 것이 imagePaths 상에서만 실행되고 input 에서의 입력값은 바뀌지 않았던 것이다. 이에 따라 파일이 기존의 파일이랑 달라지지 않아 onChange 가 실행되지 않은 것이다.

⇒ 리액트는 key 값이 없으면 변경을 감지하지 못하는 특징이 있음

imagePaths 가 변경된것을 key 로 삼아 강제로 리렌더링 시키면 onChange 가 잘 작동!

const onChangeImages = useCallback((e) => {
    console.log('images', e.target.files); 
    // e.target.files: 우리가 선택한 이미지에 대한 정보가 담김
    const imageFormData = new FormData(); 

    [].forEach.call(e.target.files, (f) => {
      imageFormData.append('image', f);
    });
    dispatch({
      type: UPLOAD_IMAGES_REQUEST,
      data: imageFormData,
    })
  }, []);

...

<div>
  <input key={imagePaths} type="file" name="image" multiple hidden ref={imageInput} 
	onChange={onChangeImages} />
  {/* onChange: 이미지 업로드 창이 뜨고 이미지를 선택 후 확인을 누르면 실행 */}
  <Button onClick={onClickImageUpload}>이미지 업로드</Button>
  <Button type="primary" style={{ float: 'right' }} htmlType="submit">짹짹</Button>
</div>

답변대로 했더니 1번 버그 뿐만아니라 2번 버그 현상까지 덩달아 사라졋다!! 1번 버그가 해결된 과정은 위에서 말한것과 같고, 2번 취소버튼에 관련된 버그가 해결된 과정도 그와 같은 맥락이었다.

우선 2번 버그가 발생한 원인을 알아보자. input file 속성은 사용자가 파일을 업로드 하지 않고 취소를 누르면 파일 길이의 값은 0이 되는 특성이 있다고 한다. 즉 “취소” 버튼을 누르면 사진을 선택하지 않았기 때문에 다음과 같이 이미지 length 가 0으로 새로 갱신된다. 이 때문에 input 값 변경이 감지되어 onChange 가 발생하고, UPLOAD_IMAGES_REQUEST 가 실행되면서 imagePaths 에도 파일 길이 0이 할당되어버려 화면에 아무 이미지도 뜨지 않는 것이었다.

하지만 제로초님 해결책대로 input 에 key 값을 주면 “취소” 버튼을 눌러도 더 이상 onChange 가 실행되지 않는다. 그 이유는 아까 설명한 이유와 똑같다. 현재 input 이 의존하고 있는 변경트리거는 imagePaths key 이고, input 의 값이 0이 되어도 imagePaths 는 변경사항이 없기 때문에 결국 onChange 가 실행되지 않는다. 그에 따라 imagePaths 도 0이 되지 않고 그대로 유지될 수 있는 것이다.

profile
FE Developer 💡

0개의 댓글