REST API๊ฐ ์๋ GraphQL์ ์ด์ฉํ๋ ๋ฐฉ์์ผ๋ก ๊ตฌํํ ์ค์ต์ฉ ์๋ฒ์ ๋๋ค.
GraphQL์ด ์ฒ์์ด์ ๋ถ๋ค์ด๋ผ๋ฉด, ์ ์ฒด๋ฅผ ์ฝ์ด๋ณด์๊ธธ ์ถ์ฒ๋๋ฆฝ๋๋ค.
REST API์ ๋จ์ ์ ๊ทน๋ณตํ๊ณ ์ ๋์จ ๋งํผ, ๋ด์ฉ์ ํ์ตํด๋ณด๊ณ ์ ์ ๊ฐ์ธ์ ์ธ ๊ฒฌํด(์ฑํฐ 8)์ ๋น๊ตํด๋ณด์๋ฉด ์ข์ ๊ฒ ๊ฐ์ต๋๋ค.
์์ธํ ์ด๋ก ์ ์๋ ๋ธ๋ก๊ทธ ๋งํฌ์์ ํ์ธํ์ค ์ ์์ต๋๋ค.
- 1. GraphQL ์๊ฐ
- 2. GraphQL์ ์ฅ์
- 3. GraphQL์ ๋จ์
- 4. ์ฃผ์ ๊ฐ๋ ๊ณผ ํน์ง
- 6. Spring Boot with GraphQL
- 8. GraphQL์ ๋ํ ๊ฐ์ธ์ ์ธ ๊ฒฌํด
- 9. ์ฐธ๊ณ ์๋ฃ
GraphQL์ API๋ฅผ ์ํ ์ฟผ๋ฆฌ ์ธ์ด์ด๋ฉฐ ์ด๋ฏธ ์กด์ฌํ๋ ๋ฐ์ดํฐ๋ก ์ฟผ๋ฆฌ๋ฅผ ์ํํ๊ธฐ ์ํ ๋ฐํ์ ์ ๋๋ค.
GraphQL ์ 2015๋ ์ ์คํ ์์ค๋ก ๊ณต๊ฐ๋์์ต๋๋ค.
๊ธฐ์กด์ API ์ ๊ทผ ๋ฐฉ์์ธ REST๊ฐ ๊ฐ์ง๋ ํ๊ณ๋ฅผ ๊ทน๋ณตํ๊ธฐ ์ํด ํ์ํ์ผ๋ฉฐ, ๋ฐ์ดํฐ ์ค๋ฒํจ์นญ๊ณผ ์ฌ๋ฌ API ์๋ํฌ์ธํธ๋ฅผ ํตํ ๋ณต์กํ ๋ฐ์ดํฐ ์์ฒญ ๊ณผ์ ์ ๋จ์ํ ํ๋ ค๋ ๋ชฉํ๋ฅผ ๊ฐ์ง๊ณ ์์ต๋๋ค.
- GraphQL ์ ํต์ฌ ์ฒ ํ์ ํด๋ผ์ด์ธํธ๊ฐ ์๋ฒ๋ก๋ถํฐ ํ์ํ ๋ฐ์ดํฐ๋ฅผ ์ ํํ, ํ์ํ ๋งํผ๋ง ์์ฒญํ ์ ์๊ฒ ํ๋๋ฐ์ ์์ต๋๋ค.
- ์๋ฒ๋ ํด๋ผ์ด์ธํธ๊ฐ GraphQL ๋ก ์์ฒญํ ์ ์๋ ๋ฐ์ดํฐ ํ์ ๊ณผ ๊ฐ ํ์ ์ ๋ํด ์์ฒญํ ์ ์๋ ํ๋๋ค์ ์ ์ํด ํ์ ์์คํ ์ ๊ตฌ์ถํฉ๋๋ค.
- ๊ฐ ํ์ ์ ํ๋์ ๋ํ ์์ฒญ์ ํด์ ๋ฐ ์ฒ๋ฆฌํ๋ ๋ก์ง(Ex. DB์ ์ ๊ทผ)์ Resolver ํจ์๋ก ๊ตฌํํฉ๋๋ค.
REST API ๋ ๋ฆฌ์์ค ๊ธฐ๋ฐ์ ์ํคํ ์ฒ์ ๋๋ค.
- ๊ฐ ๋ฆฌ์์ค(URL ์๋ํฌ์ธํธ) ์ ๋ํด HTTP ๋ฉ์๋๋ฅผ ์ด์ฉํด CRUD ์์ ์ ์ํํ๊ณ , ๊ฐ ๋ฆฌ์์ค์ ์ ๊ทผํ๊ธฐ ์ํด์๋ ๊ทธ์ ๋ง๋ URL ์๋ํฌ์ธํธ๋ฅผ ์ฌ์ฉํด์ผ ํฉ๋๋ค.
- ์ด๋ ๊ฒ ํ๋ฉด API ์ ๊ตฌ์กฐ๋ฅผ ๋ช ํํ๊ฒ ํ๊ณ ๋ฌธ์ํ๊ฐ ์ฉ์ดํด ์ฌ์ฉํ๊ธฐ ์ฝ์ต๋๋ค.
- ํ์ง๋ง REST API ๋ฐฉ์์ ๋ฐ์ดํฐ ์๊ตฌ๊ฐ ๋ณต์กํด์ง ๊ฒฝ์ฐ ์ฌ๋ฌ ์๋ํฌ์ธํธ๋ฅผ ์ฌ์ฉํด ๋ฐ์ดํฐ๋ฅผ ์ง๊ณํด์ผํ๊ณ , ๋ถํ์ํ ๋ฐ์ดํฐ๋ฅผ ํจ์นญํ๋ ์ผ์ด ์๊ธธ ์ ์์ต๋๋ค.
๋ฐ๋ฉด GraphQL์ ๋จ์ผ ์๋ํฌ์ธํธ๋ฅผ ํตํด ํด๋ผ์ด์ธํธ๊ฐ ํ์ํ ๋ฐ์ดํฐ์ ํํ๋ก ์์ฒญํ ์ ์์ต๋๋ค.
- ์ค๋ฒํจ์นญ : ํด๋ผ์ด์ธํธ๊ฐ ํ์๋ก ํ๋ ๋ฐ์ดํฐ๋ณด๋ค ๋ ๋ง์ ๋ฐ์ดํฐ๋ฅผ ์์ฒญํ๋ ๊ฒ
- ์ธ๋ํจ์นญ : ํด๋ผ์ด์ธํธ๊ฐ ํ์๋ก ํ๋ ๋ฐ์ดํฐ๋ณด๋ค ๋ ์ ์ ๋ฐ์ดํฐ๋ฅผ ์์ฒญํ๋ ๊ฒ
-
GraphQL์์๋ ์ฌ์ง์ ์ ๋ก๋ํ๊ธฐ ์ํด์๋ ๋ฐ์ดํธ ๋ฐฐ์ด๋ก ์ ๋ฌํด์ผ ํ๋ค.
-
๊ฒฐ๊ตญ GraphQL์ REST API์ ํจ๊ป ์ฌ์ฉํ ์๋ ์๋ค๊ณ ๋ ํ์ง๋ง, ๋ถํธํ๋ค.
type Mutation { # ์ด๋ฏธ์ง ์ ๋ก๋๋ฅผ ์ํ ๋ฎคํ ์ด์ uploadImage(file: UploadInput!): String! } input UploadInput { fileName: String! contentType: String! data: String! # ๋ฐ์ดํธ ๋ฐฐ์ด์ ์ ๋ฌ }
- ๋น์ฆ๋์ค ๋ก์ง์ ์์ฑํ๊ณ ๋์,
schema.graphqls
ํ์ผ์ ๋ฐ๋์ ํ์ ๊ณผ ์ฟผ๋ฆฌ๋ฅผ ์์ฑํด์ผ ํ๋ค.- ์ด๋ ์ง์ ํ์ดํ์ ํ๋ ๋ฐฉ์์ด๊ธฐ ๋๋ฌธ์, ์ค์๋ฅผ ๋ถ๋ฌ์ผ์ผํค๊ธฐ ์ฝ๋ค.
- ex. ์์ ๋์จ Mutation์ ์ ์ธํ uploadImage๋ผ๋ ๋ฉ์๋๋ช ์์ ์คํ๊ฐ ๋ฐ์ํ ๊ฒฝ์ฐ, ์๋ฒ์์ ๊ตฌํํ ๋ฆฌ์กธ๋ฒ์ ๋ฉ์๋๋ช ๊ณผ ๋ฌ๋ผ ํธ์ถ์ด ๋์ง ์๋๋ค. โ null ์ ๋ฆฌํด.. ๋ฐ๋ผ์ ๋๋ฒ๊น ํ๊ธฐ ํ๋ฌ.
- ๋ํ ๋ชจ๋ ์ํฐํฐ๋ฅผ ํ์ ์ผ๋ก ์ ์ํ๊ธฐ์๋ ์์ด ๋๋ฌด ๋ง์ ๋ฌด๋ฆฌ๊ฐ ์๋ค.
- GraphQL์์ ๊ณต์์ ์ผ๋ก ์ง์ํ๋ API ๋ฌธ์ํ ๋ฐฉ์์ GraphiQL์์ ์ง์ํ๋ Docs ๊ธฐ๋ฅ์ด๋ค.
- ํด๋ผ์ด์ธํธ๊ฐ ์์ ๋กญ๊ฒ ์ฟผ๋ฆฌ๋ฅผ ๋ถ๋ฌ์ค๋๋ก ์ด์ด์ค์ผ๋ก์จ ๋ถ์์ฉ์ด ๋ฐ์ํ ์ ์์ต๋๋ค.
- ํด๋ผ์ด์ธํธ๊ฐ ์์ฒญ์ ๋ถํ์ํ๊ฒ ๋ฌด๊ฑฐ์ด ์ฟผ๋ฆฌ๋ฅผ ๋ณด๋์ผ๋ก์จ ์๋ฒ์ ๋ถ๋ด์ด ๊ฐํด์ง ์ ์์ต๋๋ค.
- Query : ๋ฐ์ดํฐ๋ฅผ ์ฝ๊ธฐ ์ํ ์์ฒญ์
๋๋ค.
- GraphQL ์ ์ฌ์ฉํ๋ฉด ํด๋ผ์ด์ธํธ๋ ์๋ฒ์๊ฒ ํ์ํ ๋ฐ์ดํฐ์ ๊ตฌ์กฐ๋ฅผ ๋ช ์์ ์ผ๋ก ์์ฒญํ๋ฉฐ, ์๋ฒ๋ ํด๋น ๊ตฌ์กฐ์ ๋ง๊ฒ ๋ฐ์ดํฐ๋ฅผ ์๋ตํฉ๋๋ค.
- HTTP ๋ฉ์๋ ์ค GET์ ํด๋นํฉ๋๋ค.
- Mutation : ๋ฐ์ดํฐ๋ฅผ ์์ฑ, ์์ , ์ญ์ ํ๊ธฐ ์ํ ์์ฒญ์
๋๋ค.
- ์ฟผ๋ฆฌ์ ์ ์ฌํ ๋ฌธ๋ฒ์ ์ฌ์ฉํ์ง๋ง, ์๋ฒ์ ๋ฐ์ดํฐ๋ฅผ ๋ณํ์ํฌ ๋ ์ฌ์ฉ๋ฉ๋๋ค.
- HTTP ๋ฉ์๋ ์ค POST, PUT, PATCH, DELETE ๋ฉ์๋์ ํด๋นํฉ๋๋ค.
- Schema
- GraphQL์์ ์ฌ์ฉํ ์ ์๋ ๋ฐ์ดํฐ์ ์ข ๋ฅ์ ๊ทธ ๊ด๊ณ๋ฅผ ์ ์ํ๋ ๋ฌธ์์ ๋๋ค.
- ์คํค๋ง๋ ์๋ฒ์์ ์ง์ํ๋ ์ฟผ๋ฆฌ, ๋ฎคํ ์ด์ , ๊ฐ์ฒด ํ์ ๋ฑ์ ๋ช ์ํฉ๋๋ค.
- Spring Boot์ ๊ฒฝ์ฐ,
resources/graphql/schema.graphqls
๋ก ์์ฑํ๊ณค ํฉ๋๋ค.
- Type System
- GraphQL ์ ๊ฐ๋ ฅํ ํ์ ์์คํ ์ ์ฌ์ฉํด API ๋ฅผ ์ฃผ๊ณ ๋ฐ์ ๋ฐ์ดํฐ ํํ๋ฅผ ์ ์ํฉ๋๋ค.
- ์ด ์์คํ ์ API๋ฅผ ๋ ์์ ์ ์ผ๋ก ๋ง๋ค๊ณ , ํด๋ผ์ด์ธํธ์ ์๋ฒ๊ฐ์ ๋ช ํํ ์ฝ์์ ๊ฐ๋ฅํ๊ฒ ํฉ๋๋ค.
- Spring Boot์ ๊ฒฝ์ฐ, ์๋์ ๊ฐ์ด ์คํค๋ง ํ์ผ ์์ ํ์
์ ๋ช
์ํ ์ ์์ต๋๋ค.
- ์ด๋,
viewAllPost
์ ๊ฐ์ ๋ช ์นญ์ ๋ฆฌ์กธ๋ฒ์ ๋ฉ์๋๋ช ๊ณผ ๋ฐ๋์ ๋์ผํด์ผ ํฉ๋๋ค. - ์ผ์นํ์ง ์์ ๊ฒฝ์ฐ ์๋ฌ๊ฐ ๋ฐ์ํ์ง๋ ์์ง๋ง, ๋ฆฌ์กธ๋ฒ๋ฅผ ํธ์ถํ์ง ๋ชปํด null์ ๋ฐํํฉ๋๋ค.
# schema.graphqls ### Query ์ ์ (GET ์ญํ ) type Query { viewAllPost: [Post] getCommentsByPostId(postId: ID): [Comment] } ### Mutation ์ ์ (POST, PUT, PATCH, DELETE ์ญํ ) type Mutation { viewPost(postId: ID): Post savePost(request: RequestPost!): Post saveComment(postId: ID, request: RequestComment!): Comment } type Post { id: ID title: String content: String views: String author: User comments: [Comment] }
- ์ด๋,
- ๊ตฌ๋
: ์ค์๊ฐ์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ๋ฐ๊ธฐ ์ํ ๋ฉ์ปค๋์ฆ ์
๋๋ค.
- query์ mutation๊ณผ ๋ง์ฐฌ๊ฐ์ง๋ก ๋ง์ง๋ง operation type์ ๋๋ค.
- GraphQL Subscription์ WebSocket์ ๊ธฐ๋ฐ์ผ๋ก ๊ตฌํ๋์ด, ์๋ฒ๊ฐ ๊ตฌ๋ ์ค์ธ ํด๋ผ์ด์ธํธ์ ์ง์์ ์ธ ์ฐ๊ฒฐ์ ์ ์ง
- ์ค์๊ฐ ์ฑํ , ์๋ฆผ ์์คํ ๋ฑ ์ค์๊ฐ ๋ฐ์ดํฐ ์ ๋ฐ์ดํธ๊ฐ ํ์ํ ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ตฌํํ๊ธฐ ์ฉ์ดํฉ๋๋ค.
- GraphQL์ ๋ชจ๋ ์ฟผ๋ฆฌ์ ๋ฎคํ ์ด์ , ๊ตฌ๋ ์์ฒญ์ ๋จ์ผ ์๋ํฌ์ธํธ๋ฅผ ํตํด ์ฒ๋ฆฌํฉ๋๋ค.
- ์ด ์ ๊ทผ ๋ฐฉ์์ API์ ๊ตฌ์กฐ๋ฅผ ๋จ์ํํ๋ฉฐ, ํด๋ผ์ด์ธํธ๊ฐ ์ฌ๋ฌ ์๋ํฌ์ธํธ๋ฅผ ๊ด๋ฆฌํ๋ ๋ณต์ก์ฑ์ ์ค์ฌ์ค๋๋ค.
GraphQL์ ์ฟผ๋ฆฌ๋ฅผ ํ์ธํ ์ ์๋๋ก GraphiQL์ด๋ผ๋ GUI๋ฅผ ์ ๊ณตํ๋ค.
-
Spring Boot์ ๊ฒฝ์ฐ, application.yml์ ์๋์ ๊ฐ์ด ์์ฑํ ๊ฒฝ์ฐ GraphiQL์ ํ์ฑํ์ํฌ ์ ์๋ค.
spring: graphql: graphiql: enabled: true # default : false path: /graphiql # default : /graphiql
-
์ ์ฒด ๊ฒ์๊ธ ์กฐํ : query
query { viewAllPost { id title content author { id name } } }
-
ํน์ ๊ฒ์๊ธ ์กฐํ : mutation
mutation { viewPost(postId: 1) { id title content author { id name } comments { id content writer { id name } } } }
-
๊ฒ์๊ธ ์์ฑ : mutation
mutation { savePost(request: {title: "hi title", content: "hi content"}) { title content } }
-
๋๊ธ ์ ์ฅ : mutation
mutation { saveComment(postId: 1, request: {content: "hi content"}) { id content } }
-
ํน์ ๊ฒ์๊ธ์ ๋๊ธ ๋ชฉ๋ก : query
query { getCommentsByPostId(postId: 1) { id content writer { id name } } }
๊ฒฐ๋ก ์ ์ผ๋ก ์๋์ ๊ฐ์ ์ด์ ๋ก GraphQL์ด REST API๋ฅผ ๋์ฒดํ๊ธฐ์๋ ๋ฌด๋ฆฌ๊ฐ ์๋ค๊ณ ์๊ฐ์ด ๋ญ๋๋ค.
8-1. ํด๋ผ์ด์ธํธ๊ฐ ์์ ๋กญ๊ฒ ์ฟผ๋ฆฌ๋ฅผ ๋ถ๋ฌ์ค๋๋ก ์ด์ด์ค์ผ๋ก์จ ๋ถ์์ฉ์ด ๋ฐ์
- ํด๋ผ์ด์ธํธ๊ฐ ์์ฒญ์ ๋ถํ์ํ๊ฒ ๋ฌด๊ฑฐ์ด ์ฟผ๋ฆฌ๋ฅผ ๋ณด๋์ผ๋ก์จ ์๋ฒ์ ๋ถ๋ด์ด ๊ฐํด์ง ์ ์์ต๋๋ค.
- ๋ฐฑ์๋ ์๋ฒ๊ฐ MSA์ธ ๊ฒฝ์ฐ ํด๋ผ์ด์ธํธ์์ ๊ฐ ์๋น์ค์ API ์์ฒญ์ ๊ฐ๊ฐ ๋ณด๋ด์ผ ํด์ ๋๋ค์ ์ธ๋ํ์นญ์ด ๋ฐ์ํฉ๋๋ค.
- ์ธ๋ํ์นญ์ ํด๊ฒฐํ๊ธฐ ์ํด ๋ณต์ก์ฑ์ ๊ฐ์ํ๋ฉฐ GraphQL์ ์ฑํํ๋๋ฐ, ๋ค์ ์ธ๋ํ์นญ์ด ๋ฐ์ํ๋ค๋ฉด ๊ฒฐ๊ตญ ๋ณต์กํ๋ค๋ ๋จ์ ๋ง ๋จ๊ฒ ๋๋ค๊ณ ์๊ฐํฉ๋๋ค.
- ๊ธฐ๋ฅ๋ณ๋ก ์ง์ฐ์๊ฐ(letency)๋ ์๋ฌ์จ ๋ฑ์ ๋ชจ๋ํฐ๋งํ๊ธฐ ์ด๋ ค์ธ ์ ์์ต๋๋ค.
- express-graphql์์๋ ์์ฒญํ ๋ฐ์ดํฐ๊ฐ ์๋ ๊ฒฝ์ฐ ์ํ์ฝ๋ 500์ ๋ฐํํฉ๋๋ค.
- Apollo Server๋ ์ ์๋ฌ์ธ ๊ฒฝ์ฐ์๋ 200์ ๋ฐํ ํฉ๋๋ค.
- spring-graphql์์๋ ์๋ฌ๊ฐ ๋ฐ์์, ์ํ ์ฝ๋๊ฐ 200์ผ๋ก ๋ฐํ๋ฉ๋๋ค.