노트

GraphQL

GraphQL

백엔드#http · 연결된 개념 5개

쉽게 말하면

GraphQL은 정해진 세트 대신 빵, 속 재료, 소스를 골라 적는 샌드위치 주문처럼, 화면에 필요한 데이터 모양을 클라이언트가 적어 보내면 서버가 딱 그만큼 담아 주는 API예요. 덜 받거나 여러 번 갈 일이 없죠.

비유가 깨지는 곳 주문이 자유로운 만큼 대가가 있어요. URL 단위 HTTP 캐시가 어색하고, 리졸버를 순진하게 짜면 항목마다 쿼리가 나가는 N+1이 서버로 옮겨 가요. 깊은 쿼리엔 깊이·비용 제한도 필요해요.

GraphQL은 클라이언트가 필요한 데이터의 모양을 쿼리로 적어 보내면 서버가 정확히 그 모양으로 응답하는 API 쿼리 언어(query language)다. Facebook이 2012년 내부에서 만들어 2015년 공개했고, 지금은 GraphQL Foundation이 관리한다.

탄생 배경

모바일 앱 전환기에 REST로 복잡하게 얽힌 화면 데이터를 받으면 두 문제가 생겼다.

  • over-fetching: 이름과 사진만 필요한데 사용자 객체 전체를 받는다. 느린 모바일 망에서 비싸다
  • under-fetching: 한 화면에 필요한 데이터가 여러 리소스에 흩어져 요청을 여러 번 보낸다
  • 클라이언트마다 맞춤 엔드포인트와 API 버전이 늘어났다. 결론은 "데이터 모양은 클라이언트가 정하자"였다
query {
  post(id: "1") {
    title
    author { name profileImage }
    comments(first: 3) { text }
  }
}

특징

  • 강타입 스키마(strongly typed schema): 모든 타입과 필드를 스키마로 정의하고, 쿼리는 실행 전에 스키마로 검증된다. 서버와 클라이언트 사이의 계약이다
  • 인트로스펙션(introspection): API가 자기 스키마를 쿼리로 알려 준다. 문서·탐색 도구·타입 생성(codegen)이 여기서 나온다
  • 단일 엔드포인트(single endpoint): 보통 /graphql 하나. 요청은 Query(조회), Mutation(변경), Subscription(실시간 구독)
  • 버전 없는 진화: 필드를 추가해도 기존 쿼리는 그대로다. 없앨 필드는 @deprecated로 표시하고 사용량을 보며 지운다
  • 리졸버(resolver): 필드마다 데이터를 가져오는 함수를 붙인다. 필드별로 다른 DB·서비스에서 모아 오는 통합 계층으로도 쓴다

트레이드오프

  • 캐싱이 어렵다: URL 단위 HTTP 캐시가 자연스럽지 않아 클라이언트의 정규화 캐시(normalized cache)에 기댄다(브라우저 캐시, TanStack Query)
  • N+1이 서버로 옮겨 간다: 리졸버를 순진하게 짜면 목록의 항목마다 쿼리가 나간다. DataLoader로 묶어 처리한다(N+1 문제)
  • 복잡도 제어: 클라이언트가 깊은 중첩 쿼리를 만들 수 있어 깊이·비용 제한이 필요하다
  • 리소스가 단순하고 클라이언트가 하나면 REST가 더 간단하다

NestJS는 코드 우선(code-first)·스키마 우선(schema-first) 방식 모두를 지원한다. 내부 서비스 간 통신이라면 gRPC가 대안이다.

출처: GraphQL 학습 문서 · Introspection · Performance: The N+1 Problem · Facebook Engineering: GraphQL: A data query language (2015)

연결된 개념

이 노트를 가리키는 문서

뜻이 가까운 노트

  • JPQL과 @Query

    JPQL(Jakarta Persistence Query Language)은 테이블이 아니라 엔티티와 필드를 대상으로 쓰는 JPA의 객체 지향 쿼리 언어다. 실행할 때 연결된 DB의 SQL로 번역된다. Spring Data에서는 @Query로 리포지터리 메서드에 직접 붙인다.

  • 그래프

    정점(vertex, 노드)과 정점들을 잇는 간선(edge)으로 이루어진 자료구조. 트리도 그래프의 한 종류다. SNS 친구 관계, 지도와 경로, 웹 페이지 링크, 추천 시스템, 패키지 의존성처럼 "무엇과 무엇이 연결돼 있다"는 모든 것을 표현한다. 이 지식 맵도 노트를 정점, 링크를 간선으로 한 그래프다.

  • XSS

    XSS(Cross-Site Scripting)는 공격자가 넣은 스크립트가 내 사이트의 출처(origin) 권한으로 사용자 브라우저에서 실행되는 공격이다. 같은 출처의 코드로 돌기 때문에 same-origin-policy가 막아 주지 못한다. 그 스크립트는 페이지를 바꾸고, 로그인한 사용자 행세를 하며 요청을 보내고, JS가 읽을 수 있는 데이터(localStorage의 토큰 등)를 빼 갈 수 있다.

  • DRF 파서·렌더러와 콘텐츠 협상

    DRF에서 파서(Parser)는 요청 본문을 파이썬 자료형으로 바꾸고, 렌더러(Renderer)는 응답 데이터를 클라이언트가 받을 형식으로 바꾼다. 어떤 렌더러를 쓸지는 요청의 Accept 헤더를 보고 고르는데, 이를 콘텐츠 협상(content negotiation)이라 한다.

  • 브라우저 안에서 도는 RAG 구현기

    서버·요금 없이 방문자 브라우저에서 EmbeddingGemma 2로 찾고 Gemma 4로 답하는 RAG를 이 사이트에 넣은 사례. 프론트엔드 개발자가 알아야 할 개념을 구현 순서대로 짚는다.

보기 옵션