๋ธ”๋กœ๊ทธ

๐Ÿ‘จ๐Ÿปโ€๐Ÿซ InstaWP์˜ ๋‰ด์Šค๋ ˆํ„ฐ ๊ตฌ๋…์ž๋ฅผ Mailchimp๋กœ ์ž๋™ ์ „์†กํ•˜๋Š” GraphQL ์ฟผ๋ฆฌ

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

(์ด ์ฟผ๋ฆฌ์˜ ๋ฐฐ๊ฒฝ์— ๋Œ€ํ•ด์„œ๋Š” ๋ธ”๋กœ๊ทธ ๊ฒŒ์‹œ๋ฌผ ๐Ÿš€ InstaWP์˜ ๋‰ด์Šค๋ ˆํ„ฐ ๊ตฌ๋…์ž๋ฅผ Mailchimp๋กœ ์ž๋™ ์ „์†กํ•˜๊ธฐ ๋ฅผ ์ฝ์–ด ๋ณด์„ธ์š”.)

์ด GraphQL ์ฟผ๋ฆฌ๋Š” InstaWP์—์„œ ์ƒˆ ์ƒŒ๋“œ๋ฐ•์Šค ์‚ฌ์ดํŠธ๋ฅผ ์ƒ์„ฑํ•  ๋•Œ ใ€ŒSubscribe to mailing listใ€ ์ฒดํฌ๋ฐ•์Šค๋ฅผ ์„ ํƒํ•œ ๋ฐฉ๋ฌธ์ž์˜ ์ด๋ฉ”์ผ ์ฃผ์†Œ๋ฅผ ์บก์ฒ˜ํ•˜์—ฌ Mailchimp ๋ชฉ๋ก์— ๊ตฌ๋… ๋“ฑ๋กํ•ฉ๋‹ˆ๋‹ค.

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")
    @remove
  mailchimpPassword: _env(name: "MAILCHIMP_API_CREDENTIALS_PASSWORD")
    @remove
  
  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"
      }
    }
  })
}

๋˜๋Š”, WordPress ๋‰ด์Šค๋ ˆํ„ฐ ํ”Œ๋Ÿฌ๊ทธ์ธ๏ผˆ์˜ˆ: Noptin ๋“ฑ๏ผ‰์— ๊ตฌ๋…์ž๋ฅผ ๋“ฑ๋กํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด GraphQL ์ฟผ๋ฆฌ๊ฐ€ ์–ด๋–ป๊ฒŒ ์ž‘๋™ํ•˜๋Š”์ง€ ์ž์„ธํžˆ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

GraphQL ์ฟผ๋ฆฌ๋ฅผ ๋…๋ฆฝ์ ์ธ ๋‹จ์œ„๋กœ ๋ถ„๋ฆฌํ•˜๊ธฐ

GraphQL ๋ฌธ์„œ์—๋Š” ์—ฌ๋Ÿฌ ์˜คํผ๋ ˆ์ด์…˜๏ผˆ์ฟผ๋ฆฌ์™€ ๋ฎคํ…Œ์ด์…˜๏ผ‰์„ ํฌํ•จํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, ์‹คํ–‰๋˜๋Š” ๊ฒƒ์€ ๊ทธ ์ค‘ ํ•˜๋‚˜๋ฟ์ž…๋‹ˆ๋‹ค. GraphQL ์—”๋“œํฌ์ธํŠธ์˜ ?operationName=... ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ์–ด๋А ๊ฒƒ์„ ์‹คํ–‰ํ• ์ง€ ์ง€์ •ํ•˜๋ฉฐ, ์ง€์ •ํ•˜์ง€ ์•Š์œผ๋ฉด ๋งˆ์ง€๋ง‰ ์˜คํผ๋ ˆ์ด์…˜์ด ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.

์œ„ ๋ฌธ์„œ์—๋Š” 2๊ฐœ์˜ query ์˜คํผ๋ ˆ์ด์…˜์ด ์žˆ๋‹ค๋Š” ์ ์— ์ฃผ๋ชฉํ•˜์„ธ์š”.

  1. HasSubscribedToNewsletter
  2. MaybeCreateContactOnMailchimp

Webhook URL์—๋Š” ?operationName=MaybeCreateContactOnMailchimp ๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ์œผ๋ฏ€๋กœ, ํ•ด๋‹น ์˜คํผ๋ ˆ์ด์…˜์ด ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.

Multiple Query Execution ํ™•์žฅ ๊ธฐ๋Šฅ ๋•๋ถ„์—, MaybeCreateContactOnMailchimp ๋Š” @depends ๋””๋ ‰ํ‹ฐ๋ธŒ์— ์ง€์ •๋œ ๋Œ€๋กœ ๋จผ์ € HasSubscribedToNewsletter ๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.

query MaybeCreateContactOnMailchimp
   @depends(on: "HasSubscribedToNewsletter")
   # ...
{
  #
}

๋˜ํ•œ, MaybeCreateContactOnMailchimp ๋Š” ์กฐ๊ฑด๋ถ€๋กœ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค. ๋ณ€์ˆ˜ $subscribedToNewsletter ์˜ ๊ฐ’์ด true ์ธ ๊ฒฝ์šฐ์—๋งŒ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.

query MaybeCreateContactOnMailchimp
   @depends(on: "HasSubscribedToNewsletter")
   @include(if: $subscribedToNewsletter)
{
  #
}

$subscribedToNewsletter ๋Š” ๋™์  ๋ณ€์ˆ˜ ๋กœ, HasSubscribedToNewsletter ์˜คํผ๋ ˆ์ด์…˜ ๋‚ด์—์„œ export๋ฉ๋‹ˆ๋‹ค.

query HasSubscribedToNewsletter {
  # ...
  subscribedToNewsletter: _and(values: [$__hasSubscriberOptIn, $__isNotSubscriberOptInNAValue])
    @export(as: "subscribedToNewsletter")
}

๋”ฐ๋ผ์„œ, MaybeCreateContactOnMailchimp ์˜คํผ๋ ˆ์ด์…˜์€ ์‚ฌ์šฉ์ž๊ฐ€ ใ€ŒSubscribe to mailing listใ€ ์ฒดํฌ๋ฐ•์Šค๋ฅผ ์„ ํƒํ•œ ๊ฒฝ์šฐ์—๋งŒ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.

์‚ฌ์šฉ์ž๊ฐ€ ์ฒดํฌ๋ฐ•์Šค๋ฅผ ์„ ํƒํ–ˆ๋Š”์ง€ ํ™•์ธํ•˜๊ธฐ

InstaWP์˜ Webhook ๋ฌธ์„œ ์—๋Š” ํŽ˜์ด๋กœ๋“œ ๋ฐ์ดํ„ฐ์— ๋‹ค์Œ ํ•„๋“œ๊ฐ€ ํฌํ•จ๋œ๋‹ค๊ณ  ๋ช…์‹œ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค๏ผˆ๋‹ค๋ฅธ ํ•„๋“œ๋„ ์žˆ์Šต๋‹ˆ๋‹ค๏ผ‰.

  • marketing_optin: ์‚ฌ์šฉ์ž๊ฐ€ ์ฒดํฌ๋ฐ•์Šค๋ฅผ ์„ ํƒํ–ˆ๋Š”์ง€ ์—ฌ๋ถ€๋ฅผ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค
  • email: ๋ฐฉ๋ฌธ์ž์˜ ์ด๋ฉ”์ผ ์ฃผ์†Œ

๋ฌธ์„œ์—๋Š” ์ฒดํฌ๋ฐ•์Šค๊ฐ€ ์„ ํƒ๋˜์ง€ ์•Š์€ ๊ฒฝ์šฐ marketing_optin ํ•„๋“œ์˜ ๊ฐ’์ด NA ๊ฐ€ ๋œ๋‹ค๊ณ ๋งŒ ์„ค๋ช…๋˜์–ด ์žˆ์œผ๋ฏ€๋กœ, ์ด๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ์ฒ˜๋ฆฌํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

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

  • marketing_optin ํ•„๋“œ๊ฐ€ ์กด์žฌํ•˜๋Š”์ง€ ํ™•์ธํ•˜๊ณ ,
  • ๊ทธ ๊ฐ’์ด NA ๊ฐ€ ์•„๋‹Œ์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค

์ด ์ฒ˜๋ฆฌ๋Š” HasSubscribedToNewsletter ์˜คํผ๋ ˆ์ด์…˜์—์„œ ์ด๋ฃจ์–ด์ง‘๋‹ˆ๋‹ค. ๊ฐ ์ค„์ด ๋ฌด์—‡์„ ํ•˜๋Š”์ง€ ์ฃผ์„์œผ๋กœ ์„ค๋ช…ํ•œ ํ˜•ํƒœ๋กœ ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค.

query HasSubscribedToNewsletter {
 
  # Check if field `marketing_optin` is present
  hasSubscriberOptIn: _httpRequestHasParam(name: "marketing_optin")
 
  # Get the value of field `marketing_optin`
  subscriberOptIn: _httpRequestStringParam(name: "marketing_optin")
 
  # Check if the value of the field is not "NA"
  isNotSubscriberOptInNAValue: _notEquals(value1: $__subscriberOptIn, value2: "NA")
 
  # Perform an AND operation: field present && value != "NA"
  subscribedToNewsletter: _and(values: [$__hasSubscriberOptIn, $__isNotSubscriberOptInNAValue])
    
    # Export the result under dynamic variable $subscribedToNewsletter
    @export(as: "subscribedToNewsletter")
}

์ด ์ฟผ๋ฆฌ์—๋Š” ๋ช‡ ๊ฐ€์ง€ ํฅ๋ฏธ๋กœ์šด ์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

๊ธ€๋กœ๋ฒŒ ํ•„๋“œ

_ ๋กœ ์‹œ์ž‘ํ•˜๋Š” ํ•„๋“œ๋ฅผ ๋ฐœ๊ฒฌํ•˜์…จ๋‚˜์š”? ๊ตฌ์ฒด์ ์œผ๋กœ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  • _httpRequestHasParam
  • _httpRequestStringParam
  • _notEquals
  • _and

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

Field to Input

$__ ๋กœ ์‹œ์ž‘ํ•˜๋Š” ๋ณ€์ˆ˜๋ฅผ ๋ฐœ๊ฒฌํ•˜์…จ๋‚˜์š”? ๊ตฌ์ฒด์ ์œผ๋กœ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  • $__subscriberOptIn
  • $__hasSubscriberOptIn
  • $__isNotSubscriberOptInNAValue

์ด๊ฒƒ๋“ค์€ ๋™์  ๋ณ€์ˆ˜๋กœ, ๋™์ผํ•œ ์˜คํผ๋ ˆ์ด์…˜ ๋‚ด์—์„œ ๊ทธ ์ด์ „์— ์ •์˜๋œ ํ•„๋“œ์˜ ๊ฐ’์„ ๋ณด์œ ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ๋ณ€์ˆ˜ $__subscriberOptIn ์—๋Š” ๊ทธ ์œ„์— ์„ ์–ธ๋œ ํ•„๋“œ subscriberOptIn ์˜ ๊ฐ’์ด ์ €์žฅ๋ฉ๋‹ˆ๋‹ค.

์ด ๊ธฐ๋Šฅ์€ Field to Input ํ™•์žฅ ๊ธฐ๋Šฅ์—์„œ ์ œ๊ณตํ•˜๋ฉฐ, ํ•œ ํ•„๋“œ์˜ ์ถœ๋ ฅ์„ ๋‹ค๋ฅธ ํ•„๋“œ์˜ ์ž…๋ ฅ์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด ์ค๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด GraphQL ์ฟผ๋ฆฌ ๋‚ด์— ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด ์ฟผ๋ฆฌ์—์„œ๋Š”, ํ•„๋“œ isNotSubscriberOptInNAValue ๊ฐ€ ์ด์ „์— ์ฟผ๋ฆฌํ•œ ํ•„๋“œ subscriberOptIn ์˜ ๊ฐ’์ด "NA" ์™€ ๊ฐ™์ง€ ์•Š์€์ง€ ํ™•์ธํ•˜๊ณ , subscribedToNewsletter ๊ฐ€ ํ•„๋“œ hasSubscriberOptIn ๊ณผ isNotSubscriberOptInNAValue ์˜ ๊ฐ’์„ ์ด์šฉํ•œ AND ์—ฐ์‚ฐ์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

Mailchimp์— ์—ฐ๊ฒฐํ•˜๊ธฐ

MaybeCreateContactOnMailchimp ์˜คํผ๋ ˆ์ด์…˜์—๋Š” ํŽ˜์ด๋กœ๋“œ ๋ฐ์ดํ„ฐ๋ฅผ ์ถ”์ถœํ•˜๊ณ  Mailchimp API๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ์ด๋ฉ”์ผ ์ฃผ์†Œ๋ฅผ ๋‰ด์Šค๋ ˆํ„ฐ ๋ชฉ๋ก์— ๋“ฑ๋กํ•˜๋Š” ๋กœ์ง์ด ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

๊ฐ ์ค„์ด ๋ฌด์—‡์„ ํ•˜๋Š”์ง€ ์ฃผ์„์œผ๋กœ ์„ค๋ช…ํ•œ ํ˜•ํƒœ๋กœ ์˜คํผ๋ ˆ์ด์…˜์„ ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค.

query MaybeCreateContactOnMailchimp
   @depends(on: "HasSubscribedToNewsletter")
   @include(if: $subscribedToNewsletter)
{
  # Extract form field `email` from the body of the request
  subscriberEmail: _httpRequestStringParam(name: "email")
  
  # Obtain Mailchimp credentials, defined in wp-config.php
  mailchimpUsername: _env(name: "MAILCHIMP_API_CREDENTIALS_USERNAME")
    # Do not print the credentials in the response
    @remove
  mailchimpPassword: _env(name: "MAILCHIMP_API_CREDENTIALS_PASSWORD")
    @remove
  
  # Connect to Mailchimp to add a new member to the list
  mailchimpListMembersJSONObject: _sendJSONObjectItemHTTPRequest(input: {
    url: "https://us7.api.mailchimp.com/3.0/lists/{listCode}/members",
    method: POST,
    options: {
      # Provide credentials to connect to the API
      auth: {
        username: $__mailchimpUsername,
        password: $__mailchimpPassword
      },
      # Provide form data
      json: {
        email_address: $__subscriberEmail,
        status: "subscribed"
      }
    }
  })
}

์ด ์ฟผ๋ฆฌ์—์„œ ์‚ฌ์šฉ๋œ ๊ธฐ๋Šฅ๋“ค์„ ์ž์„ธํžˆ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

ํ™˜๊ฒฝ ๋ณ€์ˆ˜

Mailchimp API์— ์—ฐ๊ฒฐํ•  ๋•Œ๋Š” ์ธ์ฆ ์ •๋ณด๋ฅผ ์ œ๊ณตํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ธ์ฆ ์ •๋ณด๋ฅผ GraphQL ์ฟผ๋ฆฌ์— ์ง์ ‘ ์ž…๋ ฅํ•˜๋Š” ๊ฒƒ์€ ํ”ผํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์–ด๋”˜๊ฐ€์— ์œ ์ถœ๋  ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค๏ผˆ์˜ˆ: ๋กœ๊ทธ์— ์ถœ๋ ฅ๋  ์ˆ˜ ์žˆ์Œ๏ผ‰.

๊ทธ๋ž˜์„œ ๊ธ€๋กœ๋ฒŒ ํ•„๋“œ _env๏ผˆPHP Constants and Environment via Schema ํ™•์žฅ ๊ธฐ๋Šฅ ์ œ๊ณต๏ผ‰๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ™˜๊ฒฝ ๋ณ€์ˆ˜ ๋˜๋Š” PHP ์ƒ์ˆ˜๋ฅผ ์ฝ๊ณ , @remove ๋””๋ ‰ํ‹ฐ๋ธŒ๏ผˆField Response Removal ํ™•์žฅ ๊ธฐ๋Šฅ ์ œ๊ณต๏ผ‰๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์‘๋‹ต์— ์ธ์ฆ ์ •๋ณด๊ฐ€ ์ถœ๋ ฅ๋˜์ง€ ์•Š๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.

์ด์ œ ์ธ์ฆ ์ •๋ณด๋ฅผ wp-config.php ์— ์„ ์–ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

define( 'MAILCHIMP_API_CREDENTIALS_USERNAME', '{ username }' );
define( 'MAILCHIMP_API_CREDENTIALS_PASSWORD', '{ password }' );

Mailchimp์— HTTP ์š”์ฒญ ์ „์†กํ•˜๊ธฐ

๋กœ์ง์˜ ๋งˆ์ง€๋ง‰ ๊ตฌ์„ฑ ์š”์†Œ๋Š” ํ•„๋“œ _sendJSONObjectItemHTTPRequest ๋กœ, ํŠน์ • ์„œ๋น„์Šค์— HTTP ์š”์ฒญ์„ ์ „์†กํ•ฉ๋‹ˆ๋‹ค.

Mailchimp API์— ์—ฐ๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด, ํ•„๋“œ mailchimpListMembersJSONObject ๋Š” Mailchimp ๋ชฉ๋ก์— ๋ฉค๋ฒ„๋ฅผ ๊ตฌ๋… ๋“ฑ๋กํ•˜๋Š” ๋ฌธ์„œ์— ๋ช…์‹œ๋œ Mailchimp REST API ์—”๋“œํฌ์ธํŠธ๊ฐ€ ์š”๊ตฌํ•˜๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

  • POST ์š”์ฒญ ์ „์†ก
  • ์—”๋“œํฌ์ธํŠธ๋Š” https://{subdomain}.api.mailchimp.com/3.0/lists/{listCode}/members
  • ์š”์ฒญ ๋ณธ๋ฌธ์— email_address ์™€ status ํ•„๋“œ๋ฅผ ํฌํ•จํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค

์ž„์˜์˜ API์™€ ์—ฐ๋™ํ•˜๋Š” Webhook ๋งŒ๋“ค๊ธฐ

์ด ๊ฒŒ์‹œ๋ฌผ์˜ GraphQL ์ฟผ๋ฆฌ๋Š” InstaWP์—์„œ Mailchimp๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค.

ํ•„์š”ํ•œ ์–ด๋–ค ์กฐํ•ฉ์—๋„ ๋™์ผํ•œ ์•„์ด๋””์–ด๋ฅผ ์ ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์†Œ์Šค ์„œ๋น„์Šค๏ผˆ์–ด๋–ค ๊ฒƒ์ด๋“ ๏ผ‰์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์ถ”์ถœํ•˜๊ณ , ๊ฐ€๊ณตํ•œ ํ›„, ๋Œ€์ƒ ์„œ๋น„์Šค๏ผˆ์–ด๋–ค ๊ฒƒ์ด๋“ ๏ผ‰๋กœ ์ „์†กํ•˜์„ธ์š”.

์ฆ๊ฒ๊ฒŒ ํ™œ์šฉํ•ด ๋ณด์„ธ์š”!


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

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