본문 바로가기
제니의 개발일지/도움이 되었던 것 정리

React 리액트 이미지 수정 하는 법

by 제니운 2022. 10. 9.
728x90

우리 사이트 Homecoming Day 마이페이지

 

 

마이페이지를 내가 구현했는데, 프로필 이미지 수정을 하는 기능을 추가했다!

생각보다 이미지 수정은 간단했다.

 

 

🔷 일단 전체 코드는 이렇게 생겼다!

 

//프로필 이미지 PATCH 기능
  const [imageUrl, setImageUrl] = useState('');
  const imgRef = useRef();

  const onChangeImage = async (e) => {
    const reader = new FileReader();
    const file = imgRef.current.files[0];

    reader.readAsDataURL(file);
    reader.onloadend = () => {
      setImageUrl(reader.result);
    };
    if (e.target.files[0]) {
      const userImage = new FormData();
      userImage.append('userImage', e.target.files[0]);
      await dispatch(__patchProfileImage(userImage));
      await dispatch(__getMyPage());
    }
  };

  const onClickFileBtn = (e) => {
    imgRef.current.click();
  };

  const onErrorImg = (e) => {
    e.target.src = profileorange;
  };

 

 

1️⃣ 먼저, imageUrl을 useState로 만들어준다.

 

  const [imageUrl, setImageUrl] = useState('');

 

 

2️⃣ 이미지 부분을 클릭할 때 사용하기 위해 useRef() 사용한다.

 

const imgRef = useRef();

 

 

3️⃣ 이미지를 수정하는 코드이니까 onChangeImage라고 이름을 정해주고, 아래 코드 그대로 사용하면 된다.

 

 

맨 아래 dispatch(__patchProfileImage(userImage)라고 되어 있는 부분은, 모듈에 만든 대로 변경해주면 되고 userImage라고 ()안에 들어 있는 부분은, 이미지 이름 정해준 걸로 넣어주면 된다.

그리고 dispatch(__getMyPage())를 해준 것은, patch 해주고 get을 해줘서 보여주기 위함이다.

 

 

const onChangeImage = async (e) => {
    const reader = new FileReader();
    const file = imgRef.current.files[0];

    reader.readAsDataURL(file);
    reader.onloadend = () => {
      setImageUrl(reader.result);
    };
    if (e.target.files[0]) {
      const userImage = new FormData();
      userImage.append('userImage', e.target.files[0]);
      await dispatch(__patchProfileImage(userImage));
      await dispatch(__getMyPage());
    }
  };

 

 

😶‍🌫️ 여기서 내 트러블 슈팅 발생...

 

append 뒤에 files를 BackEnd와 정해준 이름으로 보내야 한다. 원래 구글에 예시로 많이 올라온 코드는

 

이미지 이름. append("files", e.target.files[0]) 이렇게 생겼다.

 

나는 이미지 이름을 userImage라고 API 설계할 때 정했기 때문에,

userImage.append("files", e.target.files[0])라고 코드를 작성했는데, 계속 500에러가 나서 확인해보니 아래 files를 백엔드측에서 userImage로 받고 있기 때문에, files도 정해준 이름으로 해주니까 오류가 사라졌다.

 

 

4️⃣ 이미지 클릭해서 수정하는 버튼 이벤트를 만들어주기

 

const onClickFileBtn = (e) => {
    imgRef.current.click();
  };

 

이걸 위해 위에서 imgRef 선언한 것!

 

 

5️⃣ return 안의 코드는 이렇게 사용했다.

 

<StUserImgWrap>
	<StUserImg
		src={mypages.userImage}
		onClick={() => {
  			onClickFileBtn();
    	}}
		onError={onErrorImg}
		/>
	<input
		type='file'
		ref={imgRef}
		onChange={onChangeImage}
		style={{ display: 'none' }}
		/>
	<StUserImgUpload
		onClick={() => {
  			onClickFileBtn();
		}}
	>
		<StCameraIcon />
	</StUserImgUpload>
</StUserImgWrap>

 

스타일 컴포넌트를 사용해서, stUserImage를 img로 하고 안에 src={}로 이미지를 추출해준다.

 

 

😶‍🌫️ 두 번째 트러블 슈팅 발생!

 

왜 추출을 하는 거에요? ? 

바로 처음 이미지가 없을 경우의 오류 때문이다.

이 기본 이미지를 메인 페이지, 마이페이지나 게시글 상세 조회해서 보이게 할 경우, 마이페이지만 PATCH되다 보니 여전히 에러 이미지가 보여졌다.

물론 게시글 페이지나 상세페이지에서도 아래에 정리할 Error 함수를 쓰면 해결할 수는 있으나, 그럼 굳이 PATCH를 쓸 필요가 없으므로 해결한 방법은 백엔드와의 협업!

 

백엔드의 S3에 기본 이미지를 탑재해둔다. 그 기본 이미지를 useSelector로 가져와서 mypages.useImage이런 식으로 추출한 것이다. 그걸 input으로 이미지 수정해주기!

 

mypages라고 되어 있는 것은, 내가 데이터를 꺼낼 때 useSelector를 사용하면서 mypages로 선언한 것이라, 선언한 이름으로 바꿔서 해주면 된다.

 

 

onClick 함수는 위 4번에서 클릭 이벤트 만든 것을 사용했다.

input은 이미지 업로드를 위해 사용되었고 ref함수, onChangeImage도 위에 모두 기재해두었다. 똑같이 사용하면 된다!

StUserImgUpload 스타일 컴포넌트 안에 카메라 아이콘을 넣어서 onClick함수를 기재해두고 카메라 아이콘을 누르면 이미지 업로드 창이 뜨게 구현되어 있다.

 

 

😶‍🌫️ 여기서 세 번째 트러블 슈팅 발생!

 

이건 백엔드의 S3에 이미지 탑재해두고 내가 추출했기 때문에, 더 이상 발생하진 않았던 문제이다.

만약 그렇게 하지 않고 프론트엔드에서만 해결하고자 한다면, 아래와 같이 onErrorImg 함수를 사용하면 된다.

 

 

  const onErrorImg = (e) => {
    e.target.src = profileorange;
  };

 

 

profileorange라고 되어 있는 것은, 내가 vs코드 안에 이미지를 기본 이미지를 넣어두고 import한 이미지이다.

이렇게 해두면, 이미지를 수정 PATCH 하기 전에 이 이미지가 보여져서 에러 이미지를 안 뜨게 할 수 있다.

 

다만, 마이페이지만 하는게 아니라 게시글 페이지, 상세 페이지 처럼 이미지를 사용하는 페이지가 많아진다면 함수를 계속 사용하는 것보다 이미지를 가지고 와서 PATCH하는 방식이 좀 더 효율적이었던 것 같다!

 

이미지 수정 정리 끝!

 

728x90