본문 바로가기
IT & Tech 정보

🚀 GraphQL 서버 설계 및 구현: Apollo Server + TypeScript

by 지식과 지혜의 나무 2025. 5. 25.
반응형


안녕하세요!
이번에는 Apollo Server와 TypeScript를 활용해 GraphQL 서버를 설계·구현하는 과정을 단계별로 살펴보겠습니다.
기본적인 Query·Mutation 스키마부터 인증 적용까지, 실전에서 바로 써먹을 수 있는 코드 스니펫을 제공해 드려요.



📋 목차
1. GraphQL이란?
2. 프로젝트 초기 설정
3. 스키마(typeDefs) 정의
4. 리졸버(resolvers) 구현
5. Apollo Server 설정 및 실행
6. 인증 미들웨어 적용
7. 쿼리·뮤테이션 테스트 예시
8. 실전 팁



1️⃣ GraphQL이란?
• 장점
• 클라이언트가 필요한 데이터만 요청
• 단일 엔드포인트로 다양한 리소스 조회·변경
• 타입 시스템(TypeScript 연동)으로 안정적 개발
• 유스케이스
• 마이크로서비스 간 데이터 집계
• 모바일·웹 클라이언트별 맞춤 응답



2️⃣ 프로젝트 초기 설정

# 1) 새 디렉터리 생성 및 패키지 초기화
mkdir graphql-apollo-ts && cd graphql-apollo-ts
npm init -y

# 2) 필수 패키지 설치
npm install apollo-server graphql
npm install --save-dev typescript ts-node @types/node

# 3) TypeScript 설정
npx tsc --init --rootDir src --outDir dist --esModuleInterop true \
  --resolveJsonModule true --lib es6,dom --strict

# 4) 디렉터리 구조
# graphql-apollo-ts/
# ├─ src/
# │  ├─ schema.ts
# │  ├─ resolvers.ts
# │  └─ index.ts
# └─ tsconfig.json

// package.json (scripts)
"scripts": {
  "dev": "ts-node src/index.ts",
  "build": "tsc",
  "start": "node dist/index.js"
}




3️⃣ 스키마(typeDefs) 정의

// src/schema.ts
import { gql } from 'apollo-server';

export const typeDefs = gql`
  type User {
    id: ID!
    username: String!
    email: String!
  }

  type Query {
    users: [User!]!
    user(id: ID!): User
  }

  type Mutation {
    createUser(username: String!, email: String!): User!
  }
`;

• gql 태그로 GraphQL SDL(Schema Definition Language) 작성
• Query, Mutation 타입에 필드와 입력 인자 정의



4️⃣ 리졸버(resolvers) 구현

// src/resolvers.ts
import { IResolvers } from 'apollo-server';

interface User {
  id: string;
  username: string;
  email: string;
}

const users: User[] = [
  { id: '1', username: 'alice', email: 'alice@example.com' },
  { id: '2', username: 'bob',   email: 'bob@example.com' }
];

export const resolvers: IResolvers = {
  Query: {
    users: () => users,
    user: (_parent, args: { id: string }) => {
      return users.find(u => u.id === args.id) || null;
    }
  },
  Mutation: {
    createUser: (_parent, args: { username: string; email: string }) => {
      const newUser: User = {
        id: String(users.length + 1),
        username: args.username,
        email: args.email
      };
      users.push(newUser);
      return newUser;
    }
  }
};

• 메모리 배열을 간단한 데이터 저장소로 사용
• Query·Mutation 필드에 대응되는 함수 구현



5️⃣ Apollo Server 설정 및 실행

// src/index.ts
import { ApolloServer } from 'apollo-server';
import { typeDefs } from './schema';
import { resolvers } from './resolvers';

async function startServer() {
  const server = new ApolloServer({
    typeDefs,
    resolvers,
    context: ({ req }) => {
      // 인증 토큰 처리 등
      const token = req.headers.authorization || '';
      return { token };
    }
  });

  const { url } = await server.listen({ port: 4000 });
  console.log(`🚀 서버 실행 중: ${url}`);
}

startServer();

• context로 요청별 컨텍스트(예: 토큰, 사용자 정보) 주입
• 기본 포트 4000에서 GraphQL Playground 사용 가능



6️⃣ 인증 미들웨어 적용

// src/index.ts (일부 수정)
import jwt from 'jsonwebtoken';

// context 함수 수정
context: ({ req }) => {
  const auth = req.headers.authorization || '';
  let user = null;
  try {
    const payload = jwt.verify(auth.replace('Bearer ', ''), process.env.JWT_SECRET!);
    user = (payload as any).user;
  } catch {}
  return { user };
}

// src/resolvers.ts (Mutation 보호 예시)
Mutation: {
  createUser: (_parent, args, context) => {
    if (!context.user) throw new Error('인증이 필요합니다');
    // 신규 사용자 생성 로직...
  }
}

• HTTP 헤더 Authorization: Bearer <token> 파싱
• context.user에 페이로드 정보 저장 후, 리졸버에서 검사



7️⃣ 쿼리·뮤테이션 테스트 예시

# 1) 전체 사용자 조회
query {
  users {
    id
    username
    email
  }
}

# 2) 특정 사용자 조회
query {
  user(id: "1") {
    username
    email
  }
}

# 3) 사용자 생성 (인증 토큰 필요)
mutation {
  createUser(username: "charlie", email: "charlie@example.com") {
    id
    username
  }
}

• GraphQL Playground 또는 curl·Postman으로 호출 가능
• Authorization 헤더에 JWT 토큰 설정 필요



8️⃣ 실전 팁
• 모듈 분리: 스키마·리졸버를 도메인별 파일로 분리
• 타입 안정성: graphql-code-generator로 타입 자동 생성
• 데이터베이스 연동: Prisma·TypeORM과 조합해 ORM 사용
• 구독(Subscription): apollo-server에 WebSocket 설정 추가로 실시간 기능 지원



지금까지 Apollo Server + TypeScript 기반 GraphQL 서버의
기본 구성부터 인증 적용까지 살펴봤습니다.
스키마 설계·리졸버 구현·서버 실행 순서만 익히면
다양한 마이크로서비스·클라이언트 환경에 곧바로 적용할 수 있습니다.

다음 주제에서는 Redis 캐시 레이어 도입 (Node.js + ioredis) 로 찾아뵐게요!

반응형