DevLog ๐Ÿ˜ถ

[HTTP] GET vs POST, GET์€ body ๊ฐ’์„ ๊ฐ€์ง€๋ฉด ์•ˆ ๋ ๊นŒ? ๋ณธ๋ฌธ

โœ๏ธ/CS

[HTTP] GET vs POST, GET์€ body ๊ฐ’์„ ๊ฐ€์ง€๋ฉด ์•ˆ ๋ ๊นŒ?

dolmeng2 2023. 4. 19. 10:43

๐ŸŒฑ ๋“ค์–ด๊ฐ€๊ธฐ ์ „

์Šคํ„ฐ๋””๋ฅผ ์ง„ํ–‰ํ•˜๋ฉด์„œ, GET ์š”์ฒญ๊ณผ POST ์š”์ฒญ์˜ ์ฐจ์ด๊ฐ€ ๋‹จ์ˆœํžˆ '์˜๋ฏธ๋ก ์ '์œผ๋กœ๋งŒ ์ฐจ์ด๊ฐ€ ์žˆ๋Š” ๊ฑด์ง€ ๊ถ๊ธˆํ•ด์„œ ์ฐพ์•„๋ณด๊ฒŒ ๋˜์—ˆ๋‹ค.
์Šต๊ด€์ ์œผ๋กœ ๋‚˜๋Š” ๋ฆฌ์†Œ์Šค ๋“ฑ๋ก ์‹œ POST๋ฅผ, ๊ทธ๋ฆฌ๊ณ  ์กฐํšŒ ์‹œ GET์„ ์‚ฌ์šฉํ–ˆ์—ˆ๋‹ค.
ํ•˜์ง€๋งŒ ๋ฆฌ์†Œ์Šค ๋“ฑ๋ก ์‹œ์—๋„ GET์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๋ฌธ๋ฒ•์ ์œผ๋กœ๋„ ์•ˆ ๋˜๋Š” ๊ฑด์ง€, ์•„๋‹ˆ๋ฉด ๊ด€์Šต์ ์œผ๋กœ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ๊ฒƒ์ธ์ง€๋Š” ๊ถ๊ธˆํ•ด์„œ ์ฐพ์•„๋ณด์•˜๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋ช‡ ๊ฐ€์ง€ ์š”์ฒญ๋“ค์„ ์‹ค์Šตํ•ด๊ฐ€๋ฉฐ ์–ด๋Š ์ •๋„ ์ƒ๊ฐ์„ ์ •๋ฆฌํ•ด๋‘์—ˆ๋‹ค.
(์˜์–ด ์›๋ฌธ์— ๋Œ€ํ•œ ๋ฒˆ์—ญ์„ ํ•˜๋‹ค ๋ณด๋‹ˆ ๋‹ค์†Œ ์˜๋ฏธ์  ์ฐจ์ด๊ฐ€ ์žˆ์„ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค ๐Ÿฅฒ)

 


โœ”๏ธ GET

The GET method requests that the target resource transfer a representation of its state.
GET requests should only retrieve data and should have no other effect.

GET ๋ฉ”์„œ๋“œ๋Š” ํƒ€๊ฒŸ ๋ฆฌ์†Œ์Šค๊ฐ€ ํ•ด๋‹น ๋ฆฌ์†Œ์Šค์˜ ์ƒํƒœ๋ฅผ ํ‘œํ˜„ํ•˜๋Š” ๊ฒƒ์„ ์ „์†กํ•˜๋„๋ก ์š”์ฒญํ•˜๋Š” ๊ฒƒ์ด๋‹ค.
GET ์š”์ฒญ์€ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฒ€์ƒ‰ํ•ด์•ผ ํ•˜๋ฉฐ, ๋‹ค๋ฅธ ๋ถ€์ˆ˜์  ํšจ๊ณผ๊ฐ€ ๋‚˜ํƒ€๋‚˜์ง€ ์•Š๋„๋ก ํ•ด์•ผ ํ•œ๋‹ค.
 
์—ฌ๊ธฐ์„œ 'retrieve data'๋ผ๋Š” ํ‘œํ˜„์ด ์“ฐ์˜€๋Š”๋ฐ, ์ด๋Š” DBMS์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•œ๋‹ค.
= ๋ฐ์ดํ„ฐ๋ฅผ ์–ด๋– ํ•œ ์ฟผ๋ฆฌ๋ฅผ ํ†ตํ•ด์„œ ๊ฐ€์ ธ์˜ค๋Š” ํ–‰์œ„๋ฅผ ์˜๋ฏธํ•œ๋‹ค.
 
๋ฆฌ์†Œ์Šค์˜ ๋ณ€๊ฒฝ ์—†์ด ๊ฒ€์ƒ‰์„ ํ•  ๋•Œ๋Š” URL์„ ํ†ตํ•ด '๊ฒ€์ƒ‰'ํ•˜๋Š” GET ์š”์ฒญ์ด ๋” ์œ ์šฉํ•˜๋‹ค.
W3C (๊ตญ์ œ ์›น ํ‘œ์ค€ ๊ธฐ๊ตฌ)์—์„œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด GET์„ ์ •์˜ํ•˜์˜€๋‹ค.

Use GET if:
The interaction is more like a question. (i.e, it is a safe operation such as a query, read operation, or lookup)

๋งŒ์•ฝ '์งˆ๋ฌธํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ' ์–ด๋– ํ•œ ๊ฒƒ์„ ๋ฌผ์–ด๋ณผ ๋•Œ, read ์—ฐ์‚ฐ์„ ํ•  ๋•Œ GET์„ ์‚ฌ์šฉํ•˜๋ผ๊ณ  ํ•˜์˜€๋‹ค.
๊ทธ๋ฆฌ๊ณ , URI์„ ์ด์šฉํ•ด์„œ ์ •๋ณด๋ฅผ ์š”์ฒญํ•˜๋ผ๊ณ  ๋งํ•˜๊ณ  ์žˆ๋‹ค.
 
๊ธฐ๋ณธ์ ์œผ๋กœ ์›น ์•„ํ‚คํ…์ฒ˜๋Š” RFC2396์— ์˜ํ•ด ์ •์˜๋œ URI๋กœ ์‹œ์ž‘๋œ๋‹ค. Web์€ Web๋ผ๋ฆฌ ์„œ๋กœ ์ฐธ์กฐํ•˜๊ณ , ์„ค๋ช…ํ•˜๊ณ , ์ ‘๊ทผํ•˜๊ณ , ๊ณต์œ ํ•  ์ˆ˜ ์žˆ๋„๋ก URI์˜ ๊ทœ์น™์„ ๋”ฐ๋ฅด๊ฒŒ ๋˜๋Š”๋ฐ, ๋ฆฌ์†Œ์Šค์— ๋Œ€ํ•œ URI๋Š” linking, bookmarking, caching ๋“ฑ ๋‹ค์–‘ํ•œ ์ด์ ์„ ์ค€๋‹ค๊ณ  ์†Œ๊ฐœํ•œ๋‹ค.
์—ฌ๊ธฐ์„œ 'URI addressability'๋ผ๋Š” ๋‹จ์–ด๋ฅผ ์†Œ๊ฐœํ•˜๋Š”๋ฐ, ์ด๋Š” ํด๋ผ์ด์–ธํŠธ๊ฐ€ ํŠน์ • ํƒ€์ž…์˜ ์ƒํ˜ธ์ž‘์šฉ์„ ์ˆ˜ํ–‰ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” URI๋กœ๋„ ์ถฉ๋ถ„ํ•˜๋‹ค๊ณ  ๋งํ•œ๋‹ค. ์ฆ‰, URI๋งŒ์œผ๋กœ๋„ ํ†ต์‹ ํ•˜๊ธฐ ์ถฉ๋ถ„ํ•˜๋‹ค๋Š” ์˜๊ฒฌ์ด๋‹ค. (๋ฌผ๋ก , ๋‚˜๋Š” ๋™์˜ํ•˜์ง€ ์•Š๋Š”๋‹ค ๐Ÿ˜…)
 

By convention, when GET method is used, all information required to identify the resource is encoded in the URI

๋˜ํ•œ, HTTP/1.1์—์„œ GET์€ ๊ฒ€์ƒ‰ ์ด์™ธ์˜ ๋™์ž‘์„ ์ˆ˜ํ–‰ํ•˜๋„๋ก ํ•˜์ง€ ์•Š๋Š” ๊ฒƒ์ด ์ข‹๋‹ค๊ณ  ์†Œ๊ฐœํ•˜๊ณ  ์žˆ๋‹ค.
์• ์ดˆ์— GET ์š”์ฒญ ์ž์ฒด๋ฅผ '์•ˆ์ „ํ•œ ๋ฉ”์„œ๋“œ'๋ผ๊ณ  ํŒ๋‹จํ•˜๋Š”๋ฐ, ์ž์›์„ ๋‹จ์ˆœํžˆ ์ฝ๊ธฐ๋งŒ ํ•˜๋Š” ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์— ์„œ๋ฒ„์— ์˜ํ–ฅ์„ ๋ผ์น˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.
ํ•˜์ง€๋งŒ, GET ์š”์ฒญ์˜ ๊ฒฝ์šฐ ๊ฒฐ๊ณผ์ ์œผ๋กœ ํ•„์š”ํ•œ ๋ชจ๋“  ์ •๋ณด๊ฐ€ URI์— ๋“ค์–ด๊ฐ€๊ธฐ ๋•Œ๋ฌธ์—, ๋ณด์•ˆ์ ์ธ ์ธก๋ฉด์—์„œ ์ƒ๊ฐํ•ด๋ณด์•˜์„ ๋•Œ body์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์ œ๊ณตํ•˜๋„๋ก 'GET with BODY'๋ผ๋Š” ๊ฒƒ์ด ๋…ผ์˜๋˜๊ธฐ๋Š” ํ–ˆ์—ˆ๋Š”๋ฐ ๊ธฐ๊ฐ๋˜์—ˆ๋‹ค๊ณ  ํ•œ๋‹ค. (๋ฌผ๋ก  ๊ณผ๊ฑฐ๋‹ค)
 
๊ทธ๋ž˜์„œ ์ด์— ๋Œ€ํ•ด์„œ ๋˜ ์—ฌ๋Ÿฌ ๊ฐ€์ง€๋ฅผ ์ฐพ์•„๋ณด์•˜๋‹ค.
๋กœ์ด ํ•„๋”ฉ์ด๋ผ๋Š” ์‚ฌ๋žŒ์€ 'GET with BODY'์— ๋Œ€ํ•ด์„œ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์˜๊ฒฌ์„ ๋‚จ๊ฒผ๋‹ค.

Yes. In other words, any HTTP request message is allowed to contain a message body, and thus must parse messages with that in mind. Server semantics for GET, however, are restricted such that a body, if any, has no semantic meaning to the request. The requirements on parsing are separate from the requirements on method semantics.

So, yes, you can send a body with GET, and no, it is never useful to do so.
This is part of the layered design of HTTP/1.1 that will become clear again once the spec is partitioned (work in progress).

๋ชจ๋“  HTTP ์š”์ฒญ ๋ฉ”์‹œ์ง€๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ message body๊ฐ€ ํฌํ•จ๋  ์ˆ˜ ์žˆ๋‹ค.
ํ•˜์ง€๋งŒ, 'GET'์— ๋Œ€ํ•ด ์˜๋ฏธ๋ก ์ ์ธ ๊ด€์ ์œผ๋กœ ๋ณด์•˜์„ ๋•Œ, body๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ ์š”์ฒญ์— ๋Œ€ํ•ด์„œ ๋ณ„๋‹ค๋ฅธ ์˜๋ฏธ๊ฐ€ ์—†๋„๋ก ์ œํ•œ๋œ๋‹ค.
๊ทธ๋ž˜์„œ GET์œผ๋กœ body๋ฅผ ๋‹ด์•„ ๋ณด๋‚ผ ์ˆ˜๋Š” ์žˆ์ง€๋งŒ, ์‚ฌ์‹ค์ƒ ์ข‹์ง€ ์•Š์€ ์„ค๊ณ„๋ผ๊ณ  ๋งํ–ˆ๋‹ค. (HTTP/1.1 ๊ธฐ์ค€)
 
์‹ค์ œ๋กœ, HTTP/1.1 spec์— ๊ฐ€๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ •์˜๋˜์–ด ์žˆ๋‹ค.

The GET method means retrieve whatever information ([...]) is identified by the Request-URI

๊ฒฐ๊ณผ์ ์œผ๋กœ GET ๋ฉ”์„œ๋“œ๋Š” Request-URI๋ฅผ ํ†ตํ•ด ์‹๋ณ„๋˜๋Š” ์ •๋ณด๋ฅผ ๊ฒ€์ƒ‰ํ•˜๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•œ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค.
 
ํ•˜์ง€๋งŒ, 2014๋…„๋ถ€ํ„ฐ HTTP/1.1์˜ ๊ธฐ๋ณธ ์ŠคํŽ™์ด์—ˆ๋˜ RFC2616์ด ์ œ๊ฑฐ๋˜๊ณ , RFC 7230-7237๋กœ ๋Œ€์ฒด๋˜์—‡๋‹ค.
๊ธฐ์กด์— ์กด์žฌํ•˜๋˜ "the message-body SHOULD be ignored when handling the request" ๋ผ๋Š” ๋ฌธ๊ตฌ๊ฐ€ ์ œ๊ฑฐ๋˜๊ณ , ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ฌธ๊ตฌ๊ฐ€ ์ถ”๊ฐ€๋˜์—ˆ๋‹ค.

๐ŸŒฑ Request message framing is independent of method semantics, even if the method doesn't define any use for a message body.

์š”์ฒญ ๋ฉ”์‹œ์ง€์— ๋Œ€ํ•œ ํ”„๋ ˆ์ž„์€ ์ด์ œ method์˜ ์˜๋ฏธ๋ก ์  ๊ด€์ ๊ณผ ๋…๋ฆฝ์ ์ด๋ฉฐ, ํ•ด๋‹น ๋ฉ”์„œ๋“œ๊ฐ€ message body์— ๋Œ€ํ•ด ์ •์˜ํ•˜์ง€ ์•Š๋”๋ผ๋„ ์ƒ๊ด€์—†๋‹ค๋ผ๊ณ  ๋‚˜์™€ ์žˆ๋‹ค. ๋˜ํ•œ ์•ž์„œ ์–ธ๊ธ‰ํ–ˆ๋˜ The GET method means retrieve whatever information ([...]) is identified by the Request-URI ์— ๋Œ€ํ•œ ๋ถ€๋ถ„๋„ ์ œ๊ฑฐ๋˜์—ˆ๊ธฐ ๋•Œ๋ฌธ์—, ๊ฒฐ๊ณผ์ ์œผ๋กœ ์ƒ๊ฐํ•ด๋ณธ๋‹ค๋ฉด ์˜๋ฏธ๋ก ์  ๊ด€์ ์—์„œ ๋ณด์•˜์„ ๋•Œ๋„ GET ์š”์ฒญ์— request body๊ฐ€ ๋“ค์–ด๊ฐ€๋„ ์ƒ๊ด€์ด ์—†๋‹ค๋Š” ๊ฒƒ์ด๋‹ค.
 
ํ•˜์ง€๋งŒ, ์ƒ๊ด€์€ ์—†๋‹ค๋งŒ body๊ฐ€ ํŠน๋ณ„ํ•œ ์˜๋ฏธ๋ฅผ ๊ฐ€์ง€๋Š” ๊ฒƒ์€ ์•„๋‹ˆ๋‹ค. RFC7231์—์„œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ •์˜๋˜์–ด ์žˆ๋‹ค.

A payload within a GET request message has no defined semantics;
sending a payload body on a GET request might cause some existing implementations to reject the request.

GET ์š”์ฒญ์˜ request message์—๋Š” ์ •์˜๋œ ์˜๋ฏธ๊ฐ€ ์—†๊ธฐ ๋•Œ๋ฌธ์—, GET ์š”์ฒญ์— body๋ฅผ ๋„ฃ์—ˆ์„ ๊ฒฝ์šฐ ๊ธฐ์กด์˜ ๊ตฌํ˜„์ฒด์—์„œ๋Š” ์š”์ฒญ์„ ๊ฑฐ๋ถ€ํ•  ์ˆ˜๋„ ์žˆ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค.
 
์‹ค์ œ๋กœ ES์—์„œ๋Š” GET ์š”์ฒญ์—์„œ body๋ฅผ ํ™œ์šฉํ•˜๋Š” ๊ฒฝ์šฐ๋„ ์žˆ๋‹ค.

์—ฌ๊ธฐ์„œ๋„ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ RFC 7231์˜ ๋‚ด์šฉ์„ ์–ธ๊ธ‰ํ•˜๋ฉฐ, GET with body๋ฅผ ํ†ตํ•ด ๊ฒ€์ƒ‰ํ•˜๋Š” ๊ฒƒ์„ ์„ ํ˜ธํ•œ๋‹ค๊ณ  ํ–ˆ๋‹ค ๐Ÿ˜€
 
๊ทธ๋ž˜์„œ ๊ฒฐ๊ณผ์ ์œผ๋กœ ๋‚˜๋Š” ์ด๋ ‡๊ฒŒ ๊ฒฐ๋ก  ๋‚ด๋ ธ๋‹ค.
body์— ๋„ฃ์„ ์ˆ˜๋Š” ์žˆ๊ณ , ์ด๊ฒŒ ์ •์˜๋œ ์‚ฌํ•ญ์—์„œ๋Š” ์œ„๋ฐ˜๋˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋‹ค.
๋‹ค๋งŒ, ๊ธฐ์กด์—๋Š” ๊ธˆ์ง€๊ฐ€ ๋˜์—ˆ๋˜ ๊ฒŒ ์ผ๋ฐ˜์ ์ด๊ธฐ ๋•Œ๋ฌธ์— ๊ธฐ์กด ๊ตฌํ˜„์ฒด๋“ค์˜ ๊ฒฝ์šฐ body๋ฅผ ๋‹ด์•„ GET์„ ๋ณด๋‚ด๋ฉด ๊ฑฐ์ ˆ๋‹นํ•  ์ˆ˜๊ฐ€ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์‹ ์ค‘ํ•˜๊ฒŒ ์‚ฌ์šฉํ•  ํ•„์š”๊ฐ€ ์žˆ๋‹ค. (๋˜ํ•œ, ํ†ต์ƒ์ ์œผ๋กœ ์‚ฌ๋žŒ๋“ค์ด ์ƒ๊ฐํ•˜๋Š” ๊ด€๋…์ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์›ฌ๋งŒํ•˜๋ฉด ๋ฆฌ์†Œ์Šค์˜ ์š”์ฒญ์œผ๋กœ๋งŒ ์‚ฌ์šฉํ•˜๋ ค๊ณ  ํ•œ๋‹ค)
 


โœ”๏ธ POST

The POST method requests that the target resource process the representation enclosed in the request according to the semantics of the target resource. 

POST๋Š” ํƒ€๊ฒŸ ๋ฆฌ์†Œ์Šค๊ฐ€ ์š”์ฒญ์— ํ‘œํ˜„๋œ ๊ฒƒ์„ ํƒ€๊ฒŸ ๋ฆฌ์†Œ์Šค์˜ ์˜๋ฏธ์— ๋”ฐ๋ผ์„œ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•œ๋‹ค.
 
RFC7231์—์„œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ƒํ™ฉ์—์„œ ์‚ฌ์šฉํ•˜๋ผ๊ณ  ๋งํ•œ๋‹ค.
1. HTML form์— ์ž…๋ ฅํ•œ ํ•„๋“œ์˜ ๊ฐ’๋“ค์— ๋Œ€ํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ์ œ๊ณตํ•  ๋•Œ
2. ๊ฒŒ์‹œํŒ, ๋ฉ”์ผ๋ง, ๋ธ”๋กœ๊ทธ ๊ฐ™์€ ๊ธ€ ๊ด€๋ จ ๋ฉ”์‹œ์ง€๋ฅผ ์ž‘์„ฑํ•  ๋•Œ
3. origin ์„œ๋ฒ„์—์„œ ์‹๋ณ„๋˜์ง€ ์•Š์€ ์ƒˆ๋กœ์šด ๋ฆฌ์†Œ์Šค๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๊ฒฝ์šฐ
4. ์ด๋ฏธ ์กด์žฌํ•˜๋Š” ๋ฆฌ์†Œ์Šค์— ๋Œ€ํ•ด์„œ ๋ง๋ถ™์ผ ๋•Œ 
 
์ž˜ ์ƒ๊ฐํ•ด๋ณด๋ฉด, ๋ชจ๋‘ ๋‹ค '๋ฐ์ดํ„ฐ๋ฅผ ์ „์†กํ•œ๋‹ค'๋ผ๋Š” ๊ด€์ ์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
POST ๋ฐฉ์‹์˜ ๊ฒฝ์šฐ request body ๊ฐ’์— ๋ฐ์ดํ„ฐ๋ฅผ ๋„ฃ์–ด์„œ ๋ณด๋‚ด๋Š” ๊ฒƒ์ด ์ผ๋ฐ˜์ ์ด๋‹ค.
 
ํ•˜์ง€๋งŒ, POST ๋ฐฉ์‹์ด๋”๋ผ๋„ ๋ฐ์ดํ„ฐ ๊ฒ€์ƒ‰์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
๊ฒ€์ƒ‰ ์กฐ๊ฑด์ด ๋งค์šฐ ๊นŒ๋‹ค๋กœ์›Œ์„œ URL์— ๋ถ™์—ฌ์งˆ ๋ฐ์ดํ„ฐ๊ฐ€ ๋งŽ์•„์งˆ ๊ฒฝ์šฐ, POST๋ฅผ ๊ณ ๋ คํ•  ์ˆ˜ ์žˆ๋‹ค.
๊ธฐ๋ณธ์ ์œผ๋กœ ๋ธŒ๋ผ์šฐ์ €๋Š” ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š” URL์˜ ๊ธธ์ด๊ฐ€ ์ œํ•œ์ด ์žˆ์œผ๋ฉฐ, ๋ณดํ†ต ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋„˜์–ด๊ฐ„ ๊ฐ’๋“ค์€ ์ธ์ฝ”๋”ฉ ์‹œ ๊ธ€์ž์ˆ˜๊ฐ€ ๋” ๋Š˜์–ด๋‚˜๊ธฐ ๋•Œ๋ฌธ์— ๋” ์ฃผ์˜ํ•ด์•ผ ํ•œ๋‹ค. Apache HTTP ์„œ๋ฒ„๋Š” ์ตœ๋Œ€ 4000์ž, Microsoft Internet Explorer๋Š” ์ตœ๋Œ€ 2048์ž๋ฅผ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.
 
๋˜ํ•œ, ์‚ฌ์šฉ์ž์˜ ์ด๋ฆ„์ด๋‚˜ ๋น„๋ฐ€๋ฒˆํ˜ธ ๊ฐ™์€ ์ •๋ณด ๊ฐ™์ด ๋ฏผ๊ฐํ•œ ์ •๋ณด๋Š” URL๋กœ ๋ณด๋‚ด์ง€ ์•Š๋Š” ๊ฒƒ์ด ์ข‹๋‹ค. 
HTTPS๋ฅผ ์‚ฌ์šฉํ•˜๋”๋ผ๋„ ๋ธŒ๋ผ์šฐ์ € ๊ธฐ๋ก์ด๋‚˜ ์›น ์„œ๋ฒ„ ๋กœ๊ทธ์— ์ „์ฒด URL์ด ํฌํ•จ๋  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์ด๋Ÿฐ ๊ฒฝ์šฐ ๋ณดํ†ต POST๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.
(๋‹จ, URL์— ๋ฐ์ดํ„ฐ๊ฐ€ ๋…ธ์ถœ๋˜์ง€ ์•Š์Œ์œผ๋กœ ๋ณด์•ˆ์„ฑ์€ ์ฆ๊ฐ€ํ•˜์ง€๋งŒ ์บ์‹ฑ์€ ๋˜์ง€ ์•Š๋Š”๋‹ค๋Š” ๊ฒƒ์ด ํŠน์ง•์ด๋‹ค)
 


โœ”๏ธ GET with URI

๐ŸŒฑ GET - query Parameter

๋งŒ์•ฝ GET ํ†ตํ•ด ๋ฆฌ์†Œ์Šค๋ฅผ ๋“ฑ๋กํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด ์ฟผ๋ฆฌ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
์‹ค์Šต์„ ์œ„ํ•ด ๊ฐ„๋‹จํ•œ html์„ ๊ตฌ์„ฑํ•˜์˜€๋‹ค.

๊ทธ๋ƒฅ ์ด๋ฆ„์ด๋ž‘ ๋‚˜์ด ๋„ฃ๊ณ  ์ œ์ถœํ•  ์ˆ˜ ์žˆ๋Š” form์ด๋‹ค.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<form action="/test" method="get">
    ์ด๋ฆ„: <label>
    <input type="text" name="name"/>
</label>
    ๋‚˜์ด: <label>
    <input type="text" name="age"/>
</label>
    ์ œ์ถœํ•˜๊ธฐ: <input type="submit", value="submit">
</form>
</body>
</html>

 
๊ทธ๋ฆฌ๊ณ , ์ด์— ๋Œ€์‘ํ•˜๋Š” ์ปจํŠธ๋กค๋Ÿฌ๋ฅผ ๋งŒ๋“ค์–ด๋ณด์ž.

@RestController
public class Controller {

    @GetMapping("/test")
    public void test(@RequestParam("name") String name, @RequestParam("age") int age) {
        System.out.println("name = " + name);
        System.out.println("age = " + age);
    }
}

์ •๋ง ๊ฐ„๋‹จํ•œ ์ปจํŠธ๋กค๋Ÿฌ์ด๋‹ค.
์ด์ œ ์š”์ฒญ์„ ๋‚ ๋ ค๋ณด์ž. ์–ด๋–ค ์‹์œผ๋กœ ๋™์ž‘ํ•˜๊ฒŒ ๋ ๊นŒ?

submit์„ ๋ˆ„๋ฅด๋ฉด ์œ„์™€ ๊ฐ™์ด name๊ณผ age๋ผ๋Š” ์ฟผ๋ฆฌ ํŒŒ๋ผ๋ฏธํ„ฐ๊ฐ€ ๋ถ™์€ ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

๋˜ํ•œ, ๊ฐ’์— ๋Œ€ํ•œ ๋ฐ”์ธ๋”ฉ ์—ญ์‹œ ์ž˜ ๋œ ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.
 
 


๐ŸŒฑ POST - query parameter

๋งŒ์•ฝ, Post๋กœ ์š”์ฒญ์„ ๋ฐ”๊พธ๋ฉด ์–ด๋–ป๊ฒŒ ๋ ๊นŒ?
html ํŒŒ์ผ์˜ method ๋ถ€๋ถ„์„ post๋กœ ๋ฐ”๊พธ๊ณ , ์ปจํŠธ๋กค๋Ÿฌ ์—ญ์‹œ @PostMapping์„ ํ™œ์šฉํ•˜๋„๋ก ๋ฐ”๊พธ์–ด๋ณด์ž.

@PostMapping("/test")
public void test(@RequestParam("name") String name, @RequestParam("age") int age) {
    System.out.println("name = " + name);
    System.out.println("age = " + age);
}

์ด๋ฒˆ์—๋Š” ์ œ์ถœํ•˜๋”๋ผ๋„ ๋ณ„๋‹ค๋ฅธ ์ฟผ๋ฆฌ ํŒŒ๋ผ๋ฏธํ„ฐ๊ฐ€ ๋ถ™์ง€ ์•Š๊ฒŒ ๋œ๋‹ค.

ํ•˜์ง€๋งŒ ๊ฐ’์— ๋Œ€ํ•œ ๋ฐ”์ธ๋”ฉ์˜ ๊ฒฝ์šฐ ์ž˜ ๋˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด ๊ฐ’๋“ค์€ ์–ด๋””์— ์ €์žฅ๋œ ๊ฑธ๊นŒ?

์šฐ์„ , request์˜ content-type์„ ๋ณด๋ฉด x-www-form-urlencoded ํƒ€์ž…์œผ๋กœ ์ง€์ •๋œ ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ  ํŽ˜์ด๋กœ๋“œ๋ฅผ ๋ณด๋ฉด ์œ„์™€ ๊ฐ™์ด form data๋กœ ์„ค์ •๋œ ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค!
application/x-www-form-urlencoded์˜ ๊ฒฝ์šฐ POST ์š”์ฒญ์œผ๋กœ ์ฟผ๋ฆฌ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ ์ „์†ก๋˜๋Š” ํƒ€์ž…์ด๋ผ๊ณ  ๋ณผ ์ˆ˜ ์žˆ๋‹ค.
๊ทธ๋ ‡๋‹ค๊ณ  ํ•ด์„œ ์ฟผ๋ฆฌ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋ณด๋‚ด๋Š” ๊ฒƒ๊ณผ ๋™์ผํ•œ ๊ฒƒ์€ ์•„๋‹ˆ๋‹ค. 
๋‹จ์ง€, body ๊ฐ’์˜ ์š”์ฒญ์œผ๋กœ ๋„ฃ์„ ๋•Œ content-type์ด application/x-www-form-urlencoded์ธ ๊ฒƒ๋ฟ์ด๋‹ค.

์‹ค์ œ๋กœ ์Šค๋‹ˆํŽซ ๊ฐ™์€ ๊ฒฝ์šฐ๋„ ์œ„์™€ ๊ฐ™์ด body ๊ฐ’์— key-value ํ˜•์‹์œผ๋กœ ์ „์†ก๋œ๋‹ค. ๐Ÿ˜€
์ฆ‰, POST๋กœ๋„ request parameter๋ฅผ ํ†ตํ•ด ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์ด ํ™•์ธ๋˜์—ˆ๋‹ค.
 


๐ŸŒฑ POST - multipart/form-data

ํ•˜์ง€๋งŒ ์•„๊นŒ form ํƒœ๊ทธ๋ฅผ ํ™œ์šฉํ–ˆ์„ ๋•Œ๋Š” multipart/form-data๋กœ ๊ฐ’์ด ๋„˜์–ด๊ฐ”์—ˆ๋‹ค. 
๊ทธ๋Ÿฌ๋ฉด multipart/form-data๋กœ ๋ณด๋‚ธ ์š”์ฒญ์€ @RequestParam์œผ๋กœ ๋ฐ›์„ ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์ผ๊นŒ?

๊ถ๊ธˆํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋ฐ”๋กœ ํ•ด๋ณด์•˜๋‹ค.

์˜ค... ๋ฐ”์ธ๋”ฉ์ด ๋งค์šฐ ์ž˜ ๋œ๋‹ค! body ๊ฐ’์œผ๋กœ ๋‹ด๊ธด multipart/form-data๋„ @RequestParam์œผ๋กœ ๋ฐ›์„ ์ˆ˜ ์žˆ๋‹ค๋Š” ์‚ฌ์‹ค์„ ๊นจ๋‹ฌ์•˜๋‹ค.
์‹ค์ œ๋กœ ๊ณต์‹ ๋ฌธ์„œ๋ฅผ ๊ฐ€๋ณด๋‹ˆ๊นŒ, @RequestParam์— ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ž‘์„ฑ๋˜์–ด ์žˆ์—ˆ๋‹ค.
 

In Spring MVC, "request parameters" map to query parameters, form data, and parts in multipart requests. This is because the Servlet API combines query parameters and form data into a single map called "parameters", and that includes automatic parsing of the request body.

Spring MVC์—์„œ ๋งํ•˜๋Š” web request parameter๋ž€, ์ฟผ๋ฆฌ ํŒŒ๋ผ๋ฏธํ„ฐ์™€, form-data, multipart request์—์„œ ๊ฐ๊ฐ์˜ part ๋ฐ์ดํ„ฐ๋“ค์ด ๋งคํ•‘๋œ๋‹ค๊ณ  ํ•œ๋‹ค. ์ด์œ ๋Š”? ์„œ๋ธ”๋ฆฟ API๊ฐ€ ์ฟผ๋ฆฌ ํŒŒ๋ผ๋ฏธํ„ฐ์™€ form data๋ฅผ "parameters"๋ผ๊ณ  ๋ถˆ๋ฆฌ๋Š” ๋‹จ์ผ map์œผ๋กœ ๊ฒฐํ•ฉํ•˜๊ณ , request body์˜ ์ž๋™ ๊ตฌ๋ฌธ ๋ถ„์„์„ ํฌํ•จํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค! (์ด ๋ถ€๋ถ„์€ ์ฒ˜์Œ ์•Œ์•„์„œ ์—„์ฒญ ๋†€๋ž๋‹ค.)


 

๐ŸŒฑ POST - query parameter with form data

๊ทธ๋ ‡๋‹ค๋ฉด, form data์™€ ์ฟผ๋ฆฌ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ๋™์‹œ์— ๋„ฃ์œผ๋ฉด ์–ด๋–ป๊ฒŒ ์š”์ฒญ์ด ์˜ฌ๊นŒ? ์ด๊ฒƒ๋„ ๊ถ๊ธˆํ•ด์„œ ์‹คํ—˜ํ•ด๋ณด์•˜๋‹ค.
 
1. form data์™€ query parameter๋กœ ๋ฐ›๋Š” ๊ฐ’์˜ ์ด๋ฆ„์ด ๋‹ค๋ฅผ ๋•Œ

์œ„์™€ ๊ฐ™์ด ์š”์ฒญ์„ ๋ณด๋‚ด๋ณด์•˜๋‹ค.

๋ฐ”์ธ๋”ฉ๋„ ๋งค์šฐ ์ž˜ ๋˜์—ˆ๋‹ค. ๊ทธ๋ ‡๋‹ค๋ฉด, GET ์š”์ฒญ์œผ๋กœ ๋ณด๋ƒˆ์„ ๋•Œ๋Š” ์–ด๋–ป๊ฒŒ ๋‚˜์˜ฌ๊นŒ?

๋‹น์—ฐํžˆ ๋˜์ง€ ์•Š๋Š”๋‹ค. GET ์š”์ฒญ์—์„œ๋Š” name, age, name2, age2 ๋ชจ๋‘ ๋‹ค ์ฟผ๋ฆฌ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋“ค์–ด์˜ค๊ธฐ๋ฅผ ์˜ˆ์ƒํ•˜๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.
 
 
2. form data์™€ query parameter๋กœ ๋ฐ›๋Š” ๊ฐ’์˜ ์ด๋ฆ„์ด ๊ฐ™์„ ๋•Œ

์š”์ฒญ์„ ํ•œ ๋ฒˆ ๋‚ ๋ ค๋ณด์ž.

๊ต‰์žฅํžˆ ์‹ ๊ธฐํ•œ ๊ฒฐ๊ณผ๊ฐ€ ๋‚˜์™”๋‹ค! name์˜ ๊ฒฝ์šฐ ,์œผ๋กœ ๊ตฌ๋ถ„๋œ ๊ฒฐ๊ณผ๊ฐ€ ๋‚˜์™”์ง€๋งŒ, age์˜ ๊ฒฝ์šฐ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋„˜๊ธด ๊ฐ’๋งŒ ๋“ค์–ด๊ฐ”๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.
์™œ์ธ์ง€ ๊ถ๊ธˆํ•ด์„œ ๊นŒ๋ณด๋ ค๊ณ  ํ–ˆ๋Š”๋ฐ, ์ด๊ฑฐ๋Š” ์ฝ”๋“œ ๋ ˆ๋ฒจ๋กœ ๋“ค์–ด๊ฐ€์•ผ ํ•  ๊ฒƒ ๊ฐ™์•„์„œ ์šฐ์„  ๋‹ค์Œ ํฌ์ŠคํŒ…์—์„œ ์•Œ์•„๋ณด๊ณ ์ž ํ•œ๋‹ค.
 
๋งŒ์•ฝ GET์œผ๋กœ ์š”์ฒญํ•œ๋‹ค๋ฉด ์–ด๋–ป๊ฒŒ ๋ ๊นŒ?
 

body์— ๋“ค์–ด์žˆ๋Š” ๊ฐ’์€ ๋ฌด์‹œ๋˜๊ณ , ์ฟผ๋ฆฌ ํŒŒ๋ผ๋ฏธํ„ฐ์˜ ๊ฐ’๋งŒ ๋ฐ›๋Š”๋‹ค.
 


๐ŸŒฑ ํŒŒ์ผ ์—…๋กœ๋“œ์™€ request parameter

๊ทธ๋ ‡๋‹ค๋ฉด, ํŒŒ์ผ ์—…๋กœ๋“œ ๊ธฐ๋Šฅ์„ ํ•˜๊ธฐ ์œ„ํ•ด form tag๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด ์ •์ƒ์ ์œผ๋กœ ์š”์ฒญ์ด ๊ฐˆ๊นŒ?

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<form action="/test" method="post">
    ํŒŒ์ผ: <input type="file" name="file">
    ์ œ์ถœํ•˜๊ธฐ: <input type="submit" value="submit">
</form>
</body>
</html>

์•„๊นŒ์™€ ๋น„์Šทํ•˜์ง€๋งŒ ๋งค์šฐ ์‹ฌํ”Œํ•œ ํŒŒ์ผ ์—…๋กœ๋“œ html์„ ๋งŒ๋“ค์—ˆ๋‹ค.

@RestController
public class Controller {

    @PostMapping("/test")
    public void test(@RequestParam("file") MultipartFile file) {
        System.out.println(file.getOriginalFilename());
    }
}

Get ์š”์ฒญ์„ ํ†ตํ•ด์„œ ํŒŒ์ผ์„ ๋ฐ›์•„๋ณด์ž.

ํŒŒ์ผ ์—…๋กœ๋“œ ์‹œ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค. ํŒŒ์ผ์˜ ๊ฒฝ์šฐ GET ์š”์ฒญ์œผ๋กœ ๋ฐ›์„ ์ˆ˜ ์—†๋Š” ๊ฒƒ์ด๋‹ค.
 
POST๋กœ ๋ณ€๊ฒฝํ•ด๋ณด์ž.

๊ฐ™์€ ์ด๋ฏธ์ง€ ์•„๋‹˜

์—ฌ์ „ํžˆ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.
์•ž์„œ ๋งํ–ˆ๋˜ ๊ฒƒ์ฒ˜๋Ÿผ, POST์—์„œ @requestParam์„ ์“ธ ๊ฒฝ์šฐ application/x-www-form-urlencoded ๋ฐฉ์‹์œผ๋กœ ๋ฐ›๋Š”๋‹ค.
ํ•˜์ง€๋งŒ ํŒŒ์ผ ๊ฐ™์€ ๋ฐ”์ด๋„ˆ๋ฆฌ ๋ฐ์ดํ„ฐ๋ฅผ ์šฐ๋ฆฌ๊ฐ€ ์ธ์ฝ”๋”ฉํ•  ์ˆ˜ ์žˆ์„๊นŒ? ์•„๋‹ˆ๋‹ค.
 

The content type "application/x-www-form-urlencoded" is inefficient for sending large quantities of binary data or text containing non-ASCII characters. The content type "multipart/form-data" should be used for submitting forms that contain files, non-ASCII data, and binary data.

์• ์ดˆ์— W3C์— ๋”ฐ๋ฅด๋ฉด application/x-www-form-urlencoded์˜ ๊ฒฝ์šฐ, ๊ฐ„๋‹จํ•œ ํ…์ŠคํŠธ๋‚˜ ASCII ํ˜•์‹์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณด๋‚ด๋Š” ๊ฒƒ์ด๋ผ๊ณ  ์ •์˜ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ๋Œ€ํ˜• ๋ฐ”์ด๋„ˆ๋ฆฌ ๊ฐ’์˜ ๊ฒฝ์šฐ ์‚ฌ์šฉ์ด ๋ถˆ๊ฐ€๋Šฅํ•˜๋‹ค.
 
๊ทธ๋ž˜์„œ ํŒŒ์ผ ์—…๋กœ๋“œ ์‹œ ๋ฐ›๊ณ  ์‹ถ๋‹ค๋ฉด multipart/form-data๋ฅผ ํ™œ์šฉํ•ด์•ผ ํ•œ๋‹ค.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<form action="/test" method="post" enctype="multipart/form-data">
    ํŒŒ์ผ: <input type="file" name="file">
    ์ œ์ถœํ•˜๊ธฐ: <input type="submit" value="submit">
</form>
</body>
</html>

form ํƒœ๊ทธ์˜ enctype์—์„œ multipart/form-data๋กœ ๋ณ€๊ฒฝํ•˜์ž.

๊ทธ๋ฆฌ๊ณ  ๋‹ค์‹œ ์š”์ฒญ์„ ๋ณด๋‚ด๋ฉด ์œ„์™€ ๊ฐ™์ด ์›๋ณธ ํŒŒ์ผ๋ช…์ด ์ž˜ ๋œจ๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.
 

์‹ค์ œ๋กœ Request Header์˜ ๊ฐ’์„ ๋ณด๋”๋ผ๋„ multipart/form-data ํ˜•ํƒœ๋กœ ์ž˜ ์ „๋‹ฌ๋˜๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.
 

@RestController
public class Controller {
    @PostMapping("/test")
    public void test(@RequestBody MultipartFile file) {
        System.out.println(file.getOriginalFilename());
    }
    
    // @PostMapping("/test")
    public void test(@RequestPart MultipartFile file) {
        System.out.println(file.getOriginalFilename());
    }
}

@RequestParam์ด ์•„๋‹ˆ๋”๋ผ๋„ @RequestBody, @RequestPart๋ฅผ ํ™œ์šฉํ•˜์—ฌ multipart/form-data ํ˜•ํƒœ์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›์„ ์ˆ˜ ์žˆ๋‹ค.
 

Comments