서버에 이미지 전송 (feat. 서버에 form 데이터 전송)

이승훈·2022년 9월 25일
0

TIL

목록 보기
10/31
post-thumbnail

들어가며

트위터 클론코딩을 하며 사용자가 텍스트와 이미지를 서버에 전송하는 기능을 구현하고자 하였다. 기존 텍스트만을 서버에 전송할 때 에는 JSON을 사용하여 간단하게 전송이 가능하였다. 이미지 전송도 이와 크게 다르지 않을것이라 쉽게 생각하였지만 역시 내 생각대로 쉬운것은 아무것도 없었다.

1. 전송할 form 데이터 만들기

기존 텍스트 데이터를 JSON 타입으로 변환하여 서버에 전송할 때 에도 내가 작성한 텍스트 혹은 객체타입의 데이터를 JSON.stringify() 메소드를 사용하여 JSON 타입 데이터로 변경 한 후 서버에 전송하였고, 서버에서는 내가 보낸 JSON 타입의 데이터를 해체하여 그안의 Javascript Data를 추출하였다.

이미지를 보낼 때 에도 이와 크게 다르지 않다.
서버와 클라이언트가 서로 공유할 수 있는 하나의 형태로 내가 보낼 데이터를 변환시킨 후 서버는 서로 약속된 방식으로 보내준 데이터를 받아 해체하여 사용하는것이다.

바로 그 약속된 방식의 데이터로 변환시켜주는 것이 formData() 라는 생성자함수이다.
new formData()를 통해 생성한 객체에 내가 보내고자 하는 데이터를 프로퍼티로 넣어주면 된다.

const formDataForSubmit = new formData();

자 위와 같이 코드를 작성해주면 formData()라는 생성자함수를 통해 formDataForSubmit이라는 이름의 객체가 생성되고 이 안에 내가 전송하고자 하는 데이터들을 입력해주면 된다.

2. 전송하는 form 객체에 원하는 데이터 추가 하기

formData() 생성자 함수를 통해 만들어진 formDataForSubmit 객체는 일반 객체처럼 그 값을 추가해주면 안된다.

const formDataForSubmit = new formData();

formDataForSubmit.imgaeFilte = '보내고자 하는 img 파일 URL'

이런식으로 일반 객체에 추가하듯이 하면 안된다는 뜻이다.
form 객체에 데이터를 추가하는 방법은 append() 메소드를 사용하면 된다.

append() 메소드는 생성자함수롤 통해 생성된 formDataForSubmit 객체의 기존 키에 새 값을 추가하거나, 키가 없는 경우 키를 추가한다.

formDataForSubmit.append(name, value);
formDataForSubmit.append(name, value, filename);

name

value에 포함되는 데이터 필드의 이름이다.

value

필드의 값이다. USVString 또는 Blob 일 수 있다.

USVString은 string 이라고 생각하면 된다.

Blob은 불변하는 미가공 데이터를 나타낸다.
Blob은 은 javascript 네이티브 형태가 아닌 데이터들도 표현할 수 있다.
File이 Blob에 기반한 인터페이스로, 사용자 시스템의 파일을 지원하기 위해 Blob 인터페이스를 상속해 기능을 확장한 것이다.

Blob은 Binary Large Object로 사실 말 그대로 매우 큰 이진수로 이루어진 객체라는 뜻이다.
디지털 세상에서 뭐든 다 이진수이긴 하다만 현재는 크기가 큰 이미지나 동영상들을 쪼개어 실시간으로 전송할 때 사용하는 객체정도로 알고 넘어가자.

filename

Blob 또는 file이 두 번째 매개 변수로 전달될 때, 서버에 리포트하는 파일 이름이다.
Blob 객체의 기본 파일 이름은 'blob' 이다.
File 객체의 기본 파일 이름은 파일의 이름이다.

그렇다면 위의 개념들을 사용하여 실제로 내가 작성한 코드는 아래와 같다.

const twitSubmit = (e) => {
  e.preventDefault();
  const formDataForSubmit = new FormData();
  formDataForSubmi.append("profileImg", imgRef.current.files[0]);

  fetch("API 주소", {
    method: "POST",
    headers: {
      "Content-Type": "multipart/form-data",
    },
    body: formData,
  })
    .then((response) => {
      if (response.ok === true) {
        return response.json();
      }
      throw new Error("에러 발생!");
    })
    .catch((error) => {
      alert(error);
    })
    .then((data) => {
      console.log(data);
    });
};

3. 전송하는 form 객체에 원하는 데이터 추가 하기(개선방법)

const formDataForSubmit = new FormData();
  formDataForSubmit.append("profileImg", imgRef.current.files[0]);

사실 이 방법은 기존 form 데이터가 있다면 한번 우회하는 방법이다.

form 태그안에 있는 데이터를 직접 받아와서 다시 formData() 생성자 함수를 통해 생성한 객체 안에 그 값을 추가해 주었기 때문이다.

하지만 form HTML element 자체를 가져와서 FormData() 생성자 함수 안에 인자로 준 후 객체를 생성하면 form 태그안의 input태그들의 name을 key값, value값을 value로 하는 객체를 함번에 만들 수 있다.
아래코드 참고

<form className="twitInput" onSubmit={twitSubmit} id="twitForm">
	<input type="text"
           name="text"
    />
             
    <input
            type="file"
            className="inputForImg"
            onClick={event => console.log(event)}
            id="imgImportInput"
			name="image"
    />
</form>



 fetch('http://pienk.ddns.net:3000/tweet', {
      method: 'POST',
      headers: {
        enctype: 'multipart/form-data',
        authorization: accessToken,
      },
      body: new FormData(twitForm),
    }).then(response => console.log(response));
profile
Beyond the wall

0개의 댓글