๋ธ”๋กœ๊ทธ

๐Ÿ‘จ๐Ÿปโ€๐Ÿ’ป GraphQL, ์ผ์ข…์˜ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด๋กœ์„œ

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

GraphQL์€ GraphQL ์–ธ์–ด๋ฅผ ๊ฐ–์ถ”๊ณ  ์žˆ์ง€๋งŒ, ์ผ๋ฐ˜์ ์œผ๋กœ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด๋ผ๊ณ  ๋ถ€๋ฅด์ง€๋Š” ์•Š์Šต๋‹ˆ๋‹ค. ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด๋กœ ํ•  ์ˆ˜ ์žˆ๋Š” ๋งŽ์€ ๊ฒƒ๋“ค์„ GraphQL๋กœ๋Š” ํ•  ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

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

(๋‹ค๋ฅธ ์šฉ๋„๋Š” ๋‹จ์ˆœํžˆ ์ด ๋‘ ๊ฐ€์ง€ ๊ฒฝ์šฐ์˜ ์กฐํ•ฉ์ž…๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, API ๊ฒŒ์ดํŠธ์›จ์ด๋Š” ํด๋ผ์ด์–ธํŠธ์— ๋…ธ์ถœ๋˜์ง€ ์•Š์€ ๋‚ด๋ถ€ ์„œ๋ฒ„์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๊ฑฐ๋‚˜ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.)

GraphQL์—์„œ ๋ฐ์ดํ„ฐ์— ์ ‘๊ทผํ•˜๋Š” ๊ฒฝ์šฐ:

query PrintPostTitle($postID: ID!)
{
  post(by: { id: $postID }) {
    title
  }
}

...์ด๊ฒƒ์€ PHP์—์„œ ๋‹ค์Œ๊ณผ ๊ฐ™์ด (๊ฑฐ์˜) ๋™๋“ฑํ•ฉ๋‹ˆ๋‹ค:

function printPostTitle(int $postID)
{
  $post = getPost($postID);
  echo $post->title;
}

(์•„๋ž˜์˜ ๋ชจ๋“  ์˜ˆ์‹œ๋Š” ๋น„๊ต๋ฅผ ์œ„ํ•œ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด๋กœ PHP๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.)

GraphQL์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณ€๊ฒฝํ•˜๋Š” ๊ฒฝ์šฐ:

query UpdatePost($postID: ID!, $title: String!)
{
  updatePost(
    by: { id: $postID },
    input: { title: $title }
  ) {
    title
  }
}

...์ด๊ฒƒ์€ PHP์—์„œ ๋‹ค์Œ๊ณผ ๊ฐ™์ด (๊ฑฐ์˜) ๋™๋“ฑํ•ฉ๋‹ˆ๋‹ค:

function updatePost(int $postID, string $title)
{
  $post = getPost($postID);
  $post->update(['title' => $title]);
}

GraphQL์€ ๋ณดํ†ต ํด๋ผ์ด์–ธํŠธ(JavaScript, PHP, Java ๋“ฑ์˜ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด๋กœ ์ž‘์„ฑ๋œ)์—์„œ ์ ‘๊ทผํ•˜๋ฉฐ, ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋ฐ์ดํ„ฐ๋กœ ๋ฌด์—‡์„ ํ• ์ง€์— ๋Œ€ํ•œ ๋กœ์ง์„ ํฌํ•จํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ด๊ฒƒ์œผ๋กœ ์ถฉ๋ถ„ํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ GraphQL์€ ๋‹จ๋…์œผ๋กœ ์‚ฌ์šฉ๋˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ๋‹ค๋ฅธ ๋ฌด์–ธ๊ฐ€์˜ ๋™๋ฐ˜์ž๋กœ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

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

๊ทธ๋Ÿฌ๊ธฐ ์œ„ํ•ด์„œ๋Š” GraphQL์ด ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด์˜ ๋งŽ์€ ๊ธฐ๋Šฅ์„ ์ง€์›ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

GraphQL์ด ์ง€์›ํ•˜๋Š” ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด ๊ธฐ๋Šฅ์€ ์ œํ•œ์ ์ž…๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ๋””๋ ‰ํ‹ฐ๋ธŒ @include(๋˜๋Š” @skip)๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ๋ณ€์ˆ˜๋ฅผ ์ž…๋ ฅ์œผ๋กœ ์ „๋‹ฌํ•˜๋Š” ๊ฒƒ์€ (์ผ์ข…์˜) ์กฐ๊ฑด ๋กœ์ง์œผ๋กœ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

query PrintPostProperties($postID: ID!, $addContent: Boolean!)
{
  post(by: { id: $postID }) {
    title
    content @include(if: $addContent)
  }
}

์ด ์ฟผ๋ฆฌ๋Š” PHP์—์„œ ๋‹ค์Œ๊ณผ ๋™๋“ฑํ•ฉ๋‹ˆ๋‹ค:

function printPostProperties(int $postID, bool $addContent)
{
  $post = getPost($postID);
  echo $post->title;
  if ($addContent) {
    echo $post->content;
  }
}

๊ทธ๊ฒƒ์ด ๊ธฐ๋ณธ์ ์ธ ํ•œ๊ณ„์ž…๋‹ˆ๋‹ค. GraphQL์—๋Š” ์žฌ๊ท€, ๋™์  ๋ณ€์ˆ˜(๊ฐ’์ด ๋Ÿฐํƒ€์ž„์— ๊ณ„์‚ฐ๋˜์–ด ๋ณ€์ˆ˜์— ํ• ๋‹น๋˜๋Š” ๊ฒƒ์œผ๋กœ, ๋”•์…”๋„ˆ๋ฆฌ์— ์ž…๋ ฅ์œผ๋กœ ์ „๋‹ฌ๋˜๋Š” ๊ฒƒ์ด ์•„๋‹Œ), ๋ณ€์ˆ˜ ํ• ๋‹น(์˜ˆ: ํ•„๋“œ ์ถœ๋ ฅ์„ ๋ณ€์ˆ˜์— ํ• ๋‹นํ•˜๊ณ , ์ด๋ฅผ ๋‹ค๋ฅธ ํ•„๋“œ์˜ ์ธ์ˆ˜๋กœ ์ œ๊ณต) ๋“ฑ์ด ๋ถ€์กฑํ•ฉ๋‹ˆ๋‹ค.

GraphQL๋งŒ์„ ์‚ฌ์šฉํ•˜์—ฌ ๋‹ค์Œ ๋ฌธ์ œ๋ฅผ ์–ด๋–ป๊ฒŒ ํ•ด๊ฒฐํ• ์ง€ ์ƒ๊ฐํ•ด ๋ณด์„ธ์š”:

  • ์„œ๋น„์Šค์— ์ƒˆ๋กœ์šด ์‚ฌ์šฉ์ž๊ฐ€ ๊ฐ€์ž…ํ•  ๋•Œ๋งˆ๋‹ค ํ•ด๋‹น ์„œ๋น„์Šค์— ์˜ํ•ด ํ˜ธ์ถœ๋˜๋Š” ์›นํ›…์„ ๋งŒ๋“œ์„ธ์š”. ์‚ฌ์šฉ์ž๊ฐ€ ๋‰ด์Šค๋ ˆํ„ฐ๋ฅผ ๊ตฌ๋…ํ–ˆ์„ ์ˆ˜ ์žˆ์œผ๋ฉฐ(์›นํ›… ํŽ˜์ด๋กœ๋“œ์˜ marketing_optin ํ•„๋“œ๋กœ ํ‘œ์‹œ๋จ), ๊ทธ ๊ฒฝ์šฐ ์›นํ›…์€ ์‚ฌ์šฉ์ž์˜ ์ด๋ฉ”์ผ(์›นํ›… ํŽ˜์ด๋กœ๋“œ์˜ email ํ•„๋“œ)์„ Mailchimp ๋ชฉ๋ก์— ๋“ฑ๋กํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๊ฐ€๋Šฅํ•˜๋‹ค๊ณ  ์ƒ๊ฐํ•˜์‹œ๋‚˜์š”? ์‰ฝ๋‚˜์š”? ์–ด๋ ค์šด๊ฐ€์š”? ๋ถˆ๊ฐ€๋Šฅํ•œ๊ฐ€์š”?

Gato GraphQL์—์„œ๋Š” ์ด ๋ฌธ์ œ๋ฅผ GraphQL๋งŒ์œผ๋กœ ํ•ด๊ฒฐํ•˜๊ณ ์ž ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋” ๋งŽ์€ ๋ฌธ์ œ๋“ค๋„์š”. ๊ทธ๋ž˜์„œ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด์˜ ํŠน์„ฑ์„ ์ง€์›ํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ๊นŠ์ด ๊ณ ๋ฏผํ•ด ์™”์Šต๋‹ˆ๋‹ค.

GraphQL ์„œ๋ฒ„์—์„œ ์ง€์›ํ•œ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๊ธฐ๋Šฅ๋“ค์„ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ์ด ๊ธ€์˜ ๋งˆ์ง€๋ง‰์—์„œ ๊ทธ ๋ฌธ์ œ๋ฅผ ์–ด๋–ป๊ฒŒ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ํ™•์ธํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

๊ธฐ๋Šฅ์„ฑ(Functionality)

GraphQL์˜ ํ•„๋“œ๋Š” ๋ณดํ†ต ๊ฒŒ์‹œ๋ฌผ์˜ ์ œ๋ชฉ, ์ฝ˜ํ…์ธ , ๋ฐ์ดํ„ฐ์™€ ๊ฐ™์€ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ํ•„๋“œ๋ฅผ "๊ธฐ๋Šฅ์„ฑ"์œผ๋กœ ๊ตฌํ˜„ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด, PHP์—์„œ ์‹œ๊ฐ„์„ ์ถœ๋ ฅํ•˜๋Š” ๊ฒฝ์šฐ:

function printTime()
{
  echo time();
}

...์ด๊ฒƒ์€ GraphQL์˜ ํ•„๋“œ _time์œผ๋กœ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

{
  _time
}

ํ•จ์ˆ˜ time์€ ์–ด๋–ค ํƒ€์ž…์—๋„ ์†ํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ, ํ•„๋“œ _time๋„ ๋งˆ์ฐฌ๊ฐ€์ง€์ž…๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์ด๊ฒƒ์€ ๊ธ€๋กœ๋ฒŒ ํ•„๋“œ์ด๋ฉฐ, GraphQL ์Šคํ‚ค๋งˆ์˜ ๋ชจ๋“  ํƒ€์ž…์—์„œ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

{
  posts {
    _time
  }
}

๋‹ค๋ฅธ ๊ธฐ๋Šฅ์„ฑ ํ•„๋“œ์˜ ์˜ˆ์‹œ:

  • _arrayItem
  • _arrayJoin
  • _date
  • _equals
  • _inArray
  • _intAdd
  • _isEmpty
  • _isNull
  • _makeTime
  • _objectProperty
  • _sprintf
  • _strContains
  • _strRegexReplace
  • _strSubstr

ํ•จ์ˆ˜(Functions)

๋กœ์ง์˜ ๋‹จ์œ„๋ฅผ ํ•จ์ˆ˜๋กœ ๋ถ„ํ• ํ•˜๊ณ , ํ•œ ํ•จ์ˆ˜๊ฐ€ ๋‹ค๋ฅธ ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๋„๋ก ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

function printPostProperties(int $postID)
{
  $post = getPost($postID);
  printPostTitle();
  printPostContent();
}
 
function printPostTitle(Post $post)
{
  echo $post->title;
}
 
function printPostContent(Post $post)
{
  echo $post->content;
}

GraphQL์—์„œ๋„ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ, ๋ฌธ์„œ์˜ query(๋˜๋Š” mutation) ์ž‘์—…์„ ์—ฌ๋Ÿฌ query ์ž‘์—…์œผ๋กœ ๋ถ„ํ• ํ•˜๊ณ , ํ•œ ์ž‘์—…์ด ๋‹ค๋ฅธ ์ž‘์—…์— "์˜์กด"ํ•˜๋„๋ก ํ•˜์—ฌ ๋จผ์ € ์‹คํ–‰๋˜๊ฒŒ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

query PrintPostTitle($postID: ID!)
{
  postWithTitle: post(by: { id: $postID }) {
    title
  }
}
 
query PrintPostContent($postID: ID!)
{
  postWithContent: post(by: { id: $postID }) {
    content
  }
}
 
query PrintPostProperties
  @depends(on: [
    "PrintPostTitle",
    "PrintPostContent"
  ])
{
  # ...
}

์ด ์ฟผ๋ฆฌ์—์„œ ์—”๋“œํฌ์ธํŠธ์— ?operationName=PrintPostProperties๋ฅผ ์ „๋‹ฌํ•˜์—ฌ GraphQL ์ฟผ๋ฆฌ๋ฅผ ์‹คํ–‰ํ•˜๋ฉด, ๋จผ์ € PrintPostTitle๊ณผ PrintPostContent ์ฟผ๋ฆฌ๊ฐ€ ์‹คํ–‰๋˜๊ณ , ๊ทธ ํ›„์— PrintPostProperties๊ฐ€ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.

์ด๊ฒƒ์€ Multiple Query Execution์„ ํ†ตํ•ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

๋™์  ๋ณ€์ˆ˜(Dynamic Variables)

๊ฐ’์„ ๋Ÿฐํƒ€์ž„์— ๊ณ„์‚ฐํ•˜์—ฌ ๋ณ€์ˆ˜์— ํ• ๋‹นํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๋‹ค์Œ ๊ทธ ๊ฐ’์— ๋”ฐ๋ผ ์–ด๋–ค ๊ธฐ๋Šฅ์„ ์กฐ๊ฑด๋ถ€๋กœ ์‹คํ–‰ํ• ์ง€ ๊ฒฐ์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

function printPostProperties(int $postID)
{
  $post = getPost($postID);
  echo $post->title;
  
  $addContent = isUserLoggedIn();
  if ($addContent) {
    echo $post->content;
  }
}

GraphQL์—์„œ๋Š” ํ•œ ์ž‘์—…์—์„œ ๋™์  ๋ณ€์ˆ˜์— ๊ฐ’์„ "๋‚ด๋ณด๋‚ด๊ณ ", ๋‹ค๋ฅธ ์ž‘์—…์—์„œ ๊ทธ ๊ฐ’์„ ์ฝ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

query ExportAddContent
{
  addContent: isUserLoggedIn
    @export(as: "addContent")
}
 
query PrintPostProperties($postID: ID!)
  @depends(on: "ExportAddContent")
{
  post(by: { id: $postID }) {
    title
    content @include(if: $addContent)
  }
}

๋Ÿฐํƒ€์ž„์— ๊ณ„์‚ฐ๋œ ๊ฐ’์„ ๋ณด์œ ํ•˜๋Š” ๋ณ€์ˆ˜ $addContent๋Š” PrintPostProperties ์ž‘์—…์—์„œ ์ฝํžˆ์ง€๋งŒ, ํ•ด๋‹น ์ž‘์—…์—์„œ ์„ ์–ธ๋˜์ง€ ์•Š๋Š”๋‹ค๋Š” ์ ์— ์ฃผ๋ชฉํ•˜์„ธ์š”. ์ด๊ฒƒ์ด ๋™์  ๋ณ€์ˆ˜์ด๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

ํ•จ์ˆ˜์˜ ์กฐ๊ฑด๋ถ€ ์‹คํ–‰

์•ž์˜ ์˜ˆ์‹œ์˜ ๋Œ€์•ˆ์œผ๋กœ, ๋กœ์ง์„ ํ•จ์ˆ˜๋กœ ๊ทธ๋ฃนํ™”ํ•œ ๋‹ค์Œ ๋™์  ๋ณ€์ˆ˜์˜ ๊ฐ’์— ๋”ฐ๋ผ ํ•จ์ˆ˜๋ฅผ ์กฐ๊ฑด๋ถ€๋กœ ์‹คํ–‰ํ• ์ง€ ๊ฒฐ์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

function printPostProperties(int $postID)
{
  $post = getPost($postID);
  printPostTitle();
  
  $addContent = isUserLoggedIn();
  if ($addContent) {
    printPostContent();
  }
}
 
function printPostTitle(Post $post)
{
  echo $post->title;
}
 
function printPostContent(Post $post)
{
  echo $post->content;
}

GraphQL์—์„œ๋Š” ์ž‘์—…์— @include ๋””๋ ‰ํ‹ฐ๋ธŒ๋ฅผ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

query ExportAddContent
{
  addContent: isUserLoggedIn
    @export(as: "addContent")
}
 
query PrintPostTitle($postID: ID!)
{
  postWithTitle: post(by: { id: $postID }) {
    title
  }
}
 
query PrintPostContent($postID: ID!)
  @depends(on: "ExportAddContent")
  @include(if: $addContent)
{
  postWithContent: post(by: { id: $postID }) {
    content
  }
}
 
query PrintPostProperties
  @depends(on: [
    "PrintPostTitle",
    "PrintPostContent"
  ])
{
  # ...
}

์ด์ œ $addContent๊ฐ€ true์ธ ๊ฒฝ์šฐ์—๋งŒ PrintPostContent ์ž‘์—…์ด ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.

๋ณ€์ˆ˜ ํ• ๋‹น ๋ฐ ์žฌ์ž…๋ ฅ

์•ž์˜ ์˜ˆ์‹œ๋ฅผ ์กฐ๊ธˆ ์ˆ˜์ •ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ์•ž์˜ ์˜ˆ์‹œ์—์„œ๋Š” ์กฐ๊ฑด "addContent"๊ฐ€ ์‚ฌ์šฉ์ž์˜ ๋กœ๊ทธ์ธ ์—ฌ๋ถ€์— ์—ฐ๊ฒฐ๋˜์–ด ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

์ด ๋‹ค๋ฅธ ์˜ˆ์‹œ์—์„œ๋Š”, "addContent"๋Š” ์˜ค๋Š˜์ด ์ฃผ๋ง์ผ ๋•Œ true๊ฐ€ ๋ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ๊ณ„์‚ฐํ•˜๊ธฐ ์œ„ํ•œ ๋กœ์ง์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค:

  • ์˜ค๋Š˜ ๋‚ ์งœ ๊ฐ€์ ธ์˜ค๊ธฐ
  • ๋‚ ์งœ๋ฅผ ์š”์ผ ์ด๋ฆ„(์†Œ๋ฌธ์ž)์œผ๋กœ ํ˜•์‹ํ™”ํ•˜๊ธฐ
  • "saturday" ๋˜๋Š” "sunday"์ธ์ง€ ํ™•์ธํ•˜๊ธฐ

PHP์˜ ๊ฒฝ์šฐ:

function addContent()
{
  $today = time();
  $dayName = date('l', $today);
  $lcDayName = strtolower($dayName);
  $isWeekend = in_array(
    $lcDayName,
    ['saturday', 'sunday']
  );
  return $isWeekend;
}
 
function printPostProperties(int $postID)
{
  $post = getPost($postID);
  echo $post->title;
 
  $addContent = addContent();
  if ($addContent) {
    echo $post->content;
  }
}

GraphQL์˜ ๊ฒฝ์šฐ:

query ExportAddContent
{
  today: _time
  dayName: _date(format: "l", timestamp: $__today)
  lcDayName: _strLowerCase(text: $__dayName)
  isWeekend: _inArray(
    value: $__lcDayName
    array: ["saturday", "sunday"],
  )
    @export(as: "addContent")
}
 
query PrintPostProperties($postID: ID!)
  @depends(on: "ExportAddContent")
{
  post(by: { id: $postID }) {
    title
    content @include(if: $addContent)
  }
}

ExportAddContent ์ž‘์—…์—์„œ ์ฟผ๋ฆฌ๋œ ๊ฐ ํ•„๋“œ์˜ ๊ฐ’์€ ๋™์  ๋ณ€์ˆ˜ $__fieldName์œผ๋กœ ์•„๋ž˜ ํ•„๋“œ์—์„œ ์ฆ‰์‹œ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ํ•„๋“œ์˜ ์ถœ๋ ฅ์„ ๊ฐ™์€ ์ž‘์—… ๋‚ด์—์„œ ์ฆ‰์‹œ ๋‹ค๋ฅธ ํ•„๋“œ์˜ ์ž…๋ ฅ์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๊ฒƒ์€ Field to Input์„ ํ†ตํ•ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

๊ฐ’์˜ ๋™์  ์ˆ˜์ •

์ด PHP ์˜ˆ์‹œ์—์„œ๋Š” ๋กœ๊ทธ์ธํ•œ ์‚ฌ์šฉ์ž๊ฐ€ ๊ด€๋ฆฌ์ž์ธ ๊ฒฝ์šฐ ๋ณ€์ˆ˜์˜ ๊ฐ’์„ ์ˆ˜์ •ํ•˜์—ฌ, ๊ทธ ๊ฒฝ์šฐ ๊ฒŒ์‹œ๋ฌผ ์ฝ˜ํ…์ธ ์— ๊ฒŒ์‹œ๋ฌผ ํŽธ์ง‘ ๋งํฌ๋ฅผ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค:

function isAdminUser()
{
  $user = getCurrentUser();
  return in_array("administrator", $user->roles);
}
 
function printPostContent(int $postID)
{
  $post = getPost($postID);
  $postContent = $post->content;
 
  $isAdminUser = isAdminUser();
  if ($isAdminUser) {
    $postContent = sprintf(
      '%s<p><a href="%s">%s</a></p>',
      $postContent,
      $post->edit_url,
      '(Admin only) Edit post'
    ) 
  }
 
  echo $postContent;
}

GraphQL์—์„œ๋Š” ํŠน์ • ํ•„๋“œ์— ๋Œ€ํ•ด ๋‹ค๋ฅธ ๊ฐ’์„ ์ƒ์„ฑํ•˜๋Š” ์ž‘์—… ๋˜๋Š” ๋‹ค๋ฅธ ์ž‘์—…์„ ์กฐ๊ฑด๋ถ€๋กœ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

query InitializeDynamicVariables
{
  isAdminUser: _echo(value: false)
    @export(as: "isAdminUser")
}
 
query ExportConditionalVariables
  @depends(on: "InitializeDynamicVariables")
{
  me {
    roleNames
    isAdminUser: _inArray(
      value: "administrator",
      array: $__roleNames
    )
      @export(as: "isAdminUser")
  }
}
 
query RetrieveContentForAdminUser($postId: ID!)
  @depends(on: "ExportConditionalVariables")
  @include(if: $isAdminUser)
{
  post(by: { id : $postId }) {
    originalContent: content
    wpAdminEditURL
    content: _sprintf(
      string: "%s<p><a href=\"%s\">%s</a></p>",
      values: [
        $__originalContent,
        $__wpAdminEditURL,
        "(Admin only) Edit post"
      ]
    )
  }
}
 
query RetrieveContentForNonAdminUser($postId: ID!)
  @depends(on: "ExportConditionalVariables")
  @skip(if: $isAdminUser)
{
  post(by: { id : $postId }) {
    content
  }
}
 
query ExecuteAll
  @depends(on: [
    "RetrieveContentForAdminUser",
    "RetrieveContentForNonAdminUser"
  ])
{
  # ...
}

๊ฐ™์€ ๋™์  ๋ณ€์ˆ˜๋ฅผ ์ž…๋ ฅ์œผ๋กœ @include์™€ @skip ๋””๋ ‰ํ‹ฐ๋ธŒ๋ฅผ ์‚ฌ์šฉํ•จ์œผ๋กœ์จ, RetrieveContentForAdminUser์™€ RetrieveContentForNonAdminUser ์ž‘์—…์€ ์ƒํ˜ธ ๋ฐฐํƒ€์ ์ด ๋ฉ๋‹ˆ๋‹ค.

๋ฐฐ์—ด ๋ฐ˜๋ณต ์ฒ˜๋ฆฌ

๋ฐฐ์—ด์˜ ํ•ญ๋ชฉ์„ ๋ฐ˜๋ณต ์ฒ˜๋ฆฌํ•˜์—ฌ ํ•ด๋‹น ๊ฐ’๋“ค์„ ๋Œ€๋ฌธ์ž๋กœ ๋ณ€ํ™˜ํ•˜๊ณ  ์‹ถ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด ๋ด…์‹œ๋‹ค:

function printUserRolesAsUppercase(int $userID)
{
  $user = getUser($userID);
  foreach ($user->roles as $role) {
    echo strtoupper($role);
  }
}

GraphQL์—์„œ๋Š” ๋””๋ ‰ํ‹ฐ๋ธŒ @underEachArrayItem์œผ๋กœ ๋ฐฐ์—ด ํ•ญ๋ชฉ์„ ๋ฐ˜๋ณต ์ฒ˜๋ฆฌํ•˜๊ณ , ๊ฐ ๊ฐ’์„ ์ฒด์ธ์˜ ๋‹ค์Œ ๋””๋ ‰ํ‹ฐ๋ธŒ(์ด ๊ฒฝ์šฐ @strUpperCase)์— ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

query PrintUserRolesAsUppercase($userID: ID!)
{
  user(by: { id: $userID }) {
    roles
      @underEachArrayItem
        @strUpperCase
  }
}

์ด๊ฒƒ์€ ์ปดํฌ์ €๋ธ” ๋””๋ ‰ํ‹ฐ๋ธŒ๋ฅผ ํ†ตํ•ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

๋Œ€๋Ÿ‰ CRUD ์ž‘์—…

CRUD๋Š” Create(์ƒ์„ฑ), Read(์ฝ๊ธฐ), Update(์ˆ˜์ •), Delete(์‚ญ์ œ)์˜ ์•ฝ์ž๋กœ, ๋ฆฌ์†Œ์Šค(๊ฒŒ์‹œ๋ฌผ, ์‚ฌ์šฉ์ž ๋“ฑ)์— ์ ์šฉํ•˜๋Š” ์ž‘์—…์ž…๋‹ˆ๋‹ค.

PHP์—์„œ ๋Œ€๋Ÿ‰ ์ฝ๊ธฐ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค:

function getPostTitles()
{
  $posts = getPosts();
  foreach ($posts as $post) {
    echo $post->title;
  }
}

์ด ์œ ์Šค์ผ€์ด์Šค๋Š” GraphQL์—์„œ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ํ•ด๊ฒฐ๋ฉ๋‹ˆ๋‹ค:

query GetPostTitles
{
  posts {
    title
  }
}

PHP์—์„œ ๋Œ€๋Ÿ‰ ์ˆ˜์ •์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค:

function updatePostTitlesAsUppercase()
{
  $posts = getPosts();
  foreach ($posts as $post) {
    $post->update(['title' => strtoupper($post->title)]);
  }
}

GraphQL์—์„œ ๋Œ€๋Ÿ‰ ์ˆ˜์ •์€ ๋ณดํ†ต ๋ชจ๋“  ๊ฒŒ์‹œ๋ฌผ์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›๋Š” ์ „์šฉ mutation updatePosts๋ฅผ ์ƒ์„ฑํ•˜์—ฌ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค.

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

  • updatePost + updatePosts
  • createPost + createPosts
  • ๋“ฑ

์ œ ์ƒ๊ฐ์—๋Š” ๋” ์šฐ์•„ํ•œ ์ ‘๊ทผ ๋ฐฉ์‹์€ ์ค‘์ฒฉ mutation์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ mutation Post.update๊ฐ€ ์ฟผ๋ฆฌ๋œ ๊ฐ ๋ฆฌ์†Œ์Šค์— ์ ์šฉ๋ฉ๋‹ˆ๋‹ค:

mutation UpdatePostTitlesAsUppercase
{
  posts {
    title
    ucTitle: _strUpperCase(text: $__title)
    update(
      input: { title: $__ucTitle }
    ) {
      status
      post {
        title
      }
    }
  }
}

๊ฐ™์€ ์ ‘๊ทผ ๋ฐฉ์‹์ด ๋ฆฌ์†Œ์Šค ์‚ญ์ œ์—๋„ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค:

function deletePosts()
{
  $posts = getPosts();
  foreach ($posts as $post) {
    $post->delete();
  }
}

GraphQL์˜ ๊ฒฝ์šฐ:

mutation DeletePosts
{
  posts {
    delete {
      status
    }
  }
}

์ƒ์„ฑ์˜ ๊ฒฝ์šฐ, ๋ฆฌ์†Œ์Šค๊ฐ€ ์•„์ง ์กด์žฌํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ ์ „๋‹ฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋Œ€์‹ , ์ƒ์„ฑํ•  ๋ชจ๋“  ๋ฆฌ์†Œ์Šค์˜ ๋ฐ์ดํ„ฐ ์ž…๋ ฅ์ด ๋‹ด๊ธด ๋ฐฐ์—ด์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค:

function createPosts()
{
  $postDataItems = [
    [
      'title' => 'First title',
      'content' => 'First content',
    ],
    [
      'title' => 'Second title',
      'content' => 'Second content',
    ],
  ];
  foreach ($postDataItems as $postDataItem) {
    $post = new Post($postDataItem['title'], $postDataItem['content']);
    $post->save();
  }
}

๋‹จ์ผ createPost mutation์„ ์‚ฌ์šฉํ•˜์—ฌ GraphQL์—์„œ ๋Œ€๋Ÿ‰์œผ๋กœ ๊ฒŒ์‹œ๋ฌผ์„ ์ƒ์„ฑํ•˜๋Š” ๊ฒƒ์€ ๋‹ค์†Œ ๋ณต์žกํ•˜์ง€๋งŒ ์ถฉ๋ถ„ํžˆ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

์•„์ด๋””์–ด๋Š” ๋ฐ์ดํ„ฐ ์ž…๋ ฅ ๋ฐฐ์—ด์„ ๋ฐ˜๋ณต ์ฒ˜๋ฆฌํ•˜๊ณ , ๊ฐ๊ฐ์„ ๋™์  ๋ณ€์ˆ˜ $input์— ํ• ๋‹นํ•œ ๋‹ค์Œ, ๊ทธ ์ž…๋ ฅ์„ ์ „๋‹ฌํ•˜์—ฌ createPost mutation์„ ์‹คํ–‰ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋งˆ์ง€๋ง‰์œผ๋กœ ๋™์  ๋ณ€์ˆ˜ $createdPostIDs์—์„œ ์ƒ์„ฑ๋œ ๊ฒŒ์‹œ๋ฌผ์˜ ๊ฒฐ๊ณผ ID๋ฅผ ๊ฐ€์ ธ์™€ ํ•ด๋‹น ๋ฐ์ดํ„ฐ๋ฅผ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค:

mutation CreatePosts
  @depends(on: "GetPostsAndExportData")
{
  createdPostIDs: _echo(value: [
    {
      title: "First title",
      content: "First content"
    },
    {
      title: "Second title",
      content: "Second content"
    },
  ])
    @underEachArrayItem(
      passValueOnwardsAs: "input"
    )
      @applyField(
        name: "createPost"
        arguments: {
          input: $input
        },
        setResultInResponse: true
      )
    @export(as: "createdPostIDs")
}
 
query RetrieveCreatedPosts
  @depends(on: "CreatePosts")
{
  createdPosts: posts(
    filter: {
      ids: $createdPostIDs,
    }
  ) {
    title
    content
  }
}

HTTP ์š”์ฒญ ์ „์†ก(๋ฐ ๊ธฐํƒ€ ํ•จ์ˆ˜)

์›น ์„œ๋ฒ„์— HTTP ์š”์ฒญ์„ ์ „์†กํ•˜๋Š” ๊ฒƒ์€ PHP์—์„œ file_get_contents๋‚˜ curl_exec ๊ฐ™์€ ์ „์šฉ ํ•จ์ˆ˜๋กœ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

file_get_contents ์‚ฌ์šฉ:

$xml = file_get_contents("http://www.example.com/file.xml");

GraphQL์—์„œ๋Š” HTTP ์š”์ฒญ ์‹คํ–‰ ๋กœ์ง์„ _sendHTTPRequest์™€ ๊ฐ™์€ ๊ธฐ๋Šฅ์„ฑ ํ•„๋“œ๋กœ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

query {
  _sendHTTPRequest(input: {
    url: "http://www.example.com/file.xml",
    method: GET
  }) {
    xml: body
  }
}

๊ฐ™์€ ๊ฐœ๋…์ด ๋ชจ๋“  ๊ธฐ๋Šฅ์— ์ ์šฉ๋ฉ๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด, PHP์—์„œ ์ƒ์ˆ˜ ๊ฐ’์—๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ ‘๊ทผํ•ฉ๋‹ˆ๋‹ค:

$mailchimpUsername = constant('MAILCHIMP_API_CREDENTIALS_USERNAME');

GraphQL์—์„œ ํ•ด๋‹นํ•˜๋Š” ๊ธฐ๋Šฅ์„ฑ ํ•„๋“œ๋ฅผ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

{
  mailchimpUsername: _env(name: "MAILCHIMP_API_CREDENTIALS_USERNAME")
}

GraphQL๋งŒ์„ ์‚ฌ์šฉํ•˜์—ฌ ๊ณผ์ œ ํ•ด๊ฒฐํ•˜๊ธฐ

์ง€๊ธˆ๊นŒ์ง€ ์‚ดํŽด๋ณธ ๋ชจ๋“  ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜์—ฌ, ์•ž์„œ ์ œ์‹œํ•œ ๋ฌธ์ œ๋ฅผ GraphQL๋งŒ์œผ๋กœ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค:

  • ์„œ๋น„์Šค์— ์ƒˆ๋กœ์šด ์‚ฌ์šฉ์ž๊ฐ€ ๊ฐ€์ž…ํ•  ๋•Œ๋งˆ๋‹ค ํ•ด๋‹น ์„œ๋น„์Šค์— ์˜ํ•ด ํ˜ธ์ถœ๋˜๋Š” ์›นํ›…์„ ๋งŒ๋“œ์„ธ์š”. ์‚ฌ์šฉ์ž๊ฐ€ ๋‰ด์Šค๋ ˆํ„ฐ๋ฅผ ๊ตฌ๋…ํ–ˆ์„ ์ˆ˜ ์žˆ์œผ๋ฉฐ(์›นํ›… ํŽ˜์ด๋กœ๋“œ์˜ marketing_optin ํ•„๋“œ๋กœ ํ‘œ์‹œ๋จ), ๊ทธ ๊ฒฝ์šฐ ์›นํ›…์€ ์‚ฌ์šฉ์ž์˜ ์ด๋ฉ”์ผ(์›นํ›… ํŽ˜์ด๋กœ๋“œ์˜ email ํ•„๋“œ)์„ Mailchimp ๋ชฉ๋ก์— ๋“ฑ๋กํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

ํ•ด๊ฒฐ์ฑ…์€ GraphQL ํผ์‹œ์Šคํ‹ฐ๋“œ ์ฟผ๋ฆฌ๋ฅผ ์›นํ›…์œผ๋กœ ์‚ฌ์šฉํ•˜๊ณ , ๋‹ค์Œ ์ฟผ๋ฆฌ๋ฅผ ์‹คํ–‰ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค:

query HasSubscribedToNewsletter {
  hasSubscriberOptIn: _httpRequestHasParam(name: "marketing_optin")
  subscriberOptIn: _httpRequestStringParam(name: "marketing_optin")
  isNotSubscriberOptInNAValue: _notEquals(value1: $__subscriberOptIn, value2: "NA")
  subscribedToNewsletter: _and(values: [$__hasSubscriberOptIn, $__isNotSubscriberOptInNAValue])
    @export(as: "subscribedToNewsletter")
}
 
query MaybeCreateContactOnMailchimp
   @depends(on: "HasSubscribedToNewsletter")
   @include(if: $subscribedToNewsletter)
{
  subscriberEmail: _httpRequestStringParam(name: "email")
  
  mailchimpUsername: _env(name: "MAILCHIMP_API_CREDENTIALS_USERNAME")
   
  mailchimpPassword: _env(name: "MAILCHIMP_API_CREDENTIALS_PASSWORD")
   
  
  mailchimpListMembersJSONObject: _sendJSONObjectItemHTTPRequest(input: {
    url: "https://us7.api.mailchimp.com/3.0/lists/{listCode}/members",
    method: POST,
    options: {
      auth: {
        username: $__mailchimpUsername,
        password: $__mailchimpPassword
      },
      json: {
        email_address: $__subscriberEmail,
        status: "subscribed"
      }
    }
  })
}

์ด ํ•ด๊ฒฐ์ฑ…์—์„œ, Mailchimp API์— HTTP ์š”์ฒญ์„ ์‹คํ–‰ํ•˜๋Š” MaybeCreateContactOnMailchimp ์ž‘์—…์€ marketing_optin ํ•„๋“œ์˜ ๊ฐ’์— ๋”ฐ๋ผ ์กฐ๊ฑด๋ถ€๋กœ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.

(์ด ์ฟผ๋ฆฌ์˜ ๋™์ž‘ ๋ฐฉ์‹์€ ๋ธ”๋กœ๊ทธ ๊ฒŒ์‹œ๋ฌผ ๐Ÿ‘จ๐Ÿปโ€๐Ÿซ GraphQL query to automatically send the newsletter subscribers from InstaWP to Mailchimp์—์„œ ํ™•์ธํ•˜์„ธ์š”.)

GraphQL์€ ์ƒ๊ฐํ–ˆ๋˜ ๊ฒƒ๋ณด๋‹ค ํ›จ์”ฌ ๊ฐ•๋ ฅํ•ฉ๋‹ˆ๋‹ค!

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

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

GraphQL์€ ์ •๋ง ๋Œ€๋‹จํ•ฉ๋‹ˆ๋‹ค ๐Ÿค˜


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

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