๊ฐœ๋ฐœ ๊ณต๋ถ€/์›น ์ง€์‹ ์ฐฝ๊ณ 

GraphQL vs Rest API

๊ฐ€์šค์ด 2024. 11. 7. 22:42

GraphQL

ํŽ˜์ด์Šค๋ถ์ด ๋งŒ๋“  ์ฟผ๋ฆฌ ์–ธ์–ด,

REST API์˜ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ๊ฐœ๋ฐœ

  • ์˜ค๋ฒ„ํŒจ์นญ, ์–ธ๋”ํŒจ์นญ
  • ๋ฐฑ์—”๋“œ API๊ฐ€ ์ˆ˜์ •๋  ๋•Œ๋งˆ๋‹ค API ๋ช…์„ธ์„œ ์ˆ˜์ • ๊ณผ์ •๊ณผ ํ”„๋ก ํŠธ์—”๋“œ ์ฝ”๋“œ๊ฐ€ ์ˆ˜์ •๋  ์ˆ˜ ์žˆ๋Š” ๋ฌธ์ œ

 

REST API vs GraphQL

 

  REST API GraphQL
ํ˜ธ์ถœ ์—ฌ๋Ÿฌ ์—”๋“œํฌ์ธํŠธ ํ˜ธ์ถœ (/users, /articles) ๋‹จ์ผ ์—”๋“œํฌ์ธํŠธ (/graphql)
๋ฐ์ดํ„ฐ ์š”์ฒญ ํ•ญ์ƒ ๋™์ผํ•œ ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ (์˜ค๋ฒ„ํŒจ์นญ) ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์›ํ•˜๋Š” ๋ฐ์ดํ„ฐ๋งŒ ์š”์ฒญ ๊ฐ€๋Šฅ
๋ฐ์ดํ„ฐ ์กฐ์ž‘ CRUD (GET, POST, DELETE, UPDATE) query(์กฐํšŒ), mutation(์ˆ˜์ •)
์—๋Ÿฌ ์ฒ˜๋ฆฌ HTTP ์ƒํƒœ ์ฝ”๋“œ๋กœ ์—๋Ÿฌ ๊ตฌ๋ถ„ errors ํ•„๋“œ๋ฅผ ํ†ตํ•ด ์—๋Ÿฌ ์ •๋ณด ์ œ๊ณต

 

 

๋ฐ์ดํ„ฐ ์š”์ฒญ/์กฐ์ž‘


REST API

: HTTP ๋ฉ”์„œ๋“œ(GET, POST, PUT, DELETE)๋ฅผ ์‚ฌ์šฉ

  • ํด๋ผ์ด์–ธํŠธ ๋ฐ์ดํ„ฐ ์š”์ฒญ
axios.get(`/api/users/${userId}`)
  .then(response => setUser(response.data))
  .catch(error => console.error(error));
axios.get(`/api/users/${userId}/friends`)
  .then(response => setFriens(response.data))
  .catch(error => console.error(error));

 

GraphQL

: ๋ฐ์ดํ„ฐ ์กฐํšŒ(Query), ์ˆ˜์ •(Mutation)

query {
  user(id: 1) {
    id
    email
    name
    friends {
      name
    }
  }
}
mutation {
  createUser(user: {id: 3, name: "John", email: "john@test.com"}) {
    id
    name
    email
  }
}



  • ์Šคํ‚ค๋งˆ/ํƒ€์ž… ์ •์˜: ์–ด๋–ค ๋ฐ์ดํ„ฐ๋ฅผ ์š”์ฒญํ•˜๊ณ  ์–ด๋–ค ๋ฐฉ์‹์œผ๋กœ ์š”์ฒญ์„ ๋ณด๋‚ผ ์ˆ˜ ์žˆ๋Š”์ง€ ์ •์˜
const { ApolloServer, gql } = require('apollo-server');

const typeDefs = gql`
  type User {
    id: Int!
    name: String!
    email: String!
    friends: [Friend]
  }

  type Friend {
    name: String!
    email: String!
  }
  
  input NewUser {
    id: Int!
    name: String!
    email: String!
  }

  type Query {
    users(): [User]
    user(id: Int!): User
  }

  type Mutation {
    createUser(name: String!, email: String!): User
    deleteUser(userId: ID!): Boolean
  }

 

  • ๋ฆฌ์กธ๋ฒ„ (resolvers): GraphQL ์„œ๋ฒ„์—์„œ ์ฟผ๋ฆฌ, ๋ฎคํ…Œ์ด์…˜์„ ์ฒ˜๋ฆฌํ•˜๋Š” ํ•จ์ˆ˜
const dummyUsers = [{ id: 1, name: 'kim', email: 'kim@test.com', friends: [{ name: 'Lee', email: 'lee@test.com'}, { name: 'Pack', email: 'pack@test.com' }] }, { id: 2, name: 'Lee', email: 'lee@test.com', friends: [{ name: 'kim', email: 'kim@test.com', friends: [] }}]

const resolvers = {
  Query: {
    users: () => {
      return dummyUsers
    },
    user: (_: any, { id }: { id: number }) => {
	    const user = dummyUsers.find(user => user.id === id)
	    return user
    },
  },
  Mutation: {
    createUser: (_: any, { user }: { user: NewUser }) => {
      const newUser = {
        ...user,
        friends: []
      }
      users.push(newUser)
      return newUser
    },
    deleteUser: (_: any: unknown, { id }: { id: number }) => {
      dummyUsers = dummyUsers.filter((user) => user.id !== id)
      return true
    },
  },
  User: {
    friends: (user: User) => {
      return user.friends;
    },
  },
}

 

 

 

"Apollo-client", GraphQL API์™€ ํšจ์œจ์ ์œผ๋กœ ์ƒํ˜ธ์ž‘์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๋Š” ํด๋ผ์ด์–ธํŠธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ

React ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ GraphQL API์™€ ์‰ฝ๊ฒŒ ์ƒํ˜ธ์ž‘์šฉ ๊ฐ€๋Šฅ (๋ฆฌ์•กํŠธ์—์„œ ์‚ฌ์šฉํ•  ๊ฒฝ์šฐ Redux๋ฅผ ๋Œ€์ฒด ๊ฐ€๋Šฅ)

npm i graphql @apollo/client
  • ์„ค์ •
import { ApolloClient } from "@apollo/client";
import { ApolloProvider } from '@apollo/client/react';

const client = new ApolloClient({
    uri: "https://localhost:8001",
});

ReactDOM.render(
  <ApolloProvider client={client}>
    <App />
  </ApolloProvider>,
  document.getElementById('root')
);
  • ์‚ฌ์šฉ
import { gql } from '@apollo/client';

const getUser = gql`
  query user($id: Int!) {
    user(id: $id) {
      id
      name
      friends {
        id
        name
        email
      }
    }
  }
`;
  • ์‘๋‹ต ๋ฐ์ดํ„ฐ
{
  "data": {
    "user": {
      "id": 1,
      "name": "Kim",
      "email": "kim@test.com",
      "friends": [
        { "name": "Lee" },
        { "name": "Park" }
      ]
    }
  }
}

 

API ํ…Œ์ŠคํŠธ์™€ ๋ช…์„ธ

  REST API GraphQL
ํ…Œ์ŠคํŠธ ๋„๊ตฌ Postman GraphQL Playground
API ๋ช…์„ธ Swagger GraphQL Playground

 

GraphQL Playground


GitHub - graphql/graphql-playground: ๐ŸŽฎ GraphQL IDE for better development workflows (GraphQL Subscriptions, interactive docs & collaboration)

 

GitHub - graphql/graphql-playground: ๐ŸŽฎ GraphQL IDE for better development workflows (GraphQL Subscriptions, interactive docs

๐ŸŽฎ GraphQL IDE for better development workflows (GraphQL Subscriptions, interactive docs & collaboration) - graphql/graphql-playground

github.com

  • ํ…Œ์ŠคํŠธ & ๋ช…์„ธ ์˜ˆ์‹œ

์ด๋ฏธ์ง€ ์ถœ์ฒ˜:  https://tech.kakao.com/posts/364

 

์—๋Ÿฌ ์ฒ˜๋ฆฌ


REST API

: HTTP ์ƒํƒœ ์ฝ”๋“œ (400, 500 Error)

GraphQL

: errors ๋ฐฐ์—ด์— ์—๋Ÿฌ ์ •๋ณด ์ œ๊ณต

 

 

 

๊ฐœ์ธ์ ์œผ๋กœ ์ง์ ‘ ์‚ฌ์šฉํ•ด ๋ดค์„ ๋•Œ GraphQL ๋ถˆํŽธํ–ˆ๋˜ ์ 


  • ํ”„๋ก ํŠธ์—”๋“œ ์ฝ”๋“œ๊ฐ€ ๊ธธ์–ด์งˆ ์ˆ˜ ์žˆ๋‹ค. ํ•„์š”ํ•œ ํ•„๋“œ๋ฅผ ๋ชจ๋‘ ์ž‘์„ฑํ•ด์•ผ ํ•จ
  • ๋ฆฌ์กธ๋ฒ„ ๊ด€๋ฆฌ: ํ”„๋กœ์ ํŠธ๊ฐ€ ์ปค์งˆ์ˆ˜๋ก ๋ฆฌ์กธ๋ฒ„ ๊ด€๋ฆฌ๊ฐ€ ์–ด๋ ต๋‹ค๋Š” ์ . ํ”„๋กœ์ ํŠธ๊ฐ€ ๋ชจ๋“  ํ•„๋“œ๋ฅผ ํ•œ ๊ณณ์— ์ •์˜ํ•˜๋ฉด ๊ด€๋ฆฌ๊ฐ€ ํž˜๋“ค๊ธฐ ๋•Œ๋ฌธ์— ๋ณดํ†ต ๋ชจ๋“ˆ ๋‹จ์œ„๋กœ ๋ฆฌ์กธ๋ฒ„๋ฅผ ๋‚˜๋ˆ ์„œ ๊ด€๋ฆฌํ•ฉ๋‹ˆ๋‹ค.
  • ๋ฆฌ์กธ๋ฒ„ ๋„ค์ด๋ฐ.. ํ”„๋ก ํŠธ์—์„œ ์–ด๋–ค ๋กœ์ง์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ฑด์ง€ ๋ฆฌ์กธ๋ฒ„ ๋„ค์ž„์„ ํ†ตํ•ด ํŒŒ์•…ํ•˜๋ฏ€๋กœ ๋ช…ํ™•ํ•œ ๋„ค์ด๋ฐ์ด ์ค‘์š”.. ๊ทธ๋ž˜์„œ ๋ฆฌ์กธ๋ฒ„ ๋„ค์ž„์ด ๊ธธ์–ด์ง€๋Š” ๊ฒฝ์šฐ๋„ ๋งŽ์Œ