๋ธ”๋กœ๊ทธ

๐Ÿ•ธ GraphQL์€ WordPress๋ฅผ ์–ด๋–ป๊ฒŒ, ์–ด๋””์„œ ๊ฐœ์„ ํ•  ์ˆ˜ ์žˆ๋Š”๊ฐ€ โ€” REST API๋ฅผ ๋ณด์™„ํ•˜๋ฉฐ

Leonardo Losoviz
์ž‘์„ฑ์ž: Leonardo Losoviz ยท

์—…๋ฐ์ดํŠธ 2024๋…„ 1์›” 5์ผ: Gato GraphQL vs WP REST API ๋น„๊ต๋ฅผ ํ™•์ธํ•ด ๋ณด์„ธ์š”.

์ง€๋‚œ ์ฃผ๋ง์— ๋ธ”๋กœ๊ทธ ๊ฒŒ์‹œ๋ฌผ ๐Ÿฆธ๐Ÿฟโ€โ™‚๏ธ Gato GraphQL์ด ์ด์ œ PHP 8.0์—์„œ 7.1๋กœ ํŠธ๋žœ์ŠคํŒŒ์ผ๋ฉ๋‹ˆ๋‹ค๋ฅผ ๊ฒŒ์‹œํ–ˆ์Šต๋‹ˆ๋‹ค.

Reddit์˜ /r/php์—์„œ ๊ทธ ๊ฒŒ์‹œ๋ฌผ์„ ๊ณต์œ ํ•œ ํ›„, ์ปค๋ฎค๋‹ˆํ‹ฐ์—์„œ๋Š” WordPress์—์„œ GraphQL์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์˜ ๊ฐ€์น˜, WP REST API์™€์˜ ์ฐจ์ด์ , ๊ทธ๋ฆฌ๊ณ  WordPress์— ๋˜ ๋‹ค๋ฅธ API๋ฅผ ๋„์ž…ํ•˜๋Š” ๊ฒƒ์˜ ์ •๋‹น์„ฑ์— ๋Œ€ํ•ด ํ™œ๋ฐœํ•œ ํ† ๋ก ์ด ์‹œ์ž‘๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

๋Œ€๋ถ€๋ถ„์˜ ๋Œ“๊ธ€์€ ํ•ต์‹ฌ์„ ์ฐŒ๋ฅด๊ณ  ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•˜์ง€๋งŒ, ์ผ๋ถ€๋Š” ์ค‘์š”ํ•œ ์ •๋ณด๋ฅผ ๋†“์น˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. GraphQL์€ ๋‹จ์ˆœํ•œ ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ์•„๋‹ˆ๋ผ ๊ตฌํ˜„์ด๊ธฐ๋„ ํ•ฉ๋‹ˆ๋‹ค. ์ฆ‰, ์„œ๋กœ ๋‹ค๋ฅธ ์ œ๊ณต์—…์ฒด์˜ ์„œ๋กœ ๋‹ค๋ฅธ GraphQL ์„œ๋ฒ„๋Š” ๊ฐ๊ธฐ ๋‹ค๋ฅธ ํŠน์„ฑ์„ ์šฐ์„ ์‹œํ•˜๋„๋ก ์„ค๊ณ„๋˜์—ˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ GraphQL์ด ์ œ๊ณตํ•˜๋Š” ๊ฒƒ์ด๋‚˜ GraphQL ์—”์ง„์ด ์ž‘๋™ํ•˜๋Š” ๋ฐฉ์‹์— ๋Œ€ํ•ด ํ•ญ์ƒ ํ†ต์ผ๋œ ๊ธฐ๋Œ€๋ฅผ ๊ฐ–๊ฑฐ๋‚˜ ์™„์ „ํžˆ ์ดํ•ดํ•˜๊ธฐ๋Š” ์–ด๋ ต์Šต๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด, WordPress์™€ Laravel์—์„œ์˜ GraphQL ๊ฒฝํ—˜์€ ๋‹ค๋ฅด๋ฉฐ, WPGraphQL๊ณผ Gato GraphQL์ด๋ผ๋Š” ์„œ๋กœ ๋‹ค๋ฅธ ์„œ๋ฒ„๊ฐ€ ์ œ๊ณตํ•˜๋Š” ๊ฒฝํ—˜๋„ ๋‹ค๋ฆ…๋‹ˆ๋‹ค.

์ด ๊ธ€์€ Reddit ๊ฒŒ์‹œ๋ฌผ์˜ ์—ฌ๋Ÿฌ ๋Œ“๊ธ€์„ ๋‹ค๋ฃจ๋Š” ์ € ์ž์‹ ์˜ ๊ฒฌํ•ด์ž…๋‹ˆ๋‹ค.

GraphQL vs WP REST API

[์ •๋ง ๋‚˜์œ ์ƒ๊ฐ์ด๋‹ค] ์ด๋ฏธ ์ž์ฒด REST API๋ฅผ ์‚ฌ์šฉํ•˜๋Š” WordPress ์œ„์— GraphQL API๋ฅผ ์ถ”๊ฐ€ํ•˜๋‹ค๋‹ˆ. ๊ทธ๋ƒฅ REST API๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค. [์ถœ์ฒ˜]

REST API์™€ GraphQL ๋ชจ๋‘ ๋™์ผํ•œ ๋ชฉ์ ์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค. ์ฆ‰, ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ์ œ๊ณตํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ด๋ฅผ ๋‹ฌ์„ฑํ•˜๋Š” ๋ฐฉ์‹์€ ๋‹ค๋ฆ…๋‹ˆ๋‹ค. REST๋Š” ํŠน์ • ๋ฐ์ดํ„ฐ ์ง‘ํ•ฉ์„ ์ œ๊ณตํ•˜๋Š” ๋ฏธ๋ฆฌ ์ •์˜๋œ ์—”๋“œํฌ์ธํŠธ๋ฅผ ๊ฐ–๋Š” ๋ฐ˜๋ฉด, GraphQL์€ ํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ๋งŒ ์ •ํ™•ํ•˜๊ฒŒ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

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

GraphQL์€ ์ด ์ƒํ™ฉ์„ ๊ฐœ์„ ํ•ฉ๋‹ˆ๋‹ค. ๊ฒŒ์‹œ๋ฌผ๊ณผ ์ž‘์„ฑ์ž ๋ฐ์ดํ„ฐ ์ „์ฒด๋ฅผ ๋‹จ์ผ ์š”์ฒญ์œผ๋กœ ์ง์ ‘ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ์–ด ์›นํŽ˜์ด์ง€ ๋ Œ๋”๋ง์ด ๋” ๋นจ๋ผ์ง‘๋‹ˆ๋‹ค.

{
  posts {
    id
    title
    excerpt
    date
    url
    author {
      id
      name
      url
    }
  }
}

WordPress์— REST API๊ฐ€ ์ด๋ฏธ ์žˆ๋‹ค๊ณ  ํ•ด์„œ, ๊ทธ๊ฒƒ์ด ๋ชจ๋“  ์ž‘์—…์— ํ•ญ์ƒ ๊ฐ€์žฅ ์ ํ•ฉํ•œ ๋„๊ตฌ๋ผ๋Š” ์˜๋ฏธ๋Š” ์•„๋‹™๋‹ˆ๋‹ค. ๋ฌผ๋ก  ํ•ญ์ƒ ์‚ฌ์šฉํ•  ์ˆ˜๋Š” ์žˆ์ง€๋งŒ, GraphQL์—๋„ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋‹ค๋ฉด REST๋ณด๋‹ค ์œ ๋ฆฌํ•œ ์ƒํ™ฉ์—์„œ ์ด API๋ฅผ ์„ ํƒํ•ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ๋” ๋‚˜์€ ๊ฒฐ๊ณผ๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

GraphQL์˜ ์–ด๋ ค์šด ์ดˆ๊ธฐ ์„ค์ • + ๋ฆฌ์กธ๋ฒ„ ์ž‘์„ฑ

GraphQL์˜ ์ดˆ๊ธฐ ์„ค์ •์ด REST์— ๋น„ํ•ด ๊ธฐํ•˜๊ธ‰์ˆ˜์ ์œผ๋กœ ๋†’๋‹ค๋Š” ์ฃผ์žฅ์€ ๋ถ„๋ช…ํžˆ ์žˆ์Šต๋‹ˆ๋‹ค. ์—ฐ๊ด€ ๊ด€๊ณ„๋ฅผ ์„ค์ •ํ•ด์•ผ ํ•œ๋‹ค๋Š” ์ ์€ ๋งž์Šต๋‹ˆ๋‹ค. [์ถœ์ฒ˜]

๊ทธ๋ฆฌ๊ณ ...

๋‹น์‹ ๊ณผ ์›น์˜ ๊ฑฐ์˜ ๋ชจ๋“  ์‚ฌ๋žŒ์ด ๋น ๋œจ๋ฆฌ๊ณ  ์žˆ๋Š” ๊ฒƒ์€, ์ด API ํ˜•์‹์ด ์ž‘๋™ํ•˜๋ ค๋ฉด ํŒŒ์„œ(๋ฆฌ์กธ๋ฒ„ + ํƒ€์ž…)๋ฅผ ์ž‘์„ฑํ•ด์•ผ ํ•˜๋ฉฐ, ์ด๋กœ ์ธํ•ด REST์—๋Š” ์—†๋Š” ์ผ๋ จ์˜ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค๋Š” ์ ์ž…๋‹ˆ๋‹ค. [์ถœ์ฒ˜]

์ด๋Ÿฌํ•œ ๋Œ“๊ธ€์€ ์™„์ „ํžˆ ์ •ํ™•ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. WPGraphQL๊ณผ Gato GraphQL์ด ์ด๋ฏธ WordPress ๋ฐ์ดํ„ฐ ๋ชจ๋ธ์„ GraphQL ์Šคํ‚ค๋งˆ์— ๋งคํ•‘ํ•ด ๋†“์•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค(WPGraphQL์€ ์™„์ „ํžˆ, ์ œ ํ”Œ๋Ÿฌ๊ทธ์ธ์€ ๋Œ€๋ถ€๋ถ„).

๋”ฐ๋ผ์„œ ์ด๋Ÿฌํ•œ ํ”Œ๋Ÿฌ๊ทธ์ธ ์ค‘ ํ•˜๋‚˜๋ฅผ ์„ค์น˜ํ•˜๋ฉด, ๋ฆฌ์กธ๋ฒ„๋ฅผ ๋งŒ๋“ค๊ฑฐ๋‚˜ ์—”ํ‹ฐํ‹ฐ ๊ฐ„ ์—ฐ๊ด€ ๊ด€๊ณ„๋ฅผ ์„ค์ •ํ•  ํ•„์š” ์—†์ด ์ฆ‰์‹œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ๋ฐ์ดํ„ฐ ๊ฐ€์ ธ์˜ค๊ธฐ๋ฅผ ์‹œ์ž‘ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ฌผ๋ก  ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ๊ณ ์œ  ์—”ํ‹ฐํ‹ฐ(CPT ๋“ฑ)์—์„œ ์ปค์Šคํ…€ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๋ ค๋ฉด, ๋ฆฌ์กธ๋ฒ„๋ฅผ ํ†ตํ•ด ๋งคํ•‘ํ•ด์•ผ ํ•˜๋ฉฐ ์ง์ ‘ ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ด๋Š” REST์™€ ๋‹ค๋ฅด์ง€ ์•Š์Šต๋‹ˆ๋‹ค. CPT์—์„œ ์ปค์Šคํ…€ ๋ฐ์ดํ„ฐ๊ฐ€ ํ•„์š”ํ•˜๋‹ค๋ฉด, ํ•ด๋‹น ์ปค์Šคํ…€ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๊ธฐ ์œ„ํ•œ REST ์—”๋“œํฌ์ธํŠธ๋ฅผ ๋งŒ๋“ค์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ปค์Šคํ…€ ์—”๋“œํฌ์ธํŠธ๋„ ๋ฆฌ์กธ๋ฒ„์˜ ์ผ์ข…์ž…๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ ๋ฆฌ์กธ๋ฒ„ ํ•„์š”์„ฑ ์ธก๋ฉด์—์„œ, REST์™€ GraphQL API๋Š” ๊ฑฐ์˜ ๋™์ผํ•ฉ๋‹ˆ๋‹ค.

์›น์‚ฌ์ดํŠธ์™€ ๋ฌธ์„œ๋ฅผ ๋‘˜๋Ÿฌ๋ณด๋ฉด, GraphQL์ด ์„ค์ •์— ๋” ๋งŽ์€ ๋…ธ๋ ฅ์ด ํ•„์š”ํ•˜๋‹ค๋Š” ์ธ์ƒ์„ ์ค๋‹ˆ๋‹ค. ์ด ์ถ”์ •์—๋Š” ์–ด๋А ์ •๋„ ๊ทผ๊ฑฐ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ช‡ ๊ฐ€์ง€ ์ด์œ ๊ฐ€ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ์šฐ์„  GraphQL์—๋Š” (์ตœ์†Œ) ๋‘ ๊ฐ€์ง€ ์ธก๋ฉด์ด ์žˆ์Šต๋‹ˆ๋‹ค.

  1. ๊ทธ๊ฒƒ์ด ๋ฌด์—‡์ธ์ง€, ์–ด๋–ป๊ฒŒ ์ž‘๋™ํ•˜๋Š”์ง€์— ๋Œ€ํ•œ ๊ฐœ๋…
  2. ์‹ค์ œ ๊ตฌํ˜„์„ ์ œ๊ณตํ•˜๋Š” ์„œ๋ฒ„

graphql.org์™€ ๊ฐ™์€ GraphQL ๊ณต์‹ ์‚ฌ์ดํŠธ์˜ ๋ฌธ์„œ๋ฅผ ๋ณด๋ฉด, GraphQL ๋’ค์— ์žˆ๋Š” ๊ฐœ๋…์— ์ง‘์ค‘ํ•˜๋ฉฐ ๋ฆฌ์กธ๋ฒ„๊ฐ€ ๋ฌด์—‡์ธ์ง€, ์™œ ํ•„์š”ํ•œ์ง€์— ๋Œ€ํ•ด ์ž์„ธํžˆ ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค.

์ด๋Š” Laravel๊ณผ Lighthouse๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ์ฒ˜์Œ๋ถ€ํ„ฐ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๊ตฌ์ถ•ํ•  ๋•Œ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค. ๊ทธ ๊ฒฝ์šฐ์—๋Š” ์ง์ ‘ ๋ฆฌ์กธ๋ฒ„๋ฅผ ์ฝ”๋”ฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค(๋ฌผ๋ก  REST ์—”๋“œํฌ์ธํŠธ๋„ ์ง์ ‘ ๋งŒ๋“ค์–ด์•ผ ํ•˜์ง€๋งŒ์š”).

ํ•˜์ง€๋งŒ WordPress๋Š” ์ด๋ฏธ ์™„์„ฑ๋œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด๊ณ , WPGraphQL๊ณผ Gato GraphQL์€ ๊ทธ ์†”๋ฃจ์…˜์ž…๋‹ˆ๋‹ค. ์ด ๋‘ ํ”Œ๋Ÿฌ๊ทธ์ธ์€ ์ด๋ฏธ ๋ฆฌ์กธ๋ฒ„๋ฅผ ๋งŒ๋“ค์–ด ๋†“์•˜์œผ๋ฏ€๋กœ ์‹ ๊ฒฝ ์“ธ ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค(WP REST API๋„ ์ดˆ๊ธฐ ์—”๋“œํฌ์ธํŠธ ์„ธํŠธ๋ฅผ ์ œ๊ณตํ•˜์—ฌ ์‹ ๊ฒฝ ์“ธ ํ•„์š”๊ฐ€ ์—†๋Š” ๊ฒƒ๊ณผ ๋งˆ์ฐฌ๊ฐ€์ง€์ž…๋‹ˆ๋‹ค).

๋˜ํ•œ GraphQL์€ ๊ฐœ๋ฐœ์ž ์ค‘์‹ฌ์ด๋ฉฐ, ๊ทธ ๋ฌธ์„œ๋Š” ๊ฐœ๋ฐœ์ž์—๊ฒŒ ์ง์ ‘ ๋ง์„ ๊ฑฐ๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋ณด์ž…๋‹ˆ๋‹ค. ๊ฐœ๋ฐœ์ž๊ฐ€ ์„œ๋ฒ„ ์ธก์—์„œ ๋ฆฌ์กธ๋ฒ„๋ฅผ ๋งŒ๋“ค๊ณ , ๊ฐœ๋ฐœ์ž๊ฐ€ ํด๋ผ์ด์–ธํŠธ ์ธก์—์„œ ์ปค์Šคํ…€ ์ฟผ๋ฆฌ๋กœ ํ•ด๋‹น ๋ฆฌ์กธ๋ฒ„๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ๋ฆฌ์กธ๋ฒ„ ๊ตฌ์ถ•์€ ๊ฐœ๋ฐœ์ž์˜ ์ผ์ด๊ธฐ ๋•Œ๋ฌธ์— ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ์ž์ฃผ ๋“ฑ์žฅํ•ฉ๋‹ˆ๋‹ค.

REST์˜ ๊ฒฝ์šฐ, ํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ์ œ๊ณตํ•˜๋Š” ์—”๋“œํฌ์ธํŠธ๋Š” ์ด๋ฏธ ์กด์žฌํ•ด์•ผ ํ•œ๋‹ค๋Š” ๊ธฐ๋Œ€(WP REST API๊ฐ€ ์ œ๊ณตํ•˜๋Š” ๊ฒƒ)๊ฐ€ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ์กด์žฌํ•˜์ง€ ์•Š์„ ๋•Œ๋งŒ ์ปค์Šคํ…€ ์—”๋“œํฌ์ธํŠธ ์„ค์ •์„ ๊ณ ๋ คํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ REST์—์„œ๋Š” ๋ฆฌ์กธ๋ฒ„ ์ƒ์„ฑ์— ๋Œ€ํ•œ ์–ธ๊ธ‰์ด ์ ์Šต๋‹ˆ๋‹ค.

์ฆ‰, REST์™€ GraphQL ๋ชจ๋‘ ํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ REST๋Š” ์—”๋“œํฌ์ธํŠธ๊ฐ€ ์ด๋ฏธ ์กด์žฌํ•ด์•ผ ํ•œ๋‹ค๋Š” ์ •์ ์ธ ์ ‘๊ทผ ๋ฐฉ์‹์„ ๊ถŒ์žฅํ•˜๋ฉฐ, ์กด์žฌํ•˜์ง€ ์•Š์„ ๋•Œ๋งŒ ์‹ ๊ฒฝ ์”๋‹ˆ๋‹ค. ๋ฐ˜๋ฉด GraphQL์€ ๋ชจ๋“  ์ฟผ๋ฆฌ๋ฅผ ์ปค์Šคํ…€ ์ œ์ž‘ํ•˜๋Š” ๋™์ ์ธ ์ ‘๊ทผ ๋ฐฉ์‹์„ ๊ถŒ์žฅํ•˜๋ฉฐ, ์™„๋ฒฝํ•œ ๋ฆฌ์กธ๋ฒ„๋ฅผ ์ฝ”๋”ฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ฒฐ๊ตญ REST์™€ GraphQL ์‚ฌ์ด์—๋Š” ๊ทผ๋ณธ์ ์ธ ์ฐจ์ด๊ฐ€ ์—†์œผ๋ฉฐ, ์š”๊ฑด์„ ์–ด๋–ป๊ฒŒ ์ถฉ์กฑํ•ด์•ผ ํ•˜๋Š”์ง€์— ๋Œ€ํ•œ ํ•ด์„์˜ ์ฐจ์ด๋งŒ ์žˆ์„ ๋ฟ์ž…๋‹ˆ๋‹ค.

GraphQL์˜ ์ทจ์•ฝ์  + ๋ณด์•ˆ ๊ณ ๋ ค ์‚ฌํ•ญ

์•ˆ์ „ํ•œ ์ธํ„ฐํ”„๋ฆฌํ„ฐ๋ฅผ ์ž‘์„ฑํ•˜๋Š” ๊ฒƒ์€ ์ •๋ง ์–ด๋ ต๊ธฐ ๋•Œ๋ฌธ์— ์–ธ์  ๊ฐ€ GraphQL์—์„œ ํฐ ์ทจ์•ฝ์ ์ด ๋‚˜์˜ฌ ๊ฒƒ์ž…๋‹ˆ๋‹ค. [์ถœ์ฒ˜]

๊ทธ๋ฆฌ๊ณ ...

WordPress๋Š” ์ด๋ฏธ ๊ฑฐ๋Œ€ํ•ด์„œ ํ•ญ์ƒ ํฐ ๊ณต๊ฒฉ ๋Œ€์ƒ์ด ๋ฉ๋‹ˆ๋‹ค. ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ์ถ”๊ฐ€ํ•˜๋ฉด ์œ„ํ—˜์ด ํฌ๊ฒŒ ์ฆ๊ฐ€ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  WordPress์˜ ๋ชจ๋“  ๊ฒƒ์„ ๋ฌธ์ž ๊ทธ๋Œ€๋กœ ๋…ธ์ถœํ•˜๋ ค๋Š” ํ”Œ๋Ÿฌ๊ทธ์ธ(๋ฉ”๋‰ด์™€ ๋ฉ”๋‰ด ์•„์ดํ…œ์„ ๊ณต๊ฐœํ•˜๊ฑฐ๋‚˜ ๋ชจ๋“  ์‚ฌ์šฉ์ž๋ฅผ ๊ณต๊ฐœํ•˜๋Š” ๋ณด์•ˆ ๋ชจ๋ธ์„ ์šฐํšŒํ•˜๋Š” ์ƒ˜ํ”Œ ์ฝ”๋“œ ํฌํ•จ)์€ ์ €์—๊ฒŒ๋Š” ์ ˆ๋Œ€ ์šฉ๋‚ฉํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ํ…Œ๋งˆ ๊ธฐ๋ฐ˜์ด ์•„๋‹Œ ์ถœ๋ ฅ์€ ์ ˆ๋Œ€์ ์œผ๋กœ ํ•„์š”ํ•œ ๊ฒƒ ์ด์ƒ์œผ๋กœ ์ตœ๋Œ€ํ•œ ์ œํ•œ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค(์ œ๊ฐ€ ์š”์ฒญํ•˜์ง€ ์•Š๋Š” ํ•œ ์กด์žฌํ•˜์ง€ ์•Š์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค). ์ด๊ฒƒ์ด ์ฝ”์–ด์— ํฌํ•จ๋˜์ง€ ์•Š๊ธฐ๋ฅผ ๋ฐ”๋ž๋‹ˆ๋‹ค. [์ถœ์ฒ˜]

GraphQL์€ ๋ถ„๋ช…ํžˆ ์ถ”๊ฐ€์ ์ธ ๋ณด์•ˆ ์œ„ํ—˜์„ ์ดˆ๋ž˜ํ•˜๋ฉฐ ์ด๋ฅผ ํ•ด๊ฒฐํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด ์šฐ๋ ค์— ์™„์ „ํžˆ ๋™์˜ํ•ฉ๋‹ˆ๋‹ค.

ํ•˜์ง€๋งŒ ๊ทธ๊ฒƒ์ด GraphQL์„ WP ์ฝ”์–ด์— ํฌํ•จ์‹œํ‚ฌ ๊ฐ€๋Šฅ์„ฑ์„ ๋ง‰๋Š” ๊ฒฐ์ •์ ์ธ ๋ฌธ์ œ๋ผ๊ณ ๋Š” ์ƒ๊ฐํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋” ๋‚˜์•„๊ฐ€, ์ด๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ๊ฐ€ ์ •๋ง ์–ด๋ ต๋‹ค๊ณ ๋„ ์ƒ๊ฐํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

ํ•„์š”ํ•œ ๊ฒƒ์€ GraphQL ์„œ๋ฒ„๊ฐ€ WordPress์˜ ๊ธฐ์กด ๋ณด์•ˆ ๋ฉ”์ปค๋‹ˆ์ฆ˜์„ ํ™œ์šฉํ•˜๊ณ , ๊ฐœ๋ฐœ์ž๊ฐ€ ๊ทธ ๋ฉ”์ปค๋‹ˆ์ฆ˜์„ ์‚ฌ์šฉํ•˜์—ฌ ํŠน์ • ํ•„๋“œ์— ์ ์ ˆํ•œ ์‚ฌ์šฉ์ž๋งŒ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

  • ์‚ฌ์šฉ์ž๊ฐ€ ๋กœ๊ทธ์ธ๋˜์–ด ์žˆ๋Š”๊ฐ€?
  • ์‚ฌ์šฉ์ž๊ฐ€ ๊ด€๋ฆฌ์ž์ธ๊ฐ€?
  • ์‚ฌ์šฉ์ž๊ฐ€ ์–ด๋–ค ์—ญํ• ์ด๋‚˜ ๊ถŒํ•œ์„ ๊ฐ€์ง€๊ณ  ์žˆ๋Š”๊ฐ€?
  • ์‚ฌ์šฉ์ž๊ฐ€ ํ•ด๋‹น ๊ฒŒ์‹œ๋ฌผ์˜ ์ž‘์„ฑ์ž์ธ๊ฐ€?

์ด ์š”๊ฑด์„ ์ถฉ์กฑํ•˜๊ธฐ ์œ„ํ•ด, Gato GraphQL์€ Access Control Lists(์ ‘๊ทผ ์ œ์–ด ๋ชฉ๋ก)์„ ์ œ๊ณตํ•˜์—ฌ ๊ฐ ํ•„๋“œ์™€ ๋””๋ ‰ํ‹ฐ๋ธŒ์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋Š” ์‚ฌ๋žŒ์„ ์„ค์ •์œผ๋กœ ์ •์˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋Ÿฐ๋ฐ ACL๋งŒ์œผ๋กœ๋Š” ์ถฉ๋ถ„ํ•˜์ง€ ์•Š์€ ๊ฒฝ์šฐ๋„ ์žˆ์œผ๋ฉฐ, GraphQL ์„œ๋ฒ„๊ฐ€ ์ถ”๊ฐ€์ ์ธ ๋ณด์•ˆ ์กฐ์น˜๋ฅผ ์ œ๊ณตํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ํ˜„์žฌ Gato GraphQL์˜ ๋‹ค๊ฐ€์˜ค๋Š” v0.8์„ ์œ„ํ•ด ์ž‘์—… ์ค‘์ธ ๋‚ด์šฉ์„ ์„ค๋ช…ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

ํ•„๋“œ posts(๊ฒŒ์‹œ๋ฌผ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ๊ฒƒ)๋Š” ์ธ์ฆ์ด ํ•„์š” ์—†์œผ๋ฉฐ, ๋กœ๊ทธ์ธ ์—ฌ๋ถ€์— ๊ด€๊ณ„์—†์ด ๋ชจ๋“  ์‚ฌ์šฉ์ž๊ฐ€ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ๋ณด์•ˆ์ƒ์˜ ์ด์œ ๋กœ ๊ณต๊ฐœ๋œ ๊ฒŒ์‹œ๋ฌผ๋งŒ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค.

ํ•˜์ง€๋งŒ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ƒํ™ฉ์—์„œ๋Š” ์ดˆ์•ˆ/๋ณด๋ฅ˜ ์ค‘/ํœด์ง€ํ†ต ๊ฒŒ์‹œ๋ฌผ๋„ ๊ฐ€์ ธ์™€์•ผ ํ•  ๋•Œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

  • ๊ด€๋ฆฌ์ž๊ฐ€ ์‹คํ–‰ํ•˜๋Š” ์ •์  ์›น์‚ฌ์ดํŠธ ๊ตฌ์ถ•(์‚ฌ์ดํŠธ์˜ ๋ชจ๋“  ๋ฐ์ดํ„ฐ์— ๋Œ€ํ•œ ์ ‘๊ทผ ํฌํ•จ)
  • ๊ฒŒ์‹œ๋ฌผ ์ž‘์„ฑ์ž๊ฐ€ ๊ณ„์† ํŽธ์ง‘ํ•  ์ˆ˜ ์žˆ๋„๋ก ๋ชจ๋“  ์ดˆ์•ˆ ๊ฒŒ์‹œ๋ฌผ์„ ๋‚˜์—ดํ•˜๋Š” ๊ฒฝ์šฐ

๊ทธ๋ž˜์„œ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ฒด๊ณ„๋ฅผ ๊ตฌ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ฒŒ์‹œ๋ฌผ์„ ๊ฐ€์ ธ์˜ค๊ธฐ ์œ„ํ•ด 3๊ฐœ์˜ ํ•„๋“œ๊ฐ€ ์ œ๊ณต๋ฉ๋‹ˆ๋‹ค.

  • posts: ๋ˆ„๊ตฌ๋‚˜ ์ ‘๊ทผ ๊ฐ€๋Šฅํ•˜๋ฉฐ, ๊ณต๊ฐœ๋œ ๊ฒŒ์‹œ๋ฌผ๋งŒ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ์Œ
  • myPosts: ๋ˆ„๊ตฌ๋‚˜ ์ ‘๊ทผ ๊ฐ€๋Šฅํ•˜๋ฉฐ, ๋กœ๊ทธ์ธํ•œ ์‚ฌ์šฉ์ž์˜ ๊ฒŒ์‹œ๋ฌผ๋งŒ ๋ชจ๋“  ์ƒํƒœ(๊ณต๊ฐœ๋จ/์ดˆ์•ˆ/๋ณด๋ฅ˜ ์ค‘/ํœด์ง€ํ†ต)๋กœ ๊ฐ€์ ธ์˜ด
  • postsForAdmin: ๊ด€๋ฆฌ์ž๋งŒ ์ ‘๊ทผ ๊ฐ€๋Šฅํ•˜๋ฉฐ, ๋ชจ๋“  ์ƒํƒœ์˜ ๋ชจ๋“  ๊ฒŒ์‹œ๋ฌผ์„ ๊ฐ€์ ธ์˜ด

๊ทธ๋ฆฌ๊ณ  postsForAdmin์€ ๊ธฐ๋ณธ์ ์œผ๋กœ ๋น„ํ™œ์„ฑํ™”๋˜์–ด ์žˆ์–ด GraphQL ์Šคํ‚ค๋งˆ์— ํ‘œ์‹œ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ด€๋ฆฌ์ž๊ฐ€ ๋ช…์‹œ์ ์œผ๋กœ ํ™œ์„ฑํ™”ํ•œ ๊ฒฝ์šฐ์—๋งŒ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค(์•„๋งˆ๋„ ์ •์  ์‚ฌ์ดํŠธ ๊ตฌ์ถ•์—๋งŒ ํ™œ์„ฑํ™”๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค).

๋˜ ๋‹ค๋ฅธ ์ƒํ™ฉ์€ ํŠน์ • ํ•„๋“œ๊ฐ€ ๊ณต๊ฐœ ๋ฐ์ดํ„ฐ์™€ ๋น„๊ณต๊ฐœ ๋ฐ์ดํ„ฐ๋ฅผ ๋ชจ๋‘ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๋Š” ๊ฒฝ์šฐ์ž…๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ํ•„๋“œ option์€ ํ…Œ์ด๋ธ” wp_options์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค. ์ผ๋ถ€ ํ•ญ๋ชฉ์€ ๊ณต๊ฐœ(blogname ๋“ฑ)์ด์ง€๋งŒ, ๊ทธ๋ ‡์ง€ ์•Š์€ ๊ฒƒ(admin_email ๋“ฑ)๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

๋น„์Šทํ•œ ์ƒํ™ฉ์œผ๋กœ๋Š” ํ•„๋“œ Post.metaValue, User.metaValue ๋“ฑ์„ ํ†ตํ•ด ๋ฉ”ํƒ€ ๊ฐ’์„ ๊ฐ€์ ธ์˜ค๋Š” ๊ฒฝ์šฐ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ์‚ฌ์šฉ์ž ๋ฉ”ํƒ€์—๋Š” ๋ถ„๋ช…ํžˆ ๋น„๊ณต๊ฐœ์ธ ํ•ญ๋ชฉ wp_capabilities๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ์ง€๋งŒ, description์€ ๊ณต๊ฐœ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  last_name์€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ๋”ฐ๋ผ ๊ณต๊ฐœ ๋˜๋Š” ๋น„๊ณต๊ฐœ์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด ๋ฐ์ดํ„ฐ์— ๋Œ€ํ•œ ์ ‘๊ทผ์„ ์•ˆ์ „ํ•˜๊ฒŒ ํ•˜๊ธฐ ์œ„ํ•ด, ํ”Œ๋Ÿฌ๊ทธ์ธ์€ ์„ค์ • ํŽ˜์ด์ง€์˜ ํ—ˆ์šฉ/๊ฑฐ๋ถ€ ๋ชฉ๋ก์„ ํ†ตํ•ด ์ฟผ๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š” ํ•ญ๋ชฉ์„ ์ง€์ •ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ์ „์ฒด ํ•ญ๋ชฉ ๋˜๋Š” ์ •๊ทœ์‹์„ ๋ชจ๋‘ ํ—ˆ์šฉํ•ฉ๋‹ˆ๋‹ค.

ใ€Œoptionใ€ํ•„๋“œ์˜ ํ—ˆ์šฉ/๊ฑฐ๋ถ€ ํ•ญ๋ชฉ ์ •์˜

ํ—ˆ์šฉ๋œ ์˜ต์…˜ ์ฟผ๋ฆฌ๋Š” ์ž‘๋™ํ•˜๊ณ , ๊ฑฐ๋ถ€๋œ ์˜ต์…˜์€ null์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

{
  # This option is allowed
  siteName: optionValue(name: "blogname")
  # This optionValue is not allowed
  adminEmail: optionValue(name: "admin_email")
}

GraphQL ์„œ๋ฒ„์˜ ์ ์ ˆํ•œ ๋ณด์•ˆ ์กฐ์น˜์™€ ๊ฐœ๋ฐœ์ž์˜ ์ƒ์‹์ด ์žˆ๋‹ค๋ฉด, ์•ˆ์ „ํ•œ GraphQL API๋ฅผ ๊ตฌ์ถ•ํ•˜๋Š” ๊ฒƒ์€ ์–ด๋ ต์ง€ ์•Š์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

GraphQL๋กœ ์ธํ•œ DB ๋‹ค์šด

GraphQL์€ ๊นŠ์€ ๊ด€๊ณ„ํ˜• ์ฟผ๋ฆฌ๋ฅผ ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ๋Š” ํ’๋ถ€ํ•œ ๊ตฌ๋ฌธ์„ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. WordPress์™€ ๊ฐ™์€ ์ƒํƒœ๊ณ„์—์„œ ๋ฐ์ดํ„ฐ ๋ชจ๋ธ์˜ ํ™•์žฅ์„ฑ์ด ์—”ํ‹ฐํ‹ฐ-์†์„ฑ-๊ฐ’ ํŒจํ„ด์— ๊ธฐ๋ฐ˜ํ•˜๊ธฐ ๋•Œ๋ฌธ์—, GraphQL ์ฟผ๋ฆฌ๊ฐ€ ๊นŠ๊ณ  ๋ณต์žกํ•˜๊ฑฐ๋‚˜ ์žฌ๊ท€์ ์ธ ๊ฒฝ์šฐ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ๋ฏฟ์„ ์ˆ˜ ์—†๋Š” ๋ถ€ํ•˜๊ฐ€ ๊ฑธ๋ ค ์‚ฌ์ดํŠธ๊ฐ€ ์‘๋‹ตํ•˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. WordPress๋Š” ์ด๋ฏธ MySQL/MariaDB ์ธ์Šคํ„ด์Šค๋ฅผ ํ•œ๊ณ„๊นŒ์ง€ ๋ชฐ์•„๋ถ™์ด๋Š” ๊ฒƒ์œผ๋กœ ์œ ๋ช…ํ•ฉ๋‹ˆ๋‹ค. ์ฟผ๋ฆฌ๊ฐ€ ์ ์ ˆํ•˜๊ฒŒ ์ž‘์„ฑ๋˜๊ณ  ์ธ์ฆ๋˜๋ฉฐ ์†๋„ ์ œํ•œ๋˜์ง€ ์•Š๋Š”๋‹ค๋ฉด, GraphQL์„ ์ถ”๊ฐ€ํ•˜๋ฉด ํ›จ์”ฌ ๋” ๋‚˜๋น ์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. [์ถœ์ฒ˜]

DB ๋‹ค์šด์€ GraphQL ์„œ๋ฒ„์—๊ฒŒ ์‹ฌ๊ฐํ•œ ์šฐ๋ ค ์‚ฌํ•ญ์ž…๋‹ˆ๋‹ค. Gato GraphQL์ด ์ด ์‹œ๋‚˜๋ฆฌ์˜ค๋ฅผ ํ”ผํ•˜๋ ค๋Š” ๋ฐฉ๋ฒ•์„ ์„ค๋ช…ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

Gato GraphQL์€ ์•„ํ‚คํ…์ฒ˜ ์„ค๊ณ„์— ์˜ํ•ด N+1 ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š๋„๋ก ํ•ฉ๋‹ˆ๋‹ค. ์—”์ง„์ด ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—์„œ ์—”ํ‹ฐํ‹ฐ๋ฅผ ๋กœ๋“œํ•˜๋Š” ์ฑ…์ž„์„ ์ง€๋ฉฐ, ๊ฐœ๋ฐœ์ž๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค.

๋ฆฌ์กธ๋ฒ„์—์„œ ์—ฐ๊ฒฐ์„ ํ•ด๊ฒฐํ•  ๋•Œ, ๋ฐ˜ํ™˜๋˜๋Š” ๊ฐ’์€ ๊ฐ์ฒด ์ž์ฒด๊ฐ€ ์•„๋‹Œ ๊ฐ์ฒด์˜ ID(๋˜๋Š” ID ๋ชฉ๋ก)์ž…๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ์ปค์Šคํ…€ ๊ฒŒ์‹œ๋ฌผ์˜ ์ž‘์„ฑ์ž๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ๊ฒƒ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ˆ˜ํ–‰๋ฉ๋‹ˆ๋‹ค.

class CustomPostFieldResolver extends AbstractDBDataFieldResolver
{
  private CustomPostUserTypeAPIInterface $customPostUserTypeAPI;
 
  public function getClassesToAttachTo(): array
  {
    return [
      CustomPostFieldInterfaceResolver::class,
    ];
  }
 
  public function getSchemaFieldType(string $fieldName): ?string
  {
    return match($fieldName) {
      'author' => SchemaDefinition::TYPE_ID,
      default => null,
    };
  }
 
  public function resolveValue(
    TypeResolverInterface $typeResolver,
    object $customPost,
    string $fieldName,
    array $fieldArgs = []
  ): mixed {
    switch ($fieldName) {
      case 'author':
        return $this->customPostUserTypeAPI->getAuthorID($customPost);
    }
 
    return null;
  }
 
  public function resolveFieldTypeResolverClass(
    TypeResolverInterface $typeResolver,
    string $fieldName
  ): ?string {
    switch ($fieldName) {
      case 'author':
        return UserTypeResolver::class;
    }
 
    return null;
  }
}

resolveValue์—์„œ DB ์—”ํ‹ฐํ‹ฐ์˜ ID๋ฅผ, resolveFieldTypeResolverClass(ํด๋ž˜์Šค UserTypeResolver๋กœ ํ‘œํ˜„๋จ)์—์„œ ๊ฐ์ฒด์˜ ํƒ€์ž…์„ ์–ป์–ด, GraphQL ์—”์ง„์€ ๊ฐ์ฒด์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๋กœ๋“œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ฐ์ดํ„ฐ๋ฅผ ๋กœ๋“œํ•  ๋•Œ, ์—”์ง„์€ ๋งค์šฐ ํšจ์œจ์ ์ธ ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ๋…ธ๋“œ ์ˆ˜๊ฐ€ ์•„๋‹ˆ๋ผ ์ฟผ๋ฆฌ ๋‚ด ํƒ€์ž… ์ˆ˜๋ฅผ n์œผ๋กœ ํ•˜๋Š” ์‹œ๊ฐ„ ๋ณต์žก๋„ O(n)์ž…๋‹ˆ๋‹ค.

์ด ์•Œ๊ณ ๋ฆฌ์ฆ˜์ด ์ด๋Ÿฌํ•œ ํšจ์œจ์„ฑ์„ ๋‹ฌ์„ฑํ•˜๋Š” ์ด์œ ๋Š” ๊ทธ๋ž˜ํ”„๋ฅผ ์ˆœํšŒํ•˜์ง€ ์•Š๊ณ , ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ๋ฅผ ์ปดํฌ๋„ŒํŠธ ์Šคํƒ์œผ๋กœ ๋ณ€ํ™˜ํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ์ด๋Š” ํ›จ์”ฌ ๊ฐ„๋‹จํ•˜๊ฒŒ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. (GraphQL์˜ "๊ทธ๋ž˜ํ”„"๋Š” ๊ฐœ๋…์ด์ง€ ์‹ค์ œ ๊ตฌํ˜„์ด ์•„๋‹™๋‹ˆ๋‹ค.)

์ฟผ๋ฆฌ๊ฐ€ ์—ฌ๋Ÿฌ ๋ ˆ๋ฒจ์„ ๊ฐ€์ง€๊ณ  ๊ฐ๊ฐ ๋งŽ์€ ์—”ํ‹ฐํ‹ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ๊ฒฝ์šฐ์—๋„ ์•Œ๊ณ ๋ฆฌ์ฆ˜์€ ๊ฝค ์ž˜ ๊ฒฌ๋”œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ๊นŠ์ด 10 ๋ ˆ๋ฒจ์˜ ๋‹ค์Œ ์ฟผ๋ฆฌ๋ฅผ ์‹คํ–‰ํ•ด๋„ ํฐ ์˜ํ–ฅ์ด ์—†์Šต๋‹ˆ๋‹ค.

{
  posts(pagination: { limit: 10 }) {
    excerpt
    title
    url
    author {
      name
      url
      posts(pagination: { limit: 10 }) {
        title
        tags(pagination: { limit: 10 }) {
          slug
          url
          posts(pagination: { limit: 10 }) {
            title
            comments(pagination: { limit: 10 }) {
              content
              date
              author {
                name
                posts(pagination: { limit: 10 }) {
                  title
                  url
                  comments(pagination: { limit: 10 }) {
                    content
                    date
                    author {
                      name
                      username
                      url
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}

์ด ํšจ์œจ์„ฑ์˜ ์˜ˆ์™ธ๋Š” Post.metaValue, User.metaValue, Comment.metaValue, PostTag.metaValue, PostCategory.metaValue(๋ฐ metaValues ํ•„๋“œ)๋ฅผ ํ†ตํ•ด ๋ฉ”ํƒ€ ๊ฐ’์„ ๊ฐ€์ ธ์˜ค๋Š” ๊ฒฝ์šฐ์ž…๋‹ˆ๋‹ค. WordPress ํ•จ์ˆ˜(get_post_meta, get_user_meta ๋“ฑ)๋Š” ํ•œ ๋ฒˆ์— 1๊ฐœ์˜ ID์— ๋Œ€ํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๊ธฐ ๋•Œ๋ฌธ์—, ๊ฐ ์—”ํ‹ฐํ‹ฐ๋Š” ๋ฉ”ํƒ€ ๊ฐ’์„ ๊ฐ€์ ธ์˜ค๊ธฐ ์œ„ํ•œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ํ˜ธ์ถœ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ๊ฒฐ๊ณผ์ ์œผ๋กœ ๋ฉ”ํƒ€ ๊ฐ’ ํ•ด๊ฒฐ์€ ํƒ€์ž… ์ˆ˜๊ฐ€ ์•„๋‹Œ ๋…ธ๋“œ ์ˆ˜์— ๋”ฐ๋ผ ํ™•์žฅ๋ฉ๋‹ˆ๋‹ค(์ด ์ ์—์„œ ์›๋ณธ ๋Œ“๊ธ€์ด ์ •ํ™•ํžˆ ํ•ต์‹ฌ์„ ์ฐŒ๋ฅด๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค).

์•…์˜์ ์ธ ํ–‰์œ„์ž๊ฐ€ ๋ฉ”ํƒ€ ํ•„๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ๋‚จ์šฉํ•˜๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด, Gato GraphQL(v0.8)์€ ์ด ํ•„๋“œ๋“ค์„ ๊ธฐ๋ณธ์ ์œผ๋กœ ๋น„ํ™œ์„ฑํ™”ํ•œ ์ƒํƒœ๋กœ ์ œ๊ณต๋ฉ๋‹ˆ๋‹ค. ๊ด€๋ฆฌ์ž๊ฐ€ ๋ช…์‹œ์ ์œผ๋กœ ํ™œ์„ฑํ™”ํ•ด์•ผ ํ•˜๋ฉฐ, ๊ทธ๋ ‡๊ฒŒ ํ•  ๋•Œ ์ด ํ•„๋“œ๋“ค์„ Access Control List ์•„๋ž˜์— ๋ฐฐ์น˜ํ•  ์ˆ˜ ์žˆ์–ด DB๊ฐ€ ๊ณต๊ฒฉ ์œ„ํ—˜์— ๋…ธ์ถœ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์†๋„ ์ œํ•œ๋„ ํ›Œ๋ฅญํ•œ ์•„์ด๋””์–ด์ด๋ฉฐ, ํ–ฅํ›„ ๋ฆด๋ฆฌ์Šค์—์„œ ์ง€์›ํ•  ๊ณ„ํš์ž…๋‹ˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ  ์ฟผ๋ฆฌ์˜ ๋ณต์žก์„ฑ ๋ถ„์„ ๋ฐ ์ œํ•œ ๋ถ€๊ณผ(์˜ˆ: ๋ช‡ ๋ ˆ๋ฒจ ๊นŠ์ด๊นŒ์ง€ ํ—ˆ์šฉํ•˜๋Š”์ง€)์— ๋Œ€ํ•ด์„œ๋„ ๊ฒ€ํ† ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. GraphQL ์„œ๋ฒ„๋Š” ์‹œ๊ฐ„ ๋ณต์žก๋„ O(n)์œผ๋กœ ์ฟผ๋ฆฌ๋ฅผ ํ•ด๊ฒฐํ•˜๋ฏ€๋กœ, ๋ฃจํ•‘์— ๊ด€ํ•ด์„œ๋Š” ๊ทธ๋‹ค์ง€ ํฐ ํ•ด๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๋‹จ์ผ ์ฟผ๋ฆฌ๋งŒ์œผ๋กœ๋„ DB์—์„œ ๋ฌด์ œํ•œ์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์ด๋Š” ํ”ผํ•˜๊ณ  ์‹ถ์€ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด, ์ด ๊ฐ„๋‹จํ•œ ์ฟผ๋ฆฌ๋Š” ๋‹จ์ผ ์š”์ฒญ์œผ๋กœ ๋ฐฉ๋Œ€ํ•œ ์–‘์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค(์ œ ๋ฐ๋ชจ ์‚ฌ์ดํŠธ์—๋Š” ์ˆ˜๋ฐฑ ๊ฑด์˜ ๋ ˆ์ฝ”๋“œ๋งŒ ์žˆ์–ด ์ฟผ๋ฆฌ ์‹คํ–‰์„ ์‹œ์—ฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค).

{
  posts000: posts(pagination: { limit: 100 }) {
    ...PostFields
  }
  posts100: posts(pagination: { limit: 100, offset: 100 }) {
    ...PostFields
  }
  posts200: posts(pagination: { limit: 100, offset: 200 }) {
    ...PostFields
  }
  posts300: posts(pagination: { limit: 100, offset: 300 }) {
    ...PostFields
  }
  posts400: posts(pagination: { limit: 100, offset: 400 }) {
    ...PostFields
  }
  posts500: posts(pagination: { limit: 100, offset: 500 }) {
    ...PostFields
  }
  posts600: posts(pagination: { limit: 100, offset: 600 }) {
    ...PostFields
  }
  posts700: posts(pagination: { limit: 100, offset: 700 }) {
    ...PostFields
  }
  posts800: posts(pagination: { limit: 100, offset: 800 }) {
    ...PostFields
  }
  posts900: posts(pagination: { limit: 100, offset: 900 }) {
    ...PostFields
  }
}
 
fragment PostFields on Post {
  id
  title
  content
  date
}

๋ณด์‹œ๋‹ค์‹œํ”ผ, ๋ฌธ์ œ๋ฅผ ์ผ์œผํ‚ค๊ธฐ ์œ„ํ•ด ์ฟผ๋ฆฌ๋ฅผ ์ค‘์ฒฉํ•  ํ•„์š”์กฐ์ฐจ ์—†์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์ฟผ๋ฆฌ ๋ณต์žก์„ฑ ๋ถ„์„์€ ๊นŒ๋‹ค๋กœ์šด ์ž‘์—…์ด๋ฉฐ, ์œ ์šฉํ•˜๊ฒŒ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด์„œ๋Š” ์„ธ๋ฐ€ํ•œ ์กฐ์ •์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

์ฟผ๋ฆฌ ๋ถ„์„ ์ง€์›๋„ ์ถ”๊ฐ€ํ•˜๊ณ  ์‹ถ์ง€๋งŒ, ์šฐ์„ ์ˆœ์œ„๊ฐ€ ๋†’์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ํผ์‹œ์Šคํ‹ฐ๋“œ ์ฟผ๋ฆฌ๋‚˜ ์ปค์Šคํ…€ ์—”๋“œํฌ์ธํŠธ์™€ Access Control Lists์˜ ์กฐํ•ฉ์œผ๋กœ ์ด๋ฏธ ์•…์˜์ ์ธ ํ–‰์œ„์ž๋ฅผ ์ฐจ๋‹จํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์šฐ๋ฆฌ ์ž์‹ ์€ ์ž์‹ ์˜ GraphQL ์„œ๋น„์Šค๋ฅผ ๋‚จ์šฉํ•˜์ง€ ์•Š์„(์•Š์•„์•ผ ํ• !) ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.


๋‰ด์Šค๋ ˆํ„ฐ ๊ตฌ๋…ํ•˜๊ธฐ

Gato GraphQL์˜ ๋ชจ๋“  ์—…๋ฐ์ดํŠธ๋ฅผ ๋†“์น˜์ง€ ๋งˆ์„ธ์š”.