엔지니어링 팀은 여전히 REST가 죽었는지, 아니면 gRPC가 다른 모든 것을 구식으로 만들었는지 논쟁하며 오후 시간을 통째로 허비하곤 합니다. 하지만 그 논쟁은 핵심을 놓치고 있습니다. 당신은 최선의 프로토콜을 선택하는 것이 아니라, 적절한 경계(boundary)를 선택하는 것입니다. Kubernetes 클러스터 내부에서 환상적으로 작동하는 프로토콜이라도, 수천 명의 외부 개발자에게 넘겨주는 순간 숨이 막힐 수 있습니다. 모바일 앱의 소중한 대역폭을 아껴주는 프로토콜이, 무분별한 공개 쿼리에 노출될 경우 인프라 비용을 폭등시킬 수도 있습니다. 이 결정을 기술 인기 투표처럼 다룬다면, 현재 팀원 모두가 떠난 후에도 남아있을 아키텍처 부채를 고착화하게 될 것입니다.

The Boundary Principle

아키텍처는 승자를 가리는 것이 아니라 트레이드오프(trade-offs)에 관한 것입니다. 올바른 질문은 결코 "무엇이 가장 빠른가?"나 "무엇이 가장 최신인가?"가 아닙니다. "통신 선로 반대편에 누가 앉아 있으며, 그들은 무엇을 제어하는가?"가 되어야 합니다. 프로토콜은 경계 객체(boundary objects)입니다. 잘못된 프로토콜을 선택하면 단순히 속도가 느려지는 것에 그치지 않고, 시스템에 수년간 지속될 실수를 심어놓게 됩니다.

Public APIs: REST Is Not Boring, It Is Responsible

소비자가 한 번도 만난 적 없는 외부 개발자라면, API는 단순한 인터페이스가 아니라 하나의 제품입니다. 그 개발자는 새벽 2시에 curl과 Postman 컬렉션만 가지고 디버깅을 하고 있을 것입니다. 만약 첫 번째 호출에 성공하기 위해 커스텀 클라이언트 라이브러리를 설치하거나 스키마 언어를 배워야 한다면, 당신은 이미 그들을 놓친 것입니다.

REST가 여기서 살아남는 이유는 그것이 곧 웹 그 자체이기 때문입니다. HTTP 메서드, 상태 코드, JSON은 공용어와 같습니다. 캐싱은 나중에 생각할 문제가 아니라, 이미 존재하는 인프라입니다. 브라우저, CDN, 에지 캐시는 Cache-Control 헤더와 ETag 검증을 기본적으로 이해합니다. 표준 CDN 뒤에 REST API를 배치하기만 하면, 캐싱 로직을 단 한 줄도 작성하지 않고도 즉각적인 대역폭 절감 효과를 얻을 수 있습니다. 공개 트래픽은 예측 불가능하며, 클라우드에서 나가는 모든 기가바이트에 대해 비용을 지불해야 하는 상황에서는 이것이 매우 중요합니다.

반면, GraphQL은 공개 경계에서 무거운 세금을 부과합니다. 공개 GraphQL 엔드포인트는 단 하나의 부주의하거나 악의적인 쿼리가 데이터베이스를 마비시키는 것을 방지하기 위해 쿼리 비용 분석, 깊이 제한(depth limiting), 복잡도 점수 산정 등이 필요합니다. 당신은 단순히 API를 배포하는 것이 아니라, 쿼리 실행 엔진, 속도 제한(rate-limiting) 전략, 그리고 컴퓨팅 과금 모델을 구축하고 있는 것입니다. 거대 플랫폼 수준의 운영 역량이 없다면, 이러한 오버헤드는 공개 영역에서 무모한 선택입니다. REST는 기본적으로 가드레일을 제공합니다. 각 엔드포인트는 한 가지 일만 수행합니다. 소비자는 그들이 상상하는 무엇이든 가져오는 것이 아니라, 당신이 제공하는 것을 정확히 가져갑니다.

Internal Services: Own the Whole Pipe

조직 내부에서는 이야기가 달라집니다. 클라이언트와 서버를 모두 제어할 수 있기 때문입니다. 호출 체인에 있는 모든 서비스의 기술 스택을 결정할 수 있습니다. 바로 이 지점이 gRPC가 제 가치를 발휘하는 곳입니다.

우선, JSON을 신성시하는 것을 멈추십시오. Protocol Buffers는 JSON보다 약 3배 빠르게 직렬화합니다. 포맷이 바이너리이기 때문에 페이로드 크기도 더 작습니다. 혼잡한 내부 네트워크에서 이러한 밀리초와 메가바이트의 차이는 실제 비용 절감과 낮은 테일 레이턴시(tail latency)로 이어집니다. 더 중요한 것은, Protobuf가 엄격한 계약(contract)을 제공한다는 점입니다. 필드 타입을 변경하거나 메시지 이름을 바꿀 때, 오류는 새벽 3시 운영 환경에서 다운스트림 서비스가 파싱 예외를 던지며 발생하는 것이 아니라 컴파일 타임에 발생합니다.

gRPC는 HTTP/2 위에서 동작하므로 헤더 압축, 멀티플렉싱된 스트림, 그리고 실제 스트리밍 시맨틱을 사용할 수 있습니다. 서비스 간에 높은 처리량의 이벤트를 전달하거나 실시간 업데이트를 푸시하는 경우, 서버 측 및 양방향 스트리밍은 요청-응답 프레임워크에 억지로 붙인 롱 폴링(long-polling) 우회책이 아니라 네이티브 기능입니다.

주의할 점이 있습니다. gRPC를 브라우저에 직접 연결하지 마십시오. 브라우저 네트워킹 모델은 gRPC가 기대하는 방식으로 HTTP/2를 지원하지 않습니다. 브라우저가 백엔드와 통신하게 하려고 grpc-web과 Envoy 같은 프록시를 스택에 덧붙이게 될 것입니다. 이것은 버그가 아니라 경계 신호(boundary signal)입니다. gRPC는 방화벽 뒤, 서로 신뢰할 수 있는 서비스들 사이에 두고, 디버깅의 복잡성은 속도에 대한 대가로 받아들이십시오. 바이너리 페이로드는 JSON처럼 로그 파일에서 눈에 잘 들어오지 않습니다.

Complex UIs and Mobile: GraphQL's Niche

현대의 모바일 화면은 여러 요소가 얽힌 패치워크와 같습니다. 어떤 뷰에서는 사용자 프로필이 필요할 수도 있고,