본문 바로가기

프론트엔드

[REACT, JS, AXIOS] JS 다중 파일 및 JSON 전송

1. 작성 동기

[PROJECT] 동아리 모집 설문 페이지를 제작 중 지원자들의 포트폴리오 혹은 올리고 싶은 파일을 받을 수 있도록 하여야 했는데 지원자들이 작성한 글과 함께 파일들을 다중으로 받는 경우에 어떤식으로 처리를 할지 몰라 삽질을 계속해서 하다. 결국 해결을 했는데 삽질을 하다 참고한 글들을 내가 한번 더 보기 쉽게 정리를 하면 다른 사람들한테도 도움이 되고 나한테도 도움이 될 것 같아서 이 글을 작성하게 되었다.

 

2. Form 작성

아래는 파일을 받기 위한 간단한 예제 form 이다.

 

import React from "react";
import axios from "axios";

const Survey = () => {

  return (
    <form onSubmit={(e) => onSubmit(e)}>
      <input
        type="file"
        name="profile_files"
        multiple="multiple"
      />

      <button type="submit">제출</button>
    </form>
  );
  
};

export default Survey;

 

 

위 코드에서 중요한 부분은 input 태그의 multiple 속성이다 저 속성을 반드시 붙여야 한다.

 

3. 파일 formData 객체에 담기

파일을 http 통신으로 전송 하려면 formData 객체를 이용하여 보내야 한다.

 

formData 객체는 XMLHttpRequest 전송을 위하여 설계된 특수한 객체 형태 이다.
특수한 개체이다 보니 특정한 조작을 가하지 않으면 문자열 화도 불가능하다.

 

formData 객체는 key, value 형식으로 되어 있는 객체이다.

 

formData.append('key', value);

 

따라서 파일을 다중으로 formData에 추가하려면 아래와 같이 반복문을 활용하여 넣어야 한다.

 

  const onSubmit = async (e) => {
    e.preventDefault();
    e.persist();

    let files = e.target.profile_files.files; // Form의 input을 들고온다.
    let formData = new FormData(); // formData 객체를 생성한다.
    for (let i = 0; i < files.length; i++) { 
      formData.append("files", files[i]); // 반복문을 활용하여 파일들을 formData 객체에 추가한다
    }

  };

 

4. 일반 데이터 formData 객체에 담기

파일과 함께 일반 데이터도 같이 전송을 하기 위해선 아래와 같이 코드를 작성하여야 한다.

 

  const onSubmit = async (e) => {
  	...

    let dataSet = {
      name: "Hong gil dong",
      phone: "010-1234-1234",
      birth: "2001-09-11",
    };

    formData.append("data", JSON.stringify(dataSet)); // JSON 형식으로 파싱 후 추가

  };

 

일반 JSON 데이터를 formData 객체에 추가 할 시 JSON으로 파싱을 한 후 추가를 해주어야 한다.

 

5. axios를 이용하여 전송

axios를 활용하여 전송을 하는데 기타 다른 라이브러리 혹은 fetch api를 사용해도 아래 표시될 몇가지 포인트만 잘 준수 하면 어디서든 이 방법을 활용하여 다중 파일과 JSON 데이터를 전송 할 수 있다.

아래는 전송 예제 코드이다.

 

  const onSubmit = async (e) => {

	...

    const postSurvey = await axios({
      method: "POST",
      url: `http://xxxxxx.com/api/survey`,
      mode: "cors",
      headers: {
        "Content-Type": "multipart/form-data", // Content-Type을 반드시 이렇게 하여야 한다.
      },
      data: formData, // data 전송시에 반드시 생성되어 있는 formData 객체만 전송 하여야 한다.
    });

  };

 

반드시 Content-Typedata 부분의 포인트를 틀려서는 안된다.

저부분이 다를 경우 파일과 JSON 데이터들이 올바르지 않게 전송될 수 있다.

 

6. 전체 코드 및 주의사항

전체 코드

 

import React, { useEffect, useState, useRef } from "react";
import axios from "axios";

const Survey = () => {
    
  const onSubmit = async (e) => {
    e.preventDefault();
    e.persist();

    let files = e.target.profile_files.files;
    let formData = new FormData();
    for (let i = 0; i < files.length; i++) {
      formData.append("files", files[i]);
    }

    let dataSet = {
      name: "Hong gil dong",
      phone: "010-1234-1234",
      birth: "2001-09-11",
    };

    formData.append("data", JSON.stringify(dataSet));

    const postSurvey = await axios({
      method: "POST",
      url: `v1/survey/${surveyID}/applier`,
      mode: "cors",
      headers: {
        "Content-Type": "multipart/form-data",
      },
      data: formData,
    });

    console.log(postSurvey);
  };

  return (
    <form onSubmit={(e) => onSubmit(e)}>
      <input
        type="file"
        name="profile_files"
        multiple="multiple"
      />

      <button type="submit">제출</button>
    </form>
  );
};

export default Survey;

※ 주의할 점 ※

서버에 전송된 데이터 중 JSON 데이터가 문자열 형태와 비슷하게 전송 될 수가 있으므로 서버에서 다시한번 JSON 형태로 파싱 하는 것을 추천한다.

 

7. 마무리

틀린 부분이나 수정해야 할 부분이 있을 수도 있으나 위와 같은 형식으로 하면 다중 파일들과 JSON 데이터들이 정상적으로 전송이 되는 것으로 확인 했으니 나와 같은 상황에 맞이 하신 분들이 이글을 보고 조금이나마 삽질을 덜 하셨으면 좋겠다...

'프론트엔드' 카테고리의 다른 글

[React] Storybook 설치법  (4) 2021.11.24
오늘의 수확(알아낸 것들) - 풍년이다 풍년  (1) 2021.05.10