실제 엔터프라이즈 환경에서 Apollo 기반 GraphQL을 수년간 운영해 본 뒤, GraphQL이 해결하는 문제는 생각보다 틈새이며 많은 조직에서 오히려 복잡성을 늘린다는 결론에 이르렀다.
URL: https://johnjames.blog/posts/graphql-the-enterprise-honeymoon-is-over
Title: GraphQL: 엔터프라이즈 허니문은 끝났다
By John James
Published on December 14, 2025
Read time ~3 min
저는 실제 엔터프라이즈급 애플리케이션에서 몇 년 동안 GraphQL, 그중에서도 Apollo Client와 Server를 사용해 왔습니다.
장난감 앱이 아닙니다. 그린필드 스타트업도 아닙니다. 여러 팀, BFF, 다운스트림 서비스, 관측 가능성(observability) 요구사항, 그리고 실제 사용자가 있는 제대로 된 프로덕션 구성입니다.
그리고 그 시간을 모두 지나, 꽤나 심심한 결론에 도달했습니다.
GraphQL은 실제 문제를 해결합니다. 하지만 그 문제는 사람들이 인정하는 것보다 훨씬 더 틈새입니다. 대부분의 엔터프라이즈 구성에서는 이미 다른 곳에서 해결되어 있고, 트레이드오프를 모두 합산해 보면 GraphQL은 종종 순(純)마이너스가 됩니다.
이 글은 “GraphQL은 나쁘다”가 아닙니다. “허니문 이후의 GraphQL”에 대한 글입니다.
GraphQL이 해결하려는 핵심 문제는 오버페칭(overfetching)입니다.
아이디어는 단순하면서 매력적입니다.
종이 위에서는 훌륭합니다. 하지만 실전은 더 복잡합니다.
대부분의 엔터프라이즈 프론트엔드 아키텍처에는 이미 BFF(Backend for Frontend)가 있습니다.
BFF는 원래 다음을 위해 존재합니다.
BFF 뒤에서 REST를 사용하고 있다면, 오버페칭은 이미 해결 가능합니다. BFF가 응답을 축소해서 UI가 관심 있는 것만 돌려주면 됩니다.
물론 GraphQL도 똑같이 할 수 있습니다. 하지만 사람들이 대충 넘어가는 부분이 있습니다.
대부분의 다운스트림 서비스는 여전히 REST입니다.
즉, 이제 GraphQL 레이어가 다운스트림 REST API에서 여전히 오버페칭을 한 다음 응답을 재구성해야 합니다. 오버페칭을 없앤 게 아닙니다. 한 단계 아래로 옮긴 것뿐입니다.
이 사실 하나만으로도 GraphQL의 핵심 판매 포인트는 크게 약해집니다.
여기서 GraphQL이 이기는 경우가 있긴 합니다. 여러 페이지가 같은 엔드포인트를 때리지만 필요한 필드가 약간씩 다를 때, GraphQL은 쿼리별로 그 차이를 스코프에 맞게 조절할 수 있습니다.
하지만 트레이드를 솔직히 봅시다.
대부분의 경우 요청당 몇 개 필드를 아끼는 정도에 불과한데, 그 대가로 다음을 지불합니다.
몇 KB를 아끼기 위해 치르는 비용치고는 너무 비쌉니다.
GraphQL은 REST BFF보다 구현에 훨씬 더 오래 걸립니다.
REST에서는 보통:
GraphQL에서는 이제 다음이 추가됩니다.
GraphQL은 소비(consumption)를 최적화하는 대신, 생산(production) 속도를 희생합니다.
엔터프라이즈 환경에서는 이론적 우아함보다 생산 속도가 더 중요합니다.
이건 충분히 이야기되지 않습니다.
GraphQL에는 상태 코드 관례가 좀 이상합니다.
errors 배열을 포함한 200관측 가능성 관점에서 매우 고통스럽습니다.
REST에서는:
대시보드를 2XX로 필터링하면 요청이 성공했음을 알 수 있습니다.
GraphQL에서는 200이 부분 실패 또는 완전 실패를 의미할 수도 있습니다.
물론 Apollo로 이 동작을 커스터마이즈할 수는 있습니다. 하지만 그게 요점입니다. REST가 기본 제공하는 수준으로 돌아오기 위해서조차 추가 설정, 추가 규약, 추가적인 정신적 오버헤드라는 “세금”을 계속 냅니다.
이건 블로그 글을 읽을 때가 아니라, 온콜(on call)일 때 중요합니다.
Apollo의 정규화(normalized) 캐시는 진짜로 인상적입니다.
이론상으로는요. 실전에서는 취약합니다.
필드 하나만 다른 두 쿼리가 있으면 Apollo는 이를 서로 다른 쿼리로 취급합니다. 그러면 다음이 되도록 수작업으로 엮어야 합니다.
그 시점에서는:
반면 REST는 몇 개 필드를 더 오버페칭해도 전체 응답을 캐시하고 넘어갑니다. 몇 KB는 싸지만, 복잡성은 비쌉니다.
Apollo는 기본적으로 모든 객체가 id 또는 _id 필드를 가져야 한다고 기대합니다. 아니면 커스텀 식별자를 설정해야 합니다.
이 가정은 많은 엔터프라이즈 API에서 성립하지 않습니다.
많은 API가:
그러면 GraphQL 클라이언트를 만족시키기 위해 BFF가 로컬에서 ID를 생성해야 합니다.
이는 곧:
아이러니하게도 원래 목표가 오버페칭을 줄이는 것이었다는 점을 생각하면 더욱 그렇습니다.
REST 클라이언트는 이런 제약을 강요하지 않습니다.
GraphQL은 바이너리 데이터에 잘 맞지 않습니다.
실전에서는 결국:
PDF 같은 큰 페이로드를 GraphQL 응답에 직접 넣으면 응답이 비대해지고 성능이 나빠집니다.
이 한 가지 이유만으로도 “단일 API”라는 이야기는 깨집니다.
대부분의 프론트엔드/풀스택 개발자는 GraphQL보다 REST에 훨씬 익숙합니다.
GraphQL을 도입하면 다음을 가르쳐야 합니다.
이 학습 곡선은 마찰을 만들고, 특히 팀이 빠르게 움직여야 할 때 부담이 됩니다.
REST는 지루하지만, 지루함은 놀라울 정도로 잘 확장됩니다.
GraphQL의 에러 응답은… 이상합니다.
다음이 있습니다.
이 모든 것은 간접 계층을 늘립니다.
이를 간단한 REST 구성과 비교해 보세요.
우아한 에러보다 단순한 에러가 이해하기 쉽습니다.
GraphQL에는 분명 타당한 사용 사례가 있습니다.
하지만 대부분의 엔터프라이즈 환경에서는:
모든 것을 합산해 보면, GraphQL은 좁은 문제를 해결하는 대신 더 넓은 범위의 새로운 문제들을 도입하는 경우가 많습니다.
그래서 수년간 프로덕션에서 써 본 뒤 저는 이렇게 말하겠습니다.
GraphQL은 나쁘지 않습니다. 그냥 틈새입니다. 그리고 아마 여러분에겐 필요 없습니다.
특히 여러분의 아키텍처가 이미 GraphQL이 해결하려던 문제를 해결해 두었다면 더더욱요.