Relay Specification이란?

Relay Specification은 Facebook이 GraphQL 클라이언트 라이브러리 Relay를 위해 정의한 서버 규격이다. 페이지네이션, 객체 식별, 뮤테이션 응답에 대한 표준 패턴을 제공한다.

Relay 전용이 아니라 GraphQL 생태계 전반에서 사실상 표준(de facto standard)으로 채택되었다. GitHub API, Shopify API, Saleor 등 대규모 GraphQL API가 이 규격을 따른다.


세 가지 핵심 규격

1. Connection (Cursor 기반 페이지네이션)

목록 데이터를 edges + node + pageInfo 구조로 반환하는 패턴이다. offset 기반 페이지네이션의 한계(데이터 삽입/삭제 시 중복·누락)를 해결한다.

query {
  users(first: 10, after: "cursor_abc") {
    edges {
      cursor
      node {
        id
        name
      }
    }
    pageInfo {
      hasNextPage
      hasPreviousPage
      startCursor
      endCursor
    }
    totalCount
  }
}
구성 요소역할
edges각 항목을 cursor + node로 감싼 배열
node실제 데이터 객체
cursor해당 항목의 위치를 나타내는 불투명(opaque) 문자열
pageInfo페이지 탐색 메타데이터

페이지네이션 인자:

  • first / after — 앞에서부터 N개, cursor 이후
  • last / before — 뒤에서부터 N개, cursor 이전

2. Global Object Identification (Node Interface)

모든 객체가 Node 인터페이스를 구현하고, 전역적으로 유일한 id를 가진다. 루트에 node(id: ID!) 쿼리를 두어 타입에 관계없이 아무 객체나 ID 하나로 조회할 수 있다.

interface Node {
  id: ID!
}
 
type Query {
  node(id: ID!): Node
}

이를 통해 클라이언트는 캐시 키로 id를 사용하고, 객체를 정규화하여 저장할 수 있다.

3. Mutation Convention

뮤테이션의 입력과 출력을 일관된 구조로 정의한다:

  • 입력: 단일 input 인자로 묶음
  • 출력: 변경된 객체와 관련 연결을 포함하는 전용 Payload 타입
mutation {
  createUser(input: { name: "Kim", email: "kim@example.com" }) {
    user {
      id
      name
    }
    errors {
      field
      message
    }
  }
}

Offset vs Cursor 페이지네이션

항목Offset (skip/limit)Cursor (Relay)
데이터 변동 시중복·누락 발생 가능cursor 기준으로 안정적
임의 페이지 접근가능 (page=5)불가 (순차 탐색만)
성능큰 offset에서 느려짐cursor 인덱스로 일정한 성능
실시간 피드부적합적합

관련 문서

  • GraphQL — Relay Specification이 적용되는 API 쿼리 언어