오늘날의 텍스트에서는 gRPC와 REST를 자세히 살펴보고자 합니다. 아마도 현재 API를 만들기 위해 가장 일반적으로 사용되는 두 가지 접근 방식일 것입니다.
I will start with a short characteristic of both tools — what they are and what they can offer. Then I will compare them according to seven categories, in my opinion, most crucial for modern-day systems.
분류는 다음과 같습니다:
- 기본 HTTP 프로토콜
- 지원되는 데이터 포맷
- 데이터 크기
- 처리량
- 정의
- 채택의 용이성
- 도구 지원
왜 그런가
사람들이 “API”라고 들으면 아마도 바로 REST API를 떠올릴 것입니다. 그러나 REST는 API 구축을 위한 많은 접근 방식 중 하나일 뿐입니다. 모든 사용 사례를 위한 완벽한 해결책은 아닙니다. 다른 방법도 있으며, RPC(원격 프로시저 호출)는 그 중 하나이며, gRPC는 RPC를 사용하는 데 가장 성공적인 프레임워크일 것입니다.
상당히 성숙하고 효율적인 기술이지만, gRPC는 여전히 새로운 것으로 간주되어 REST보다 덜 널리 채택되고 있습니다. 그러나 어떤 사용 사례에서는 상당히 편리합니다.
이 블로그 게시물을 쓰는 저의 주된 이유는 gRPC를 대중화하고 그것이 빛날 수 있는 사용 사례를 지적하는 것입니다.
REST란 무엇인가?
REST, 또는 Representational State Transfer는 아마도 API를 노출하는 어플리케이션을 만드는 가장 일반적인 방법일 것입니다. 이것은 HTTP를 기본 통신 매체로 사용합니다. 그 때문에 캐싱과 같은 HTTP의 모든 장점을 활용할 수 있습니다.
게다가 처음부터 무상태인 특성으로 인해 REST는 클라이언트와 서버를 쉽게 분리할 수 있습니다. 클라이언트는 서버가 노출한 인터페이스만 알고 있으면 서버와 효과적으로 통신할 수 있으며, 서버 구현에 대한 어떤 종속성도 없습니다. 클라이언트와 서버 간의 통신은 요청과 응답을 기반으로 하며, 각 요청은 전형적인 HTTP 요청입니다.
REST는 프로토콜이나 도구가 아닙니다(일부 제한 조건 하에서): 이는 애플리케이션을 구축하기 위한 건축적인 접근 방식입니다. REST 접근 방식을 따르는 서비스를 RESTFul 서비스라고 합니다. 건축학적으로 이것은 사용자에게 여러 제약 조건을 부과합니다. 특히:
- 클라이언트-서버 통신
- 무상태 통신
- 캐싱
- 통일된 인터페이스
- 계층화된 시스템
- 코드 주문
REST의 두 가지 주요 개념은 다음과 같습니다:
- 엔드포인트: 특정 자원을 나타내는 고유한 URL(Uniform Resource Locator); 인터넷을 통해 특정 작업이나 데이터 요소에 접근하는 방법으로 볼 수 있습니다
- 자원: 특정 URL 아래에 사용 가능한 특정 데이터 조각
또한, Richardson 성숙도 모델이라는 설명이 있습니다. 이는 REST API의 “전문성” 정도를 설명하는 모델로, 특정 API가 가지고 있는 특성 세트를 기반으로 REST API를 3단계(또는 단계 0을 계산한다면 4단계)로 분류합니다.
그중 하나의 특성은 REST 엔드포인트가 URL에 명사를 사용하고 해당 자원을 관리하기 위한 올바른 HTTP 요청 메소드를 사용해야 한다는 것입니다.
- 예시: DELETE user/1 대신에 GET user/deleteById/1
HTTP 메소드와 그와 관련된 동작은 다음과 같습니다.
- GET – 특정 자원 또는 자원 모음을 검색
- POST – 새 자원 생성
- PUT – 전체 자원 업서트
- PATCH – 특정 자원의 부분 업데이트
- DELETE – ID로 특정 자원 제거
성숙도 모델은 그것 이상으로 많은 것을 규정합니다. 예를 들어, HyperMedia라는 개념이 있습니다. HyperMedia는 데이터 표현과 클라이언트가 수행할 수 있는 작업을 제어하는 것을 결합합니다.
A full description of the maturity model is out of the scope of this blog — you can read more about it here.
면책조항: 이 문단에서 언급된 많은 것들은 여기서 설명한 것보다 더 미묘합니다. REST는 매우 방대한 주제로 전체 글 시리즈에 가치가 있습니다. 그럼에도 불구하고 여기 있는 모든 것은 일반적으로 알려진 모든 최선의 REST 관행에 부합합니다.
gRPC란 무엇인가?
이것은 상대적으로 오래된 원격 프로시저 호출(RPC) 개념의 또 다른 구현입니다. 구글의 사람들이 만들었기 때문에 이름에 “g”가 들어갔습니다. 이는 RPC를 다루기 위한 가장 현대적이고 효율적인 도구이며, CNCF 친화 프로젝트입니다.
gRPC는 Google의 Protocol Buffers를 직렬화 형식으로 사용하면서 HTTP/2를 전송 매체로 사용하지만, gRPC는 JSON을 데이터 계층으로 사용할 수도 있습니다.
gRPC의 기본 구성 요소에는 다음이 포함됩니다:
- 메서드: gRPC의 기본 구성 요소로, 각 메서드는 입력을 받고 출력을 반환하는 원격 프로시저 호출입니다. 이는 선택한 프로그래밍 언어에 따라 추가적으로 구현된 단일 작업을 수행합니다. 현재 gRPC는 4가지 유형의 메서드를 지원합니다:
- 일대일: 메서드가 입력을 받고 출력을 반환하는 전통적인 요청-응답 모델
- 서버 스트리밍: 메서드가 입력으로 메시지를 받고 출력으로 메시지 스트림을 반환합니다. gRPC는 개별 RPC 호출 내에서 메시지 순서를 보장합니다.
- 클라이언트 스트리밍: 메서드가 입력으로 메시지 스트림을 받아 메시지가 남지 않을 때까지 처리한 후 단일 메시지를 출력으로 반환합니다. 위와 유사하게, gRPC는 개별 RPC 호출 내에서 메시지 순서를 보장합니다.
- 양방향 스트리밍: 이 방법은 스트림을 입력으로 받아 스트림을 출력으로 반환하며, 두 개의 읽기와 쓰기 스트림을 효과적으로 사용합니다. 두 스트림은 독립적으로 작동하며 스트림 수준에서 메시지 순서가 보존됩니다.
- 서비스: 서비스 내에서 각 메서드는 고유한 이름을 가져야 하는 메서드 그룹을 나타냅니다. 서비스는 보안, 시간 초과, 재시도와 같은 기능도 설명합니다.
- 메시지: 메서드의 입력 또는 출력을 나타내는 객체입니다.
gRPC API 정의는 위에서 언급한 세 가지 기본 빌딩 블록을 모두 포함하는 .proto 파일 형식으로 작성됩니다. 또한 gRPC는 .proto 파일에서 클라이언트 및 서비스 코드를 생성하는 프로토콜 버퍼 컴파일러를 제공합니다.
서버 측 메서드는 우리가 원하는 대로 구현할 수 있습니다. API의 입력-출력 계약에 맞춰야 합니다.
클라이언트 측에서는 서버의 모든 메서드를 알고 있는 클라이언트(또는 스텁)라는 객체가 있습니다. 이는 원격 프로시저 호출을 처리하고 응답을 반환합니다.
비교
기본 HTTP 프로토콜
이것은 첫 번째 범주이자 아마도 가장 중요한 범주일 것입니다. 그 영향은 다른 영역에서도 명확하게 드러날 수 있습니다.
일반적으로 REST는 요청-응답 기반이며 HTTP/1.1을 전송 매체로 사용합니다. 웹소켓(자세한 내용은 여기에서 확인 가능)이나 스트리밍이나 더 오래 지속되는 연결과 같은 다른 프로토콜을 사용해야 합니다.
우리는 REST를 스트리밍처럼 보이게 하기 위해 비효율적인 코드를 구현할 수도 있습니다. 더욱이 HTTP/1.1 REST를 사용하면 요청-응답 교환당 하나의 연결이 필요합니다. 이러한 접근 방식은 긴 실행 요청이나 제한된 네트워크 기능을 가질 때 문제가 될 수 있습니다.
물론, HTTP/2를 사용하여 REST 스타일의 API를 구축할 수 있지만, 모든 서버와 라이브러리가 아직 HTTP/2를 지원하지 않을 수 있습니다. 따라서 다른 곳에서 문제가 발생할 수 있습니다.
반면에 gRPC는 HTTP/2만 사용합니다. 이는 단일 TCP 연결을 통해 여러 요청-응답 쌍을 보낼 수 있게 해줍니다. 이러한 접근 방식은 애플리케이션에 대한 상당한 성능 향상이 될 수 있습니다.
- 결과: gRPC에 약간의 우위
지원되는 데이터 형식
REST API가 HTTP/1.1을 사용하는 기본 경우를 가정할 때, 다양한 형식을 지원할 수 있습니다.
REST는 일반적으로 메시지 형식과 스타일에 대한 제한을 부과하지 않습니다. 기본적으로 일반 텍스트로 직렬화할 수 있는 모든 형식이 유효합니다. 특정 시나리오에서 가장 적합한 형식을 사용할 수 있습니다.
REST 애플리케이션에서 데이터를 보내는 가장 인기 있는 형식은 확실히 JSON입니다. XML은 많은 레거시 애플리케이션 때문에 두 번째입니다.
그러나 REST와 HTTP/2를 함께 사용할 때는 이진 교환 형식만 지원됩니다. 이 경우 Protobuf나 Avro를 사용할 수 있습니다. 물론 이러한 접근 방식에는 단점이 있을 수 있지만, 이에 대해서는 다음 점에서 자세히 설명하겠습니다.
한편, gRPC는 데이터 교환을 위해 두 가지 형식만 지원합니다:
- Protobuf — 기본적으로
- JSON — 구식 API와 통합해야 할 때
JSON을 시도하기로 결정하면, gRPC는 메시지에 대한 인코딩 형식으로 JSON을 사용하고 GSON을 메시지 형식으로 사용합니다. 또한, JSON을 사용하려면 몇 가지 추가 구성을 수행해야 합니다. gRPC에 대한 문서화는 그것을 어떻게 하는지에 대해 설명합니다.
- 결과: REST가 더 많은 형식을 지원하므로 승리합니다.
데이터 크기
기본적으로 gRPC는 이진 데이터 교환 형식을 사용하므로 네트워크를 통해 전송되는 메시지의 크기를 크게 줄입니다: 연구에 따르면 바이트 단위로 약 40-50% 크기가 작습니다 — 이전 프로젝트 중 하나에서의 경험에 따르면 50-70% 적습니다.
위의 기사에서는 JSON과 Protobuff 사이의 크기 비교를 비교적 심층적으로 제공합니다. 저자는 또한 JSON과 이진 파일을 생성하는 도구를 제공합니다. 따라서 그의 실험을 다시 실행하고 결과를 비교할 수 있습니다.
기사의 객체들은 상당히 단순하지만, 일반적으로 JSON의 구조가 더 복잡하고 더 많은 중첩 객체를 가질수록 Protobuf에 비해 더 무거워집니다. Protobuf에 대한 크기 차이가 50%라는 것은 좋은 기준선입니다.
차이점은 REST를 위한 바이너리 교환 형식을 사용하여 최소화하거나 제거할 수 있습니다. 그러나 이것은 RESTful API를 수행하는 가장 일반적이고 가장 잘 지원되는 방법은 아니므로 다른 문제가 발생할 수 있습니다.
- 결과: 기본 케이스에서는 gRPC의 승리; 둘 다 바이너리 데이터 형식을 사용하는 경우, 무승부.
처리량
다시, REST의 경우, 모든 것이 기본 HTTP 프로토콜과 서버에 달려 있습니다.
기본 케이스에서, HTTP/1.1을 기반으로 하는 REST는 가장 뛰어난 성능의 서버조차 gRPC의 성능을 능가하지 못할 것이며, 특히 JSON을 사용할 때 직렬화 및 역직렬화 오버헤드를 추가할 때 말이죠. 그러나 HTTP/2로 전환하면 차이가 줄어들 것으로 보입니다.
최대 처리량의 경우, 양쪽 모두 HTTP는 전송 매체이므로 무한대로 확장할 수 있습니다. 따라서 모든 것은 사용하고 있는 도구와 애플리케이션에서 정확히 무엇을 하고 있는지에 달려 있으며, 설계상 제한은 없습니다.
- 결과: 기본 케이스에서는 gRPC; 둘 다 바이너리 데이터 및 HTTP/2를 사용하는 경우, 무승부 또는 gRPC의 약간의 승리.
정의
이 부분에서는 두 접근 방식에서 메시지와 서비스를 어떻게 정의하는지 설명하겠습니다.
대부분의 REST 애플리케이션에서는 요청과 응답을 클래스, 객체 또는 특정 언어가 지원하는 구조로 선언합니다. 그런 다음 제공된 라이브러리에 의존하여 JSON/XML/YAML 또는 필요한 형식을 직렬화 및 역직렬화합니다.
또한, Swagger에서 REST API 정의를 기반으로 선택한 프로그래밍 언어로 코드를 생성할 수 있는 도구를 만들기 위한 지속적인 노력이 있습니다. 그러나 이들은 아직 알파 버전에 있으므로, 아직 몇 가지 버그와 사소한 문제가 발생할 수 있어 사용하기 어려울 수 있습니다.
REST 애플리케이션에서 이진 및 비이진 형식 사이의 차이는 매우 미미하며, 두 경우 모두 규칙이 대체로 동일합니다. 이진 형식의 경우, 특정 형식에 필요한 방식으로 모든 것을 정의합니다.
또한, 우리는 기본 라이브러리 또는 프레임워크의 메서드 또는 어노테이션을 통해 우리의 REST 서비스를 정의했습니다. 이 도구는 다른 구성과 함께 이를 외부로 공개하는 책임이 있습니다.
gRPC의 경우, Protobuf가 기본이며 사실상 유일한 정의 작성 방법입니다. 메시지, 서비스 및 메서드를 .proto 파일에 선언해야 하므로 사실상 간단합니다.
그런 다음 gRPC가 제공하는 도구를 사용하여 코드를 생성하고, 메서드만 구현하면 됩니다. 그 후, 모든 것이 예상대로 작동해야 합니다.
또한, Protobuf는 가져오기를 지원하므로 설정을 여러 파일로 분산시키는 것이 상당히 간단합니다.
- 결과: 여기서 승자는 없고, 설명과 제 조언만 있습니다: 어떤 접근 방식이든 가장 잘 맞는 것을 선택하세요.
채택의 용이성
이 부분에서는 현대 프로그래밍 언어에서 각 접근 방식에 대한 라이브러리/프레임워크 지원을 비교할 것입니다.
일반적으로, 소프트웨어 엔지니어로서의 짧은 경력 동안 접한 모든 프로그래밍 언어(Java, Scala, Python)에는 REST 스타일의 애플리케이션을 만들기 위한 최소 3개의 주요 라이브러리/프레임워크가 있으며, JSON을 객체/클래스로 파싱하기 위한 라이브러리도 비슷한 수가 있습니다.
또한, REST는 기본적으로 사람이 읽기 쉬운 형식을 사용하기 때문에 신입 개발자가 디버깅하고 작업하기 쉽습니다. 이는 새로운 기능을 제공하는 평화에도 영향을 미치며 코드에 나타나는 버그와 싸울 수 있게 도와줍니다.
간단히 말해서, REST 스타일 애플리케이션을 지원하는 것은 적어도 매우 좋습니다.
Scala에서는 tapir라는 도구를 사용할 수 있습니다. — 잠시 동안 제가 유지보수자 중 한 명이었던 기쁜 경험이 있었습니다. Tapir을 사용하면 HTTP 서버를 추상화하고 여러 서버에서 작동하는 엔드포인트를 작성할 수 있습니다.
gRPC 자체는 8개 이상의 인기 있는 프로그래밍 언어용 클라이언트 라이브러리를 제공합니다. 이 라이브러리들은 gRPC API를 만들기 위해 필요한 모든 것을 포함하고 있으며, 또한 Java용(Spring Boot Starter를 통해)과 Scala용 더 높은 추상화를 제공하는 라이브러리도 알고 있습니다.
또 다른 점은 REST가 오늘날 전 세계적인 표준으로 간주되며 서비스 구축의 입구로 여겨지고 있지만, RPC와 특히 gRPC는 이미 어느 정도 오래된 것으로 보이지만 여전히 새로운 것으로 간주되고 있다는 것입니다.
- 결과: REST는 더 널리 채택되어 있고 훨씬 더 많은 라이브러리와 프레임워크가 있기 때문에
도구 지원
라이브러리, 프레임워크 및 일반 시장 점유율은 위에서 다룬 바 있으므로 이 부분에서는 두 스타일에 대한 도구를 다루고자 합니다. 이는 테스트, 성능/스트레스 테스트 및 문서화를 위한 도구를 의미합니다.
자동화된 테스트/테스트
먼저 REST의 경우 자동화된 테스트를 구축하기 위한 도구가 다양한 라이브러리 및 프레임워크에 내장되어 있거나 REST-assured와 같이 이러한 목적으로 구축된 별도의 도구입니다.
gRPC의 경우 스텁을 생성하여 테스트에 사용할 수 있습니다. 더 엄격하게 하고 싶다면 생성된 클라이언트를 별도의 애플리케이션으로 사용하여 실제 서비스에 대한 테스트의 기반으로 사용할 수 있습니다.
gRPC에 대한 외부 도구 지원의 경우 알고 있는 것은:
- Postman 앱 gRPC 지원
- JetBrains의 IDE에서 사용되는 HTTP 클라이언트도 최소한의 구성으로 gRPC를 지원할 수 있습니다.
- 결과 하나: REST의 승리; 그러나 gRPC의 상황이 개선되는 것으로 보인다.
성능 테스트
여기서 REST는 JMeter나 Gatling과 같은 도구로 인해 REST API의 스트레스 테스트를 상당히 쉽게 할 수 있는 상당한 이점을 가지고 있습니다.
불행히도, gRPC는 그러한 지원이 없습니다. Gatling에서 gRPC 플러그인을 현재 릴리스에 포함시켰다는 것을 알고 있어, 상황이 개선되고 있는 것으로 보입니다.
그러나 지금까지 우리는 ghz라는 단 하나의 비공식 플러그인과 라이브러리만 가지고 있었습니다. 이들은 모두 좋지만, REST에 비해 지원 수준이 같지는 않습니다.
- 결과 둘: REST의 승리; 그러나 gRPC의 상황이 다시 개선되는 것으로 보인다, 또 해보세요 😉
문서화
API 문서화의 경우, 승리는 다시 한 번 REST OpenAPI와 Swagger가 산업 전반에 걸쳐 널리 채택되어 사실상의 표준이 되어, 거의 모든 REST 라이브러리가 최소한의 노력으로 또는 그냥 즉시 Swagger 문서를 생성할 수 있습니다.
불행히도, gRPC는 이와 같은 것이 없습니다.
그러나 문제는 gRPC가 이런 도구를 전혀 필요로 하는지 여부입니다. gRPC는 설계상 REST보다 더 설명적이므로 추가적인 문서화 도구가 필요할지도 모릅니다.
일반적으로 .proto 파일은 우리의 API 설명과 함께 우리의 REST API 코드를 만드는 코드보다 더 선언적이고 간결합니다. 그래서 gRPC로부터 더 많은 문서화가 필요하지 않을 수도 있습니다. 답은 여러분에게 맡기겠습니다.
- 결과 세: REST의 승리; 그러나 gRPC 문서화에 대한 질문은 열려 있습니다.
전반적인 결과:
A significant victory for REST
요약
최종 점수표는 다음과 같습니다.

점수는 두 스타일 모두에게 공평하게 분배되어 각각 세 번 승리하고 한 가지 카테고리에서는 명확한 승자가 없습니다.
은탄환은 없습니다: 어떤 카테고리가 애플리케이션에 가장 중요한지 생각한 다음 그 중 대부분에서 이긴 접근 방식을 선택하십시오. 적어도 이것이 저의 추천입니다.
저의 선호에 대해 말씀드리자면, 가능하다면 gRPC를 시도해 보고 싶습니다. 저의 마지막 프로젝트에서 꽤 잘 작동했습니다. 구식 REST보다 더 나은 선택일 수 있습니다.
REST를 gRPC보다 선택하거나 다른 종류의 기술적 문제를 해결해야 할 때 도움이 필요하시면 알려주세요. 도움이 될 수 있습니다.
시간 내어 주셔서 감사합니다.