LUCATHREE.COM

โ† Back to list
๐Ÿง TIL

[๋ฐฑ์—”๋“œ ๊ธฐ๋ณธ ๊ฐœ๋… ์ •๋ฆฌ] REST API

์ž‘์„ฑ์ผ:
TILTerms

REST API

REST๋Š”ย ๋‘ ์‹œ์Šคํ…œ ๊ฐ„์˜ ํ†ต์‹ ์„ ์œ„ํ•œ ์•„ํ‚คํ…์ฒ˜ ์Šคํƒ€์ผ๋กœ, Representational State Transfer์˜ ์•ฝ์ž์ด๋‹ค. REST API๋Š” REST ์Šคํƒ€์ผ์„ ์‚ฌ์šฉํ•˜์—ฌ ๊ตฌํ˜„๋œ API๋ฅผ ๋ถ€๋ฅด๋Š” ๋ช…์นญ์ด๋‹ค.
REST๋Š” 2000๋…„ ๋กœ์ด ํ•„๋”ฉ(Roy Fielding)์˜ ๋…ผ๋ฌธ์—์„œ ์ œ์•ˆ๋˜์—ˆ๋Š”๋ฐ, ํ•ต์‹ฌ์€ ๋‹จ์ˆœํ•˜๋‹ค.
๋ฆฌ์†Œ์Šค๋ฅผ URI๋กœ ํ‘œํ˜„ํ•˜๊ณ , ์ƒํƒœ์˜ ์ „์†ก์„ HTTP๋กœ ์ˆ˜ํ–‰ํ•œ๋‹ค.
๋‹ค์‹œ ๋งํ•ด, REST๋Š” โ€œ๋ฌด์—‡์„ ์š”์ฒญํ• ์ง€โ€์™€ โ€œ์–ด๋–ป๊ฒŒ ์š”์ฒญํ• ์ง€โ€๋ฅผ ๊ตฌ๋ถ„ํ•˜์—ฌ ํ‘œํ˜„ํ•˜๋Š” ๊ทœ์น™์œผ๋กœ, ์›น์ƒ์˜ ์ž์›์„ URI๋กœ ์ •์˜ํ•˜๊ณ , GET, POST, PUT, DELETE ๋“ฑ์˜ HTTP ๋ฉ”์†Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•ด ์ž์›์˜ ์ƒํƒœ๋ฅผ ์ฃผ๊ณ ๋ฐ›๋Š” ์‹์œผ๋กœย ํด๋ผ์ด์–ธํŠธ์™€ ์„œ๋ฒ„๊ฐ€ ์ •ํ•ด์ง„ ๊ทœ์น™์— ๋”ฐ๋ผ ์„œ๋กœ ์š”์ฒญ๊ณผ ์‘๋‹ต์„ ์ฃผ๊ณ ๋ฐ›๋„๋ก ํ•œ๋‹ค.

REST API์˜ ํ•ต์‹ฌ์š”์†Œ

๋ฆฌ์†Œ์Šค (Resource)

๋ฆฌ์†Œ์Šค๋Š” ์‚ฌ์šฉ์ž, ๊ฒŒ์‹œ๊ธ€, ์ฃผ๋ฌธ ๋“ฑ ์„œ๋ฒ„๊ฐ€ ๋‹ค๋ฃจ๋Š” ๋ชจ๋“  ๋ฐ์ดํ„ฐ๋ฅผ ์˜๋ฏธํ•˜๋ฉฐ, ๊ณ ์œ ํ•œ ์‹๋ณ„์ž์ธ URI๋ฅผ ๊ฐ€์ง„๋‹ค.
GET /users GET /posts/42

HTTP ๋ฉ”์†Œ๋“œ

REST๋Š” HTTP ๋ฉ”์†Œ๋“œ๋ฅผ ์ด์šฉํ•ด ๋ฆฌ์†Œ์Šค์— ๋Œ€ํ•ด ์ˆ˜ํ–‰ํ•  ๋™์ž‘์„ ๋‚˜ํƒ€๋‚ธ๋‹ค.
์ผ๋ฐ˜์ ์ธ CRUD(Create, Read, Update, Delete) ์ž‘์—…์ด ์•„๋ž˜์™€ ๊ฐ™์ด ๊ฐ ๋ฉ”์†Œ๋“œ๋กœ ํ‘œํ˜„๋œ๋‹ค.
  • GET: ์กฐํšŒ(Read) โ€” ๋ฆฌ์†Œ์Šค๋ฅผ ๊ฐ€์ ธ์˜จ๋‹ค
  • POST: ์ƒ์„ฑ(Create) โ€” ์ƒˆ๋กœ์šด ๋ฆฌ์†Œ์Šค๋ฅผ ๋งŒ๋“ ๋‹ค
  • PUT: ์ „์ฒด ์ˆ˜์ •(Update) โ€” ๋ฆฌ์†Œ์Šค ์ „์ฒด๋ฅผ ๋ฎ์–ด์“ด๋‹ค
  • PATCH: ์ผ๋ถ€ ์ˆ˜์ •(Update) โ€” ๋ฆฌ์†Œ์Šค์˜ ์ผ๋ถ€๋ฅผ ๋ณ€๊ฒฝํ•œ๋‹ค
  • DELETE ์‚ญ์ œ(Delete) โ€” ๋ฆฌ์†Œ์Šค๋ฅผ ์ œ๊ฑฐํ•œ๋‹ค
// ์ƒˆ๋กœ์šด ์‚ฌ์šฉ์ž ๋ฆฌ์†Œ์Šค๋ฅผ ๋งŒ๋“ ๋‹ค. POST /users // ์ƒ์„ฑ๋˜์–ด ์žˆ๋Š” ์‚ฌ์šฉ์ž ๋ฆฌ์†Œ์Šค๋ฅผ ์กฐํšŒํ•œ๋‹ค GET /users/1

ํ‘œํ˜„ (Representation)

์ž์›์˜ ์ƒํƒœ๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ์ •๋ณด์˜ ํ˜•์‹์œผ๋กœ REST API๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ JSON์„ ์‚ฌ์šฉํ•œ๋‹ค.
  • ์š”์ฒญ
    • POST /users Content-Type: application/json { "name": "Lucas", "email": "clee0627@gmail.com" }
  • ์‘๋‹ต
    • HTTP/1.1 201 Created Content-Type: application/json { "id": 1, "name": "Lucas", "email": "clee0627@gmail.com" }
ย 

REST์˜ ํŠน์ง•๊ณผ ์žฅ์ 

  • Server-Client ๊ตฌ์กฐ: ์„œ๋ฒ„์™€ ํด๋ผ์ด์–ธํŠธ๋กœ ์ด๋ฃจ์–ด์ง„ ๊ตฌ์กฐ๋ฅผ ๊ฐ€์ง€๋ฉฐ ๋‘˜์€ ์„œ๋กœ ๋…๋ฆฝ์ ์œผ๋กœ ๊ฐœ๋ฐœ๋  ์ˆ˜ ์žˆ๋‹ค. ์ด๋กœ ์ธํ•ด ์‹œ์Šคํ…œ์˜ ํ™•์žฅ ๋ฐ ๋ณ€๊ฒฝ์ด ์šฉ์ดํ•˜๋‹ค.
  • ์ธํ„ฐํŽ˜์ด์Šค ์ผ๊ด€์„ฑ (Uniform Interface): ์š”์ฒญ์˜ ์˜๋ฏธ๋Š” HTTP ๋ฉ”์„œ๋“œ/์ƒํƒœ์ฝ”๋“œ/ํ•˜์ดํผ๋ฏธ๋””์–ด๋กœ ์ผ๊ด€๋˜๊ฒŒ ์ „๋‹ฌ๋œ๋‹ค. API์˜ ๋ช…ํ™•ํ•œ ์š”์ฒญ๊ณผ ์‘๋‹ต ๊ตฌ์กฐ ๋•๋ถ„์— ๊ฐœ๋ฐœ์ž๋“ค์ด API๋ฅผ ์ดํ•ดํ•˜๊ณ  ์‚ฌ์šฉํ•˜๋ฉฐ ์œ ์ง€๋ณด์ˆ˜ํ•˜๊ธฐ๊ฐ€ ์šฉ์ดํ•˜๋‹ค.
  • ๊ณ„์ธตํ™” (Layered System): ํด๋ผ์ด์–ธํŠธ์™€ ์„œ๋ฒ„ ๊ฐ„์˜ ํ†ต์‹ ์„ ์—ฌ๋Ÿฌ ๊ณ„์ธต์œผ๋กœ ๋ถ„๋ฆฌํ•˜์—ฌ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์‹ค์ œ ์„œ๋ฒ„๋ฅผ ์ง์ ‘ ์•Œ์ง€ ๋ชปํ•˜๊ฒŒ ํ•œ๋‹ค. ์ด ๊ณผ์ •์—์„œ ํด๋ผ์ด์–ธํŠธ๋Š” ์ค‘๊ฐ„ ๊ณ„์ธต(์บ์‹œ, ๊ฒŒ์ดํŠธ์›จ์ด)์ด ์žˆ์Œ์„ ์‹ ๊ฒฝ ์“ธ ํ•„์š”๊ฐ€ ์—†์œผ๋ฉฐ ์ด๋ฅผ ํ†ตํ•ด ํ™•์žฅ์„ฑ, ์œ ์—ฐ์„ฑ, ๋ณด์•ˆ์„ฑ์„ ๋†’์ธ๋‹ค.
  • ๋ฌด์ƒํƒœ (Statetless): ์„œ๋ฒ„๋Š” ํด๋ผ์ด์–ธํŠธ ์ƒํƒœ๋ฅผ ์œ ์ง€ํ•˜์ง€ ์•Š์œผ๋ฉฐ ๊ฐ ์š”์ฒญ์€ ํ•„์š”ํ•œ ๋ชจ๋“  ์ •๋ณด๋ฅผ ๋‹ด์•„์•ผ ํ•œ๋‹ค. ์ƒํƒœ๋ฅผ ์„œ๋ฒ„๊ฐ€ ๊ธฐ์–ตํ•  ํ•„์š”๊ฐ€ ์—†์œผ๋ฏ€๋กœ ์„œ๋ฒ„ ํ™•์žฅ์„ฑ๊ณผ ๊ฐ€์šฉ์„ฑ์ด ์ข‹๋‹ค.

๋‹จ์ ๊ณผ ํ•œ๊ณ„

REST๋Š” ๊ทœ์น™์ด ๋‹จ์ˆœํ•˜๊ณ  ๋ช…ํ™•ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋งŽ์ด ์‚ฌ์šฉ๋˜์ง€๋งŒ ์•„ํ‚คํ…์ฒ˜ ์Šคํƒ€์ผ์ผ ๋ฟ ์—„๊ฒฉํ•œ ํ‘œ์ค€ ๊ทœ์•ฝ์ด ์กด์žฌํ•˜์ง€๋Š” ์•Š๋Š”๋‹ค. ๊ทธ๋ž˜์„œ ๊ฐœ๋ฐœ์ž์˜ ์—ญ๋Ÿ‰์ด๋‚˜ ๊ด€์ ์— ๋”ฐ๋ผ ๋‹ค๋ฅด๊ฒŒ ์„ค๊ณ„๋  ์ˆ˜ ์žˆ๊ณ  REST์˜ ๊ธฐ๋ณธ ์›์น™์„ ์ง€ํ‚ค์ง€ ์•Š๊ณ ๋„ REST API ์ฒ˜๋Ÿผ ์‚ฌ์šฉ๋˜๋Š” ์•ˆํ‹ฐํŒจํ„ด์ด ์ ์šฉ๋  ๊ฐ€๋Šฅ์„ฑ์ด ๋†’๋‹ค.
๋˜ํ•œ ์š”์ฒญ๊ณผ ์‘๋‹ต์œผ๋กœ ์ด๋ฃจ์–ด์ง„ ๊ตฌ์กฐ์ƒ ๊ด€๊ณ„ ๋ฐ์ดํ„ฐ๊ฐ€ ๋ณต์žกํ•  ๊ฒฝ์šฐ ๋ฐ˜๋ณตํ•ด์„œ ์š”์ฒญ์„ ํ•ด์•ผํ•˜๊ฑฐ๋‚˜ ์‹ค์‹œ๊ฐ„์œผ๋กœ ๋ณ€๊ฒฝ๋˜๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์ง€์†์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•ด์•ผํ•˜๋Š” ๊ฒฝ์šฐ์—๋Š” ๋งž์ง€ ์•Š๋Š”๋‹ค. ๊ทธ๋ž˜์„œ ์ตœ๊ทผ์—๋Š” GraphQL, gRPC, WebSocket API ๊ฐ™์€ ๋‹ค๋ฅธ ์ ‘๊ทผ๋ฒ•์ด ํ•จ๊ป˜ ์‚ฌ์šฉ๋œ๋‹ค.

RESTful

์•ž์„œ ๋งํ–ˆ๋“ฏ REST๋Š” ์—„๊ฒฉํ•œ ํ‘œ์ค€ ๊ทœ์•ฝ์ด ์žˆ์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ์•ˆํ‹ฐํŒจํ„ด์ด ์ ์šฉ๋˜๊ธฐ ์‰ฝ๋‹ค. ๊ทธ๋ž˜์„œ REST ์•„ํ‚คํ…์ฒ˜ ์›์น™์„ ์ตœ๋Œ€ํ•œ ์ž˜ ์‹ค์ฒœํ•˜๋Š” ๊ฒƒ์„ โ€œRESTfulโ€์ด๋ผ๊ณ  ํ‘œํ˜„ํ•œ๋‹ค.
๋‹จ์ˆœํžˆ HTTP ๋ฉ”์†Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  URI๋กœ ๋ฆฌ์†Œ์Šค ๊ด€๊ณ„๋ฅผ ๋‚˜ํƒ€๋ƒˆ๋‹ค๊ณ  RESTful ํ•œ ๊ฒƒ์ด ์•„๋‹Œ๋ฐ, REST ์•„ํ‚คํ…์ฒ˜ ์›์น™์„ ์ž˜ ๋”ฐ๋ฅด๊ธฐ ์œ„ํ•ด์„œ๋Š” ๋ฆฌ์†Œ์Šค ์ค‘์‹ฌ ์„ค๊ณ„, ๋ฌด์ƒํƒœ์„ฑ, ์ผ๊ด€๋œ ์ธํ„ฐํŽ˜์ด์Šค, ๊ทธ๋ฆฌ๊ณ  ํ•˜์ดํผ๋ฏธ๋””์–ด(HATEOAS) ๊ฐ™์€ ๊ฐœ๋…์ด ์ž˜ ์ง€์ผœ์ ธ์•ผ ํ•œ๋‹ค.

HATEOAS (Hypermedia As The Engine Of Application State)

HATEOAS๋Š” REST ์›์น™ ์ค‘ ์ผ๊ด€๋œ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ง€ํ‚ฌ ์ˆ˜ ์žˆ๋„๋ก ํ•˜๊ธฐ ์œ„ํ•ด ๋‚˜์˜จ ๊ฐœ๋…์œผ๋กœ ๊ธฐ๋ณธ์ ์ธ ์•„์ด๋””์–ด๋Š” ํ•˜์ดํผ๋ฏธ๋””์–ด๋ฅผ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์ƒํƒœ๋ฅผ ๊ด€๋ฆฌํ•˜๊ธฐ ์œ„ํ•œ ์ˆ˜๋‹จ์œผ๋กœ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด๋‹ค.
๋” ์‰ฝ๊ฒŒ ํ‘œํ˜„ํ•˜๋ฉด, ์„œ๋ฒ„๊ฐ€ ์‘๋‹ต์— ๋‹ค์Œ ๊ฐ€๋Šฅํ•œ ํ–‰๋™(์ƒํƒœ ์ „ํ™˜)์„ ๋‚˜ํƒ€๋‚ด๋Š” ํ•˜์ดํผ๋งํฌ(๋งํฌ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ)๋ฅผ ํฌํ•จ์‹œ์ผœ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์Šค์Šค๋กœ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ํ๋ฆ„์„ ๋ฐœ๊ฒฌํ•˜๋„๋ก ํ•˜๋Š” ๋ฐฉ๋ฒ•์œผ๋กœ ํด๋ผ์ด์–ธํŠธ๋Š” ์„œ๋ฒ„ ์‘๋‹ต์—์„œ ์–ด๋–ค URL์„ ํ˜ธ์ถœํ•ด์•ผ ๋‹ค์Œ ํ–‰๋™์„ ํ•  ์ˆ˜ ์žˆ๋Š”์ง€์— ๋Œ€ํ•ด ํŒŒ์•…ํ•  ์ˆ˜ ์žˆ๋‹ค.

HATEOAS ๊ฐœ๋…์˜ ์˜๋„

  • ํด๋ผ์ด์–ธํŠธ-์„œ๋ฒ„ ๊ณ„์•ฝ์„ ๋А์Šจํ•˜๊ฒŒ ๋งŒ๋“ ๋‹ค โ€” ์„œ๋ฒ„๊ฐ€ ๊ฐ€๋Šฅํ•œ ํ–‰๋™์„ ๋งํฌ๋กœ ์ œ๊ณตํ•˜๋ฉด, ํด๋ผ์ด์–ธํŠธ๋Š” URL ๊ทœ์น™์„ ํ•˜๋“œ์ฝ”๋”ฉํ•˜์ง€ ์•Š์•„๋„ ๋œ๋‹ค.
  • ์„œ๋ฒ„ ์ˆ˜์ •, ์œ ์ง€๊ด€๋ฆฌ์— ์œ ๋ฆฌ โ€” ์„œ๋ฒ„๊ฐ€ ๋งํฌ ๊ตฌ์กฐ๋ฅผ ๋ฐ”๊ฟ”๋„ ํด๋ผ์ด์–ธํŠธ๋Š” ์‘๋‹ต์— ํฌํ•จ๋œ ๋งํฌ๋งŒ ๋”ฐ๋ฅด๋ฉด ๋œ๋‹ค.
  • ์‚ฌ์šฉ์ž ํ๋ฆ„(์›Œํฌํ”Œ๋กœ์šฐ)์„ ๋ช…์‹œ โ€” ํ˜„์žฌ ์ƒํƒœ์—์„œ ์–ด๋–ค ํ–‰๋™์ด ํ—ˆ์šฉ๋˜๋Š”์ง€, ์–ด๋–ค ๊ด€๊ณ„(์˜ˆ: cancel, next, approve)๊ฐ€ ์žˆ๋Š”์ง€ ํ‘œํ˜„ ๊ฐ€๋Šฅ.
์„œ๋ฒ„ ์‘๋‹ต ์˜ˆ์‹œ
{ "data": { "type": "articles", "id": "42", "attributes": { "title": "REST์™€ HATEOAS", "body": "..." } }, "links": { "self": "/articles/42", "comments": "/articles/42/comments", "author": "/users/7" }, "actions": { "edit": { "method": "PATCH", "href": "/articles/42", "title": "Edit this article" }, "delete": { "method": "DELETE", "href": "/articles/42" } } }
์ฆ‰, HATEOAS๋Š” ๊ฐœ๋ฐœ์ž๊ฐ€ ๋ณต์žกํ•œ API ๋ฌธ์„œ๋ฅผ ์ž‘์„ฑํ•˜๊ณ  ๊ทธ ๋‚ด์šฉ๊ณผ ๊ทœ์น™๋“ค์„ ํด๋ผ์ด์–ธํŠธ ์ชฝ์—์„œ ๋ชจ๋‘ ํŒŒ์•…ํ•˜๊ณ  ์žˆ์ง€ ์•Š์•„๋„ ๊ฐœ๋ฐœ์— ๋ฌธ์ œ๊ฐ€ ์—†๋„๋ก ํ•˜์—ฌ REST ์›์น™์„ ๋”ฐ๋ฅผ ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๋Š” ๋ฐฉ๋ฒ•์ด๋‹ค.
ย