9일차 스터디 - GraphQL

9일차 스터디 - GraphQL

GraphQL은 API용 쿼리 언어이자 기존 데이터로 이러한 쿼리를 수행하기 위한 런타임입니다.
GraphQL은 API의 데이터에 대한 완전하고 이해하기 쉬운 설명을 제공하고, 클라이언트가 필요한 것을 정확하게 요청할 수 있는 기능을 제공하며, 시간이 지남에 따라 API를 더 쉽게 발전시키고 강력한 개발자 도구를 활성화합니다.

GraphQL이란?

GraphQL은 간단하게 객체의 특정 필드를 요청하는 것입니다.
매우 간단한 쿼리와 실행했을 때 얻은 결과부터 살펴보겠습니다.

요청

{
    hero {
        name
    }
}

응답

{
    "data": {
        "hero": {
            "name": "R2-D2"
        }
    }
}

타입 언어

GraphQL 서비스는 어떤 언어로든 작성할 수 있습니다.
GraphQL 스키마에 대해 이야기하기 전에 JavaScript와 같은 특정 언어 문법에 의존 할 수 없기 때문에 간단한 언어를 정의할 것입니다.
여기서는 GraphQL 스키마 언어(GraphQL schema language) 를 사용할 것입니다.
이것은 쿼리 언어와 비슷하며, GraphQL 스키마를 언어에 의존적이지 않은 방식으로 표현할 수 있게 해줍니다.

객체 타입과 필드

GraphQL 스키마의 가장 기본적인 구성 요소는 객체 타입입니다.
객체 타입은 서비스에서 가져올 수 있는 객체의 종류와 그 객체의 필드를 나타냅니다.
GraphQL 스키마 언어에서는 다음과 같이 표현할 수 있습니다.

type Episode {
    title: String!
}
type Character {
    name: String!
    appearsIn: [Episode]!
}

쿼리 타입 & 뮤테이션 타입

스키마 대부분의 타입은 일반 객체 타입이지만 스키마 내에는 특수한 두 가지 타입이 있습니다.

schema {
    query: Query
    mutation: Mutation
}

모든 GraphQL 서비스는 query 타입을 가지며 mutation 타입은 가질 수도 있고 가지지 않을 수도 있습니다.
이러한 타입은 일반 객체 타입과 동일하지만 모든 GraphQL 쿼리의 진입점(entry point) 을 정의하므로 특별합니다.

query {
    hero {
        name
    }
    droid(id: "2000") {
        name
    }
}

위와 같은 쿼리를 호출하기 위해서는 herodroid 필드가 있는 Query 타입이 있어야 합니다.

type Query {
    hero(episode: Episode): Character
    droid(id: ID!): Droid
}

뮤테이션도 비슷한 방식으로 작동합니다.
즉, Mutation 타입의 필드를 정의하면 쿼리에서 호출할 수 있는 루트 뮤테이션 필드로 사용할 수 있습니다.

스키마에 대한 진입점 이라는 특수한 점 이외의 쿼리 타입과 뮤테이션 타입은 다른 GraphQL 객체 타입과 동일하며 해당 필드는 정확히 동일한 방식으로 작동한다는 점을 기억하세요.

스칼라 타입

GraphQL 객체 타입은 이름과 필드를 가지지만, 어떤 시점에서 이 필드는 구체적인 데이터로 해석되어야합니다. GraphQL 에서는 스칼라 타입들이 기본 제공됩니다.

열거형 타입

Enums 라고도 하는 열거형 타입은 특정 값들로 제한되는 특별한 종류의 스칼라입니다.
이를 통해 다음과 같은 작업을 할 수 있습니다.

  1. 타입의 인자가 허용된 값 중 하나임을 검증합니다.
  2. 필드가 항상 값의 열거형 집합 중 하나가 될 것임을 타입 시스템을 통해 의사소통합니다.
enum Episode {
    NEWHOPE
    EMPIRE
    JEDI
}

즉, 스키마에서 Episode 타입을 사용할 때마다 정확히 NEWHOPE, EMPIRE, JEDI 중 하나일 것입니다.

Apollo

Apollo란 GraphQL의 클라이언트 라이브러리 중 하나로 GraphQL을 사용한다면 거의 필수적으로 사용하는 상태 관리 플랫폼입니다.
React와 함께 사용하는 경우 Redux, REST API를 대체하는 강력한 기능을 제공하여 줍니다.

axios와 비슷하게 HTTP요청을 통해 Query 및 Mutation 을 직접 전송 및 응답을 받아옴으로써 HTTP 요청에 대해 신경 쓸 필요가 사라집니다.
또한 전송 받은 데이터를 자동으로 캐싱하여 반복 요청을 줄여 시스템 부하를 줄여줍니다.

index-diagram

Apollo는 크게 두가지로 나눠집니다.

  1. Apollo Server
  2. Apollo Client

1. Apollo Server

Apollo Server는 다음을 제공합니다.

GraphQL 스키마 정의

스키마를 사용하여 클라이언트가 쿼리할 수 있는 데이터 구조를 정의합니다.

import { gql, ApolloServer } from 'apollo-server';

const typeDefs = gql`
    type Movie {
        id: Int!
        title: String!
        subTitle: String
        year: String!
    }

    type Query {
        movies: [Movie]!
        movie(id: Int!): Movie
    }
    type Mutation {
        deleteMovie(id: Int!) Boolean!
    }
`;

Resolver 정의

Apollo Server는 쿼리를 실행할 때 해당 데이터 세트를 사용해야 한다는 것을 알지 못합니다.
이 문제를 해결하기 위해 resolver 를 만듭니다.

const resolvers = {
    Query: {
        books: () => books,
        book: (id) => book,
    },
    Mutation: {
        deleteMovie: (id) => true,
    },
};

booksbook은 리턴되는 데이터셋입니다.

Apollo Instance Server 생성

const server = new ApolloServer({ typeDefs, resolvers });

// The `listen` method launches a web server.
server.listen().then(({ url }) => {
    console.log(`🚀  Server ready at ${url}`);
});

node.js를 사용하여 서버를 실행하면 GrqphQL 쿼리를 실행할 수 있습니다.
이때 Apollo에서 지원하는 Apollo Sandbox를 사용할 수 있습니다.\

http://localhost:4000

Apollo Client

Apollo Client 는 GraphQL을 사용하여 로컬 및 원격 데이터를 모두 관리할 수 있는 JavaScript용 포괄적인 상태 관리 라이브러리입니다.
이를 사용하여 UI를 자동으로 업데이트하면서 애플리케이션 데이터를 가져오고 캐시하고 수정합니다.

특징

과제

금일 과제는 없습니다! GraphQL과 Apollo는 스터디만으로 감이 잘 오시지 않을것입니다. 본 프로젝트가 시작되면 함께 코딩하면서 익혀나가면 좋을것 같습니다!!