Java

gRPC 연동 정리 (Java vs Kotlin vs NestJS)

마시멜로를찾아서 2025. 4. 2. 14:14
반응형

📌 gRPC란?

  • Google이 개발한 고성능, 언어 중립 RPC 프레임워크
  • 데이터 직렬화는 Protocol Buffers(proto) 사용
  • HTTP/2 기반으로 양방향 스트리밍, 성능 우수
  • REST보다 빠르며 마이크로서비스 통신에 적합

🔗 기술별 구성 방식 요약

항목 Java (Spring Boot) Kotlin (Ktor) NestJS (TypeScript)
주요 라이브러리 grpc-spring-boot-starter, protobuf grpc-kotlin, kotlinx-coroutines @grpc/grpc-js, @nestjs/microservices
서버 정의 @GRpcService로 구현 코루틴 기반 suspend 함수 사용 @GrpcMethod 데코레이터 사용
클라이언트 정의 ChannelBuilder + Stub 사용 비동기 Stub 호출 GrpcOptions + ClientGrpcProxy 사용
코드 생성 protoc → Java Stub 생성 protoc-gen-grpc-kotlin 사용 proto-loader, ts-proto, @types 등 사용
특징 성능, 안정성 높음 코루틴과 찰떡궁합 설정은 약간 복잡하지만 개발 속도 빠름

🧪 gRPC 서버-클라이언트 샘플 예제

🟦 1. .proto 파일 (공통)

// greet.proto
syntax = "proto3";

package greet;

service GreeterService {
  rpc SayHello (HelloRequest) returns (HelloResponse);
}

message HelloRequest {
  string name = 1;
}

message HelloResponse {
  string message = 1;
}

☕ Java (Spring Boot)

📌 서버 구현

@GRpcService
public class GreeterServiceImpl extends GreeterServiceGrpc.GreeterServiceImplBase {
    @Override
    public void sayHello(HelloRequest request, StreamObserver<HelloResponse> responseObserver) {
        HelloResponse response = HelloResponse.newBuilder()
                .setMessage("Hello, " + request.getName())
                .build();
        responseObserver.onNext(response);
        responseObserver.onCompleted();
    }
}

📌 클라이언트

ManagedChannel channel = ManagedChannelBuilder.forAddress("localhost", 9090).usePlaintext().build();
GreeterServiceGrpc.GreeterServiceBlockingStub stub = GreeterServiceGrpc.newBlockingStub(channel);

HelloRequest request = HelloRequest.newBuilder().setName("World").build();
HelloResponse response = stub.sayHello(request);
System.out.println(response.getMessage());

🟣 Kotlin (Ktor)

📌 서버

class GreeterServiceImpl : GreeterServiceCoroutineImplBase() {
    override suspend fun sayHello(request: HelloRequest): HelloResponse {
        return HelloResponse.newBuilder()
            .setMessage("Hello, ${request.name}")
            .build()
    }
}

📌 클라이언트

val channel = ManagedChannelBuilder.forAddress("localhost", 9090).usePlaintext().build()
val stub = GreeterServiceCoroutineStub(channel)

val response = stub.sayHello(HelloRequest.newBuilder().setName("Kotlin").build())
println(response.message)

🟨 NestJS (TypeScript)

📌 서버

@GrpcMethod('GreeterService', 'SayHello')
sayHello(data: { name: string }): { message: string } {
  return { message: `Hello, ${data.name}` };
}

📌 클라이언트 설정

ClientsModule.register([
  {
    name: 'GREETER_PACKAGE',
    transport: Transport.GRPC,
    options: {
      package: 'greet',
      protoPath: join(__dirname, './proto/greet.proto'),
    },
  },
])

📌 클라이언트 호출

@Injectable()
export class GreetService {
  constructor(@Inject('GREETER_PACKAGE') private client: ClientGrpc) {}

  private greeterService: any;

  onModuleInit() {
    this.greeterService = this.client.getService('GreeterService');
  }

  async greet(name: string) {
    const res = await lastValueFrom(this.greeterService.SayHello({ name }));
    return res.message;
  }
}

✅ 마무리 요약

항목 Spring Boot Kotlin NestJS 
개발 속도 중간 (JVM 빌드 시간 존재) 빠름 매우 빠름
통신 성능 매우 우수 매우 우수 (코루틴) 우수 (Node.js 한계 있음)
사용 난이도 높은 자유도, 복잡도 있음 DSL 기반 단순화 가능 데코레이터 기반 구성 쉬움
실제 적용 사례 대기업 MSA 환경 다수 적용 실시간 처리, 백엔드 서버에 적합 빠른 MVP, 서버리스 백엔드에 적합
반응형