[GraphQL] GraphQL Codegen으로 보안 스키마 가져오기
Introspection 대신 GitHub SDL로 보안 강화
기존 방식의 문제점
GraphQL Introspection 기반 스키마 조회
기존에는 GraphQL API 엔드포인트에서 Introspection을 통해 직접 스키마를 가져오는 방식을 사용했습니다.
// codegen.ts (기존)
import type { CodegenConfig } from "@graphql-codegen/cli";
const config: CodegenConfig = {
schema: "https://api.example.com/graphql",
documents: "src/**/*.gql",
generates: {
// TypeScript 타입, React Hooks, 로컬 스키마 생성
},
};
이 방식은 설정이 단순하고 편리하지만 프로덕션 환경에서는 다음과 같은 문제가 있습니다.
보안 측면의 한계
GraphQL Introspection은 __schema 쿼리를 통해 API의 전체 스키마 구조를 조회할 수 있는 기능입니다.
개발 단계에서는 유용하지만 프로덕션 환경에서는 다음과 같은 문제가 존재합니다.
- API 전체 구조 노출
- 내부용 쿼리 / 뮤테이션 노출 가능성
- 공격 위험 증가
이 때문에 많은 팀에서 프로덕션 환경에서는 Introspection을 비활성화하거나 제한합니다.
GraphQL 스키마 보안을 강화하는 방법들
프로덕션 환경에서 GraphQL 스키마를 안전하게 관리하는 방식은 여러 가지가 있습니다.
1. 프로덕션에서 Introspection 비활성화
- 가장 기본적인 보안 조치
- API 구조 노출 방지 가능
다만 이 방식만 사용할 경우 프론트엔드에서 Codegen을 실행하려면 여전히 API 서버 접근이 필요합니다.
2. 인증된 사용자에게만 Introspection 허용
- 특정 권한(API Key, JWT 등)을 가진 요청만 허용
- 외부 접근은 차단
하지만 이 경우에도 인증 토큰 관리가 필요하고 API 서버 상태에 Codegen이 의존하게 됩니다.
3. 로컬 SDL(schema.graphql) 파일 사용
- Introspection 없이 로컬 SDL 파일을 스키마 소스로 사용
- API 서버 접근 완전 제거 가능
다만 팀원끼리 스키마를 계속 동기화해야 하고, 누가 언제 뭘 바꿨는지 추적하기가 번거롭습니다.
4. GitHub 기반 SDL 관리 (선택한 방식)
이 글에서는 위 방식들 중
👉 GitHub Repository에 버전 관리된 SDL 스키마를 단일 소스로 사용하는 방식을 선택했습니다.
이 방식을 선택하면 앞서 말한 문제들을 해결할 수 있습니다.
- 프로덕션 API에서 Introspection을 완전히 끌 수 있음
- Codegen이 API 서버에 의존하지 않아도 됨
- 스키마 변경 이력을 Git으로 추적할 수 있음
- 브랜치만 바꾸면 개발 중인 스키마도 바로 확인 가능
개선한 방식: GitHub 기반 스키마 관리
백엔드 레포에 있는 GraphQL SDL 스키마 파일을 Codegen에서 직접 가져오도록 변경했습니다.
GITHUB TOKEN 발급
Private Repository에 접근하려면 GitHub Personal Access Token(PAT)이 필요해서 환경 변수로 설정했습니다.
# .env
YOUR_GITHUB_TOKEN=ghp_xxxxxxxxxxxxxxxxxxxx
codegen.ts 설정
GraphQL Code Generator는 HTTP(S)를 통해 원격 SDL 스키마를 직접 가져오는 방식을 공식적으로 지원합니다.
const config: CodegenConfig = {
schema: {
// GitHub에 버전 관리된 GraphQL-SDL 스키마
// https://raw.githubusercontent.com/{org}/{repo}/{branch}/path/to/schema.gql
[GITHUB_SCHEMA_URL]: {
method: "GET",
handleAsSDL: true,
headers: {
Authorization: `token ${process.env.YOUR_GITHUB_TOKEN}`,
},
},
},
documents: "src/**/*.gql",
generates: {
// TypeScript 타입, React Hooks, 로컬 스키마 생성
},
};
export default config;
작동 흐름
1. npm run gqlgen 실행
↓
2. codegen.ts 실행
↓
3. GitHub Raw URL을 통해 SDL 스키마 다운로드
↓
4. .gql 쿼리 파일 분석
↓
5. 코드 생성
- TypeScript 타입
- Apollo Client Hooks
- schema.graphql (에디터 지원용)
이 과정에서 API 서버는 전혀 호출되지 않고 스키마는 GitHub에 저장된 파일만을 기준으로 사용됩니다.
장점
보안 측면
- 프로덕션 GraphQL API에서 Introspection 완전 제거
- API 구조 외부 노출 방지
- Codegen 실행을 위한 서버 접근 권한 최소화
개발 생산성
이 방식의 가장 큰 장점은 브랜치만 바꿔서 바로 작업 중인 스키마를 확인할 수 있다는 점입니다.
- 백엔드 서버 실행 없이 스키마 파악 가능
- 프론트엔드 개발을 백엔드 환경과 분리
- 스키마 변경 흐름을 Git PR 기준으로 추적 가능
// ex) feat/admin-user 브랜치의 스키마를 바로 참조
const GITHUB_SCHEMA_URL =
"https://raw.githubusercontent.com/org/repo/feat/admin-user/schema.gql";
결론
백엔드에서 ApolloServer Introspection을 껐을 때 프론트에서 GitHub에 있는 SDL 스키마를 직접 가져오는 방식으로 우회하는 방법을 소개했습니다.
이 방식으로 바꾸면서 보안을 강화하고 브랜치 별로 스키마에 접근할 수 있게 되어 개발이 더욱 편리해졌습니다.
댓글남기기