[Next.js] 프로필 이미지 업로드

JunSeok·2023년 1월 27일
5

Movie-inner 프로젝트

목록 보기
4/13
post-thumbnail
post-custom-banner

상황

회원가입 도중 프로필 사진을 업로드하는 기능을 구현하려 한다.

원하는 것

항상 느끼는 것이지만 원하는 것이 무엇인지 명확히 해야 한다.
그래야 해결책을 찾을 수 있다.

1. 이미지 클릭하면 이미지 업로드하기

2. 이미지 업로드하는 버튼 따로 만들기

3. 이미지 업로드하면 프로필 사진에 업로드한 이미지 사진 띄우기

4. 이미지 URL 반환받기

구현

기타 관련없는 코드는 삭제했으므로 필요한 부분만 참고할 것

특이사항

  • 이미지 파일은 file 타입의 input이 받되, 화면에는 보이지 않게 한다.
  • 프론트 엔드 코드에 한정된 부분이기 때문에 AWS S3 관련 코드는 없다.
    이미지 파일을 서버에 보내고, 서버는 받은 이미지 파일을 S3에 저장하고 받은 URL 값을 클라이언트로 반환해준다.

const TestComponent = () => {
  // 초기값은 프로필 사진 없을 때 넣을 기본 이미지
  const [image, setImage] = useState('/blank.png')
  
  const fileInput = useRef(null)
  
  const handleImage = async (e: any) => {
    // 내가 받을 파일은 하나기 때문에 index 0값의 이미지를 가짐
	const file = e.target.files[0]
    if(!file) return
    
    // 이미지 화면에 띄우기
    const reader = new FileReader()
    // 파일을 불러오는 메서드, 종료되는 시점에 readyState는 Done(2)이 되고 onLoad 시작
    reader.readAsDataURL(file)
    read.onLoad = (e: any) => {
    	if(reader.readyState === 2) {
        	// 파일 onLoad가 성공하면 2, 진행 중은 1, 실패는 0 반환
          	setImage(e.target.result)
        }
    }
    
    // 이미지 파일을 formData에 담아서 서버에 보내고, 서버는 받은 이미지 파일을 S3에 저장하고 받은 URL 값을 클라이언트로 반환해준다.
    const formData = new FormData()
    formData.append('image', file)
    try {
      // 
    	const imageRes = await (/*api 부분은 생략*/).post('/image', formData, {
          // 헤더에 보낼 파일의 타입이 multipart라 말해줘야 한다. 이미지 파일은 크기 때문에 부분으로 나눠서 보내기 때문
        	headers: { "Content-Type": "multipart/form-data" }
        })
        // 반환받은 이미지 URL, 원하는 곳에 사용하면 된다. 나 같은 경우 회원가입 할 때, 회원정보와 같이 한 번에 서버로 보내줬다.
        const image_URL = imageRes.data.imageURL
    } catch (e) {
    	console.error(e.response)
    }
    
  }
  
  return (
  	<>	
    	// 이미지 클릭했을 때 이미지 업로드, 숨긴 input의 reference를 fileInput으로 설정해서 가능
    	<a href="#" onClick={() => fileInput.current.click() } >
    		<Image src={image} width={150} height={150} alt="프로필 이미지" />
    	</a>

		// 이미지 업로드 버튼, htmlFor값을 숨긴 input의 id값으로 설정
		<label htmlFor="input-file" >이미지 선택</label>

		// 실제 이미지 받을 file 타입의 input
		<input type="file" name="image_URL" id="input-file" accept='image/*'
		style={{ display : "none" }} ref={fileInput} onChange={handleImage} />
    </>
  )
}

느낀 점

처음에는 굉장히 어려워보였고, 구현하는데도 실제로 오래 걸렸다.
근데 모르는 것을 찾아보면서 구현에 성공을 하니 이제는 익숙해졌다.

백엔드 코드를 보고 싶다면
[Node.js] S3와 multer를 이용하여 프로필 이미지 저장하기

profile
최선을 다한다는 것은 할 수 있는 한 가장 핵심을 향한다는 것
post-custom-banner

0개의 댓글