리액트와 GraphQL: Relay 사용하기


리액트와 GraphQL: Relay 사용하기


GraphQL은 데이터 쿼리 언어로, API 요청 시 필요한 데이터를 명확하게 지정할 수 있어 효율적입니다. 리액트(React) 애플리케이션에서 GraphQL을 사용하는 방법 중 하나는 Relay를 활용하는 것입니다. Relay는 Facebook에서 개발한 GraphQL 클라이언트로, 리액트 애플리케이션에서 데이터를 효율적으로 관리하고 최적화할 수 있게 도와줍니다. 이 포스팅에서는 Relay를 사용하여 리액트 애플리케이션에서 GraphQL을 구현하는 방법을 자세히 살펴보겠습니다.


Relay의 중요성


Relay는 GraphQL을 사용하는 리액트 애플리케이션에서 다음과 같은 장점을 제공합니다:

  • 자동 최적화: 중복된 요청을 제거하고, 효율적인 데이터 페칭을 수행합니다.
  • 프래그먼트 구성: 컴포넌트 간에 독립적인 데이터 요청을 정의하고 재사용할 수 있습니다.
  • 정적 쿼리 분석: 빌드 시점에서 쿼리를 분석하여 최적화합니다.
  • 캐싱: 요청 결과를 캐싱하여 성능을 향상시킵니다.

프로젝트 설정 및 Relay 설치


Relay를 사용하기 위해 필요한 패키지를 설치합니다. 다음 명령어를 사용하여 프로젝트를 생성하고 필요한 패키지를 설치합니다.


npx create-react-app my-relay-app --template typescript
cd my-relay-app
npm install react-relay relay-runtime graphql

Relay 환경 설정


Relay를 사용하기 위해서는 Relay 환경을 설정해야 합니다. 이를 위해 Relay 환경 설정 파일을 생성합니다.


// src/RelayEnvironment.ts
import { Environment, Network, RecordSource, Store } from 'relay-runtime';

async function fetchQuery(operation, variables) {
  const response = await fetch('https://your-graphql-endpoint.com/graphql', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      query: operation.text,
      variables,
    }),
  });
  return await response.json();
}

const environment = new Environment({
  network: Network.create(fetchQuery),
  store: new Store(new RecordSource()),
});

export default environment;

위 코드에서는 fetchQuery 함수를 정의하여 GraphQL 요청을 수행하고, Relay 환경을 생성합니다.


기본 사용법


Relay를 사용하여 기본적인 데이터 쿼리와 컴포넌트를 설정해보겠습니다.


데이터 쿼리 작성


먼저, GraphQL 쿼리를 정의합니다.


# src/queries/UserQuery.graphql
query UserQuery($id: ID!) {
  user(id: $id) {
    id
    name
    email
  }
}

컴포넌트 설정


Relay를 사용하여 데이터를 쿼리하고, 컴포넌트에서 이를 사용하는 방법을 살펴보겠습니다.


// src/App.tsx
import React from 'react';
import { QueryRenderer, graphql } from 'react-relay';
import environment from './RelayEnvironment';

const App: React.FC = () => {
  return (
    <QueryRenderer
      environment={environment}
      query={graphql`
        query UserQuery($id: ID!) {
          user(id: $id) {
            id
            name
            email
          }
        }
      `}
      variables={{ id: '1' }}
      render={({ error, props }) => {
        if (error) {
          return <div>Error: {error.message}</div>;
        }
        if (!props) {
          return <div>Loading...</div>;
        }
        return (
          <div>
            <h1>{props.user.name}</h1>
            <p>{props.user.email}</p>
          </div>
        );
      }}
    />
  );
};

export default App;

위 코드에서는 QueryRenderer를 사용하여 GraphQL 쿼리를 실행하고, 데이터를 받아와 화면에 렌더링합니다.


프래그먼트 사용


Relay의 프래그먼트는 컴포넌트별로 데이터를 독립적으로 요청하고 재사용할 수 있게 해줍니다.


프래그먼트 정의


먼저, 프래그먼트를 정의합니다.


# src/fragments/UserFragment.graphql
fragment UserFragment_user on User {
  id
  name
  email
}

프래그먼트 사용


프래그먼트를 사용하여 컴포넌트에서 데이터를 요청합니다.


// src/UserComponent.tsx
import React from 'react';
import { createFragmentContainer, graphql } from 'react-relay';

const UserComponent: React.FC<{ user: any }> = ({ user }) => {
  return (
    <div>
      <h1>{user.name}</h1>
      <p>{user.email}</p>
    </div>
  );
};

export default createFragmentContainer(UserComponent, {
  user: graphql`
    fragment UserFragment_user on User {
      id
      name
      email
    }
  `,
});

프래그먼트를 포함한 쿼리


쿼리에서 프래그먼트를 포함하여 데이터를 요청합니다.


// src/App.tsx
import React from 'react';
import { QueryRenderer, graphql } from 'react-relay';
import environment from './RelayEnvironment';
import UserComponent from './UserComponent';

const App: React.FC = () => {
  return (
    <QueryRenderer
      environment={environment}
      query={graphql`
        query UserQuery($id: ID!) {
          user(id: $id) {
            ...UserFragment_user
          }
        }
      `}
      variables={{ id: '1' }}
      render={({ error, props }) => {
        if (error) {
          return <div>Error: {error.message}</div>;
        }
        if (!props) {
          return <div>Loading...</div>;
        }
        return <UserComponent user={props.user} />;
      }}
    />
  );
};

export default App;

뮤테이션 사용


Relay를 사용하여 GraphQL 뮤테이션을 수행할 수 있습니다.


뮤테이션 정의


먼저, 뮤테이션을 정의합니다.


# src/mutations/CreateUserMutation.graphql
mutation CreateUserMutation($input: CreateUserInput!) {
  createUser(input: $input) {
    user {
      id
      name
      email
    }
  }
}

뮤테이션 실행


뮤테이션을 실행하여 데이터를 전송합니다.


// src/CreateUserComponent.tsx
import React, { useState } from 'react';
import { commitMutation, graphql } from 'react-relay';
import environment from './RelayEnvironment';

const mutation = graphql`
  mutation CreateUserMutation($input: CreateUserInput!) {
    createUser(input: $input) {
      user {
        id
        name
        email
      }
    }
  }
`;

const CreateUserComponent: React.FC = () => {
  const [name, setName] = useState('');
  const [email, setEmail] = useState('');

  const handleSubmit = (e: React.FormEvent) => {
    e.preventDefault();
    const variables = {
      input: {
        name,
        email,
      },
    };
    commitMutation(environment, {
      mutation,
      variables,
      onCompleted: (response) => {
        console.log('Response received:', response);
      },
      onError: (err) => console.error(err),
    });
  };

  return (
    <form onSubmit={handleSubmit}>
      <div>
        <label htmlFor="name">Name</label>
        <input
          id="name"
          type="text"
          value={name}
          onChange={(e) => setName(e.target.value)}
        />
      </div>
      <div>
        <label htmlFor="email">Email</label>
        <input
          id="email"
          type="email"
          value={email}
          onChange={(e) => setEmail(e.target.value)}
        />
      </div>
      <button type="submit">Create User</button>
    </form>
  );
};

export default CreateUserComponent;

위 코드에서는 사용자가 입력한 데이터를 뮤테이션을 통해 서버에 전송하고, 응답을 받아와 처리합니다.


주요 포인트 요약 및 추가 학습 자료


이 포스팅에서는 Relay를 사용하여 리액트 애플리케이션에서 GraphQL을 구현하는 방법에 대해 살펴보았습니다. Relay는 효율적인 데이터 페칭, 프래그먼트 구성, 정적 쿼리 분석, 캐싱 등을 통해 리액트 애플리케이션의 데이터 관리를 최적화할 수 있습니다. 추가로 학습할 자료는 다음 링크를 참고하시기 바랍니다:


다음 이전