GraphQL개념및 express와 적용

Featured image

restapi가 있는데 왜 graphql이 나왔나

Graphql은 rest에서 부족한점을 보완하기위해 탄생

rest api개발을 마치고 프론트엔드개발자가 api에서 받아온 데이터를 이용해 화면에 보여주는 것이 그동안의 방법

이렇게 하기 위해서는 프론트엔드 개발자가 rest api개발이 끝날때 까지 기다려야 한다

하지만 GraphQL을 사용하면 프론트엔드 개발자와 백엔드 개발자가 프로세스를 병렬로 개발할 수 있다

graphQL의 스키마를 정의하고 그 스키마에 따라 프론트엔드 개발자는 어떤 데이터를 요청할지 미리 알 수 있다 백엔드 개발자는 이 스키마에 맞춰 리졸버를 구현한다 리졸버란 실제로 데이터를 가져오고 클라이언트의 요청을 처리하는 로직 Overfetching과 Underfetching을 막아준다

예를 들어 사용자 프로필페이지를 만드는데 필요한 데이터는 사용자의 이름과 이메일뿐이다 하지만 restapi는 모든 정보를 반환한다 -> 이름과 이메일이 아닌 다른 불필요한 데이터가 전송된다

예를 들어 사용자와 사용자가 쓴 포스트를 둘다 함께 가져와야 할떄 rest api는 여러번의 네트워크를 요청해야 하고 여러번의 요청에 의해 전체 응답시간이 길어질 수 있다

사용해보기

https://swapi.dev/ 는 스타워즈의 정보를 rest api 형식으로 반환한다

https://graphql.org/swapi-graphql 이 사이트를 통해 똑같은 스타워즈 정보를 GraphQL을 사용해볼 수 있다 보통 rest api는 url뒤에 파람을 붙여 전달한다 -> graphQL은 스키마를 정의한다

{}을 사용해 열고 가져올 파람을 적는다

그 후 ()안에 안에 이 파람에서 가져올것이 있으면 적는다

가져오고 싶은 데이터만을 적는다

{
  starship(starshipID: 9) {
    name
    model
    crew
  }
}

또한 한번의 요청으로 여러 요청을 한꺼번에 보내고 반환받을 수 있다

{
  starship(starshipID: 9) {
    name
    model
    crew
  }
  planet(planetID:1) {
    name
    diameter
  }
}

graphql의 단점

  1. 개발자가 graphql를 쓰는 법을 따로 배워야 한다
  2. 백엔드가 스키마 및 타입을 정해줘야 한다
  3. restaou 보다 캐싱이 까다롭다

GraphQL을 express에서 사용하기 위해서는 두개의 종속성을 설치해야한다

yarn add express-graphql graphql

graphql 은 타입 스키마를 구성하고 쿼리를 통해 필요한 데이터를 요청한다

express-graphql 은 연견스타일 미들웨어를 지원하는 http 프레임워크로 GraphQL HTTP 서버를 만듬

import express from 'express'
import { graphqlHTTP } from 'express-graphql';
import { buildSchema  } from 'graphql'

// Define your schema
const schema = buildSchema(`
    type Query {
      description: String
    }
  `); //스키마 작성
  
  // description으로 요청이 들어오면 보낼 값
  const root = {
    description: () => {
      return 'Hello world!';
    },
  };
  
  // Create an instance of Express
  const app = express();
  
  // Define the /graphql endpoint
  app.use('/graphql', graphqlHTTP({ //이 경로로 요청을 오면 그에 맞는 응답(이 스키마에 맞는 응답)
    schema: schema,
    rootValue: root,
    graphiql: true, // Enable GraphiQL UI for testing
  }));
  
  // Start the server
  app.listen(4000, () => {
    console.log('Running a GraphQL API server at http://localhost:4000/graphql');
  });

### 뮤테이션

뮤테이션(Mutation)은 GraphQL에서 데이터의 변경을 처리하기 위한 작업 유형

post, put, delete와 유사한 역할을 한다

이 반대로 query는 조회 역할을 한다

타입을 정의 하고 그 뒤 뮤테이션의 타입을 정의 한다

  import { buildSchema } from 'graphql';
import { userController } from '../controllers/userController.js';

const schema = buildSchema(`
  type User {
    id: ID!
    name: String!
  }

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

  type Mutation {
    addUser(name: String!): User
    updateUser(id: ID!, name: String!): User
    deleteUser(id: ID!): User
  }
`);

const root = {
  users: userController.users,
  user: userController.user,
  addUser: userController.addUser,
  updateUser: userController.updateUser,
  deleteUser: userController.deleteUser,
};

export { schema, root };

스키마 정리 후 익스프레스 서버 설정 파일에서 graphql를 쓸때 이 스키미와 루트를 쓰겠다고 설정한다

import express from 'express';
import { graphqlHTTP } from 'express-graphql';
import { schema, root } from './schemas/userSchema.js';

const app = express();

app.use('/graphql', graphqlHTTP({
  schema: schema,
  rootValue: root,
  graphiql: true,
}));

app.listen(4000, () => {
  console.log('Running a GraphQL API server at http://localhost:4000/graphql');
});

restapi를 사용하면 컨트롤러, 서비스, 레포지토리를 똑같이 만들고 반환값을 설정하는 root라는 속성에 연결해준다

import {
  getUsers,
  getUserById,
  createUser,
  updateUser,
  deleteUser,
} from '../models/userModel.js';

export const userController = {
  users: async () => {
    return await getUsers();
  },
  user: async ({ id }) => {
    return await getUserById(id);
  },
  addUser: async ({ name }) => {
    return await createUser(name);
  },
  updateUser: async ({ id, name }) => {
    return await updateUser(id, name);
  },
  deleteUser: async ({ id }) => {
    return await deleteUser(id);
  },
};

정리

좀 어렵게 생각했는데 그냥 rest와 대체되는거였다

둘 모두 먼저 약속을 정해놓고 이렇게 들어오면 이 쿼리를 실행한다