๐ธ GraphQL์ WordPress๋ฅผ ์ด๋ป๊ฒ, ์ด๋์ ๊ฐ์ ํ ์ ์๋๊ฐ โ REST API๋ฅผ ๋ณด์ํ๋ฉฐ
์ ๋ฐ์ดํธ 2024๋ 1์ 5์ผ: Gato GraphQL vs WP REST API ๋น๊ต๋ฅผ ํ์ธํด ๋ณด์ธ์.
์ง๋ ์ฃผ๋ง์ ๋ธ๋ก๊ทธ ๊ฒ์๋ฌผ ๐ฆธ๐ฟโโ๏ธ Gato GraphQL์ด ์ด์ PHP 8.0์์ 7.1๋ก ํธ๋์คํ์ผ๋ฉ๋๋ค๋ฅผ ๊ฒ์ํ์ต๋๋ค.
Reddit์ /r/php์์ ๊ทธ ๊ฒ์๋ฌผ์ ๊ณต์ ํ ํ, ์ปค๋ฎค๋ํฐ์์๋ WordPress์์ GraphQL์ ์ฌ์ฉํ๋ ๊ฒ์ ๊ฐ์น, WP REST API์์ ์ฐจ์ด์ , ๊ทธ๋ฆฌ๊ณ WordPress์ ๋ ๋ค๋ฅธ API๋ฅผ ๋์ ํ๋ ๊ฒ์ ์ ๋น์ฑ์ ๋ํด ํ๋ฐํ ํ ๋ก ์ด ์์๋์์ต๋๋ค.
๋๋ถ๋ถ์ ๋๊ธ์ ํต์ฌ์ ์ฐ๋ฅด๊ณ ์๋ค๊ณ ์๊ฐํ์ง๋ง, ์ผ๋ถ๋ ์ค์ํ ์ ๋ณด๋ฅผ ๋์น๊ณ ์์ต๋๋ค. GraphQL์ ๋จ์ํ ์ธํฐํ์ด์ค๊ฐ ์๋๋ผ ๊ตฌํ์ด๊ธฐ๋ ํฉ๋๋ค. ์ฆ, ์๋ก ๋ค๋ฅธ ์ ๊ณต์ ์ฒด์ ์๋ก ๋ค๋ฅธ GraphQL ์๋ฒ๋ ๊ฐ๊ธฐ ๋ค๋ฅธ ํน์ฑ์ ์ฐ์ ์ํ๋๋ก ์ค๊ณ๋์์ ์ ์์ต๋๋ค. ๋ฐ๋ผ์ GraphQL์ด ์ ๊ณตํ๋ ๊ฒ์ด๋ GraphQL ์์ง์ด ์๋ํ๋ ๋ฐฉ์์ ๋ํด ํญ์ ํต์ผ๋ ๊ธฐ๋๋ฅผ ๊ฐ๊ฑฐ๋ ์์ ํ ์ดํดํ๊ธฐ๋ ์ด๋ ต์ต๋๋ค.
์๋ฅผ ๋ค์ด, WordPress์ Laravel์์์ GraphQL ๊ฒฝํ์ ๋ค๋ฅด๋ฉฐ, WPGraphQL๊ณผ Gato GraphQL์ด๋ผ๋ ์๋ก ๋ค๋ฅธ ์๋ฒ๊ฐ ์ ๊ณตํ๋ ๊ฒฝํ๋ ๋ค๋ฆ ๋๋ค.
์ด ๊ธ์ Reddit ๊ฒ์๋ฌผ์ ์ฌ๋ฌ ๋๊ธ์ ๋ค๋ฃจ๋ ์ ์์ ์ ๊ฒฌํด์ ๋๋ค.
GraphQL vs WP REST API
[์ ๋ง ๋์ ์๊ฐ์ด๋ค] ์ด๋ฏธ ์์ฒด REST API๋ฅผ ์ฌ์ฉํ๋ WordPress ์์ GraphQL API๋ฅผ ์ถ๊ฐํ๋ค๋. ๊ทธ๋ฅ REST API๋ฅผ ์ฌ์ฉํ๋ฉด ๋๋ค. [์ถ์ฒ]
REST API์ GraphQL ๋ชจ๋ ๋์ผํ ๋ชฉ์ ์ ์ํํฉ๋๋ค. ์ฆ, ์ ํ๋ฆฌ์ผ์ด์ ์ ํ์ํ ๋ฐ์ดํฐ๋ฅผ ์ ๊ณตํ๋ ๊ฒ์ ๋๋ค. ํ์ง๋ง ์ด๋ฅผ ๋ฌ์ฑํ๋ ๋ฐฉ์์ ๋ค๋ฆ ๋๋ค. REST๋ ํน์ ๋ฐ์ดํฐ ์งํฉ์ ์ ๊ณตํ๋ ๋ฏธ๋ฆฌ ์ ์๋ ์๋ํฌ์ธํธ๋ฅผ ๊ฐ๋ ๋ฐ๋ฉด, GraphQL์ ํ์ํ ๋ฐ์ดํฐ๋ง ์ ํํ๊ฒ ์ ๊ณตํ ์ ์์ต๋๋ค.
์ด๋ฌํ ๋์ ์ฐจ์ด๋ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ฑ๋ฅ์ ์ง์ ์ ์ธ ์ํฅ์ ๋ฏธ์น ์ ์์ต๋๋ค. REST์์ ๊ฒ์๋ฌผ ๋ชฉ๋ก๊ณผ ๊ฐ ๊ฒ์๋ฌผ ์์ฑ์์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์์ผ ํ๋ ๊ฒฝ์ฐ, ์ถ๊ฐ ์์ฒญ์ ๋ณด๋ด์ผ ํฉ๋๋ค. ๋ชจ๋ ์์ฑ์ ๋ฐ์ดํฐ์ ๋ํด 1๊ฐ์ ์ถ๊ฐ ์์ฒญ, ๋๋ ์์ฑ์๋น 1๊ฐ์ ์ถ๊ฐ ์์ฒญ์ด ํ์ํ ์ ์์ต๋๋ค. ๊ทธ๋์ ์น์ฌ์ดํธ ๋ฐฉ๋ฌธ์๋ ํ์ด์ง๊ฐ ๋ ๋๋ง๋๊ธฐ๋ฅผ ๊ธฐ๋ค๋ฆฌ๊ณ ์์ ๊ฒ์ ๋๋ค.
GraphQL์ ์ด ์ํฉ์ ๊ฐ์ ํฉ๋๋ค. ๊ฒ์๋ฌผ๊ณผ ์์ฑ์ ๋ฐ์ดํฐ ์ ์ฒด๋ฅผ ๋จ์ผ ์์ฒญ์ผ๋ก ์ง์ ๊ฐ์ ธ์ฌ ์ ์์ด ์นํ์ด์ง ๋ ๋๋ง์ด ๋ ๋นจ๋ผ์ง๋๋ค.
{
posts {
id
title
excerpt
date
url
author {
id
name
url
}
}
}WordPress์ REST API๊ฐ ์ด๋ฏธ ์๋ค๊ณ ํด์, ๊ทธ๊ฒ์ด ๋ชจ๋ ์์ ์ ํญ์ ๊ฐ์ฅ ์ ํฉํ ๋๊ตฌ๋ผ๋ ์๋ฏธ๋ ์๋๋๋ค. ๋ฌผ๋ก ํญ์ ์ฌ์ฉํ ์๋ ์์ง๋ง, GraphQL์๋ ์ ๊ทผํ ์ ์๋ค๋ฉด REST๋ณด๋ค ์ ๋ฆฌํ ์ํฉ์์ ์ด API๋ฅผ ์ ํํด ์ฌ์ฉํ ์ ์์ผ๋ฉฐ, ๋ ๋์ ๊ฒฐ๊ณผ๋ฅผ ์ป์ ์ ์์ต๋๋ค.
GraphQL์ ์ด๋ ค์ด ์ด๊ธฐ ์ค์ + ๋ฆฌ์กธ๋ฒ ์์ฑ
GraphQL์ ์ด๊ธฐ ์ค์ ์ด REST์ ๋นํด ๊ธฐํ๊ธ์์ ์ผ๋ก ๋๋ค๋ ์ฃผ์ฅ์ ๋ถ๋ช ํ ์์ต๋๋ค. ์ฐ๊ด ๊ด๊ณ๋ฅผ ์ค์ ํด์ผ ํ๋ค๋ ์ ์ ๋ง์ต๋๋ค. [์ถ์ฒ]
๊ทธ๋ฆฌ๊ณ ...
๋น์ ๊ณผ ์น์ ๊ฑฐ์ ๋ชจ๋ ์ฌ๋์ด ๋น ๋จ๋ฆฌ๊ณ ์๋ ๊ฒ์, ์ด API ํ์์ด ์๋ํ๋ ค๋ฉด ํ์(๋ฆฌ์กธ๋ฒ + ํ์ )๋ฅผ ์์ฑํด์ผ ํ๋ฉฐ, ์ด๋ก ์ธํด REST์๋ ์๋ ์ผ๋ จ์ ๋ฌธ์ ๊ฐ ๋ฐ์ํ๋ค๋ ์ ์ ๋๋ค. [์ถ์ฒ]
์ด๋ฌํ ๋๊ธ์ ์์ ํ ์ ํํ์ง ์์ต๋๋ค. WPGraphQL๊ณผ Gato GraphQL์ด ์ด๋ฏธ WordPress ๋ฐ์ดํฐ ๋ชจ๋ธ์ GraphQL ์คํค๋ง์ ๋งคํํด ๋์๊ธฐ ๋๋ฌธ์ ๋๋ค(WPGraphQL์ ์์ ํ, ์ ํ๋ฌ๊ทธ์ธ์ ๋๋ถ๋ถ).
๋ฐ๋ผ์ ์ด๋ฌํ ํ๋ฌ๊ทธ์ธ ์ค ํ๋๋ฅผ ์ค์นํ๋ฉด, ๋ฆฌ์กธ๋ฒ๋ฅผ ๋ง๋ค๊ฑฐ๋ ์ํฐํฐ ๊ฐ ์ฐ๊ด ๊ด๊ณ๋ฅผ ์ค์ ํ ํ์ ์์ด ์ฆ์ ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ฐ์ดํฐ ๊ฐ์ ธ์ค๊ธฐ๋ฅผ ์์ํ ์ ์์ต๋๋ค.
๋ฌผ๋ก ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ณ ์ ์ํฐํฐ(CPT ๋ฑ)์์ ์ปค์คํ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ค๋ ค๋ฉด, ๋ฆฌ์กธ๋ฒ๋ฅผ ํตํด ๋งคํํด์ผ ํ๋ฉฐ ์ง์ ํด์ผ ํฉ๋๋ค. ํ์ง๋ง ์ด๋ REST์ ๋ค๋ฅด์ง ์์ต๋๋ค. CPT์์ ์ปค์คํ ๋ฐ์ดํฐ๊ฐ ํ์ํ๋ค๋ฉด, ํด๋น ์ปค์คํ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ค๊ธฐ ์ํ REST ์๋ํฌ์ธํธ๋ฅผ ๋ง๋ค์ด์ผ ํฉ๋๋ค. ์ปค์คํ ์๋ํฌ์ธํธ๋ ๋ฆฌ์กธ๋ฒ์ ์ผ์ข ์ ๋๋ค.
๋ฐ๋ผ์ ๋ฆฌ์กธ๋ฒ ํ์์ฑ ์ธก๋ฉด์์, REST์ GraphQL API๋ ๊ฑฐ์ ๋์ผํฉ๋๋ค.
์น์ฌ์ดํธ์ ๋ฌธ์๋ฅผ ๋๋ฌ๋ณด๋ฉด, GraphQL์ด ์ค์ ์ ๋ ๋ง์ ๋ ธ๋ ฅ์ด ํ์ํ๋ค๋ ์ธ์์ ์ค๋๋ค. ์ด ์ถ์ ์๋ ์ด๋ ์ ๋ ๊ทผ๊ฑฐ๊ฐ ์์ต๋๋ค.
๋ช ๊ฐ์ง ์ด์ ๊ฐ ์๋ค๊ณ ์๊ฐํฉ๋๋ค. ์ฐ์ GraphQL์๋ (์ต์) ๋ ๊ฐ์ง ์ธก๋ฉด์ด ์์ต๋๋ค.
- ๊ทธ๊ฒ์ด ๋ฌด์์ธ์ง, ์ด๋ป๊ฒ ์๋ํ๋์ง์ ๋ํ ๊ฐ๋
- ์ค์ ๊ตฌํ์ ์ ๊ณตํ๋ ์๋ฒ
graphql.org์ ๊ฐ์ GraphQL ๊ณต์ ์ฌ์ดํธ์ ๋ฌธ์๋ฅผ ๋ณด๋ฉด, GraphQL ๋ค์ ์๋ ๊ฐ๋ ์ ์ง์คํ๋ฉฐ ๋ฆฌ์กธ๋ฒ๊ฐ ๋ฌด์์ธ์ง, ์ ํ์ํ์ง์ ๋ํด ์์ธํ ์ค๋ช ํฉ๋๋ค.
์ด๋ Laravel๊ณผ Lighthouse๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ฒ๋ผ ์ฒ์๋ถํฐ ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ตฌ์ถํ ๋ ์ ์ฉํฉ๋๋ค. ๊ทธ ๊ฒฝ์ฐ์๋ ์ง์ ๋ฆฌ์กธ๋ฒ๋ฅผ ์ฝ๋ฉํด์ผ ํฉ๋๋ค(๋ฌผ๋ก REST ์๋ํฌ์ธํธ๋ ์ง์ ๋ง๋ค์ด์ผ ํ์ง๋ง์).
ํ์ง๋ง WordPress๋ ์ด๋ฏธ ์์ฑ๋ ์ ํ๋ฆฌ์ผ์ด์ ์ด๊ณ , WPGraphQL๊ณผ Gato GraphQL์ ๊ทธ ์๋ฃจ์ ์ ๋๋ค. ์ด ๋ ํ๋ฌ๊ทธ์ธ์ ์ด๋ฏธ ๋ฆฌ์กธ๋ฒ๋ฅผ ๋ง๋ค์ด ๋์์ผ๋ฏ๋ก ์ ๊ฒฝ ์ธ ํ์๊ฐ ์์ต๋๋ค(WP REST API๋ ์ด๊ธฐ ์๋ํฌ์ธํธ ์ธํธ๋ฅผ ์ ๊ณตํ์ฌ ์ ๊ฒฝ ์ธ ํ์๊ฐ ์๋ ๊ฒ๊ณผ ๋ง์ฐฌ๊ฐ์ง์ ๋๋ค).
๋ํ GraphQL์ ๊ฐ๋ฐ์ ์ค์ฌ์ด๋ฉฐ, ๊ทธ ๋ฌธ์๋ ๊ฐ๋ฐ์์๊ฒ ์ง์ ๋ง์ ๊ฑฐ๋ ๊ฒ์ฒ๋ผ ๋ณด์ ๋๋ค. ๊ฐ๋ฐ์๊ฐ ์๋ฒ ์ธก์์ ๋ฆฌ์กธ๋ฒ๋ฅผ ๋ง๋ค๊ณ , ๊ฐ๋ฐ์๊ฐ ํด๋ผ์ด์ธํธ ์ธก์์ ์ปค์คํ ์ฟผ๋ฆฌ๋ก ํด๋น ๋ฆฌ์กธ๋ฒ๋ฅผ ์ฌ์ฉํฉ๋๋ค. ๋ฆฌ์กธ๋ฒ ๊ตฌ์ถ์ ๊ฐ๋ฐ์์ ์ผ์ด๊ธฐ ๋๋ฌธ์ ์์ฐ์ค๋ฝ๊ฒ ์์ฃผ ๋ฑ์ฅํฉ๋๋ค.
REST์ ๊ฒฝ์ฐ, ํ์ํ ๋ฐ์ดํฐ๋ฅผ ์ ๊ณตํ๋ ์๋ํฌ์ธํธ๋ ์ด๋ฏธ ์กด์ฌํด์ผ ํ๋ค๋ ๊ธฐ๋(WP REST API๊ฐ ์ ๊ณตํ๋ ๊ฒ)๊ฐ ์๋ค๊ณ ์๊ฐํฉ๋๋ค. ์กด์ฌํ์ง ์์ ๋๋ง ์ปค์คํ ์๋ํฌ์ธํธ ์ค์ ์ ๊ณ ๋ คํด์ผ ํฉ๋๋ค. ๋ฐ๋ผ์ REST์์๋ ๋ฆฌ์กธ๋ฒ ์์ฑ์ ๋ํ ์ธ๊ธ์ด ์ ์ต๋๋ค.
์ฆ, REST์ GraphQL ๋ชจ๋ ํ์ํ ๋ฐ์ดํฐ๋ฅผ ์ ๊ณตํฉ๋๋ค. ํ์ง๋ง REST๋ ์๋ํฌ์ธํธ๊ฐ ์ด๋ฏธ ์กด์ฌํด์ผ ํ๋ค๋ ์ ์ ์ธ ์ ๊ทผ ๋ฐฉ์์ ๊ถ์ฅํ๋ฉฐ, ์กด์ฌํ์ง ์์ ๋๋ง ์ ๊ฒฝ ์๋๋ค. ๋ฐ๋ฉด GraphQL์ ๋ชจ๋ ์ฟผ๋ฆฌ๋ฅผ ์ปค์คํ ์ ์ํ๋ ๋์ ์ธ ์ ๊ทผ ๋ฐฉ์์ ๊ถ์ฅํ๋ฉฐ, ์๋ฒฝํ ๋ฆฌ์กธ๋ฒ๋ฅผ ์ฝ๋ฉํ ์ ์์ต๋๋ค.
๊ฒฐ๊ตญ REST์ GraphQL ์ฌ์ด์๋ ๊ทผ๋ณธ์ ์ธ ์ฐจ์ด๊ฐ ์์ผ๋ฉฐ, ์๊ฑด์ ์ด๋ป๊ฒ ์ถฉ์กฑํด์ผ ํ๋์ง์ ๋ํ ํด์์ ์ฐจ์ด๋ง ์์ ๋ฟ์ ๋๋ค.
GraphQL์ ์ทจ์ฝ์ + ๋ณด์ ๊ณ ๋ ค ์ฌํญ
์์ ํ ์ธํฐํ๋ฆฌํฐ๋ฅผ ์์ฑํ๋ ๊ฒ์ ์ ๋ง ์ด๋ ต๊ธฐ ๋๋ฌธ์ ์ธ์ ๊ฐ GraphQL์์ ํฐ ์ทจ์ฝ์ ์ด ๋์ฌ ๊ฒ์ ๋๋ค. [์ถ์ฒ]
๊ทธ๋ฆฌ๊ณ ...
WordPress๋ ์ด๋ฏธ ๊ฑฐ๋ํด์ ํญ์ ํฐ ๊ณต๊ฒฉ ๋์์ด ๋ฉ๋๋ค. ํ๋ฌ๊ทธ์ธ์ ์ถ๊ฐํ๋ฉด ์ํ์ด ํฌ๊ฒ ์ฆ๊ฐํฉ๋๋ค. ๊ทธ๋ฆฌ๊ณ WordPress์ ๋ชจ๋ ๊ฒ์ ๋ฌธ์ ๊ทธ๋๋ก ๋ ธ์ถํ๋ ค๋ ํ๋ฌ๊ทธ์ธ(๋ฉ๋ด์ ๋ฉ๋ด ์์ดํ ์ ๊ณต๊ฐํ๊ฑฐ๋ ๋ชจ๋ ์ฌ์ฉ์๋ฅผ ๊ณต๊ฐํ๋ ๋ณด์ ๋ชจ๋ธ์ ์ฐํํ๋ ์ํ ์ฝ๋ ํฌํจ)์ ์ ์๊ฒ๋ ์ ๋ ์ฉ๋ฉํ ์ ์์ต๋๋ค. ํ ๋ง ๊ธฐ๋ฐ์ด ์๋ ์ถ๋ ฅ์ ์ ๋์ ์ผ๋ก ํ์ํ ๊ฒ ์ด์์ผ๋ก ์ต๋ํ ์ ํ๋์ด์ผ ํฉ๋๋ค(์ ๊ฐ ์์ฒญํ์ง ์๋ ํ ์กด์ฌํ์ง ์์์ผ ํฉ๋๋ค). ์ด๊ฒ์ด ์ฝ์ด์ ํฌํจ๋์ง ์๊ธฐ๋ฅผ ๋ฐ๋๋๋ค. [์ถ์ฒ]
GraphQL์ ๋ถ๋ช ํ ์ถ๊ฐ์ ์ธ ๋ณด์ ์ํ์ ์ด๋ํ๋ฉฐ ์ด๋ฅผ ํด๊ฒฐํด์ผ ํฉ๋๋ค. ์ด ์ฐ๋ ค์ ์์ ํ ๋์ํฉ๋๋ค.
ํ์ง๋ง ๊ทธ๊ฒ์ด GraphQL์ WP ์ฝ์ด์ ํฌํจ์ํฌ ๊ฐ๋ฅ์ฑ์ ๋ง๋ ๊ฒฐ์ ์ ์ธ ๋ฌธ์ ๋ผ๊ณ ๋ ์๊ฐํ์ง ์์ต๋๋ค. ๋ ๋์๊ฐ, ์ด๋ฅผ ํด๊ฒฐํ๊ธฐ๊ฐ ์ ๋ง ์ด๋ ต๋ค๊ณ ๋ ์๊ฐํ์ง ์์ต๋๋ค.
ํ์ํ ๊ฒ์ GraphQL ์๋ฒ๊ฐ WordPress์ ๊ธฐ์กด ๋ณด์ ๋ฉ์ปค๋์ฆ์ ํ์ฉํ๊ณ , ๊ฐ๋ฐ์๊ฐ ๊ทธ ๋ฉ์ปค๋์ฆ์ ์ฌ์ฉํ์ฌ ํน์ ํ๋์ ์ ์ ํ ์ฌ์ฉ์๋ง ์ ๊ทผํ ์ ์๋๋ก ํ๋ ๊ฒ์ ๋๋ค.
- ์ฌ์ฉ์๊ฐ ๋ก๊ทธ์ธ๋์ด ์๋๊ฐ?
- ์ฌ์ฉ์๊ฐ ๊ด๋ฆฌ์์ธ๊ฐ?
- ์ฌ์ฉ์๊ฐ ์ด๋ค ์ญํ ์ด๋ ๊ถํ์ ๊ฐ์ง๊ณ ์๋๊ฐ?
- ์ฌ์ฉ์๊ฐ ํด๋น ๊ฒ์๋ฌผ์ ์์ฑ์์ธ๊ฐ?
์ด ์๊ฑด์ ์ถฉ์กฑํ๊ธฐ ์ํด, Gato GraphQL์ Access Control Lists(์ ๊ทผ ์ ์ด ๋ชฉ๋ก)์ ์ ๊ณตํ์ฌ ๊ฐ ํ๋์ ๋๋ ํฐ๋ธ์ ์ ๊ทผํ ์ ์๋ ์ฌ๋์ ์ค์ ์ผ๋ก ์ ์ํ ์ ์์ต๋๋ค.
๊ทธ๋ฐ๋ฐ ACL๋ง์ผ๋ก๋ ์ถฉ๋ถํ์ง ์์ ๊ฒฝ์ฐ๋ ์์ผ๋ฉฐ, GraphQL ์๋ฒ๊ฐ ์ถ๊ฐ์ ์ธ ๋ณด์ ์กฐ์น๋ฅผ ์ ๊ณตํด์ผ ํฉ๋๋ค. ํ์ฌ Gato GraphQL์ ๋ค๊ฐ์ค๋ v0.8์ ์ํด ์์ ์ค์ธ ๋ด์ฉ์ ์ค๋ช ํ๊ฒ ์ต๋๋ค.
ํ๋ posts(๊ฒ์๋ฌผ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ค๋ ๊ฒ)๋ ์ธ์ฆ์ด ํ์ ์์ผ๋ฉฐ, ๋ก๊ทธ์ธ ์ฌ๋ถ์ ๊ด๊ณ์์ด ๋ชจ๋ ์ฌ์ฉ์๊ฐ ์ ๊ทผํ ์ ์์ต๋๋ค. ๋ฐ๋ผ์ ๋ณด์์์ ์ด์ ๋ก ๊ณต๊ฐ๋ ๊ฒ์๋ฌผ๋ง ๊ฐ์ ธ์ต๋๋ค.
ํ์ง๋ง ๋ค์๊ณผ ๊ฐ์ ์ํฉ์์๋ ์ด์/๋ณด๋ฅ ์ค/ํด์งํต ๊ฒ์๋ฌผ๋ ๊ฐ์ ธ์์ผ ํ ๋๊ฐ ์์ต๋๋ค.
- ๊ด๋ฆฌ์๊ฐ ์คํํ๋ ์ ์ ์น์ฌ์ดํธ ๊ตฌ์ถ(์ฌ์ดํธ์ ๋ชจ๋ ๋ฐ์ดํฐ์ ๋ํ ์ ๊ทผ ํฌํจ)
- ๊ฒ์๋ฌผ ์์ฑ์๊ฐ ๊ณ์ ํธ์งํ ์ ์๋๋ก ๋ชจ๋ ์ด์ ๊ฒ์๋ฌผ์ ๋์ดํ๋ ๊ฒฝ์ฐ
๊ทธ๋์ ๋ค์๊ณผ ๊ฐ์ ์ฒด๊ณ๋ฅผ ๊ตฌ์ํ์ต๋๋ค. ๊ฒ์๋ฌผ์ ๊ฐ์ ธ์ค๊ธฐ ์ํด 3๊ฐ์ ํ๋๊ฐ ์ ๊ณต๋ฉ๋๋ค.
posts: ๋๊ตฌ๋ ์ ๊ทผ ๊ฐ๋ฅํ๋ฉฐ, ๊ณต๊ฐ๋ ๊ฒ์๋ฌผ๋ง ๊ฐ์ ธ์ฌ ์ ์์myPosts: ๋๊ตฌ๋ ์ ๊ทผ ๊ฐ๋ฅํ๋ฉฐ, ๋ก๊ทธ์ธํ ์ฌ์ฉ์์ ๊ฒ์๋ฌผ๋ง ๋ชจ๋ ์ํ(๊ณต๊ฐ๋จ/์ด์/๋ณด๋ฅ ์ค/ํด์งํต)๋ก ๊ฐ์ ธ์ดpostsForAdmin: ๊ด๋ฆฌ์๋ง ์ ๊ทผ ๊ฐ๋ฅํ๋ฉฐ, ๋ชจ๋ ์ํ์ ๋ชจ๋ ๊ฒ์๋ฌผ์ ๊ฐ์ ธ์ด
๊ทธ๋ฆฌ๊ณ postsForAdmin์ ๊ธฐ๋ณธ์ ์ผ๋ก ๋นํ์ฑํ๋์ด ์์ด GraphQL ์คํค๋ง์ ํ์๋์ง ์์ต๋๋ค. ๊ด๋ฆฌ์๊ฐ ๋ช
์์ ์ผ๋ก ํ์ฑํํ ๊ฒฝ์ฐ์๋ง ํ์๋ฉ๋๋ค(์๋ง๋ ์ ์ ์ฌ์ดํธ ๊ตฌ์ถ์๋ง ํ์ฑํ๋ ๊ฒ์
๋๋ค).
๋ ๋ค๋ฅธ ์ํฉ์ ํน์ ํ๋๊ฐ ๊ณต๊ฐ ๋ฐ์ดํฐ์ ๋น๊ณต๊ฐ ๋ฐ์ดํฐ๋ฅผ ๋ชจ๋ ๊ฐ์ ธ์ฌ ์ ์๋ ๊ฒฝ์ฐ์
๋๋ค. ์๋ฅผ ๋ค์ด, ํ๋ option์ ํ
์ด๋ธ wp_options์์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ต๋๋ค. ์ผ๋ถ ํญ๋ชฉ์ ๊ณต๊ฐ(blogname ๋ฑ)์ด์ง๋ง, ๊ทธ๋ ์ง ์์ ๊ฒ(admin_email ๋ฑ)๋ ์์ต๋๋ค.
๋น์ทํ ์ํฉ์ผ๋ก๋ ํ๋ Post.metaValue, User.metaValue ๋ฑ์ ํตํด ๋ฉํ ๊ฐ์ ๊ฐ์ ธ์ค๋ ๊ฒฝ์ฐ๊ฐ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด, ์ฌ์ฉ์ ๋ฉํ์๋ ๋ถ๋ช
ํ ๋น๊ณต๊ฐ์ธ ํญ๋ชฉ wp_capabilities๊ฐ ํฌํจ๋์ด ์์ง๋ง, description์ ๊ณต๊ฐ๋์ด ์์ต๋๋ค. ๊ทธ๋ฆฌ๊ณ last_name์ ์ ํ๋ฆฌ์ผ์ด์
์ ๋ฐ๋ผ ๊ณต๊ฐ ๋๋ ๋น๊ณต๊ฐ์ผ ์ ์์ต๋๋ค.
์ด ๋ฐ์ดํฐ์ ๋ํ ์ ๊ทผ์ ์์ ํ๊ฒ ํ๊ธฐ ์ํด, ํ๋ฌ๊ทธ์ธ์ ์ค์ ํ์ด์ง์ ํ์ฉ/๊ฑฐ๋ถ ๋ชฉ๋ก์ ํตํด ์ฟผ๋ฆฌํ ์ ์๋ ํญ๋ชฉ์ ์ง์ ํ ์ ์๊ฒ ๋ฉ๋๋ค. ์ ์ฒด ํญ๋ชฉ ๋๋ ์ ๊ท์์ ๋ชจ๋ ํ์ฉํฉ๋๋ค.

ํ์ฉ๋ ์ต์
์ฟผ๋ฆฌ๋ ์๋ํ๊ณ , ๊ฑฐ๋ถ๋ ์ต์
์ null์ ๋ฐํํฉ๋๋ค.
{
# This option is allowed
siteName: optionValue(name: "blogname")
# This optionValue is not allowed
adminEmail: optionValue(name: "admin_email")
}GraphQL ์๋ฒ์ ์ ์ ํ ๋ณด์ ์กฐ์น์ ๊ฐ๋ฐ์์ ์์์ด ์๋ค๋ฉด, ์์ ํ GraphQL API๋ฅผ ๊ตฌ์ถํ๋ ๊ฒ์ ์ด๋ ต์ง ์์ ๊ฒ์ ๋๋ค.
GraphQL๋ก ์ธํ DB ๋ค์ด
GraphQL์ ๊น์ ๊ด๊ณํ ์ฟผ๋ฆฌ๋ฅผ ํํํ ์ ์๋ ํ๋ถํ ๊ตฌ๋ฌธ์ ๊ฐ์ง๊ณ ์์ต๋๋ค. WordPress์ ๊ฐ์ ์ํ๊ณ์์ ๋ฐ์ดํฐ ๋ชจ๋ธ์ ํ์ฅ์ฑ์ด ์ํฐํฐ-์์ฑ-๊ฐ ํจํด์ ๊ธฐ๋ฐํ๊ธฐ ๋๋ฌธ์, GraphQL ์ฟผ๋ฆฌ๊ฐ ๊น๊ณ ๋ณต์กํ๊ฑฐ๋ ์ฌ๊ท์ ์ธ ๊ฒฝ์ฐ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ๋ฏฟ์ ์ ์๋ ๋ถํ๊ฐ ๊ฑธ๋ ค ์ฌ์ดํธ๊ฐ ์๋ตํ์ง ์์ ์ ์์ต๋๋ค. WordPress๋ ์ด๋ฏธ MySQL/MariaDB ์ธ์คํด์ค๋ฅผ ํ๊ณ๊น์ง ๋ชฐ์๋ถ์ด๋ ๊ฒ์ผ๋ก ์ ๋ช ํฉ๋๋ค. ์ฟผ๋ฆฌ๊ฐ ์ ์ ํ๊ฒ ์์ฑ๋๊ณ ์ธ์ฆ๋๋ฉฐ ์๋ ์ ํ๋์ง ์๋๋ค๋ฉด, GraphQL์ ์ถ๊ฐํ๋ฉด ํจ์ฌ ๋ ๋๋น ์ง ์ ์์ต๋๋ค. [์ถ์ฒ]
DB ๋ค์ด์ GraphQL ์๋ฒ์๊ฒ ์ฌ๊ฐํ ์ฐ๋ ค ์ฌํญ์ ๋๋ค. Gato GraphQL์ด ์ด ์๋๋ฆฌ์ค๋ฅผ ํผํ๋ ค๋ ๋ฐฉ๋ฒ์ ์ค๋ช ํ๊ฒ ์ต๋๋ค.
Gato GraphQL์ ์ํคํ ์ฒ ์ค๊ณ์ ์ํด N+1 ๋ฌธ์ ๊ฐ ๋ฐ์ํ์ง ์๋๋ก ํฉ๋๋ค. ์์ง์ด ๋ฐ์ดํฐ๋ฒ ์ด์ค์์ ์ํฐํฐ๋ฅผ ๋ก๋ํ๋ ์ฑ ์์ ์ง๋ฉฐ, ๊ฐ๋ฐ์๊ฐ ์๋๋๋ค.
๋ฆฌ์กธ๋ฒ์์ ์ฐ๊ฒฐ์ ํด๊ฒฐํ ๋, ๋ฐํ๋๋ ๊ฐ์ ๊ฐ์ฒด ์์ฒด๊ฐ ์๋ ๊ฐ์ฒด์ ID(๋๋ ID ๋ชฉ๋ก)์ ๋๋ค. ์๋ฅผ ๋ค์ด, ์ปค์คํ ๊ฒ์๋ฌผ์ ์์ฑ์๋ฅผ ๊ฐ์ ธ์ค๋ ๊ฒ์ ๋ค์๊ณผ ๊ฐ์ด ์ํ๋ฉ๋๋ค.
class CustomPostFieldResolver extends AbstractDBDataFieldResolver
{
private CustomPostUserTypeAPIInterface $customPostUserTypeAPI;
public function getClassesToAttachTo(): array
{
return [
CustomPostFieldInterfaceResolver::class,
];
}
public function getSchemaFieldType(string $fieldName): ?string
{
return match($fieldName) {
'author' => SchemaDefinition::TYPE_ID,
default => null,
};
}
public function resolveValue(
TypeResolverInterface $typeResolver,
object $customPost,
string $fieldName,
array $fieldArgs = []
): mixed {
switch ($fieldName) {
case 'author':
return $this->customPostUserTypeAPI->getAuthorID($customPost);
}
return null;
}
public function resolveFieldTypeResolverClass(
TypeResolverInterface $typeResolver,
string $fieldName
): ?string {
switch ($fieldName) {
case 'author':
return UserTypeResolver::class;
}
return null;
}
}resolveValue์์ DB ์ํฐํฐ์ ID๋ฅผ, resolveFieldTypeResolverClass(ํด๋์ค UserTypeResolver๋ก ํํ๋จ)์์ ๊ฐ์ฒด์ ํ์
์ ์ป์ด, GraphQL ์์ง์ ๊ฐ์ฒด์ ๋ฐ์ดํฐ๋ฅผ ๋ก๋ํ ์ ์์ต๋๋ค.
๋ฐ์ดํฐ๋ฅผ ๋ก๋ํ ๋, ์์ง์ ๋งค์ฐ ํจ์จ์ ์ธ ์๊ณ ๋ฆฌ์ฆ์ ์ฌ์ฉํฉ๋๋ค. ์ด๋ ๋
ธ๋ ์๊ฐ ์๋๋ผ ์ฟผ๋ฆฌ ๋ด ํ์
์๋ฅผ n์ผ๋ก ํ๋ ์๊ฐ ๋ณต์ก๋ O(n)์
๋๋ค.
์ด ์๊ณ ๋ฆฌ์ฆ์ด ์ด๋ฌํ ํจ์จ์ฑ์ ๋ฌ์ฑํ๋ ์ด์ ๋ ๊ทธ๋ํ๋ฅผ ์ํํ์ง ์๊ณ , ๋ฐ์ดํฐ ๊ตฌ์กฐ๋ฅผ ์ปดํฌ๋ํธ ์คํ์ผ๋ก ๋ณํํ๊ธฐ ๋๋ฌธ์ ๋๋ค. ์ด๋ ํจ์ฌ ๊ฐ๋จํ๊ฒ ํด๊ฒฐํ ์ ์์ต๋๋ค. (GraphQL์ "๊ทธ๋ํ"๋ ๊ฐ๋ ์ด์ง ์ค์ ๊ตฌํ์ด ์๋๋๋ค.)
์ฟผ๋ฆฌ๊ฐ ์ฌ๋ฌ ๋ ๋ฒจ์ ๊ฐ์ง๊ณ ๊ฐ๊ฐ ๋ง์ ์ํฐํฐ๋ฅผ ๊ฐ์ ธ์ค๋ ๊ฒฝ์ฐ์๋ ์๊ณ ๋ฆฌ์ฆ์ ๊ฝค ์ ๊ฒฌ๋ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด, ๊น์ด 10 ๋ ๋ฒจ์ ๋ค์ ์ฟผ๋ฆฌ๋ฅผ ์คํํด๋ ํฐ ์ํฅ์ด ์์ต๋๋ค.
{
posts(pagination: { limit: 10 }) {
excerpt
title
url
author {
name
url
posts(pagination: { limit: 10 }) {
title
tags(pagination: { limit: 10 }) {
slug
url
posts(pagination: { limit: 10 }) {
title
comments(pagination: { limit: 10 }) {
content
date
author {
name
posts(pagination: { limit: 10 }) {
title
url
comments(pagination: { limit: 10 }) {
content
date
author {
name
username
url
}
}
}
}
}
}
}
}
}
}
}์ด ํจ์จ์ฑ์ ์์ธ๋ Post.metaValue, User.metaValue, Comment.metaValue, PostTag.metaValue, PostCategory.metaValue(๋ฐ metaValues ํ๋)๋ฅผ ํตํด ๋ฉํ ๊ฐ์ ๊ฐ์ ธ์ค๋ ๊ฒฝ์ฐ์
๋๋ค. WordPress ํจ์(get_post_meta, get_user_meta ๋ฑ)๋ ํ ๋ฒ์ 1๊ฐ์ ID์ ๋ํ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ค๊ธฐ ๋๋ฌธ์, ๊ฐ ์ํฐํฐ๋ ๋ฉํ ๊ฐ์ ๊ฐ์ ธ์ค๊ธฐ ์ํ ๋ฐ์ดํฐ๋ฒ ์ด์ค ํธ์ถ์ด ํ์ํฉ๋๋ค. ๊ฒฐ๊ณผ์ ์ผ๋ก ๋ฉํ ๊ฐ ํด๊ฒฐ์ ํ์
์๊ฐ ์๋ ๋
ธ๋ ์์ ๋ฐ๋ผ ํ์ฅ๋ฉ๋๋ค(์ด ์ ์์ ์๋ณธ ๋๊ธ์ด ์ ํํ ํต์ฌ์ ์ฐ๋ฅด๊ณ ์์ต๋๋ค).
์ ์์ ์ธ ํ์์๊ฐ ๋ฉํ ํ๋๋ฅผ ์ฌ์ฉํ๊ณ ๋จ์ฉํ๋ ๊ฒ์ ๋ฐฉ์งํ๊ธฐ ์ํด, Gato GraphQL(v0.8)์ ์ด ํ๋๋ค์ ๊ธฐ๋ณธ์ ์ผ๋ก ๋นํ์ฑํํ ์ํ๋ก ์ ๊ณต๋ฉ๋๋ค. ๊ด๋ฆฌ์๊ฐ ๋ช ์์ ์ผ๋ก ํ์ฑํํด์ผ ํ๋ฉฐ, ๊ทธ๋ ๊ฒ ํ ๋ ์ด ํ๋๋ค์ Access Control List ์๋์ ๋ฐฐ์นํ ์ ์์ด DB๊ฐ ๊ณต๊ฒฉ ์ํ์ ๋ ธ์ถ๋์ง ์์ต๋๋ค.
์๋ ์ ํ๋ ํ๋ฅญํ ์์ด๋์ด์ด๋ฉฐ, ํฅํ ๋ฆด๋ฆฌ์ค์์ ์ง์ํ ๊ณํ์ ๋๋ค.
๊ทธ๋ฆฌ๊ณ ์ฟผ๋ฆฌ์ ๋ณต์ก์ฑ ๋ถ์ ๋ฐ ์ ํ ๋ถ๊ณผ(์: ๋ช ๋ ๋ฒจ ๊น์ด๊น์ง ํ์ฉํ๋์ง)์ ๋ํด์๋ ๊ฒํ ํ๊ณ ์์ต๋๋ค. GraphQL ์๋ฒ๋ ์๊ฐ ๋ณต์ก๋ O(n)์ผ๋ก ์ฟผ๋ฆฌ๋ฅผ ํด๊ฒฐํ๋ฏ๋ก, ๋ฃจํ์ ๊ดํด์๋ ๊ทธ๋ค์ง ํฐ ํด๊ฐ ์์ต๋๋ค. ํ์ง๋ง ๋จ์ผ ์ฟผ๋ฆฌ๋ง์ผ๋ก๋ DB์์ ๋ฌด์ ํ์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ฌ ์ ์์ผ๋ฉฐ, ์ด๋ ํผํ๊ณ ์ถ์ ๊ฒ์
๋๋ค.
์๋ฅผ ๋ค์ด, ์ด ๊ฐ๋จํ ์ฟผ๋ฆฌ๋ ๋จ์ผ ์์ฒญ์ผ๋ก ๋ฐฉ๋ํ ์์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ต๋๋ค(์ ๋ฐ๋ชจ ์ฌ์ดํธ์๋ ์๋ฐฑ ๊ฑด์ ๋ ์ฝ๋๋ง ์์ด ์ฟผ๋ฆฌ ์คํ์ ์์ฐํ ์ ์์ต๋๋ค).
{
posts000: posts(pagination: { limit: 100 }) {
...PostFields
}
posts100: posts(pagination: { limit: 100, offset: 100 }) {
...PostFields
}
posts200: posts(pagination: { limit: 100, offset: 200 }) {
...PostFields
}
posts300: posts(pagination: { limit: 100, offset: 300 }) {
...PostFields
}
posts400: posts(pagination: { limit: 100, offset: 400 }) {
...PostFields
}
posts500: posts(pagination: { limit: 100, offset: 500 }) {
...PostFields
}
posts600: posts(pagination: { limit: 100, offset: 600 }) {
...PostFields
}
posts700: posts(pagination: { limit: 100, offset: 700 }) {
...PostFields
}
posts800: posts(pagination: { limit: 100, offset: 800 }) {
...PostFields
}
posts900: posts(pagination: { limit: 100, offset: 900 }) {
...PostFields
}
}
fragment PostFields on Post {
id
title
content
date
}๋ณด์๋ค์ํผ, ๋ฌธ์ ๋ฅผ ์ผ์ผํค๊ธฐ ์ํด ์ฟผ๋ฆฌ๋ฅผ ์ค์ฒฉํ ํ์์กฐ์ฐจ ์์ต๋๋ค. ๋ฐ๋ผ์ ์ฟผ๋ฆฌ ๋ณต์ก์ฑ ๋ถ์์ ๊น๋ค๋ก์ด ์์ ์ด๋ฉฐ, ์ ์ฉํ๊ฒ ๋ง๋ค๊ธฐ ์ํด์๋ ์ธ๋ฐํ ์กฐ์ ์ด ํ์ํฉ๋๋ค.
์ฟผ๋ฆฌ ๋ถ์ ์ง์๋ ์ถ๊ฐํ๊ณ ์ถ์ง๋ง, ์ฐ์ ์์๊ฐ ๋์ง ์์ต๋๋ค. ํผ์์คํฐ๋ ์ฟผ๋ฆฌ๋ ์ปค์คํ ์๋ํฌ์ธํธ์ Access Control Lists์ ์กฐํฉ์ผ๋ก ์ด๋ฏธ ์ ์์ ์ธ ํ์์๋ฅผ ์ฐจ๋จํ ์ ์์ผ๋ฉฐ, ์ฐ๋ฆฌ ์์ ์ ์์ ์ GraphQL ์๋น์ค๋ฅผ ๋จ์ฉํ์ง ์์(์์์ผ ํ !) ๊ฒ์ด๊ธฐ ๋๋ฌธ์ ๋๋ค.