GraphQL
GraphQL์ ํ์ด์ค๋ถ์์ ๋ง๋ ์คํ ์์ค ์ฟผ๋ฆฌ ์ธ์ด์ด๋ค. Graph + Query Language์ ์ค์๋ง๋ก Server API๋ฅผ ํตํด ์ ๋ณด๋ฅผ ์ฃผ๊ณ ๋ฐ๊ธฐ ์ํด ์ฌ์ฉํ๋ Query Language๋ฅผ ๋ปํ๋ค. ์ฝ๊ฒ ๋งํด API๋ฅผ ์ํ ์ฟผ๋ฆฌ ์ธ์ด๋ก, 2016๋ ์ฒ์ ๋ฑ์ฅํด ํ์ฌ๊น์ง ์ธ์ง๋ ๋ฐ ๋ง์กฑ ๋ถ๋ถ์์ ๋์ ๋น์จ์ ์ฐจ์งํ๊ณ ์๋ค.
Graph๋ฅผ ์ฌ์ฉํ๋ ์ด์
GraphQL์ ๊ทธ๋ํ๋ก ์๊ฐํ๋ค๋ ์์ด๋์ด์์ ์ถ๋ฐํ๋ค. ๊ทธ๋ํ๋ผ๋ ์๋ฃ๊ตฌ์กฐ๋ ์ธ๊ฐ์ ๋ ๊ตฌ์กฐ ๋ฐ ์ธ์ด์ ์ธ ์ค๋ช ๊ณผ ๋น์ทํ๊ธฐ ๋๋ฌธ์ ์ค์ ํ์ค ์ธ๊ณ์ ๋ง์ ํ์๋ค์ ๋ชจ๋ธ๋งํ ์ ์๋ ๊ฐ๋ ฅํ ๋๊ตฌ์ด๋ค. ๊ทธ๋ํ ์๋ฃ ๊ตฌ์กฐ๋ฅผ ์ดํด๋ณด๋ฉด ํน์ ๊ฐ๋ ์ ํ์ตํ๊ณ ์ฐ๊ด์ํฌ๋ ์์ฐ์ค๋ฝ๊ฒ ์ฌ์ฉํ๋ ๋ง์ธ๋๋งต๊ณผ ์ ์ฌํ ๋ฐ์ดํฐ๊ตฌ์กฐ์์ ์ ์ ์๋ค.
๊ทธ๋ํ๋ ์ฌ๋ฌ ๊ฐ์ ์ ๋ค์ด ์๋ก ๋ณต์กํ๊ฒ ์ฐ๊ฒฐ๋์ด ์๋ ๊ด๊ณ๋ฅผ ํํํ ์๋ฃ๊ตฌ์กฐ๋ฅผ ๋ปํ๋ค. ๊ฐ ๋ ธ๋(์ ์ )๊ฐ์ ๊ด๊ณ๊ฐ ์ง์ ์ ์ด๋ผ๋ฉด ๊ฐ์ ์ผ๋ก ์ฐ๊ฒฐ๋๊ณ , ๊ฐ์ ์ ์ธ ๊ด๊ณ๋ผ๋ฉด ๋ช๊ฐ์ ๋ ธ๋์ ์ ์ ๊ฑธ์ณ ์ด์ด์ง๋ค. ๋ํ ๊ฐ ๋ ธ๋๊ฐ์ ๊ฐ์ ์ ํตํด ํน์ ํ ์์์ ๋ฐ๋ผ ๊ทธ๋ํ๋ฅผ ์ฌ๊ท์ ์ผ๋ก ํ์ํ ์๋ ์๋ค.
GraphQL์์๋ ๋ชจ๋ ๋ฐ์ดํฐ๊ฐ ๊ทธ๋ํ ํํ๋ก ์ฐ๊ฒฐ๋์ด ์๋ค๊ณ ์ ์ ํ๋ค. ์ผ๋์ผ๋ก ์ฐ๊ฒฐ๋์ด๋, ์ฌ๋ฌ ๊ณ์ธต(ํธ๋ฆฌ ๊ตฌ์กฐ)์ผ๋ก ์ด๋ฃจ์ด์ ธ๋ ๋ ธ๋์ ๋ ธ๋๋ฅผ ์ฐ๊ฒฐํ๋ ๊ฐ์ ์ผ๋ก ๊ตฌ์ฑ๋์๊ธฐ ๋๋ฌธ์ ๋ชจ๋ ๊ทธ๋ํ์ด๋ค. ๋จ์ง ๊ทธ ๊ทธ๋ํ๋ฅผ ๋๊ตฌ์ ์ ์ฅ์์ ์ ๋ ฌํ๋๋, ์ฆ ํด๋ผ์ด์ธํธ๊ฐ ์ด๋ค ๋ฐ์ดํฐ๋ฅผ ํ์๋ก ํ๋๋์ ๋ฐ๋ผ ํธ๋ฆฌ ๊ตฌ์กฐ๋ฅผ ์ด๋ฃฐ ์ ์๋ ๊ฒ์ด๋ค.
์ด๋ฅผ ํตํด GraphQL์ ํด๋ผ์ด์ธํธ์ ์์ฒญ์ ๋ฐ๋ผ ์ ์ฐํ๊ฒ ํธ๋ฆฌ ๊ตฌ์กฐ์ JSON ๋ฐ์ดํฐ๋ฅผ ์๋ต์ผ๋ก ์ ์กํ ์ ์๋ค. ๋ค์ ๋งํด GraphQL์ REST API ๋ฐฉ์์ ๊ณ ์ ๋ ์์์ด ์๋ ํด๋ผ์ด์ธํธ ์์ฒญ์ ๋ฐ๋ผ ์ ์ฐํ๊ฒ ์์์ ๊ฐ์ ธ์ฌ ์ ์๋ค๋ ์ด์ ์ ๊ฐ๋๋ค.
GraphQL๋ก ๊ทธ๋ํ ์ํ
GraqhQL๋ก ๊ทธ๋ํ๋ฅผ ์ํํ๊ธฐ ์ํด ๋์๊ด์ ๋์ ๋ชฉ๋ก ์์คํ ์ ๊ตฌ์ถํ๋ค๊ณ ๊ฐ์ ํ๋ค๋ฉด, ํ๋์ ๋์ ๋ชฉ๋ก์๋ ๋ง์ ์ฑ ๊ณผ ์ ์๊ฐ ์์ ๊ฒ์ด๋ฉฐ ๊ฐ ์ฑ ์๋ ์ต์ ํ ๋ช ์ ์ ์, ๊ทธ๋ฆฌ๊ณ ์ต์ํ ํ ๊ถ์ ์ฑ ์ ๊ฐ์ด ์ด ๊ณต๋์ ์๋ ์์ ๊ฒ์ด๋ค.
์์ ๊ทธ๋ํ๋ ๋ฐฉ๊ธ์ ๊ฐ์ ์ ๊ทธ๋ํ ํํ๋ก ์๊ฐํํ ๊ฒ์ด๋ค. ์ด๋ ๊ฒ ๊ทธ๋ํ๋ก ํํํ ์ ์๋ค๋ฉด ์ฐ๋ฆฌ๊ฐ ๊ฐ์ง๊ณ ์๋ ๋ฐ์ดํฐ์ ์กฐ๊ฐ๋ค์ด๋ ๋ํ๋ด๊ณ ์ ํ๋ ์ํฐํฐ(์ฑ , ์ ์) ๊ฐ์ ๊ด๊ณ๋ฅผ ๋ํ๋ผ ์ ์๊ณ , GraphQL์ ์ฌ์ฉํด ํธ๋ฆฌ๋ฅผ ์ถ์ถํ ์ ์๋ค.
๊ทธ๋ํ์์ ํธ๋ฆฌ๋ฅผ ์ถ์ถํ๋ ๋ฐฉ๋ฒ
๊ธฐ๋ณธ์ ์ผ๋ก ํธ๋ฆฌ๋ ๋ฐฉํฅ์ฑ์ ์กด์ฌํ๋ ์ฌ์ดํด์ ์กด์ฌํ์ง ์๋ ๋น์ํ ๊ทธ๋ํ์ด๋ค. ๋ฃจํธ์ ๋ชจ์๋ฆฌ๋ฅผ ํตํด ๋ ธ๋๋ฅผ ๋ฐ๋ผ ์ํํ ์๋ ์์ง๋ง ๋์ผํ ๋ ธ๋๋ก ๋์์ฌ ์ ์๋ ์์ฑ์ ๊ฐ์ง๊ณ ์๋ค. GraphQL ์ฟผ๋ฆฌ์ ์์ ๊ทธ๋ํ์์ ํธ๋ฆฌ๋ฅผ ์ถ์ถํ๋ค๋ฉด ์คํํ ์ ์๋ ์ฟผ๋ฆฌ๋ ์๋์ ๊ฐ๋ค.
query {
์ฑ
(ISBN์ด "9780674430006") { // ํ ๊ถ์ ์ฑ
๋ง ๊ฒ์ํ๊ธฐ ์ํ ํน์ ์กฐ๊ฑด
์ฑ
์ด๋ฆ
์ ์ {
์ด๋ฆ
}
}
}
์์ ๋ฐฉ์์ผ๋ก ์๋ฒ์ ์์ฒญ์ ๋ณด๋ด๊ณ ์๋ฒ๊ฐ ํด๋น ์์ฒญ์ ํด๊ฒฐํ๋ค๋ฉด ๋์์จ ์ฟผ๋ฆฌ๋ ์๋์ ๊ฐ์ ๊ฒ์ด๋ค.
{
์ฑ
: {
์ฑ
์ด๋ฆ : "GraphQL์ ์ด๋ ต์ง ์๋ค",
์ ์ : [
{ ์ด๋ฆ : "๊น์ฝ๋ฉ"},
{ ์ด๋ฆ : "๋ฐํด์ปค"},
]
}
}
์ด ์์์๋ ISBN ๋ฒํธ๋ฅผ ์ฌ์ฉํด ์ ํํ ์ฑ
๋
ธ๋์์ ์์ํ๋ค. ๊ทธ ๋ค์ GraphQL์ ์ค์ ๋ ๊ฐ ํ๋๋ก ํ์๋ ๊ฐ์ ์ ๋ฐ๋ผ ๊ทธ๋ํ๋ฅผ ํ์ํ๊ธฐ ์์ํ๋ค. ์ฆ, ์ฟผ๋ฆฌ ๋ด ์ค์ฒฉ๋ ์ฑ
์ด๋ฆ
ํ๋๋ฅผ ํตํด ์ฑ
์ ์ ๋ชฉ์ด ์๋ ๋
ธ๋๋ก ์ด๋ํ๋ค. ๊ทธ๋ฌ๋ฉด์ ์ ์
๋ก ๋ ์ด๋ธ์ด ์ง์ ๋ ์ฑ
์ ๊ฐ์ ์ ๋ฐ๋ผ ์ ์
๋
ธ๋๋ฅผ ๊ฐ์ ธ์ค๊ณ , ๊ฐ ์ ์์ ์ด๋ฆ
์ ์ป์ด์ค๋ ๊ฒ์ด๋ค. ์ด๋ฅผ ํธ๋ฆฌ ๊ตฌ์กฐ๋ก ํํํ๋ฉด ์๋์ ๊ฐ๋ค.
์ด๋ ๊ฒ GraphQL์ ์ค์ฒฉ๋ ํ๋๋ฅผ ๊ณ์ธต ๊ตฌ์กฐ๋ก ํํํ๋ฉด ์ด๋ ๊ฒ ํธ๋ฆฌ ๊ตฌ์กฐ๋ก๋ ํํํ ์ ์๊ฒ ๋๋ค. ์ฆ, GraphQL์ ํธ๋ฆฌ ๊ตฌ์กฐ๋ก ์ฟผ๋ฆฌ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ๊ธฐ ์ํด ๊ทธ๋ํ๋ฅผ ํ์ํ๋ ์ฟผ๋ฆฌ ์ธ์ด๋ผ ๋ณผ ์ ์๋ค.
GraphQL์ ํน์ง
- HTTP๋ฅผ ํตํด API ์๋ฒ๋ก ์์ฒญ์ ๋ณด๋ด๊ณ ์๋ต์ ๋ฐ๋๋ค.
- ์๋ต์ ๋ฐ์ ์, ๋ฐ์ดํฐ ๊ฒฐ๊ณผ๋ฅผ JSON ํ์์ผ๋ก ๋ฐ๋๋ค.
- ์๋ฒ ๊ฐ๋ฐ์๊ฐ ์์ฑํ ๊ฐ ํ๋์ ๋์ํ๋ resolver ํจ์๋ก ๊ฐ ํ๋์ ๋ฐ์ดํฐ๋ฅผ ์กฐํํ ์ ์๋ค.
- GraphQL ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ์กฐํ ๋์ schema๊ฐ ์ ํจํ์ง ๊ฒ์ฌํ๋ค.
GraphQL vs. REST API
GraphQL์ด ์๊ธฐ๊ธฐ ์ด์ ์ API๋ฅผ ์ํด ์ด๋ฏธ REST API๋ผ๋ ๋ฐฉ๋ฒ๋ก ์ด ์กด์ฌํ๋ค. ๊ทธ๋ผ์๋ ๋ถ๊ตฌํ๊ณ GraphQL์ด ์๊ฒจ๋ ์ด์ ๋ REST API์ ํ๊ณ์ ์ด ์กด์ฌํ๊ธฐ ๋๋ฌธ์ด๋ค.
REST API์ ํ๊ณ
๊ฐ์์ ๋ธ๋ก๊ทธ ์ฑ์ ๊ตฌํํ๋ค๊ณ ๊ฐ์ ํด๋ณด์. ์์ ํ๋ฉด์ ๊ฐ์ง ์ฑ์ ๊ตฌํํ๊ธฐ ์ํด์๋ ๋ค์์ ๋ฐ์ดํฐ๊ฐ ํ์ํ๋ค.
- ์ฌ์ฉ์์ ์ด๋ฆ
- ์ฌ์ฉ์์ ํฌ์คํ ๋ชฉ๋ก
- ์ฌ์ฉ์์ ํ๋ก์ ๋ชฉ๋ก
์ด๋ฐ ๋ฐ์ดํฐ๋ฅผ REST API๋ก ๋ฐ์์จ๋ค๋ฉด ์๋์ ๊ฐ์ ๋ฌธ์ ์ ์ด ์กด์ฌํ๋ค.
- Overfetch : ํ์์๋ ๋ฐ์ดํฐ๊น์ง ์ ๊ณตํจ
๋ธ๋ก๊ทธ ์ฑ ์์ ์ฒ๋ผ ์ ์ ์ ์ด๋ฆ๋ง ํ์ํ ์ํฉ์์ REST API๋ฅผ ์ฌ์ฉํ๋ค๋ฉด, ์๋ต ๋ฐ์ดํฐ์๋ ์ ์ ์ ์ฃผ์, ์์ผ ๋ฑ๊ณผ ๊ฐ์ด ์ค์ ํด๋ผ์ด์ธํธ์๋ ํ์์๋ ์ ๋ณด๊ฐ ํฌํจ๋์ด ์์ ์ ์๋ค.
- Underfetch : Endpoint๊ฐ ํ์ํ ์ ๋ณด๋ฅผ ์ถฉ๋ถํ ์ ๊ณตํ์ง ๋ชปํจ
Underfetch์ ๊ฒฝ์ฐ ํด๋ผ์ด์ธํธ๋ ํ์ํ ์ ๋ณด๋ฅผ ๋ชจ๋ ํ๋ณดํ๊ธฐ ์ํด ์ถ๊ฐ์ ์ธ ์์ฒญ์ ๋ณด๋ด์ผ๋ง ํ๋ค. ๋ธ๋ก๊ทธ ์ฑ ์์ ํ๋ฉด์ ๊ตฌํํ๊ธฐ ์ํด์ ์ ์ ์ ๋ณด ๋ฟ๋ง ์๋๋ผ ์ ์ ์ ํฌ์คํ ๋ชฉ๋ก ๋ฐ ์ ์ ๊ฐ ๋ณด์ ํ ํ๋ก์๊น์ง ํ์ํ๋ค. ์ด๋ ํ์ํ ์ ๋ณด๋ฅผ ๋ชจ๋ ๊ฐ์ ธ์ค๋ ค๋ฉด REST API์์๋ ๊ฐ๊ฐ์ ์์์ ๋ฐ๋ผ ์๋ํฌ์ธํธ๋ฅผ ๊ตฌ๋ถํ๊ธฐ ๋๋ฌธ์ 3๊ฐ์ง ์๋ํฌ์ธํธ์ ์์ฒญ์ ๋ณด๋ด์ผ ํ๋ค.
- ํด๋ผ์ด์ธํธ ๊ตฌ์กฐ ๋ณ๊ฒฝ ์ ์๋ํฌ์ธํธ ๋ณ๊ฒฝ ๋๋ ๋ฐ์ดํฐ ์์ ์ด ํ์ํจ
REST API์์๋ ์์์ ํฌ๊ธฐ์ ํํ๋ฅผ ์๋ฒ์์ ๊ฒฐ์ ํ๊ธฐ ๋๋ฌธ์ ํด๋ผ์ด์ธํธ๊ฐ ์ง์ ๋ฐ์ดํฐ์ ํํ๋ฅผ ๊ฒฐ์ ํ ์ ์๋ค. ์ด๋ก ์ธํด ๋ง์ฝ ํด๋ผ์ด์ธํธ์์ ํ์ํ ๋ฐ์ดํฐ์ ๋ด์ฉ์ด ๋ณํ ๊ฒฝ์ฐ ๋ค๋ฅธ endpoint๋ฅผ ํตํด ๋ณ๊ฒฝ๋ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ค๊ฑฐ๋ ์์ ํด์ผ ํ๋ค.
REST API์ GraphQL์ ๋ค๋ฅธ ์
REST API | GraphQL |
---|---|
Resource์ ๋ํ ํํ ์ ์์ ๋ฐ์ดํฐ ์์ฒญ ๋ฐฉ๋ฒ์ด ์ฐ๊ฒฐ๋์ด ์๋ค. | Resource์ ๋ํ ํํ ์ ์์ ๋ฐ์ดํฐ ์์ฒญ์ด ์์ ํ ๋ถ๋ฆฌ๋์ด ์๋ค. |
Resource์ ํฌ๊ธฐ์ ํํ๋ฅผ ์๋ฒ์์ ๊ฒฐ์ ํ๋ค. | Resource์ ๋ํ ์ ๋ณด๋ง ์ ์ํ๊ณ , ํ์ํ ํฌ๊ธฐ์ ํํ๋ ํด๋ผ์ด์ธํธ ๋จ์์ ์์ฒญ ์ ๊ฒฐ์ ํ๋ค. |
URI๊ฐ Resource๋ฅผ ๋ํ๋ด๊ณ Method๊ฐ ์์ ์ ์ ํ์ ๋ํ๋ธ๋ค. | GraphQL Schema๊ฐ Resource๋ฅผ ๋ํ๋ด๊ณ Query, Mutation ํ์ ์ด ์์ ์ ์ ํ์ ๋ํ๋ธ๋ค. |
์ฌ๋ฌ Resource์ ์ ๊ทผํ๊ณ ์ ํ ๋ ์ฌ๋ฌ ๋ฒ์ ์์ฒญ์ด ํ์ํ๋ค. | ํ๋ฒ์ ์์ฒญ์์ ์ฌ๋ฌ Resource์ ์ ๊ทผ ๊ฐ๋ฅํ๋ค. |
๊ฐ ์์ฒญ์ ํด๋น ์๋ํฌ์ธํธ์ ์ ์๋ ํธ๋ค๋ง ํจ์๋ฅผ ํธ์ถํ์ฌ ์์ ์ ์ฒ๋ฆฌํ๋ค. | ์์ฒญ ๋ฐ์ ๊ฐ ํ๋์ ๋ํ resolver๋ฅผ ํธ์ถํ์ฌ ์์ ์ ์ฒ๋ฆฌํ๋ค. |
GraphQL์ ์ฅ์
GraphQL์ ๊ฐ์ฅ ํฐ ์ฅ์ ์ ์ ๋ณด๋ฅผ ์ฌ์ฉํ๋ ์ธก์์ ์ํ๋ ๋๋ก ์ ๋ณด๋ฅผ ๊ฐ์ ธ์ฌ ์ ์๊ณ , ๋ณด๋ค ํธํ๊ฒ ์ ๋ณด๋ฅผ ์์ ํ ์ ์๋๋ก ํ๋ ํ์คํ๋ ์ฟผ๋ฆฌ ์ธ์ด๋ผ๋ ์ ์ด๋ค.
- ํ๋์ endpoint ์์ฒญ
/graphql
์ด๋ผ๋ ํ๋์ endpoint ๋ก ์์ฒญ์ ๋ฐ๊ณ ๊ทธ ์์ฒญ์ ๋ฐ๋ผ query , mutation์ resolver ํจ์๋ก ์ ๋ฌํด์ ์์ฒญ์ ์๋ตํ๋ค. ๋ชจ๋ ํด๋ผ์ด์ธํธ ์์ฒญ์POST
๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ค.
- No under & overfetching
์ฌ๋ฌ ๊ฐ์ endpoint ์์ฒญ์ ํ ํ์์์ด ํ๋์ endpoint์์ ์ฟผ๋ฆฌ๋ฅผ ์ด์ฉํด ์ํ๋ ๋ฐ์ดํฐ๋ฅผ ์ ํํ๊ฒ API์ ์์ฒญํ๊ณ ์๋ต์ผ๋ก ๋ฐ์ ์ ์๋ค.
- ๊ฐ๋ ฅํ playground
graphql ์๋ฒ๋ฅผ ์คํํ๋ฉด playground๋ผ๋ GUI(POSTMAN ๊ณผ ๋น์ทํจ)๋ฅผ ์ด์ฉํด resolver ์ schema ๋ฅผ ํ ๋์ ๋ณด๊ณ ํ ์คํธ ํด ๋ณผ ์ ์๋ค.
- ํด๋ผ์ด์ธํธ ๊ตฌ์กฐ ๋ณ๊ฒฝ์๋ ์ง์ฅ์ด ์์
ํด๋ผ์ด์ธํธ ๊ตฌ์กฐ๊ฐ ๋ฐ๋์ด๋ ํ์ํ ๋ฐ์ดํฐ๋ฅผ ๊ฒฐ์ ํ๊ณ ๋ฐ๋ ์ฃผ์ฒด๊ฐ ํด๋ผ์ด์ธํธ์ด๊ธฐ ๋๋ฌธ์ ์๋ฒ์ ์ง์ฅ์ด ์์ต๋๋ค. ํด๋ผ์ด์ธํธ์์๋ ๋ฌด์จ ๋ฐ์ดํฐ๊ฐ ํ์ํ ์ง์ ๋ํด์๋ง ์๊ตฌ์ฌํญ์ ์ฟผ๋ฆฌ๋ก ์์ฑํ๋ฉด ๋ฉ๋๋ค.
GraphQL์ ๋จ์
- REST API์ ์น์ํ ๊ฐ๋ฐ์์ ๊ฒฝ์ฐ GraphQL์ ํ์ตํ๋ ๋ฐ ์๊ฐ์ด ํ์ํ๋ค.
- ์บ์ฑ์ด REST๋ณด๋ค ํจ์ฌ ๋ณต์กํ๋ค.
HTTP์์ ๊ฐ ๋ฉ์๋์ ๋ฐ๋ผ ์บ์ฑ์ด ๊ตฌํ๋์ด ์์ง๋ง, GraphQL์์
POST
๋ฉ์๋๋ง์ ์ด์ฉํด ์์ฒญ์ ๋ณด๋ด๊ธฐ ๋๋ฌธ์ ๊ฐ ๋ฉ์๋์ ๋ฐ๋ฅธ ์บ์ฑ์ ์ง์๋ฐ์ ์ ์๋ค. ์ด๋ฅผ ๋ณด์ํ๊ธฐ ์ํด Apollo ์์ง์ ์บ์ฑ๊ณผ ์์ ์ฟผ๋ฆฌ ๋ฑ์ด ๋ฑ์ฅํ๊ฒ ๋์๋ค.
- ๊ณ ์ ๋ ์์ฒญ๊ณผ ์๋ต๋ง ํ์ํ ๊ฒฝ์ฐ Query๋ก ์ธํด ์์ฒญ์ ํฌ๊ธฐ๊ฐ RESTful API๋ณด๋ค ๋ ์ปค์ง๋ค.
GraphQL์ ๊ตฌ์กฐ
GraphQL Keywords
์๋ฒ๋ก๋ถํฐ ๋ฐ์ดํฐ๋ฅผ ์กฐํ(Read)ํ๋ ๊ฒฝ์ฐ GraphQL์์๋ Query๋ฅผ ์ด์ฉํด ์ํ๋ ๋ฐ์ดํฐ๋ฅผ ์์ฒญํ ์ ์๊ณ , Create, Delete์ ๊ฐ์ด ์ ์ฅ๋ ๋ฐ์ดํฐ๋ฅผ ์์ ํ๋ ๊ฒฝ์ฐ Mutation์ ์ด์ฉํด ์ด๋ฅผ ์ํํ ์ ์๋ค.
์ฌ๊ธฐ์์ ๋ ๋์๊ฐ ๊ตฌ๋ (Subscription)์ด๋ผ๋ ๊ฐ๋ ์ ์ ๊ณตํ์ฌ ์ด๋ฅผ ์ด์ฉํด ์ค์๊ฐ ์ ๋ฐ์ดํธ๋ฅผ ๊ตฌํํ ์ ์๋ค. Subscription์ ์ ํต์ ์ธ Client(์์ฒญ)โServer(์๋ต) ๋ชจ๋ธ์ ๋ฐ๋ฅด๋ Query์ Mutation๊ณผ ๋ฌ๋ฆฌ, ๋ฐํ/๊ตฌ๋ (publish/subscribe) ๋ชจ๋ธ์ ๋ฐ๋ฅธ๋ค. ํด๋ผ์ด์ธํธ๊ฐ ์ด๋ค ์ด๋ฒคํธ๋ฅผ ๊ตฌ๋ ํ๋ฉด, ํด๋ผ์ด์ธํธ๋ ์๋ฒ์ WebSocket์ ๊ธฐ๋ฐ์ผ๋ก ์ง์์ ์ธ ์ฐ๊ฒฐ์ ํ์ฑํ๊ณ ์ ์งํ๊ฒ ๋๋ค. ๊ทธ ํ ํน์ ์ด๋ฒคํธ๊ฐ ๋ฐ์ํ๋ฉด ์๋ฒ๋ ๋์ํ๋ ๋ฐ์ดํฐ๋ฅผ ํด๋ผ์ด์ธํธ์ ํธ์ํด์ค๋ค.
- Query: ์ ์ฅ๋ ๋ฐ์ดํฐ ๊ฐ์ ธ์ค๊ธฐ (REST์ GET๊ณผ ๋น์ทํฉ๋๋ค.)
- Mutation:ย ์ ์ฅ๋ ๋ฐ์ดํฐ ์์ ํ๊ธฐ
- Create: ์๋ก์ด ๋ฐ์ดํฐ ์์ฑ
- Update: ๊ธฐ์กด์ ๋ฐ์ดํฐ ์์
- Delete: ๊ธฐ์กด์ ๋ฐ์ดํฐ ์ญ์
- Subscription: ํน์ ์ด๋ฒคํธ๊ฐ ๋ฐ์ ์ ์๋ฒ๊ฐ ๋์ํ๋ ๋ฐ์ดํฐ๋ฅผ ์ค์๊ฐ์ผ๋ก ํด๋ผ์ด์ธํธ์๊ฒ ์ ์ก
์ฟผ๋ฆฌ(Query, ๋ฐ์ดํฐ ์กฐํ)
ํ๋(field)
๊ฐ๋จํ query๋ฅผ ์คํํ์ ๋ ์ป์ ๊ฐ์ ์๋์ ๊ฐ๋ค.
# ์์ฒญ
# hero์ name์ ์ฟผ๋ฆฌ
{
hero {
name
}
}
// ์๋ต
{
"data": {
"hero": {
"name": "R2-D2"
}
}
}
ํ๋์ name
์ String ํ์
์ ๋ฐํํ๋ค. ์ฟผ๋ฆฌ์ ๊ฒฐ๊ณผ๊ฐ ์ ํํ๊ฒ ๊ฐ์ ๋ชจ์์ ํ๊ณ ์์์ ํ์ธํ ์ ์๋๋ฐ, ์ด ๋ถ๋ถ์ GraphQL์ ์์ด ํ์์ ์ธ ๋ถ๋ถ์ด๋ค. GraphQL์ ์๋ฒ์ ์์ฒญํ์ ๋ ์์ํ๋ ๋๋ก ๋๋ ค๋ฐ๊ณ , ์๋ฒ๋ GraphQL์ ํตํด ํด๋ผ์ด์ธํธ๊ฐ ์๊ตฌํ๋ ํ๋๋ฅผ ์ ํํ ์๊ธฐ ๋๋ฌธ์ด๋ค.
# ์์ฒญ
# ์ํ๋ ํ๋๋ฅผ ์ค์ฒฉํ์ฌ ์ฟผ๋ฆฌ๋ ๊ฐ๋ฅ
{
hero {
name
friends {
name
}
}
}
// ์๋ต
{
"data": {
"hero": {
"name": "R2-D2",
"friends": [
{
"name": "Luke Skywalker"
},
{
"name": "Han Solo"
},
{
"name": "Leia Organa"
}
]
}
}
}
์์ ์์์ freinds
ํ๋๋ ๋ฐฐ์ด์ ๋ฐํํ๋ค. GraphQL ์ฟผ๋ฆฌ๋ ๊ด๋ จ ๊ฐ์ฒด ๋ฐ ํ๋๋ฅผ ์ํํ ์ ์๊ธฐ ๋๋ฌธ์ ๋ค์ํ endpoint๋ฅผ ๋ง๋ค์ด ๊ฐ๊ธฐ ์์ฒญ์ ๋ณด๋ด๋ ๋์ ํด๋ผ์ด์ธํธ๊ฐ ํ๋์ ์์ฒญ์ ๋ณด๋์ผ๋ก์จ ๊ด๋ จ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ฌ ์ ์๋ค.
์ ๋ฌ์ธ์(Arguments)
ํ๋์ ์ธ์๋ฅผ ์ ๋ฌํ๋ ๋ถ๋ถ์ ์ถ๊ฐํ๊ฒ ๋๋ฉด ์ฟผ๋ฆฌ์ ํ๋ ๋ฐ ์ค์ฒฉ๋ ๊ฐ์ฒด๋ค์ ์ ๋ฌํด ์ํ๋ ๋ฐ์ดํฐ๋ง ๋ฐ์์ฌ ์ ์๋ค.
# ์์ฒญ
# id๊ฐ 1000์ธ
# human์ name๊ณผ height๋ฅผ ์ฟผ๋ฆฌ
{
human(id: "1000") {
name
height
}
}
// ์๋ต
{
"data": {
"human": {
"name": "Luke Skywalker",
"height": 1.72
}
}
}
๋ณ๋ช (Aliases)
ํ๋ ์ด๋ฆ์ ์ค๋ณตํด์ ์ฌ์ฉํ ์ ์์ผ๋ฏ๋ก, ํ๋ ์ด๋ฆ์ ์ค๋ณต์ผ๋ก ์ฌ์ฉํด์ ์ฟผ๋ฆฌ๋ฅผ ํด์ผ ํ ๋๋ ๋ณ๋ช ์ ๋ถ์ฌ์ ์ฟผ๋ฆฌ๋ฅผ ํ๋ค.
# ์๋ชป๋ ๋ฐฉ์
{
hero(episode: EMPIRE) {
name
}
hero(episode: JEDI) {
name
}
}
# ๋ณ๋ช
์ ๋ถ์ด๋ฉด ์ฟผ๋ฆฌ ๊ฐ๋ฅ
{
empireHero: hero(episode: EMPIRE) {
name
}
jediHero: hero(episode: JEDI) {
name
}
}
// ์์ฒญ ๊ฒฐ๊ณผ
{
"data": {
"empireHero": {
"name": "Luke Skywalker"
},
"jediHero": {
"name": "R2-D2"
}
}
}
์คํผ๋ ์ด์ ๋ค์(Operation name)
์ค์ ์ฑ์์๋ ์ฟผ๋ฆฌ์ ์ฟผ๋ฆฌ ๋ค์์ ๋ชจ๋ ์๋ตํ์ง ์๊ณ ๋ชจํธํ์ง ์๊ฒ ์์ฑํ๋ ๊ฒ์ด ์ค์ํ๋ค.
query HeroNameAndFriends {
hero {
name
friends {
name
}
}
}
์์ query
๋ ์คํผ๋ ์ด์
ํ์
์ด๋ฉฐ, ์ฌ๊ธฐ์๋ query
๋ฟ๋ง ์๋๋ผ mutation
, subscription
, describes
๋ฑ์ด ์๋ค. ์ฟผ๋ฆฌ๋ฅผ ์ฝ์์ผ๋ก ์์ฑํ์ง ์๋ ํ ์คํผ๋ ์ด์
ํ์
์ ๋ฐ๋์ ํ์ํ๋ฉฐ, ์คํผ๋ ์ด์
๋ค์์ ์์ฑํ ๋๋ ์คํผ๋ ์ด์
ํ์
์ ๋ง๋ ์ด๋ฆ์ผ๋ก ์์ฑํ๋ ๊ฒ์ด ์ข๋ค.
๋ณ์(Variables)
์ค์ ์ฑ์ ์ฌ์ฉํ ๋๋ ๊ณ ์ ๋ ์ธ์๋ฅผ ๋ฐ๋ ๊ฒ ๋ณด๋ค ๋์ ์ผ๋ก ์ธ์๋ฅผ ๋ฐ์ ์ฟผ๋ฆฌํ๋ ๊ฒฝ์ฐ๊ฐ ๋๋ค์์ด๋ค. ๋ณ์๋ ๊ทธ๋ฐ ์ธ์๋ค์ ๋์ ์ผ๋ก ๋ฐ๊ณ ์ถ์ ๋ ์ฌ์ฉํ๋ค. ์คํผ๋ ์ด์
๋ค์ ์์ $๋ณ์ ์ด๋ฆ: ํ์
ํํ
๋ก ์ ์ํ๋ค. ์๋์ ์์์ฒ๋ผ $episode: Episode
์ผ ๋, ๋ค์ !
๊ฐ ๋ถ๋๋ค๋ฉด episode๋ ๋ฐ๋์ Episode์ฌ์ผ ํ๋ค๋ ๋ป์ด๋ค. !
๋ ์ต์
๋ํ ์ฌํญ์ด๋ค.
query HeroNameAndFriends($episode: Episode) {
hero(episode: $episode) {
name
friends {
name
}
}
}
๋ฎคํ ์ด์ (mutation, ๋ฐ์ดํฐ ์์ )
GraphQL์ ๋๊ฐ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ค๋ ๋ฐ์ ์ค์ ์ ๋๊ณ ์์ง๋ง ์๋ฒ์ธก ๋ฐ์ดํฐ๋ฅผ ์์ ํ๊ธฐ๋ ํ๋ค. REST API์์ ๋ฐ์ดํฐ๋ฅผ ์์ ํ ๋ POST
๋ PUT
, PATCH
๋ฅผ ์ฌ์ฉํ๋ ๊ฒ ์ฒ๋ผ GraphQL๋ ์ ์ฌํ๋ค. GraphQL์ mutation
์ด๋ผ๋ ํค์๋๋ฅผ ์ฌ์ฉํ์ฌ ์๋ฒ ์ธก ๋ฐ์ดํฐ๋ฅผ ์์ ํ๋ค.
mutation CreateReviewForEpisode($ep: Episode!, $review: ReviewInput!) {
createReview(episode: $ep, review: $review) {
stars
commentary
}
}
์คํค๋ง/ํ์ (Schema/Type)
GraphQL ์คํค๋ง์ ๊ฐ์ฅ ๊ธฐ๋ณธ์ ์ธ ๊ตฌ์ฑ ์์๋ ์๋น์ค์์ ๊ฐ์ ธ์ฌ ์ ์๋ ๊ฐ์ฒด์ ์ข ๋ฅ, ๊ทธ๋ฆฌ๊ณ ํฌํจํ๋ ํ๋๋ ๋ํ๋ด๋ ๊ฐ์ฒด ์ ํ์ด๋ค.
type Character {
name: String!
appearsIn: [Episode!]!
}
Character
๋ GraphQL ๊ฐ์ฒด ํ์ ์ด๋ฉฐ, ์ฆ ํ๋๊ฐ ์๋ ํ์ ์์ ์๋ฏธํ๋ค. ์คํค๋ง์ ์๋ ๋๋ถ๋ถ์ ํ์ ์ ๊ฐ์ฒด ํ์ ์ด๋ค.
name
ย ๊ณผยappearIn
ย ์ยCharacter
ย ํ์ ์ย ํ๋๋ค. ์ฆยname
ย ๊ณผยappearIn
ย ์ GraphQL ์ฟผ๋ฆฌ์ยCharacter
ย ํ์ ์ด๋์๋ ์ฌ์ฉํ ์ ์๋ ํ๋์ด๋ค.
String
์ ๋ด์ฅ๋ ์ค์นผ๋ผ ํ์ ์ค ํ๋์ด๋ค. ์ด๋ ๋จ์ผ ์ค์นผ๋ผ ๊ฐ์ฒด๋ก ํ์ธ๋๋ ์ ํ์ด๋ฉฐ ์ฟผ๋ฆฌ์์ ํ์ ์ ํ์ ๊ฐ์ง ์ ์์ผ๋ฉฐ, ์ค์นผ๋ผ ํ์ ์๋ ID, Int๋ ์๋ค.
!
๊ฐ ๋ถ๋๋ค๋ฉด ์ด ํ๋๋ nullableํ์ง ์๊ณ ๋ฐ๋์ ๊ฐ์ด ๋ค์ด์จ๋ค๋ ์๋ฏธ์ด๋ค. ์ด๊ฒ์ ๋ถ์ฌ ์ฟผ๋ฆฌํ๋ค๋ฉด ๋ฐ๋์ ๊ฐ์ ๋ฐ์ ์ ์์ ๊ฒ์ด๋ ์์์ ํ ์ ์๋ค.
[ ]
๋ ๋ฐฐ์ด์ ์๋ฏธํ๋ค. ๋ฐฐ์ด์๋!
๊ฐ ๋ถ์ ์ ์๋๋ฐ, ์ฌ๊ธฐ์๋!
์ด ๋ค์ ๋ถ์ด ์์ด null ๊ฐ์ ํ์ฉํ์ง ์์ผ๋ฏ๋ก ํญ์ 0๊ฐ ์ด์์ ์์๋ฅผ ํฌํจํ ๋ฐฐ์ด์ ๊ธฐ๋ํ ์ ์๊ฒ ๋๋ค.
๋ฆฌ์กธ๋ฒ(Resolver)
์์ฒญ์ ๋ํ ์๋ต์ ๊ฒฐ์ ํด์ฃผ๋ ํจ์๋ก์จ GraphQL์ ์ฌ๋ฌ ํ์ ์ค Query, Mutation, Subscription๊ณผ ๊ฐ์ ํ์ ์ ์ค์ ์ผํ๋ ๋ฐฉ์, ์ฆ ๋ก์ง์ ์์ฑํ๋ค. ๋ค์ ๋งํด ์์ ๊ฐ์ด ์คํค๋ง๋ฅผ ์ ์ํ๋ฉด ๊ทธ ์คํค๋ง ํ๋์ ์ฌ์ฉ๋๋ ํจ์์ ์ค์ ํ๋์ Resolver์์ ์ ์ํ๋ค. ๋ณดํต ์ด๋ฐ ํจ์๋ค์ด ๋ชจ์ฌ์๊ธฐ ๋๋ฌธ์ Resolvers๋ผ ๋ถ๋ฅธ๋ค. GraphQL์์๋ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ค๋ ๊ตฌ์ฒด์ ์ธ ๊ณผ์ ์ ์ง์ ๊ตฌํํด์ผ ํ๋๋ฐ ์ด์ ๊ฐ์ ์์ (e.g. ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฟผ๋ฆฌ, ์๊ฒฉ API ์์ฒญ)์ Resolver๊ฐ ๋ด๋นํ๊ฒ ๋๋ค.
const db = require("./../db")
const resolvers = {
Query: { // **Query :** ์ ์ฅ๋ ๋ฐ์ดํฐ ๊ฐ์ ธ์ค๊ธฐ (REST ์ GET ๊ณผ ๋น์ทํฉ๋๋ค.)
getUser: async (_, { email, pw }) => {
db.findOne({
where: { email, pw }
}) ... // ์ค์ ๋๋น์์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ค๋ ๋ก์ง์ ์์ฑํฉ๋๋ค.
...
}
},
Mutation: { // **Mutation :** ์ ์ฅ๋ ๋ฐ์ดํฐ ์์ ํ๊ธฐ ( Create , Update , Delete )
createUser: async (_, { email, pw, name }) => {
...
}
}
Subscription: { // **Subscription :** ์ค์๊ฐ ์
๋ฐ์ดํธ
newUser: async () => {
...
}
}
};
Uploaded by N2T