반응형

자바를 사용한 gRPC 서비스 구현.

src/main/proto

 

디렉터리 생성 -> ProductInfo.proto (서비스 정의 파일) 생성.

 



// productInfo.proto

syntax = "proto3";
import "google/protobuf/wrappers.proto";
package grpc_test_01;

service ProductInfo {
  rpc addProduct(Product) returns (ProductID);
  rpc getProduct(ProductID) returns (Product);
}

message  Product {
  string id = 1;
  string name = 2;
  string description = 3;
  float price = 4;
}

message ProductID {
  string value = 1;
}

 

 

build.gradle 수정



plugins {
    id 'java'
    id 'org.springframework.boot' version '3.2.0'
    id 'io.spring.dependency-management' version '1.1.4'
}

group = 'com.example'
version = '0.0.1-SNAPSHOT'

java {
    sourceCompatibility = '21'
}

repositories {
    mavenCentral()
}

def grpcVersion = '1.56.1'

// 의존성 추가 3번째 grpc부터 추가

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
    implementation 'io.grpc:grpc-netty:${grpcVersion}'
    implementation 'io.grpc:grpc-protobuf:${grpcVersion}'
    implementation 'io.grpc:grpc-stub:${grpcVersion}'
    implementation 'com.google.protobuf:protobuf-javalite:3.22.2'
}

// insert
buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath 'com.google.protobuf:protobuf-gradle-plugin:0.9.2'
    }
}

protobuf {
    protoc {
        artifact = 'com.google.protobuf:protoc:3.9.2'
    }
    plugins {
        grpc {
            artifact = 'io.grpc:protoc-gen-grpc-java:${grpcVersion}'
        }
    }
    generateProtoTasks {
        all()*.plugins {
            grpc {}
        }
    }
}

sourceSets {
    main {
        java {
            srcDirs 'build/generated/source/proto/main/grpc'
            srcDirs 'build/generated/source/proto/main/java'
        }
    }
}

jar {
    manifest {
        attributes "Main-Class": "grpc_test_01.ProductInfoServer"
    }
    from {
        configurations.compile.collect{ it.isDirectory() ? it : zipTree(it)}
    }
}

apply plugin: 'application'
startScripts.enable = false
// insert end

tasks.named('test') {
    useJUnitPlatform()
}
java : 21
Gradle JVM : openjdk 21

 

 

종속성 로드를 했더니

 

오류!
Possible solution:

 - Use Java 20 as Gradle JVM: Open Gradle settings 
 - Open Gradle wrapper settings, change `distributionUrl` property to use compatible Gradle version and reload the project

 

 

오류가 발생했다. gradle jvm 21 버전은 지원을 안 하는 거 같아서 20으로 변경했습니다.

20으로 변경하니 오류가 하나 줄고 다른 문제에 도달했습니다.

 

오류!
startup failed:

  build file '/Users/woonggichu/projects/gRPC/ch02/gRPC_test_01/build.gradle': 32: all buildscript {} blocks must appear before any plugins {} blocks in the script

 

 

buildscript가 plugins 뒤에 있으면 안된다고 해서 가장 앞으로 옮겼습니다.

 

오류!
Could not find method protobuf() for arguments

 

이번에는 protobuf를 찾을수 없다고 해서 찾아보니 build.gradle 처음 부분에 플로그인 적용하는 부분을 안 해준 걸 확인했습니다.

 



// build.gradle 수정

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath 'com.google.protobuf:protobuf-gradle-plugin:0.9.2'
    }
}

plugins {
    id 'java'
    id 'org.springframework.boot' version '3.2.0'
    id 'io.spring.dependency-management' version '1.1.4'
}

group = 'com.example'
version = '0.0.1-SNAPSHOT'

java {
    sourceCompatibility = '21'
}

apply plugin: 'java'
apply plugin: 'com.google.protobuf'

repositories {
    mavenCentral()
}

// 의존성 추가 3번째 grpc부터

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
    implementation 'io.grpc:grpc-netty:1.56.1'
    implementation 'io.grpc:grpc-protobuf:1.56.1'
    implementation 'io.grpc:grpc-stub:1.56.1'
    implementation 'com.google.protobuf:protobuf-javalite:3.22.2'
}

// insert


protobuf {
    protoc {
        artifact = 'com.google.protobuf:protoc:3.9.2'
    }
    plugins {
        grpc {
            artifact = 'io.grpc:protoc-gen-grpc-java:${grpcVersion}'
        }
    }
    generateProtoTasks {
        all()*.plugins {
            grpc {}
        }
    }
}

sourceSets {
    main {
        java {
            srcDirs 'build/generated/source/proto/main/grpc'
            srcDirs 'build/generated/source/proto/main/java'
        }
    }
}

jar {
    manifest {
        attributes "Main-Class": "grpc_test_01.ProductInfoServer"
    }
    from {
        configurations.compile.collect{ it.isDirectory() ? it : zipTree(it)}
    }
}

apply plugin: 'application'
startScripts.enabled = false
// insert end

tasks.named('test') {
    useJUnitPlatform()
}

 

원래 기존에는 

def grpcVersion = '1.56.1'

 

저걸 의존성 추가에 사용했으나 오류가 떠서 지우고 버전을 적어줬습니다.

 

그랬더니 드디어 빌드에 성공했습니다!

 

 

책에서는 gradle init 명령을 사용해서 쉽게 생성이 가능하다고 하니 이것도 한번 시도해볼 생각입니다.

 

오류!
gradle: command not found

에러가 떠서 찾아보니 그래들이 설치가 안되어있다고 나오네요. 그럼 바로 설치!

터미널 혹은 iterm2를 실행 시키고

brew install gradle 

 

조금의 시간이 지나면 열심히 설치하는 모습을 보실 수 있습니다.

 

gradle을 최신 버전으로 업데이트하고 gradle build를 터미널로 실행하니

 

오류!
Could not get unknown property 'compile' for configuration container of type org.gradle.api.internal.artifacts.configurations.DefaultConfigurationContainer.

 

build.gradle에서 



// 변경 전
jar {
    manifest {
        attributes "Main-Class": "grpc_test_01.ProductInfoServer"
    }
    from {
        configurations.compile.collect{ it.isDirectory() ? it : zipTree(it)}
    }
}


// 변경 후 
jar {
    manifest {
        attributes "Main-Class": "grpc_test_01.ProductInfoServer"
    }
    from {
        configurations.implementation.collect{ it.isDirectory() ? it : zipTree(it)}
    }
}

 

compile -> implementation으로 변경했습니다. 

 

오류!
Resolving dependency configuration 'implementation' is not allowed as it is defined as 'canBeResolved=false'. Instead, a resolvable ('canBeResolved=true') dependency configuration that extends 'implementation' should be resolved

 

.. 오류가 대체 몇 개가 발생하는 건지... ㅠㅠ

다시 구글링을 하던 중

 

setCanBeResolved(true)이제 더 이상 사용되지 않으며 Gradle 9.0에서 제거될 예정입니다.

 

라는 문구를 보게 되었습니다.

그럼 다른 방법은 무엇인가..?

// 다시 수정!

jar {
    manifest {
        attributes "Main-Class": "grpc_test_01.ProductInfoServer"
    }
    from {
        configurations.compileClasspath.collect{ it.isDirectory() ? it : zipTree(it)}
    }
}

 

오류!
Entry META-INF/LICENSE.txt is a duplicate but no duplicate handling strategy has been set. Please refer to https://docs.gradle.org/8.5/dsl/org.gradle.api.tasks.Copy.html#org.gradle.api.tasks.Copy:duplicatesStrategy for details.

 

이건 또 무엇인가요...

 

-> 라이브러리끼리 동일한 이름의 파일이 추가되어 중복문제가 발생해 생긴 문제!

 



jar {
    manifest {
        attributes "Main-Class": "grpc_test_01.ProductInfoServer"
    }
    from {
        configurations.compileClasspath.collect{ it.isDirectory() ? it : zipTree(it)}

    }
    
    // 이 구문 추가!
    duplicatesStrategy = DuplicatesStrategy.EXCLUDE
}

 

Build Successful

 

드디어 빌드에 성공했습니다.

일단 어렵게 성공했으므로 이번에는 다른 폴더 명으로 해서 gradle init 명령을 사용해 생성을 해보았습니다.

 

작업폴더에서 
$ mkdir product-info-service // product-info-service 폴더 생성
$ cd product-info-service // product-info-service 폴더로 이동
$ gradle init --type java-application
선택 목록이 나오는데 제가 선택한 목록은
1 : Groovy
1 : JUnit 4
Project name : product-info-service
Source package : ecommerce
Java Version : 21

 

바로 생성이 되었으며, 실제로 타이핑하는 것보다 오류가 발생하지 않았습니다.

발생한 오류는 buildscript가 plugins 뒤에 있으면 안 된다고 하는 것뿐이었습니다.

해결 후 빌드!

물론 build.gradle을 수정하다 보면 이 또한 오류가 발생하지만 확실히 직접 입력하는 것보다 오류의 수가 적었습니다.

직접 만드는 것보다 gradle init으로 생성해서 작업해도 좋을 거 같습니다.

반응형
복사했습니다!