Contents
see List개요
gRPC는 Google이 개발한 고성능 RPC 프레임워크로, Protocol Buffers를 사용하여 JSON보다 빠르고 작은 페이로드를 제공합니다. Spring Boot에서 gRPC를 사용하면 REST API 대비 10배 이상 빠른 마이크로서비스 간 통신을 구현할 수 있습니다. 이 문서에서는 Spring Boot 3.5와 gRPC-Spring-Boot-Starter를 활용한 실전 구현 방법을 다룹니다.
의존성 및 플러그인 설정
gRPC와 Protobuf 코드 생성을 위한 의존성을 추가합니다.
<properties>
<grpc.version>1.60.0</grpc.version>
<protobuf.version>3.25.1</protobuf.version>
</properties>
<dependencies>
<dependency>
<groupId>net.devh</groupId>
<artifactId>grpc-spring-boot-starter</artifactId>
<version>3.1.0.RELEASE</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-protobuf</artifactId>
<version>1.60.0</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-stub</artifactId>
<version>1.60.0</version>
</dependency>
</dependencies>
<build>
<extensions>
<extension>
<groupId>kr.motd.maven</groupId>
<artifactId>os-maven-plugin</artifactId>
<version>1.7.1</version>
</extension>
</extensions>
<plugins>
<plugin>
<groupId>org.xolstice.maven.plugins</groupId>
<artifactId>protobuf-maven-plugin</artifactId>
<version>0.6.1</version>
<configuration>
<protocArtifact>
com.google.protobuf:protoc:3.25.1:exe:detect
</protocArtifact>
<pluginId>grpc-java</pluginId>
<pluginArtifact>
io.grpc:protoc-gen-grpc-java:1.60.0:exe:detect
</pluginArtifact>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>compile-custom</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>Protocol Buffers 정의
서비스와 메시지 타입을 .proto 파일로 정의합니다.
// src/main/proto/user_service.proto
syntax = "proto3";
option java_multiple_files = true;
option java_package = "com.example.grpc.user";
package user;
service UserService {
rpc GetUser(UserRequest) returns (UserResponse);
rpc CreateUser(CreateUserRequest) returns (UserResponse);
rpc StreamUsers(StreamRequest) returns (stream UserResponse);
}
message UserRequest {
int64 id = 1;
}
message CreateUserRequest {
string name = 1;
string email = 2;
}
message UserResponse {
int64 id = 1;
string name = 2;
string email = 3;
int64 created_at = 4;
}
message StreamRequest {
int32 limit = 1;
}gRPC 서버 구현
@GrpcService 어노테이션으로 서비스를 구현합니다.
@GrpcService
@RequiredArgsConstructor
public class UserGrpcService extends UserServiceGrpc.UserServiceImplBase {
private final UserRepository userRepository;
@Override
public void getUser(UserRequest request,
StreamObserver<UserResponse> responseObserver) {
User user = userRepository.findById(request.getId())
.orElseThrow(() -> new StatusRuntimeException(
Status.NOT_FOUND.withDescription("User not found")
));
UserResponse response = UserResponse.newBuilder()
.setId(user.getId())
.setName(user.getName())
.setEmail(user.getEmail())
.setCreatedAt(user.getCreatedAt().toEpochSecond())
.build();
responseObserver.onNext(response);
responseObserver.onCompleted();
}
@Override
public void createUser(CreateUserRequest request,
StreamObserver<UserResponse> responseObserver) {
User user = new User(request.getName(), request.getEmail());
User saved = userRepository.save(user);
UserResponse response = UserResponse.newBuilder()
.setId(saved.getId())
.setName(saved.getName())
.setEmail(saved.getEmail())
.setCreatedAt(saved.getCreatedAt().toEpochSecond())
.build();
responseObserver.onNext(response);
responseObserver.onCompleted();
}
@Override
public void streamUsers(StreamRequest request,
StreamObserver<UserResponse> responseObserver) {
userRepository.findAll(PageRequest.of(0, request.getLimit()))
.forEach(user -> {
UserResponse response = UserResponse.newBuilder()
.setId(user.getId())
.setName(user.getName())
.setEmail(user.getEmail())
.build();
responseObserver.onNext(response);
});
responseObserver.onCompleted();
}
}gRPC 클라이언트 구현
@GrpcClient 어노테이션으로 다른 서비스를 호출합니다.
@Service
public class OrderService {
@GrpcClient("user-service")
private UserServiceGrpc.UserServiceBlockingStub userStub;
public Order createOrder(Long userId, OrderRequest request) {
// gRPC로 사용자 정보 조회
UserResponse user = userStub.getUser(
UserRequest.newBuilder()
.setId(userId)
.build()
);
// 주문 생성 로직
Order order = new Order(user.getName(), request.getProduct());
return orderRepository.save(order);
}
}# application.yml
grpc:
server:
port: 9090
client:
user-service:
address: 'static://localhost:9090'
negotiationType: plaintext # 개발 환경
# 프로덕션: TLS 설정
# enableKeepAlive: true
# keepAliveTime: 30s활용 팁
- 에러 처리: StatusRuntimeException으로 gRPC 표준 에러 코드를 반환합니다. (NOT_FOUND, INVALID_ARGUMENT, PERMISSION_DENIED 등)
- 인터셉터: @GrpcGlobalServerInterceptor로 인증, 로깅, 메트릭 수집을 전역 처리할 수 있습니다.
- 스트리밍: Server/Client/Bidirectional 스트리밍으로 실시간 데이터 전송이 가능합니다.
- TLS 보안: 프로덕션 환경에서는 반드시 TLS를 활성화하여 데이터를 암호화해야 합니다.
- 성능: JSON REST API 대비 직렬화 속도가 5~10배 빠르고, 페이로드 크기가 30~50% 작습니다.
마무리
Spring Boot와 gRPC의 조합은 마이크로서비스 간 통신 성능을 극대화합니다. Protocol Buffers의 타입 안정성 덕분에 컴파일 타임에 계약을 검증할 수 있고, HTTP/2 기반으로 멀티플렉싱과 스트리밍을 지원합니다. REST API는 외부 클라이언트용으로 유지하고, 내부 서비스 간 통신은 gRPC로 전환하면 전체 시스템 성능을 크게 개선할 수 있습니다. 특히 높은 처리량이 요구되는 결제, 추천, 검색 등의 서비스에서 즉각적인 효과를 체감할 수 있습니다.