[ 공모전 ] Binary Data : File

최문길·2024년 8월 3일
0

공모전

목록 보기
41/46

내가 맡은 페이지, 기능부분에서 일어난 이슈가 아니라, 다른 팀원한테서 일어난 이슈이지만, 디깅과, 해결해볼 가치가 있다고 판단을 했었다.


issue - mixed content error

공모전 포스팅들 중에서 서울시 데이터 통신을 할 때 http 프로토콜로 인해 mixed content Error 가 발생했는데,
우리측, 서버 프로토콜도 http 이다. http 프로토콜을 사용한 이유는 백엔드에서 나름의 이유가 있어서 http 를 사용했다고 하는데....

issue - file객체 none

해결 방법은 우리측에서 multipart/form을 api router 로 우회하여 서버와 통신하는 방법을 선택했다.
그렇지만

여기서 새로운 사실을 알게 되었다.
실제로 팀원분의 terminal을 통해 확인했는데, form에 들어가 있는 파일 객체가 보이지가 않는다.

const Binary = () => {
  const method = useForm();
  const submitForm = (value: FieldValues) => {
    console.log(value); // {text: 'asd', image: FileList}
    const _File = value.file[0];
    const result = await axios.post("/api/binary/handler", {
      ...value,
      file: _File,
    });
    console.log(result.data) //   { text: 'asd', image: { '0': {} } }
  };
  return (
    <form onSubmit={method.handleSubmit(submitForm)}>
      <input type="text" {...method.register("text")} />
      <input type="file" {...method.register("image")} />
      <button type="submit">제출</button>
    </form>
  );
};

터미널 창에서도 { text: 'asd', image: { '0': {} } } 이렇게 빈 객체만이 보여서 의아했지만, multPart/Form을 보내는 것이므로 (text 뿐만 아닌 이미지와 같은 파일도 보낼 수 있게.)

왜 API Router (Node.js) 에서 File객체는 빈 객체일까?

File API를 사용하면 웹 애플리케이션이 파일과 그 콘텐츠에 접근할 수 있습니다. mdn

File API는 웹 페이지에서 Javascript 가 조작 할 수 있도록 제공하는 웹 API이다.
즉, 웹에서만 있는 개념이다. node에 있는 개념이 아니다.

File객체와 Blob

File 객체는 Blob의 한 종류로, Blob을 사용할 수 있는 모든 맥락에서 사용할 수 있습니다 mdn

File 객체도 Blob의 하위 인스턴스라는 말인데, Blob이란?

  1. Blob(Binary Large Object)를 의미하며, 일련의 데이터를 처리하거나 간접 참조하는 객체이다.
    -> 데이터 자체라기 보다는 데이터를 간접적으로 접근하기 위한 객체이다.

  2. Blob은 웹에서 사용되는 데이터 형식으로, 이진 데이터 를 나타내며, 텍스트, 이미지, 오디오, 비디오 등 다양한 형식을 지원하고, 주로 파일 업로드, 미디어 처리등에 사용된다.

따라서, File 객체는 로컬 파일을 참조하는 Blob객체이다.
로컬 파일을 읽거나 쓸 수 있다.

이진데이터란 컴퓨터가 이해 할수 있는 데이터이다. (메트릭스에서 보던 0과1의 세계관) 이 중에서
base64는 이진 데이터를 텍스트로 표현하기 위한 인코딩 방식 중 하나이다. (다음 포스팅에서 써먹을 text형식의 인코딩)

그러므로

클라이언트 측 ( 브라우저 ) 에서는 파일 객체가 File 또는 Blob 객체로 표현되어 File API 를 통해서 자바스크립트가 접근하여 파일을 읽거나 한다.

그렇지만
서버 측(Node.js)에서는 File 이나 Blob 객체가 존재 하지 않는다. 그렇기에 서버측에서 파일객체를 다룰 때 사용하는 버퍼(Buffer) 형식으로 처리한다.

그렇기에 node.js로 보냈을 경우 빈 객체가 있는것이다.

서버와 브라우저 둘다 자바스크립트를 쓴다고 객체가 자유롭게 이동되는 것이 아니다.
브라우저에서 서버로 보내는 Request body를 어떻게 구성하고, 어떤 데이터 타입인지 명시해줘야 한다. 단순히 JSON형식으로만 주고 받지 않으므로

번외) 그렇다면 File API를 자바스크립트에서 어떻게 조작 할까?

첫 번째로는 URL.createObjectURL() 인자로 File객체를 받으며, 해당 file의 고유 URL 정보 생성 및 반환한다.
두 번째로는 FileReader 로 File객체에 있는 실제 데이터를 읽을 수 있다.

어떻게 해야하나

FormData를 보내고 싶으면, 헤더에 Content-Type: multipart/form-data 를 명시해주고, Web APis의 FormData를 사용하여 보낸다.

new FormData()

잠깐 formData를 설명하자면
HTML에서도 폼 데이터를 다룰 수 있지만, 자바스크립트에서 폼 데이터를 다루기 위한 Class instance이다.

자바스크립트에서 폼 데이터를 다루기 위함 이란, 이미지 같은 멀티미디어 파일을 보내거나, 할 때 사용한다.


  const submitForm = (value: FieldValues) => {
    const formData = new FormData();
    Object.entries(value).forEach((item) => {
      if (item[0] === "file") formData.append(item[0], item[1][0]);
      formData.append(item[0], item[1]);
    });
    
    // formData = { text: string, file: File }
    const result = await axios.post("/api/binary/handler", formData);

위와 같이 formData 객체에 넣어 요청을 보내면, 브라우저가 보내는 HTTP 메시지는 인코딩되고 Content-Type 속성은 multipart/form-data로 지정된 후 전송하게 된다.

axios.postForm

FormData를 생성하지 않고 보내는 방법중에 axios에서는 postForm이라는 메소드를 가지고 통신해도 똑같은 결과가 나온다고 한다.

 const submitForm = (value: FieldValues) => {
   // value = { text: string, file: File }
    const result = await axios.postForm("/api/binary/handler", value);

따라서, new FormData() , axios.postForm 을 사용해서 Form데이터를 다루면 된다.

multipart/form-data || application/x-www-form-urlencoded

header의 Content-Type : multipart/form-data || Content-Type: application/x-www-form-urlencoded
둘중 하나로 axios에서 formData를 보내 줄 때 지정하는데 뭔차이인가?

-> https://velog.io/@shin6403/HTTP-multipartform-data-%EB%9E%80 //여기서 이해를 했다.

  • Content-type: application/x-www-form-urlencoded
    기본적으로 form의 default 값으로, 모든 문자들을 서버로 보내기 전에 인코딩됨을 명시한다.
    enctype : 폼 데이터(form data)가 서버로 제출될 때
    해당 데이터가 인코딩되는 방법을 명시한다.
  • multipart/form-data : 모든 문자를 인코딩하지 않음을 명시한다.
    이 방식은 <form> 요소가 파일이나 이미지를 서버로 전송할 때 주로 사용한다.

Content-type도 타입을 하나만 명시할 수 있지만 multipart/form-data로 여러가지 타입으로 보낼수 있도록 명시해준다.



마무리

브라우저와 서버간, 리액트, vue, nextjs, axios와 같은 라이브러리 프레임워크와 상관없이 동일한 규칙을 통해서 서로 통신한다.
그 통신 규칙을 프로토콜이라 부르고, 웹서버와 브라우저간 사용하는 프로토콜이 HTTP이다.

Form 데이터를 통신 할 경우, form의 Content-Type은 json이 아니기에, 어떤 Content-Type으로 request 메세지를 구성해야하는지, request body를 구성해야 하는지를 잘 알아야 한다.

뿐만 아닌 서버에서는 이런 request를 받았을 때, 어떻게 해석하여 서버 로직에 쓰는지도 알 필요성이 분명하다.
브라우저와 서버 둘다 자바스크립트를 사용한다고 객체가 자유롭게 이동되는 것이 아니라는 것을 알게 되었다.

0개의 댓글

관련 채용 정보