eatthefrog

[GraphQL] 스키마 폴링과 Introspection 보안 본문

백엔드 노트

[GraphQL] 스키마 폴링과 Introspection 보안

eater_forg 2026. 1. 3. 10:29

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 같은 도구의 기본 설정 때문에 발생합니다.

이 현상의 핵심인 IntrospectionSchema 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을 끄라고 강력히 권고하는 이유는 명확합니다.

  1. 공격자에게 평면도 제공: 설계도가 공개되면 어떤 필드에 취약점이 있을지, 어떤 중첩 쿼리로 서버를 마비시킬 수 있는지 공격자가 쉽게 파악할 수 있습니다.
  2. DoS 공격의 단초: 복잡한 Introspection 쿼리 자체가 서버 자원을 많이 소모하므로, 이를 악용한 서비스 거부 공격이 가능해집니다.
  3. 자원 낭비: 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을 차단하고, 개발 환경에서는 폴링 간격을 조절하는 작은 습관이 시스템의 안정성을 만듭니다.