๐พ Gato GraphQL์ด ์ด์ ์ค์ฝํ๋์์ต๋๋ค. PHP-Scoper ๋๋ถ์ ๋๋ค!
ํ๋ฌ๊ทธ์ธ Gato GraphQL์ด ์ค์ฝํ๋์์ต๋๋ค. ์ด์ ํ๋ฌ๊ทธ์ธ์ ๋๋์ด WordPress ํ๋ฌ๊ทธ์ธ ๋๋ ํ ๋ฆฌ์ ์ ๋ก๋ํ ์ ์๊ฒ ๋์์ต๋๋ค.

์ด๋ฅผ ์ํด ํ๋ฅญํ PHP-Scoper๋ฅผ ์ฌ์ฉํ๊ณ ์์ต๋๋ค. ์ด ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ WordPress์ ํจ๊ป ์ฌ์ฉํ๋ ๊ฒ์ ์ฝ์ง ์์ผ๋ฏ๋ก, ์ด ๋ธ๋ก๊ทธ ํฌ์คํธ์์ ์ด๋ป๊ฒ ํด๊ฒฐํ๋์ง ์ค๋ช ํ๊ฒ ์ต๋๋ค.
์น์ :
- ์ค์ฝํ์ ๊ฒฐ์ ํ๊ธฐ๊น์ง
- ์ต์ ๊ฒํ
- Mozart๋ฅผ ์๋ํ๊ณ ์คํจํ๋ค
- PHP-Scoper๋ฅผ ํ์ธํ๊ณ ๊ณตํฉ ์ํ์ ๋น ์ง๋ค
- PHP-Scoper๋ก ๋์์ค๋ค, ์ด๋ฒ์๋ ์ง์ฌ์ผ๋ก
- PHP-Scoper, ์ฌ์ด ๋ฐฉ๋ฒ ๐ ๐๐ฝ ์ฌ๊ธฐ์ ์ ํด๊ฒฐ์ฑ ์ด ์์๋ฉ๋๋ค
- ์ค์ ์ฝ๋๋ฅผ ๋ณด์ฌ์ฃผ์ธ์
- ํ ์คํธ
- ๊ฒฐ๊ณผ ํ์ธ
์ค์ฝํ์ ๊ฒฐ์ ํ๊ธฐ๊น์ง
๋ช ์ฃผ ์ , Matt Mullenweg๊ฐ ใGraphQL ํ๋ฌ๊ทธ์ธใ์ ์ฃผ์ํ๊ฒ ๋ค๊ณ ๋ฐํํ์ต๋๋ค. ๋ช ๋ฐฑํ WPGraphQL์ ๊ฐ๋ฆฌํค๋ ๊ฒ์ด์์ต๋๋ค. ๊ทธ์ ๋ฐ์ธ์ GraphQL ํ๋ฌ๊ทธ์ธ์ด ํ๋๋ฟ์ด๋ผ๊ณ ์๊ฐํ๊ณ ์์์ ๋ณด์ฌ์ฃผ์ง๋ง, ์ค์ ๋ก๋ ๋ ๊ฐ๊ฐ ์์ต๋๋ค(์ ์ธ๋ ๊ฒ์, ์, ์ ๊ฒ์ ๋๋ค). ์ด๋ฅผ ํตํด ์ ํ๋ฌ๊ทธ์ธ์ด ์ผ๋ง๋ ์ฃผ๋ชฉ๋ฐ์ง ๋ชปํ๊ณ ์๋์ง๋ฅผ ๊นจ๋ซ๊ฒ ๋์๊ณ , ์์ธํ ๋ง์์ด ๋ค์์ต๋๋ค.
Matt๋ ์ ํ๋ฌ๊ทธ์ธ์ด ์กด์ฌํ๋ค๋ ์ฌ์ค์ ๋ชฐ๋์ต๋๋ค. WordPress ์ปค๋ฎค๋ํฐ์ ๋๋ถ๋ถ๋ ๋ง์ฐฌ๊ฐ์ง์ ๋๋ค. ๋ถ๋ช ํ ํ๋ณด๊ฐ ์ถฉ๋ถํ์ง ์์ต๋๋ค. ๋ง์ผํ ๊ณผ ์์ ๋ฏธ๋์ด๋ ์ ๊ฐ์ ์ด ์๋๋๋ค. ๊ธฐ์ ์ ์ธ ๋ถ๋ถ์ ๊ทธ๋ฐ๋๋ก ์ํ๋ค๊ณ ์๊ฐํ์ง๋ง์. ๊ทธ๋์ ์ต์ํ ์ ๋ฅ๋ ฅ ๋ฒ์ ๋ด์์ ๋ฌด์ธ๊ฐ ํ๋ํ๊ธฐ๋ก ๊ฒฐ์ฌํ์ต๋๋ค.
ํ์ฌ ์์ ํ๊ณ ์๋ ๋ด์ฉ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
- ์ด ์น์ฌ์ดํธ gatographql.com์ ์ฝ๋ฉ์ ๋ฐฉ๊ธ ๋ง์น๊ณ 2์ฃผ ์ ์ ์ถ์ํ์ต๋๋ค(๋ง์ธ! ๐ฅณ ๊ทธ๋ฐ๋ฐ, ์ด๋ป๊ฒ ์๊ฐํ์๋์? DM์ด๋ ์ด๋ฉ์ผ๋ก ํผ๋๋ฐฑ์ ์ฃผ์๋ฉด ๊ฐ์ฌํ๊ฒ ์ต๋๋ค)
- 3์ผ ์ ์ ๋๋์ด ํ๋ฌ๊ทธ์ธ ์ค์ฝํ์ ์์ํ๊ณ , ์ด์ ์ด ์์ ์ ์๋ฃํ์ต๋๋ค!(์๋ฒฝ 3์์์ง๋ง, ํ ๋งํ ๊ฐ์น๊ฐ ์์์ต๋๋ค ๐ )
- ๋ง์ง๋ง์ผ๋ก, ๋ค์ ๋ฒ์
0.8์์ ์ ์ด๋ฏธ ์์ํ์ต๋๋ค. ์ด๊ฒ์ด ํ๋ฌ๊ทธ์ธ ์ ์ฅ์์์ ์ฒ์์ผ๋ก ์ด์ฉ ๊ฐ๋ฅํ ๋ฒ์ ์ด ๋ ๊ฒ์ ๋๋ค
ํ๋ฌ๊ทธ์ธ์ ์ค์ฝํํ๋ ๊ฒ์ ์ ์ฅ์์ ์ ๋ก๋ํ๊ธฐ ์ํ ํ์ ์กฐ๊ฑด์ ๋๋ค. ๊ทธ๋ ์ง ์์ผ๋ฉด ์ ํ๋ฌ๊ทธ์ธ๊ณผ ๋์ผํ ์์กด์ฑ์ ํ์๋ก ํ์ง๋ง ๋ค๋ฅธ ๋ฒ์ ์ ๊ฐ์ง ๋ค๋ฅธ ํ๋ฌ๊ทธ์ธ๊ณผ ์ถฉ๋์ด ๋ฐ์ํ ์ ์๊ธฐ ๋๋ฌธ์ ๋๋ค. ์ด๋ฅผ ์๋ฃํ ๊ฒ์ ์ ๋ง ์ค์ํ ์ด์ ํ์ ๋๋ค. ์ด๋ณด๋ค ์ค์ํ ๊ฐ๋ฐ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด, WordPress ๋ฐ์ดํฐ ๋ชจ๋ธ๊ณผ ์์ ํ ์ผ์นํ๋๋ก GraphQL ์คํค๋ง๋ฅผ ์์ฑํด์ผ ํ์ง๋ง, ๊ทธ๊ฒ์ ๊ฐ๊ฐ์ ์ ๋ฆด๋ฆฌ์ค์์ ๊พธ์คํ ์งํ๋ ๊ฒ์ ๋๋ค.
๋ช ์ฃผ ํ์๋ ใGraphQLใ๋ก ๊ฒ์ํ์ ๋ ํ๋ฌ๊ทธ์ธ์ด ๋ํ๋๊ฒ ๋๊ณ , GraphQL API ๊ตฌํ์ ์ค์ ๋ก ํ์๋ก ํ๋ ์ฌ๋๋ค์ด ์ ํ๋ฌ๊ทธ์ธ์ ์กด์ฌ๋ฅผ ์๊ฒ ๋ ๊ฒ์ ๋๋ค.
์ค์ ๋ก, ์ ๋ ์ ํ๋ฌ๊ทธ์ธ์ด WordPress์ ๋ฏธ๋์์ ์ง์งํ๊ฒ ๊ณ ๋ ค๋๊ธฐ๋ฅผ ๋ฐ๋๋๋ค. ๋ช ๋ ๋์ ์์ ํด ์์ต๋๋ค. ์ ์ฅ์๋ 2016๋ 8์์ ์์๋์์ต๋๋ค. ์ด๋ WPGraphQL์ด ์กด์ฌํ๊ธฐ ์ ์ด๋ฉฐ, GraphQL์ ์ด์ฐฝ๊ธฐ์ ๋๋ค. ํ์ง๋ง ์ด ํ๋ก์ ํธ๊ฐ GraphQL ์๋ฒ๊ฐ ๋ ์ค์ ๋ชฐ๋์ต๋๋ค. ๊ทธ ๋ฐฉํฅ์ผ๋ก ์ ํ๋ ๊ฒ์ ๋ถ๊ณผ 1.5๋ ์ ์ ์ผ์ ๋๋ค.
(์ด ํ๋ก์ ํธ๋ ์ค์ ๋ก ์๋ฒ ์ฌ์ด๋ ์ปดํฌ๋ํธ๋ฅผ ์ฌ์ฉํ์ฌ ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ตฌ์ถํ๊ธฐ ์ํ ํ๋ ์์ํฌ์ด๋ฉฐ, ์ด ์ํคํ ์ฒ๋ฅผ ์ฌ์ฉํ๋ฉด GraphQL ์๋ฒ๋ฅผ ์๋ฒฝํ๊ฒ ๊ตฌ์ถํ ์ ์์ต๋๋ค. ๊ทธ๋์ ๊ทธ๋ฅ ๊ตฌ์ถํ ๊ฒ์ ๋๋ค.)
WPGraphQL์ ํ๋ฆฝ๋ ํ๋ฌ๊ทธ์ธ์ด๋ฉฐ, ๊ทธ๋ด ๋งํ ์ด์ ๊ฐ ์์ต๋๋ค. ๋ช ๋ ์ ์ ์์๋์ด ์ปค๋ฎค๋ํฐ๊ฐ ํ์ฑ๋์์ต๋๋ค. Jason Bahl(Gatsby์ ๊ณ ์ฉ๋)๊ณผ ํ๋ก์ ํธ์ ๊ธฐ์ฌ์๋ค์ ์์ ์ ํ์ํ์ต๋๋ค. WordPress๋ฅผ Jamstack์ ํตํฉํ๋ ๊ฒ์ด ์ด๋ ๋๋ณด๋ค ์ฌ์์ก์ต๋๋ค.
ํ์ง๋ง Gatsby์ Jamstack์ ํ ๊ฐ์ง์ด๊ณ , WordPress๋ ๋ค๋ฅธ ๊ฒ์ ๋๋ค. WordPress๋ ์น์ 40%๋ฅผ ์ฐจ์งํ๋ฉฐ, ๋จ์ํ ์ ์ ์ฌ์ดํธ ์์ฑ๊ธฐ์ ์ ๋ ฅ์ด ์๋๋๋ค.
๋ฐ๋ผ์ ์ด์ ๋์์ด ์์ด์ ์ด ๊ฒฐ์ ์ด ๊ฐ์๋๋ ๊ฒ ์์ด, WPGraphQL์ด ์ฌ๋ฐ๋ฅธ ์ ํ์ธ์ง ๊ณ ๋ คํ ์ ์์ต๋๋ค. ๋ ํ๋ฌ๊ทธ์ธ์ ๋ถ์ํ์ฌ ์ด๋ ์ชฝ์ ๋ชฉํ๊ฐ WordPress์ ์ค์ํ ๊ฒ๊ณผ ๋ ์ผ์นํ๋์ง ํ์ธํ ์ ์์ต๋๋ค.
Gato GraphQL๋ Jamstack๊ณผ ํจ๊ป ์๋ํ ์ ์์ต๋๋ค. ํ์ง๋ง ๊ทธ ์ฃผ์ ๋ชฉํ๋ ๋ ํ๋ฅญํ๋ค๊ณ ์๊ฐํฉ๋๋ค. ใ๋ฐ์ดํฐ ๊ฒ์๋ฅผ ๋ฏผ์ฃผํใํ๋ ๊ฒ, ์ฆ API ํธ์ง์ ๊ฒ์๋ฌผ ํธ์ง๋งํผ ์ฝ๊ฒ ๋ง๋๋ ๊ฒ(๋๊ตฌ๋ ํ ์ ์๋ ๊ฒ), ๊ทธ๋ฆฌ๊ณ WordPress๋ฅผ ์น์ OS๋ก ๋ง๋๋ ๊ฒ์ ๋๋ค.
ํ๋ฌ๊ทธ์ธ์ด ์ ์ฅ์์์ ์ด์ฉ ๊ฐ๋ฅํด์ง๋ฉด, ๋ ๋ง์ ์ฌ๋๋ค์ด ์๋ํด ๋ณด๊ณ ใ์ด๊ฑฐ ์ ๋ง ๋๋ฐ์ด๋ค! ์ ์ด๋ฐ ๊ฑธ ๋ชฐ๋์๊น?ใ๋ผ๊ณ ๋งํด์ฃผ๊ธฐ๋ฅผ ๋ฐ๋๋๋ค.
๊ทธ๋ ๊ฒ ๋๋ฉด ใGraphQL ํ๋ฌ๊ทธ์ธใ์ ์ ํ์ ๋ฏธ๋ฆฌ ๊ฒฐ์ ๋์ง ์๊ณ , WordPress ์ปค๋ฎค๋ํฐ๊ฐ WPGraphQL๊ณผ Gato GraphQL ๋ชจ๋๋ฅผ ๊ฐ๊ฐ์ ์ฅ์ ์ ๋ฐํ์ผ๋ก ๊ณ ๋ คํ ์ ์๊ฒ ๋ฉ๋๋ค.
๋๊ธฐ์ ๋ํ ์ค๋ช ์ด ๋๋ฌ์ผ๋, ๊ธฐ์ ์ ์ธ ์ด์ผ๊ธฐ๋ฅผ ํด๋ด ์๋ค ๐ค.
์ต์ ๊ฒํ
ํ๋ฌ๊ทธ์ธ ์ค์ฝํ์ ํ๋ฌ๊ทธ์ธ ์ฝ๋๋ฅผ ์ ๋ ฅ์ผ๋ก ๋ฐ์ ์ค์ฝํ๋ ํ๋ฌ๊ทธ์ธ์ ์ถ๋ ฅํ๋ ๋๊ตฌ๋ฅผ ์คํํ๋ ๊ฒ์ ํฌํจํฉ๋๋ค. ๋ณ๊ฑฐ ์๋์ฃ ? ์ผ๋ง๋ ์ด๋ ค์ธ ์ ์์๊น์?

์ฝ๋๋ฒ ์ด์ค์ ๋ฐ๋ผ, ์ค์ฝํ ๋ช ๋ น๋ง ์คํํ๋ ๊ฒ์ผ๋ก๋ ์ถฉ๋ถํ์ง ์์ ์ ์์ต๋๋ค. ๊ทธ ํ์๋ ์ฝ์์ ์ค๋ฅ๋ฅผ ํ์ธํ๊ณ , ์์ ํ๊ณ , ์ ํ๋ฆฌ์ผ์ด์ ์ ์ฒ ์ ํ ํ ์คํธํ๊ณ , ์ค๋ฅ์ ๊ทธ ์์ธ์ ํ์ ํ๊ณ , ์์ ํ๊ณ , ๋ฐ๋ณตํด์ผ ํฉ๋๋ค. ์์ ํ ์ฌ๋ฐ๋ฅด๊ฒ ํ๊ธฐ ์ํด์๋ ์ด๋ ์ ๋์ ์๊ฐ์ด ํ์ํ ์ ์์ต๋๋ค.
์ค์ฝํ์ ์ํ 2๊ฐ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ์์ผ๋ฉฐ, ๊ฐ๊ฐ ๋ค๋ฅธ ๋ชฉ์ ์ ๊ฐ์ง๋๋ค.
- Mozart, WordPress ์ฝ๋์ฉ
- PHP-Scoper, ๋ชจ๋ PHP ์ฝ๋์ฉ. ํนํ PHAR์ ์์ฑํ ๋
WordPress ํ๋ฌ๊ทธ์ธ์ ๊ฐ์ง๊ณ ์์ผ๋ฏ๋ก, ๋จผ์ Mozart๋ฅผ ์๋ํด ๋ณด์์ต๋๋ค. ์ด๋ป๊ฒ ๋์๋์ง ์ดํด๋ณด๊ฒ ์ต๋๋ค.
Mozart๋ฅผ ์๋ํ๊ณ ์คํจํ๋ค
์ฝ 1๋
์ ์ Mozart๋ฅผ ์๋ํด ๋ณด์์ต๋๋ค. ๋ฌธ์์ ๋ฐ๋ฅด๋ฉด ใmozart compose ๋ช
๋ น์ด ๋ชจ๋ ๋ง๋ฒ์ ์ํํ๋คใ๊ณ ํฉ๋๋ค. ๊ทธ๋์ ๋ชจ๋ ๊ฒ์ด ๋งค์ฐ ๋น ๋ฅด๊ณ ๊ฐ๋จํ๊ฒ ํด๊ฒฐ๋์ด ๋๋จธ์ง ํ๋ฃจ๋ฅผ ๋ค์ดํค๋ฆฌ๋ฅผ ์ฆ๊ธฐ๋ฉฐ ๋ณด๋ผ ์ ์๊ธฐ๋ฅผ ๊ธฐ๋ํ์ต๋๋ค.
์ํ๊น๊ฒ๋, Mozart๋ ์ ์ฝ๋๋ฒ ์ด์ค์์ ์๋ํ์ง ์์์ต๋๋ค. ๊ณ์ ๋ฌธ์ ๊ฐ ๋ฐ์ํ์ฌ ์ค์ฝํ์ด ์คํ๋์ง ๋ชปํ์ต๋๋ค. ํ์ํ ์ง์๋ ๋ฐ์ง ๋ชปํ์ต๋๋ค. PR์ ์ ์ถํ์ง๋ง ๋ณํฉ์ด ๊ณ ๋ ค๋์ง ์์๊ณ , ๊ทธ ์ฌ์ค์กฐ์ฐจ ํต์ง๋ฐ์ง ๋ชปํ๊ธฐ ๋๋ฌธ์ ์์ฐ์ค๋ฝ๊ฒ ์ด ํ๋ก์ ํธ์ ๋ํ ๊ด์ฌ์ ์์ ๋๊น์ง ๊ธฐ๋ค๋ ค์ผ ํ์ต๋๋ค.
Mozart๊ฐ ์ ํ๋ฌ๊ทธ์ธ์ ์ผ๋ถ ์์กด์ฑ์ ์ฒ๋ฆฌํ์ง ๋ชปํ๋ค๊ณ ์๊ฐํฉ๋๋ค. Symfony์ ์ฌ๋ฌ ์ปดํฌ๋ํธ๋ฅผ ์ฌ์ฉํ๊ณ ์์ผ๋ฉฐ, DependencyInjection, Cache, Dotenv๊ฐ ํฌํจ๋์ด ์์ผ๋ฉฐ, ๋ชจ๋ Composer๋ก ๊ด๋ฆฌ๋ฉ๋๋ค.
PHP ์ค์ฝํ์ ๋จ์ํ PHP๋ง์ ๋ฌธ์ ๊ฐ ์๋๋๋ค. ์ค์ฝํผ์๋ ํผํด์ผ ํ ๋ง์ ์ฅ์ ๋ฌผ๊ณผ ํด๊ฒฐํด์ผ ํ ๊ณผ์ ๊ฐ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด, Symfony DependencyInjection์ ์ค์ ์ YAML ํ์ผ์ ์ฌ์ฉํ๋ฉฐ, ์ด๊ฒ๋ค๋ ์ค์ฝํ๋์ด์ผ ํฉ๋๋ค. ๋ํ composer.json ํ์ผ์๋ PSR-4 ์๋ ๋ก๋ฉ ์ค์ ์ด ํฌํจ๋์ด ์์ผ๋ฉฐ, ์ด๊ฒ๋ ์ค์ฝํ๋์ด์ผ ํฉ๋๋ค. Mozart๋ ์ด๋ฌํ ๋ณต์ก์ฑ์ ์ ๋๋ก ์ฒ๋ฆฌํ์ง ๋ชปํ๋ค๊ณ ์๊ฐํฉ๋๋ค.
ํ์ง๋ง ์ ๊ฒฝํ๋ง์ด ์ ์ผํ ๊ฒ์ ์๋๋ผ๊ณ ํ์ ํ๋ฉฐ, ๋ง์กฑํ๋ ์ฌ์ฉ์๋ค๋ ๋ง์ด ์์ ๊ฒ์ ๋๋ค. ๋ํ ์ ์คํจํ ์๋๋ 1๋ ์ ์ ์ผ์ด๋ฏ๋ก, ๊ทธ ์ดํ๋ก ๋๊ตฌ๊ฐ ๊ฐ์ ๋์์ ์๋ ์์ต๋๋ค. ๊ทธ๋ฆฌ๊ณ ์์ง ๋ง์ธ์. ใ์ค์ฝํ๋ ํ๋ฌ๊ทธ์ธ์ ๋ชจ๋ ๋น์ทํ๋ค. ์ค์ฝํ๋์ง ์์ ํ๋ฌ๊ทธ์ธ์ ๊ฐ์ ๋ ์์ ์ธ ๋ฐฉ์์ผ๋ก ์ค์ฝํ๋์ง ์๋๋คใ๋ ๋ง์ฒ๋ผ, ์ด์ฉ๋ฉด ์ ๋ง์ ๋ฌธ์ ์ผ ์๋ ์์ต๋๋ค.
WordPress ํ๋ฌ๊ทธ์ธ์ด ๋จ์ํ๊ณ ์์ฒด ์๊ฒฐ์ ์ธ ๋ก์ง์ ๊ฐ์ง๋ฉฐ, ์ค์ฝํ์ด PHP ์ฝ๋ ๋ด์์๋ง ์ํ๋์ด์ผ ํ๋ ๊ฒฝ์ฐ๋ผ๋ฉด Mozart๊ฐ ์๋ํ ๊ฐ๋ฅ์ฑ์ด ์์ต๋๋ค. ์ง์ ํ์ธํด ๋ณด๋ ์๋ฐ์ ์์ต๋๋ค.
PHP-Scoper๋ฅผ ํ์ธํ๊ณ ๊ณตํฉ ์ํ์ ๋น ์ง๋ค
๊ทธ๋์ PHP-Scoper๋ก ํฅํ์ต๋๋ค. ํ์ง๋ง ์ฆ์ ๊ฒ์ด ๋์ ์๋์กฐ์ฐจ ํด๋ณด์ง ๋ชปํ์ต๋๋ค.
๋จผ์ , ์ด ๋๊ตฌ๋ WordPress๋ฅผ ๊ธฐ๋ณธ์ ์ผ๋ก ์ง์ํ์ง ์์ต๋๋ค. ๊ทธ๋ฆฌ๊ณ ๊ณ์ํด์, ๊ทธ๋ค ์์ ์ Makefile์ ์ดํด๋ณผ ๊ฒ์ ๊ถ์ฅํ๋๋ฐ, ๋ค์๊ณผ ๊ฐ์ ๋ชจ์ต์ ๋๋ค.
# See https://tech.davis-hansson.com/p/make/
MAKEFLAGS += --warn-undefined-variables
MAKEFLAGS += --no-builtin-rules
.DEFAULT_GOAL := help
PHPBIN=php
PHPNOGC=php -d zend.enable_gc=0
IS_PHP8=$(shell php -r "echo version_compare(PHP_VERSION, '8.0.0', '>=') ? 'true' : 'false';")
SRC_FILES=$(shell find bin/ src/ -type f)
.PHONY: help
help:
@echo "\033[33mUsage:\033[0m\n make TARGET\n\n\033[32m#\n# Commands\n#---------------------------------------------------------------------------\033[0m\n"
@fgrep -h "##" $(MAKEFILE_LIST) | fgrep -v fgrep | sed -e 's/\\$$//' | sed -e 's/##//' | awk 'BEGIN {FS = ":"}; {printf "\033[33m%s:\033[0m%s\n", $$1, $$2}'
#
# Build
#---------------------------------------------------------------------------
.PHONY: clean
clean: ## Clean all created artifacts
clean:
git clean --exclude=.idea/ -ffdx
update-root-version: ## Check the lastest GitHub release and update COMPOSER_ROOT_VERSION accordingly
update-root-version:
rm .composer-root-version || true
$(MAKE) .composer-root-version๊ทธ๋ฆฌ๊ณ 600์ค ์ด์, ๋ชจ๋ ์ด๋ฐ ๋ด์ฉ์ ๋๋ค. ๋ง์น ์์๊ป๋ผ ๊ฐ์ต๋๋ค. ํ๋ฌ๊ทธ์ธ์ ์ค์ฝํํ๊ธฐ ์ํด ๊ทธ ์ฝ๋๋ฅผ ์ดํดํด์ผ ํ๋ค๊ณ ์๊ฐํ๋, ํฉ๊ธํ ๋๋ง์ณค์ต๋๋ค.
(์, ๊ทธ ์ฝ๋๋ฅผ ์ดํดํ๋ ๊ฒ์ ์ค์ฝํ๋ ์ ํ๋ฆฌ์ผ์ด์
์ ํ
์คํธํ๊ธฐ ์ํ ๊ถ์ฅ ์ฌํญ์ด์ง, ํ์๋ ์๋๋๋ค. ๋จ์ํ php-scoper add-prefix ๋ช
๋ น์ ์คํํ๊ณ , ๋ชจ๋ ๋ง๋ฒ์ ๋งก๊ธฐ๊ณ , ๋ค์ดํค๋ฆฌ๋ฅผ ๋ง์๋ฌ ๊ฐ ์๋ ์์ต๋๋ค.)
PHP-Scoper๋ก ๋์์ค๋ค, ์ด๋ฒ์๋ ์ง์ฌ์ผ๋ก
3์ผ ์ , ์ด๋ป๊ฒ๋ ์ค์ฝํ์ ๊ตฌํํ๊ธฐ๋ก ๊ฒฐ์ฌํ์ต๋๋ค. ๋ฐ๋์ ์คํ์์ผ์ผ ํ์ต๋๋ค.
PHP-Scoper๋ก ๋์์์ ์ง์งํ๊ฒ ์๋ํด ๋ณด๊ธฐ๋ก ํ์ต๋๋ค. PHP Scoper: How to Avoid Namespace Issues in your Composer Dependencies(Delicious Brains์ ํ๋ฅญํ ํ์ด ์์ฑํ)๋ฅผ ์ฝ๊ณ WordPress๋ฅผ ์ค์ฝํํ ์ ์๋ค๋ ๊ฒ์ ์๊ณ ์์์ต๋๋ค. ๋จ์ง ํ๋์ ๋๊ธฐ์ ๋ฌธ์ ์์ต๋๋ค.
๊ธฐ์กด ์๋ฃจ์ ๋ค์ ํ์ํด ๋ณด์์ต๋๋ค.
ํ์ง๋ง ๋ชจ๋ ์์ ํ ๋ง์กฑ์ค๋ฝ์ง ์์์ต๋๋ค. ์ฝ๋๊ฐ ํดํน์ฒ๋ผ ๋ณด์ด๊ฑฐ๋, ์ทจ์ฝํ๊ณ ์ธ์ ๊ฐ ๊นจ์ง ๊ฒ ๊ฐ์ ๊ฒ๋ค์ด์์ต๋๋ค.
์๋ฅผ ๋ค์ด, Google Web Stories ํ๋ฌ๊ทธ์ธ์ ์ฝ๋๋ฅผ ์ค์ฝํํ ๋ค์, ๊ฐ ์ถฉ๋์ ๋ค์ ๋๋๋ฆฝ๋๋ค.
return [
'patchers' => [
function ( $file_path, $prefix, $contents ) {
/*
* There is currently no easy way to simply whitelist all global WordPress functions.
*
* This list here is a manual attempt after scanning through the AMP plugin, which means
* it needs to be maintained and kept in sync with any changes to the dependency.
*
* As long as there's no built-in solution in PHP-Scoper for this, an alternative could be
* to generate a list based on php-stubs/wordpress-stubs. devowlio/wp-react-starter/ seems
* to be doing just this successfully.
*
* @see https://github.com/humbug/php-scoper/issues/303
* @see https://github.com/php-stubs/wordpress-stubs
* @see https://github.com/devowlio/wp-react-starter/
*/
$contents = str_replace( "\\$prefix\\_doing_it_wrong", '\\_doing_it_wrong', $contents );
$contents = str_replace( "\\$prefix\\__", '\\__', $contents );
$contents = str_replace( "\\$prefix\\esc_html_e", '\\esc_html_e', $contents );
$contents = str_replace( "\\$prefix\\esc_html", '\\esc_html', $contents );
$contents = str_replace( "\\$prefix\\esc_attr", '\\esc_attr', $contents );
$contents = str_replace( "\\$prefix\\esc_url", '\\esc_url', $contents );
$contents = str_replace( "\\$prefix\\do_action", '\\do_action', $contents );
// ...
}
]
]์ ๊ทธ๋ ๊ฒ ํ๋์ง ์ดํดํ์ง๋ง, ๋ง์์ ๋ค์ง ์์ต๋๋ค. ์๋ก์ด WordPress ํจ์๊ฐ ์ฐธ์กฐ๋ ๋๋ง๋ค ์ด ๋ชฉ๋ก์๋ ์ถ๊ฐํด์ผ ํฉ๋๋ค. ๋๋ฌด ์๋์ ์ด๊ณ , ๋๋ฌด ์ทจ์ฝํฉ๋๋ค.
์ด๊ฒ์ด ์ ๊ณผ์ ์์ต๋๋ค. ํ๋ฌ๊ทธ์ธ์ ์ค์ฝํํ๋ ๋ ๊ฐ๋จํ ๋ฐฉ๋ฒ์ด ์๊ณ , ์น๊ตฌ๋ ๋๋ฃ์๊ฒ ๋ณด์ฌ์ค๋ ๋ถ๋๋ฝ์ง ์์ ์ฝ๋์ ์์กดํ ์ ์์๊น์?
PHP-Scoper, ์ฌ์ด ๋ฐฉ๋ฒ ๐
์๊ฐ๋ณด๋ค ํจ์ฌ ์ฌ์ ์ต๋๋ค! ๋จ ๋ช ์๊ฐ ๋ง์ ๋ชจ๋ ๊ฒ์ด ์๋ํ์ต๋๋ค.

ใ์ฝ๋คใ์ ใ๋ช ์๊ฐใ์ด๋ผ๊ณ ๋งํ ๋, ์ค์ ๋ก ์๋ฏธํ๋ ๊ฒ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค. ์ฝ๋๋ฒ ์ด์ค์ ์ ์ ํ ๊ตฌ์กฐ๋ฅผ ๋ง๋๋ ๋ฐ 2๊ฐ์์ ๋ณด๋ธ ํ์์ผ ๋ชจ๋ ๊ฒ์ด ์ฆ์ ์๋ํ๋ค๋ ๊ฒ์ ๋๋ค(๋์ค์ ๋ ์์ธํ ์ค๋ช ํ๊ฒ ์ต๋๋ค).
ํ์ง๋ง ์ค์ํ ๊ฒ์, ํ๋ก์ ํธ์ ์ฌ๋ฐ๋ฅธ ์ค์ ์ด ์๋ค๋ฉด ์ค์ฝํ์ ๊ธ๋ฐฉ ๋ฌ์ฑํ ์ ์๋ค๋ ๊ฒ์ ๋๋ค.
WordPress ์ฝ๋๋ฅผ ์ค์ฝํํ ๋์ ๋ฌธ์ ๋ ๋ฐ๋ก WordPress ์ฝ๋ ์์ฒด์
๋๋ค. ๋ฌธ์ ๋ ์ฌ๊ธฐ์ ์ค๋ช
๋์ด ์์ต๋๋ค. ์์ฝํ๋ฉด, ๋ชจ๋ WordPress ํจ์์ ํด๋์ค๋ ๋ค์์คํ์ด์คํ๋๋ค๋ ๊ฒ์
๋๋ค. ์ฝ๋์์ WP_Query๋ฅผ ์ฐธ์กฐํ๊ฑฐ๋ get_posts๋ฅผ ํธ์ถํ๋ฉด, ์ด๊ฒ๋ค์ด MyPrefixedNamespace\WP_Query์ MyPrefixedNamespace\get_posts๋ก ๋ณํ๋์ด ๋ฐํ์์ ๋์คํจ๋ฅผ ์ด๋ํฉ๋๋ค. ๊ทธ๋ฆฌ๊ณ ์ด๊ฒ์ PHP-Scoper์์ ํดํน ์์ด๋ ํผํ ์ ์์ต๋๋ค.
๊ทธ๋ ๋ค๋ฉด, ํด๊ฒฐ์ฑ
์ ๋ฌด์์ผ๊น์? ๊ฐ๋จํฉ๋๋ค. ์ค์ฝํ๋ ์ฝ๋๋ฒ ์ด์ค์์ WP_Query๋ฅผ ์ฐธ์กฐํ๊ฑฐ๋, get_posts๋ฅผ ํธ์ถํ๊ฑฐ๋, ์ด๋ค WordPress ์ฝ๋๋ ์ฌ์ฉํ์ง ์๋ ๊ฒ์
๋๋ค.

์๋์, ์ ๋ ๋ฏธ์น์ง ์์๊ณ , ์ฌ๋ฌ๋ถ๋ ๋ง์ฐฌ๊ฐ์ง๋ผ๊ณ ์๊ฐํฉ๋๋ค. ๊ทธ๋ฆฌ๊ณ ๋ค, WordPress ํ๋ฌ๊ทธ์ธ์ ๊ตฌ์ถํ๊ณ ์๋ค๋ ๊ฒ์ ์๊ณ ์์ต๋๋ค... ์ค๋ช ํ๊ฒ ์ต๋๋ค.
์ด๋ป๊ฒ WordPress ์ฝ๋๋ฅผ ํฌํจํ์ง ์์ ์ ์์๊น์? ์ฝ๋๋ฒ ์ด์ค๋ฅผ 2์ธํธ์ ํจํค์ง๋ก ๋ถํ ํจ์ผ๋ก์จ ๊ฐ๋ฅํฉ๋๋ค.
- WordPress ์ฝ๋๋ฅผ ํฌํจํ์ง๋ง, ์ธ๋ถ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ์ฝ๋๋ฅผ ์ฐธ์กฐํ์ง ์๋ ๊ฒ
- ๋น์ฆ๋์ค ๋ก์ง์ ํฌํจํ์ง๋ง, WordPress ์ฝ๋๋ฅผ ์ ํ ํฌํจํ์ง ์๊ณ , ํ์ํ ์์กด์ฑ๊ณผ ํด๋น ์ฝ๋์ ๋ํ ๋ชจ๋ ์ฐธ์กฐ๋ฅผ ํฌํจํ๋ ๊ฒ
์ด๋ ๊ฒ ํ๋ฉด, ๋จ์ผ ์ฝ๋๋ฒ ์ด์ค๋ฅผ ๊ฐ๋ ๋์ ์ฌ๋ฌ ์ฝ๋๋ฒ ์ด์ค(๋๋ ํจํค์ง)๋ฅผ ๊ฐ๊ฒ ๋ฉ๋๋ค. ์ผ๋ถ๋ ์ค์ฝํ๋๊ณ ์ผ๋ถ๋ ์ค์ฝํ๋์ง ์์ผ๋ฉฐ, ๋ชจ๋ Composer๋ฅผ ํตํด ์ฐ๊ฒฐ๋์ด ํ๋ฌ๊ทธ์ธ์ ๊ตฌ์ฑํฉ๋๋ค.
๊ทธ๋ฌ๋ฉด WordPress ์ฝ๋๋ฅผ ํฌํจํ๋ ํจํค์ง๋ ์ค์ฝํํ์ง ์์ ์ถฉ๋์ ๋ฐฉ์งํฉ๋๋ค. ์ด๊ฒ์ด ์๋ํ๋ ์ด์ ๋ ์ธ๋ถ ์์กด์ฑ์ ์ํ๋ ์ฝ๋๋ฅผ ์ฐธ์กฐํ์ง ์๊ธฐ ๋๋ฌธ์
๋๋ค. ๋ชจ๋ ์ฐธ์กฐ๋ MyNamespace\MyPlugin\MyClass์ ๊ฐ์ ๋ด๋ถ ์ฐธ์กฐ์
๋๋ค. ํ์ง๋ง ์ด๊ฒ๋ค์ ์ค์ฝํํ ํ์๊ฐ ์์ต๋๋ค. WordPress ์ฌ์ดํธ์๋ ํ๋ฌ๊ทธ์ธ์ ๋ฒ์ ์ด ํ๋๋ง ์ค์น๋ ๊ฒ์ด๋ผ๊ณ ์์ ํ๊ฒ ๊ฐ์ ํ ์ ์์ผ๋ฉฐ, ์์ ์ ๋ค์์คํ์ด์ค MyNamespace\*๋ฅผ ํ์ดํธ๋ฆฌ์คํธ์ ๋ฑ๋กํ ์ ์๊ธฐ ๋๋ฌธ์
๋๋ค.
๋๋ถ์ด, ํ๋ฌ๊ทธ์ธ์ด ํ์ฅ ๊ฐ๋ฅํ๋ค๋ฉด ์์ ์ ๋ค์์คํ์ด์ค๋ฅผ ํ์ดํธ๋ฆฌ์คํธ์ ๋ฑ๋กํ๋ ๊ฒ์ ํ์์
๋๋ค. ์๋ฅผ ๋ค์ด, Gato GraphQL์ ํ๋ ๋ฆฌ์กธ๋ฒ๋ ํด๋์ค PoP\ComponentModel\FieldResolvers\AbstractFieldResolver๋ฅผ ํ์ฅํ์ฌ ๊ตฌํ๋ฉ๋๋ค. ์ค์ฝํํ๋ฉด ๊ฐ๋ฐ์๋ค์ ๊ฐ๋ฐ ์์๋ PoP\ComponentModel\FieldResolvers\AbstractFieldResolver๋ฅผ ์ฐธ์กฐํ๊ณ , ํ๋ก๋์
ํ๊ฒฝ์์๋ PrefixedByPoP\PoP\ComponentModel\FieldResolvers\AbstractFieldResolver๋ฅผ ์ฐธ์กฐํด์ผ ํฉ๋๋ค. ๊ทธ๊ฒ์ ๋ฐ์๋ค์ผ ์ ์์ต๋๋ค.
๋ฐ๋ผ์ ์ธ๋ถ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋ํ ๋ชจ๋ ์ฐธ์กฐ๋ฅผ ํฌํจํ์ง๋ง WordPress ์ฝ๋๋ ํฌํจํ์ง ์๋ ๋น์ฆ๋์ค ๋ก์ง ํจํค์ง๋ง ์ค์ฝํํฉ๋๋ค.
์์ฝํ๋ฉด, ์ด ์ ๋ต์ ์ ํํฉ๋๋ค.
ใ๋จ์ผ ์ฝ๋๋ฒ ์ด์ค๋ฅผ ๊ฐ๊ณ , ์ค์ฝํํ ๋ค์, ์์ฒญ๋ ๊ณ ํต๊ณผ ์ธ๋ด๋ก ํผํด๋ฅผ ์๋๋๋ก ๋๋๋ฆฌ๊ณ , ์ถฉ๋์ด ๋์ ๋์ง ์์ ํ๋ก๋์ ์์ ๐ฃ ํญ๋ฐํ์ง ์๊ธฐ๋ฅผ ๊ธฐ๋ํ๋คใ
์ด๊ฒ์ผ๋ก ๋ฐ๊ฟ๋๋ค.
ใ์ฝ๋๋ฒ ์ด์ค๋ฅผ 2๊ฐ์ ๊ทธ๋ฃน์ผ๋ก ๋๋๊ณ , ์ธ๋ถ ์์กด์ฑ์ ๋ํ ์ฐธ์กฐ๋ฅผ ํฌํจํ๊ณ WordPress ์ฝ๋๋ ํฌํจํ์ง ์๋ ๊ฒ๋ง ์ค์ฝํํ ๋ค์, ์๊ณ ํ ๋ค์ดํค๋ฆฌ๋ฅผ ๋ง์๋ฌ ๊ฐ๋ค ๐นใ
์ค์ ์ฝ๋๋ฅผ ๋ณด์ฌ์ฃผ์ธ์
์์์ง๋ฅผ ์ด์ด์ ์ง์ง ๊ณ ๊ธฐ๊ฐ ๋ค์ด ์๋์ง ํ์ธํ ์๊ฐ์ ๋๋ค ๐ญ.
4์ผ ์ , ์ ํ๋ฌ๊ทธ์ธ์๋ ๋ค์ ์ฝ๋๊ฐ ์์์ต๋๋ค.
namespace GraphQLAPI\GraphQLAPI\ContentProcessors;
use Parsedown;
class MarkdownContentParser
{
protected function getHTMLContent(string $fileContent): string
{
return (new Parsedown())->text($markdownContent);
}
}ํด๋์ค Parsedown์ ํ๋ฌ๊ทธ์ธ์ composer.json์ ์ ์๋ ์ธ๋ถ ์์กด์ฑ erusev/parsedown์์ ์ต๋๋ค.
{
"require": {
"erusev/parsedown": "^1.7"
}
}๋ฐ๋ผ์ ์ ํ๋ฌ๊ทธ์ธ์๋ ์ธ๋ถ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋ํ ์ฐธ์กฐ๊ฐ ํฌํจ๋์ด ์์๊ธฐ ๋๋ฌธ์, ์ค์ฝํํ์ฌ Parsedown์ PrefixedByPoP\Parsedown์ผ๋ก ๋ณํํด์ผ ํ์ต๋๋ค. ํ์ง๋ง ๊ทธ๋ ๊ฒ ํ๋ฉด ํ๋ฌ๊ทธ์ธ ๋ด์ ๋ชจ๋ WordPress ์ฝ๋๋ ์ค์ฝํ๋์ด ์ถฉ๋์ด ๋ฐ์ํฉ๋๋ค.
๊ทธ๋์ ์ฝ๋๋ฅผ graphql-api/markdown-convertor๋ผ๋ ๋ณ๋์ ํจํค์ง๋ก ์ถ์ถํ๊ณ , composer.json์ ์๋ํํฐ ์์กด์ฑ์ ์์ ์ ์์กด์ฑ์ผ๋ก ๊ต์ฒดํ์ต๋๋ค.
{
"require": {
"graphql-api/markdown-convertor": "^0.8"
}
}์ด์ ํ๋ฌ๊ทธ์ธ์ ์ธ๋ถ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ง์ ์ฐธ์กฐํ์ง ์๊ณ , ๋์ ์ ํจํค์ง์ ์๋น์ค MarkdownConvertorInterface๋ฅผ ์ฐธ์กฐํฉ๋๋ค.
namespace GraphQLAPI\GraphQLAPI\ContentProcessors;
use GraphQLAPI\MarkdownConvertor\MarkdownConvertorInterface;
class MarkdownContentParser extends AbstractContentParser
{
protected MarkdownConvertorInterface $markdownConvertorInterface;
function __construct(MarkdownConvertorInterface $markdownConvertorInterface)
{
$this->markdownConvertorInterface = $markdownConvertorInterface;
}
protected function getHTMLContent(string $fileContent): string
{
return $this->markdownConvertorInterface->convertMarkdownToHTML($fileContent);
}
}์๋ํํฐ ์์กด์ฑ์ ๋ํ ์ฐธ์กฐ๋ ์ ํจํค์ง์์ ์ํ๋ฉ๋๋ค.
namespace GraphQLAPI\MarkdownConvertor;
use Parsedown;
class MarkdownConvertor implements MarkdownConvertorInterface
{
public function convertMarkdownToHTML(string $markdownContent): string
{
return (new Parsedown())->text($markdownContent);
}
}์ต์ข ์ ์ผ๋ก, ๋ค์์ ์ํํด์ผ ํฉ๋๋ค.
- ์์กด์ฑ
graphql-api/markdown-convertor๋ฅผ ์ค์ฝํ - ํ๋ฌ๊ทธ์ธ ์ฝ๋์ ์ค์ฝํ ๊ฑด๋๋ฐ๊ธฐ
- ์์ ์ ํด๋์ค๊ฐ ์ค์ฝํ๋์ง ์๋๋ก ๋ค์์คํ์ด์ค
GraphQLAPI\*๋ฅผ ํ์ดํธ๋ฆฌ์คํธ์ ๋ฑ๋ก
์ด๊ฒ์ด ๊ธฐ๋ณธ ์ ๋ต์ ๋๋ค. ์ด์ ๋ถํฐ๋ ํ๋ฌ๊ทธ์ธ์ด ์ค์ฝํ๋ ์ ์์ ๋๊น์ง ๋ชจ๋ ์ธ๋ถ ์์กด์ฑ์ ์ฝ๋์์ ์ ๊ฑฐํ๋ฉด์ ์ด ๋์ผํ ์์ด๋์ด๋ฅผ ๋ฐ๋ณตํฉ๋๋ค.
์ถ์ถํด์ผ ํ ์์กด์ฑ์ composer.json ํ์ผ์ require ์น์
์ ์๋ ๊ฒ๋ค๋ฟ์
๋๋ค. require-dev์ ๊ฒฝ์ฐ ์ธ๋ถ ์ฌ๋ถ์ ๊ด๊ณ์์ด ์์กด์ฑ์ ์ ์งํ ์ ์์ต๋๋ค. ๊ฐ๋ฐ์ ์ฌ์ฉ๋๋ ์์กด์ฑ์ ์ค์ฝํํ ํ์๊ฐ ์์ผ๋ฉฐ, ํ๋ก๋์
์ฉ ํ๋ฌ๊ทธ์ธ์ ๋ง๋ค๊ณ ๋ฐฐํฌํ๊ธฐ ์ํ ๊ฒ๋ค๋ง ์ค์ฝํํ๋ฉด ๋ฉ๋๋ค.
๊ฒฐ๊ตญ, ํ๋ฌ๊ทธ์ธ์ composer.json์๋ ์ธ๋ถ ์์กด์ฑ์ด ํฌํจ๋์ง ์์์ผ ํฉ๋๋ค. ์ ํ๋ฌ๊ทธ์ธ์ ๊ฒฝ์ฐ, ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
{
"require": {
"php": "^7.4|^8.0",
"getpop/engine-wp": "^0.8",
"graphql-api/markdown-convertor": "^0.8",
"graphql-by-pop/graphql-clients-for-wp": "^0.8",
"graphql-by-pop/graphql-endpoint-for-wp": "^0.8",
"graphql-by-pop/graphql-server": "^0.8",
"pop-schema/basic-directives": "^0.8",
"pop-schema/comment-mutations-wp": "^0.8",
"pop-schema/commentmeta-wp": "^0.8",
"pop-schema/comments-wp": "^0.8",
"pop-schema/custompost-mutations-wp": "^0.8",
"pop-schema/custompostmedia-mutations-wp": "^0.8",
"pop-schema/custompostmedia-wp": "^0.8",
"pop-schema/custompostmeta-wp": "^0.8",
"pop-schema/generic-customposts": "^0.8",
"pop-schema/media-wp": "^0.8",
"pop-schema/pages-wp": "^0.8",
"pop-schema/post-mutations": "^0.8",
"pop-schema/post-tags-wp": "^0.8",
"pop-schema/posts-wp": "^0.8",
"pop-schema/taxonomymeta-wp": "^0.8",
"pop-schema/taxonomyquery-wp": "^0.8",
"pop-schema/user-roles-access-control": "^0.8",
"pop-schema/user-roles-wp": "^0.8",
"pop-schema/user-state-mutations-wp": "^0.8",
"pop-schema/user-state-wp": "^0.8",
"pop-schema/usermeta-wp": "^0.8",
"pop-schema/users-wp": "^0.8"
}
}์ด ํจํค์ง๋ค์ ๋ชจ๋ ๋ค์์คํ์ด์ค getpop, graphql-api, graphql-by-pop, pop-schema๋ฅผ ๊ฐ์ง ์ ๊ฒ์
๋๋ค. ํ๋ฌ๊ทธ์ธ์ ๋ชจ๋ ์ฝ๋๋ฅผ ํฌํจํ๋ ์์กด์ฑ๋ค์
๋๋ค. ์ฝ๋๋ฅผ ๋ ์ ๊ด๋ฆฌํ๊ธฐ ์ํด ๋ค๋ฅธ ๋ค์์คํ์ด์ค๋ก ๋ถ์ฐ๋์ด ์์ง๋ง, ๊ทธ๋ด ํ์๋ ์์ต๋๋ค. ๋จ์ผ ๋ค์์คํ์ด์ค๋ฅผ ์ฌ์ฉํด๋ ์ ์๋ํฉ๋๋ค.
์ ํ๋ฆฌ์ผ์ด์
๋ด์ ํจํค์ง ์๊ฐ ์ฆ๊ฐํจ์ ๋ฐ๋ผ, ๋ชจ๋ ํจํค์ง๋ฅผ ๋ชจ๋
ธ๋ฆฌํฌ์ ํธ์คํ
ํด์ผ ํฉ๋๋ค. ๊ทธ๋ ์ง ์์ผ๋ฉด ์ฌ๋ฌ ํจํค์ง๋ฅผ ํฌํจํ๋ ํ ๋ฆฌํ์คํธ๋ฅผ ๋ง๋ค๋ค๊ฐ ๋ฏธ์ณ๋ฒ๋ฆด ๊ฒ์
๋๋ค(๋ฏฟ์ด ์ฃผ์ธ์, ๊ฒฝํํด ๋ดค์ต๋๋ค). ์ ๊ฒฝ์ฐ, ๋ชจ๋ ํจํค์ง๋ GatoGraphQL/GatoGraphQL ๋ชจ๋
ธ๋ฆฌํฌ์ ํธ์คํ
๋์ด ์์ผ๋ฉฐ, ํ๋ฅญํ Monorepo Builder๋ก ๋๊ธฐํ๋ฅผ ์ ์งํ๊ณ ์์ต๋๋ค(์ด ๋๊ตฌ์ ๋ํ ๊ธ์ ์จ์ผ๊ฒ ์ต๋๋ค. ์ ๋ง ์๋ช
์ ์์ธ์
๋๋ค!).
์ด ํจํค์ง๋ค์ ๋ค์์คํ์ด์ค๋ PoP, GraphQLAPI, GraphQLByPoP, PoPSchema์
๋๋ค. ์ ๊ฒ์ด๋ฏ๋ก ์ ํ๋ฆฌ์ผ์ด์
์ ํ ๋ฒ๋ง ๋ํ๋ ๊ฒ์ ์๊ธฐ ๋๋ฌธ์ ์ค์ฝํ์ ํผํ ์ ์์ต๋๋ค.
์ด๋ฅผ ์ํด scoper.inc.php์์ ํ์ดํธ๋ฆฌ์คํธ์ ๋ฑ๋กํฉ๋๋ค.
return [
'whitelist' => [
// Own namespaces
'PoPSchema\*',
'PoP\*',
'GraphQLByPoP\*',
'GraphQLAPI\*',
// Own container cache
'PoPContainer\*',
],
];๋ง์ง๋ง ํญ๋ชฉ์ ์์กด์ฑ ์ฃผ์
์ปจํ
์ด๋์ ํด๋นํ๋ฉฐ, ์ด๊ฒ๋ ์ค์ฝํ๋์ด์ผ ํฉ๋๋ค. ๊ธฐ๋ณธ์ ์ผ๋ก ์ด ์ปจํ
์ด๋๋ ๊ธ๋ก๋ฒ ๋ค์์คํ์ด์ค์ ์ง์ ProjectServiceContainer๋ผ๋ ์ด๋ฆ์ผ๋ก ํ ๋น๋ฉ๋๋ค. ํ์ง๋ง PHP-Scoper๋ ๊ธ๋ก๋ฒ ๋ค์์คํ์ด์ค์ ํน์ ํด๋์ค๋ฅผ ํ์ดํธ๋ฆฌ์คํธ์ ๋ฑ๋กํ๋ ๊ฒ์ ์ง์ํ์ง ์์ต๋๋ค. ๋ฐ๋ผ์ ์ธ๊ณต์ ์ธ ๋ค์์คํ์ด์ค PoPContainer๋ฅผ ํ์ดํธ๋ฆฌ์คํธ์ ์ถ๊ฐํ๊ณ , ์ปจํ
์ด๋๋ฅผ ๋์คํฌ์ ๋คํํ ๋ ์ด ๋ค์์คํ์ด์ค๋ฅผ ํ ๋นํ์ต๋๋ค.
$dumper = new PhpDumper($containerBuilder);
file_put_contents(
self::$cacheFile,
$dumper->dump(
// Save under own namespace to avoid conflicts
array('namespace' => 'PoPContainer')
)
);ํจํค์ง์ ๋ํด, ์ผ๋ถ๋ -wp๋ก ๋๋๋ ๊ฒ(์: pop-schema/users-wp)์ด ์๊ณ ๊ทธ๋ ์ง ์์ ๊ฒ(์: graphql-by-pop/graphql-server)๋ ์๋ค๋ ๊ฒ์ ๋์น์ฑ์
จ์ ๊ฒ์
๋๋ค. ๋ค, ๋ง์ต๋๋ค. ์ ์๋ WordPress ์ฝ๋๋ฅผ ํฌํจํ๊ณ ์ธ๋ถ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋ํ ์ฐธ์กฐ๊ฐ ์์ผ๋ฉฐ, ํ์๋ ์ธ๋ถ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋ํ ์ฐธ์กฐ๋ฅผ ํฌํจํ ์ ์์ง๋ง WordPress ์ฝ๋๋ ์ ํ ํฌํจํ์ง ์์ต๋๋ค.
๊ทธ๋ฐ ๋ค์, WordPress ํจํค์ง์ ์ค์ฝํ์ ๊ฑด๋๋๋๋ค.
return [
'finders' => [
// Scope packages under vendor/, excluding local WordPress packages
Finder::create()
->files()
->notPath([
// Exclude libraries ending in "-wp"
'#getpop/[a-zA-Z0-9_-]*-wp/#',
'#pop-schema/[a-zA-Z0-9_-]*-wp/#',
'#graphql-by-pop/[a-zA-Z0-9_-]*-wp/#',
])
->in('vendor')
]
];WordPress ํจํค์ง๊ฐ ์ธ๋ถ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฐธ์กฐํด์ผ ํ๋๋ฐ ๋ค๋ฅธ ํจํค์ง๋ก ์ถ์ถํ ์ ์๋ ๊ฒฝ์ฐ์๋ ์ด๋ป๊ฒ ํ ๊น์? ์๋ฅผ ๋ค์ด, ์ ํจํค์ง getpop/routing-wp๋ brain/cortex์ ์์กดํ๋ฉฐ, ์ด๊ฒ์ ํผํ ์ ์์ต๋๋ค.
getpop/routing-wp๋ WordPress ์ฝ๋๋ฅผ ํฌํจํ๋ฏ๋ก ํจํค์ง ์ ์ฒด๋ฅผ ์ค์ฝํํ ์ ์์ต๋๋ค. ๋์ , ํด๋น ์ฐธ์กฐ๊ฐ ์๋ ํ์ผ์ ์๋ณํ๊ณ ๊ทธ ํ์ผ๋ค์ WordPress ์ฝ๋๊ฐ ํฌํจ๋์ง ์๋๋ก ํฉ๋๋ค. ๊ทธ๋ฌ๋ฉด ๊ทธ ํ์ผ๋ค๋ง ์ค์ฝํํ ์ ์์ต๋๋ค.
์ด ๊ฒฝ์ฐ, Cortex/Brain์ ๋ํ ์ฐธ์กฐ๋ 2๊ฐ์ ํ์ผ์์ ์ด๋ฃจ์ด์ง๋ฉฐ, layers/Engine/packages/routing-wp/src/Hooks/SetupCortexHookSet.php๊ฐ ํฌํจ๋ฉ๋๋ค.
namespace PoP\RoutingWP\Hooks;
use PoP\Hooks\AbstractHookSet;
use Brain\Cortex\Route\RouteCollectionInterface;
use Brain\Cortex\Route\RouteInterface;
use Brain\Cortex\Route\QueryRoute;
use PoP\RoutingWP\WPQueries;
use PoP\Routing\Facades\RoutingManagerFacade;
class SetupCortexHookSet extends AbstractHookSet
{
protected function init()
{
$this->hooksAPI->addAction(
'cortex.routes',
[$this, 'setupCortex'],
1
);
}
/**
* @param RouteCollectionInterface<RouteInterface> $routes
*/
public function setupCortex(RouteCollectionInterface $routes): void
{
$routingManager = RoutingManagerFacade::getInstance();
foreach ($routingManager->getRoutes() as $route) {
$routes->addRoute(new QueryRoute(
$route,
function (array $matches) {
return WPQueries::STANDARD_NATURE;
}
));
}
}
}์ฌ๊ธฐ์ ์ด์ํ ์ ์ ๋์น์ฑ์
จ๋์? ์ด๊ฒ์ ํ
์ ๊ตฌํ์ด์ง๋ง add_action์ด ํธ์ถ๋์ง ์์ต๋๋ค. ์ฌ๊ธฐ์ WordPress ์ฝ๋๋ฅผ ํฌํจํ ์ ์๊ธฐ ๋๋ฌธ์
๋๋ค. ๋์ , ์๋น์ค HooksAPIInterface์ ํจ์ addAction์ ํธ์ถํ๋ฉฐ, ์ด ์๋น์ค๋ ํจํค์ง getpop/hooks-wp์ ํด๋์ค HooksAPI์ ์ํด ๊ตฌํ๋์ด ์์ผ๋ฉฐ, ๊ฑฐ๊ธฐ์๋ WordPress ์ฝ๋๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
namespace PoP\HooksWP;
use PoP\Hooks\HooksAPIInterface;
class HooksAPI implements HooksAPIInterface
{
public function addAction(string $tag, callable $function_to_add, int $priority = 10, int $accepted_args = 1): void
{
add_action($tag, $function_to_add, $priority, $accepted_args);
}
}์ฝ๋๊ฐ ๊น๋ํ๊ฒ ๋ถ๋ฆฌ๋์์ผ๋ฏ๋ก, ์ธ๋ถ ์์กด์ฑ์ ์ฐธ์กฐํ๋ 2๊ฐ์ ํ์ผ์ ์ค์ฝํํ ์ ์์ต๋๋ค.
return [
'finders' => [
Finder::create()->append([
'vendor/getpop/routing-wp/src/Component.php',
'vendor/getpop/routing-wp/src/Hooks/SetupCortexHookSet.php',
])
]
];์์ ์ค์ฝํ ์ค์ ์๋ ๋ช ์๊ฐ์ด ๊ฑธ๋ ธ์ง๋ง, 2๊ฐ์๊ฐ์ ์์ ํ์๋ค๊ณ ์ธ๊ธํ์ต๋๋ค. ์ด ์์๊ฐ ๊ทธ ์๋ฏธ๋ฅผ ์ ๋ณด์ฌ์ค๋๋ค. ์ค์ ์์ ์ ์ฝ๋๋ฒ ์ด์ค๋ฅผ 2๊ฐ์ ์ธํธ๋ก ๊น๋ํ๊ฒ ๋๋๋ ๊ฒ์ ์์ต๋๋ค.
์ ๊ฒฝ์ฐ, ์์
์ 2๊ฐ์์ด ๊ฑธ๋ฆฐ ๊ฒ์ ์ธ๋ถ ์์ค์ด ๊ทน๋จ์ ์ด์๊ธฐ ๋๋ฌธ์
๋๋ค. ํ๋ฌ๊ทธ์ธ์ 125๊ฐ์ ํจํค์ง๋ก ๊ตฌ์ฑ๋์์ต๋๋ค! ํ์ง๋ง ์ด๊ฒ์ ์์ธ์ ์ธ ๊ฒฝ์ฐ๋ก, ํ๋ฌ๊ทธ์ธ์ ๊ธฐ๋ฐ ์๋ฒ๋ฅผ CMS ๋น์ข
์์ ์ผ๋ก ๋ง๋ค์ด ํด๋นํ๋ -wp ํจํค์ง๋ฅผ ์ฌ๊ตฌํํ๋ ๊ฒ๋ง์ผ๋ก ๋ค๋ฅธ CMS/ํ๋ ์์ํฌ์ ๊ตฌํ์ ์ง์ํ๋ ค๋ ๋ชฉํ๊ฐ ์์๊ธฐ ๋๋ฌธ์
๋๋ค.
(์ด ์ ๋ต์ ๋ํด์๋ Abstracting WordPress Code To Reuse With Other CMSs: Concepts์ Implementation ๊ธฐ์ฌ์์ ์์ธํ ์ค๋ช ํ์ต๋๋ค.)
ํ์คํ ์๋นํ ์์ ์ด์ง๋ง, ์ฝ๋์ ๊น๋ํจ์ด ํฅ์๋์ด ๊ทธ๋งํ ๊ฐ์น๊ฐ ์์ต๋๋ค. ๊ทธ๋ฆฌ๊ณ ํ๋ฌ๊ทธ์ธ ์ค์ฝํ๋ฟ๋ง ์๋๋ผ(์ด๊ฒ์ ์ ์๊ฒ ์์ ํ ๋๋ผ์ด ์ผ์ด์๊ณ , ์์์น ๋ชปํ ํ๋ณต์ ์์ง๋ ๊ธฐ๋ปํ๊ณ ์์ต๋๋ค), ์๋ฅผ ๋ค์ด PHPStan๊ณผ PHPUnit์ WordPress ์ฝ๋์ ๋น-WordPress ์ฝ๋์ ๋ณ๋๋ก ์คํํ์ฌ ๋ง์ ๊ณจ์น๊ฑฐ๋ฆฌ๋ฅผ ํผํ ์ ์์ต๋๋ค.
์ฝ๋๋ฒ ์ด์ค๊ฐ ์ ๋ฆฌ๋๋ฉด, ์ธ์์ ๊ฐ์๊ธฐ ํจ์ฌ ๋ ๋์ ๊ณณ์ด ๋ฉ๋๋ค.
ํ ์คํธ
๊ทธ๋ ๋ค๋ฉด, ์ด๊ฒ์ ์ด๋ป๊ฒ ํ ์คํธํ ๊น์?
์ ๊ฐ ์๊ฐํด๋ธ ํด๊ฒฐ์ฑ ์ PHP ์ฝ๋๋ฅผ ๊ฐ๋ฐ์ฉ PHP 7.4์์ ํ๋ก๋์ ์ฉ 7.1๋ก ๋ค์ด๊ทธ๋ ์ด๋ํ๋ ๋ฐ ์ฌ์ฉํ๋ ๊ฒ๊ณผ ๋์ผํ ๋๊ตฌ Rector๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ ๋๋ค.
์์ด๋์ด๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
- ํ๋ฌ๊ทธ์ธ์ ์ค์ฝํํ๋ค
- ์ด๋ค ๊ท์น์ด๋ ์ ์ฉํ์ฌ Rector๋ก ๋ถ์ํ๋ค(์ด๋ค ๊ท์น์ด๋ ์๊ด์์ต๋๋ค)
์ค์ฝํ ์ค์ ๋ฌด์ธ๊ฐ ์๋ชป๋์๋ค๋ฉด, Rector๋ ์ผ๋ถ ํด๋์ค๋ฅผ ๋ก๋ํ ์ ์์ด ์ค๋ฅ๋ฅผ ๋ฐ์์ํต๋๋ค. ์๋ฅผ ๋ค์ด, ํด๋์ค Brain\Cortex๊ฐ PrefixedByPoP\Brain\Cortex๋ก ์ค์ฝํ๋์๋๋ฐ, ์ผ๋ถ ์ฐธ์กฐ๊ฐ ์ฌ์ ํ Brain\Cortex๋ก ๋จ์ ์๋ค๋ฉด ์ด ํด๋์ค์ ์๋ ๋ก๋ฉ์ด ์คํจํฉ๋๋ค.
์ด๊ฒ์ด ํ
์คํธ์ฉ GitHub Action์
๋๋ค(working-directory๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ ๋ชจ๋
ธ๋ฆฌํฌ์ ๋ฃจํธ์์ ์์
ํ์ง๋ง ์ค์ฝํ์ ํ๋ฌ๊ทธ์ธ ํด๋์์ ์ด๋ฃจ์ด์ง๊ธฐ ๋๋ฌธ์
๋๋ค).
name: Scope Gato GraphQL tests
on:
push:
branches:
- master
pull_request: null
env:
COMPOSER_ROOT_VERSION: "dev-master"
jobs:
main:
defaults:
run:
working-directory: layers/GraphQLAPIForWP/plugins/graphql-api-for-wp
name: Scope the plugin code via PHP-Scoper, and execute tests
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Set-up PHP
uses: shivammathur/setup-php@v2
with:
php-version: 7.4
coverage: none
env:
COMPOSER_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Install root dependencies
uses: "ramsey/composer-install@v1"
- name: Install plugin dependencies for PROD
run: composer install --no-dev --no-progress --no-interaction --ansi
- name: Install PHP-Scoper
run: |
composer global config minimum-stability dev
composer global config prefer-stable true
composer global require humbug/php-scoper
# The scoped results correspond to vendor/, so must generate them in such folder
- name: Scope plugin into separate folder
run: php-scoper add-prefix --output-dir ../../../../build-prefixed/vendor --ansi
- name: Copy scoped code back into plugin
run: rsync -av build-prefixed/ layers/GraphQLAPIForWP/plugins/graphql-api-for-wp/ --quiet
working-directory: .
- name: Regenerate autoloader
run: composer dumpautoload --optimize --classmap-authoritative --ansi
- name: Run Rector on the scoped code
run: vendor/bin/rector process --config=layers/GraphQLAPIForWP/plugins/graphql-api-for-wp/rector-test-scoping.php --ansi
working-directory: .
๊ทธ๋ฆฌ๊ณ ์ด๊ฒ์ด ์ Rector ์ค์ ์ ๋๋ค.
use Rector\CodeQuality\Rector\LogicalAnd\AndAssignsToSeparateLinesRector;
use Rector\Core\Configuration\Option;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
return static function (ContainerConfigurator $containerConfigurator): void {
$services = $containerConfigurator->services();
$services->set(AndAssignsToSeparateLinesRector::class);
$parameters->set(Option::AUTO_IMPORT_NAMES, true);
$parameters->set(Option::AUTOLOAD_PATHS, [
__DIR__ . '/vendor/scoper-autoload.php',
__DIR__ . '/vendor/erusev/parsedown/Parsedown.php',
__DIR__ . '/vendor/jrfnl/php-cast-to-type/cast-to-type.php',
__DIR__ . '/vendor/jrfnl/php-cast-to-type/class.cast-to-type.php',
]);
// files to rector
$parameters->set(Option::PATHS, [
__DIR__ . '/vendor',
]);
// files to skip
$parameters->set(Option::SKIP, [
// Exclude tests
'*/tests/*',
__DIR__ . '/vendor/nikic/fast-route/test/*',
__DIR__ . '/vendor/psr/log/Psr/Log/Test/*',
__DIR__ . '/vendor/symfony/service-contracts/Test/*',
]);
};erusev/parsedown/Parsedown.php์ ๊ฐ์ ์ผ๋ถ ์์กด์ฑ ํ์ผ์ Option::AUTOLOAD_PATHS์ ์ถ๊ฐํด์ผ ํจ์ ์ ์ ์์ต๋๋ค. ์ด๊ฒ์ ํจํค์ง์ composer.json ์ค์ฝํ์ด 100% ์ ๋ขฐํ ์ ์์ด ์๋ ๋ก๋ฉ์ด ์คํจํ ์ ์๊ธฐ ๋๋ฌธ์
๋๋ค.
๊ทธ๋ฐ ๊ฒฝ์ฐ, Rector๋ ์ด๋ค ํด๋์ค์ ์๋ ๋ก๋ฉ์ด ์คํจํ๋ค๊ณ ๊ฒฝ๊ณ ํฉ๋๋ค. ๊ทธ๋ก๋ถํฐ ํด๋น ํ์ผ์ ์๋ณํ๊ณ ์๋ ๋ก๋ฉ ๊ฒฝ๋ก์ ์๋์ผ๋ก ์ถ๊ฐํฉ๋๋ค.
๊ฒฐ๊ณผ ํ์ธ
์ด๊ฒ์ด ํ๋ฌ๊ทธ์ธ์ ์์ค ์ฝ๋์ด๋ฉฐ, ์ด๊ฒ์ด ์ค์ฝํ๋(PHP 7.1๋ก ๋ค์ด๊ทธ๋ ์ด๋๋) ๋ฒ์ ์ ๋๋ค.
7๊ฐ์ง ์ฐจ์ด์ ์ ์ฐพ์๋ณด์ธ์ ๐. (ํํธ๋ฅผ ๋๋ฆฌ๊ฒ ์ต๋๋ค. PrefixedByPoP๋ฅผ ๊ฒ์ํด ๋ณด์ธ์.)
๊ทธ๋ฆฌ๊ณ ์ด๊ฒ์ด ์ต์ข
graphql-api.zip ํ๋ฌ๊ทธ์ธ ํ์ผ์
๋๋ค. ์ฌ์ดํธ์ ์ค์นํ ์ค๋น๊ฐ ๋์ด ์์ต๋๋ค.
์ด์์ ๋๋ค. ๋์์ด ๋์ จ์ผ๋ฉด ํฉ๋๋ค ๐๐ช๐