GraphQL
GraphQL์ 2015๋
์ ํ์ด์ค๋ถ์ ์ํด ๊ณต๊ฐ๋ ์ฟผ๋ฆฌ ์ธ์ด(Query Language)๋ก ํด๋ผ์ด์ธํธ ์ค์ฌ์ ์ผ๋ก ์ํ๋ ๋ฐ์ดํฐ๋ฅผ ์ ํํ๊ฒ ์์ฒญํ ์ ์๋๋ก ํ๋ค.
ํ์ ๋ฐฐ๊ฒฝ โ REST API์ ํ๊ณ
REST API๋ ์ค๋ซ๋์ ์น์ ํ์ค์ฒ๋ผ ์ฌ์ฉ๋์์ง๋ง ํ๋ก ํธ์๋๊ฐ ๋ณ๋์ ๊ฐ๋ฐ ๋ถ์ผ๋ก ๋ถ๋ฆฌ๋๊ณ ์ค์์ฑ๊ณผ ๋ณต์ก๋๊ฐ ์ฌ๋ผ๊ฐ๋ฉด์ REST๊ฐ ๊ฐ์ง ๊ตฌ์กฐ์ ์ ์ฝ์ ํ๊ณ๋ฅผ ๋๋ฌ๋ด๊ธฐ ์์ํ๋ค.
REST๋ ์์ ์ค์ฌ(Resource Oriented)์ผ๋ก, URI๋ก ๋ช
ํํ ๋ฆฌ์์ค๋ฅผ ํํํ๊ณ HTTP ๋ฉ์๋๋ก ํ๋์ ๋ํ๋ธ๋ค. ์ด ๊ตฌ์กฐ๋ ๋จ์ํ๊ณ ์ง๊ด์ ์ด์ง๋ง ์๋น์ค๊ฐ ์ปค์ง๋ฉด์ ๋ฐ์ํ๋ ๋จ์ ๋ค์ด ์๋ค.
์๋ฅผ ๋ค์ด ํด๋ผ์ด์ธํธ๊ฐ ๋ค์ ๋ฐ์ดํฐ๋ฅผ ํ์๋ก ํ๋ค๊ณ ํ์.
- ์ฌ์ฉ์ ์ด๋ฆ
- ์ฌ์ฉ์๊ฐ ์์ฑํ ๊ฒ์๊ธ ๋ชฉ๋ก
- ๊ฐ ๊ฒ์๊ธ์ ๋ฌ๋ฆฐ ๋๊ธ ์
REST ๋ฐฉ์์ด๋ผ๋ฉด ๊ฐ ๋ฆฌ์์ค์ ๋ํด ์๋์ฒ๋ผ ์ฌ๋ฌ ๋ฒ์ ์์ฒญ์ ํด์ผ ํ๋ค.
- /users/1 โ ์ด๋ฆ์ ํฌํจํ ์ฌ์ฉ์ ์ ์ฒด ์ ๋ณด
- /users/1/posts โ ๊ฒ์๊ธ ๋ชฉ๋ก
- ๊ฐ ๊ฒ์๊ธ๋ง๋ค /posts/:id/comments โ ๋๊ธ ์
ย
๊ฒฐ๊ตญ, over-fetching(ํ์ ์ด์์ ๋ฐ์ดํฐ)๊ณผ under-fetching(ํ์ํ ๋ฐ์ดํฐ๋ฅผ ๋ค ๋ชป ๋ฐ๋ ํ์)์ด ๋ฐ๋ณต๋๋ค. ์ด๋ฐ ๋นํจ์จ์ ํด๊ฒฐํ๊ธฐ ์ํด ๋ฑ์ฅํ๊ฒ ๋ ๊ฒ์ด GraphQL์ด๋ค.
GraphQL์ ํต์ฌ ๊ฐ๋
GraphQL์ API์ ๋์ ๋ฐฉ์์ ๋ฐ์ดํฐ ์ง์(Query) ์ค์ฌ์ผ๋ก ๋ฐ๊พผ๋ค.
REST์ฒ๋ผ ์์ ๋จ์๋ก ์์ฒญํ๋ ๊ฒ์ด ์๋๋ผ, ํด๋ผ์ด์ธํธ๊ฐ ํ์ํ ๋ฐ์ดํฐ์ ๊ตฌ์กฐ๋ฅผ ์ง์ ์ ์ธํ๋ ๋ฐฉ์์ด๋ค.
์์ REST API์์ ์ฌ๋ฌ๋ฒ์ ์์ฒญ์ ๋ณด๋ด์ผํ๋ ๋ฐ์ดํฐ๋ฅผ ์ป๋ ๊ณผ์ ์ด GraphQL์์๋ ์๋์ ๊ฐ์ ์ฟผ๋ฆฌ ํ๋ฒ์ผ๋ก ์ฒ๋ฆฌ๊ฐ ๊ฐ๋ฅํ๋ฉฐ ์ ํํ ํ์๋ก ํ๋ ๋ฐ์ดํฐ๋ค๋ง ์์ฒญํ ์ ์๋ค.
์์ฒญ
{ user(id: 1) { name posts { title commentCount } } }
์๋ต
{ "data": { "user": { "name": "Lucas", "posts": [ { "title": "GraphQL", "commentCount": 12 }, { "title": "REST API vs GraphQL", "commentCount": 5 } ] } } }
์คํค๋ง (Schema)
GraphQL ์๋ฒ ๊ตฌํ์ ์ํด์๋ API์ ๊ท์น์ ์ ์ํ ๊ณ์ฝ์์ด์, ๋ฐ์ดํฐ ๊ตฌ์กฐ์ ์ฒญ์ฌ์ง์ธ ์คํค๋ง ์ ์๊ฐ ๋ฐ๋์ ํ์ํ๋ค. ์คํค๋ง์๋ ํด๋ผ์ด์ธํธ๊ฐ ์ฌ์ฉํ ์ ์๋ ์ฟผ๋ฆฌ์ ๋ฐ์ดํฐ ํ์
์ด ๋ช
์ธ๋๋ฉฐ ์ด๋ฅผ ํตํด ์๋ ๋ฌธ์ํ, ํ์
๊ฒ์ฆ, ๊ฐ๋ฐ์ ๊ฒฝํ ์์น ๋ฑ์ ์ด์ ์ ์ทจํ ์ ์๋ค.
์์
type User { id: ID! name: String! posts: [Post!]! } type Post { id: ID! title: String! commentCount: Int! } type Query { user(id: ID!): User }
REST์์ ์ฐจ์ด
ํน์ง | REST | GraphQL |
๋ฐ์ดํฐ ๊ตฌ์กฐ | ๊ณ ์ ๋ ์๋ํฌ์ธํธ ๊ธฐ๋ฐ | ํด๋ผ์ด์ธํธ ์ ์ํ ์ฟผ๋ฆฌ ๊ธฐ๋ฐ |
ํต์ ๋ฐฉ์ | HTTP Method ์ค์ฌ | Query/Mutation ์ค์ฌ |
๋ฐ์ดํฐ ์์ฒญ | ํด๋ผ์ด์ธํธ๊ฐ ์ฌ๋ฌ ์๋ํฌ์ธํธ์ ์์ฒญ์ ๋ณด๋ด์ผ ํจ | ๋จ์ผ ์๋ํฌ์ธํธ์ ํด๋ผ์ด์ธํธ๊ฐ ์ฟผ๋ฆฌ ์ธ์ด๋ก ์ํ๋ ๋ฐ์ดํฐ ๊ตฌ์กฐ๋ฅผ ๋ช
์ |
์๋ต ๋ฐ์ดํฐ | ํ์ํ ๋ฐ์ดํฐ ์ธ์ ์ถ๊ฐ ์ ๋ณด๊ฐ ํฌํจ๋ ์ ์์ | ์์ฒญํ ๋ฐ์ดํฐ๋ง ๋ฐ์ (Over-fetching ๋ฌธ์ ํด๊ฒฐ) |
๋ฒ์ ๊ด๋ฆฌ | /v1, /v2 ๋ฑ์ผ๋ก ๋ถ๋ฆฌ | ์คํค๋ง ๋ณ๊ฒฝ์ผ๋ก ๋์ |
๋ฌธ์ํ | Swagger/OpenAPI | Schema ์์ฒด๊ฐ ๋ฌธ์ |
Mutation
Mutation์ GraphQL์์ ๋ฐ์ดํฐ ๋ณ๊ฒฝ์ ์ฌ์ฉ๋๋ ์์์ผ๋ก REST์ POST, PUT, DELETE ๋ฉ์๋์ ํด๋นํ๋ ๊ฐ๋
์ด๋ค.
์์ฒญ
mutation { createPost(input: { title: "์ ๊ธ", userId: 1 }) { id title } }
์๋ต
{ "data": { "createPost": { "id": 42, "title": "์ ๊ธ" } } }
mutation์์๋ ๋ฐ์ดํฐ๋ฅผ ์์ ํ ๋ค์ ํ์ํ ๋ฐ์ดํฐ๋ง ๋ฐ๋ ํ๋ฆ์ ๋ฐ๋ฅธ๋ค.
๋จ์
๋ฌผ๋ก GraphQL์ด ์๋ฒฝํ ๋์์ ์๋๋ฉฐ ์๋์ ๊ฐ์ ๋จ์ ๋ค์ ๊ฐ์ง๋ค.
- ์๋ํฌ์ธํธ๊ฐ ํ๋๋ฟ์ด๊ธฐ ๋๋ฌธ์ ์บ์ฑ ๊ตฌํ์ด ์ด๋ ต๋ค.
- ๋ฐ์ดํฐ ์ฟผ๋ฆฌ ์์ ์ ์ฒ๋ฆฌํ๊ธฐ ์ํ ์๋ฒ ๋ณต์ก๋๊ฐ ๋์์ง๋ค.
- ๋จ์ํ API์ ์คํ๋ ค ๊ณผํ ์ ํ์ผ ์ ์๋ค.
ย
โ React ๊ธฐ๋ฐ ๋์๋ณด๋, ๋ชจ๋ฐ์ผ ์ฑ ๊ฐ์ด ํ๋ก ํธ์๋ ๊ท๋ชจ๊ฐ ํฌ๊ณ ๋น์ค์ด ๋์ ๋ง์ ํ๊ฒฝ์ ์ ํฉํ๋ฉฐ ๋จ์ํ CRUD ์์ฃผ์ ์๋น์ค์์๋ ์ฌ์ ํ REST๊ฐ ํจ์จ์ ์ด๋ค.