본문으로 건너뛰기
중급20

GraphQL 테스트: REST와 다른 점, 쿼리·뮤테이션 검증하기

GraphQL은 하나의 엔드포인트로 원하는 데이터만 골라 받는다. REST와 다른 이 구조가 테스트 관점에서 무엇을 다르게 만드는지 이해한다.

  • #GraphQL
  • #API테스트
  • #N플러스1

개념

REST와 GraphQL의 근본적 차이

레슨 1~5에서 다룬 API들은 REST 방식이었다 — 자원마다 별도의 URL(/orders, /products)과 메서드(모듈 9 레슨 2)로 구분됐다. GraphQL은 다르다.

REST:    GET /orders/123          → 그 엔드포인트가 정해준 필드를 통째로 받음
GraphQL: POST /graphql (쿼리 포함)  → 클라이언트가 원하는 필드만 골라서 요청

GraphQL은 엔드포인트가 하나(보통 /graphql)이고, 무엇을 가져올지는 요청 본문에 담긴 **쿼리(Query)**가 결정한다.

query {
  order(id: "123") {
    orderId
    totalPrice
    items {
      productName
    }
  }
}

이 쿼리는 "주문 123번의 주문ID, 총액, 그리고 담긴 상품들의 이름만"을 요청한다 — REST였다면 서버가 미리 정해둔 응답 구조를 통째로 받아야 했을 것을, 필요한 부분만 선택해서 받는다.

쿼리(Query)와 뮤테이션(Mutation)

  • 쿼리 — 데이터를 조회한다(REST의 GET에 대응)
  • 뮤테이션(Mutation) — 데이터를 변경한다(REST의 POST/PUT/DELETE에 대응)
mutation {
  createOrder(productId: "P001", quantity: 2) {
    orderId
    totalPrice
  }
}

레슨 2~3에서 배운 어서션 작성법은 GraphQL에도 그대로 적용된다 — 다만 확인 대상이 "이 쿼리에 대해 정확히 요청한 필드들이 돌아왔는가"로 조금 달라진다.

상태 코드만으로는 부족하다

GraphQL은 요청 자체가 잘못되지 않는 한 대부분 상태 코드 200으로 응답한다 — 심지어 요청한 데이터를 찾지 못해도 200을 주고, 본문 안에 errors 필드로 에러를 표현하는 경우가 많다.

{
  "data": { "order": null },
  "errors": [{ "message": "주문을 찾을 수 없습니다" }]
}

모듈 9(레슨 2)에서 배운 "상태 코드로 원인을 좁힌다"는 습관이 GraphQL에서는 그대로 통하지 않는다 — 응답 본문 안의 errors 필드를 직접 확인해야 실제 에러 여부를 알 수 있다. 이건 GraphQL 테스트에서 가장 흔히 놓치는 함정이다.

N+1 문제 — GraphQL 특유의 성능 이슈

클라이언트가 "주문 목록과 각 주문에 딸린 상품 이름"을 한 번에 요청하면, 서버 구현이 미숙할 경우 주문 하나마다 별도로 데이터베이스 조회가 일어나는 비효율이 생길 수 있다(주문이 N개면 조회가 N+1번 발생) — 모듈 9(레슨 5)에서 배운 SQL과 직접 연결되는 문제다. GraphQL API를 테스트할 때는 응답 값뿐 아니라 응답 속도도 함께 관찰해서, 요청한 필드 개수가 늘어날 때 비정상적으로 느려지지 않는지 확인하는 것이 좋다.

스키마도 계약이다

GraphQL은 전체 API 구조를 **스키마(Schema)**로 정의한다 — 이건 레슨 4에서 배운 OpenAPI 스펙과 비슷한 역할을 한다. 스키마가 있으면 어떤 쿼리·뮤테이션이 가능한지, 각 필드의 타입이 무엇인지 명확하게 알 수 있고, 이 스키마를 기준으로 한 계약 테스트도 가능하다.

실무에서 왜 필요한가

REST에 익숙한 QA가 GraphQL API를 처음 테스트할 때, "상태 코드 200이니 성공"이라고 잘못 판단하는 경우가 실무에서 흔하다. 응답 본문의 errors 필드를 확인하는 습관 하나만 알아도 이런 놓침을 방지할 수 있다. 또한 N+1 문제처럼 GraphQL 특유의 성능 함정을 아는 QA는, 단순 기능 검증을 넘어 성능 관점(모듈 16)까지 챙길 수 있다.

실습 과제

과제 1 — 에러 놓침 시나리오 (10분)

다음 GraphQL 응답을 보고, 이걸 "상태 코드만 보고 성공"이라고 잘못 판단했을 때 어떤 문제가 생길지 설명한다.

{
  "data": { "createOrder": null },
  "errors": [{ "message": "재고가 부족합니다" }]
}

(HTTP 상태 코드는 200)

과제 2 — 쿼리로 확인할 항목 설계하기 (10분)

"고객이 자신의 주문 목록과 각 주문에 담긴 상품명을 조회하는" GraphQL 쿼리를 테스트한다면, 기능 검증(값이 맞는가)과 성능 검증 (N+1 문제) 관점에서 각각 무엇을 확인해야 할지 적는다.

자가 체크리스트

  • REST와 GraphQL이 데이터를 요청하는 방식의 근본적 차이를 설명할 수 있다
  • 쿼리와 뮤테이션의 역할을 REST 메서드와 대응해서 설명할 수 있다
  • GraphQL에서 상태 코드만으로 성공 여부를 판단하면 안 되는 이유를 설명할 수 있다
  • N+1 문제가 무엇이고 왜 테스트에서 신경 써야 하는지 설명할 수 있다

흔한 실수

  • GraphQL 응답도 REST처럼 상태 코드만 보고 성공/실패를 판단한다. 본문의 errors 필드를 반드시 확인해야 한다.
  • 필요한 필드만 요청할 수 있다는 장점을, 테스트에서는 전혀 활용하지 않고 매번 모든 필드를 요청한다. 실제 클라이언트가 쓰는 쿼리 형태로 테스트해야 실제 사용 패턴의 문제를 잡을 수 있다.
  • 응답 값만 확인하고 응답 속도는 신경 쓰지 않는다. N+1 문제는 값은 맞지만 성능이 나쁜 형태로 나타나 놓치기 쉽다.

참고 자료