1 ๋ถ„ ์†Œ์š”

GraphQL? ๐Ÿ‘€

GraphQL : Facebook์—์„œ ๋งŒ๋“  Graph Query Language๋กœ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋ ˆ์ด์–ด ์ฟผ๋ฆฌ ์–ธ์–ด์ด๋‹ค.

GQL์ฆ‰, API๋ฅผ ์œ„ํ•œ ์ฟผ๋ฆฌ ์–ธ์–ด์ด๋ฉฐ, ํƒ€์ž… ์‹œ์Šคํ…œ์„ ์‚ฌ์šฉํ•˜์—ฌ ์ฟผ๋ฆฌ๋ฅผ ์‹คํ–‰ํ•˜๋Š” ์„œ๋ฒ„์‚ฌ์ด๋“œ ๋Ÿฐํƒ€์ž„์ด๋‹ค.

GraphQL์€ ํŠน์ •ํ•œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋‚˜ ์Šคํ† ๋ฆฌ์ง€์— ๊ท€์†๋˜์–ด ์žˆ์ง€ ์•Š์œผ๋ฉฐ, ๊ธฐ์กด ์ฝ”๋“œ์™€ ๋ฐ์ดํ„ฐ์— ์˜ํ•ด ๋Œ€์ฒด๋œ๋‹ค.

(์ผ๋ฐ˜์ ์œผ๋กœ GQL์˜ ์ธํ„ฐํŽ˜์ด์Šค๊ฐ„ ์†ก์ˆ˜์‹ ์€ ๋„คํŠธ์›Œํฌ ๋ ˆ์ด์–ด L7์˜ HTTP POST ๋ฉ”์„œ๋“œ์™€ ์›น์†Œ์ผ“ ํ”„๋กœํ† ์ฝœ์„ ํ™œ์šฉํ•œ๋‹ค. ํ•„์š”์— ๋”ฐ๋ผ์„œ๋Š” ์–ผ๋งˆ๋“ ์ง€ L4์˜ TCP/UDP๋ฅผ ํ™œ์šฉํ•˜๊ฑฐ๋‚˜ ์‹ฌ์ง€์–ด L2 ํ˜•์‹์˜ ์ด๋”๋„ท ํ”„๋ ˆ์ž„์„ ํ™œ์šฉ ํ•  ์ˆ˜๋„ ์žˆ๋‹ค.)


GQL, SQL์˜ ์ฐจ์ด

SQL์€ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์‹œ์Šคํ…œ์— ์ €์žฅ๋œ ๋ฐ์ดํ„ฐ๋ฅผ ํšจ์œจ์ ์œผ๋กœ ๊ฐ€์ ธ์˜ค๋Š” ๊ฒƒ์ด ๋ชฉ์ ์ด๊ณ , GQL์€ ์›น ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋ฐ์ดํ„ฐ๋ฅผ ์„œ๋ฒ„๋กœ ๋ถ€ํ„ฐ ํšจ์œจ์ ์œผ๋กœ ๊ฐ€์ ธ์˜ค๋Š” ๊ฒƒ์ด ๋ชฉ์ ์ด๋‹ค.

SQL์˜ ๋ฌธ์žฅ(statement)์€ ์ฃผ๋กœ ๋ฐฑ์—”๋“œ ์‹œ์Šคํ…œ์—์„œ ์ž‘์„ฑํ•˜๊ณ  ํ˜ธ์ถœํ•˜๋Š” ๋ฐ˜๋ฉด, GQL์˜ ๋ฌธ์žฅ์€ ์ฃผ๋กœ ํด๋ผ์ด์–ธํŠธ ์‹œ์Šคํ…œ์—์„œ ์ž‘์„ฑํ•˜๊ณ  ํ˜ธ์ถœํ•œ๋‹ค.


REST API์˜ ํ•œ๊ณ„

REST API์˜ ๊ฐœ๋…์„ ๊ฐ„๋‹จํ•˜๊ฒŒ ๋งํ•˜์ž๋ฉด ๋ชจ๋“  Resource๋“ค์„ ํ•˜๋‚˜์˜ Endpoint์— ์—ฐ๊ฒฐํ•˜๊ณ  ์—ฐ๊ฒฐ๋œ Endpoint๋Š” Resource์™€ ๊ด€๋ จ๋œ ๋‚ด์šฉ๋งŒ ๊ด€๋ฆฌํ•˜๊ฒŒ ํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

์ด๋Š” ๋‹จ์ˆœํ•œ ์„œ๋น„์Šค์—์„œ๋Š” ์•„์ฃผ ์ข‹์ง€๋งŒ ๋ณต์žกํ•œ ์„œ๋น„์Šค๋‚˜ ํด๋ผ์ด์–ธํŠธ์˜ ์š”์ฒญ์‚ฌํ•ญ์— ๋”ฐ๋ผ Over-Fetching๊ณผ Under-Fetching์ด ๋ฐœ์ƒํ•œ๋‹ค.

๋˜ํ•œ REST API๋กœ ์—ฌ๋Ÿฌ ํ™˜๊ฒฝ์—์„œ ํ•„์š”ํ•œ ์ •๋ณด๋“ค์„ Resource ๋ณ„๋กœ Endpoint๋ฅผ ๊ฐ–๋„๋ก ๊ตฌํ˜„ํ•˜๋Š” ๊ฒƒ์€ ์–ด๋ ต๋‹ค.

ํ•œ๋งˆ๋””๋กœ ๋น„์Šทํ•˜์ง€๋งŒ Endpoint๊ฐ€ ๋‹ค๋ฅธ API๊ฐ€ ๋งŽ์ด ํŒŒ์ƒ๋œ๋‹ค.

  • Over-Fetching
GET /user/1/
response body
{
"user_no":1,
"user_name": "test",
"user_grade": "VVIP",
"zip": "11053",
"last_login_timetamp": "2019-08-08 12:11:44",
...
}

์—ฌ๊ธฐ์—์„œ ํด๋ผ์ด์–ธํŠธ๋Š” 1๋ฒˆ์— ํ•ด๋‹นํ•˜๋Š” ์œ ์ €์˜ ์ด๋ฆ„๋งŒ์„ ์‚ฌ์šฉํ•˜๊ณ ์ž ํ•œ๋‹ค๊ณ  ํ•ด๋„ ์œ ์ € ์ด๋ฆ„๋งŒ ๋ฐ˜ํ™˜ํ•˜๋Š” API๊ฐ€ ์—†๋‹ค๋ฉด ์œ„์™€ ๊ฐ™์€ /user/1/API๋ฅผ ํ˜ธ์ถœํ•œ ๋‹ค์Œ, user_name์„ ๊ฐ€์ ธ์™€ ์‚ฌ์šฉํ•ด์•ผํ•œ๋‹ค. ์ด ๋•Œ, user_grade, zip ๋“ฑ๋“ฑ์˜ ๋ฐ์ดํ„ฐ๋Š” ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ๋ฐ์ดํ„ฐ๋„ ๊ฐ™์ด ๋ฐ˜ํ™˜๋ฐ›๋Š”๋‹ค. ์ด๋Š” ๊ณง ๋ฆฌ์†Œ์Šค์˜ ๋‚ญ๋น„๋ผ๊ณ  ๋ณผ ์ˆ˜ ์žˆ๊ณ  ์ด์™€ ๊ฐ™์€ ๋‚ญ๋น„๋ฅผ Over-Fetching์ด๋ผ ๋ช…ํ•œ๋‹ค.

  • Under-Fetching
/user/1/
/cart/
/notification/
/wish/
...

์š”์ฒญ์— ๋งž๊ฒŒ ์œ ํšจํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณด์—ฌ์ฃผ๊ธฐ ์œ„ํ•ด ์—ฌ๋Ÿฌ API๋ฅผ ํ˜ธ์ถœํ•˜๊ฒŒ ๋˜๋Š” ๊ฒฝ์šฐ๋ฅผ Under-Fetching์ด๋ผ ํ•œ๋‹ค.


Example

์š”์ฒญ์ฟผ๋ฆฌ

query{
      user(user_no:1){
            user_name
      }
}

๋ฐ˜ํ™˜๋ฐ์ดํ„ฐ

{
      "data": {
            "user": {
                  "user_name": "jim",
            }
      }
}
  • ์žฅ์ 

    • ํด๋ผ์ด์–ธํŠธ๊ฐ€ ํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ๋งŒ ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์žˆ๋‹ค.
    • 1๋ฒˆ์˜ ํ˜ธ์ถœ๋กœ ์›ํ•˜๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ํ•œ๋ฒˆ์— ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๋‹ค.
    • REST API์˜ N+1 Problem์„ ํ•ด๊ฒฐ ํ•  ์ˆ˜ ์žˆ๋‹ค.
    • ํ™•์žฅ์ด ์šฉ์ด
  • ๋‹จ์ 

    • ๋ฐฑ์—”๋“œ, ํด๋ผ์ด์–ธํŠธ ๊ฐœ๋ฐœ์ž ์–‘์ชฝ ๋‹ค ๋Ÿฌ๋‹์ปค๋ธŒ๊ฐ€ ์žˆ๋‹ค.
    • ๋‹จ์ˆœํ•œ ์„œ๋น„์Šค์—์„œ๋Š” ์‚ฌ์šฉํ•˜๊ธฐ๊ฐ€ ๋ณต์žกํ•˜๋‹ค.
    • ๋Œ€๋ถ€๋ถ„์˜ ์–ธ์–ด์—์„œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋กœ ์ œ๊ณตํ•œ๋‹ค.
    • ์บ์‹ฑ ๊ธฐ๋Šฅ์˜ ๊ตฌํ˜„์ด ๋ณต์žกํ•˜๋‹ค.
    • ์š”์ฒญ์ด text๋กœ ๋‚ ์•„๊ฐ€๊ธฐ ๋•Œ๋ฌธ์— File ์ „์†ก ๋“ฑ์„ ๊ตฌํ˜„ํ•˜๊ธฐ๊ฐ€ ์–ด๋ ต๋‹ค.

์—…๋ฐ์ดํŠธ: