코딩관계론

내부 서버들은 어떤 통신 프로토콜 좋을까..(gRPC를 선택하게 된 이유) 본문

개발

내부 서버들은 어떤 통신 프로토콜 좋을까..(gRPC를 선택하게 된 이유)

개발자_티모 2024. 8. 7. 01:51
반응형

서론

앞서 API Gateway를 공부하면서, 특정 API Gateway Framework(AGF)를 사용하는 것의 한계에 대해 알아보았습니다. 그중 하나는 내부 통신 프로토콜로 REST를 강제하는 단점이 있었습니다. 이는 내부 서버 간의 통신에서 굳이 REST를 사용할 필요가 없다는 뜻이기도 합니다.

 

따라서 저는 내부 서버의 통신은 gRPC프로토콜을 선택하여 사용했고, 이제부터는 gRPC 통신의 장점에 대해서 설명해보겠습니다

REST API의 성능 문제

REST API를 강제했을 때 발생할 수 있는 문제점은 무엇일까요? 이전 글에서 성능 이슈에 대해 언급했는데, 이를 구체적인 예시를 통해 설명해보겠습니다.

 

사용자가 "모든 정보 조회"라는 API를 요청한다고 가정해봅시다. 내부 서비스에서 사용자 정보를 조회하는 데 3초, 주문 정보를 조회하는 데 5초, 결제 정보를 조회하는 데 쿼리 문제로 4초가 걸린다고 가정해보겠습니다.

 

만약 이 정보 조회 요청이 동기식으로 작동한다면, 각 요청이 순차적으로 이루어져 3초 + 5초 + 4초 = 총 12초가 소요될 것입니다. 하지만 비동기적으로 요청을 처리할 수 있다면, 가장 오래 걸리는 요청(5초)만으로 사용자가 원하는 응답을 제공할 수 있습니다. 이 경우 성능 차이가 두 배 이상 벌어지게 됩니다.

 

이 사례는 REST API를 강제할 때 발생할 수 있는 성능 문제를 잘 보여줍니다. 비동기적 통신이 가능하다면, 보다 효율적으로 응답을 제공할 수 있으며, 결과적으로 사용자 경험이 크게 향상될 수 있습니다.

 

직렬화의 차이점: REST vs. gRPC

REST와 gRPC 간의 또 다른 성능 차이점은 데이터 직렬화에서 발생합니다.

 

다음과 같은 JSON Payload를 가정해보겠습니다. 이 페이로드는 서버에 전송되기 위해 직렬화 과정을 거친 후 바이트로 인코딩되어 서버로 전송됩니다. JSON의 경우 모든 데이터가 텍스트 형식으로 변환되기 때문에, 데이터 크기의 낭비가 커질 수 있습니다.

{
  "name": "Alice",
  "age": 25,
  "email": "alice@example.com"
}

 

예를 들어, 위의 JSON 데이터에서 'age':25를 생각해봅시다. 이 숫자도 직렬화 과정에서 문자열로 변환되며, UTF-8 인코딩에 의해 각 문자가 1바이트씩 차지하게 됩니다. 따라서 25는 2바이트가 됩니다. 여기에 "age" 필드명까지 포함하면, 총 5바이트가 됩니다.

 

이렇게 텍스트 기반의 인코딩 방식은 데이터 크기를 증가시키고, 네트워크 대역폭을 더 많이 사용하게 됩니다. 이는 대량의 데이터를 전송할 때, 전송 속도와 효율성에 부정적인 영향을 미칠 수 있습니다.

 

반면에, gRPC는 Protobuf를 사용하여 데이터를 직렬화합니다. Protobuf는 Varint 인코딩을 통해 작은 정수를 1바이트로 효율적으로 인코딩할 수 있습니다. 예를 들어, 숫자 25는 Protobuf에서 1바이트로 표현되며, 필드명 또한 숫자로 변환되어 데이터 크기를 최소화합니다.

이러한 효율적인 인코딩 방식 덕분에 gRPC는 동일한 데이터라도 훨씬 작은 크기로 전송할 수 있으며, 이는 네트워크 대역폭을 절약하고, 데이터 전송 속도를 크게 향상시킵니다.

 

결론적으로, REST의 JSON 직렬화는 텍스트 기반의 데이터 표현 때문에 크기가 커지는 반면, gRPC의 Protobuf는 바이너리 형식으로 데이터를 압축하여 보다 효율적으로 전송할 수 있습니다. 이는 특히 대용량 데이터 전송에서 gRPC가 REST보다 유리한 이유 중 하나입니다.

 

참고로 왜 페이로드의 크기에 따라서 데이터의 전송이 느려지는지 그 이유를 보면 페이로드는 아래의 그림처럼 패킷단위로 쪼개지게 됩니다. 따라서 페이로드가 크면 전송 할 패킷이 많다는 뜻이고, 이는 네트워크 트레픽을 네트워크 트래픽을 증가시켜 전송 속도를 저하시킬 수 있습니다. 이러한 이유로, 효율적인 데이터 전송을 위해 페이로드 크기를 최적화하는 것이 중요합니다.

 
SYNC ACK SYNC 비싸다며?
 

네트워크 연결 비용이 비싸다는 말은 프로그램 개발에서 자주 듣는 이야기입니다. 이는 네트워크 연결을 설정하는 과정에서 발생하는 시간과 자원 소모를 의미합니다. 예를 들어, 데이터베이스 연결에서는 커넥션 풀을 미리 생성하여 이러한 비용을 줄이려고 합니다.

 

HTTP 1.1을 사용한 REST 통신에서는 기본적으로 각 요청마다 네트워크 연결을 수립해야 합니다. 반면, HTTP/2를 사용하는 gRPC는 이와 다르게 동작합니다. HTTP/2는 한 번의 TCP 연결만으로 클라이언트와 서버 간에 데이터를 계속 주고받을 수 있습니다. 클라이언트는 데이터를 지속적으로 서버에 전송할 수 있고, 서버도 마찬가지로 클라이언트에게 계속해서 데이터를 전송할 수 있습니다.

하지만 이것이 진짜 차이점일까요? 정답은 아닙니다. 왜냐하면 HTTP 1.1에서도 Persistent Connection이 가능하기 때문입니다. 하지만

HTTP 1.1의 Persistent Connection에서는 요청이 순차적으로 처리되므로, 하나의 요청이 완료되어야 다음 요청이 처리됩니다. 반면, HTTP/2의 경우에는 하나의 TCP 연결 내에서 여러 개의 요청이 병렬로 처리되기 때문에 응답 속도가 더 빨라지고, 네트워크 자원의 효율성이 높아집니다.

 

이러한 기술을 **멀티플렉싱(Multiplexing)**이라고 부르며, 아래의 그림은 클라이언트가 네트워크 커넥션을 맺고, 여러 스트림(stream)을 통해 요청을 병렬로 보내고 있는 것을 나타냅니다.

반응형