블록체인

gRPC (Java) 구현목적과 동기/비동기 통신방식

늘근이 2017. 10. 31. 00:16

다음의 사이트를 참조했다.


gRPC Basics - Java

https://grpc.io/docs/tutorials/basic/java.html

gRPC 공식 사이트


디지털 세상을 만드는 아날로거 - Microservices with gRPC

https://medium.com/@goinhacker/microservices-with-grpc-d504133d191d

한글로 되어있는 친절한 내용이다. 


위의 참고되는 두 사이트는 내용이 거의 동일하고 내용을 모두 커버하고 있지만 이글의 존재가치는, 아무래도 여러 방식의 설명이 있으면 뭔가 인터넷검색러들에게 도움이 될것같아 키보드를 쳐본다. 

---------------------------------------------------------------------

우리는 왜 gRPC를 쓰는가? 누군가가 써서 그렇다. 그냥 예전거 쓰지 왜 귀찮게 다른건 쓰는가? 레퍼런스가 되는 놈을 만든 분들이 멋있다고 느꼈기 때문이다.

그 레퍼런스는 블록체인의 멋쟁이 하이퍼레저이며, gRPC는 1.0부터 꽤나 미는 방식으로 보이고, 향후 3~5년까지는 계속 구현사례가 많아질것으로 느낌이 든다.

일단 gRPC의 대략적인 아웃라인을 이해하기 위해서 몇가지 생각해본다. 우리는 클라이언트 코드를 구현할때 서버에 있는 무언가를 쓰고자 한다면 무언가 주소를 호출한다. 아래와같이 깔끔하게 떨어지는 경우도 있고 

http://something.com/user/149192

아닌 경우도 있다.

http://something?q=149192

RPC방식으로 작동하는 코드는 위의 주소호출는 죄다 잊어버려도 된다. gRPC는 그 이름답게 Remote Procedure Call의 기능에 충실한다. 일단 클라이언트에서 서버에 있는 사람의 정보를 가져오고 싶다고 하자.


클라이언트의 getUser()메서드

getUser() -> 주소를 통해 서버에 붙고 -> 서버에서 주는 json/xml형식의 데이터 파싱 -> User 객체에 넣기 -> 이용.

서버의 getUser()메서드

getUser() -> DB에 붙고 -> JDBC등이 주는 데이터를 클라이언트에 response해줌

근데 여기서 쓰잘데기 없어 보이는게 있다. 클라이언트도 어차피 User라는 놈을 쓸것이고, 서버도 어차피 User라는 놈을 쓰고 둘의 정보는 같다. 그렇다면 그냥 서버에있는 코드를 클라이언트가 바로 쓰지 왜 굳이 문자열로 바꿔주고 쏴주고 이를다시 바꿔주고 하는 클라이언트의 거추장스러운 방식을 통해서 서버의 데이터를 호출해야 하는가?

클라이언트는 사실 서버가 쓰는 getUser() 메서드를 가져다 쓰기만 하면 되는것이다. 다만, 서버에 로직이 구현되어있는건 알겠는데, 뭘 어떻게 불러야하는가? 결국에는 네트워크를 이용하는 뭔가를 구현해야하지 않는가? 라는 복잡한 문제는 잊어버리기위한 방법이 원격프로시저호출 (Remote Procedure Call)이다.

이를 편리하게 만들어놓은게 구글신이 만드는 gRPC 가 그 일종.

클라이언트는 .proto라는 파일에 몇가지 세팅만 해놓고 서버에서 쓰는 기능 을 Stub으로 만든다. (모의) 그리고 그냥 서버가 하듯이 메서드를 호출하기만 하면 알아서 저 메서드는 구현을 하지 않더라도 서버의 같은 이름의 메서드가 작동하여 뿅 바로 클라이언테에게 데이터를 내려주게 된다.


다만 데이터를 이용하는 방법이 여러개 있는데 다음을 보자. proto파일 안에다 구현하는 간단한 세팅이다.

1) 클라이언트가 요청하고 서버가 한번 응답하는 방식

rpc GetGamza(money) returns (Gamza) {}

2) 클라이언트가 요청하고 서버가 스트림으로 주는 방식

rpc GetGamza(money) returns (stream Gamza) {}

3) 클라이언트가 스트리밍으로 보내는 방식

rpc GetGamza(stream Goguma) returns (Gamza) {}

4) 둘다 스트리밍으로 냅다 던지는 방식

rpc GetGamza(stream Goguma) returns (stream Gamza) {}

지금이 야밤이라 배고파 생각이 잘나지않아 감자로 그림을 그려버려서 예제가 참 억지스럽지만 어떻게 하겠는가, 벌써 그려버린것을. 

어쩄든 예를들어 클라이언트가 복수로 이루어져 있는 서버 네트워크 안으로 무언가 데이터를 던지면, 서버는 이에대한 응답 요청을 여러번 해야될 경우가 있다는것이다. 이놈저놈 죄다 준비가 될때마다 클라이언트에게 보내주어야 한다는것이다.

블록체인을 생각해보면 블록체인 네트워크에 나의 데이터를 던진 후, 서버안의 하나의 피어가 오케이를 보낼때마다 결과를 받고싶어할수 있다. 이러한 경우가 딱이다.

어쨌든 기존방식과 다르게 클라이언트는 한번던져도 되고 막던져도 되고, 그것은 서버도 마찬가지다. 구현만 잘 해놓으면 된다. 

사실 여기 샘플이 잘 있으니 참고하도록하고,

https://github.com/grpc/grpc-java/blob/master/examples/src/main/java/io/grpc/examples/routeguide/RouteGuideServer.java

StreamObserver을 상속받아 구현만 잘 하기만하면 이제 onNext()에서 저 감자를 하나씩 받을때마다 어떤 로직을 타야하는지 구현을 할수도 있고 onCompleted()에서 모든게 끝났을때 로직을 구현할수도있다.

상세한 구현코드를 적고자 했지만, 일단 내일을 위해 잔다.


간단한 gRPC 사용체험기 - 

일단, RPC 방식을 씀에 있어 클라이언트에서 서버의 코드를 바로 옆에 있는것처럼 자연스레 쓴다는 개념은 좋다. 다만, 클라이언트는 실제 구현된 코드가 없기 때문에 proto파일을 통해 뭔가 빌드하고 청소해주는 작업들이 부수적으로 생긴다는 것이다. 물론, IDE빨을 타기는 하겠지만, 그래도 자동생성되는 코드를 이용한다는것은 빌드해서 맞춰주는 세팅절차가 필요하단것이고, 가끔은 뭐가 잘 안맞으면 구현보다 세팅에 시간이 더 필요할때도 있는 법이다.