๋ธ”๋กœ๊ทธ

๐ŸŽ‰ Gato GraphQL v0.7 ์ถœ์‹œ โ€” mutation ๋ฐ nested mutation ์ง€์› ์ถ”๊ฐ€!

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

Gato GraphQL ๋ฒ„์ „ 0.7์ด ์ถœ์‹œ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. mutation๊ณผ nested mutation์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค! ๐ŸŽ‰

Mutation์€ ์ •๋ง ํ›Œ๋ฅญํ•ฉ๋‹ˆ๋‹ค!

์ƒˆ๋กญ๊ฒŒ ์ถ”๊ฐ€๋œ ๊ธฐ๋Šฅ๋“ค์„ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

1. Mutations! ๐Ÿš€

GraphQL mutations๋Š” ์ฟผ๋ฆฌ๋ฅผ ํ†ตํ•ด ๋ฐ์ดํ„ฐ๋ฅผ ์ˆ˜์ •(์ฆ‰, ๋ถ€์ž‘์šฉ์„ ์‹คํ–‰)ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค๋‹ˆ๋‹ค.

Mutation์€ Gato GraphQL์— ์•„์ง ์—†์—ˆ๋˜ ์ค‘์š”ํ•œ ๊ธฐ๋Šฅ์ด์—ˆ์Šต๋‹ˆ๋‹ค. ์ด์ œ ์ถ”๊ฐ€๋˜์—ˆ์œผ๋ฏ€๋กœ, ์ด GraphQL ์„œ๋ฒ„๋Š” ๊ฑฐ์˜ ๊ธฐ๋Šฅ์ด ์™„์ „ํ•˜๋‹ค๊ณ  ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(subscriptions๋งŒ ๋‚จ์•„ ์žˆ์œผ๋ฉฐ, ์ถ”๊ฐ€ ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ์ด๋ฏธ ๊ฒ€ํ†  ์ค‘์ž…๋‹ˆ๋‹ค).

์ธํ„ฐ๋ž™ํ‹ฐ๋ธŒ ์Šคํ‚ค๋งˆ์˜ Mutation root

๋Œ“๊ธ€ ์ถ”๊ฐ€ ์˜ˆ์‹œ๋ฅผ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ๋‹ค๋งŒ, ๋จผ์ € ๋กœ๊ทธ์ธ์„ ์œ„ํ•œ ๋‹ค๋ฅธ mutation์„ ์‹คํ–‰ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋Œ“๊ธ€์„ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜๊ธฐ ์œ„ํ•ด์„œ์ž…๋‹ˆ๋‹ค. ์•„๋ž˜ GraphiQL ํด๋ผ์ด์–ธํŠธ์—์„œ ใ€ŒRunใ€ ๋ฒ„ํŠผ์„ ๋ˆŒ๋Ÿฌ, ๋ฏธ๋ฆฌ ์ƒ์„ฑ๋œ ํ…Œ์ŠคํŠธ ์‚ฌ์šฉ์ž๋กœ mutation ํ•„๋“œ loginUser๋ฅผ ์‹คํ–‰ํ•ด ์ฃผ์„ธ์š”:

mutation LogUserIn {
  loginUser(
    by: { credentials: { usernameOrEmail: "test", password: "pass" } }
  ) {
    id
    name
  }
}

์ด์ œ ๋Œ“๊ธ€์„ ์ถ”๊ฐ€ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ์•„๋ž˜ Run ๋ฒ„ํŠผ์„ ๋ˆŒ๋Ÿฌ, mutation ํ•„๋“œ addCommentToCustomPost๋ฅผ ์‹คํ–‰ํ•˜์—ฌ ๊ฒŒ์‹œ๋ฌผ์— ๋Œ“๊ธ€์„ ์ถ”๊ฐ€ํ•ด ์ฃผ์„ธ์š”(๋Œ“๊ธ€ ํ…์ŠคํŠธ๋„ ํŽธ์ง‘ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค):

mutation AddComment {
  addCommentToCustomPost(
    input: { customPostID: 1459, comment: "Adding a comment: bla bla bla" }
  ) {
    id
    content
    date
  }
}

์ด๋ฒˆ ์ฒซ ๋ฒˆ์งธ ๋ฆด๋ฆฌ์Šค์—์„œ ํ”Œ๋Ÿฌ๊ทธ์ธ์—๋Š” ๋‹ค์Œ mutation์ด ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค:

โœ… createPost
โœ… updatePost
โœ… setFeaturedImageforCustomPost
โœ… removeFeaturedImageforCustomPost
โœ… addCommentToCustomPost
โœ… replyComment
โœ… loginUser
โœ… logoutUser

2. Nested Mutations! ๐Ÿš€๐Ÿš€

Nested mutations๋ž€ GraphQL์˜ root ํƒ€์ž… ์ด์™ธ์˜ ํƒ€์ž…์— ๋Œ€ํ•ด mutation์„ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋Šฅ์ž…๋‹ˆ๋‹ค.

์ด ๊ธฐ๋Šฅ์€ GraphQL ์ŠคํŽ™์— ์ถ”๊ฐ€๊ฐ€ ์š”์ฒญ๋œ ๋ฐ” ์žˆ์œผ๋‚˜, ์•„์ง ์Šน์ธ๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค(์•ž์œผ๋กœ๋„ ์Šน์ธ๋˜์ง€ ์•Š์„ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค). ๊ทธ๋ž˜์„œ Gato GraphQL์€ Nested Mutations ๋ชจ๋“ˆ์„ ํ†ตํ•ด ์˜ตํŠธ์ธ ๊ธฐ๋Šฅ์œผ๋กœ ์ง€์›์„ ์ถ”๊ฐ€ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

ํ”Œ๋Ÿฌ๊ทธ์ธ์€ ๋‹ค์Œ ๋‘ ๊ฐ€์ง€ ๋™์ž‘์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค:

  1. ํ‘œ์ค€ GraphQL ๋™์ž‘(์ฆ‰, root ํƒ€์ž…์— mutation ํ•„๋“œ๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ), ๊ธฐ๋ณธ๊ฐ’
  2. Nested mutations, ์˜ตํŠธ์ธ์œผ๋กœ

์˜ˆ๋ฅผ ๋“ค์–ด, ์œ„์˜ ์ฟผ๋ฆฌ๋Š” ๋‹ค์Œ ์ฟผ๋ฆฌ๋กœ๋„ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ์ฟผ๋ฆฌ์—์„œ๋Š” ๋จผ์ € Root.post๋กœ ๊ฒŒ์‹œ๋ฌผ์„ ๊ฐ€์ ธ์˜จ ๋‹ค์Œ, Post.addComment๋กœ ๋Œ“๊ธ€์„ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค:

mutation AddComment {
  post(by: { id: 1459 }) {
    addComment(
      input: {
        comment: "Notice how field `addCommentToCustomPost` under the `Root` type is renamed as `addComment` under the `Post` type? The schema got neater!"
      }
    ) {
      id
      content
      date
    }
  }
}

Mutation์€ ๋‹ค๋ฅธ mutation์˜ ๊ฒฐ๊ณผ์— ๋Œ€ํ•ด์„œ๋„ ๋ฐ์ดํ„ฐ๋ฅผ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์•„๋ž˜ ์ฟผ๋ฆฌ์—์„œ๋Š” ๋จผ์ € Root.post๋กœ ๊ฒŒ์‹œ๋ฌผ์„ ๊ฐ€์ ธ์˜จ ํ›„, mutation Post.addComment๋ฅผ ์‹คํ–‰ํ•˜์—ฌ ์ƒ์„ฑ๋œ ๋Œ“๊ธ€ ๊ฐ์ฒด๋ฅผ ์–ป๊ณ , ๋งˆ์ง€๋ง‰์œผ๋กœ ๊ทธ ๋Œ“๊ธ€์— ๋Œ€ํ•ด mutation Comment.reply๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค:

mutation AddCommentAndResponse {
  post(by: { id: 1459 }) {
    id
    title
    addComment(input: { comment: "Isn't this awesome?" }) {
      id
      date
      content
      reply(input: { comment: "I think so!" }) {
        id
        date
        content
      }
    }
  }
}

์ •๋ง ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค! ๐Ÿ˜ (๋™์ผํ•œ ๋™์ž‘์„ ๋‹จ์ผ ์ฟผ๋ฆฌ์—์„œ ์‹คํ˜„ํ•˜๋Š” ๋Œ€์•ˆ์ ์ธ ๋ฐฉ๋ฒ•์€ @export ๋””๋ ‰ํ‹ฐ๋ธŒ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹คโ€ฆ ํ–ฅํ›„ ๋ธ”๋กœ๊ทธ ๊ฒŒ์‹œ๋ฌผ์—์„œ ๋‘ ๊ฐ€์ง€๋ฅผ ๋น„๊ตํ•  ์˜ˆ์ •์ž…๋‹ˆ๋‹ค).


์ด๋ฒˆ ์ฒซ ๋ฒˆ์งธ ๋ฆด๋ฆฌ์Šค์—์„œ ํ”Œ๋Ÿฌ๊ทธ์ธ์—๋Š” ๋‹ค์Œ mutation์ด ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค:

โœ… CustomPost.update
โœ… CustomPost.setFeaturedImage
โœ… CustomPost.removeFeaturedImage
โœ… CustomPost.addComment
โœ… Comment.reply

ํ‘œ์ค€ ๋˜๋Š” nested? ์•„๋‹ˆ๋ฉด ๋‘˜ ๋‹ค?

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

์ข‹์€ ์†Œ์‹์ด ์žˆ์Šต๋‹ˆ๋‹ค: ๊ทธ๊ฒƒ์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

Schema Configuration์— ใ€ŒMutation Schemeใ€ ์„น์…˜์„ ์ถ”๊ฐ€ํ–ˆ์Šต๋‹ˆ๋‹ค. ์ด ์„น์…˜์€ Custom Endpoints์™€ Persisted Queries์˜ ์Šคํ‚ค๋งˆ๋ฅผ ์ปค์Šคํ„ฐ๋งˆ์ด์ง•ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค:

Schema configuration์˜ Mutation scheme

์ด๋ฅผ ํ†ตํ•ด nested mutations๋ฅผ ๋ชจ๋“  ๊ณณ์—์„œ ๋น„ํ™œ์„ฑํ™”ํ•˜๋ฉด์„œ, ์ž์‚ฌ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜๋งŒ ์‚ฌ์šฉํ•˜๋Š” ํŠน์ • custom endpoint์—์„œ๋งŒ ํ™œ์„ฑํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๐Ÿ’ช

root ํƒ€์ž…์—์„œ ์ค‘๋ณต ํ•„๋“œ ์ œ๊ฑฐํ•˜๊ธฐ

Nested mutations๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด mutation ํ•„๋“œ๊ฐ€ ์Šคํ‚ค๋งˆ์— ๋‘ ๋ฒˆ ์ถ”๊ฐ€๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

  • root ํƒ€์ž… ์•„๋ž˜์— ํ•œ ๋ฒˆ
  • ํŠน์ • ํƒ€์ž… ์•„๋ž˜์— ํ•œ ๋ฒˆ

์˜ˆ๋ฅผ ๋“ค์–ด, ๋‹ค์Œ ํ•„๋“œ๋“ค์€ ์„œ๋กœ์˜ ใ€Œ์ค‘๋ณตใ€์œผ๋กœ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

  • Root.updatePost
  • Post.update

Gato GraphQL์—์„œ๋Š” ๋‘˜ ๋‹ค ์œ ์ง€ํ•˜๊ฑฐ๋‚˜, root ํƒ€์ž…์˜ ์ค‘๋ณต ํ•„๋“œ๋ฅผ ์ œ๊ฑฐํ•˜๋Š” ๊ฒƒ์„ ์„ ํƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋‹ค์Œ 3๊ฐ€์ง€ ์Šคํ‚ค๋งˆ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค:

  1. ํ‘œ์ค€ ๋™์ž‘:
    ์ฟผ๋ฆฌ ์ฒ˜๋ฆฌ์— QueryRoot ํƒ€์ž…์„, mutation ์ฒ˜๋ฆฌ์— MutationRoot ํƒ€์ž…์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค
  2. ์ค‘๋ณต mutation ํ•„๋“œ๋ฅผ ์œ ์ง€ํ•˜๋Š” nested mutations:
    ๋‹จ์ผ Root ํƒ€์ž…์ด ์ฟผ๋ฆฌ์™€ mutation์„ ์ฒ˜๋ฆฌํ•˜๋ฉฐ, ์ด ํƒ€์ž…์˜ ์ค‘๋ณต mutation ํ•„๋“œ๋Š” ์œ ์ง€๋ฉ๋‹ˆ๋‹ค
  3. root ํƒ€์ž…์—์„œ ์ค‘๋ณต mutation ํ•„๋“œ๋ฅผ ์ œ๊ฑฐํ•˜๋Š” nested mutations:
    ์œ„์™€ ๋™์ผํ•˜์ง€๋งŒ, Root ํƒ€์ž…์—์„œ ๋ชจ๋“  ์ค‘๋ณต mutation ํ•„๋“œ๋ฅผ ์ œ๊ฑฐํ•ฉ๋‹ˆ๋‹ค

โœฑ ์ฐธ๊ณ ๋กœ 1, ์ด 3๊ฐ€์ง€ ์Šคํ‚ค๋งˆ๋Š” ๋ชจ๋‘ ๋™์ผํ•œ ์—”๋“œํฌ์ธํŠธ๋ฅผ ์‚ฌ์šฉํ•˜์ง€๋งŒ, URL ํŒŒ๋ผ๋ฏธํ„ฐ ?mutation_scheme์„ standard, nested, lean_nested๋กœ ๋ณ€๊ฒฝํ•˜์—ฌ ์ „ํ™˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ GraphQL ์„œ๋ฒ„๊ฐ€ code-first ์ ‘๊ทผ ๋ฐฉ์‹์„ ๋”ฐ๋ฅด๊ธฐ ๋•Œ๋ฌธ์— ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. ๐ŸคŸ

โœฑ ์ฐธ๊ณ ๋กœ 2, ์ด ์˜ต์…˜๋“ค์€ Schema configuration(์œ„์— ํ‘œ์‹œ๋จ)์˜ ใ€ŒMutation Schemeใ€ ์„น์…˜์—์„œ ์„ ํƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ๊ฐœ๋ณ„ custom endpoints์™€ persisted queries์— ์ ์šฉํ•  ๋™์ž‘๋„ ๊ฒฐ์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๐Ÿ‘


์ด์ œ v0.8์„ ์ค€๋น„ํ•  ์‹œ๊ฐ„์ž…๋‹ˆ๋‹ค! ๐Ÿ™


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

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