REST와 GraphQL 비교

REST와 GraphQL 비교

Jan 22 ·
21 분 읽음

들어가며

이전 직장에서 REST API로 구축된 프로젝트를 GraphQL로 전환하는 과정을 경험했습니다.
당시에는 둘 다 데이터를 주고받는 방식일 뿐이라고 생각했지만,
그 과정은 단순한 기술 교체가 아니라 데이터를 주고받는 사고방식 자체의 전환이었습니다.

오랫동안 웹 API의 표준처럼 여겨져 온 REST의 자원 중심 접근 방식과,
최신 애플리케이션의 복잡한 데이터 요구에 맞춰 등장한 GraphQL의 클라이언트 중심 접근 방식은
생각보다 더 큰 차이를 만들어냈습니다.

이번 글에서는 두 기술이 어떻게 탄생했고,
그들의 철학적 차이가 어떤 구조적 차이로 이어지는지를 정리해 보았습니다.


REST — 웹의 원리를 따른 아키텍처 스타일

REST의 탄생 배경

REST는 2000년 로이 필딩의 박사 논문에서 처음 제안되었습니다.
REST는 특정 프로토콜이나 표준이 아닌, 웹 전체를 설계하기 위한 아키텍처 스타일입니다.

로이 필딩은 HTTP의 주요 저자 중 한 사람으로서,
월드 와이드 웹이 스스로의 복잡성으로 인해 무너지지 않도록,
확장성과 안정성을 유지할 수 있는 일련의 원칙을 정리했습니다.
그 결과물이 바로 REST입니다.

REST의 핵심 원칙


인터페이스 일관성의 네 가지 세부 원칙

  1. 자원의 식별 (Identification of Resources)
    모든 자원은 URI(Uniform Resource Identifier)를 통해 고유하게 식별됩니다.
    예를 들어 /users/123은 특정 사용자를 나타냅니다.

  2. 표현을 통한 자원 조작 (Manipulation of Resources Through Representations)
    클라이언트는 자원의 표현(JSON, XML 등)을 통해 서버와 상호작용합니다.
    HTTP 메서드(GET, POST, PUT, DELETE 등)를 사용해 동작을 명확히 전달합니다.

  3. 자기 서술적 메시지 (Self-Descriptive Messages)
    각 메시지는 그 자체로 처리 방식을 알 수 있어야 합니다.
    예를 들어 Content-Type: application/json은 본문이 JSON 형식임을 명시합니다.

  4. 애플리케이션 상태의 엔진으로서 하이퍼미디어 (HATEOAS)
    서버 응답에는 현재 자원과 관련된 행동이나 이동할 수 있는 링크가 포함되어야 합니다.
    예를 들어 주문 조회 응답에 결제 또는 취소 링크를 함께 제공하는 방식입니다.


현실 속의 REST

이론적으로는 HATEOAS(Hypermedia as the Engine of Application State)까지 구현해야 진정한 REST라고 할 수 있지만,
오늘날 대부분의 REST API에서는 거의 구현되지 않습니다.

이 원칙이 의미하는 것은 간단합니다.

클라이언트는 서버가 제공하는 링크를 따라가며 애플리케이션의 상태를 전이해야 한다.

하지만 이는 구현 복잡도가 높고 개발 비용이 크기 때문에 실제로는 거의 쓰이지 않습니다.

그래서 우리가 흔히 말하는 REST API는 사실상 REST API가 아닙니다.
로이 필딩 역시 이런 API는 진정한 REST가 아니라
그저 HTTP 기반 API일 뿐이라고 말했습니다. (출처)

이 현실을 설명하기 위해 등장한 개념이
리처드슨 성숙도 모델(Richardson Maturity Model)입니다.

단계설명예시
Level 0 – POX(Plain Old XML)단순히 HTTP를 데이터 전송 통로로만 사용. 실제로는 RPC 스타일.POST /api<getUser id="1" />
Level 1 – 자원(Resource) 중심URL을 통해 자원을 구분하지만, 모든 동작에 같은 HTTP 메서드 사용.POST /users/get, POST /users/create
Level 2 – HTTP 메서드 중심각 자원에 맞게 GET, POST, PUT, DELETE 등 HTTP 메서드를 활용.GET /users/1, DELETE /users/1
Level 3 – HATEOAS응답 안에 관련 링크를 포함해 클라이언트가 상태 전이를 스스로 탐색할 수 있음.응답: { "user": {...}, "links": { "self": "/users/1", "friends": "/users/1/friends" } }

실무에서 우리가 RESTful API라고 부르는 대부분의 서비스는 Level 2에 해당합니다.
이 수준만 되어도 구조가 직관적이고, HTTP의 기본 원리를 잘 활용하면서도
구현이 복잡하지 않기 때문에 많은 팀에서 합리적인 선택으로 여겨집니다.


GraphQL — 클라이언트 중심 데이터 쿼리 언어

왜 GraphQL이 등장했을까

2010년대 초, 페이스북은 모바일 앱으로 전환하면서 심각한 성능 문제를 겪었습니다.
뉴스피드처럼 복잡한 데이터를 여러 번의 REST 요청으로 가져오다 보니,
네트워크 지연과 중복 데이터 요청으로 성능이 급격히 저하되었습니다.

이 문제는 두 가지로 요약됩니다.

GraphQL은 2012년 페이스북 내부에서 이 문제를 해결하기 위해 개발되었고,
2015년에 오픈소스로 공개되었습니다.

GraphQL의 핵심은 다음 한 문장으로 요약할 수 있습니다.

클라이언트가 필요한 데이터의 구조를 직접 정의한다.


GraphQL의 주요 구성 요소


REST vs GraphQL 비교

구분RESTGraphQL
데이터 요청 방식서버가 응답 구조를 정의클라이언트가 요청 구조를 정의
엔드포인트 구조자원별로 여러 개일반적으로 하나(/graphql)
HTTP 활용메서드(GET, POST, PUT, DELETE)로 의미 구분주로 POST 하나로 통합
타입 시스템약한 타입스키마 정의 언어(Schema Definition Language) 기반의 강한 타입
캐싱HTTP 표준 캐싱 활용 가능HTTP 캐싱 어려움, 클라이언트 단에서 캐싱 필요
버전 관리/v1/users처럼 버전 구분필드 Deprecation을 통한 점진적 진화
에러 처리HTTP 상태 코드응답 본문 내 errors 배열

캐싱 관점에서 본 두 접근법

REST는 웹의 인프라와 완벽히 호환됩니다.
브라우저나 CDN, 프록시 서버 모두 HTTP 캐싱을 그대로 활용할 수 있습니다.
예를 들어 GET /users/123은 멱등성이 보장되기 때문에 ETag나 Cache-Control 헤더로 쉽게 캐싱할 수 있습니다.

반면 GraphQL은 대부분 단일 엔드포인트(/graphql)로 POST 요청을 보내기 때문에
HTTP 캐시로는 쿼리별 결과를 구분하기 어렵습니다.

따라서 GraphQL의 캐싱은 네트워크 레벨이 아닌 애플리케이션 레벨에서 처리됩니다.
Apollo Client나 Relay 같은 라이브러리가 이를 담당하며, 데이터를 정규화해 메모리 캐시로 관리합니다.

이 방식은 유연하지만, REST보다 설정과 관리가 훨씬 복잡합니다.


보안 측면의 차이

REST는 이미 검증된 표준 보안 패턴이 많습니다.
JWT, OAuth 2.0, API Key 등으로 인증과 인가를 처리하고,
엔드포인트별로 Rate Limiting을 적용할 수 있습니다.

GraphQL은 단일 엔드포인트 구조라 조금 다릅니다.
쿼리 내용이 본문 안에 들어있기 때문에, 필드 단위로 접근 권한을 제어해야 하며,
쿼리 깊이 제한이나 복잡도 점수 계산 같은 추가적인 방어 로직이 필요합니다.

또한 프로덕션 환경에서는 인트로스펙션(Introspection) 기능을 비활성화해야 합니다.
이 기능이 활성화된 상태에서는 공격자가 API 스키마 전체를 손쉽게 탐색할 수 있기 때문입니다.


언제 어떤 방식을 선택해야 할까

상황REST 권장GraphQL 권장
단순 CRUD / 명확한 자원 중심
캐싱이 중요하고 CDN을 적극 활용하는 서비스
복잡한 관계형 데이터, 다양한 클라이언트 타입
여러 마이크로서비스 통합(API Gateway 역할)
초기 러닝커브를 최소화하고 빠른 팀 온보딩이 필요할 때

마치며

GraphQL을 처음 써보며 느낀 점

처음에는 이걸 꼭 써야 할까 하는 생각이 들었습니다.
GraphQL이 최신 기술이라는 점은 분명 매력적이었지만,
프로덕트 레벨의 실제 서비스에서 이걸 도입하는 것이 정말 옳은 선택인지 확신이 없었습니다.
새로운 기술이 좋다는 이유만으로 바로 도입하기에는,
서비스의 안정성과 유지보수성이 더 중요하다고 생각했기 때문입니다.

특히 Relay를 사용할 때는 강력한 기능에 비해 문서가 불친절했고,
스키마가 커질수록 필드 관계를 파악하기 어려워졌습니다.

하지만 실제로 프로젝트에 적용해보며 느낀 것은,
GraphQL은 단순히 새로운 기술이 아니라 데이터를 다루는 방식을 다시 생각하게 만드는 계기였습니다.


GraphQL과 Relay가 남긴 인사이트

GraphQL을 사용하면서 가장 크게 느낀 장점은 필요한 데이터만 가져올 수 있다는 점이었습니다.
프런트엔드 개발자로서, 특히 컴포넌트 단위로 필요한 데이터 범위를 명확히 선언할 수 있다는 점은
생각보다 훨씬 큰 생산성 향상을 가져왔습니다.

Relay를 실제로 사용하면서 느낀 가장 큰 이점은
데이터 종속성이 코드 레벨에서 명확히 드러난다는 점이었습니다.
각 컴포넌트는 자신이 필요로 하는 데이터를 직접 선언해야만 동작하기 때문에,
데이터 구조와 UI 구조가 자연스럽게 일관성을 유지했습니다.

또한 Relay는 스키마를 기반으로 자동 생성되는 타입 정의를 통해
데이터 타입 안정성을 보장하고 런타임 에러를 줄여 주었습니다.
이 덕분에 어떤 필드가 존재하지 않거나 타입이 다른 문제를
빌드 단계에서 바로 확인할 수 있었습니다.

팀 단위 협업에서도 분명한 장점이 있었습니다.
API 변경이나 필드 수정이 발생하더라도,
어느 컴포넌트가 영향을 받는지 즉시 파악할 수 있었고,
덕분에 기능 추가나 리팩터링 시 불필요한 커뮤니케이션이 줄어들었습니다.

결국 Relay는 단순히 데이터를 효율적으로 가져오는 도구라기보다,
데이터와 UI 사이의 관계를 명확히 정의하게 만드는 프레임워크였습니다.

Relay를 사용하면서 React 컴포넌트가 어떤 데이터를 책임져야 하는지,
그리고 데이터가 UI 구조 안에서 어떻게 흘러가야 하는지를
조금 더 깊이 이해하게 되었습니다.

이전에는 단순히 API 응답을 받아 화면에 표시하는 흐름으로만 생각했다면,
Relay를 통해 데이터 의존성을 컴포넌트 단위로 명확히 나누는 것이
결국 더 안정적인 UI 구조를 만드는 일이라는 점을 배웠습니다.


REST와 GraphQL, 좋고 나쁨의 문제가 아니다

GraphQL을 사용하면서 느낀 점은, 이 기술이 좋고 나쁨의 문제가 아니라
우리 팀에 적합한가의 문제라는 것이었습니다.

REST는 단순하고 예측 가능하며,
HTTP 규약에 익숙한 개발자라면 바로 적용할 수 있습니다.
또한 캐싱이나 모니터링도 훨씬 수월합니다.

반면 GraphQL은 유연하고 강력하지만,
프런트엔드 입장에서는 학습해야 할 내용이 많습니다.
스키마 설계는 주로 백엔드에서 진행되었지만,
프런트엔드에서는 쿼리 작성, 상태 관리, 캐시 정책, 에러 처리까지 직접 다뤄야 했습니다.
결국 백엔드와의 협업 구조를 얼마나 잘 가져가느냐가
GraphQL 운영의 핵심이라는 점을 느꼈습니다.


결국, 기술은 철학이다

GraphQL은 REST보다 더 좋은 기술이 아닙니다.
다만 문제를 바라보는 관점이 다른 기술일 뿐입니다.

REST는 서버가 자원을 정의한다는 철학 위에 서 있고,
GraphQL은 클라이언트가 데이터 요구를 주도한다는 철학 위에 서 있습니다.
둘 중 어느 쪽이 옳다고 단정할 수는 없습니다.

경험이 쌓일수록 기술의 우열보다
우리 팀의 맥락에 맞는지가 더 중요하다는 것을 절실히 느낍니다.
그래서 이제는 새로운 기술을 볼 때마다
그 기능보다, 그 기술이 태어난 배경과 철학을 먼저 살펴보려 합니다.

좋은 개발은 도구의 선택이 아니라
문제를 인식하는 깊이에서 시작된다고 생각합니다.


요약하자면,
GraphQL과 Relay를 통해 데이터 구조와 UI 구조의 관계를 명확히 설계하는 방법을 배웠고,
아무리 좋은 기술이라도 문제를 명확히 정의하지 않으면
복잡성만 커질 수 있다는 사실을 느꼈습니다.

REST와 GraphQL 중 어느 쪽이 더 옳은가보다,
우리 팀이 당면한 문제를 가장 우아하게 해결할 방법이 무엇인지
끊임없이 고민하는 것,
그것이 경험 많은 개발자가 가져야 할 태도라고 생각합니다.