๋ธ”๋กœ๊ทธ

๐Ÿ’ฌ 'Gutenberg๊ณผ ๋ถ„๋ฆฌํ˜• ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜'์— ๋Œ€ํ•œ ์ƒˆ๋กœ์šด ์ ‘๊ทผ ๋ฐฉ์‹ ์ œ์•ˆ

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

๋ฉฐ์น  ์ „, WPGraphQL์˜ ์ œ์ž‘์ž์ธ Jason Bahl์ด Gutenberg and Decoupled Applications๋ฅผ ๊ณต๊ฐœํ•˜์—ฌ GraphQL๊ณผ Gutenberg๋ฅผ ํ†ตํ•ฉํ•˜๋Š” 3๊ฐ€์ง€ ์ ‘๊ทผ ๋ฐฉ์‹์˜ ์žฅ๋‹จ์ ์„ ๋ถ„์„ํ–ˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋กœ๋ถ€ํ„ฐ ์ผ์ฃผ์ผ ์ „, ๊ทธ๋Š” Twitter์—์„œ๋„ ์–ธ๊ธ‰ํ–ˆ์Šต๋‹ˆ๋‹ค. Gato GraphQL์˜ Gutenberg ๋ชจ๋ธ๋ง ์ ‘๊ทผ ๋ฐฉ์‹์€ ๋ถ€์ ์ ˆํ•˜๋‹ค๊ณ ์š”:

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

์˜ˆ์ธก ๊ฐ€๋Šฅํ•œ ํ˜•ํƒœ๊ฐ€ ์—†๋Š” ์™€์ผ๋“œ์นด๋“œ ใ€ŒObjectใ€ ํƒ€์ž…์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค๋Š” ๊ฒƒ์€ ์„œ๋ฒ„์™€ ํด๋ผ์ด์–ธํŠธ ์‚ฌ์ด์— ๋” ์ด์ƒ ๊ณ„์•ฝ์ด ์—†์œผ๋ฏ€๋กœ ํด๋ผ์ด์–ธํŠธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์–ธ์ œ๋“ ์ง€ ์ค‘๋‹จ๋  ์ˆ˜ ์žˆ์Œ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ์„œ๋ฒ„๊ฐ€ ํด๋ผ์ด์–ธํŠธ๋กœ๋ถ€ํ„ฐ ์ œ์–ด๊ถŒ์„ ๋นผ์•—์•„ ๋ฒ„๋ฆฐ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

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

COPE๋ฅผ ์‚ฌ์šฉํ•œ Gutenberg ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ์ถ”์ถœ

์ €์˜ ์†”๋ฃจ์…˜์€ ๋„ค ๋ฒˆ์งธ ์ ‘๊ทผ ๋ฐฉ์‹์œผ๋กœ ๋ณผ ์ˆ˜ ์žˆ์œผ๋ฉฐ, ๋‚ด์šฉ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค:

GraphQL์„ ๊ตฌ๋™ํ•˜๊ธฐ ์œ„ํ•œ Gutenberg ๋ฐ์ดํ„ฐ๋ฅผ ์–ป๊ธฐ ์œ„ํ•ด PHP ์ธก์— ์ถ”๊ฐ€ ์Šคํ‚ค๋งˆ๋ฅผ ๋งŒ๋“ค๊ฑฐ๋‚˜ ๊ธฐ์กด ๋ฐ์ดํ„ฐ๋ฅผ ๋ณต์ œํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋Œ€์‹  COPE(ใ€ŒCreate Once, Publish Everywhereใ€) ์ „๋žต์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ธ”๋ก์— ์ €์žฅ๋œ ์ฝ˜ํ…์ธ ์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์ถ”์ถœํ•ฉ๋‹ˆ๋‹ค.

(COPE๋Š” ์ฝ˜ํ…์ธ ์˜ ๋‹จ์ผ ์‹ ๋ขฐ ์†Œ์Šค๋ฅผ ๊ฐ–๊ณ  ์ด๋ฅผ ๋‹ค์–‘ํ•œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ๋…ธ์ถœํ•  ์ˆ˜ ์žˆ๋Š” ์ „๋žต์ž…๋‹ˆ๋‹ค. ์šฐ๋ฆฌ์˜ ๊ฒฝ์šฐ ๋‹จ์ผ ์‹ ๋ขฐ ์†Œ์Šค๋Š” ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์ €์žฅ๋œ Gutenberg ๋ธ”๋ก ๋ฐ์ดํ„ฐ์ž…๋‹ˆ๋‹ค. COPE์™€ WordPress์— ๋Œ€ํ•œ ๊ตฌํ˜„์€ ์ด ๊ธ€์—์„œ ์„ค๋ช…ํ–ˆ์Šต๋‹ˆ๋‹ค.)

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

์ด ์ „๋žต์€ ์ ˆ์ถฉ์•ˆ์ด์ง€ ๊ฒฐ์ •์ ์ธ ํ•ด๊ฒฐ์ฑ…์ด ์•„๋‹™๋‹ˆ๋‹ค

์ด ์ „๋žต์€ Jason์ด ์ง€์ ํ•˜๋Š” ๋ฌธ์ œ, ์ฆ‰ ์„œ๋ฒ„ ์ธก์— ์Šคํ‚ค๋งˆ๊ฐ€ ์—†์–ด ์„œ๋ฒ„์™€ ํด๋ผ์ด์–ธํŠธ ์‚ฌ์ด์˜ ๊ณ„์•ฝ์„ ๋งŒ๋“ค ์ˆ˜ ์—†๋‹ค๋Š” ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜์ง€๋Š” ์•Š์Šต๋‹ˆ๋‹ค.

COPE๊ฐ€ ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์—†๋Š” ์ด์œ ๋Š” ์ €์žฅ๋œ ์ฝ˜ํ…์ธ ๋งŒ์œผ๋กœ๋Š” ์Šคํ‚ค๋งˆ๋ฅผ ์žฌ๊ตฌ์„ฑํ•  ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค:

  • ์ €์žฅ๋œ ์ฝ˜ํ…์ธ ๋Š” ํ•„๋“œ์˜ ํƒ€์ž…์„ ๋‚˜ํƒ€๋‚ด์ง€ ์•Š์Šต๋‹ˆ๋‹ค
  • ์ €์žฅ๋œ ์ฝ˜ํ…์ธ ๋Š” ํ•„๋“œ์˜ ์ œ์•ฝ ์กฐ๊ฑด(nullable์ธ์ง€? ์–‘์˜ ์ •์ˆ˜์ธ์ง€? ๋ฌธ์ž์—ด์ด ์ด๋ฉ”์ผ์ธ์ง€ URL์ธ์ง€?)์„ ๋‚˜ํƒ€๋‚ด์ง€ ์•Š์Šต๋‹ˆ๋‹ค
  • nullable ํ•„๋“œ๋Š” ๊ธฐ๋ณธ๊ฐ’์„ ๊ฐ€์งˆ ์ˆ˜ ์žˆ๋Š”๋ฐ, ์ด๋Š” ์ €์žฅ๋œ ์ฝ˜ํ…์ธ ์— ๋‚˜ํƒ€๋‚˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค

๊ทธ๋Ÿฌ๋‚˜ COPE ์ „๋žต๊ณผ ๋‹จ์ผ Block ํƒ€์ž…์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ชจ๋“  ๋ธ”๋ก์„ ํ‘œํ˜„ํ•จ์œผ๋กœ์จ, Gato GraphQL์€ ๊ธฐ์กด์˜ ํ•œ๊ณ„๋ฅผ ๊ทน๋ณตํ•œ Gutenberg์™€์˜ ๋งค์šฐ ํ›Œ๋ฅญํ•œ ํ†ตํ•ฉ์„ ๊ตฌ์ถ•ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด ๊ธ€ ์ „์ฒด์—์„œ ์„ค๋ช…๋“œ๋ฆฌ๊ฒ ์Šต๋‹ˆ๋‹ค.

Gato GraphQL๊ณผ Gutenberg์˜ ํ†ตํ•ฉ

์ด ์†”๋ฃจ์…˜์€ ์•„์ง ์ง„ํ–‰ ์ค‘์ธ ์ž‘์—…์ด์ง€๋งŒ, ์–ด๋–ป๊ฒŒ ๋™์ž‘ํ• ์ง€๋Š” ์ด๋ฏธ ์„ค๋ช…ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ธ”๋ก๋งˆ๋‹ค ๋‹ค๋ฅธ ํƒ€์ž…์— ์˜์กดํ•˜๋Š”(WPGraphQL์ด WPGraphQL for Gutenberg ํ”Œ๋Ÿฌ๊ทธ์ธ์— ์˜์กดํ•  ๋•Œ ํ•˜๋Š” ๋ฐฉ์‹) ๋Œ€์‹ , Gato GraphQL์€ ๋ชจ๋“  ๋ธ”๋ก์„ ํ‘œํ˜„ํ•˜๋Š” ๋‹จ์ผ Block ํƒ€์ž…์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

์ด ์ฟผ๋ฆฌ์—์„œ Post.blockDataItems ํ•„๋“œ๋Š” ๊ฒŒ์‹œ๋ฌผ์—์„œ Block ์š”์†Œ ๋ชฉ๋ก์„ ๊ฒ€์ƒ‰ํ•ฉ๋‹ˆ๋‹ค(๋‹จ๋ฝ, ์ด๋ฏธ์ง€, ๋ชฉ๋ก ๋“ฑ ๋‹ค์–‘ํ•œ Gutenberg ๋ธ”๋ก ํฌํ•จ):

{
  post(by: { id: 1499 }) {
    title
    blockDataItems
  }
}

ํŠน์ • ๋ธ”๋ก์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฒ€์ƒ‰ํ•˜๋ ค๋ฉด ๋ธ”๋ก์˜ ์ด๋ฆ„(core/paragraph, core/quote ๋“ฑ)์„ ๊ธฐ์ค€์œผ๋กœ ํ•„ํ„ฐ๋งํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด ์ฟผ๋ฆฌ์—์„œ๋Š” ์ด๋ฏธ์ง€ ๋ธ”๋ก๋งŒ ๊ฒ€์ƒ‰ํ•ฉ๋‹ˆ๋‹ค:

{
  post(by: { id: 1177 }) {
    title
    blockDataItems(
      filterBy: { include: "core/image" }
    )
  }
}

๋‹จ์ผ Block ํƒ€์ž… ์‚ดํŽด๋ณด๊ธฐ

์ด ์ ‘๊ทผ ๋ฐฉ์‹์—์„œ ์‘๋‹ต์€ ์Šคํ‚ค๋งˆ๊ฐ€ ์•„๋‹Œ ์ €์žฅ๋œ ์ฝ˜ํ…์ธ ์— ๋”ฐ๋ผ ๋‹ฌ๋ผ์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ํŠน์„ฑ์€ ๊ทธ ์žฅ์ (API๋ฅผ ์œ ์—ฐํ•˜๊ฒŒ ๋งŒ๋“ฆ)์ด์ž ๋‹จ์ (์„œ๋ฒ„-ํด๋ผ์ด์–ธํŠธ ๊ณ„์•ฝ์„ ๊ฐ•์ œํ•  ์ˆ˜ ์—†์Œ)์ž…๋‹ˆ๋‹ค.

๋ชจ๋“  Block ์š”์†Œ๋Š” ๋‘ ๊ฐ€์ง€ ์†์„ฑ์„ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค:

  • name: ๋ธ”๋ก์˜ ์ด๋ฆ„(core/paragraph, core/quote ๋“ฑ)
  • meta: ๋ธ”๋ก์— ํฌํ•จ๋œ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ

๊ฐ Gutenberg ๋ธ”๋ก์€ ์„œ๋กœ ๋‹ค๋ฅด๋ฉฐ, ๋‹ค๋ฅธ ๋ฐ์ดํ„ฐ๋ฅผ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค(๋‹จ๋ฝ ์ฝ˜ํ…์ธ , YouTube ๋™์˜์ƒ, ์ด๋ฏธ์ง€ ์†Œ์Šค URL๊ณผ ํฌ๊ธฐ ๋“ฑ). ๋”ฐ๋ผ์„œ meta ํ•„๋“œ์˜ ์‘๋‹ต์— ํฌํ•จ๋œ ๋ฐ์ดํ„ฐ๋„ ๋‹ฌ๋ผ์ง‘๋‹ˆ๋‹ค.

๊ทธ ๋•Œ๋ฌธ์— meta ํ•„๋“œ๋Š” GraphQL ์Šคํ‚ค๋งˆ์˜ ํ•ด๋‹น JSONObject ํƒ€์ž…์„ ํ†ตํ•ด ๋‹จ์ˆœํžˆ JSON ๊ฐ์ฒด(ใ€Œ์›์‹œใ€ ๋ฐ์ดํ„ฐ๋ฅผ ํฌํ•จํ•  ์ˆ˜ ์žˆ๋Š”)๋กœ ๋งคํ•‘๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

์ด๋Ÿฐ ์‘๋‹ต์ด ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค:

{
  "data": {
    "post": {
      "title": "COPE with WordPress: Post demo containing plenty of blocks",
      "blockDataItems": [
        {
          "name": "core/paragraph",
          "attributes": {
            "content": "Lorem ipsum dolor sit amet"
          }
        },
        {
          "name": "core/image",
          "attributes": {
            "src": "https://ps.w.org/gutenberg/assets/banner-1544x500.jpg"
          }
        },
        {
          "name": "core/quote",
          "attributes": {
            "quote": "Etiam tempor orci eu lobortis elementum nibh tellus molestie",
            "cite": "Aristoteles"
          }
        },
        {
          "name": "core/heading",
          "attributes": {
            "size": "xl",
            "heading": "Welcome to my site"
          }
        },
        {
          "name": "core/list",
          "attributes": {
            "items": [
              "First element",
              "Second element",
              "Third element"
            ]
          }
        },
      ]
    }
  }
}

๋ณด์‹œ๋‹ค์‹œํ”ผ ๊ฐ๊ธฐ ๋‹ค๋ฅธ ๋ธ”๋ก์ด ๋‹ค๋ฅธ ์†์„ฑ์„ ๊ฒ€์ƒ‰ํ•ฉ๋‹ˆ๋‹ค:

  • core/paragraph๋Š” content ์†์„ฑ์„ ๊ฐ€์ง‘๋‹ˆ๋‹ค
  • core/image๋Š” src ์†์„ฑ์„ ๊ฐ€์ง€๋ฉฐ, ์„ ํƒ์ ์œผ๋กœ width, height, caption ์†์„ฑ์„ ๊ฐ€์ง‘๋‹ˆ๋‹ค(์œ„ ์‘๋‹ต์—๋Š” ๋‚˜ํƒ€๋‚˜์ง€ ์•Š์Œ)
  • core/quote๋Š” quote์™€ cite(์ธ์šฉ๋œ ์ธ๋ฌผ์„ ์œ„ํ•œ) ์†์„ฑ์„ ๊ฐ€์ง‘๋‹ˆ๋‹ค
  • core/heading์€ header์™€ size ์†์„ฑ์„ ๊ฐ€์ง‘๋‹ˆ๋‹ค(xl ๊ฐ’์€ <h2>๋ฅผ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค. COPE๊ฐ€ ๊ฐ’์„ ๋Œ€์ƒ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜, ์ด ๊ฒฝ์šฐ ์›น์‚ฌ์ดํŠธ๋กœ๋ถ€ํ„ฐ ๋ถ„๋ฆฌํ•˜๊ธฐ ๋•Œ๋ฌธ)
  • core/list๋Š” items ์†์„ฑ์„ ๊ฐ€์ง€๋ฉฐ, ์ด๋Š” ์š”์†Œ์˜ ๋ชฉ๋ก์ž…๋‹ˆ๋‹ค

JSONObject ํƒ€์ž…์ด ์ŠคํŽ™์— ํฌํ•จ๋˜์ง€ ์•Š๋Š” ์ด์œ 

์œ„์—์„œ ์„ค๋ช…ํ•œ JSONObject ํƒ€์ž…์„ ํ†ตํ•ด GraphQL์€ ใ€Œ๋™์ ใ€ ํ•„๋“œ(๋ชจ๋ฅด๋Š” ํ•„๋“œ ๋“ฑ) ๋˜๋Š” ์—ฌ๋Ÿฌ ๊ตฌ์„ฑ์„ ๊ฐ€์งˆ ์ˆ˜ ์žˆ๋Š” ํ•„๋“œ(Gutenberg ๋ธ”๋ก์˜ ๊ฒฝ์šฐ๊ฐ€ ์ด์— ํ•ด๋‹น)๋ฅผ ๊ฒ€์ƒ‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํ˜„์žฌ GraphQL ์ŠคํŽ™์€ JSONObject๋‚˜ Map ํƒ€์ž…์„ ์ง€์›ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ง€์› ์ถ”๊ฐ€๊ฐ€ ์š”์ฒญ๋˜์—ˆ๋Š”๋ฐ, ๊ทธ ์ด์œ ๋กœ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์˜๊ฒฌ์ด ์žˆ์Šต๋‹ˆ๋‹ค:

[...] ์ด ๊ธฐ๋Šฅ์˜ ๋ถ€์žฌ๋Š” ํŠนํžˆ ๋ฌธ์ œ๊ฐ€ ๋ฉ๋‹ˆ๋‹ค. GraphQL์ด ์ธํ„ฐํŽ˜์ด์Šคํ•˜๋Š” ๋งŽ์€ ํƒ€์ž… ์‹œ์Šคํ…œ๊ณผ ์„œ๋น„์Šค์—์„œ ์ง€์›๋˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

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

์ด ๊ธฐ๋Šฅ์ด ์ŠคํŽ™์—์„œ ์ง€์›๋˜์ง€ ์•Š๋Š” ๊ฒƒ์€ ๋™์  ํ•„๋“œ๋ฅผ ๋‹ค๋ฃจ๋Š” ๊ฒƒ์ด GraphQL์˜ ๊ฐ•๋ ฅํ•œ ํƒ€์ž… ์ง€์ • ๋™์ž‘์— ๋ฐ˜ํ•˜์—ฌ ์„œ๋ฒ„์™€ ํด๋ผ์ด์–ธํŠธ ๊ฐ„์˜ ๊ณ„์•ฝ์„ ๊นจ๋œจ๋ฆฌ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

๊ทธ๋ž˜๋„ ์ด ํƒ€์ž…์€ Gutenberg์— ์œ ์ตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋‚˜์ค‘์— ๋ณด์—ฌ๋“œ๋ฆฌ๊ฒ ์Šต๋‹ˆ๋‹ค.

๋ธ”๋ก๋งˆ๋‹ค ๋‹ค๋ฅธ ํƒ€์ž…๊ณผ ์„œ๋ฒ„ ์ธก ๋ ˆ์ง€์ŠคํŠธ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ์˜ ๋ฌธ์ œ

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

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

์ด๋Š” GraphQL์ด ์™ธ๋ถ€ ํด๋ผ์šฐ๋“œ ๊ธฐ๋ฐ˜ ์„œ๋น„์Šค์™€ ์ƒํ˜ธ์ž‘์šฉํ•˜์—ฌ ๊ฒŒ์‹œ๋ฌผ์˜ ๋ชจ๋“  ๋ธ”๋ก์— ์–ด๋–ค ๊ธฐ๋Šฅ์„ ์ ์šฉํ•  ๋•Œ(๋ฒˆ์—ญ, ๋ฌธ๋ฒ• ์ˆ˜์ •, SEO ์ œ์•ˆ, ๋ถ„์„ ๋“ฑ์„ ์ƒ๊ฐํ•ด ๋ณด์„ธ์š”) ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด์— ๋Œ€ํ•œ ์˜ˆ์‹œ๋ฅผ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

Gutenberg 4๋‹จ๊ณ„์—์„œ ๋‹ค๊ตญ์–ด ๊ธฐ๋Šฅ์ด ์ถ”๊ฐ€๋  ์˜ˆ์ •์ด๋ฏ€๋กœ, @strTranslate ๋””๋ ‰ํ‹ฐ๋ธŒ๋ฅผ ํ†ตํ•ด ์‹คํ–‰๋˜๋Š” Google Translate API ํ˜ธ์ถœ๋กœ ํ”Œ๋Ÿฌ๊ทธ์ธ ๋‚ด ๋ชจ๋“  ๋ธ”๋ก์„ ๋ฒˆ์—ญํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ชจ๋ธ๋งํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

(์ด ์ดˆ๊ธฐ API ๊ธฐ๋ฐ˜ ๋ฒˆ์—ญ ์ดํ›„, ์‚ฌ์šฉ์ž๋Š” ํ•ญ์ƒ WordPress ํŽธ์ง‘๊ธฐ ๋‚ด์—์„œ ๋ฒˆ์—ญ๋œ ์–ธ์–ด๋กœ ๋ธ”๋กœ๊ทธ ๊ฒŒ์‹œ๋ฌผ์„ ๊ณ„์† ํŽธ์ง‘ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.)

๊ฐ๊ธฐ ๋‹ค๋ฅธ ๋ธ”๋ก์—๋Š” ๋ฒˆ์—ญ์ด ํ•„์š”ํ•œ ๋‹ค์–‘ํ•œ ์ •๋ณด๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค:

  • core/paragraph: ํ…์ŠคํŠธ
  • core/image: ์บก์…˜
  • core/quote: ์ธ์šฉ๋ฌธ ๋ฐ ์ธ์šฉ๋œ ์ธ๋ฌผ(ใ€Œ๊ต์žฅ ์„ ์ƒ๋‹˜ใ€๊ณผ ๊ฐ™์€ ์งํ•จ์ผ ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ)
  • core/heading: ์ œ๋ชฉ
  • core/list: ๋ชฉ๋ก์˜ ๋ชจ๋“  ํ•ญ๋ชฉ

๋ธ”๋ก๋งˆ๋‹ค ๋‹ค๋ฅธ ํƒ€์ž…์„ ์‚ฌ์šฉํ•˜๋ฉด ๊ฒฐ๊ณผ ์ฟผ๋ฆฌ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

{
  post(by: { id: 1 }) {
    blocks {
      ... on CoreParagraphBlock {
        content @strTranslate
      }
      ... on CoreImageBlock {
        caption @strTranslate
      }
      ... on CoreQuoteBlock {
        quote @strTranslate
        cite @strTranslate
      }
      ... on CoreHeadingBlock {
        heading @strTranslate
      }
      ... on CoreListBlock {
        items @strTranslateList
      }
      ... on EmbedTwitterBlock {
        caption @strTranslate
      }
      ... on EmbedYoutubeBlock {
        caption @strTranslate
      }
      ... on EmbedVimeoBlock {
        caption @strTranslate
      }
    }
  }
}

์ด๋Ÿฐ ์‹์œผ๋กœ ๊ณ„์†๋ฉ๋‹ˆ๋‹ค. ๋ธ”๋ก์ด ๋งŽ์•„์งˆ์ˆ˜๋ก ์ด ์ฟผ๋ฆฌ๋Š” ๊ธธ์–ด์ ธ์„œ ์‰ฝ๊ฒŒ 100์ค„ ์ด์ƒ์œผ๋กœ ๋Š˜์–ด๋‚ฉ๋‹ˆ๋‹ค.

๋ช…๋ฐฑํ•œ ๋ฌธ์ œ๋Š” ์ฟผ๋ฆฌ๊ฐ€ ์šฐ๋ฆฌ๊ฐ€ ์œ ์ง€ ๊ด€๋ฆฌํ•ด์•ผ ํ•˜๋Š” ๋‹ค๋ฃจ๊ธฐ ํž˜๋“  ์กด์žฌ๊ฐ€ ๋œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๋˜ํ•œ ๋ชจ๋“  ๋ธ”๋ก์— ๋Œ€ํ•ด ์ž‘๋™ํ•˜๊ฒŒ ํ•˜๋ ค๋ฉด ์ปค์Šคํ…€ ๊ธฐ๋Šฅ์„ ๋„์ž…ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด @strTranslate๋Š” CoreListBlock.items์—๋Š” ์ž‘๋™ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ด๋Š” ๋ฌธ์ž์—ด ๋ชฉ๋ก(์ฆ‰, [String]์„ ๋ฐ˜ํ™˜)์ธ๋ฐ ๋””๋ ‰ํ‹ฐ๋ธŒ๋Š” String์„ ๊ธฐ๋Œ€ํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ @strTranslateList๋ฅผ ๋งŒ๋“ค์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋ฉด core/table์—๋Š” ์ž์ฒด ์ปค์Šคํ…€ ๋””๋ ‰ํ‹ฐ๋ธŒ(@strTranslateTable?)๊ฐ€ ํ•„์š”ํ•ด์ง‘๋‹ˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ  ์„œ๋“œํŒŒํ‹ฐ ์ปค์Šคํ…€ ๋ธ”๋ก์€ ์ž์ฒด ์ปค์Šคํ…€ ๋””๋ ‰ํ‹ฐ๋ธŒ๊ฐ€ ํ•„์š”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋˜ํ•œ ๋ช‡ ๊ฐ€์ง€ ๋ฌธ์ œ๊ฐ€ ๋” ๋ณด์ž…๋‹ˆ๋‹ค.

์ „๋ถ€ ์•„๋‹ˆ๋ฉด ์ „๋ฌด

๋ธ”๋กœ๊ทธ ๊ฒŒ์‹œ๋ฌผ์—๋Š” WordPress ํŽธ์ง‘๊ธฐ์— ์„ค์น˜๋œ ์ž„์˜์˜ ๋ธ”๋ก์ด ํฌํ•จ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ฟผ๋ฆฌ๋ฅผ ์ฝ”๋”ฉํ•  ๋•Œ ๊ฒŒ์‹œ๋ฌผ์ด ์–ด๋–ค ๋ธ”๋ก์„ ์‚ฌ์šฉํ•˜๋Š”์ง€ ๋ฏธ๋ฆฌ ์•Œ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

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

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

๊ฒฐ๊ณผ์ ์œผ๋กœ ๋ฌธ์ œ๊ฐ€ ๋˜๋Š” ๋ธ”๋ก์„ ํฌํ•จํ•˜๋“  ์•„๋‹ˆ๋“  ๋ฒˆ์—ญ๋œ ๊ฒŒ์‹œ๋ฌผ์„ ๋” ์ด์ƒ ์‹ ๋ขฐํ•  ์ˆ˜ ์—†๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ๋ชจ๋“  ๋ธ”๋ก์ด ๋ ˆ์ง€์ŠคํŠธ๋ฆฌ์— ์ถ”๊ฐ€๋˜์ง€ ์•Š์œผ๋ฉด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์‹ ๋ขฐํ•  ์ˆ˜ ์—†๊ฒŒ ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ƒˆ ๋ธ”๋ก์ด ์„ค์น˜๋  ๋•Œ๋งˆ๋‹ค ์ฟผ๋ฆฌ๋ฅผ ์—…๋ฐ์ดํŠธํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค

๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ๋ชจ๋“  ๋ธ”๋ก์€ GraphQL ์ฟผ๋ฆฌ์—์„œ ์ฒ˜๋ฆฌ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ฆ‰, ์ƒˆ ๋ธ”๋ก์„ ์„ค์น˜ํ•  ๋•Œ๋งˆ๋‹ค ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ฝ”๋“œ๋กœ ๋Œ์•„๊ฐ€์„œ ์—…๋ฐ์ดํŠธํ•˜๊ณ  ์žฌ๋ฐฐํฌํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์ด๊ฒƒ์€ ๋‹จ์ˆœํ•œ ์ถ”๊ฐ€ ๊ด€๋ฃŒ์ฃผ์˜๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค: ๋ชจ๋“  ์ฟผ๋ฆฌ๊ฐ€ ์—…๋ฐ์ดํŠธ๋  ๋•Œ๊นŒ์ง€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๊นจ๋œจ๋ฆด ์šฐ๋ ค ์—†์ด ๋ผ์ด๋ธŒ ์‚ฌ์ดํŠธ์— ๋ธ”๋ก์„ ์„ค์น˜ํ•  ์ˆ˜ ์—†๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

GraphQL์€ WordPress๋ฅผ ์œ„ํ•ด ์กด์žฌํ•ด์•ผ ํ•˜๋ฉฐ, ๊ทธ ๋ฐ˜๋Œ€๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค

JSONObject๊ฐ€ GraphQL ์ŠคํŽ™์— ์ถ”๊ฐ€๋˜์ง€ ์•Š์€ ์ด์œ ๋ฅผ ๋‹ค์‹œ ์ƒ๊ฐํ•ด๋ณด๋ฉด, ๊ทธ๊ฒƒ์ด GraphQL ๋ฐฉ์‹์— ๋งž์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ ์—ฌ๊ธฐ์„œ ์šฐ๋ฆฌ๊ฐ€ ์ง„์ •์œผ๋กœ ๊ด€์‹ฌ์„ ๊ฐ–๋Š” ๊ฒƒ์€ GraphQL์ด ์•„๋‹™๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๊ฐ€ ์‹ ๊ฒฝ ์“ฐ๋Š” ๊ฒƒ์€ WordPress์ด๋ฉฐ, ์ด ๊ฒฝ์šฐ์—๋Š” ๋” ๊ตฌ์ฒด์ ์œผ๋กœ Gutenberg์ž…๋‹ˆ๋‹ค.

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

๊ทธ๋ฆฌ๊ณ  ์ถฉ๋Œ์ด ๋ฐœ์ƒํ•˜๋Š” ๊ฒฝ์šฐ WordPress๊ฐ€ ์šฐ์„ ํ•ฉ๋‹ˆ๋‹ค.

์–ด๋–ค ๊ธฐ๋Šฅ์ด GraphQL์—๋Š” ๋งž์ง€ ์•Š์ง€๋งŒ Gutenberg์—๋Š” ๋งž๋Š” ๊ฒฝ์šฐ, ๊ทธ๊ฒƒ์„ ๊ณ ๋ คํ•ด์•ผ ํ• ๊นŒ์š”?

์ €๋Š” ๊ทธ๋ž˜์•ผ ํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

๋‹จ์ผ Block ํƒ€์ž…์ด ์–ด๋–ป๊ฒŒ Gutenberg๋ฅผ ๋” ์ž˜ ์ง€์›ํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

๋‹จ์ผ Block ํƒ€์ž…์œผ๋กœ ์ด์ „ ๋ฌธ์ œ ํ•ด๊ฒฐํ•˜๊ธฐ

์•ž์˜ ์˜ˆ์‹œ์— ๋”ฐ๋ผ ๋‹จ์ผ Block ํƒ€์ž…์„ ์‚ฌ์šฉํ•˜์—ฌ ๊ฒŒ์‹œ๋ฌผ์˜ ๋ชจ๋“  ๋ธ”๋ก์„ ์˜์–ด์—์„œ ํ”„๋ž‘์Šค์–ด๋กœ ๋ฒˆ์—ญํ•˜๋Š” ๊ฒƒ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋ฉ๋‹ˆ๋‹ค(๋˜๋Š” ์ด ๊ฐœ๋…์— ๊ทผ์ ‘ํ•œ ๋ฐฉ์‹์œผ๋กœ):

{
  post(by: { id: 1 }) {
    blocks {
      name
      meta
        @advancePointersInArray(paths: "{{ translatablePaths }}")
          @underEachArrayItem
            @strTranslate(from: "en", to: "fr")
    }
  }
}

์ด๊ฒŒ ์ „๋ถ€์ธ๊ฐ€์š”? ์ „์ฒด ์ฟผ๋ฆฌ๊ฐ€? ๋ชจ๋“  ๋ธ”๋ก์„ ๋ฒˆ์—ญํ•˜๊ธฐ ์œ„ํ•ด? ๋„ค.

์ฝ”์–ด์™€ ํ”Œ๋Ÿฌ๊ทธ์ธ ๋ชจ๋‘์˜ ์ด๋ฏธ ์กด์žฌํ•˜๊ฑฐ๋‚˜ ์•„์ง ๋งŒ๋“ค์–ด์ง€์ง€ ์•Š์€ ๋ชจ๋“  ๋ธ”๋ก์— ๋Œ€ํ•ด ์ž‘๋™ํ• ๊นŒ์š”? ๋„ค.

์ด ์ฟผ๋ฆฌ๊ฐ€ ์กฐ๊ธˆ ์ด์ƒํ•ด ๋ณด์ด์‹œ๋‚˜์š”? ๊ทธ๋ ‡๋‹ค๋ฉด Gato GraphQL์—์„œ๋งŒ ์ง€์›ํ•˜๋Š” ๋น„ํ‘œ์ค€ GraphQL ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค:

  • {{ translatablePaths }}๋Š” ์ž„๋ฒ ๋“œ ๊ฐ€๋Šฅํ•œ ํ•„๋“œ๋กœ, ํ•„๋“œ์˜ ๊ฐ’์„ ๋‹ค๋ฅธ ํ•„๋“œ๋‚˜ ๋””๋ ‰ํ‹ฐ๋ธŒ์˜ ์ธ์ˆ˜๋กœ ์ž…๋ ฅํ•˜๊ธฐ ์œ„ํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค(์ด ๊ฒฝ์šฐ Block ํƒ€์ž…์€ translatableFields ํ•„๋“œ๋ฅผ ๊ฐ€์ง€๋ฉฐ, ๊ทธ ๊ฐ’์ด @advancePointersInArray ๋””๋ ‰ํ‹ฐ๋ธŒ์— ์ฃผ์ž…๋ฉ๋‹ˆ๋‹ค)
  • ๋””๋ ‰ํ‹ฐ๋ธŒ๋Š” ๋‹ค๋ฅธ ๋””๋ ‰ํ‹ฐ๋ธŒ๋กœ ๊ตฌ์„ฑ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค

์–ด๋–ค ๊ธฐ๋Šฅ์ด CMS๊ฐ€ ํ•„์š”๋กœ ํ•˜๋Š” ๊ฒƒ์„ ์ •ํ™•ํžˆ ์ถฉ์กฑ์‹œํ‚ค์ง€๋งŒ ๊ทธ ๊ธฐ๋Šฅ์ด ๋น„ํ‘œ์ค€์ธ ๊ฒฝ์šฐ, ๊ทธ๋ž˜๋„ ์‚ฌ์šฉํ•ด์•ผ ํ• ๊นŒ์š”? ์ €๋Š” ๊ทธ๋ž˜์•ผ ํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

์ด๋Ÿฌํ•œ ๊ธฐ๋Šฅ๋“ค์— ๋Œ€ํ•ด GraphQL ์ŠคํŽ™์—๋„ ์š”์ฒญ์„ ํ–ˆ์Šต๋‹ˆ๋‹ค(๋ฐ›์•„๋“ค์—ฌ์ง€์ง€ ์•Š๊ฒ ์ง€๋งŒ):

๋‹จ์ผ Block ํƒ€์ž…์˜ ์ž‘๋™ ๋ฐฉ์‹

์ฃผ์˜: ๊ธฐ์ˆ ์ ์ธ ์„น์…˜์ด ์ด์–ด์ง‘๋‹ˆ๋‹ค.

Block ํƒ€์ž…์€ translatablePaths ํ•„๋“œ๋ฅผ ๊ฐ€์ง€๋ฉฐ, ๋ฒˆ์—ญ์ด ํ•„์š”ํ•œ JSONObject์˜ ์†์„ฑ ๋ฐฐ์—ด์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค:

  • core/paragraph๋Š” ["content"]๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค
  • core/image๋Š” ["caption"]์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค
  • core/quote๋Š” ["quote", "cite"]๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค
  • core/heading์€ ["header"]๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค
  • core/list๋Š” ["items.0", "items.1", "items.2", ...]๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค

@advancePointersInArray๋Š” ๋ฉ”ํƒ€ ๋””๋ ‰ํ‹ฐ๋ธŒ์ž…๋‹ˆ๋‹ค: ์ดํ›„ ๋””๋ ‰ํ‹ฐ๋ธŒ์˜ ์ปจํ…์ŠคํŠธ๋ฅผ ์ˆ˜์ •ํ•ฉ๋‹ˆ๋‹ค. ์ดํ›„ ๋””๋ ‰ํ‹ฐ๋ธŒ๊ฐ€ ์ฟผ๋ฆฌ๋œ JSONObject ๋‚ด์˜ ํ•˜์œ„ ์š”์†Œ(๋‹จ๋ฝ ๋ธ”๋ก์˜ content ์†์„ฑ ๋“ฑ)๋ฅผ ๋ฐ›๋„๋ก ํ•ฉ๋‹ˆ๋‹ค. ๊ฒฝ๋กœ ๋ชฉ๋ก์€ ๋™์ผํ•˜๊ฒŒ ์ฟผ๋ฆฌ๋œ ์—”ํ„ฐํ‹ฐ์—์„œ ํ‰๊ฐ€๋œ translatablePaths ํ•„๋“œ๋ฅผ ํ†ตํ•ด ์–ป์Šต๋‹ˆ๋‹ค.

๊ทธ๋Ÿฐ ๋‹ค์Œ @underEachArrayItem์€ ๋˜ ๋‹ค๋ฅธ ๋ฉ”ํƒ€ ๋””๋ ‰ํ‹ฐ๋ธŒ๋กœ, ์ฟผ๋ฆฌ๋œ ์—”ํ„ฐํ‹ฐ์˜ ์š”์†Œ ๋ชฉ๋ก์„ ๋ฐ˜๋ณตํ•˜๊ณ  ๋ฐ˜๋ณต๋œ ์š”์†Œ์— ๋Œ€ํ•œ ์ฐธ์กฐ๋ฅผ ๋‹ค์Œ ๋””๋ ‰ํ‹ฐ๋ธŒ์— ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค. ์ด ๊ฒฝ์šฐ ๋ชจ๋“  ์—”ํ„ฐํ‹ฐ์— ๋Œ€ํ•ด ๋ฒˆ์—ญํ•  ์†์„ฑ์˜ ์ „์ฒด ๋ชฉ๋ก์„ ๊ฐ€์ ธ์˜ค๊ณ , ๊ฐ๊ฐ์€ String ํƒ€์ž…์ด๋ฉฐ, ๊ฐœ๋ณ„ String ์š”์†Œ๋ฅผ ์•„๋ž˜๋กœ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค.

๋งˆ์ง€๋ง‰์œผ๋กœ @strTranslate ๋””๋ ‰ํ‹ฐ๋ธŒ๋Š” JSONObject ๋‚ด์— ํฌํ•จ๋œ String ํƒ€์ž…์˜ ์š”์†Œ๋ฅผ ๋ฐ›์•„ JSONObject ์ž์ฒด ๋‚ด์—์„œ ๋ฐ”๋กœ ๋ฒˆ์—ญํ•ฉ๋‹ˆ๋‹ค.

์ด ์†”๋ฃจ์…˜์ด ์–ผ๋งˆ๋‚˜ ์œ ์—ฐํ•œ์ง€ ์ฃผ๋ชฉํ•ด ์ฃผ์„ธ์š”. JSONObject ๋‚ด์˜ ๋ฌธ์ž์—ด ๊ฒฝ๋กœ๋งŒ ์ œ๊ณตํ•˜๋ฉด ๊ฐ’์— ์ ‘๊ทผํ•˜๊ณ , @strTranslate(๋˜๋Š” ๋‹ค๋ฅธ ๋””๋ ‰ํ‹ฐ๋ธŒ)๋กœ ์ˆ˜์ •ํ•˜๊ณ , ์‹ฌ์ง€์–ด DB์— ๊ฐ’์„ ๋‹ค์‹œ ์ €์žฅํ•˜๋Š” ๊ฒƒ๋„ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค(์ด๋ฅผ ๋‹ฌ์„ฑํ•˜๊ธฐ ์œ„ํ•œ ์ž‘์—…์ด ํ˜„์žฌ ์ง„ํ–‰ ์ค‘์ž…๋‹ˆ๋‹ค).

core/list์—์„œ๋Š” ์ด๋ฏธ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค. ๋ชฉ๋ก์˜ ๋ชจ๋“  ์š”์†Œ๋Š” ์ž์ฒด ๊ฒฝ๋กœ(items.0์ด ๋ฐฐ์—ด์˜ ์ฒซ ๋ฒˆ์งธ ์š”์†Œ ๋“ฑ)๋ฅผ ํ†ตํ•ด ๋„๋‹ฌํ•  ์ˆ˜ ์žˆ๊ณ , ๊ฐ๊ฐ์—์„œ String ๊ฐ’์— ์ ‘๊ทผํ•˜์—ฌ @strTranslate์— ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ @strTranslateList๋ฅผ ๋งŒ๋“ค ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.

๋งˆ์ฐฌ๊ฐ€์ง€๋กœ core/table์—์„œ๋„ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค. cells ์†์„ฑ์„ ํ†ตํ•ด ๋ฐ์ดํ„ฐ๋ฅผ ๋…ธ์ถœํ•˜๊ธฐ๋งŒ ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค. ์ด๋Š” 2์ฐจ์› ๋ฐฐ์—ด(ํ–‰์„ ์œ„ํ•œ ๋ฐฐ์—ด, ์—ด์„ ํฌํ•จํ•˜๋Š” ๋ฐฐ์—ด)์ด ๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋ฉด translatablePaths๋Š” ["cells.0.0", "cells.0.1", "cells.1.0", ...]๋กœ ๋ชจ๋“  ์š”์†Œ์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์„œ๋“œํŒŒํ‹ฐ ๋ธ”๋ก์—์„œ๋„ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฅผ ์œ„ํ•ด ๋ธ”๋ก ๋ฐ์ดํ„ฐ๊ฐ€ ์–ด๋–ป๊ฒŒ ์ €์žฅ๋˜๋Š”์ง€ ์ฃผ์˜๋ฅผ ๊ธฐ์šธ์ด๋ฉด ์†์„ฑ ๊ฒฝ๋กœ๋ฅผ ์ถ”๋ก ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋‹จ์ผ Block์€ PHP ์ฝ”๋“œ์— ๊ธฐ๋ฐ˜ํ•œ ์„ค์ •์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค

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

Gutenberg์—์„œ ๋ธ”๋ก์˜ ์†์„ฑ์„ ์ €์žฅํ•  ์ˆ˜ ์žˆ๋Š” ๋‘ ๊ฐ€์ง€ ์œ„์น˜๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค: ์†์„ฑ(attribute)์œผ๋กœ์„œ, ๋˜๋Š” ๋ Œ๋”๋ง๋œ ์ฝ˜ํ…์ธ  ๋‚ด๋ถ€์—.

์˜ˆ๋ฅผ ๋“ค์–ด core/image ๋ธ”๋ก์€ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ €์žฅ๋ฉ๋‹ˆ๋‹ค:

<!-- wp:image {"id":1670,"sizeSlug":"large","linkDestination":"none"} -->
<figure class="wp-block-image size-large">
<img src="https://newapi.getpop.org/wp/wp-content/uploads/2021/01/dynamic-include-first-query.webp" alt="" class="wp-image-1670"/>
</figure>
<!-- /wp:image -->

์ด ๊ฒฝ์šฐ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค:

  1. id, sizeSlug, linkDestination ์†์„ฑ์€ attribute๋กœ ์ €์žฅ๋ฉ๋‹ˆ๋‹ค
  2. src ์†์„ฑ์€ ๋ Œ๋”๋ง๋œ ์ฝ˜ํ…์ธ  ๋‚ด๋ถ€์— ์ €์žฅ๋ฉ๋‹ˆ๋‹ค

์ด์ œ API๋ฅผ ์ฟผ๋ฆฌํ•˜๋ฉด core/image ๋ธ”๋ก์˜ ์‘๋‹ต์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค:

{
  "data": {
    "blocks": [
      {
        "name": "core/image",
        "meta": {
          "id": 1670,
          "sizeSlug": "large",
          "linkDestination": "none",
          "src": "https://newapi.getpop.org/wp/wp-content/uploads/2021/01/dynamic-include-first-query.webp"
        }
      }
    ]
  }
}

API๋Š” Gutenberg์— ์ €์žฅ๋œ ๋ธ”๋ก์„ ํŒŒ์‹ฑํ•˜์—ฌ ์†์„ฑ์„ ๊ฒ€์ƒ‰ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค(๊ทธ๊ฒƒ์ด COPE ์ „๋žต์ž…๋‹ˆ๋‹ค). ์ด ๊ณผ์ •์€ ์–ด๋А ์ •๋„ ์ž๋™์œผ๋กœ ์ˆ˜ํ–‰๋  ์ˆ˜ ์žˆ๊ณ , ์ดํ›„ ํ›…์„ ํ†ตํ•œ ์ˆ˜๋™ ์ž…๋ ฅ์ด๋‚˜ ์‚ฌ์šฉ์ž ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

attribute๋กœ ์ง์ ‘ ๋งคํ•‘๋œ ์†์„ฑ์„ ์–ป๋Š” ๊ฒƒ์€ ๊ฐ„๋‹จํ•ฉ๋‹ˆ๋‹ค. GraphQL ์„œ๋ฒ„๋Š” ์ด๋ฏธ ๋ธ”๋ก์—์„œ ๋ชจ๋“  attribute๋ฅผ ๊ฒ€์ƒ‰ํ•˜์—ฌ ์†์„ฑ์œผ๋กœ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•˜๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋˜๋Š” ๋…ธ์ถœํ•  ๊ฒƒ์„ ๋ช…์‹œ์ ์œผ๋กœ ์ •์˜ํ•˜๋ ค๋ฉด ํ•„ํ„ฐ ํ›…์„ ํ†ตํ•ด ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

$attrs = apply_filters("blockPropsAsAttr:core/image", []);
 
add_filter("blockPropsAsAttr:core/image", function ($attrs) {
  return array_merge($attrs, ['id', 'sizeSlug', 'linkDestination']);
})

์ฝ˜ํ…์ธ ์— ์ €์žฅ๋œ ์†์„ฑ์€ ์ •๊ทœ์‹์œผ๋กœ ์ถ”์ถœํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

$propRegexes = apply_filters("blockPropsAsRegex:core/image", []);
 
add_filter("blockPropsAsRegex:core/image", function ($propRegexes) {
  $propRegexes['src'] = '/<img src="(.*?)"/';
  return $propRegexes;
})

๋งˆ์ง€๋ง‰์œผ๋กœ @strTranslate๊ฐ€ ์ž‘์šฉํ•  ๋ธ”๋ก์˜ ๋ฒˆ์—ญ ๊ฐ€๋Šฅํ•œ ์†์„ฑ์„ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค:

$propRegexes = apply_filters("translatableProperties:core/image", []);
 
add_filter("translatableProperties:core/image", function ($properties) {
  $properties[] = 'caption';
  return $properties;
})

์ด์ œ ์ด๋Ÿฌํ•œ ์†์„ฑ๋“ค์€ ์—ฌ์ „ํžˆ ๋ˆ„๊ตฐ๊ฐ€, ์•„๋งˆ๋„ ํ”Œ๋Ÿฌ๊ทธ์ธ ๊ฐœ๋ฐœ์ž๊ฐ€ ์ถฉ์กฑ์‹œ์ผœ์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์„œ๋ฒ„ ์ธก ๋ ˆ์ง€์ŠคํŠธ๋ฆฌ๋ฅผ ๊ฐ–์ถ”๋ฉด ์ด ๋ชฉํ‘œ ๋‹ฌ์„ฑ์— ๋„์›€์ด ๋ฉ๋‹ˆ๋‹ค.

ํ•˜์ง€๋งŒ WordPress ์ปค๋ฎค๋‹ˆํ‹ฐ๊ฐ€ ์ œ์•ˆ๋œ ์„œ๋ฒ„ ์ธก ๋ ˆ์ง€์ŠคํŠธ๋ฆฌ๋ฅผ ์ถ”๊ฐ€ํ•˜๊ณ  ์‹ถ์ง€ ์•Š๋‹ค๋ฉด ์–ด๋–ป๊ฒŒ ๋ ๊นŒ์š”? ์ด ์ „๋žต์€ ์‰ฝ๊ฒŒ ์ ์‘ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋งคํ•‘์„ PHP ์ฝ”๋“œ๋กœ ํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค(๋ฐฉ๊ธˆ ๋ณด์—ฌ๋“œ๋ฆฐ ๊ฒƒ์ฒ˜๋Ÿผ).

์–ด๋–ค ๋ธ”๋ก์ด ๋งคํ•‘๋˜์ง€ ์•Š์€ ๊ฒฝ์šฐ, ์‚ฌ์šฉ์ž๋„ Gutenberg์— ๋Œ€ํ•œ ์•ฝ๊ฐ„์˜ ์ง€์‹๋งŒ ์žˆ์œผ๋ฉด(GraphQL์ด๋‚˜ ์Šคํ‚ค๋งˆ์— ๋Œ€ํ•œ ์ง€์‹์€ ๋ถˆํ•„์š”) ์ง์ ‘ ๋งคํ•‘ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋˜ํ•œ ๋งคํ•‘๋˜์ง€ ์•Š์€ ๋ธ”๋ก(๋ฒˆ์—ญํ•  ์ˆ˜ ์—†๋Š” ๋ธ”๋ก)์ด ์žˆ์„ ๋•Œ GraphQL์ด ์‚ฌ์šฉ์ž์—๊ฒŒ ์•Œ๋ฆผ์„ ๋ณด๋‚ด๋„๋ก ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ์กฐ๊ฑด์ด ์ถฉ์กฑ๋˜๋ฉด @sendEmail ๋””๋ ‰ํ‹ฐ๋ธŒ๋ฅผ ์‹คํ–‰ํ•˜๋Š” @if ๋ฉ”ํƒ€ ๋””๋ ‰ํ‹ฐ๋ธŒ๋ฅผ ์ถ”๊ฐ€ํ•˜์—ฌ ์ด๋ฅผ ์‹คํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

{
  post(by: { id: 1 }) {
    blocks {
      name
      meta
        @advancePointersInArray(paths: "{{ translatablePaths }}")
          @underEachArrayItem
            @strTranslate(from: "en", to: "fr")
        @if(condition: "{{ isTranslatablePathsUnmapped }}")
          @sendEmail(
            to: "{{ root.adminEmail }}",
            subject: "Block with name {{ name }} has 'translatablePaths' unmapped"
          )
    }
  }
}

์ด ์†”๋ฃจ์…˜์€ ์œ ์—ฐํ•˜๊ณ  ๋‹จ์ˆœํ•˜๋ฉฐ, ๊ฐœ๋ฐœ์ž๊ฐ€ ์ƒˆ๋กœ์šด ๊ธฐ์ˆ ์„ ๋ฐฐ์šฐ๊ฑฐ๋‚˜ Gutenberg ์ž‘๋™ ๋ฐฉ์‹์„ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š์•„๋„ GraphQL์ด WordPress๋ฅผ ์œ„ํ•ด ๋ด‰์‚ฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ฒฐ๋ก 

GraphQL๊ณผ Gutenberg์˜ ํ†ตํ•ฉ์ด ์–ด๋–ป๊ฒŒ ๋ ์ง€(WordPress ์ฝ”์–ด์— ์ž ์žฌ์ ์œผ๋กœ ํฌํ•จ๋˜๋Š” ๊ด€์ ์—์„œ) ์ƒ๊ฐํ•  ๋•Œ, GraphQL์ด Gutenberg์˜ ๋ชจ๋“  ๋ฏธ๋ž˜ ์š”๊ตฌ ์‚ฌํ•ญ์„ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ํ™•์ธํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋‹ค์Œ์— ๋Œ€ํ•œ ์™„์ „ํ•œ ์ง€์›์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค:

  • ๋‹ค๊ตญ์–ด ๋ธ”๋ก
  • Full Site Editing
  • ํ˜‘์—… ํŽธ์ง‘
  • ๋ผ์ด๋ธŒ ์‚ฌ์ดํŠธ์—์„œ ์„œ๋“œํŒŒํ‹ฐ ์„œ๋น„์Šค์™€์˜ ์ƒํ˜ธ์ž‘์šฉ

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

์ด๋ฅผ ๊ฐ์•ˆํ•˜๋ฉด ์ œ๊ฐ€ ์—ฌ๊ธฐ์„œ ์ œ์•ˆํ•˜๋Š” ๋„ค ๋ฒˆ์งธ ์ ‘๊ทผ ๋ฐฉ์‹์ด ์‹ค์ œ๋กœ ๋งค์šฐ ์ž˜ ์ž‘๋™ํ•  ์ˆ˜ ์žˆ๋‹ค๊ณ  ๋ฏฟ์Šต๋‹ˆ๋‹ค.


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

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