GraphQL을 사용해보자(2) : Apollo vs Urql

Jimin Lee·2025년 1월 16일

GraphQL

목록 보기
3/3
post-thumbnail

GraphQL은 FE 입장에서 RESTful과 같은 역할의 프로토콜이므로 GraphQL 자체가 요청을 보내는 역할을 하지 않는다. 따라서 request를 위한 별도의 무언가가 필요하다.

fetch 사용

물론 fetch를 사용도 가능하다. fetch를 사용하면 method는 주로 POST를 사용한다.

fetch('https://rickandmortyapi.com/graphql', {
  method: 'POST',
  headers: {
    "Content-Type": "application/json"
  },
  body: JSON.stringify({
    query: `{
      characters {
        results {
          name
        }
      }
    }`
  })
})

하지만 이렇게 하면 string 문자열을 매번 적어줘야 하고 JSON.stringify를 매번 해줘야 하는 번거로움이 있기 때문에 Apollo, urql과 같은 라이브러리를 사용하는 것이다.


현재 프로젝트는 Nextjs App router를 사용하고 있기 때문에 이 기준에 부합하는 라이브러리를 살펴보겠다.

Client 라이브러리 비교

Apollo Client

공식 사이트
아마 가장 대중적인 라이브러리라고 생각한다. 라이브러리 중에서 가장 많은 기능을 지원하고 그렇기에 무겁다.

Nextjs와의 조합

처음엔 이걸 사용할까 고민했지만, nextjs 13부터 적용된 rsc에 대응하기 위한 패키지가 아직 정식 버전이 아닌 듯 했다. 이름부터 experimental이 들어가있다.
https://www.npmjs.com/package/@apollo/experimental-nextjs-app-support

위 사이트 설명에서도 정식 버전이 아님을 말하고 있다.
사용방법은 이전 포스팅을 참고하면 된다.

장점

  1. 캐싱과 상태 관리도 해준다.
    GraphQL API 연결여부와 관계없이 빌트인 캐싱과 상태 관리 기능을 지원한다고 한다.
  2. 다양한 기능을 지원한다.
    에러 처리, 페이지네이션, 데이터 prefetching 등도 지원한다.
  3. 커뮤니티가 커서 레퍼런스가 많다.
  4. 리액트, 뷰 등 여러가지 프레임워크를 지원한다.

단점

  1. 기능이 많아서 무겁다.
    next에서 빌드했을 때 번들 사이즈가 urql의 5배가 넘는거 같다. 실제로 가장 작은 사이즈의 apollo가 30.7KB인데 이는 urql의 2배라고 한다.
  2. nextjs의 app router를 지원하는 패키지가 아직 정식 버전이 아니다.

Urql

사용법은 Apollo와 거의 흡사했다.

기본 설정

// @/lib/urql/UrqlWrapper.tsx
'use client';

import {
  cacheExchange,
  createClient,
  fetchExchange,
  ssrExchange,
  UrqlProvider,
} from '@urql/next';
import { useMemo } from 'react';

export default function UrqlWrapper({
  children,
}: {
  children: React.ReactNode;
}) {
  const [client, ssr] = useMemo(() => {
    const ssr = ssrExchange({
      isClient: typeof window !== 'undefined',
    });
    const client = createClient({
      url: process.env.NEXT_PUBLIC_BASE_URL || '',
      exchanges: [cacheExchange, ssr, fetchExchange],
      suspense: true,
    });

    return [client, ssr];
  }, []);

  return (
    <UrqlProvider client={client} ssr={ssr}>
      {children}
    </UrqlProvider>
  );
}
// layout.tsx
import UrqlWrapper from '@/lib/urql/UrqlWrapper';

export default function UrqlLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <UrqlWrapper>
      {children}
    </UrqlWrapper>
  );
}

rsc 설정

apollo와 마찬가지로 rsc 지원을 위한 별도 설정이 필요하다.

import { registerUrql } from '@urql/next/rsc';
import { cacheExchange, createClient, fetchExchange } from 'urql';

const makeClient = () => {
  return createClient({
    url: process.env.BASE_URL || 'http://localhost:3001/graphql',
    exchanges: [cacheExchange, fetchExchange],
  });
};

export const { getClient } = registerUrql(makeClient);

쿼리 사용하기

// @/lib/urql/queries
import { gql } from 'urql';

// 쿼리 선언 방법 Apollo와 동일하다.
export const GET_POST_LIST = gql`
  {
    posts {
      id
      title
    }
  }
`;

차이점이 있다면 apollo와 다르게 server component에서 상태 관리까지 해주진 못한다 ㅠ

import { GET_POST_LIST } from '@/lib/urql/queries';
import { getClient } from '@/lib/urql/UrqlClient';
import { Post } from '@/types/post';
import Link from 'next/link';

export default async function Page() {
  const { data } = await getClient().query<{ posts: Post[] }>(
    GET_POST_LIST,
    {}
  );
  return (
    <div>
      <ul>
        {data &&
          data.posts.map((el) => (
            <li key={el.id}>
              <Link href={`/test/${el.id}`}>{el.title}</Link>
            </li>
          ))}
      </ul>
    </div>
  );
}

장점

  1. 작고 가볍다.
  2. 기본 기능에 충실하다.

단점

  1. turbopack 문제인 듯하나 (참고) 데브모드에서 --turbopack을 붙이면 에러가 발생한다.
  2. 커뮤니티가 작다.
  3. 기본 기능외엔 페이지네이션이나 로컬 상태 관리 등의 다른 기능을 지원하지 않는다.

둘의 차이점

캐싱 방식의 차이가 있다. Apollo는 id를 사용한 정규화 캐싱을 사용하고 Urql은 Document 캐싱을 사용한다. => 아직 내용 파악이 안됐다 ㅠ 찾아봐야함

Urql

공식 문서 참고
urql은 데이터를 캐싱할 때 기준이 query와 그 변수이다.


정리

상태 관리, 페이지네이션, 에러 핸들링 등 다양한 기능이 필요하다 => Apollo
graphql 관련된 기능만 필요하다 => Urql

개인적으론, 러닝 커브가 있지만 고점이 높다는 Relay를 사용해보고 싶은데 next app router 버전부터는 공식 지원이 안돼서 아쉽다 ㅠ

참고

https://blog.logrocket.com/why-i-finally-switched-to-urql-from-apollo-client/
apollo client의 문제점
apollo vs relay vs urql

0개의 댓글