Open Hae-Riri opened 3 years ago
코틀린
gRPC는 client, sever 단위로 인터셉터를 구현하고 설치할 수 있는 간단한 api를 제공한다. 인터셉터는 각 rpc 호출을 중간에서 가로채는 역할을 하고, 사용자는 인터셉터를 사용해서 로깅, 인증/권한부여 등 rpc 전체를 아우르는 공용 기능을 수행할 수 있다.
전처리, rpc 호출, 후처리 세 부분으로 나뉨.
- rpc 호출의 컨텍스트, 메소드 문자열, 전송 요청 등의 설정 정보를 전처리에 사용 가능함. 이걸 이용해 rpc 호출을 수정할 수 있음.
- 전처리가 끝났다면 invoker 를 호출해서 rpc 요청을 호출할 수 있음.
- invoker가 응답과 오류를 반환하면 이제 rpc 호출의 사후처리를 수행할 수 있음. rpc 응답시각과 에러 등을 기록할 수 있다.
unary Interceptor
https://www.mobiinside.co.kr/2019/09/26/buzzvil-grpc/
MSA에수 중요한 건 네트워크 속도. 모놀리식 아케틱처에서 모듈 간 통신은 하나의 프로세스에서 이루어지는 반면, MSA에서는 다양한 서비스들이 다른 프로세스, 다른 호스트에서 돌아가고 있으며 각 서비스 사이 통신이 매우 빈번하게 일어난다.
protocol buffer를 사용하는 grpc는 일반적으로 http/json 요청보다 빠른 속도를 보인다. 물론 요청 한번에 엄청나게 많은 시간을 절약해주는 건 아니지만 하나의 요청에 많은 내부 요청을 사용하는 MSA를 사용하려면 네트워크 요청 시간을 조금이라도 줄이는 게 매우 중요하다.
서비스 간 통신 규약을 정하는 것도 중요하다. 서비스 사이 의존성이 낮아지면서 얻은 장점 대신, 각 서비스가 변경되면서 발생할 수 있는 문제들이 생겨나게 된다. Json을 통한 직렬화는 서비스 사이에서 쉽게 규약이 어긋나거나 실수하기 쉽고, api route 역시 변경 사항을 널리 적용하기 어렵다. 물론 잘 구성된 문서를 통해 규약을 맞추거나, swagger 같은 open api 도구를 사용할 수도 있지만, 이 역시 grpc처럼 학습 비용이 필요한 건 마찬가지다. 어차피 학습한다면 성능 더 좋은걸 학습하는게 낫지?
하나의 proto 파일로 go, python, java, swift 등 다양한 언어의 서버/클라이언트 코드를 생성할 수 있다.
grpc를 http/json으로 변환할 수도 있다. 프로토콜버퍼를 적절하게 json 형태로 선언만 해주면 하나의 grpc 서버로 두 형태 모두 대응할 수 있다. (근데 이걸 반대로 해 내는 방안에 대해서는 알아보는 중임)
내부 모습. 백엔드에서 뭔일이 나나?
생성된 클래스를 보면 안에 stream으로부터 int, string을 읽어오는 부분이 있다. (직렬화가 바이트로 인코딩하고 객체로 복원하는 일련의 과정인데 그 중 객체로 복원하는 과정(디코딩)이 생성된 클래스 내부에 있다.)
CodeInputStream.readInt32()같은 걸 쓰고 있는데, CodeInputStream은 메시지필드를 읽고 디코드 하는 역할이다.
Person 이라는 message를 만들면 protoc로 컴파일되었을 때 Person.java가 생성된다. 얘를 통해 우리는 Person이라는 메시지 유형에 대해 클래스로 접근할 수 있다.
컴파일된 파일 내부에는 아래와 같은 것들이 있다.
FileDescriptor : 파일에 대한 설명자
FieldDescriptor : 필드에 대한 설명자
GeneratedProtocolMessageType 이라는 메타 클래스를 제공함.
EnumDescriptor
EnumValueDescriptor
Descriptor : 메시지에 대한 설명자
프로토콜 버퍼의 장단점
몇가지 데이터 타입들 살펴보자.