많은 팀이 GraphQL을 도입하려 고민하지만, 실제로는 필요하지 않은 경우가 많다. GraphQL이 어떤 문제를 해결하는지, 그리고 언제(또는 누구에게) 진짜로 필요한지에 대해 정리한다.
2024년 4월 10일
20,934회 조회
트위터에서 저는 “왜 GraphQL을 사용하지 않나요?”라고 물었고, 150개가 넘는 답변 중 대부분은 어떤 형태로든 “필요하지 않다”는 내용이었습니다.
그리고 그 사람들은 옳습니다. 그들에게는 아마 GraphQL이 필요 없을 겁니다!
이 글이 GraphQL 회사의 공동 창업자가 쓴 것이라는 점을 생각하면 놀랄 수도 있습니다.
이유를 설명해 보겠습니다.
Facebook이 2015년에 GraphQL을 공개한 직후(거의 10년 전입니다!), GraphQL은 타입 안정성이 있는 API를 그 어떤 API보다 좋은 개발자 경험과 함께 만들 수 있게 해준다는 이유로 엄청난 주목을 받았습니다. 그 결과, 아래와 같은 다양한 사람들이 GraphQL을 도입했습니다.
하지만 GraphQL은 원래 이런 사용 사례들을 위해 만들어진 것이 아니었습니다.
Facebook은 수많은 최종 사용자 대상 클라이언트와 수많은 데이터 소스들 사이에 위치하는 중앙 중개 레이어로서 GraphQL을 발명했습니다. 이 레이어가 여러 언어로 작성된 마이크로서비스 전반에 걸쳐 동작할 수 있도록, 그들은 새로운 언어(따라서 새로운 툴체인)를 만든 것입니다.
이는 “클라이언트 측 데이터 접근을 타입 안전하게 만들고 싶다”는 문제에 대해서는 다소 과한(heavy-handed) 해결책입니다. 결국, 그 사용 사례들에 더 적합한 해결책들(예: tRPC)이 등장했고, 채택 면에서 GraphQL을 앞지르게 되었습니다. 그리고 React 서버 컴포넌트의 등장으로, 이들 사용 사례 중 상당수는 다시 한 번 더 단순화될 가능성이 커졌습니다.
“누가 GraphQL이 필요한가?”라는 질문에 답하기 어려운 이유는, GraphQL이 여러 가지 서로 다른 문제들을 해결하기 때문입니다. GraphQL을 사용하는 두 사람과 대화를 나누면, 그들이 GraphQL을 사용하는 이유에 대해 서로 다른 답변을 듣게 될 가능성이 매우 큽니다.
그뿐만 아니라, GraphQL은 이 다양한 문제들을 ‘명확하게 해결한다’기보다는, GraphQL을 사용하면 많은 문제들이 그냥… 사라져 버리는 경향이 있습니다. 그래서 GraphQL이 그 문제들을 해결한다는 사실을 깨닫기 어렵습니다. 예전에 그 상황을 직접 겪어본 적이 있어야만, 어떤 문제들이 조용히 사라졌는지 알아차릴 수 있기 때문입니다.
저는 압니다. GraphQL 회사를 운영하는 제 일의 일부로, 지난 3년 동안 수백 개 회사의 수천 명의 엔지니어들과 그들의 API, 특히 GraphQL로 구축된 API에 대해 이야기를 나누어 왔습니다.
이제 그들이 말해 준, GraphQL이 어떤 문제를 어떻게 해결해 주었는지 정리해 보겠습니다.
GraphQL은 클라이언트가 명시적으로 요청한 필드만 반환합니다. 따라서 새로운 기능을 추가하고 싶다면, 새로운 타입이나 필드를 추가하면 됩니다. 이는 기존 클라이언트에 대해서는 결코 브레이킹 체인지가 아닙니다.
게다가 클라이언트는 자신이 필요로 하는 데이터를 정확히 지정해야 하므로, 어떤 클라이언트가 어떤 필드를 사용하고 있는지 모니터링할 수도 있습니다.
GraphQL을 사용하면, 클라이언트는 페이지/뷰 전체를 렌더링하는 데 필요한 모든 데이터를 하나의 요청으로 보냅니다. 서버는 그 모든 데이터를 한 번에 resolve해서 하나의 응답으로 돌려줍니다. 이 과정에서 BFF가 도입되며 발생하는 중복도 생기지 않습니다. (클라이언트는 @defer와 @stream 디렉티브를 사용해, 서버에 ‘우선 화면 상단(above-the-fold) 데이터부터 스트리밍해 달라’고 요청할 수도 있습니다.)
GraphQL은 각 엔티티/리소스의 데이터 접근을 중앙집중화합니다. 어느 마이크로서비스나 데이터베이스가 내부적으로 데이터를 관리하는 방식을 변경하더라도, 그 변경 사항은 API 레이어의 단 하나의 중앙 지점에만 반영하면 됩니다. 여러 엔드포인트나 BFF를 일일이 수정할 필요가 없습니다.
한 걸음 더 나아가, GraphQL은 클라이언트가 프래그먼트를 사용해 컴포넌트 수준에서 데이터 요구 사항을 명시하도록 해 줍니다. (예: UserAvatar 컴포넌트는 추상적으로 UserType.avatarUrl이 필요하다고 명시할 수 있습니다.) 따라서 클라이언트 코드에서도 관련 변경은 해당 변경과 연관된 특정 컴포넌트에만 적용하면 됩니다!
GraphQL은 클라이언트들을 위한 중앙 데이터 액세스 레이어이기 때문에, 필요하다면 매우 세밀한 수준에서 보안 및 성능 SLA를 강제할 수 있습니다. REST API에서 엔드포인트별로 제한을 거는 것과 유사하게, GraphQL에서는 오퍼레이션별로 제한을 둘 수도 있습니다. 하지만 여기서 나아가 타입별, 심지어 필드별로까지 더 세밀한 제한을 둘 수도 있습니다.
당신의 회사가 이 문제들 중 하나(또는 그 이상!)를 겪고 있다면, 스택에 GraphQL을 도입하는 것을 진지하게 검토해 볼 가치가 있습니다.
오늘은 이 문제들 중 아무것도 겪지 않고 있다면, “도대체 언제 이런 문제들에 부딪히게 될까?”라는 궁금증이 생길 수 있습니다. 그 답은, 각자의 구체적인 사용 사례에 따라 다르기 때문에 예측하기가 어렵다는 것입니다. 어떤 회사는 50명 이상의 엔지니어와 수백만 명의 사용자 규모로 성장해도 이런 문제를 전혀 겪지 않을 수 있습니다. 반면, 어떤 회사는 MVP를 만드는 단계에서 이미 이 문제들 중 복수 개에 부딪히기도 합니다.
제 경험을 바탕으로 한 가이드라인을 드리자면: 늦어도 엔지니어가 100명 이상이 되는 시점에는, 이 문제들 중 적어도 하나는 겪게 될 가능성이 큽니다.
그래서 제 트윗에 답변을 준 대부분의 사람들은 옳았습니다. 그들에게는 아마 GraphQL이 필요 없습니다.
하지만 한 가지는 분명합니다. 언젠가 이 문제들 중 어떤 것에든 부딪히게 된다면, GraphQL은 그 문제를 해결해 줄 준비가 되어 있을 것입니다.