GraphQL의 Fragments란 무엇인가?

Fragments

한마디로 Fragments란 쿼리의 일부분을 재활용 가능한 단위로 나눠놓은것이다. 이 예제에서 우리는 blog-post.js라고 하는 템플릿 파일을 사용할것이다. 이 템플릿 파일로 블로그의 게시글들을 찍어낼수 있다.

템플릿 파일 안에는 포스트를 불러오기 위한 쿼리와 그걸 보여주기 위한 마크업이 존재한다. 포스트 내용을 불러오기 위한 GraphQL 쿼리는 다음과 같다.

export const query = graphql`
  query($id: String!) {
    post: postsJson(id: { eq: $id }) {
      title
      slug
      content
      publishDate(formatString: "MMMM DD, YYYY")
      tags
      author {
        slug
        name
        biography
      }
    }
  }
`;

위 쿼리를 살펴보면 post를 위한 영역과 author를 위한 영역이 분리되어 있다. 위 쿼리를 다음과 같이 두개의 프래그먼트로 쪼갤수 있다.

export const query = graphql`
  fragment postFields on PostsJson {
    slug
    title
    content
    publishDate(formatString: "MMMM DD, YYYY")
    tags
  }

  fragment authorFields on AuthorsJson {
    slug
    name
    biography
  }

  query($id: String!) {
    post: postsJson(id: { eq: $id }) {
      ...postFields
      author {
        ...authorFields
      }
    }
  }
`;

postFieldsauthorFields라고 하는 두개의 프래그먼트로 나눴고 쿼리문 안에서 두개의 프래그먼트를 스프레드 연산자를 통해서 뿌려주고 있다. 이제 포스트에 대한 쿼리문 작성은 끝났다.

그런데, 만약에 author의 정보를 보여주기 위한 쿼리를 또 작성해야 한다고 생각해보자. 이 쿼리문은 post를 위한 쿼리문과 별로 다를게 없을것이다. 왜냐면 두 쿼리에서 필요한 정보가 거의 비슷할것이기 때문이다. 다음은 blog-author.js 템플릿에서 작성자의 정보를 보여주기 위한 쿼리문이다.

export const query = graphql`
  query($id: String!) {
    post: authorsJson(id: { eq: $id }) {
      slug
      name
      biography
      posts {
        title
        slug
        content
        publishDate(formatString: "MMMM DD, YYYY")
        tags
      }
    }
  }
`;

Gastby에서 fragments를 내보내기

이 쿼리문에서 프래그먼트로 쿼리를 분리한다고 해도 아까 작성한 post의 프래그먼트들과 별로 다를것이 없을것이다. 그러니까 author를 위한 새로운 프래그먼트를 또 만들지 말고 아까 만들어둔 프래그먼트를 가져와서 재사용하자.

gastby 공식문서에 있는 graphql부분을 보면 fragments에 대해서 다음과 같이 설명한다.

Fragments are a way to save frequently used queries for re-use. To create a fragment, define it in a query and export it as a named export from any file Gatsby is aware of. A fragment is available for use in any other GraphQL query, regardless of location in the project. Fragments defined in a Gatsby project are global, so names must be unique.

대충 해석해보자.

  1. 프래그먼트는 쿼리문 안에서 작성되어야 한다.
  2. 프래그먼트는 named export 방식으로 내보내져야한다.
  3. 프래그먼트는 프로젝트 위치에 상관없이 다른 GraphQL 쿼리문에서 재사용가능하다.
  4. 프래그먼트는 Gastby 프로젝트에서 글로벌로 세팅되기 때문에, 이름이 unique해야한다.

그래서 어디에 프래그먼트를 작성해야 하고, 어떤식으로 써야 하는데??

blog-post.jsblog-author.js 라고 하는 두개의 템플릿 파일에서 아까 만든 두개의 프래그먼트를 사용하기위해, srcfragments.js라고 하는 파일을 생성한다. 프래그먼트를 하나의 파일에 집중시킬건지 분산시킬건지는 너의 팀과 프로젝트에 따라 알아서 결정해라.

fragments.js파일에 다음과 같이 두개의 프래그먼트를 붙여 넣자.

export const postFields = graphql`
  fragment postFields on PostsJson {
    slug
    title
    content
    publishDate(formatString: "MMMM DD, YYYY")
    tags
  }
`;

export const authorFields = graphql`
  fragment authorFields on AuthorsJson {
    slug
    name
    biography
  }
`;

다시 한번 말하지만 프래그먼트의 이름은 유일해야한다. global하게 프래그먼트가 export되기 때문에 프로젝트 내의 어떤 쿼리문 안에서도 이 프래그먼트를 재활용 할 수 있다.

필드가 몇개 없는 부분을 프래그먼트로 만드는건 오히려 가성비가 떨어진다. 수십, 수백개의 필드가 있는 쿼리의 일부를 프래그먼트화 한다면 아주 가성비가 좋은 분리가 될 수 있다.

출처

Loading script...