개요
아직 experimental 한 프로젝트지만 Spring Initializr에서 선택 가능한 Spring gRPC를 사용하여 빠르게 gRPC 서비스를 생성할 수 있다.
'org.springframework.grpc:spring-grpc-spring-boot-starter'를 사용하여 빠르게 gRPC 서비스를 생성해 본다.
Getting started
Project 생성
Spring Initializr를 사용하여 Spring gRPC를 선택하고 프로젝트를 생성한다.
Spring gRPC는 Spring Boot 3.3.x 이상만 지원한다.
(https://docs.spring.io/spring-grpc/reference/getting-started.html)
build.gradle
생성된 build.gradle을 확인해 보면 spring-grpc-spring-boot-starter와 proto파일을 위한 설정이 추가되었다.
dependencies {
implementation 'io.grpc:grpc-services'
implementation 'org.springframework.grpc:spring-grpc-spring-boot-starter'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.springframework.grpc:spring-grpc-test'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
}
dependencyManagement {
imports {
mavenBom "org.springframework.grpc:spring-grpc-dependencies:${springGrpcVersion}"
}
}
protobuf {
protoc {
artifact = 'com.google.protobuf:protoc'
}
plugins {
grpc {
artifact = 'io.grpc:protoc-gen-grpc-java'
}
}
generateProtoTasks {
all()*.plugins {
grpc {
option 'jakarta_omit'
option '@generated=omit'
}
}
}
}
proto
gRPC 서비스를 하기 위해서는 proto파일을 생성해야 하는데 프로젝트를 생성하면 src/main/proto 디렉터리가 자동으로 생성되고 이 디렉터리에 proto파일을 생성하고 gradle 빌드를 하면 자동으로 proto 파일이 컴파일이 되어 프로젝트에서 사용할 수 있다.
사용자를 저장하고 조회하는 간단한 proto 파일을 생성하고, gradle 빌드를 실행한다.
syntax = "proto3";
package org.igooo.grpc;
message UserRequest {
string name = 1;
int32 age = 2;
}
message UserResponse {
int32 id = 1;
string name = 2;
int32 age = 3;
}
message Empty {
}
service UserManagement {
rpc CreateUser(UserRequest) returns (UserResponse) {}
rpc FindUsers(Empty) returns (stream UserResponse) {}
}
gradle build
Executing 'build'…
Download https://repo.maven.apache.org/maven2/com/google/protobuf/protoc/3.25.5/protoc-3.25.5.pom, took 39 ms
Download https://repo.maven.apache.org/maven2/com/google/google/5/google-5.pom, took 6 ms
> Task :extractIncludeProto
> Task :extractProto
Download https://repo.maven.apache.org/maven2/com/google/protobuf/protoc/3.25.5/protoc-3.25.5-windows-x86_64.exe, took 772 ms
Download https://repo.maven.apache.org/maven2/io/grpc/protoc-gen-grpc-java/1.69.0/protoc-gen-grpc-java-1.69.0.pom, took 18 ms
Download https://repo.maven.apache.org/maven2/io/grpc/protoc-gen-grpc-java/1.69.0/protoc-gen-grpc-java-1.69.0-windows-x86_64.exe, took 78 ms
> Task :generateProto
> Task :compileJava
> Task :processResources
> Task :classes
> Task :resolveMainClassName
> Task :bootJar
> Task :jar
> Task :assemble
> Task :extractIncludeTestProto
> Task :extractTestProto
> Task :generateTestProto NO-SOURCE
> Task :compileTestJava
> Task :processTestResources NO-SOURCE
> Task :testClasses
OpenJDK 64-Bit Server VM warning: Sharing is only supported for boot loader classes because bootstrap classpath has been appended
2025-01-11T19:29:48.526+09:00 INFO 12920 --- [grpc] [ionShutdownHook] o.s.g.s.lifecycle.GrpcServerLifecycle : Completed gRPC server shutdown
> Task :test
> Task :check
> Task :build
BUILD SUCCESSFUL in 10s
12 actionable tasks: 12 executed
Execution finished 'build'.
UserService
gRPC 사용을 위한 준비는 모두 완료되었으니, 실제 사용자 처리를 위한 서비스를 작성한다.
gRPC 구현을 위한 UserService를 생성하고 proto 파일을 컴파일하면 생성되는 UserManagemetGrpc 클래스 파일에 UserManagementImplBase 클래스를 상속받고 createUser, findUsers 메서드를 구현해 준다.
createUser에서 사용자 정보를 입력받아 users 리스트에 추가하고 findUsers에서 현재 저장된 사용자 목록을 반환한다.
@GrpcService
public class UserService extends UserManagementGrpc.UserManagementImplBase {
private final AtomicInteger counter = new AtomicInteger(0);
private List<UserInfo> users = new ArrayList<>();
@Override
public void createUser(User.UserRequest request, StreamObserver<User.UserResponse> responseObserver) {
var userInfo = new UserInfo(this.counter.incrementAndGet(), request.getName(), request.getAge());
this.users.add(userInfo);
responseObserver.onNext(User.UserResponse.newBuilder().setId(userInfo.id()).setName(userInfo.name()).setAge(userInfo.age()).build());
responseObserver.onCompleted();
}
@Override
public void findUsers(User.Empty request, StreamObserver<User.UserResponse> responseObserver) {
users.forEach(u -> responseObserver.onNext(User.UserResponse.newBuilder().setId(u.id()).setName(u.name()).setAge(u.age()).build()));
responseObserver.onCompleted();
}
record UserInfo(int id, String name, int age) {
}
}
Run
벌써 gRPC 구현이 완료되었다. Spring Boot Application을 실행해 본다
기본적으로 9090 port로 서비스가 구동된다. (spring.grpc.server.port 설정으로 변경 가능)
2025-01-11T19:56:02.452+09:00 INFO 11356 --- [grpc] [ main] org.igooo.grpc.GrpcApplication : Starting GrpcApplication using Java 21.0.2 with PID 11356 (C:\Users\igooo\IdeaProjects\grpc\build\classes\java\main started by igooo in C:\Users\igooo\IdeaProjects\grpc)
2025-01-11T19:56:02.453+09:00 INFO 11356 --- [grpc] [ main] org.igooo.grpc.GrpcApplication : No active profile set, falling back to 1 default profile: "default"
2025-01-11T19:56:02.873+09:00 INFO 11356 --- [grpc] [ main] o.s.grpc.server.NettyGrpcServerFactory : Registered gRPC service: org.igooo.grpc.UserManagement
2025-01-11T19:56:02.873+09:00 INFO 11356 --- [grpc] [ main] o.s.grpc.server.NettyGrpcServerFactory : Registered gRPC service: grpc.reflection.v1.ServerReflection
2025-01-11T19:56:02.873+09:00 INFO 11356 --- [grpc] [ main] o.s.grpc.server.NettyGrpcServerFactory : Registered gRPC service: grpc.health.v1.Health
2025-01-11T19:56:02.967+09:00 INFO 11356 --- [grpc] [ main] o.s.g.s.lifecycle.GrpcServerLifecycle : gRPC Server started, listening on address: [/[0:0:0:0:0:0:0:0]:9090]
2025-01-11T19:56:02.970+09:00 INFO 11356 --- [grpc] [ main] org.igooo.grpc.GrpcApplication : Started GrpcApplication in 0.715 seconds (process running for 0.998)
실행한 gRPC를 호출해 본다.(grpc-curl를 사용해도 된다. https://github.com/xoofx/grpc-curl )
### Request: CreateUSer
GRPC localhost:9090/org.igooo.grpc.UserManagement/CreateUser
{
"name": "igooo",
"age": 10
}
### Response: CreateUSer
GRPC localhost:9090/org.igooo.grpc.UserManagement/CreateUser
{
"id": 1,
"name": "igooo",
"age": 10
}
### Response: FindUser
GRPC localhost:9090/org.igooo.grpc.UserManagement/FindUsers
{
"id": 1,
"name": "igooo",
"age": 10
}
{
"id": 2,
"name": "test",
"age": 20
}
intellij를 사용하면 간단하게 gRPC를 호출할 수 있다.
Summary
Spring Initialzr를 사용하여 gRPC 의존성을 추가하는 것으로 바로 gRPC 서비스를 사용할 수 있다. 추가적으로 Actuator를 사용하여 메트릭을 제공할 수도 있고 spring-boot-starter-security를 사용하여 서비스를 보호할 수도 있다.
전체 소스 코드는 GitHub에서 확인할 수 있습니다.
'dev > spring' 카테고리의 다른 글
Spring Boot + Testcontainers 테스트 빠르게 실행하기 (1) | 2025.01.16 |
---|---|
[Spring] Redisson으로 분산락 구현하기(Distrubuted Lock) (1) | 2024.11.21 |
Spring Batch MongoDB 빠르게 수집하기 (MongoCursorItemReader) (4) | 2024.11.08 |
Spring AI를 사용한 AI 어시스턴트 구현 RAG - Part 2 (with OpenAI) (1) | 2024.10.03 |
Spring AI를 사용한 AI 어시스턴트 구현 - Part 1 (with OpenAI) (1) | 2024.10.01 |