Language/JavaScript

[JS] 이미지 전송; base64와 FormData

혬수 2024. 4. 13. 02:09

 

음식 인식을 위한 음식 사진, 유저 사진 등 서버로 이미지를 전송해야할 필요가 있었다.

기존에는 base64 방식을 채택했으나, 서버로 전송하는데 시간이 오래 걸려 이 부분을 개선하기로 했다.

 

이미지 전송에는 여러 가지 방법이 있지만,

대표적인 방식인 Base64와 FormData에 대해 알아보도록 하자!

 

📍Base64 인코딩

이진 데이터를 64개의 ASCII 문자로 변환하는 방식이다.

 

인코딩 방법

24비트 버퍼에 위쪽(MSB)부터 한 바이트씩 세 바이트를 집어넣는다. (버퍼의 남은 부분은 0으로 채워넣는다.)
그리고, 버퍼의 위쪽부터 6비트(2^6=64)씩 
잘라 그 값을 읽어 Base64 색인표와 맵핑한다.
이 과정을 거치면 4개의
 ASCII 문자로 변환된다.

++예시

 

특징

  • 데이터 손실 방지: 이진 데이터를 ASCII 문자열로 변환하므로, 데이터 전송 중에 발생할 수 있는 데이터 손실을 방지할 수 있다. 
  • 호환성: ASCII 문자만을 사용하므로, 대부분의 시스템과 호환된다. 
  • URL 안전: Base64 인코딩된 문자열은 URL에 안전하게 포함될 수 있다. 

그러나, 원래 3바이트(24비트)의 이진 데이터가 4개의 ASCII 문자로 변환되므로, 데이터 크기가 약 33% 증가하게 된다.
따라서 대용량의 데이터를 전송하는 경우에는 비효율적일 수 있다. 

 

📍Form Data

JavaScript에서 XMLHttpRequest, Fetch와 같은 웹 API와 호환되는 방식으로 데이터를 보내기 위한 객체이다.

 

이때 Form은 웹 폼(Form)을 의미하는데, 사용자가 입력한 데이터를 서버로 전송하는 데 사용되는 HTML 요소이다.
FormData 객체는 이 웹 폼의 데이터를 표현하는 데 사용되며, 각 키-값 쌍은 폼의 각 필드를 나타낸다.

 

HTTP 요청으로 서버 전송할 때, Content-Type 헤더 속성은 multipart/form-data라는 MIME타입이고, 인코딩되어 전송된다.

 

  • MIME 타입
    : Multipurpose Internet Mail Extensions
    : 이메일 보낼 때 사용되는 인터넷 표준이다. 원래는 이메일에서 비-ASCII 문자를 지원하기 위해 만들어졌지만, 현재는 웹에서도 널리 사용되고 있다.
    : 타입(type)과 서브타입(subtype)이라는 두 부분으로 이루어져 있다. 이 두 부분은 슬래시(/)로 구분된다.
    : 웹에서는 HTTP 응답의 'Content-Type' 헤더에 MIME 타입을 지정하여, 클라이언트에게 응답의 내용이 어떤 형식인지 알려준다. 이를 통해 클라이언트는 적절한 방식으로 데이터를 처리할 수 있다.

 

사용 방법

FormData 객체 생성 후, append(key, value)를 통해 데이터를 추가할 수 있다.

 

이때, iOS에서 파일의 URI가 'file://'로 시작하는데, 이 부분을 제거하지 않으면 일부 라이브러리나 API에서 파일을 제대로 인식하지 못할 수 있다. 따라서 iOS에서 파일을 FormData로 전송할 때는 'file://' 부분을 제거해야 한다.

  const form = new FormData();
  
  const uri =
  Platform.OS === 'android'
    ? uploadInfo.file
    : uploadInfo.file.replace('file://', '');

  form.append('name', testName);
  form.append('image', {
    uri,
    name: 'image.jpg',
    type: 'image/jpg',
  })

 

 

서버에 전송하는 방법은 다음과 같다.

// fetch 이용
async function uploadData() {
  try {
    const response = await fetch('서버 URL', {
      method: 'POST',
      body: form,
      headers: {
        'Content-Type': 'multipart/form-data',
      },
    });
    const data = await response.json();
    console.log(data);
  } catch (error) {
    console.error(error);
  }
}

uploadData();

 

// axios 이용
async function uploadData() {
  try {
    const response = await axios.post('서버 URL', form, {
      headers: {
        'Content-Type': 'multipart/form-data',
      },
    });
    console.log(response);
  } catch (error) {
    console.error(error);
  }
}

uploadData();

 

 

 

참고

https://ko.wikipedia.org/wiki/%EB%B2%A0%EC%9D%B4%EC%8A%A464

https://developer.mozilla.org/en-US/docs/Web/API/FormData