-
[Android] kotlin + gRpc 연결하기Android📱 2024. 4. 23. 21:30
이번에 gRpc를 통한 네트워크 통신을 경험할뻔했는데
요구사항에 맞지 않아 아쉽게 기술 분석만 해보고 끝나서
아까워서 글을 남겨본다
gRpc란?
google에서 개발한 오픈소스 RPC 프레임 워크로
다른 주소 공간에서 함수나 프로시저를 호출할 수 있도록 하는 통신 방식이다.
서비스 규격에 맞추어서 인터페이스를 구현한 서버가 있다면 프로세스 간 통신 방식이니 앱에서도 사용할 수 있다.
Protocol Buffers를 사용하기 때문에 Json보다 성능이 좋고 REST api와는 다르게 HTTP/2를 이용한 양방향 통신이 가능하다.
그래서 양방향 통신을 위해서 grpc를 고려한 거였는데 이번 프로젝트에서 원하는 양방향 통신을 구현하기가 어려워서 결과적으로 웹소켓을 채택하게 되었다.
아래 설정은 kotlin dsl로 세팅한 예제이다.
세팅
일단 프로토콜 버퍼를 설정해준다
libs.versions.toml
protobuf = { id = "com.google.protobuf", version.ref = "protobuf_version" }
프로젝트 수준의 build.gradle.kts
plugins { alias(libs.plugins.androidApplication) apply false alias(libs.plugins.jetbrainsKotlinAndroid) apply false alias(libs.plugins.protobuf) apply false }
그리고 빌드를 한번 해준다.
그러면 builde.kts 파일에서 com.google.protobuf를 불러올 수 있다.
libs.versions.toml
grpc_protobuf_version = "3.21.12" grpc_version = "1.57.0" grpc_kotlin_version = "1.3.0" protobuf_version = "0.9.4" [libraries] grpc-okhttp = { group = "io.grpc", name = "grpc-okhttp", version.ref = "grpc_version" } grpc-stub = { group = "io.grpc", name = "grpc-stub", version.ref = "grpc_version" } grpc-protobuf-lite = { group = "io.grpc", name = "grpc-protobuf-lite", version.ref = "grpc_version" } grpc-kotlin-stub = { group = "io.grpc", name = "grpc-kotlin-stub", version.ref = "grpc_kotlin_version" } protobuf-kotlin-lite = { group = "com.google.protobuf", name = "protobuf-kotlin-lite", version.ref = "grpc_protobuf_version" }
libs에 grpc 추가
app 수준 build.gradle.kts
import com.google.protobuf.gradle.id plugins { ... alias(libs.plugins.protobuf) } android { ... } val grpcProtobufVersion = "3.21.12" val grpcVersion = "1.57.0" val grpcKotlinVersion = "1.3.0" val protobufVersion = "0.8.18" protobuf { protoc { artifact = "com.google.protobuf:protoc:$grpcProtobufVersion" } plugins { id("java") { artifact = "io.grpc:protoc-gen-grpc-java:$grpcVersion" } id("grpc") { artifact = "io.grpc:protoc-gen-grpc-java:$grpcVersion" } id("grpckt") { artifact = "io.grpc:protoc-gen-grpc-kotlin:$grpcKotlinVersion:jdk8@jar" } } generateProtoTasks { all().forEach { generateProtoTask -> generateProtoTask.plugins { id("java") { option("lite") } id("grpc") { option("lite") } id("grpckt") { option("lite") } } generateProtoTask.builtins { id("kotlin") { option("lite") } } } } } dependencies { ... }
protobuf 추가
그리고
main 아래에 proto 디렉터리를 만들고, 안에 각자 정의한 proto파일을 넣어준다.
protoSmaple.proto
syntax = "proto3"; option java_multiple_files = true; option java_package = "파일을 만들 패키지 경로"; option java_outer_classname = "SampleProto"; service SampleService { rpc getClientStream(stream SampleRequest) returns (SampeResponse); } message SampleRequest { string id = 1; } message SampeResponse { string message = 1; }
더 복잡한 함수나 다른 자료형 등이 필요하다면 프로토콜 퍼퍼스 공식 문서에서 확인가능하다 참고
이렇게 하고 빌드를 또 해주면
이렇게 해당 함수와 클래스들이 생성된다.
그리고
companion object { private const val ADDRESS = "URL" } private val _id = MutableSharedFlow<SampleRequest>() val id = _id.asSharedFlow() private var managedChannel: ManagedChannel? = null @Synchronized private fun getManagedChannel(): ManagedChannel? { if (managedChannel == null) { managedChannel = ManagedChannelBuilder .forAddress(ADDRESS, 8080) // .useTransportSecurity() //HTTPS인 경우 사용 .usePlaintext() .build() } return managedChannel } private suspend fun getProfileTest() = coroutineScope { getManagedChannel()?.let { channel -> val stub = SampleServiceGrpcKt.SampleServiceCoroutineStub(channel) val requestMessage = stub.getClientStream(id).message Log.i("TAG", "Test() - message: ${requestMessage}" ) } }
해당 코드를 사용할 곳에서 정의한 함수에 맞게 사용해 주면 된다.
내 샘플의 경우는 stream을 인자로 String을 반환하는 함수라서 flow를 이용하여 데이터를 넣어주고 메시지를 받아오는 구조였다.
각자 레이어에 맞춰서 사용하면 좋을 듯!
'Android📱' 카테고리의 다른 글
[Android] pendingIntent putExtra 및 주의 사항 (0) 2024.09.12 [Android] Sensor를 이용하여 방위각 구해보기~~ (1) 2024.06.04 [Android] BottomSheetBehavior (0) 2023.10.19 안드로이드에서의 Clean Architecture와 Google Recommendation Architecture (1) 2023.10.11 [Android] ConnectivityManager로 네트워크 상태 판단하기 (0) 2023.09.12