[네트워크] application/x-www-form-urlencoded, application/json 무슨 차이가 있는걸까?

Hocaron·2023년 12월 31일
2

네트워크

목록 보기
5/6
post-custom-banner

PHP 로 되어있던 코드를 JAVA 로 이관하면서, Content-Type 이 application/x-www-form-urlencoded, application/json 둘다 요청받을 수 있던 코드에서 application/json 만 받을 수 있도록 변경된 케이스가 있었다.

application/json 만 요청가능한 path 에 다른 Content-Type 으로 요청시에는 아래와 같은 에러를 클라이언트에서 응답받게 된다.


Postman 에서도 요청값을 다양하게 변경 가능한데, 이 값들이 어떤 차이가 있는지 이참에 알아보자.

Content-Type 과 MIME 에 대해서 먼저 알아보자

MIME type 은 뭘까?

MIME을 사용하기전에는 UUEncode 방식을 이용하고 있었으며 UUEncode에는 치명적인 단점이 있다. 그러한 담점을 보강하여 새로운 인코딩 방식이 등장하게 되었으니 이것을 MIME이라고 한다.

예전에는 텍스트파일을 주고받는데 ASCII로 공통된 표준에 따르기만하면 문제가 없었지만, 네트워크를 통해 ASCII 파일이 아닌 바이너리 파일을 보내는 경우가 생기게 되었다. 이러한 바이너리파일에는 음악파일, 무비파일, 워드파일 등등의 문서를 지칭하는 것이다.
하지만 ASCII만으로는 전송이 불가능하여 이러한 바이너리 파일들을 기존의 시스템에서 문제 없이 전달하기 위해서는 텍스트파일로 변환이 필요하게 되엇다.

  • 인코딩(Encoding) : 바이너리 파일 -> 텍스트 파일
  • 디코딩(Decoding) : 텍스트 파일 -> 바이너리 파일
    MIME으로 인코딩 한 파일은 Content-type 정보를 파일의 앞부분에 담게 되며, Content-type은 여러가지의 타입이 있다.

Content-Type 은 뭘까?

Content-Type 헤더는 HTTP 통신에서 미디어 데이터의 타입(MIME type)을 지정하는 데 사용되며, 이는 리소스의 원래 타입을 나타내거나, 응답에서 실제 콘텐츠의 타입을 제공하거나, 요청에서 클라이언트가 보내는 데이터의 타입을 알려준다.
출처: MDN

MIME type 과 Content-Type 은 어떤 관계일까?

MIME 타입은 데이터의 종류를 식별하는 데 사용되는 개념이고, Content-Type은 HTTP에서 이를 실제로 사용하는 헤더 중 하나이다. MIME 타입이 Content-Type에 포함되어 실제로 데이터의 종류를 명시하는 역할을 한다.

application/x-www-form-urlencoded, application/json 무슨 차이가 있는걸까?

둘다 Content-Type 의 종류 중에 하나인데, 어떤 차이가 있는지 알아보자.

application/x-www-form-urlencoded 이란?

application/x-www-urlencoded는 html form을 통한 POST 전송 방식 중 가장 기본이 되는 Content-Type이다.
urlencoded라는 단어로부터 알 수 있는 것처럼 보내는 데이터를 url 인코딩 후 웹 서버에 보내는 방식이고, 인코딩이 필요하기 때문에 크기가 큰 데이터에 대해 해당하는 방식으로 보내기가 적합하지 않다는 특징이 있다.

POST /api/data HTTP/1.1
Host: example.com
Content-Type: application/x-www-form-urlencoded

name=John+Doe&age=30&city=New+York

x-www-form-urlencoded 에 대한 인코딩 규칙은 아래와 같다.

  1. key=value 형식
    요청 데이터를 키(key)와 값(value)의 쌍으로 구성합니다. 각 쌍은 '='로 키와 값이 연결되며, 여러 개의 key-value 쌍은 '&'로 구분되는데요. 이러한 형식을 통해 여러 개의 데이터를 한 번에 전송할 수 있습니다.
  2. URL Encoding
    데이터의 특수 문자나 공백과 같은 부분이 url 인코딩 규칙[RFC1738]에 따라 인코딩 됩니다. 특정 문자들은 '%' 기호와 그 문자의 ASCII 코드를 표시하여 인코딩 됩니다.

URL Encoding 이란?
단순하게 요약하자면 URL로 사용할 수 없는 문자(특수문자, 예약문자, 훈민정음)들을 사용할 수 있도록 인코딩 해주는 것이다. 인코딩된 문자는 triplet(트리플렛, 세개가 한묶음)들로 인코딩되며 인코딩된 문자는 '%(Percent)'로 시작하고 그 뒤의 두 숫자는 16진수 숫자들(digits)로 표현된다.
HTTP GET 요청에서 쿼리스트링(파라미터)에 한글 또는 ASCII에 정의되지 않은 문자가 포함되는 경우 인코딩 되는 경우
예) ?nick=호선우 -> nick=%ED%98%B8%EC%84%A0%EC%9A%B0
쿼리리스트링에 들어간 value가 예약어로서 동작하지 않게 하기 위해서 인코딩 되는 경우
예) ?pageUrl=http://codist.co.kr/intro#mymy -> pageUrl=http%3A%2F%2Fcodist.co.kr%2Fintro%23mymy
출처 : wikipedia

key, value 값이 URL 부분이 아닌 요청값에 담기는데, 왜 굳이 URL 인코딩을 사용하는지 궁금중이 생겼지만 이유를 찾지는 못 했다.

chatGpt 의 답변은 아래와 같다.

--data-urlencode 옵션을 사용하는 경우, 해당 데이터가 HTTP 요청의 본문(body)에 들어가게 됩니다. 즉, 이 데이터는 URL에 직접 노출되지 않고 요청의 본문에 포함되어 전송됩니다. 그렇기 때문에 URL과의 의미 혼동은 발생하지 않습니다.
하지만 이 옵션을 사용하는 이유는 HTTP 요청의 본문에 들어가는 데이터도 URL 인코딩이 필요할 수 있기 때문입니다. 본문 데이터에 특수 문자나 공백이 포함되어 있으면, 이를 URL에서 안전하게 전송하기 위해 URL 인코딩이 필요합니다.
간단한 예시를 통해 설명하겠습니다. 아래와 같은 cURL 명령어를 생각해 봅시다:
bash
Copy code
curl --data-urlencode "name=John Doe" --data-urlencode "email=user@example.com" https://example.com/api
여기서 --data-urlencode를 사용하여 "name"과 "email"을 전송하는데, 만약 이름에 공백이 있거나 이메일에 특수 문자가 있다면 이 데이터를 URL에서 안전하게 전송하기 위해 URL 인코딩이 수행됩니다. 이 인코딩된 데이터는 HTTP 요청의 본문에 들어가게 되며, URL에서는 노출되지 않습니다.
종합하면, --data-urlencode는 HTTP 요청의 본문에 데이터를 안전하게 포함시키기 위한 것이지 URL에 직접적으로 노출되는 것은 아닙니다.

multipart/form-data

application/x-www-form-urlencoded 방식은 인코딩 과정이 들어가기 때문에 대량의 데이터를 보내는 것에는 적합하지 않은데, 파일이나 이미지 같은 바이너리 데이터가 포함된 데이터를 보낼 때는 multipart/form-data라는 Content-Type을 사용한다.

multipart/form-data의 특징은 웹 클라이언트가 요청을 보낼 때 폼 데이터를 여러 부분으로 나눠서 보낼 수 있다는 것이다.

즉, 서로 다른 두 개의 content-type을 가진 데이터를 하나의 HTTP Request Body에 보내야 하는 경우에 사용된다.

POST /api/upload HTTP/1.1
Host: example.com
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW

------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="textData"
Content-Type: text/plain

This is some text data.
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="image"; filename="example.jpg"
Content-Type: image/jpeg

(binary image data)
------WebKitFormBoundary7MA4YWxkTrZu0gW--

이 예시에서는 textData라는 텍스트 파일과 image 이라는 이미지 파일 필드를 가진 폼 데이터를 전송하고 있다. 각 필드는 ------WebKitFormBoundary7MA4YWxkTrZu0gW로 구분되어 있다.

application/json 이란?

키-값 쌍의 집합으로, 각 필드는 큰 따옴표로 둘러싸인 문자열이나 숫자, 배열, 객체 등의 형태를 가질 수 있다.

POST /api/data HTTP/1.1
Host: example.com
Content-Type: application/json

{
  "name": "John Doe",
  "age": 30,
  "city": "New York"
}

정리

  • application/x-www-form-urlencoded 은 별도의 인코딩이 필요하여, 대용량 파일을 요청하기에는 적합하지 않다.

Referenced

profile
기록을 통한 성장을
post-custom-banner

0개의 댓글