gRPC Series #3

박인성 (Bahk InSung)·2023년 8월 11일
1

grpc_series

목록 보기
3/3
post-thumbnail

오늘도 돌아왔다. gRPC로. 이번에는 간단히 Stream에 대한 개념을 익혀볼려고 한다. 사실 본인은 백엔드를 다룬 것도 고등학교 2학년 PHP로 쇼핑몰 프로젝트 (심지어 학교 과제로) 해본 것 외에는 정말 없고 Stream을 해본 적이 없어서 어렵습니다.

이번에는 gRPC에서 말하는 Stream와 구현을 알아볼려고 한다.

Stream 🌥️

선배가 나에게 말하길...

Stream은 빨대와 같은 것이다.

아래 사진을 보고 한번 설명을 해보려 한다.

gRPC의 기초적인 형태를 말하고 있다. 여기서 Consumer를 Client, Product Info는 Server로 정의를 하자. Client는 Server에게 요청을 한다. 이때 요청을 하는 일종의 라인 (편하게 생각하면 전화선) 이 Stream와 같은 역할을 하는 것이다. 반대로 Server가 Client에게 전송하거나 요청을 하는 경우도 있을 것이다. 이것 또한 Stream을 거치게 된다.

단, 어디서 출발을 하고 어떤 빨대를 타고 전달을 하냐에 따라서 명칭과 하는 역할, 내용이 달라질 수 있다. 이를 Unary RPC, Client-streaming RPC, Server-streaming RPC, bidrectional streaming RPC가 있다.

🥥 Simple RPC (Unary RPC)


흔히들 알고 있는 기본적인 RPC 형태라고 생각하면 될 것 같다. 요청하는 곳이 있고 요청을 받아서 응답을 하는 곳이 있는 Request와 Response의 위치가 정해져 있는 RPC 형태가 곧 Unary RPC 형태이다.

Protobuf의 정의에 따라서 주고 받는 메세지가 달라질 것이고 전달되는 내용과 방식이 다르겠지만 기본적으로 Consumer가 Request를 보내면 Order Mgt Service인 Server에서 그에 맞는 Response를 해준다.

👷‍♂️Server-Streaming RPC


Unary RPC와는 살짝 다르다. 이름에서 보이는 것처럼 Server-Streaming 이지 않는가? 빨대를 계속 꽂고 있다고 생각해보자. 여기서 빨대는 Server가 Client에게 꽂는다. 그 말인 즉슨, 한번의 Request에 여러개의 Response이 오고간다는 것을 의미한다.

이게 왜 필요할까? 라고 생각할 수 있지만 여러개의 응답을 한번에 전송해야하는 경우가 있다. 만약에 Client가 전송한 Request가 "업무 시작!" 이라는 Request 였다면 Server에서는 계속해서 업무가 끝이 날떄까지 응답을 보내는 서비스 등이 존재할 것이다. 실시간으로 정보를 전달하거나 여러개의 정보를 나눠서 보내는 등의 방법에서 활용될 수 있을 것이다.

Stream을 정의할 때에는 Protobuf에서 정의시 stream을 반드시 붙여줘야한다. 아래 예시를 보면 이해가 빠를 것이다.

syntax = "proto3";

import "google/protobuf/wrappers.proto";

package ecommerce;

service OrderManagement {
    ...
    rpc searchOrders(google.protobuf.StringValue) returns (stream Order); 1
    ...
}

간단한 예시인 만큼 크게 내용은 아래 Message는 생략하였다. 보면, Requst로는 String이 들어가지만 Response로는 Order라는 Message가 stream으로 들어간다. 곧, stream으로 전송해주는 것은 계속 응답을 해주는 것을 의미하며 이는 코드와 구현에 따라 달라지겠지만 한번의 응답에서 끝은 아니다. Server-Streaming RPC는 동기처리로 진행하게 되면서 Client의 요청 이후 Server의 응답까지 기다리게 된다. Client 단에서 하나의 요청을 보내더라도 Server가 모든 답을 하기 전까지는 Client는 대기 상태이다.

🛂 Client-Streaming RPC


Server-Streaming와 같이 Client-Streaming은 Client에서 여러개의 Request를 보낸다고 생각하면 된다. Stream이 Client 단에서 존재하기 때문에 Response는 Server 단에서는 한번만 보내게 된다. Server-Streaming과는 반대라고 이해하는게 맞다. Protobuf의 코드는 아래와 같이 작성하면 된다.

syntax = "proto3";

import "google/protobuf/wrappers.proto";

package ecommerce;

service OrderManagement {
...
    rpc updateOrders(stream Order) returns (google.protobuf.StringValue);
...
}

보이는 것과 같이 Request에서 stream이 있어서 여러개의 Request를 보내고 이를 받은 Server 단에서는 한번의 Response를 반환하게 된다. 물론 이 내용도 코드 작성과 구현에 따라 다를 순 있다. 중요한 점은 비동기처리와 같이 작동된다. Client 단에서 아무리 많은 요청을 보내어도 Client는 Server의 응답을 기다리지 않는다.

🤜🤛 Bidirectional-Streaming RPC


무려 양방향 통신이다. Server-Streaming과 Client-Streaming이 하나가 되어서 Bidrectional Streaming이 되는 것이다. 그렇게 되면 Reqeust도 Response도 서로 계속 주고 받게 되면서 일종의 실시간 처리처럼 작용하게 된다. Bidrectional Streaming은 Client- 와 Server-Streaming에 반해서 동기처리로 진행하게 된다. 헷갈리지 말 것.

Refernce

  1. gRPC Up & Running: Building Cloud Native Applications with Go and Java for Docker and Kubernetes (O'Reily)
  2. Core concepts, architecture and lifecycle
profile
Just normal person, that know COBOL

0개의 댓글