-
RPC (Remote Procedure Call)Back-end Developer/Server, Spring 2020. 10. 29. 18:38
오늘은 제가 SW maestro 10기에서 적용한 thrift 즉, RPC에 대해 정리해보려 합니다.
-> 아직은 부족한 게 많아 지속적으로 수정될 예정입니다.
막상 사용하는 것 자체는 찾아보면 쉽게 할 수 있습니다. (generate code를 통해 생성하기 때문에 매우 편리합니다.)
하지만, 제대로 된 개념을 아는 것은 좀 다른 문제겠지요.
RPC
원격 프로시저 호출(remote procedure call, 리모트 프로시저 콜, RPC)은 별도의 원격 제어를 위한 코딩 없이 다른 주소 공간에서 함수나 프로시저를 실행할 수 있게 하는 프로세스 간 통신 기술이다. 다시 말해, 원격 프로시저 호출을 이용하면 프로그래머는 함수가 실행 프로그램에 로컬 위치에 있든 원격 위치에 있든 동일한 코드를 이용할 수 있다.
(출처 wiki)
여기서 주목할 점은 '통신 기술'입니다.
즉, 일반적으로 사용하는 Server-Client 구조를 갖는다고 생각하시면 됩니다.
그런데, 서버-클라이언트 구조를 이와 같이 이해하시면 조금은 헷갈릴 수 있습니다.
Server: back-endClient: front-end그들의 역할을 기준으로 생각해봅시다.
Server: response
Client: request
서버는 클라이언트의 어떤 요청에 대해 응답합니다.
아시겠지만, 요청을 보낼 때 서버와 시간을 정해 언제 요청을 보내겠다 약속하고 보내진 않습니다.
일반적으로 언제든 응답을 줄 수 있도록 실행 및 대기하고 있죠.
RPC를 구성할 때 이러한 점을 잘 고려해서 어떤 것이 Server/Client 역할을 할지 고민해보는 것이 좋습니다.
위와 같이 서버-클라이언트의 역할을 받아들이셨다면, 본 내용으로 들어가겠습니다.
정확히 어떤 이유로 인해 RPC가 생겨났고 필요한지 그리고 구성요소 등을 살펴봅시다.
일반적으로 통신하면 주로 사용하고 잘 알려진 것은 Socket입니다.
Socket은 원격지와 로컬의 프로세스를 연결해 통신할 수 있도록 도와줍니다.
Socket 단점
1. Data Formatting
2. 통신 관련 장애 처리
요즘 같은 분산 네트워크 환경에선 위와 같은 작업을 일일이 하는 것은 거의 불가능에 가깝겠죠.
이를 단순히 하기 위해 등장한 것이 바로 RPC입니다.
통신 관련 문제를 신경 쓰지 않고 원격지의 함수를 마치 로컬의 함수처럼 쓴다는 것이 큰 장점입니다.
특히, IDL(Interface Definication Language) 기반으로 다양한 언어를 가진 환경에서도 쉽게 확장이 가능합니다.
IDL
인터페이스 정의 언어 (Interface Definition Language)는 소프트웨어 컴포넌트의 인터페이스를 묘사하기 위한 명세 언어이다. IDL은 어느 한 언어에 국한되지 않는 언어 중립적인 방법으로 인터페이스를 표현함으로써, 같은 언어를 사용하지 않는 소프트웨어 컴포넌트 사이의 통신을 가능하게 한다. 예를 들면, C++을 사용하여 작성한 컴포넌트와 자바를 사용한 컴포넌트 사이에서 국한되지 않고, 인터페이스를 묘사하는 개념이다.
IDL 은 보통 RPC를 이용한 소프트웨어에서 사용된다. 이때, RPC "연결"의 양 쪽에 있는 컴퓨터는 다른 운영 체제와 프로그래밍 언어를 사용할 수 있다. IDL은 다른 두 개의 시스템을 연결하는 다리 역할을 한다.
(출처 wiki)
IDL은 위에 설명과 같이 다리 역할을 합니다. IDL로 연결하는 프로시저를 정의하고, 이를 통해 코드를 generate 합니다.
RPC에서 실질적으로 가장 중요한 역할을 하는 것은 stub입니다.
우선, 일상생활을 예로 들어 보겠습니다.
왼쪽 집에서 오른쪽 집으로 이사했다고 가정해봅시다.
침실에 있던 침대를 이사 후에도 그 위치대로 둔다면, 침대는 화장실로 가겠죠.
현관에 있던 신발들은, 침실 2로 이동할 것입니다.
말이 안 되는 상황입니다. 당연히 이사를 했으면 그에 맞는 위치에 놓아주어야죠.
RPC도 마찬가지입니다. 로컬에서 어떤 변수를 통해 원격지에 요청을 보냈다고 가정하겠습니다.
그런 경우 사용할 변수의 정확한 위치를 알아야 하는데, 로컬에서 쓰던 변수의 주소를 통해 접근해도 될까요?
당연히 안됩니다. 따라서 이러한 주소의 싱크(?)를 맞춰주는 역할을 stub가 진행합니다.
Client(caller) stub
Marshalling (함수 호출에 사용된 파라미터의 변환) 및 함수 실행 후 서버에서 전달된 응답 변환.
Server(callee) skeleton
Unmarshalling (클라이언트가 전달한 매개 변수 역변환) 및 함수 실행 결과 변환
(출처 wordpress)
- IDL(Interface Definition Language)을 통해 사용할 프로시저 방식을 정의
- stub code를 generate
- caller에서 stub에 정의된 함수 호출 (by. RPC Runtime)
- callee는 수신된 procedure 호출에 대한 처리 후 결과 값을 반환
이렇게 개발자가 해야 할 일을 직접 처리해 주는 편리한 방식에도 불구하고 아래의 단점으로 일반 통신에선 잘 사용하지 않습니다.
RPC 단점
Server-client가 한데 묶여 업그레이드가 어려움
육안으로 코드를 이해하기 어려움
에러 발생 시 바이너리 포맷 분석 및 디버깅의 어려움
third party 언어에 의존적
따라서, 일반적인 통신에선 'REST API'가 주로 사용되고 있습니다.
하지만, 아래의 글에서도 보시다시피, 특정 상황에서 gRPC가 대체로 고려되기도 오히려 더 낫다는 의견도 있습니다.
https://stackoverflow.com/questions/44877606/is-grpchttp-2-faster-than-rest-with-http-2
우리 팀은 왜 thrift를 사용했을까?
이러한 내용을 보니 저희 팀은 왜 SW maestro에서 thrift를 사용했을까 의문이 생기실 수 있습니다.
별로 안 궁금하시다면 여기서 포스팅을 마치도록..저희가 thrift를 적용한 기능은 서버에서 이미지로 요청을 보내 모듈로부터 응답받는 방식이었습니다.
우선 딥러닝 모듈의 로딩 속도가 30초로 매우 길다는 것이 RPC가 가장 필요한 이유였습니다.
두 번째와 같은 방식으로 매 요청마다 발생한 로딩 시간을 처음 실행 후 대기로 요청 간 로딩 시간을 없애 빠른 응답 요청을 의도했습니다.
또한, 막바지 기간에 작업한 것으로 구현도 빠른 기술이 필요했습니다.
-> 자동으로 생성되는 stub, skeleton 및 간결한 코드.
굳이 gRPC가 아닌 thrift를 적용한 이유는 gRPC의 Async 관련 지원이 1.25v(2019.11)부터 이루어졌기 때문입니다.
저희 팀은 19년 8~9월부터 이미 관련 개발 진행했으며, 빠른 응답 요청을 위한 비동기 처리는 필수였습니다.
특히, RPC 적인 요소보다 상이한 언어 간 효율적인 데이터 변환 및 통신을 위해 고려되었습니다.
영상을 시간마다 이미지로 끊어서 보내야 했기 때문에 방대한 양의 이미지의 크기를 줄이고 통신하는 방법에 대한 대응.
또한, thrift는 공식 문서가 잘 나온 편은 아니라고 하는데.. 적당히 찾아보면 금방 구현되더라고요.
(물론 gRPC는 별로다 또는 더 어렵다는 뜻은 아닙니다.)
결과적으로 사용하시기에 앞서 자신의 프로젝트에 잘 어울리는 것이 무엇인지 충분히 고민하고 적용하시길 바랍니다.
참고 자료
반응형'Back-end Developer > Server, Spring' 카테고리의 다른 글
MSA (0) 2021.03.24 RestTemplate & URLConnection (0) 2020.10.30 REST API (2) (0) 2020.07.19 REST API (1) (0) 2020.07.17 AOP (0) 2020.06.29