리액트와 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는 효율적인 데이터 페칭, 프래그먼트 구성, 정적 쿼리 분석, 캐싱 등을 통해 리액트 애플리케이션의 데이터 관리를 최적화할 수 있습니다. 추가로 학습할 자료는 다음 링크를 참고하시기 바랍니다: