들어가면서
게임에서는 문자열을 모두 원본 형태로 보내는 JSON 방식이 아닌 더욱 적은 대역폭으로 전송을 하는 Protobuf를 사용하기도 한다. 이를 실무에서 사용하기 전에 공부해보고자 Protobuf와 RPC에 대한 글을 정리하였다.
RPC 통신
- RPC 통신이란
- Remote Procedure Call(원격 프로시저 호출)의 준말로, 별도의 원격제어 코드 없이
다른 주소 공간에서 함수/프로시저를 실행하도록 하는 프로세스 간 통신 기술(어디든 동일 호출)- 함수
- input에 따른 output의 발생
- return값을 필요로 하며, 간단한 계산 및 수치 등을 도출할 때 사용
- 프로시저
- output 값에 집중보단, 명령 단위 수행절차에 집중
- return은 없을 수도 있고, 서버단에서 함수보다 큰 실행, 프로세싱 시 사용
- 함수
- 프로세스는 기본적으로 자신의 주소공간 안에 존재하는 함수만 호출하여 실행
- RPC는 네트워크를 통한 메시징을 수행하여 서로 다른 네트워크에서의 프로세스에서도 호출 가능
- Remote Procedure Call(원격 프로시저 호출)의 준말로, 별도의 원격제어 코드 없이
- RPC의 목표
- Client-Server간의 커뮤니케이션에 필요한 상세정보를 최대한 감춘다
- Client-Server는 각각 일반 메서드를 호출하는 것처럼 원격지의 프로시저 호출 가능
- RPC의 동작 방식
- IDL을 사용하여 서버의 호출 규약 정의
- 함수명, 인자, 반환값에 대한 데이터 타입이 저장된 IDL 파일을 rpcgen 컴파일러를 이용하여 Stub 코드를 자동으로 생성
- IDL
- Interface Defination Language의 준말로 서버의 호출 규약을 정의
- 인터페이스 정의 언어로 언어 중립적인 방법으로 인터페이스 표현, 구현 언어가 아닌 정의 언어로 구현 언어로의 매핑을 지원
- Stub은 원시 소스코드(C, Java) 형태로 만들어지므로, Client-Server 프로그램에 각각 포함하여 빌드
- 서버에서는 클라이언트 Stub에 정의된 함수를 호출
- Stub 코드는 데이터 타입을 XDR 형식으로 변환
- XDR
- External Data Representation의 준말로 기본 데이터 타입(정수형, 부동 소수점 등)에 대한 메모리 저장 방식(Little, Big-Endian)이 CPU 아키텍처 별로 상이하여바이트 전송 순서 보장을 위해 변경
- XDR
- 서버는 수신된 함수/프로시저 호출에 대한 처리를 서버 Stub을 통해 처리 후, 결과값을 XDR 변환하여 Return
- 클라이언트 프로그램은 서버가 Return한 결과 값을 전송 받음
- IDL을 사용하여 서버의 호출 규약 정의
- RPC의 장점
- 고유 프로세스 개발에 집중 가능
- 프로세스 간 통신 기능을 비교적 쉽게 구현하고 정교한 제어 가능
- RPC의 단점
- 호출 실행과 반환 시간이 보장되지 않음
- 네트워크 구간을 통해 RPC 통신을 하는 경우 네트워크가 끊겼을 때 보장해주지 않음
- 보안이 보장되지 않음
- 호출 실행과 반환 시간이 보장되지 않음
- RPC의 대표적인 구현체
- 구글의 ProtocolBuffer(protobuf)
- 페이스북의 Thrift
- 트위터의 Finalge
Protocol Buffers란
- 구조화된 데이터 직렬화를 통해 언어, 플랫폼 중립적인 패킷을 전송할 수 있으며, 데이터를 바이너리화하여 압축하기 때문에 JSON/XML보다 적은 대역폭으로 송수신 가능
- JSON과의 차이
- JSON
- 사람이 읽는 일반 텍스트로 전송하여 대역폭을 상대적으로 크게 가져가며, 두 언어 모두 쉽게 읽을 수 있어 js/html 기반 웹에서 사용하기에 더 수월
- 사람이 읽을 수 있어 더 간편하며, 디버깅 용이
- protobuf
- 바이너리화되기 때문에 적은 대역폭에서도 사용할 수 있으며, 적게나마 암호화되는 효과를 볼 수 있음
- 응용 프로그램 간 RPC통신 가능
- 데이터 구조 변경 시 이전 버전과 호환 보장
- JSON
- 문법
- Syntax
- 버전을 정하는 것
- proto2, proto3가 존재하며 default는 proto2
- Field Types
- double, float : 실수
- int32, int64 : 음수에 비효율적
- uint32, uint64 : unsigned int 같은 느낌일까요
- sint32, sint64 : 부호있는 정수
- fixed32, fixed64 : 항상 4, 8바이트. 값이 2^28, 2^56보다 크면 효율적
- sfixed32, sfixed64 : 항상 4, 8바이트
- bool : 부울
- string : UTF-8 혹은 7bit ASCII 이여야 함
- bytes : 임의의 바이트 배열 사용가능
- Field Rules
- 필드 타입 앞 선언 시 생기는 조건
message GetUserInfo{
required string uid = 1;
optional string nickname = 2;
repeated string address = 3;
} - 종류
- required : 이 필드를 반드시 1개 가진다(반드시 필요한 필드)
- optional : 이 필드는 가지지 않거나 1개 가진다
- repeated : 이 필드를 0개 이상 가진다(배열처럼 사용 가능)
- proto3에서는 required, optional → deprecate로 변경
- 필드 타입 앞 선언 시 생기는 조건
- Tag
- 각 변수의 숫자는 초기화가 아닌 바이너리 형식 필드를 구분하기 위한 태그
- 0은 사용할 수 없다
- 15번 이전까진 1바이트 인코딩, 15번 이후로는 2바이트 인코딩
- 19000~19999는 예약된 태그여서 사용할 수 없다
- 태그 최대치는 2^29이다
string uid = 1; // 여기서 1에 해당하는 부분이 Tag이다.
- Reserved Field
- 기존 사용하던 필드를 중간에 제거 시, 다시 해당 필드를 재사용하게 되면 일관성 & 호환성 장애를 초래한다
- 그래서 reserved field를 사용하여 사용하지 못하게끔 한다
message GetUserInfo{
reserved 2;
required string uid = 1;
// optional string nickname = 2; // 사용하지 않게됨
repeated string address = 3;
}
- Style guide
- Message 명은 파스칼케이스를 사용한다(첫 문자도 대문자인 카멜 케이스)
- 필드명은 스네이크 케이스로 작성한다
- Syntax
참고 블로그
Protobuf 문법
목차 Syntax Field types Field Rules Tag Reserved Field service(rpc) style guide Syntax syntax = "proto3"; //proto3 버전 문법 사용 'syntax'는 버전을 정하는 구문이며 'proto2'와 'proto3'가 있다. 해당 내용이 없으면 'proto2'가 de
leo-history.tistory.com
'서버개발' 카테고리의 다른 글
Spring protobuf 부분 로딩 오류 해결(GCP Storage Signed Url) (0) | 2023.02.15 |
---|---|
SpringBoot JUnit5 테스트 및 어노테이션 (0) | 2023.02.10 |
GraalVM 소개 (0) | 2023.02.01 |
백엔드 기술 면접 대비(HTTP, JAVA, Spring, JPA 등) (1) | 2022.10.04 |
[Spring] WebSocketConfig StompConfig SSL 설정 및 failover 설정 (0) | 2022.08.21 |