React image 업로드

윤성민·2020년 10월 22일
8

업무 진행 중, React에서 image를 업로드 해야 할 일이 생겨 정리해보았다.

input type='file'

image는 file이기 때문에, input 태그를 사용하여 업로드 할 수 있다.

<div>
  <input type='file' 
      accept='image/jpg,impge/png,image/jpeg,image/gif' 
      name='profile_img' 
      onChange={onChange}>
  </input>
</div>

accept 는 업로드 할 수 있는 파일 확장자이다. 어진 파일 유형의 식별 방법이 여러 가지일 수도 있으므로, 특정 파일 형식이 필요할 땐 유형의 집합을 제공하는 것이 좋다.

file 타입 input의 value는 선택한 파일의 경로를 나타내는 DOM String을 담고 있다. 여러 개의 파일을 선택한 경우, 첫 번째 파일을 가리킨다. 나머지 파일 요소는 HTMLInputElement.files 속성으로 가져올 수 있다.

FormData

다음과 같이 파일을 입력받아 FormData 객체에 집어넣어 파일을 손쉽게 전송할 수 있다.

const onChange = (e) => {
    const img = e.target.files[0];
    const formData = new FormData();
    formData.append('file', img);
}

MDN 문서에 FormData 인터페이스는 form 필드와 그 값을 나타내는 일련의 key/value 쌍을 쉽게 생성할 수 있는 방법을 제공합니다. 라고 쓰여있다.

다시말하면formData 는 내가 지정한 key값과 파일을 value로 삼아 데이터 및 파일 전송을 손쉽게 해주는 객체이다.

기존의 formData가 없었을 때는, 서버로 복합적인 데이터를 보내기 위해 multipart/form-data를 사용해야 했다.

multipart/form-data 는 파일 업로드가 있는 양식요소에 사용되는 enctype 속성의 값중 하나이고, multipart는 폼데이터가 여러 부분으로 나뉘어 서버로 전송되는 것을 의미한다.

<form method="post" enctype="multipart/form-data" action="http://foo.bar/upload">
<input type="file" name="media"/>

<input name="nickname"/>
<input name="website"/>
<input type="submit" value="upload"/>

</form>

하지만 formData 를 통해 form을 생성하지 않고 손쉽게 파일을 전송할 수 있게 되었다.

const onChange = (e) => {
    const img = e.target.files[0];
    const formData = new FormData();
    formData.append('img', img);
    console.log(formData) // FormData {}
    for (const keyValue of formData) console.log(keyValue); // ["img", File] File은 객체
}

다시 onChange 함수로 돌아가서, console.log(formData)에 빈 객체가 찍히는 이유는 FormData는 XMLHtpRequest를 사용하여 전송할 키/값 쌍 집합을 컴파일한 특수한 객체이기 때문에, 문자열로 표현할 수 없기 때문이다.

그렇기 때문에, FormData의 요소를 확인하려면, 객체를 반복시키는 루프 for ... of 로 내부를 확인해 볼 수 있다.

profile
기록은 기억보다 강하다.

0개의 댓글