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로 전환하면 전체 시스템 성능을 크게 개선할 수 있습니다. 특히 높은 처리량이 요구되는 결제, 추천, 검색 등의 서비스에서 즉각적인 효과를 체감할 수 있습니다.
spring
| No | 작성일 | Title |
|---|---|---|
| 2005 | 2025. 11. 30. | Spring Security 6 JWT 인증 구현 |
| 2004 | 2025. 11. 30. | Spring Boot 3.x 새로운 기능 정리 |
| 1824 | 2022. 05. 24. | [ spring ] interceptor 등 스프링에서 @Autowired 인식을 못할때 |
| 421 | 2016. 08. 02. | [ spring-security ] 스프링 시큐리티 csrf (크로스도메인) 설정방법 |
| 349 | 2016. 02. 16. | [ spring ] spring4 jsonp callback |
| 346 | 2016. 02. 08. | [ spring 4 ] 스프링 4 websocket 및 stomp (채팅 및 쪽지 구현) |
| 344 | 2016. 02. 06. | [ spring-security ] 스프링 시큐리티 4 버전에서 hasRole 및 hasAnyRole 안될경우 |
| 328 | 2015. 11. 05. | [ spring security ] 스프링 시큐리티 유저정보 얻는 방법 |
| 311 | 2015. 06. 30. | [ spring ] IOException while loading persisted sessions: java.io.EOFException 해결 |
| 310 | 2015. 06. 29. | [ spring ] How To Get HTTP Request Header In spring ( 스프링에서 http header 값 가져오기) |