eatthefrog
[GraphQL] 스키마 폴링과 Introspection 보안 본문
https://www.reddit.com/r/graphql/comments/cdzyxl/playground_wont_stop_requesting_data/?tl=ko
Reddit의 graphql 커뮤니티
graphql 커뮤니티에서 이 게시물을 비롯한 다양한 콘텐츠를 살펴보세요
www.reddit.com
분명히 요청을 몇 번 보내지도 않았는데 서버에서 429 Too Many Requests 에러가 발생했습니다. 이는 주로 Apollo Sandbox나 GraphQL Playground 같은 도구의 기본 설정 때문에 발생합니다.
이 현상의 핵심인 Introspection과 Schema Polling을 파헤쳐보고, 보안과 자원 효율성을 모두 챙기는 방법을 알아보겠습니다.
1. Introspection: GraphQL의 자기소개서
Introspection(자기 성찰)은 클라이언트가 GraphQL 서버에게 "너는 어떤 스키마(타입, 쿼리, 뮤테이션)를 가지고 있니?"라고 물어보는 특수 쿼리입니다.
- 기능: 서버의 설계도(Schema)를 JSON 형태로 반환합니다.
- 활용: 이 데이터를 바탕으로 개발 도구들은 코드 자동 완성, 문서화, 타입 체크 기능을 제공합니다.
2. 스키마 폴링(Schema Polling): "바뀌었니? 지금은?"
스키마 폴링은 개발 도구가 최신 스키마를 유지하기 위해 Introspection 쿼리를 주기적으로(기본 2초) 보내는 행위입니다.
⚠️ 왜 429 에러(Rate Limit)가 발생할까?
대부분의 API 서버는 보안을 위해 Rate Limit(요청 제한)을 설정합니다. (예: 15분당 100회 요청)
- 폴링의 계산식: 2초마다 1회 요청 시,
-
$$\text{1분} = 30\text{회}, \quad \text{15분} = 450\text{회}$$
- 결과: 사용자가 실제 쿼리를 단 한 번도 보내지 않아도, Sandbox 창을 열어둔 것만으로도 15분 만에 제한량의 4.5배를 초과하게 됩니다.
https://www.reddit.com/r/graphql/comments/zxj9df/is_there_a_way_to_slow_the_polling_interval_in/
Reddit의 graphql 커뮤니티
graphql 커뮤니티에서 이 게시물을 비롯한 다양한 콘텐츠를 살펴보세요
www.reddit.com
3. 편리함 뒤에 숨겨진 보안 위험
공식 문서들이 운영 환경에서 Introspection을 끄라고 강력히 권고하는 이유는 명확합니다.
- 공격자에게 평면도 제공: 설계도가 공개되면 어떤 필드에 취약점이 있을지, 어떤 중첩 쿼리로 서버를 마비시킬 수 있는지 공격자가 쉽게 파악할 수 있습니다.
- DoS 공격의 단초: 복잡한 Introspection 쿼리 자체가 서버 자원을 많이 소모하므로, 이를 악용한 서비스 거부 공격이 가능해집니다.
- 자원 낭비: 2초마다 발생하는 불필요한 트래픽은 서버 로그를 오염시키고 불필요한 비용을 발생시킵니다.
https://graphql.org/learn/security/
Security | GraphQL
September 08–10 Amsterdam, Netherlands
graphql.org
- 핵심 내용: "공격자가 스키마를 알게 되면, 어떤 필드가 민감한지 혹은 어떤 중첩 쿼리를 보내 서버를 마비시킬 수 있는지(DoS) 쉽게 파악할 수 있다." "Introspection은 개발 도구(Sandbox 등)에 스키마 정보를 제공하여 자동 완성 등을 돕지만, 운영 환경(Production)에서는 반드시 꺼야(Disabled) 한다"고 명시하고 있습니다.
- 권장 사항: 운영 환경에서는 Introspection을 비활성화할 것. 2. 개발 시에는 수동으로 스키마를 업데이트하거나, 로컬 파일을 참조할 것.
4. 더 나은 보안을 위한 개선 전략
"보안과 자원 효율을 위해 개발자가 수동으로 업데이트하는 것이 맞지 않나?"라는 의문은 매우 합리적입니다. 현업에서는 다음과 같이 계층별로 대응합니다.
① 환경별 차등 설정 (Production vs Development)
가장 기본적이면서 강력한 조치입니다.
const server = new ApolloServer({
typeDefs,
resolvers,
// 운영 환경에서는 설계도 노출을 원천 차단합니다.
introspection: process.env.NODE_ENV !== "production",
});
② 도구 설정 최적화 (DX 개선)
개발 환경에서도 2초 폴링은 과합니다. Apollo Sandbox 설정에서 다음을 조정하세요.
- Polling OFF: 스키마를 수정했을 때만 수동으로 Refresh 버튼을 누릅니다.
- Interval 조정: 폴링이 꼭 필요하다면 간격을 1분(60,000ms) 이상으로 늘립니다.
③ 로컬 스키마 참조 (Codegen 활용)
서버에 매번 물어보는 대신, 로컬에 저장된 schema.graphql 파일을 참조하도록 설정합니다. 이는 네트워크 요청이 발생하지 않으므로 가장 안전하고 빠릅니다.
5. 결론: 보안은 '당연한 것'과의 싸움
도구들의 "기본 설정(Default)"은 언제나 "가장 편리한 상태"를 지향하지, "가장 안전한 상태"를 지향하지 않습니다.
2초마다 설계도를 묻는 친절함이 때로는 서버를 멈추게 하는 독이 될 수 있습니다. 운영 환경에서는 Introspection을 차단하고, 개발 환경에서는 폴링 간격을 조절하는 작은 습관이 시스템의 안정성을 만듭니다.
'백엔드 노트' 카테고리의 다른 글
| [GraphQL] 설계도: 배열 필드 페이징 (0) | 2026.01.03 |
|---|---|
| [GraphQL] 보안 : 쿼리 깊이 제한, 일괄 요청 제한 (0) | 2026.01.03 |
| MongoDB 연결 옵션 Deprecation 경고 해결하기 (0) | 2025.12.18 |
| MongoDB를 잘 사용했을 때 얻는 이점 (0) | 2025.11.20 |
| MongoDB MCP 서버 (0) | 2025.11.20 |