본문 바로가기
개발/Next.js

Next.js + Graphql

by oneday-lifeDev 2025. 8. 22.
반응형

Nextjs

1. Next.js + GraphQL 프로젝트

간단한 게시판 프로젝트를 생각하며 , 프론트엔드 공부를 시작한지 얼마 안되서, Rest API 개념을 배우고 , 팀프로젝트서 , 

 

프론트 : Next.js + Apollo Client 

 

서버 : Nest.js + GraphQL

 

쇼핑몰 프로젝트를 한적이 있었다. 당시에 GraphQL PlayGround 를 만지면서 작업하다보니 , 굉장히 편하다 느낌을 굉장히 많이 받았다. 

 

 

이전에 기억이 좋아서 , 이번에 간단한 게시판 사이트를 한번 만들어보자! 라는 생각에 

Next.js + Apollo Client + GraphQL 을 사용함으로써 ,

Rest api를 사용하면서 Swagger 문서 작성하는게 시간 소모가 굉장히 크기에 , GraphQL은 우리가 사용하는 

 

Query, Mutation 에 대한 코드작성만 잘한다면 문제없이, PlayGround에 문서화로 작성이 잘 되어져 혼자 프로젝트를 하더라도 

 

시간소모를 많이 막아줄거라 생각해서, 선택하게된 상황입니다.

 

 

2. 설치

 

 

 

Next.js App router 

npx create-next-app@latest

 

설치를 먼저 하고서 , 

GraphQL 패키지를 설치합니다. 

npm install @apollo/server @as-integrations/next graphql graphql-tag
npm install @apollo/client

 

차례대로 파일을 세팅을 해야합니다.

 

1) GraphQL API 엔드포인트 생성 (route.ts)

// app/api/graphql/route.ts
import { ApolloServer } from '@apollo/server';
import { startServerAndCreateNextHandler } from '@as-integrations/next';
import { typeDefs } from '@/lib/graphql/schema';
import { resolvers } from '@/lib/graphql/resolvers';

const server = new ApolloServer({
  typeDefs, // 데이터 스키마 정의
  resolvers, // 실제 데이터 처리 로직
});

// Next.js와의 통합 
// @as-intergrations/next 패키지가 Apollo Server를 Next.js API Route와 연결
// Next.js의 Request/Response 객체를 Apollo Server가 이해할 수 있는 형태로 변환
const handler = startServerAndCreateNextHandler(server);
export { handler as GET, handler as POST };

 

  • Apollo Server는 GraphQL 사양을 완전히 구현한 서버입니다.
  • typeDefs 와 resolvers를 결합해서 완전한 GraphQL API를 만듭니다.

 

2) Apollo Client 설정(apollo-client.ts)

// lib/apollo-client.ts
import { ApolloClient, InMemoryCache, createHttpLink } from '@apollo/client';

const httpLink = createHttpLink({
  uri: '/api/graphql',  // 위에서 만든 API 엔드포인트
});

export const apolloClient = new ApolloClient({
  link: httpLink,
  cache: new InMemoryCache(),  // 쿼리 결과 캐싱
});

 

역할: 클라이언트 사이드에서 GraphQL API와 통신할 수 있는 Apollo Client를 설정합니다. 캐싱과 상태 관리도 담당합니다.

 

3) GraphQL 스키마 정의(schema.ts)

// lib/graphql/schema.ts
import { gql } from 'graphql-tag';

export const typeDefs = gql`
  type User {
    id: ID!
    email: String!
    name: String
    created_at: String!
  }
  
  type Query {
    users: [User!]!
    user(id: ID!): User
  }
  
  type Mutation {
    createUser(input: CreateUserInput!): User!
  }
  
  input CreateUserInput {
    email: String!
    name: String
  }
`;

 

간단한 스키마를 작성했습니다. 

 

Type 정의

type User {
  id: ID!
  email: String!
  name: String
  created_at: String!
}
  • User 라는 데이터 타입을 정의 
  • ! 는 필수 필드(null 불가)
  • ID! : 고유 식별자(필수)
  • String!: 문자열 (필수)
  • String: 문자열(선택적)

Query 정의 

type Query {
  users: [User!]!
  user(id: ID!): User
}
  • 데이터를 읽는 작업들을 정의 
  • users:User 배열을 반환(빈 배열 가능, null 불가)
  • user(id: ID!): ID를 받아서 특정 User 반환(null 가능)

Mutation 정의

type Mutation {
  createUser(input: CreateUserInput!): User!
}
  • 데이터를 변경하는 작업들을 Mutation 작업들을 정의 
  • 현재는 createUser : 새 사용자 생성 -> CreateUserInput! 을 받아서 User!를 반환

Input 타입 

input CreateUserInput {
  email: String!
  name: String
}
  • 함수의 매개변수 역할 
  • email 은 필수 , name은 선택적

4) Apollo Provider 설정 (providers.tsx)

// providers/apollo-provider.tsx
'use client';
import { ApolloProvider } from '@apollo/client';
import { apolloClient } from '@/lib/apollo-client';

export function ApolloProviderWrapper({ children }: { children: React.ReactNode }) {
  return (
    <ApolloProvider client={apolloClient}>
      {children}
    </ApolloProvider>
  );
}




// app/layout.tsx
import { ApolloProviderWrapper } from '@/providers/apollo-provider';
import { StoreProvider } from "@/store/store-provider";

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <body>
        <ApolloProviderWrapper>
          <StoreProvider>
            {children}
          </StoreProvider>
        </ApolloProviderWrapper>
      </body>
    </html>
  );
}

 

!! Apollo Provide를 만드는 이유는 React Context 시스템 때문입니다.

React Context의 작동방식 -> 

React 데이터 상위 컴포넌트에서 하위 컴포넌트로 전달할 때 Props를 통해 단계별로 내려줘야합니다. 하지만 Apollo Client 같은 전역 상태는 모든 컴포넌트에서 사용해야 하는데, 매번 props로 전달하기 어려워 Provider를 통해 전역에서 쉽게 사용이 가능하도록 세팅을 해줍니다. 그리고 Next.js 프레임워크 app router 에서 서버 컴포넌트와 , 클라이언트 컴포넌트의 분리에 대한 이유로 "use client" 지시어를 작성해야하는 상황이다 보니 , 별도 파일로 분리해서 명시를 해줘야합니다. 

 

하위 컴포넌트에서 useQuery, useMutation  사용 시 자동으로 해당 client 를 찾으며 , 별도로 client 를 전달하지 않아도 됩니다. 

이렇게 하면 전역에서 GraphQL 쿼리를 간편하게 사용할 수 있습니다. 

 

프로젝트를 세팅 후 , 내가 필요로한 라이브러리를 하나 하나 선택하며 나는 이러한 이유로 이걸 택했어, 자신있게 설명하며 

내가 이걸 통해서 이런 점에서 퍼포먼스를 보여줬다는걸 기록하는 습관을 가지는게 목표입니다. 

반응형

'개발 > Next.js' 카테고리의 다른 글

Socket.io 를 활용한 상태값 주기적 체크  (0) 2025.01.09