React) 이미지 업로드 및 삭제

은유로그·2022년 7월 29일
2

✍️ devlog

목록 보기
3/6
post-thumbnail
  • React와 TypeScript를 이용한 이미지 업로드 및 삭제 구현
  • 다중 이미지 업로드가 아닌 단일 이미지 업로드 구현 -> 다중 이미지 업로드 대응하기로 함
  • 이미지 업로드를 위한 url(src)는 서버에서 응답 받음 -> url(src)를 배열 형태로 받기로 함
  • CORS 이슈는 CORS Unblock 익스텐션으로 임시 대응 -> 백엔드분과 얘기 나눠야함! 해결

이미지 업로드 (REST API)

요청
method: POST
path: /api/image
header: 
	Authorization: Bearer 토큰정보
body:
	file: 파일 데이터... (multipart-form-data 형식)
응답
status: 200
body:
{
   "url": "https://..."
}

handleUpload

  • 이미지 업로드를 구현한 함수
  • console.log(event.target.files)를 찍어면 위와 같이 보여진다. FileList - MDN
  • 이미지 업로드를 위해 필요한 값은 FileList가 아닌 File 데이터다.
  • console.log(event.target.files[0])를 찍으면 위와 같이 보여진다. File - MDN
  • FileList배열이 아니지만, 0이란 키에 File 데이터가 담겨있기 때문에 배열처럼 0번째 요소를 가져오면 File 데이터가 보여진다.
  • multipart-form-data 형식으로 요청해야하기 때문에 FormData 객체를 생성(new FormData())하고, File 데이터를 추가(FormData.append())한다. FormData - MDN
  • fetch API를 이용해 서버에 요청을 보내고, 응답 받은 url(src)를 상태에 담는다.
  • 코드는 아래와 같다.
const handleUpload = async (event: ChangeEvent<HTMLInputElement>) => {
  if (event.target.files) {
    setFiles(event.target.files[0])
  }

  const formData = new FormData()
  if (files) {
    formData.append('file', files)
  }

  const result: string = await fetch('http://localhost:4000/api/image', {
    method: 'post',
    body: formData,
    headers: {
      authorization:
      'Bearer zmk1g6n0xia2eq8f6pdy8rxrgwcjzs.d7iec3dk41357xcbqno59m8tnzf671pv5hz1ghtgiy33xujmk0.54da9zfdt5fgrtwr0hyb3o5loqjsqb',
    },
  })
  .then((res) => res.json())
  .then((body) => body.url)

  if (result) setShowImages([...showImages, result])
}

handleDelete

  • 업로드된 이미지를 삭제하는 함수
  • 간단하게 slice()를 이용해서 구현했다.
const handleDelete = (idx: number) => {
  setShowImages([
    ...showImages.slice(0, idx),
    ...showImages.slice(idx + 1, showImages.length),
  ])
}

전체 코드

import {useState, ChangeEvent} from 'react'

const UploadImages = () => {
  const [files, setFiles] = useState<File | null>(null)
  const [showImages, setShowImages] = useState<string[]>([])

  const handleUpload = ...

  const handleDelete = ...

  return (
    <div>
      <input
        type="file"
        accept="image/*"
        onChange={handleUpload}
      />
      {showImages.map((src, idx) => {
        return (
          <div>
            <image src={src} alt={`${src}`} />
            <button onClick={() => handleDelete(idx)}>X</button>
          </div>
        )
      })}
    </div>
  )
}

export default UploadImages
profile
๑•‿•๑

0개의 댓글