1. Apollo Client 설정 (App Router 버전)
Apollo Client 설정 (lib/apolloClient.ts
)
클라이언트 환경에서 Apollo Client를 생성하는 설정입니다.
// lib/apolloClient.ts
import { ApolloClient, InMemoryCache } from "@apollo/client";
import { createUploadLink } from "apollo-upload-client";
const apolloClient = new ApolloClient({
link: createUploadLink({
uri: process.env.NEXT_PUBLIC_API_BASE_URL,
credentials: "include", // 쿠키 포함
}),
cache: new InMemoryCache(),
});
export default apolloClient;
2. ApolloProvider 설정
클라이언트 컴포넌트에서 ApolloProvider 사용
App Router의 구조에서는 ApolloProvider
를 클라이언트 컴포넌트에서 사용해야 합니다.
ApolloProvider
를 설정하려면 components/ApolloWrapper.tsx
처럼 Wrapper 컴포넌트를 만들어 사용하는 것이 좋습니다.
// components/ApolloWrapper.tsx
"use client";
import { ApolloProvider } from "@apollo/client";
import apolloClient from "../lib/apolloClient";
export default function ApolloWrapper({ children }: { children: React.ReactNode }) {
return <ApolloProvider client={apolloClient}>{children}</ApolloProvider>;
}
3. App Layout에 ApolloWrapper 적용
app/layout.tsx
에서 ApolloWrapper
를 감싸도록 설정합니다.
// app/layout.tsx
import ApolloWrapper from "../components/ApolloWrapper";
import "./globals.css";
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
<body>
<ApolloWrapper>{children}</ApolloWrapper>
</body>
</html>
);
}
4. 서버 컴포넌트에서 데이터 패칭
App Router에서 서버 컴포넌트를 사용하는 경우 Apollo Client는 클라이언트에서 동작하므로, 서버에서 GraphQL 데이터를 가져오려면 graphql-request
나 @apollo/client
의 fetch
기반 도구를 사용할 수 있습니다.
서버 컴포넌트 예시
// app/page.tsx
import { gql } from "graphql-request";
import { request } from "graphql-request";
export const metadata = {
title: "Apollo with App Router",
};
export default async function Page() {
const query = gql`
query ExampleQuery {
exampleField
}
`;
const data = await request(process.env.NEXT_PUBLIC_API_BASE_URL!, query);
return (
<div>
<h1>Data from GraphQL:</h1>
<pre>{JSON.stringify(data, null, 2)}</pre>
</div>
);
}
Next.js의 App Router 환경에서 "use client"
를 사용하는 컴포넌트에서 Apollo Client를 통해 GraphQL 쿼리를 실행하려면, Apollo Client의 useQuery
나 useMutation
훅을 사용하면 됩니다. 이 경우 클라이언트 컴포넌트에서만 실행됩니다.
5. 클라이언트 컴포넌트에서 데이터 패칭
클라이언트 컴포넌트에서 쿼리 실행
"use client";
import { gql, useQuery } from "@apollo/client";
const GET_DATA = gql`
query GetData {
exampleField
}
`;
export default function ExampleClientComponent() {
const { data, loading, error } = useQuery(GET_DATA);
if (loading) return <p>Loading...</p>;
if (error) return <p>Error: {error.message}</p>;
return (
<div>
<h1>Data from GraphQL:</h1>
<pre>{JSON.stringify(data, null, 2)}</pre>
</div>
);
}
useQuery
동작:- Apollo Client는 자동으로 데이터를 캐시하고 업데이트합니다.
loading
,error
,data
상태를 관리합니다.
클라이언트 컴포넌트에서 데이터 뮤테이션 실행
"use client";
import { gql, useMutation } from "@apollo/client";
const ADD_ITEM = gql`
mutation AddItem($input: AddItemInput!) {
addItem(input: $input) {
id
name
}
}
`;
export default function MutationClientComponent() {
const [addItem, { data, loading, error }] = useMutation(ADD_ITEM);
const handleAddItem = async () => {
try {
await addItem({
variables: {
input: { name: "New Item" }, // 입력 값
},
});
} catch (e) {
console.error("Error adding item:", e);
}
};
return (
<div>
<button onClick={handleAddItem} disabled={loading}>
Add Item
</button>
{loading && <p>Loading...</p>}
{error && <p>Error: {error.message}</p>}
{data && <p>Item added: {JSON.stringify(data.addItem)}</p>}
</div>
);
}
useMutation
동작:- 실행 함수 (
addItem
)를 반환합니다. - 실행 결과를
data
,loading
,error
로 관리합니다.
- 실행 함수 (
클라이언트 컴포넌트에서의 추가 고려사항
- ApolloProvider 적용 확인: 클라이언트 컴포넌트에서 Apollo Client를 사용하려면 반드시
ApolloProvider
가 적용된 상태여야 합니다. (app/layout.tsx
에 설정) - Dynamic Import: 클라이언트 컴포넌트를 서버 컴포넌트에서 호출하려면
dynamic
을 사용할 수 있습니다.
import dynamic from "next/dynamic";
const DynamicClientComponent = dynamic(() => import("../components/ExampleClientComponent"), { ssr: false });
export default function Page() {
return (
<div>
<h1>Server Component</h1>
<DynamicClientComponent />
</div>
);
}
- DevTools 사용: Apollo Client DevTools를 활성화하면 브라우저에서 쿼리 상태와 데이터를 디버깅할 수 있습니다.
상태 관리 및 캐싱 전략
- Apollo Cache:
useQuery
로 가져온 데이터는 Apollo의 캐시 시스템에 저장됩니다. 이를 통해 동일한 데이터를 반복적으로 요청하지 않고, 효율적으로 관리할 수 있습니다. - 캐시 업데이트:
useMutation
의update
옵션을 사용하면 캐시를 수동으로 업데이트할 수 있습니다.
const [addItem] = useMutation(ADD_ITEM, {
update(cache, { data: { addItem } }) {
cache.modify({
fields: {
items(existingItems = []) {
return [...existingItems, addItem];
},
},
});
},
});
5. DevTools 활성화
Apollo Client DevTools는 클라이언트 환경에서만 동작하므로 App Router와 함께 사용하려면 아래 단계를 참고하세요.
DevTools 활성화 조건
ApolloClient
가 브라우저 환경에서 동작하도록 설정.- DevTools 확장 프로그램 설치 필요.
// lib/apolloClient.ts (개발 환경에서 DevTools 활성화)
import { ApolloClient, InMemoryCache } from "@apollo/client";
import { createUploadLink } from "apollo-upload-client";
const apolloClient = new ApolloClient({
link: createUploadLink({
uri: process.env.NEXT_PUBLIC_API_BASE_URL,
credentials: "include",
}),
cache: new InMemoryCache(),
});
if (typeof window !== "undefined" && process.env.NODE_ENV === "development") {
import("@apollo/client/devtools").then((devtools) => devtools);
}
export default apolloClient;
요약
- 클라이언트 컴포넌트에서
ApolloProvider
를 사용하여 Apollo Client를 적용. - 서버 컴포넌트에서 데이터 패칭은
graphql-request
또는 서버 fetch를 활용. - 클라이언트 컴포넌트에서 데이터 페칭은
useQuery, useMutation
을 사용. - Apollo DevTools는 개발 환경에서 활성화.
'TIL' 카테고리의 다른 글
[241209 TIL] AWS - RDS, EB 에 nest 배포(2) (0) | 2024.12.09 |
---|---|
[241208 TIL] AWS - RDS, EB 에 nest 배포(1) (0) | 2024.12.09 |
[241115 TIL] as const (0) | 2024.11.15 |
[241115 TIL] abstract, implements (2) | 2024.11.15 |
[241113 TIL] 5432 port 사용중일때 (0) | 2024.11.13 |