공부/CS

Http통신 데이터 형식(바이너리, base64) form-data사용하는이유

youngble 2024. 10. 16. 02:46

 

시작

처음시작은 하나의 의문에서 시작되었다. 왜 JSON 형태의 객체를 주고받을때 문자열 상태 '{ "a" : "hi" }' 와 같은 형태로 변경되어서 보내거나 받는걸까? JSON이면 우리가 content-type에 지정했듯이 application/json 이라고 명시되어있는데 왜 저렇게 문자열로 주고받아야하고 저걸 불필요하게 직렬화 하거나 역직렬화/파싱 처리를 해야할까? 라는 의문이들었다.
 

데이터 통신의 형태

리서치한 결과 http를 통해 데이터를 보낼수있는 형태는 바이너리 와 문자열(텍스트)로만 가능하다는것이다. 물론 다른 프로토콜을 사용하거나 타입이나 그런건 설정으로 바꿀수있다곤하지만 결국에는 바이너리 or 문자열 이다.
여기서 혼동되면 안되는부분이 header에 들어가는 content-type의 경우 말그대로 프로토콜이라는 개념으로 이해해야한다.
요청과 응답사이에서 보내는 데이터가 어떤 형태일거야 그렇게 나중에 처리해 그렇게 받아 이런 협의를 하기위한 형태이지 application/json 이라고 입력을했다고해서 JSON 데이터 형식으로 가는것도 아니다. 말했듯이 Http를 통해서는 바이너리 형태로 보내던가 문자열로 보내야하기때문에 보통 서버에서 JSON 문자열로 직렬화 작업을한다.
 
예로 Java의 경우는 Class형태의 데이터를 JSON 문자열로 직렬화(Serialization) 작업을 하게되는거고, 클라이언트(프론트)경우에도 응답으로 받은 JSON문자열을 Parse하여 JSON 데이터 형태로 바꾸는것이다 그래서 우리가 JSON.parse() 를 쓰는경우도 이에 해당하고, 서버의 경우는 JSON문자열을 받으면 ObjectMapper(Jackson)를 사용해서 JSON 문자열을 자바 클래스 객체 구조로 역직렬화하는것이다(당연히 스프링을 쓰면 애노테이션을 써서 이러한 기능을 대신해주는것도 가능하지만 말이다.).
 
따라서 데이터는 다음과 같이 두가지 형태로만 가능하다
 

1. 바이너리 2진수로 이루워진 데이터형식
2. 텍스트형식(Base64 문자열, JSON 문자열 등) - 단지 MIME을통해 Content-Type으로 명시하여 알려줄뿐

 

이미지

그래서 어떻게 실제 적용될수있는걸 생각할까하다가 당연히 많이 다루던 이미지 또는 비디오였고 가장 쉽게 접하는 이미지를 예를 생각했다.
우리가 이미지를 <input type="file" > 형식으로 받았다고 하면 이떄 들어가게되는형식은 File 형식으로 되어있고 데이터는 바이너리 상태이다. 이때 서버에게 넘겨주기전에 new FormData를 하여 key, value 형식으로 해당 File 값을 value에 넣어주는데 예를들어 formdata.append("image", file) 와 같은것이다. 이렇게 담기게되면 이미지 파일을 바이너리 형태 즉 원본 상태 그대로 보낼수있기 때문에(Content-Type은 multipart/form-data) 특히 대용량 크기일대 매우좋다. 왜냐하면 텍스트형태의 API로 보낼려고 base64로 인코딩시 약 33%의 크기가 증가한다고한다.
서버쪽에서 바이너리형태(byte)로 준다면 이를 자바스크립트에서 제공하는 Blob(Binary Large Object)를 이용하거나 File, FileReader를 사용해서 바이너리를 다룰수있는 형태나 Base64를 다룰수있는 형태로 변형해서 사용한다. 
 
 

JSON 데이터

이미지를 예를들었지만 실질적으로 의문이 든것은 이미지나 비디오 같은 형태가 아닌 User와 같은 클래스의 데이터를 JSON 데이터형식으로 사용하기위해서 의문점이 들었던것이다. 따라서 JSON 데이터는 바이너리가 아니기때문에 텍스트형식으로 바꿔줘야하는데 이를 직렬화Serialization이라 한다. 왜 직렬화 라는 이름일까 생각해보면 자바의 클래스형식은 필드, 메서드 등 트리처럼 되어있는 구조라고 했을때 이를 일자로 펴서 문자열로 나타낸다면 이를 직렬화로 생각하지 않았을까 싶다. 예를들어

class User { 
 String name;
 Integer age;
 ..
 .
}

User user = new User("test", 1);

와 같은 자바 클래스가 있다고한다면 이를 JSON 문자열로 직렬화하면 '{ "name" : "test", "age" :"1" }' 형태가 될거기 때문이다.
반대의 과정을 역직렬화(Deserialization) 인것이다.
 
작은 의문에서 시작되어 예전에 풀리지않던 데이터형태들과 HTTP 프로토콜 이해가 되서 퍼즐이 한순간에 맞춰지는 순간이였다.
 
이미지화된 도표나 그림이나 코드는 내가 이해했기때문에 따로 시각화 하지않고 여기서 끝