딜리셔스 정보검색파트가 이미지 검색 API 에 gRPC 를 적용하며 정리한 글이다. REST 호출이 중첩될 때 생기는 직렬화 비용과 스레드 점유, 반복 구현 부담을 짚고 Spring Boot 에 gRPC 를 얹는 설정을 proto 정의부터 서버 기동까지 따라간다. 적용 결과는 성능 이득보다 반복 작업 제거 쪽이 컸다고 솔직하게 적는다.
핵심 포인트- REST 를 대체하기 어려웠던 걸림돌로 JSON 변환 후 다시 바이너리로 직렬화하는 중복 작업, 언어와 CPU 가 달라 생기는 endian 및 byte 처리 차이, 한 통신을 한 스레드가 붙잡는 낭비, 클라이언트가 알아야 하는 API 정보량을 든다.
- gRPC 는 구글이 내부 서비스 간 통신에 쓰던 Stubby 를 2015년경 오픈소스로 낸 라이브러리다. HTTP/2 기반 이벤트 방식으로 동작한다.
- 프로토콜 버퍼 IDL 을 정의하면 서비스 인터페이스와 DTO 클래스, 직렬화 코드가 자동 생성된다. 서버는 인터페이스 구현만, 클라이언트는 호출만 하면 된다.
- 통신 방식은 네 가지다. 단일 요청과 단일 응답, 서버 스트리밍, 클라이언트 스트리밍, 양방향 스트리밍.
- 적용 결과 평가가 냉정하다. 대상인 이미지 벡터 조회는 요청이 많지 않아 성능 이득이 작았고, 쿠버네티스가 아닌 EC2 환경이라 로드밸런서에 gRPC 프로토콜 처리를 수동으로 추가해야 했다.
상세 정리- proto 파일에는 syntax 와 outer class 이름, package 를 명시하고 message 로 요청과 응답 객체를, service 로 인터페이스를 정의한다. 각 필드 끝의 숫자는 order 를 나타내는 필수값이다.
- 키워드 두 개를 구분한다. stream 은 여러 개의 요청이나 응답을, repeated 는 배열을 뜻한다.
- 빌드 자동화가 중요하다. gradle 에 protobuf 플러그인과 protoc, protoc-gen-grpc-java 아티팩트를 지정하지 않으면 수동 빌드를 반복하게 된다.
- 의존성은 grpc-netty-shaded, grpc-protobuf, grpc-stub 과 protobuf-java-util 이고 테스트에는 grpc-testing 을 쓴다.
- sourceSets 에 build/generated/source/proto 하위 경로를 소스 폴더로 추가하고 proto 파일 위치도 지정해야 IDE 가 생성된 클래스를 인식한다.
- 서비스 구현은 생성된 추상 클래스를 상속한다. gRPC 가 이벤트 기반이라 구현 방식이 Spring WebFlux 나 Rx 라이브러리와 비슷하다.
- 단일 응답은 결과를 만들어 responseObserver 의 onNext 로 보내고 onCompleted 로 완료 이벤트를 던진다. 예외는 Status 에 설명을 붙여 onError 로 반환하며, cause 는 클라이언트로 전송되지 않고 인터셉터 참조용이다.
- 클라이언트 스트리밍은 StreamObserver 를 반환해 onNext 로 계속 요청을 받고, 클라이언트가 완료 이벤트를 보낸 시점에 한 번의 응답을 돌려준다. 완료 이벤트가 오지 않으면 서버는 계속 대기한다.
- 서버 스트리밍은 반대로 요청 한 번에 onNext 를 여러 번 호출해 데이터를 흘려보낸다. 개념적으로 모바일 알림과 같다고 설명한다.
- 기본 타입 객체는 자동 생성된 has 메서드로 존재 여부를 검증할 수 있다.
- 서버 설정은 ServerBuilder 로 포트와 서비스 빈을 등록해 Server 빈을 만드는 것이 전부다. grpc-java 는 Netty 를 임베드해 쓴다.
- 기동은 Spring 과 별도로 해야 해서 ApplicationRunner 에서 start 와 awaitTermination 을 호출하고, DisposableBean 의 destroy 에서 shutdown 한다.
- 저자는 Spring Web 에서 하던 controller 와 parameter dto 구성 같은 반복 작업이 빌드 시 자동 생성돼 비즈니스 로직에 집중할 수 있었던 점을 실제 이득으로 꼽고, 서비스 간 통신량이 많은 환경일수록 가치가 크다고 정리한다.
왜 읽나MSA 내부 통신을 REST 에서 gRPC 로 옮길지 저울질하는 백엔드 개발자에게 Spring Boot 설정 전 과정과 도입 후에도 남는 불편까지 알려주는 적용기.