๋ธ”๋กœ๊ทธ

๐Ÿ‘ถ๐Ÿป GraphQL๋กœ WordPress๋ฅผ ๋˜์‚ด๋ฆฌ๋‹ค

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

WordPress๋Š” ๋ ˆ๊ฑฐ์‹œ CMS์ž…๋‹ˆ๋‹ค. 17๋…„ ์ด์ƒ ์ „์— ํƒ„์ƒํ•œ ์ด ์‹œ์Šคํ…œ์€, ์ง€๊ธˆ ๋‹ค์‹œ ๋งŒ๋“ ๋‹ค๋ฉด ๋‹ค๋ฅธ ๋ฐฉ์‹์œผ๋กœ ์ž‘์„ฑ๋˜์—ˆ์„ PHP ์ฝ”๋“œ๋กœ ๊ฐ€๋“ ์ฐจ ์žˆ์Šต๋‹ˆ๋‹ค.

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

์ด ๋‘ ๊ฐ€์ง€๋ฅผ ๊ฒฐํ•ฉํ•˜๋ฉด ์–ด๋–ค ์ผ์ด ์ผ์–ด๋‚ ๊นŒ์š”? WordPress ๋ฐ์ดํ„ฐ์— ์ ‘๊ทผํ•˜๊ธฐ ์œ„ํ•œ GraphQL ์ธํ„ฐํŽ˜์ด์Šค๋Š” ์–ด๋–ป๊ฒŒ ์„ค๊ณ„ํ•ด์•ผ ํ• ๊นŒ์š”?

๋Œ€๋žต์ ์œผ๋กœ ๋‘ ๊ฐ€์ง€ ์ „๋žต์„ ์ƒ๊ฐํ•ด ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  1. ์ „ํ†ต์„ ์กด์ค‘ํ•˜๊ณ , WordPress ๋ฐ์ดํ„ฐ ๋ชจ๋ธ์„ ๊ทธ๋Œ€๋กœ ์œ ์ง€ํ•˜๋Š” ๋งคํ•‘์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค (์ˆ˜๋…„์— ๊ฑธ์ณ ์Œ“์ธ ๊ธฐ์ˆ ์  ๋ถ€์ฑ„๋„ ํฌํ•จํ•˜์—ฌ)

  2. ๊ธฐ์ˆ ์  ๋ถ€์ฑ„๋ฅผ ํ•ด์†Œํ•˜๊ณ , ๋ฐ์ดํ„ฐ๋ฅผ ์ถ”์ƒ์ ์ด๊ณ  WordPress์— ์ข…์†๋˜์ง€ ์•Š๋Š” ๋ฐฉ์‹์œผ๋กœ ๋…ธ์ถœํ•˜๋Š” ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค

๋‘ ์ ‘๊ทผ ๋ฐฉ์‹ ๋ชจ๋‘ ์žฅ๋‹จ์ ์ด ์žˆ์œผ๋ฉฐ, ์–ด๋А ์ชฝ์ด ๋งž๊ณ  ํ‹€๋ฆฌ๋‹ค๋Š” ๊ฒƒ์€ ์—†์Šต๋‹ˆ๋‹ค. ๋‹จ์ง€ ์–ด๋–ค ๋™์ž‘์„ ๋‹ค๋ฅธ ๊ฒƒ๋ณด๋‹ค ์šฐ์„ ์‹œํ•˜๋Š” ์ฃผ๊ด€์ ์ธ ์„ ํƒ์ผ ๋ฟ์ž…๋‹ˆ๋‹ค.

ํ”Œ๋Ÿฌ๊ทธ์ธ Gato GraphQL ์—์„œ๋Š” ํ›„์ž์˜ ์ ‘๊ทผ ๋ฐฉ์‹์„ ์„ ํƒํ•˜์—ฌ, WordPress๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ WordPress๋ฅผ ์œ„ํ•ด ๋™์ž‘ํ•˜๋ฉด์„œ๋„ WordPress์— ์ข…์†๋˜์ง€ ์•Š๋Š” (์˜ˆ๋ฅผ ๋“ค์–ด, ์ผ๊ด€์„ฑ ์—†๋Š” ์ด๋ฆ„๊ณผ ๊ด€๊ณ„๋ฅผ ์ œ๊ฑฐํ•˜๋Š”) GraphQL ์Šคํ‚ค๋งˆ๋ฅผ ๋งŒ๋“ค๋ ค ํ–ˆ์Šต๋‹ˆ๋‹ค.

๊ทธ ๊ฒฐ๊ณผ, GraphQL์€ WordPress๋ฅผ ๋˜์‚ด๋ฆฝ๋‹ˆ๋‹ค. ๊ธฐ๋ฐ˜ CMS๋กœ์„œ์˜ WordPress๋Š” ๊ทธ๋Œ€๋กœ์ด๊ณ  ๋ ˆ๊ฑฐ์‹œ PHP ์ฝ”๋“œ๋„ ๋ณ€ํ•˜์ง€ ์•Š์ง€๋งŒ, ๋ฐ์ดํ„ฐ ๊ณ„์ธต์€ ์ „ํ†ต์ด ์•„๋‹Œ ์ƒ์‹์— ๊ธฐ๋ฐ˜ํ•˜์—ฌ ์ƒˆ๋กญ๊ฒŒ ๋งŒ๋“ค์–ด์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฐ์ดํ„ฐ ๊ณ„์ธต์€ ์‚ฌ์ถ˜๊ธฐ์—์„œ ๋‹ค์‹œ ์œ ์•„๊ธฐ๋กœ ๋Œ์•„๊ฐ€๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

GraphQL + WordPress๋Š” ํ™˜์ƒ์˜ ์กฐํ•ฉ

๊ทธ ๊ฒฐ๊ณผ๋Š” WordPress ๋ฐ์ดํ„ฐ ๋ชจ๋ธ์„ ํ‘œํ˜„ํ•˜๋Š” GraphQL ์Šคํ‚ค๋งˆ์ด๋ฉฐ, ์ค‘์ฒฉ๋œ mutation๋„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค.

์–ด๋–ป๊ฒŒ ๊ตฌํ˜„๋˜์—ˆ๋Š”์ง€ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

WordPress ๋ฐ์ดํ„ฐ ๋ชจ๋ธ

WordPress์—๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์—”ํ‹ฐํ‹ฐ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

  • posts
  • pages
  • custom posts
  • ๋ฏธ๋””์–ด ์š”์†Œ
  • users
  • user roles
  • tags
  • categories
  • comments
  • blocks
  • meta ์†์„ฑ
  • ๊ธฐํƒ€ (options, plugins, themes ๋“ฑ)

์ด๋Ÿฌํ•œ ์—”ํ‹ฐํ‹ฐ๋“ค์€ ๊ณ„์ธต ๊ตฌ์กฐ๋ฅผ ๊ฐ€์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, post, page, ๋ฏธ๋””์–ด ์š”์†Œ๋Š” ๋ชจ๋‘ custom post type์ด๋ฉฐ, tags์™€ categories๋Š” ๋ชจ๋‘ ํƒ์†Œ๋…ธ๋ฏธ์ž…๋‹ˆ๋‹ค.

๋‹ค์Œ์€ WordPress ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋‹ค์ด์–ด๊ทธ๋žจ์œผ๋กœ, ๋ชจ๋“  ์—”ํ‹ฐํ‹ฐ์˜ ๋ฐ์ดํ„ฐ๊ฐ€ ์–ด๋–ป๊ฒŒ ์ €์žฅ๋˜๋Š”์ง€๋ฅผ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค.

WordPress ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋‹ค์ด์–ด๊ทธ๋žจ

๋งคํ•‘์ด DB ๋‹ค์ด์–ด๊ทธ๋žจ์˜ ์™„์ „ํ•œ ๋ณต์ œ์ธ๊ฐ€์š”?

WordPress ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ GraphQL ์Šคํ‚ค๋งˆ๋กœ ๋งคํ•‘ํ•  ๋•Œ, ์œ„์˜ ๋‹ค์ด์–ด๊ทธ๋žจ์„ 1:1๋กœ ๋”ฐ๋ฅผ ํ•„์š”๊ฐ€ ์žˆ์„๊นŒ์š”?

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

๋”ฐ๋ผ์„œ WordPress์˜ GraphQL ์Šคํ‚ค๋งˆ๋ฅผ ๋งŒ๋“ค ๋•Œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋‹ค์ด์–ด๊ทธ๋žจ์„ ๊ทธ๋Œ€๋กœ ๋”ฐ๋ฅผ ํ•„์š”๋Š” ์—†์Šต๋‹ˆ๋‹ค. ์ฆ‰, WordPress ๋ฐ์ดํ„ฐ ๋ชจ๋ธ์ด ๊ฐ€์ง„ ๊ธฐ์ˆ ์  ๋ถ€์ฑ„์˜ ์ผ๋ถ€๋ฅผ ํ•ด์†Œํ•˜๋Š” GraphQL ์Šคํ‚ค๋งˆ๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

WordPress ๋ฐ์ดํ„ฐ ๋ชจ๋ธ์„ GraphQL ์Šคํ‚ค๋งˆ๋กœ ๋งคํ•‘ํ•˜๊ธฐ

๋งคํ•‘์„ ์ง„ํ–‰ํ•ด ๋ด…์‹œ๋‹ค. ๋จผ์ € ์›๋ž˜ ์—”ํ‹ฐํ‹ฐ๋ฅผ ๊ฐ€๋Šฅํ•œ ํ•œ type์œผ๋กœ ๋งคํ•‘ํ•ฉ๋‹ˆ๋‹ค. WordPress ๋ฐ์ดํ„ฐ ๋ชจ๋ธ์˜ ์—”ํ‹ฐํ‹ฐ ๋ชฉ๋ก์—์„œ GraphQL ์Šคํ‚ค๋งˆ๋ฅผ ์œ„ํ•œ ๋‹ค์Œ type๋“ค์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

  • Post
  • Page
  • Media
  • User
  • UserRole
  • PostTag
  • PostCategory
  • Comment

๊ทธ๋Ÿฐ ๋‹ค์Œ ๋ชจ๋“  type์— ๊ธฐ๋Œ€๋˜๋Š” ํ•„๋“œ๋ฅผ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค. ์Šคํ‚ค๋งˆ๋ฅผ ํ‘œํ˜„ํ•˜๊ธฐ ์œ„ํ•ด SDL, ์ฆ‰ Schema Definition Language๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. (์ด๋Š” ๋ฌธ์„œํ™” ๋ชฉ์ ์œผ๋กœ๋งŒ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ํ”Œ๋Ÿฌ๊ทธ์ธ ์ž์ฒด๋Š” SDL๋กœ ์Šคํ‚ค๋งˆ๋ฅผ ์ฝ”๋“œํ™”ํ•˜์ง€ ์•Š์œผ๋ฉฐ, ๋ชจ๋‘ PHP ์ฝ”๋“œ์ž…๋‹ˆ๋‹ค.)

Post์˜ ํ•„๋“œ (๊ทธ ์™ธ ๋‹ค์ˆ˜ ์ค‘์—์„œ) ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

type Post {
  id: ID!
  title: String
  content: String
  excerpt: String
  publishedAt: Date!
}

User์˜ ํ•„๋“œ (๊ทธ ์™ธ ๋‹ค์ˆ˜ ์ค‘์—์„œ) ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

type User {
  id: ID!
  name: String
  email: String!
}

๋Œ€์‘ํ•˜๋Š” ์—ฐ๊ฒฐ(connection)๋„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. ์—ฐ๊ฒฐ์ด๋ž€ ์Šค์นผ๋ผ(์ˆซ์ž๋‚˜ ๋ฌธ์ž์—ด ๋“ฑ)๊ฐ€ ์•„๋‹Œ ๋‹ค๋ฅธ ์—”ํ‹ฐํ‹ฐ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ํ•„๋“œ์ž…๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, post์— ์ €์ž๊ฐ€ ์žˆ๊ณ , user๊ฐ€ posts๋ฅผ ์†Œ์œ ํ•œ๋‹ค๋Š” ๊ฒƒ์„ ํ‘œํ˜„ํ•ฉ๋‹ˆ๋‹ค.

type Post {
  author: User!
}
 
type User {
  posts: [Post]
}

ํ•„๋“œ์™€ ์—ฐ๊ฒฐ์€ ์ธ์ˆ˜๋ฅผ ๋ฐ›์„ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, Post.date๋ฅผ ํฌ๋งท ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•˜๊ณ , User.posts์—์„œ ํ•ญ๋ชฉ ๊ฒ€์ƒ‰๊ณผ ์ˆ˜ ์ œํ•œ์„ ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค.

type Post {
  date(format: String): Date!
}
 
type User {
  posts(limit: Int, search: String): [Post]
}

WordPress ๋ฐ์ดํ„ฐ ๋ชจ๋ธ์˜ ๋ชจ๋“  ์—”ํ‹ฐํ‹ฐ์— ๋Œ€ํ•ด ์ด ์ž‘์—…์„ ๊ณ„์†ํ•ฉ๋‹ˆ๋‹ค. ์™„์„ฑ๋˜๋ฉด Voyager ํด๋ผ์ด์–ธํŠธ(ํ”Œ๋Ÿฌ๊ทธ์ธ ๋ฉ”๋‰ด์—์„œ "Interactive Schema"๋กœ ์ด์šฉ ๊ฐ€๋Šฅ)๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋Š” WordPress์˜ GraphQL ์Šคํ‚ค๋งˆ๊ฐ€ ์™„์„ฑ๋ฉ๋‹ˆ๋‹ค.

WordPress์˜ GraphQL ์Šคํ‚ค๋งˆ

์ด ์Šคํ‚ค๋งˆ๋Š” WordPress ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋‹ค์ด์–ด๊ทธ๋žจ๊ณผ ์œ ์‚ฌํ•œ ๋ถ€๋ถ„๋„ ์žˆ์ง€๋งŒ ๋งŽ์€ ์ฐจ์ด์ ๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ถ„์„ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

์—”ํ‹ฐํ‹ฐ ์—†๋Š” ์ž‘์—…์€ Root ํ•„๋“œ๋กœ ๋งคํ•‘๋ฉ๋‹ˆ๋‹ค

WordPress ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋‹ค์ด์–ด๊ทธ๋žจ์€ ๋ฐ์ดํ„ฐ๊ฐ€ ์ €์žฅ๋˜๋Š” ๋ฐฉ์‹์„ ๋‚˜ํƒ€๋‚ด๋ฏ€๋กœ ใ€Œ์‹œ์ž‘์ ใ€์ด ์—†์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ GraphQL์€ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฒ€์ƒ‰ํ•˜๊ธฐ ์œ„ํ•œ ์ธํ„ฐํŽ˜์ด์Šค์ด๋ฏ€๋กœ, ์ฟผ๋ฆฌ๋ฅผ ์‹คํ–‰ํ•˜๊ธฐ ์œ„ํ•œ ์ดˆ๊ธฐ ๋‹จ๊ณ„๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

์ด ์ดˆ๊ธฐ ๋‹จ๊ณ„๊ฐ€ Root type์ด๋ฉฐ, ๋” ์ •ํ™•ํ•˜๊ฒŒ๋Š” QueryRoot์™€ MutationRoot๋ผ๋Š” ๋‘ type(๊ฐ๊ฐ queries์™€ mutations๋ฅผ ์ฒ˜๋ฆฌ)์ž…๋‹ˆ๋‹ค.

์ด ๋‘ type์—๋Š” get_posts(), get_users(), wp_signon()์ฒ˜๋Ÿผ ์—”ํ‹ฐํ‹ฐ์— ์˜์กดํ•˜์ง€ ์•Š๋Š” ๋ชจ๋“  ์ž‘์—…์„ ๋งคํ•‘ํ•ฉ๋‹ˆ๋‹ค.

type QueryRoot {
  posts: [Post]!
  users: [User]!
}
 
type MutationRoot {
  logUserIn(username: String, password: String): User
}

ํ•„๋“œ๊ฐ€ ๋‚˜ํƒ€๋‚ด๋Š” ์ž‘์—…๊ณผ ๋™์ผํ•œ ์ด๋ฆ„์ด๋‚˜ ์‹œ๊ทธ๋‹ˆ์ฒ˜๋ฅผ ๊ฐ€์งˆ ํ•„์š”๋Š” ์—†์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ํ•„๋“œ ์ด๋ฆ„์„ signOn๋ณด๋‹ค logUserIn์œผ๋กœ ํ•˜๋Š” ๊ฒƒ์ด ๋” ์ ํ•ฉํ•˜๋‹ค๊ณ  ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ชจ๋“  mutation์€ MutationRoot ์•„๋ž˜์— ๋‘ก๋‹ˆ๋‹ค

wp_update_post()์ฒ˜๋Ÿผ ํŠน์ • ์—”ํ‹ฐํ‹ฐ์— ์˜์กดํ•˜๋Š” ์ž‘์—…๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Š” ์–ด๋–ค post์— ์ ์šฉ๋ฉ๋‹ˆ๋‹ค. ๋Œ€์‘ํ•˜๋Š” mutation์€ GraphQL ์Šคํ‚ค๋งˆ์˜ MutationRoot type์— ์ถ”๊ฐ€ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์ด GraphQL์˜ ์‚ฌ์–‘์ž…๋‹ˆ๋‹ค.

์ด ์ž‘์—…์€ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋งคํ•‘๋ฉ๋‹ˆ๋‹ค.

type MutationRoot {
  updatePost(input: {
    postID: ID!,
    newTitle: String,
    newContent: String
  }): Post
}

์ด ํ”Œ๋Ÿฌ๊ทธ์ธ์€ ์ค‘์ฒฉ๋œ mutation๋„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค (ํ‘œ์ค€ GraphQL ๋™์ž‘์ด ์•„๋‹ˆ๋ฏ€๋กœ ์˜ตํŠธ์ธ ๊ธฐ๋Šฅ์œผ๋กœ ์ œ๊ณต). ์ด ๊ฒฝ์šฐ mutation์€ MutationRoot๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ๋ชจ๋“  type ์•„๋ž˜์— ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๊ฒฝ์šฐ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋ฉ๋‹ˆ๋‹ค.

type Post {
  update(input: {
    newTitle: String,
    newContent: String
  }): Post!
}

custom posts ์ฒ˜๋ฆฌํ•˜๊ธฐ

GraphQL์—๋Š” type ์ƒ์†์ด ์—†์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ CustomPost๋ผ๋Š” type์„ ๊ฐ€์ง€๊ณ , Post์™€ Page๊ฐ€ ์ด๋ฅผ ์ƒ์†ํ•˜๋Š” ๊ตฌ์กฐ๋ฅผ ์ทจํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

GraphQL์€ ์ด ์ œ์•ฝ์„ ๋ณด์™„ํ•˜๊ธฐ ์œ„ํ•ด ๋‘ ๊ฐ€์ง€ ์ˆ˜๋‹จ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ์ธํ„ฐํŽ˜์ด์Šค์™€ union type์ž…๋‹ˆ๋‹ค.

์ฒซ ๋ฒˆ์งธ๋กœ, ์Šคํ‚ค๋งˆ์— CustomPost ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๋งŒ๋“ค๊ณ  custom post์—์„œ ๊ธฐ๋Œ€๋˜๋Š” ๋ชจ๋“  ํ•„๋“œ๋ฅผ ์„ ์–ธํ•˜๋ฉฐ, Post์™€ Page๊ฐ€ ๊ทธ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•˜๋„๋ก ์ •์˜ํ•ฉ๋‹ˆ๋‹ค.

interface CustomPost {
  title: String
  content: String
  excerpt: String
  date(format: String): Date!
}
 
type Post implements CustomPost {
  title: String
  content: String
  excerpt: String
  date(format: String): Date!
}
 
type Page implements CustomPost {
  title: String
  content: String
  excerpt: String
  date(format: String): Date!
}

๋‘ ๋ฒˆ์งธ๋กœ, ๋ชจ๋“  custom post type์„ ๋ฐ˜ํ™˜ํ•˜๋Š” CustomPostUnion type์„ ์Šคํ‚ค๋งˆ์— ๋งŒ๋“ญ๋‹ˆ๋‹ค.

union CustomPostUnion = Post | Page

๊ทธ๋ฆฌ๊ณ  ์ ์ ˆํ•œ ๊ฒฝ์šฐ์— ์ด type์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ํ•„๋“œ๋ฅผ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค.

type QueryRoot {
  customPost(id: ID): CustomPostUnion
  customPosts: [CustomPostUnion]!
}
 
type User {
  customPosts: [CustomPostUnion]
}
 
type Comment {
  customPost: CustomPostUnion!
}

๋ณด์‹œ๋‹ค์‹œํ”ผ, GraphQL ์Šคํ‚ค๋งˆ์—์„œ๋Š” posts๋ฅผ ๋‹ค๋ฃจ๊ณ  ์žˆ๋Š”์ง€ custom posts๋ฅผ ๋‹ค๋ฃจ๊ณ  ์žˆ๋Š”์ง€ ๋ช…์‹œ์ ์œผ๋กœ ๊ตฌ๋ณ„ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด ๋‘˜์€ ๊ฐ™์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค! ์ด ๋‘ ๊ฐ€์ง€๋ฅผ ํ˜ผ์šฉํ•˜๋Š” ๊ฒƒ์€ WordPress์˜ ๊ธฐ์ˆ ์  ๋ถ€์ฑ„์ด๋ฉฐ, ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์— custom post๋Š” ํ•ญ์ƒ Post๊ฐ€ ์•„๋‹Œ CustomPost๋ผ๊ณ  ๋ถ€๋ฅด๊ณ , custom posts๋ฅผ ๋‹ค๋ฃจ๋Š” ํ•„๋“œ๋Š” ํ•ญ์ƒ posts๊ฐ€ ์•„๋‹Œ customPosts๋ผ๊ณ  ๋ถ€๋ฅด๋ฉฐ, custom post์˜ ID๋ฅผ ๋ฐ›๋Š” ํ•„๋“œ ์ธ์ˆ˜๋Š” ๋งคํ•‘๋˜๋Š” WordPress ํ•จ์ˆ˜์—์„œ์˜ ์ด๋ฆ„์ด postID๋ผ ํ•˜๋”๋ผ๋„ customPostID๋ผ๊ณ  ๋ถ€๋ฆ…๋‹ˆ๋‹ค.

์ด๋ ‡๊ฒŒ ํ•จ์œผ๋กœ์จ ๊ธฐ๋Œ€ํ•˜๋Š” ๋™์ž‘์ด ํ•ญ์ƒ ๋ช…ํ™•ํ•ด์ง‘๋‹ˆ๋‹ค.

  • ํ•„๋“œ User.customPosts๋Š” posts์™€ pages๋ฅผ ํฌํ•จํ•œ ๋ชจ๋“  custom post ๋ชฉ๋ก์„ ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐ˜๋ฉด, User.posts๋Š” posts๋งŒ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค
  • ํ•„๋“œ Root.setFeaturedImageOnCustomPost๋Š” ๋ชจ๋“  custom post์— ๋Œ€ํ‘œ ์ด๋ฏธ์ง€๋ฅผ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค (๊ทธ๋ž˜์„œ setFeaturedImageOnPost๋ผ๊ณ  ๋ถ€๋ฅด์ง€ ์•Š์Šต๋‹ˆ๋‹ค)

tags (์™€ categories)๋ฅผ ๋‹จ์ผ type์œผ๋กœ ๋ฌถ์ง€ ์•Š๊ธฐ

์™œ PostTag (PostCategory๋„ ๋งˆ์ฐฌ๊ฐ€์ง€)๋ผ๋Š” type ์ด๋ฆ„์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฑธ๊นŒ์š”? ๋‹จ์ˆœํžˆ Tag๋ผ๊ณ  ํ•˜๋ฉด ์•ˆ ๋˜๋Š” ๊ฑธ๊นŒ์š”?

์™œ๋ƒํ•˜๋ฉด, ์ด ์ฟผ๋ฆฌ๋ฅผ ์‹คํ–‰ํ•  ๋•Œ (product๋ฅผ CPT๋กœ ๊ฐ€์ •), posts์™€ products์˜ tags ํ•„๋“œ ๊ฒฐ๊ณผ๋Š” ํ•ญ์ƒ ๋‹ค๋ฅด๊ณ  ๊ฒน์น˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

query {
  posts {
    tags {
      id
      name
    }
  }
  products {
    tags {
      id
      name
    }
  }
}

posts์— ์ถ”๊ฐ€๋œ tags๋Š” products์˜ tags๋ฅผ ๊ฒ€์ƒ‰ํ•ด๋„ ๋‚˜ํƒ€๋‚˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค (๋ฐ˜๋Œ€์˜ ๊ฒฝ์šฐ๋„ ๋งˆ์ฐฌ๊ฐ€์ง€์ž…๋‹ˆ๋‹ค). ๋‹จ, product๊ฐ€ post_tag ํƒ์†Œ๋…ธ๋ฏธ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ์—๋Š” PostTag type์œผ๋กœ ํ‘œํ˜„ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. WordPress์—์„œ๋Š” ์ด๋Ÿฌํ•œ ํ•ญ๋ชฉ๋“ค์„ ๋™์ผํ•œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ํ…Œ์ด๋ธ”์˜ ๋‹ค๋ฅธ ํ–‰์œผ๋กœ ์ทจ๊ธ‰ํ•  ์ˆ˜ ์žˆ์–ด ํฐ ๋ฌธ์ œ๊ฐ€ ์•„๋‹ˆ์ง€๋งŒ, ๊ฐ•ํ•œ ํƒ€์ž… ์‹œ์Šคํ…œ์„ ๊ฐ€์ง„ GraphQL์—์„œ๋Š” ์ค‘์š”ํ•œ ๊ตฌ๋ณ„์ž…๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ ์ด๋Ÿฌํ•œ ์—”ํ‹ฐํ‹ฐ๋“ค์„ ๊ฐ์ž์˜ type์œผ๋กœ ๋ถ„๋ฆฌํ•ด ๋‘๋Š” ๊ฒƒ์ด ์ข‹์€ ์„ค๊ณ„์ž…๋‹ˆ๋‹ค. posts์˜ tags๋Š” PostTag type์œผ๋กœ ๋ฐ˜ํ™˜ํ•˜๊ณ , ์ปค์Šคํ…€ ํ”Œ๋Ÿฌ๊ทธ์ธ์ด ์ž์ฒด product CPT๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ๊ฒฝ์šฐ ํ•ด๋‹น tags์— ProductTag type์„ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๋ฏธ๋””์–ด ์•„์ดํ…œ์— ๊ณ ์œ ํ•œ ์ •์ฒด์„ฑ ๋ถ€์—ฌํ•˜๊ธฐ

WordPress์˜ ๋ฏธ๋””์–ด ์—”ํ‹ฐํ‹ฐ๋Š” ๊ตฌํ˜„์ƒ์˜ ํŽธ์˜๋ฅผ ์œ„ํ•ด custom post type์œผ๋กœ ์ทจ๊ธ‰๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ GraphQL ์Šคํ‚ค๋งˆ์—์„œ๋Š” ์ด ๊ธฐ์ˆ ์  ๋ถ€์ฑ„๋ฅผ ํ”ผํ•˜๊ณ , ๋ฏธ๋””์–ด ์š”์†Œ๋ฅผ custom posts๊ฐ€ ์•„๋‹Œ ๊ณ ์œ ํ•œ ์—”ํ‹ฐํ‹ฐ๋กœ ๋ชจ๋ธ๋งํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด์— ๋”ฐ๋ผ GraphQL ์Šคํ‚ค๋งˆ์—์„œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ฒฐ์ •์ด ๋‚ด๋ ค์ง‘๋‹ˆ๋‹ค.

  • customPosts ํ•„๋“œ๋ฅผ ์ฟผ๋ฆฌํ•ด๋„ ๋ฏธ๋””์–ด ์š”์†Œ๋Š” ๊ฐ€์ ธ์˜ค์ง€ ์•Š์Šต๋‹ˆ๋‹ค
  • Media type์€ CustomPost ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•˜์ง€ ์•Š์œผ๋ฉฐ, CustomPostUnion type์— ํฌํ•จ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค
  • Media type์€ custom post type์—์„œ ๊ธฐ๋Œ€๋˜๋Š” excerpt, date, status ๋“ฑ์˜ ํ•„๋“œ๋ฅผ ๊ฐ–์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋Œ€์‹ , ๋ฏธ๋””์–ด ์š”์†Œ์—์„œ ๊ธฐ๋Œ€๋˜๋Š” ํ•„๋“œ๋งŒ ๊ฐ–์Šต๋‹ˆ๋‹ค.
type Media {
  id: ID!
  src: String!
  width: Int
  height: Int
}

enum ์‹๋ณ„ ๋ฐ ๋งคํ•‘

WordPress์—์„œ๋Š” ํŠน์ • ๊ฐ’ ์ง‘ํ•ฉ์—์„œ ๊ณ ์ •๋œ ๊ฐ’์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, post์˜ ์ƒํƒœ๋Š” "publish", "draft", "pending", "trash" ์ค‘ ํ•˜๋‚˜๋งŒ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

GraphQL์—์„œ๋Š” ์ด๊ฒƒ๋“ค์„ string ๋Œ€์‹  enum์œผ๋กœ ์ทจ๊ธ‰ํ•˜๊ณ , ๋Œ€์‘ํ•˜๋Š” enumeration type์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. GraphQL ํ‘œ์ค€์— ๋”ฐ๋ฅด๋ฉด enum์€ ๋Œ€๋ฌธ์ž๋กœ ์ž‘์„ฑ๋ฉ๋‹ˆ๋‹ค.

enum CUSTOM_POST_STATUS {
  PUBLISH
  DRAFT
  PENDING
  TRASH
}

๊ทธ๋Ÿฌ๋‚˜ ๊ทธ๋ ‡๊ฒŒ ํ•˜๋ฉด WordPress์™€ ์ง์ ‘ ์ƒํ˜ธ ์ž‘์šฉํ•˜๊ธฐ ์œ„ํ•ด ์ฟผ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. get_posts( [ "post_status" => "PUBLISH" ] )๊ฐ€ ์ž‘๋™ํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

๊ทธ๋ž˜์„œ ํƒ€ํ˜‘์•ˆ์œผ๋กœ, ์ด๋Ÿฌํ•œ enum ๊ฐ’๋“ค์€ ์†Œ๋ฌธ์ž๋กœ ์œ ์ง€ํ•ฉ๋‹ˆ๋‹ค.

enum CUSTOM_POST_STATUS {
  publish
  draft
  pending
  trash
}

์ถ”๊ฐ€ type ๋งคํ•‘

๋ธ”๋ก์€ WordPress ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋‹ค์ด์–ด๊ทธ๋žจ์—์„œ ์ง์ ‘ ๋ณด์ด์ง€ ์•Š์Šต๋‹ˆ๋‹ค. wp_posts์— ์ €์žฅ๋˜์–ด ์žˆ๊ณ  (wp_blocks๋ผ๋Š” ํ…Œ์ด๋ธ”์€ ์กด์žฌํ•˜์ง€ ์•Š์Œ), ๊ทธ๋Ÿผ์—๋„ ๋ถˆ๊ตฌํ•˜๊ณ  ๋…์ž์ ์ธ ์—”ํ‹ฐํ‹ฐ์ž…๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ ๋ธ”๋ก์„ ๋งคํ•‘ํ•˜๊ธฐ ์œ„ํ•ด Block type์„ ๋„์ž…ํ•ฉ๋‹ˆ๋‹ค.

type Post {
  blocks: [Block]
}
 
type Block {
  type: String!
  attributes: JSONObject
}

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

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