From 422786bd6a55a6cc5f6238c14b94f984b37c5d8b Mon Sep 17 00:00:00 2001 From: kangyuri1114 Date: Tue, 31 Dec 2024 18:18:21 +0900 Subject: [PATCH 01/21] =?UTF-8?q?[feat]:=20CustomResultCall=20=ED=81=B4?= =?UTF-8?q?=EB=9E=98=EC=8A=A4=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/network/model/CustomResultCall.kt | 134 ++++++++++++++++++ 1 file changed, 134 insertions(+) create mode 100644 core/network/src/main/java/com/hmh/hamyeonham/core/network/model/CustomResultCall.kt diff --git a/core/network/src/main/java/com/hmh/hamyeonham/core/network/model/CustomResultCall.kt b/core/network/src/main/java/com/hmh/hamyeonham/core/network/model/CustomResultCall.kt new file mode 100644 index 000000000..e02c54d00 --- /dev/null +++ b/core/network/src/main/java/com/hmh/hamyeonham/core/network/model/CustomResultCall.kt @@ -0,0 +1,134 @@ +package com.hmh.hamyeonham.core.network.model + +import okhttp3.Request +import okio.IOException +import okio.Timeout +import retrofit2.Call +import retrofit2.Callback +import retrofit2.HttpException +import retrofit2.Response +import retrofit2.Retrofit +import timber.log.Timber + +class CustomResultCall( + private val call: Call, + private val retrofit: Retrofit, +): Call>{ + + // clone() : 동일 요청 수행하는 새로운 Call 객체 반환 + override fun clone(): Call> { + return CustomResultCall(call.clone(), retrofit) + } + + // execute() : HTTP 요청을 동기적으로 실행. 성공 시 Response> 반환, 실패 시 Exception 발생 + // 주로 테스트 용도 + override fun execute(): Response> { + return Response.success(Result.success(call.execute().body() ?: throw NullPointerException("응답 body가 비었습니다."))) + } + + // isExecuted() : HTTP 요청이 이미 실행되었는지 여부 반환. + // 한 번 이상 실행되면 true, 그렇지 않으면 false 반환 + override fun isExecuted(): Boolean { + return call.isExecuted + } + + // cancel() : 실행 중인 HTTP 요청 취소 + override fun cancel() { + call.cancel() + } + + // isCanceled() : HTTP 요청이 취소되었는지 여부 반환 + override fun isCanceled(): Boolean { + return call.isCanceled + } + + // request() : Call 객체에 대한 HTTP 요청 반환 + override fun request(): Request { + return call.request() + } + + // timeout() : Call 객체에 대한 Timeout 객체 반환 + override fun timeout(): Timeout { + return call.timeout() + } + + // enqueue() : HTTP 요청을 비동기적으로 실행. 요청 결과를 전달받기 위해 Callback>를 인자로 받음 + // enqueue() 메서드를 Custom + override fun enqueue(callback: Callback>) { + // Callback> 객체를 인자로 받아 Call 객체의 enqueue() 메서드 호출 + call.enqueue(object : Callback { + + // onResponse() : HTTP 요청 성공 시 호출 + override fun onResponse(call: Call, response: Response) { + + // response.isSuccessful : HTTP 응답 코드가 200~299 사이인지 여부 반환(성공 여부) + if (response.isSuccessful) { + + // HTTP 요청은 성공했지만 body가 빈 경우 + if(response.body() == null) { + callback.onResponse( + this@CustomResultCall, + Response.success(Result.failure(CustomCallException("응답 body가 비었습니다.", HttpException(response)))) + ) + } + // HTTP 요청 성공 + else { + callback.onResponse( + this@CustomResultCall, + Response.success(response.code(), Result.success(response.body() ?: throw NullPointerException("응답 body가 비었습니다."))) + ) + } + + } else { // HTTP 요청 실패 + + // errorBody가 비어있는 경우 + if(response.errorBody() == null) { + callback.onResponse( this@CustomResultCall, + Response.success(Result.failure(CustomCallException("errorBody가 비었습니다.", HttpException(response)))) + ) + } + // 요청에 실패한 경우 + else { + // errorBody에서 사용자에게 보여줄 메시지 추출 + // errorBody를 BaseResponse 객체로 변환 + val errorBody = retrofit.responseBodyConverter>( + BaseResponse::class.java, + BaseResponse::class.java.annotations + ).convert(response.errorBody() ?: throw NullPointerException("errorBody가 비었습니다.")) + + val message: String = errorBody?.message ?: "errorBody가 비었습니다" + + // CustomCallException 객체 생성 + callback.onResponse(this@CustomResultCall, + Response.success(Result.failure(CustomCallException(message, HttpException(response)))) + ) + + Timber.tag("ResultCall - onResponse").e("${CustomCallException(message, HttpException(response))}") + } + } + } + + // onFailure() : HTTP 요청 실패 시 호출 + override fun onFailure(call: Call, t: Throwable) { + val message = when (t) { + is IOException -> "네트워크 연결이 불안정합니다. 다시 시도해주세요." + is HttpException -> "${t.code()} : 서버 통신 중 문제가 발생했습니다. 다시 시도해주세요." + else -> t.message ?: "알 수 없는 오류가 발생했습니다. 다시 시도해주세요." + } + + // CustomCallException 객체 생성 + callback.onResponse( + this@CustomResultCall, + Response.success(Result.failure(CustomCallException(message, t))) + ) + + Timber.tag("ResultCall - onFailure").e("${CustomCallException(message, t)}") + } + }) + } +} + +class CustomCallException( + override val message: String, + throwable: Throwable +): Exception(message, throwable) \ No newline at end of file From aa12a0b3217ce995290b11bea5604bd4503cde2e Mon Sep 17 00:00:00 2001 From: kangyuri1114 Date: Tue, 31 Dec 2024 18:38:18 +0900 Subject: [PATCH 02/21] =?UTF-8?q?[feat]:=20CustomResultCallAdapterFactory?= =?UTF-8?q?=20=ED=81=B4=EB=9E=98=EC=8A=A4=20=EC=83=9D=EC=84=B1=20=EB=B0=8F?= =?UTF-8?q?=20Retrofit=20=EB=B9=8C=EB=8D=94=EC=97=90=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/network/call/CustomCallException.kt | 6 +++ .../{model => call}/CustomResultCall.kt | 10 ++--- .../call/CustomResultCallAdapterFactory.kt | 39 +++++++++++++++++++ .../hamyeonham/core/network/di/NetModule.kt | 5 +++ 4 files changed, 53 insertions(+), 7 deletions(-) create mode 100644 core/network/src/main/java/com/hmh/hamyeonham/core/network/call/CustomCallException.kt rename core/network/src/main/java/com/hmh/hamyeonham/core/network/{model => call}/CustomResultCall.kt (97%) create mode 100644 core/network/src/main/java/com/hmh/hamyeonham/core/network/call/CustomResultCallAdapterFactory.kt diff --git a/core/network/src/main/java/com/hmh/hamyeonham/core/network/call/CustomCallException.kt b/core/network/src/main/java/com/hmh/hamyeonham/core/network/call/CustomCallException.kt new file mode 100644 index 000000000..36a9e6dea --- /dev/null +++ b/core/network/src/main/java/com/hmh/hamyeonham/core/network/call/CustomCallException.kt @@ -0,0 +1,6 @@ +package com.hmh.hamyeonham.core.network.call + +class CustomCallException( + override val message: String, + throwable: Throwable +): Exception(message, throwable) \ No newline at end of file diff --git a/core/network/src/main/java/com/hmh/hamyeonham/core/network/model/CustomResultCall.kt b/core/network/src/main/java/com/hmh/hamyeonham/core/network/call/CustomResultCall.kt similarity index 97% rename from core/network/src/main/java/com/hmh/hamyeonham/core/network/model/CustomResultCall.kt rename to core/network/src/main/java/com/hmh/hamyeonham/core/network/call/CustomResultCall.kt index e02c54d00..f19bc87fb 100644 --- a/core/network/src/main/java/com/hmh/hamyeonham/core/network/model/CustomResultCall.kt +++ b/core/network/src/main/java/com/hmh/hamyeonham/core/network/call/CustomResultCall.kt @@ -1,5 +1,6 @@ -package com.hmh.hamyeonham.core.network.model +package com.hmh.hamyeonham.core.network.call +import com.hmh.hamyeonham.core.network.model.BaseResponse import okhttp3.Request import okio.IOException import okio.Timeout @@ -126,9 +127,4 @@ class CustomResultCall( } }) } -} - -class CustomCallException( - override val message: String, - throwable: Throwable -): Exception(message, throwable) \ No newline at end of file +} \ No newline at end of file diff --git a/core/network/src/main/java/com/hmh/hamyeonham/core/network/call/CustomResultCallAdapterFactory.kt b/core/network/src/main/java/com/hmh/hamyeonham/core/network/call/CustomResultCallAdapterFactory.kt new file mode 100644 index 000000000..48112549d --- /dev/null +++ b/core/network/src/main/java/com/hmh/hamyeonham/core/network/call/CustomResultCallAdapterFactory.kt @@ -0,0 +1,39 @@ +package com.hmh.hamyeonham.core.network.call + +import retrofit2.Call +import retrofit2.CallAdapter +import retrofit2.Retrofit +import java.lang.reflect.ParameterizedType +import java.lang.reflect.Type + +// CallAdapter 객체 생성을 위한 Factory 클래스 +class CustomResultCallAdapterFactory: CallAdapter.Factory() { + + // retrofit 호출 결과를 변환하기 위해 호출 + override fun get( + returnType: Type, + annotations: Array, + retrofit: Retrofit + ): CallAdapter<*, *>? { + // 변환 타입 검증 (기본 Type이 Call인지, 제네릭 타입인지) + if (getRawType(returnType) != Call::class.java || returnType !is ParameterizedType) { + return null + } + + // Retrofit의 반환 타입이 Call>인지 확인 + val upperBound = getParameterUpperBound(0, returnType) + + return if (upperBound is ParameterizedType && upperBound.rawType == Result::class.java) { + object : CallAdapter>> { + override fun responseType(): Type = getParameterUpperBound(0, upperBound) + + // 기존 Call 객체를 CustomResultCall 객체로 변환 + override fun adapt(call: Call): Call> = + CustomResultCall(call, retrofit) as Call> + } + } else { + // 반환 객체가 Call>이 아닌 경우 null 반환 + null + } + } +} \ No newline at end of file diff --git a/core/network/src/main/java/com/hmh/hamyeonham/core/network/di/NetModule.kt b/core/network/src/main/java/com/hmh/hamyeonham/core/network/di/NetModule.kt index f19770a57..c118ba2f5 100644 --- a/core/network/src/main/java/com/hmh/hamyeonham/core/network/di/NetModule.kt +++ b/core/network/src/main/java/com/hmh/hamyeonham/core/network/di/NetModule.kt @@ -7,6 +7,7 @@ import com.hmh.hamyeonham.common.qualifier.Secured import com.hmh.hamyeonham.common.qualifier.Unsecured import com.hmh.hamyeonham.core.network.auth.authenticator.HMHAuthenticator import com.hmh.hamyeonham.core.network.auth.interceptor.HeaderInterceptor +import com.hmh.hamyeonham.core.network.call.CustomResultCallAdapterFactory import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory import dagger.Binds import dagger.Module @@ -93,10 +94,12 @@ object NetModule { fun provideRetrofit( @Secured client: OkHttpClient, converterFactory: Converter.Factory, + resultCallAdapterFactory: CustomResultCallAdapterFactory, ): Retrofit = Retrofit.Builder() .baseUrl(HMHBaseUrl) .client(client) .addConverterFactory(converterFactory) + .addCallAdapterFactory(resultCallAdapterFactory) .build() @Singleton @@ -105,10 +108,12 @@ object NetModule { fun provideRetrofitNotNeededAuth( @Unsecured client: OkHttpClient, converterFactory: Converter.Factory, + resultCallAdapterFactory: CustomResultCallAdapterFactory, ): Retrofit = Retrofit.Builder() .baseUrl(HMHBaseUrl) .client(client) .addConverterFactory(converterFactory) + .addCallAdapterFactory(resultCallAdapterFactory) .build() @Module From 13264b365cc3e77dca0554a372397920fb7b7041 Mon Sep 17 00:00:00 2001 From: kangyuri1114 Date: Tue, 31 Dec 2024 18:58:09 +0900 Subject: [PATCH 03/21] =?UTF-8?q?[feat]:=20CustomResultCallAdapterFactory?= =?UTF-8?q?=20=EC=A3=BC=EC=9E=85=EC=9D=84=20=EC=9C=84=ED=95=9C=20@Inject?= =?UTF-8?q?=20=EC=83=9D=EC=84=B1=EC=9E=90=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/network/call/CustomResultCallAdapterFactory.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core/network/src/main/java/com/hmh/hamyeonham/core/network/call/CustomResultCallAdapterFactory.kt b/core/network/src/main/java/com/hmh/hamyeonham/core/network/call/CustomResultCallAdapterFactory.kt index 48112549d..07a2708f8 100644 --- a/core/network/src/main/java/com/hmh/hamyeonham/core/network/call/CustomResultCallAdapterFactory.kt +++ b/core/network/src/main/java/com/hmh/hamyeonham/core/network/call/CustomResultCallAdapterFactory.kt @@ -5,9 +5,10 @@ import retrofit2.CallAdapter import retrofit2.Retrofit import java.lang.reflect.ParameterizedType import java.lang.reflect.Type +import javax.inject.Inject // CallAdapter 객체 생성을 위한 Factory 클래스 -class CustomResultCallAdapterFactory: CallAdapter.Factory() { +class CustomResultCallAdapterFactory @Inject constructor(): CallAdapter.Factory() { // retrofit 호출 결과를 변환하기 위해 호출 override fun get( From 86f4255a9e9eb996d40db87b30cfead0aa2f08f0 Mon Sep 17 00:00:00 2001 From: kangyuri1114 Date: Tue, 31 Dec 2024 18:18:21 +0900 Subject: [PATCH 04/21] =?UTF-8?q?[feat]:=20CustomResultCall=20=ED=81=B4?= =?UTF-8?q?=EB=9E=98=EC=8A=A4=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/network/model/CustomResultCall.kt | 134 ++++++++++++++++++ 1 file changed, 134 insertions(+) create mode 100644 core/network/src/main/java/com/hmh/hamyeonham/core/network/model/CustomResultCall.kt diff --git a/core/network/src/main/java/com/hmh/hamyeonham/core/network/model/CustomResultCall.kt b/core/network/src/main/java/com/hmh/hamyeonham/core/network/model/CustomResultCall.kt new file mode 100644 index 000000000..e02c54d00 --- /dev/null +++ b/core/network/src/main/java/com/hmh/hamyeonham/core/network/model/CustomResultCall.kt @@ -0,0 +1,134 @@ +package com.hmh.hamyeonham.core.network.model + +import okhttp3.Request +import okio.IOException +import okio.Timeout +import retrofit2.Call +import retrofit2.Callback +import retrofit2.HttpException +import retrofit2.Response +import retrofit2.Retrofit +import timber.log.Timber + +class CustomResultCall( + private val call: Call, + private val retrofit: Retrofit, +): Call>{ + + // clone() : 동일 요청 수행하는 새로운 Call 객체 반환 + override fun clone(): Call> { + return CustomResultCall(call.clone(), retrofit) + } + + // execute() : HTTP 요청을 동기적으로 실행. 성공 시 Response> 반환, 실패 시 Exception 발생 + // 주로 테스트 용도 + override fun execute(): Response> { + return Response.success(Result.success(call.execute().body() ?: throw NullPointerException("응답 body가 비었습니다."))) + } + + // isExecuted() : HTTP 요청이 이미 실행되었는지 여부 반환. + // 한 번 이상 실행되면 true, 그렇지 않으면 false 반환 + override fun isExecuted(): Boolean { + return call.isExecuted + } + + // cancel() : 실행 중인 HTTP 요청 취소 + override fun cancel() { + call.cancel() + } + + // isCanceled() : HTTP 요청이 취소되었는지 여부 반환 + override fun isCanceled(): Boolean { + return call.isCanceled + } + + // request() : Call 객체에 대한 HTTP 요청 반환 + override fun request(): Request { + return call.request() + } + + // timeout() : Call 객체에 대한 Timeout 객체 반환 + override fun timeout(): Timeout { + return call.timeout() + } + + // enqueue() : HTTP 요청을 비동기적으로 실행. 요청 결과를 전달받기 위해 Callback>를 인자로 받음 + // enqueue() 메서드를 Custom + override fun enqueue(callback: Callback>) { + // Callback> 객체를 인자로 받아 Call 객체의 enqueue() 메서드 호출 + call.enqueue(object : Callback { + + // onResponse() : HTTP 요청 성공 시 호출 + override fun onResponse(call: Call, response: Response) { + + // response.isSuccessful : HTTP 응답 코드가 200~299 사이인지 여부 반환(성공 여부) + if (response.isSuccessful) { + + // HTTP 요청은 성공했지만 body가 빈 경우 + if(response.body() == null) { + callback.onResponse( + this@CustomResultCall, + Response.success(Result.failure(CustomCallException("응답 body가 비었습니다.", HttpException(response)))) + ) + } + // HTTP 요청 성공 + else { + callback.onResponse( + this@CustomResultCall, + Response.success(response.code(), Result.success(response.body() ?: throw NullPointerException("응답 body가 비었습니다."))) + ) + } + + } else { // HTTP 요청 실패 + + // errorBody가 비어있는 경우 + if(response.errorBody() == null) { + callback.onResponse( this@CustomResultCall, + Response.success(Result.failure(CustomCallException("errorBody가 비었습니다.", HttpException(response)))) + ) + } + // 요청에 실패한 경우 + else { + // errorBody에서 사용자에게 보여줄 메시지 추출 + // errorBody를 BaseResponse 객체로 변환 + val errorBody = retrofit.responseBodyConverter>( + BaseResponse::class.java, + BaseResponse::class.java.annotations + ).convert(response.errorBody() ?: throw NullPointerException("errorBody가 비었습니다.")) + + val message: String = errorBody?.message ?: "errorBody가 비었습니다" + + // CustomCallException 객체 생성 + callback.onResponse(this@CustomResultCall, + Response.success(Result.failure(CustomCallException(message, HttpException(response)))) + ) + + Timber.tag("ResultCall - onResponse").e("${CustomCallException(message, HttpException(response))}") + } + } + } + + // onFailure() : HTTP 요청 실패 시 호출 + override fun onFailure(call: Call, t: Throwable) { + val message = when (t) { + is IOException -> "네트워크 연결이 불안정합니다. 다시 시도해주세요." + is HttpException -> "${t.code()} : 서버 통신 중 문제가 발생했습니다. 다시 시도해주세요." + else -> t.message ?: "알 수 없는 오류가 발생했습니다. 다시 시도해주세요." + } + + // CustomCallException 객체 생성 + callback.onResponse( + this@CustomResultCall, + Response.success(Result.failure(CustomCallException(message, t))) + ) + + Timber.tag("ResultCall - onFailure").e("${CustomCallException(message, t)}") + } + }) + } +} + +class CustomCallException( + override val message: String, + throwable: Throwable +): Exception(message, throwable) \ No newline at end of file From 42871a5ac35895fae0a96a2d40768a6830aca9e7 Mon Sep 17 00:00:00 2001 From: kangyuri1114 Date: Tue, 31 Dec 2024 18:38:18 +0900 Subject: [PATCH 05/21] =?UTF-8?q?[feat]:=20CustomResultCallAdapterFactory?= =?UTF-8?q?=20=ED=81=B4=EB=9E=98=EC=8A=A4=20=EC=83=9D=EC=84=B1=20=EB=B0=8F?= =?UTF-8?q?=20Retrofit=20=EB=B9=8C=EB=8D=94=EC=97=90=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/network/call/CustomCallException.kt | 6 +++ .../{model => call}/CustomResultCall.kt | 10 ++--- .../call/CustomResultCallAdapterFactory.kt | 39 +++++++++++++++++++ .../hamyeonham/core/network/di/NetModule.kt | 5 +++ 4 files changed, 53 insertions(+), 7 deletions(-) create mode 100644 core/network/src/main/java/com/hmh/hamyeonham/core/network/call/CustomCallException.kt rename core/network/src/main/java/com/hmh/hamyeonham/core/network/{model => call}/CustomResultCall.kt (97%) create mode 100644 core/network/src/main/java/com/hmh/hamyeonham/core/network/call/CustomResultCallAdapterFactory.kt diff --git a/core/network/src/main/java/com/hmh/hamyeonham/core/network/call/CustomCallException.kt b/core/network/src/main/java/com/hmh/hamyeonham/core/network/call/CustomCallException.kt new file mode 100644 index 000000000..36a9e6dea --- /dev/null +++ b/core/network/src/main/java/com/hmh/hamyeonham/core/network/call/CustomCallException.kt @@ -0,0 +1,6 @@ +package com.hmh.hamyeonham.core.network.call + +class CustomCallException( + override val message: String, + throwable: Throwable +): Exception(message, throwable) \ No newline at end of file diff --git a/core/network/src/main/java/com/hmh/hamyeonham/core/network/model/CustomResultCall.kt b/core/network/src/main/java/com/hmh/hamyeonham/core/network/call/CustomResultCall.kt similarity index 97% rename from core/network/src/main/java/com/hmh/hamyeonham/core/network/model/CustomResultCall.kt rename to core/network/src/main/java/com/hmh/hamyeonham/core/network/call/CustomResultCall.kt index e02c54d00..f19bc87fb 100644 --- a/core/network/src/main/java/com/hmh/hamyeonham/core/network/model/CustomResultCall.kt +++ b/core/network/src/main/java/com/hmh/hamyeonham/core/network/call/CustomResultCall.kt @@ -1,5 +1,6 @@ -package com.hmh.hamyeonham.core.network.model +package com.hmh.hamyeonham.core.network.call +import com.hmh.hamyeonham.core.network.model.BaseResponse import okhttp3.Request import okio.IOException import okio.Timeout @@ -126,9 +127,4 @@ class CustomResultCall( } }) } -} - -class CustomCallException( - override val message: String, - throwable: Throwable -): Exception(message, throwable) \ No newline at end of file +} \ No newline at end of file diff --git a/core/network/src/main/java/com/hmh/hamyeonham/core/network/call/CustomResultCallAdapterFactory.kt b/core/network/src/main/java/com/hmh/hamyeonham/core/network/call/CustomResultCallAdapterFactory.kt new file mode 100644 index 000000000..48112549d --- /dev/null +++ b/core/network/src/main/java/com/hmh/hamyeonham/core/network/call/CustomResultCallAdapterFactory.kt @@ -0,0 +1,39 @@ +package com.hmh.hamyeonham.core.network.call + +import retrofit2.Call +import retrofit2.CallAdapter +import retrofit2.Retrofit +import java.lang.reflect.ParameterizedType +import java.lang.reflect.Type + +// CallAdapter 객체 생성을 위한 Factory 클래스 +class CustomResultCallAdapterFactory: CallAdapter.Factory() { + + // retrofit 호출 결과를 변환하기 위해 호출 + override fun get( + returnType: Type, + annotations: Array, + retrofit: Retrofit + ): CallAdapter<*, *>? { + // 변환 타입 검증 (기본 Type이 Call인지, 제네릭 타입인지) + if (getRawType(returnType) != Call::class.java || returnType !is ParameterizedType) { + return null + } + + // Retrofit의 반환 타입이 Call>인지 확인 + val upperBound = getParameterUpperBound(0, returnType) + + return if (upperBound is ParameterizedType && upperBound.rawType == Result::class.java) { + object : CallAdapter>> { + override fun responseType(): Type = getParameterUpperBound(0, upperBound) + + // 기존 Call 객체를 CustomResultCall 객체로 변환 + override fun adapt(call: Call): Call> = + CustomResultCall(call, retrofit) as Call> + } + } else { + // 반환 객체가 Call>이 아닌 경우 null 반환 + null + } + } +} \ No newline at end of file diff --git a/core/network/src/main/java/com/hmh/hamyeonham/core/network/di/NetModule.kt b/core/network/src/main/java/com/hmh/hamyeonham/core/network/di/NetModule.kt index f19770a57..c118ba2f5 100644 --- a/core/network/src/main/java/com/hmh/hamyeonham/core/network/di/NetModule.kt +++ b/core/network/src/main/java/com/hmh/hamyeonham/core/network/di/NetModule.kt @@ -7,6 +7,7 @@ import com.hmh.hamyeonham.common.qualifier.Secured import com.hmh.hamyeonham.common.qualifier.Unsecured import com.hmh.hamyeonham.core.network.auth.authenticator.HMHAuthenticator import com.hmh.hamyeonham.core.network.auth.interceptor.HeaderInterceptor +import com.hmh.hamyeonham.core.network.call.CustomResultCallAdapterFactory import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory import dagger.Binds import dagger.Module @@ -93,10 +94,12 @@ object NetModule { fun provideRetrofit( @Secured client: OkHttpClient, converterFactory: Converter.Factory, + resultCallAdapterFactory: CustomResultCallAdapterFactory, ): Retrofit = Retrofit.Builder() .baseUrl(HMHBaseUrl) .client(client) .addConverterFactory(converterFactory) + .addCallAdapterFactory(resultCallAdapterFactory) .build() @Singleton @@ -105,10 +108,12 @@ object NetModule { fun provideRetrofitNotNeededAuth( @Unsecured client: OkHttpClient, converterFactory: Converter.Factory, + resultCallAdapterFactory: CustomResultCallAdapterFactory, ): Retrofit = Retrofit.Builder() .baseUrl(HMHBaseUrl) .client(client) .addConverterFactory(converterFactory) + .addCallAdapterFactory(resultCallAdapterFactory) .build() @Module From ef257e3524726ffc706f581a29bd0543133a038a Mon Sep 17 00:00:00 2001 From: kangyuri1114 Date: Tue, 31 Dec 2024 18:58:09 +0900 Subject: [PATCH 06/21] =?UTF-8?q?[feat]:=20CustomResultCallAdapterFactory?= =?UTF-8?q?=20=EC=A3=BC=EC=9E=85=EC=9D=84=20=EC=9C=84=ED=95=9C=20@Inject?= =?UTF-8?q?=20=EC=83=9D=EC=84=B1=EC=9E=90=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/network/call/CustomResultCallAdapterFactory.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core/network/src/main/java/com/hmh/hamyeonham/core/network/call/CustomResultCallAdapterFactory.kt b/core/network/src/main/java/com/hmh/hamyeonham/core/network/call/CustomResultCallAdapterFactory.kt index 48112549d..07a2708f8 100644 --- a/core/network/src/main/java/com/hmh/hamyeonham/core/network/call/CustomResultCallAdapterFactory.kt +++ b/core/network/src/main/java/com/hmh/hamyeonham/core/network/call/CustomResultCallAdapterFactory.kt @@ -5,9 +5,10 @@ import retrofit2.CallAdapter import retrofit2.Retrofit import java.lang.reflect.ParameterizedType import java.lang.reflect.Type +import javax.inject.Inject // CallAdapter 객체 생성을 위한 Factory 클래스 -class CustomResultCallAdapterFactory: CallAdapter.Factory() { +class CustomResultCallAdapterFactory @Inject constructor(): CallAdapter.Factory() { // retrofit 호출 결과를 변환하기 위해 호출 override fun get( From 24b176b0b98c8f5fb0ee34f5c4215ca078317826 Mon Sep 17 00:00:00 2001 From: kangyuri1114 Date: Fri, 3 Jan 2025 01:24:29 +0900 Subject: [PATCH 07/21] =?UTF-8?q?[refact]:=20=EB=A9=94=EC=84=9C=EB=93=9C?= =?UTF-8?q?=20=EC=88=9C=EC=84=9C,=20=ED=81=B4=EB=9E=98=EC=8A=A4=EB=AA=85?= =?UTF-8?q?=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...CustomCallException.kt => ApiException.kt} | 2 +- .../call/CustomResultCallAdapterFactory.kt | 4 +- .../{CustomResultCall.kt => ResultCall.kt} | 103 +++++++++--------- 3 files changed, 55 insertions(+), 54 deletions(-) rename core/network/src/main/java/com/hmh/hamyeonham/core/network/call/{CustomCallException.kt => ApiException.kt} (83%) rename core/network/src/main/java/com/hmh/hamyeonham/core/network/call/{CustomResultCall.kt => ResultCall.kt} (80%) diff --git a/core/network/src/main/java/com/hmh/hamyeonham/core/network/call/CustomCallException.kt b/core/network/src/main/java/com/hmh/hamyeonham/core/network/call/ApiException.kt similarity index 83% rename from core/network/src/main/java/com/hmh/hamyeonham/core/network/call/CustomCallException.kt rename to core/network/src/main/java/com/hmh/hamyeonham/core/network/call/ApiException.kt index 36a9e6dea..8eb746e6d 100644 --- a/core/network/src/main/java/com/hmh/hamyeonham/core/network/call/CustomCallException.kt +++ b/core/network/src/main/java/com/hmh/hamyeonham/core/network/call/ApiException.kt @@ -1,6 +1,6 @@ package com.hmh.hamyeonham.core.network.call -class CustomCallException( +class ApiException( override val message: String, throwable: Throwable ): Exception(message, throwable) \ No newline at end of file diff --git a/core/network/src/main/java/com/hmh/hamyeonham/core/network/call/CustomResultCallAdapterFactory.kt b/core/network/src/main/java/com/hmh/hamyeonham/core/network/call/CustomResultCallAdapterFactory.kt index 07a2708f8..50995f707 100644 --- a/core/network/src/main/java/com/hmh/hamyeonham/core/network/call/CustomResultCallAdapterFactory.kt +++ b/core/network/src/main/java/com/hmh/hamyeonham/core/network/call/CustomResultCallAdapterFactory.kt @@ -28,9 +28,9 @@ class CustomResultCallAdapterFactory @Inject constructor(): CallAdapter.Factory( object : CallAdapter>> { override fun responseType(): Type = getParameterUpperBound(0, upperBound) - // 기존 Call 객체를 CustomResultCall 객체로 변환 + // 기존 Call 객체를 ResultCall 객체로 변환 override fun adapt(call: Call): Call> = - CustomResultCall(call, retrofit) as Call> + ResultCall(call, retrofit) as Call> } } else { // 반환 객체가 Call>이 아닌 경우 null 반환 diff --git a/core/network/src/main/java/com/hmh/hamyeonham/core/network/call/CustomResultCall.kt b/core/network/src/main/java/com/hmh/hamyeonham/core/network/call/ResultCall.kt similarity index 80% rename from core/network/src/main/java/com/hmh/hamyeonham/core/network/call/CustomResultCall.kt rename to core/network/src/main/java/com/hmh/hamyeonham/core/network/call/ResultCall.kt index f19bc87fb..fe2b68a10 100644 --- a/core/network/src/main/java/com/hmh/hamyeonham/core/network/call/CustomResultCall.kt +++ b/core/network/src/main/java/com/hmh/hamyeonham/core/network/call/ResultCall.kt @@ -11,51 +11,15 @@ import retrofit2.Response import retrofit2.Retrofit import timber.log.Timber -class CustomResultCall( +class ResultCall( private val call: Call, private val retrofit: Retrofit, ): Call>{ - // clone() : 동일 요청 수행하는 새로운 Call 객체 반환 - override fun clone(): Call> { - return CustomResultCall(call.clone(), retrofit) - } - - // execute() : HTTP 요청을 동기적으로 실행. 성공 시 Response> 반환, 실패 시 Exception 발생 - // 주로 테스트 용도 - override fun execute(): Response> { - return Response.success(Result.success(call.execute().body() ?: throw NullPointerException("응답 body가 비었습니다."))) - } - - // isExecuted() : HTTP 요청이 이미 실행되었는지 여부 반환. - // 한 번 이상 실행되면 true, 그렇지 않으면 false 반환 - override fun isExecuted(): Boolean { - return call.isExecuted - } - - // cancel() : 실행 중인 HTTP 요청 취소 - override fun cancel() { - call.cancel() - } - - // isCanceled() : HTTP 요청이 취소되었는지 여부 반환 - override fun isCanceled(): Boolean { - return call.isCanceled - } - - // request() : Call 객체에 대한 HTTP 요청 반환 - override fun request(): Request { - return call.request() - } - - // timeout() : Call 객체에 대한 Timeout 객체 반환 - override fun timeout(): Timeout { - return call.timeout() - } - // enqueue() : HTTP 요청을 비동기적으로 실행. 요청 결과를 전달받기 위해 Callback>를 인자로 받음 // enqueue() 메서드를 Custom override fun enqueue(callback: Callback>) { + // Callback> 객체를 인자로 받아 Call 객체의 enqueue() 메서드 호출 call.enqueue(object : Callback { @@ -68,14 +32,14 @@ class CustomResultCall( // HTTP 요청은 성공했지만 body가 빈 경우 if(response.body() == null) { callback.onResponse( - this@CustomResultCall, - Response.success(Result.failure(CustomCallException("응답 body가 비었습니다.", HttpException(response)))) + this@ResultCall, + Response.success(Result.failure(ApiException("응답 body가 비었습니다.", HttpException(response)))) ) } // HTTP 요청 성공 else { callback.onResponse( - this@CustomResultCall, + this@ResultCall, Response.success(response.code(), Result.success(response.body() ?: throw NullPointerException("응답 body가 비었습니다."))) ) } @@ -84,8 +48,8 @@ class CustomResultCall( // errorBody가 비어있는 경우 if(response.errorBody() == null) { - callback.onResponse( this@CustomResultCall, - Response.success(Result.failure(CustomCallException("errorBody가 비었습니다.", HttpException(response)))) + callback.onResponse( this@ResultCall, + Response.success(Result.failure(ApiException("errorBody가 비었습니다.", HttpException(response)))) ) } // 요청에 실패한 경우 @@ -99,12 +63,12 @@ class CustomResultCall( val message: String = errorBody?.message ?: "errorBody가 비었습니다" - // CustomCallException 객체 생성 - callback.onResponse(this@CustomResultCall, - Response.success(Result.failure(CustomCallException(message, HttpException(response)))) + // ApiException 객체 생성 + callback.onResponse(this@ResultCall, + Response.success(Result.failure(ApiException(message, HttpException(response)))) ) - Timber.tag("ResultCall - onResponse").e("${CustomCallException(message, HttpException(response))}") + Timber.tag("ResultCall - onResponse").e("${ApiException(message, HttpException(response))}") } } } @@ -117,14 +81,51 @@ class CustomResultCall( else -> t.message ?: "알 수 없는 오류가 발생했습니다. 다시 시도해주세요." } - // CustomCallException 객체 생성 + // ApiException 객체 생성 callback.onResponse( - this@CustomResultCall, - Response.success(Result.failure(CustomCallException(message, t))) + this@ResultCall, + Response.success(Result.failure(ApiException(message, t))) ) - Timber.tag("ResultCall - onFailure").e("${CustomCallException(message, t)}") + Timber.tag("ResultCall - onFailure").e("${ApiException(message, t)}") } }) } + + // clone() : 동일 요청 수행하는 새로운 Call 객체 반환 + override fun clone(): Call> { + return ResultCall(call.clone(), retrofit) + } + + // execute() : HTTP 요청을 동기적으로 실행. 성공 시 Response> 반환, 실패 시 Exception 발생 + // 주로 테스트 용도 + override fun execute(): Response> { + return Response.success(Result.success(call.execute().body() ?: throw NullPointerException("응답 body가 비었습니다."))) + } + + // isExecuted() : HTTP 요청이 이미 실행되었는지 여부 반환. + // 한 번 이상 실행되면 true, 그렇지 않으면 false 반환 + override fun isExecuted(): Boolean { + return call.isExecuted + } + + // cancel() : 실행 중인 HTTP 요청 취소 + override fun cancel() { + call.cancel() + } + + // isCanceled() : HTTP 요청이 취소되었는지 여부 반환 + override fun isCanceled(): Boolean { + return call.isCanceled + } + + // request() : Call 객체에 대한 HTTP 요청 반환 + override fun request(): Request { + return call.request() + } + + // timeout() : Call 객체에 대한 Timeout 객체 반환 + override fun timeout(): Timeout { + return call.timeout() + } } \ No newline at end of file From d53d8e8703996e9eb6234f4a4d08bccdc9533670 Mon Sep 17 00:00:00 2001 From: kangyuri1114 Date: Fri, 3 Jan 2025 01:26:24 +0900 Subject: [PATCH 08/21] =?UTF-8?q?[refact]:=20=ED=81=B4=EB=9E=98=EC=8A=A4?= =?UTF-8?q?=EB=AA=85=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...mResultCallAdapterFactory.kt => ResultCallAdapterFactory.kt} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename core/network/src/main/java/com/hmh/hamyeonham/core/network/call/{CustomResultCallAdapterFactory.kt => ResultCallAdapterFactory.kt} (94%) diff --git a/core/network/src/main/java/com/hmh/hamyeonham/core/network/call/CustomResultCallAdapterFactory.kt b/core/network/src/main/java/com/hmh/hamyeonham/core/network/call/ResultCallAdapterFactory.kt similarity index 94% rename from core/network/src/main/java/com/hmh/hamyeonham/core/network/call/CustomResultCallAdapterFactory.kt rename to core/network/src/main/java/com/hmh/hamyeonham/core/network/call/ResultCallAdapterFactory.kt index 50995f707..a34a9fff8 100644 --- a/core/network/src/main/java/com/hmh/hamyeonham/core/network/call/CustomResultCallAdapterFactory.kt +++ b/core/network/src/main/java/com/hmh/hamyeonham/core/network/call/ResultCallAdapterFactory.kt @@ -8,7 +8,7 @@ import java.lang.reflect.Type import javax.inject.Inject // CallAdapter 객체 생성을 위한 Factory 클래스 -class CustomResultCallAdapterFactory @Inject constructor(): CallAdapter.Factory() { +class ResultCallAdapterFactory @Inject constructor(): CallAdapter.Factory() { // retrofit 호출 결과를 변환하기 위해 호출 override fun get( From 2bae9fe86f924c8d4c6eee1505ab777641d8154a Mon Sep 17 00:00:00 2001 From: kangyuri1114 Date: Fri, 3 Jan 2025 01:47:35 +0900 Subject: [PATCH 09/21] =?UTF-8?q?[add]:=20ErrorResponse=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../hmh/hamyeonham/core/network/call/ResultCall.kt | 8 ++++---- .../hamyeonham/core/network/model/ErrorResponse.kt | 12 ++++++++++++ 2 files changed, 16 insertions(+), 4 deletions(-) create mode 100644 core/network/src/main/java/com/hmh/hamyeonham/core/network/model/ErrorResponse.kt diff --git a/core/network/src/main/java/com/hmh/hamyeonham/core/network/call/ResultCall.kt b/core/network/src/main/java/com/hmh/hamyeonham/core/network/call/ResultCall.kt index fe2b68a10..7c8d01d99 100644 --- a/core/network/src/main/java/com/hmh/hamyeonham/core/network/call/ResultCall.kt +++ b/core/network/src/main/java/com/hmh/hamyeonham/core/network/call/ResultCall.kt @@ -1,6 +1,6 @@ package com.hmh.hamyeonham.core.network.call -import com.hmh.hamyeonham.core.network.model.BaseResponse +import com.hmh.hamyeonham.core.network.model.ErrorResponse import okhttp3.Request import okio.IOException import okio.Timeout @@ -56,9 +56,9 @@ class ResultCall( else { // errorBody에서 사용자에게 보여줄 메시지 추출 // errorBody를 BaseResponse 객체로 변환 - val errorBody = retrofit.responseBodyConverter>( - BaseResponse::class.java, - BaseResponse::class.java.annotations + val errorBody = retrofit.responseBodyConverter>( + ErrorResponse::class.java, + ErrorResponse::class.java.annotations ).convert(response.errorBody() ?: throw NullPointerException("errorBody가 비었습니다.")) val message: String = errorBody?.message ?: "errorBody가 비었습니다" diff --git a/core/network/src/main/java/com/hmh/hamyeonham/core/network/model/ErrorResponse.kt b/core/network/src/main/java/com/hmh/hamyeonham/core/network/model/ErrorResponse.kt new file mode 100644 index 000000000..5320c4ff3 --- /dev/null +++ b/core/network/src/main/java/com/hmh/hamyeonham/core/network/model/ErrorResponse.kt @@ -0,0 +1,12 @@ +package com.hmh.hamyeonham.core.network.model + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +data class ErrorResponse( + @SerialName("status") + val status: Int, + @SerialName("message") + val message: String, +) From bd9792620651a1fbd0925afc2afe057ac56217ed Mon Sep 17 00:00:00 2001 From: kangyuri1114 Date: Fri, 3 Jan 2025 01:48:30 +0900 Subject: [PATCH 10/21] =?UTF-8?q?[add]:=20ErrorResponse=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/hmh/hamyeonham/core/network/call/ResultCall.kt | 2 +- .../java/com/hmh/hamyeonham/core/network/model/ErrorResponse.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/core/network/src/main/java/com/hmh/hamyeonham/core/network/call/ResultCall.kt b/core/network/src/main/java/com/hmh/hamyeonham/core/network/call/ResultCall.kt index 7c8d01d99..c21f7e3ea 100644 --- a/core/network/src/main/java/com/hmh/hamyeonham/core/network/call/ResultCall.kt +++ b/core/network/src/main/java/com/hmh/hamyeonham/core/network/call/ResultCall.kt @@ -56,7 +56,7 @@ class ResultCall( else { // errorBody에서 사용자에게 보여줄 메시지 추출 // errorBody를 BaseResponse 객체로 변환 - val errorBody = retrofit.responseBodyConverter>( + val errorBody = retrofit.responseBodyConverter( ErrorResponse::class.java, ErrorResponse::class.java.annotations ).convert(response.errorBody() ?: throw NullPointerException("errorBody가 비었습니다.")) diff --git a/core/network/src/main/java/com/hmh/hamyeonham/core/network/model/ErrorResponse.kt b/core/network/src/main/java/com/hmh/hamyeonham/core/network/model/ErrorResponse.kt index 5320c4ff3..4ef4ea769 100644 --- a/core/network/src/main/java/com/hmh/hamyeonham/core/network/model/ErrorResponse.kt +++ b/core/network/src/main/java/com/hmh/hamyeonham/core/network/model/ErrorResponse.kt @@ -4,7 +4,7 @@ import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable @Serializable -data class ErrorResponse( +data class ErrorResponse( @SerialName("status") val status: Int, @SerialName("message") From 1ec45369dc1962d99aa0d65159e76a59c375e5b8 Mon Sep 17 00:00:00 2001 From: kangyuri1114 Date: Fri, 3 Jan 2025 02:47:33 +0900 Subject: [PATCH 11/21] =?UTF-8?q?[add]:=20provideResultCallAdapterFactory?= =?UTF-8?q?=20=EB=A9=94=EC=84=9C=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/hmh/hamyeonham/core/network/di/NetModule.kt | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/core/network/src/main/java/com/hmh/hamyeonham/core/network/di/NetModule.kt b/core/network/src/main/java/com/hmh/hamyeonham/core/network/di/NetModule.kt index c118ba2f5..489345e3d 100644 --- a/core/network/src/main/java/com/hmh/hamyeonham/core/network/di/NetModule.kt +++ b/core/network/src/main/java/com/hmh/hamyeonham/core/network/di/NetModule.kt @@ -7,7 +7,7 @@ import com.hmh.hamyeonham.common.qualifier.Secured import com.hmh.hamyeonham.common.qualifier.Unsecured import com.hmh.hamyeonham.core.network.auth.authenticator.HMHAuthenticator import com.hmh.hamyeonham.core.network.auth.interceptor.HeaderInterceptor -import com.hmh.hamyeonham.core.network.call.CustomResultCallAdapterFactory +import com.hmh.hamyeonham.core.network.call.ResultCallAdapterFactory import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory import dagger.Binds import dagger.Module @@ -88,13 +88,17 @@ object NetModule { .writeTimeout(15, TimeUnit.SECONDS) .build() + @Singleton + @Provides + fun provideResultCallAdapterFactory(): ResultCallAdapterFactory = ResultCallAdapterFactory() + @Singleton @Provides @Secured fun provideRetrofit( @Secured client: OkHttpClient, converterFactory: Converter.Factory, - resultCallAdapterFactory: CustomResultCallAdapterFactory, + resultCallAdapterFactory: ResultCallAdapterFactory, ): Retrofit = Retrofit.Builder() .baseUrl(HMHBaseUrl) .client(client) @@ -108,7 +112,7 @@ object NetModule { fun provideRetrofitNotNeededAuth( @Unsecured client: OkHttpClient, converterFactory: Converter.Factory, - resultCallAdapterFactory: CustomResultCallAdapterFactory, + resultCallAdapterFactory: ResultCallAdapterFactory, ): Retrofit = Retrofit.Builder() .baseUrl(HMHBaseUrl) .client(client) From ad713d5a77c17f25a3ecd16e4de4b530bb6c5fe2 Mon Sep 17 00:00:00 2001 From: kangyuri1114 Date: Sat, 4 Jan 2025 20:23:38 +0900 Subject: [PATCH 12/21] =?UTF-8?q?[feat]:=20ApiException=20=ED=81=B4?= =?UTF-8?q?=EB=9E=98=EC=8A=A4=EC=97=90=EC=84=9C=20message=EB=A5=BC=20error?= =?UTF-8?q?Response=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/hmh/hamyeonham/core/network/call/ApiException.kt | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/core/network/src/main/java/com/hmh/hamyeonham/core/network/call/ApiException.kt b/core/network/src/main/java/com/hmh/hamyeonham/core/network/call/ApiException.kt index 8eb746e6d..4ee41cfc5 100644 --- a/core/network/src/main/java/com/hmh/hamyeonham/core/network/call/ApiException.kt +++ b/core/network/src/main/java/com/hmh/hamyeonham/core/network/call/ApiException.kt @@ -1,6 +1,9 @@ package com.hmh.hamyeonham.core.network.call +import com.hmh.hamyeonham.core.network.model.ErrorResponse + class ApiException( - override val message: String, - throwable: Throwable -): Exception(message, throwable) \ No newline at end of file + val errorResponse: ErrorResponse, + //throwable: Throwable + val errorCode: Int +): Exception() \ No newline at end of file From 5cfb0be103e144333629fdd94544b604c3d96271 Mon Sep 17 00:00:00 2001 From: kangyuri1114 Date: Sat, 4 Jan 2025 20:24:29 +0900 Subject: [PATCH 13/21] =?UTF-8?q?[feat]:=20getTemporaryErrorResponse=20?= =?UTF-8?q?=EB=A9=94=EC=84=9C=EB=93=9C=20=EC=B6=94=EA=B0=80=20=ED=9B=84=20?= =?UTF-8?q?body=EA=B0=80=20null=EC=9D=B8=20=EA=B2=BD=EC=9A=B0=20=EA=B4=80?= =?UTF-8?q?=EB=A0=A8=20=EC=BD=94=EB=93=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/network/call/ResultCall.kt | 67 +++++++++---------- 1 file changed, 32 insertions(+), 35 deletions(-) diff --git a/core/network/src/main/java/com/hmh/hamyeonham/core/network/call/ResultCall.kt b/core/network/src/main/java/com/hmh/hamyeonham/core/network/call/ResultCall.kt index c21f7e3ea..2840e51b2 100644 --- a/core/network/src/main/java/com/hmh/hamyeonham/core/network/call/ResultCall.kt +++ b/core/network/src/main/java/com/hmh/hamyeonham/core/network/call/ResultCall.kt @@ -25,51 +25,42 @@ class ResultCall( // onResponse() : HTTP 요청 성공 시 호출 override fun onResponse(call: Call, response: Response) { + val responseBody = response.body() // response.isSuccessful : HTTP 응답 코드가 200~299 사이인지 여부 반환(성공 여부) if (response.isSuccessful) { - // HTTP 요청은 성공했지만 body가 빈 경우 - if(response.body() == null) { + if(responseBody == null) { + val errorBody = getTemporaryErrorResponse(response) + callback.onResponse( this@ResultCall, - Response.success(Result.failure(ApiException("응답 body가 비었습니다.", HttpException(response)))) + Response.success(Result.failure(ApiException(errorBody, response.code()))) ) - } - // HTTP 요청 성공 - else { + } else { // HTTP 요청 성공 callback.onResponse( this@ResultCall, - Response.success(response.code(), Result.success(response.body() ?: throw NullPointerException("응답 body가 비었습니다."))) + Response.success(response.code(), Result.success(responseBody)) ) } - } else { // HTTP 요청 실패 - - // errorBody가 비어있는 경우 - if(response.errorBody() == null) { - callback.onResponse( this@ResultCall, - Response.success(Result.failure(ApiException("errorBody가 비었습니다.", HttpException(response)))) - ) - } - // 요청에 실패한 경우 - else { - // errorBody에서 사용자에게 보여줄 메시지 추출 - // errorBody를 BaseResponse 객체로 변환 - val errorBody = retrofit.responseBodyConverter( - ErrorResponse::class.java, - ErrorResponse::class.java.annotations - ).convert(response.errorBody() ?: throw NullPointerException("errorBody가 비었습니다.")) - - val message: String = errorBody?.message ?: "errorBody가 비었습니다" - - // ApiException 객체 생성 - callback.onResponse(this@ResultCall, - Response.success(Result.failure(ApiException(message, HttpException(response)))) - ) - - Timber.tag("ResultCall - onResponse").e("${ApiException(message, HttpException(response))}") - } + val errorResponse = try { + response.errorBody()?.let { + retrofit.responseBodyConverter( + ErrorResponse::class.java, + ErrorResponse::class.java.annotations + ).convert(it) + } + } catch (e: Exception) { + null + } ?: getTemporaryErrorResponse(response) + + callback.onResponse( + this@ResultCall, + Response.success(Result.failure(ApiException(errorResponse, response.code()))) + ) + + Timber.tag("ResultCall - onResponse").e("ErrorResponse: $errorResponse") } } @@ -84,14 +75,20 @@ class ResultCall( // ApiException 객체 생성 callback.onResponse( this@ResultCall, - Response.success(Result.failure(ApiException(message, t))) + Response.success(Result.failure(RuntimeException(message))) ) - Timber.tag("ResultCall - onFailure").e("${ApiException(message, t)}") + Timber.tag("ResultCall - onFailure").e("onFailure: $message") } }) } + // errorBody가 null인 경우 임시 ErrorResponse 객체 생성 + private fun getTemporaryErrorResponse(response: Response) = ErrorResponse( + status = response.code(), + message = "errorResponse is null" + ) + // clone() : 동일 요청 수행하는 새로운 Call 객체 반환 override fun clone(): Call> { return ResultCall(call.clone(), retrofit) From f800a87a276663a8e53082ae9c07f4b8c35528ea Mon Sep 17 00:00:00 2001 From: KEZ Date: Sat, 4 Jan 2025 20:40:35 +0900 Subject: [PATCH 14/21] =?UTF-8?q?[fix]:=20=EC=BD=94=EB=93=9C=20=EC=A0=95?= =?UTF-8?q?=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/network/call/ApiException.kt | 6 +---- .../core/network/call/ResultCall.kt | 24 ++++++++----------- 2 files changed, 11 insertions(+), 19 deletions(-) diff --git a/core/network/src/main/java/com/hmh/hamyeonham/core/network/call/ApiException.kt b/core/network/src/main/java/com/hmh/hamyeonham/core/network/call/ApiException.kt index 4ee41cfc5..2df4da33a 100644 --- a/core/network/src/main/java/com/hmh/hamyeonham/core/network/call/ApiException.kt +++ b/core/network/src/main/java/com/hmh/hamyeonham/core/network/call/ApiException.kt @@ -2,8 +2,4 @@ package com.hmh.hamyeonham.core.network.call import com.hmh.hamyeonham.core.network.model.ErrorResponse -class ApiException( - val errorResponse: ErrorResponse, - //throwable: Throwable - val errorCode: Int -): Exception() \ No newline at end of file +class ApiException(val errorResponse: ErrorResponse) : Exception() \ No newline at end of file diff --git a/core/network/src/main/java/com/hmh/hamyeonham/core/network/call/ResultCall.kt b/core/network/src/main/java/com/hmh/hamyeonham/core/network/call/ResultCall.kt index 2840e51b2..d73737231 100644 --- a/core/network/src/main/java/com/hmh/hamyeonham/core/network/call/ResultCall.kt +++ b/core/network/src/main/java/com/hmh/hamyeonham/core/network/call/ResultCall.kt @@ -31,11 +31,9 @@ class ResultCall( if (response.isSuccessful) { // HTTP 요청은 성공했지만 body가 빈 경우 if(responseBody == null) { - val errorBody = getTemporaryErrorResponse(response) - callback.onResponse( this@ResultCall, - Response.success(Result.failure(ApiException(errorBody, response.code()))) + Response.success(Result.failure(ApiException(getBodyNullErrorResponse(response)))) ) } else { // HTTP 요청 성공 callback.onResponse( @@ -45,19 +43,17 @@ class ResultCall( } } else { // HTTP 요청 실패 val errorResponse = try { - response.errorBody()?.let { - retrofit.responseBodyConverter( - ErrorResponse::class.java, - ErrorResponse::class.java.annotations - ).convert(it) - } + retrofit.responseBodyConverter( + ErrorResponse::class.java, + ErrorResponse::class.java.annotations + ).convert(response.errorBody()!!) } catch (e: Exception) { null - } ?: getTemporaryErrorResponse(response) + } ?: getBodyNullErrorResponse(response) callback.onResponse( this@ResultCall, - Response.success(Result.failure(ApiException(errorResponse, response.code()))) + Response.success(Result.failure(ApiException(errorResponse))) ) Timber.tag("ResultCall - onResponse").e("ErrorResponse: $errorResponse") @@ -83,10 +79,10 @@ class ResultCall( }) } - // errorBody가 null인 경우 임시 ErrorResponse 객체 생성 - private fun getTemporaryErrorResponse(response: Response) = ErrorResponse( + // 응답 Body가 null인 경우 임시 ErrorResponse 객체 생성 + private fun getBodyNullErrorResponse(response: Response) = ErrorResponse( status = response.code(), - message = "errorResponse is null" + message = "response body is null" ) // clone() : 동일 요청 수행하는 새로운 Call 객체 반환 From a5eee1a4da15e198ceaacf5b949d60023779d127 Mon Sep 17 00:00:00 2001 From: kangyuri1114 Date: Sat, 11 Jan 2025 20:15:15 +0900 Subject: [PATCH 15/21] =?UTF-8?q?[feat]:=20BaseResponse=20data=20?= =?UTF-8?q?=EC=B6=94=EC=B6=9C=20=ED=99=95=EC=9E=A5=ED=95=A8=EC=88=98=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/network/call/util/ResultExtensions.kt | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 core/network/src/main/java/com/hmh/hamyeonham/core/network/call/util/ResultExtensions.kt diff --git a/core/network/src/main/java/com/hmh/hamyeonham/core/network/call/util/ResultExtensions.kt b/core/network/src/main/java/com/hmh/hamyeonham/core/network/call/util/ResultExtensions.kt new file mode 100644 index 000000000..34929296e --- /dev/null +++ b/core/network/src/main/java/com/hmh/hamyeonham/core/network/call/util/ResultExtensions.kt @@ -0,0 +1,15 @@ +package com.hmh.hamyeonham.core.network.call.util + +import com.hmh.hamyeonham.core.network.model.BaseResponse + +fun Result>.getResult(): Result { + return this.fold( + onSuccess = { response -> + response.data?.let { Result.success(it) } + ?: Result.failure(IllegalStateException("response body is null")) + }, + onFailure = { throwable -> + Result.failure(throwable) + } + ) +} \ No newline at end of file From 550df51ed7f27cdeae2d08cc9ae6836bf7337fc7 Mon Sep 17 00:00:00 2001 From: kangyuri1114 Date: Sat, 11 Jan 2025 20:22:10 +0900 Subject: [PATCH 16/21] =?UTF-8?q?[feat]:=20getUserInfo=20API=20Result?= =?UTF-8?q?=EB=A5=BC=20=ED=99=9C=EC=9A=A9=ED=95=9C=20=EC=98=88=EC=99=B8?= =?UTF-8?q?=EC=B2=98=EB=A6=AC=20=EB=A1=9C=EC=A7=81=EC=9C=BC=EB=A1=9C=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/hmh/hamyeonham/core/network/mypage/MyPageService.kt | 2 +- .../com/hmh/hamyeonham/data/main/DefaultMainRepository.kt | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/core/network/src/main/java/com/hmh/hamyeonham/core/network/mypage/MyPageService.kt b/core/network/src/main/java/com/hmh/hamyeonham/core/network/mypage/MyPageService.kt index 451c8aeeb..c11f0c9ac 100644 --- a/core/network/src/main/java/com/hmh/hamyeonham/core/network/mypage/MyPageService.kt +++ b/core/network/src/main/java/com/hmh/hamyeonham/core/network/mypage/MyPageService.kt @@ -6,5 +6,5 @@ import retrofit2.http.GET interface MyPageService { @GET("api/v1/user") - suspend fun getUserInfo(): BaseResponse + suspend fun getUserInfo(): Result> } diff --git a/data/main/src/main/java/com/hmh/hamyeonham/data/main/DefaultMainRepository.kt b/data/main/src/main/java/com/hmh/hamyeonham/data/main/DefaultMainRepository.kt index dd4e7b907..77ee2d2ae 100644 --- a/data/main/src/main/java/com/hmh/hamyeonham/data/main/DefaultMainRepository.kt +++ b/data/main/src/main/java/com/hmh/hamyeonham/data/main/DefaultMainRepository.kt @@ -1,5 +1,6 @@ package com.hmh.hamyeonham.data.main +import com.hmh.hamyeonham.core.network.call.util.getResult import com.hmh.hamyeonham.core.network.main.MainService import com.hmh.hamyeonham.domain.main.MainRepository import com.hmh.hamyeonham.domain.main.banner.model.Banner @@ -10,8 +11,8 @@ class DefaultMainRepository @Inject constructor( private val mainService: MainService ) : MainRepository { override suspend fun getBanner(): Result { - return runCatching { - mainService.getBanner().data.toBanner() + return mainService.getBanner().getResult().mapCatching { response -> + response.toBanner() } } } \ No newline at end of file From cd212969a10e06cfe0e97f29c683bf2f8cc52614 Mon Sep 17 00:00:00 2001 From: kangyuri1114 Date: Sat, 11 Jan 2025 20:23:51 +0900 Subject: [PATCH 17/21] =?UTF-8?q?[feat]:=20getBanner=20API=20Result?= =?UTF-8?q?=EB=A5=BC=20=ED=99=9C=EC=9A=A9=ED=95=9C=20=EC=98=88=EC=99=B8?= =?UTF-8?q?=EC=B2=98=EB=A6=AC=20=EB=A1=9C=EC=A7=81=EC=9C=BC=EB=A1=9C=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../hmh/hamyeonham/core/network/main/MainService.kt | 2 +- .../userinfo/repository/DefaultUserInfoRepository.kt | 11 +++++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/core/network/src/main/java/com/hmh/hamyeonham/core/network/main/MainService.kt b/core/network/src/main/java/com/hmh/hamyeonham/core/network/main/MainService.kt index 147c08e37..2fd914af0 100644 --- a/core/network/src/main/java/com/hmh/hamyeonham/core/network/main/MainService.kt +++ b/core/network/src/main/java/com/hmh/hamyeonham/core/network/main/MainService.kt @@ -6,5 +6,5 @@ import retrofit2.http.GET interface MainService { @GET("api/v2/banner") - suspend fun getBanner(): BaseResponse + suspend fun getBanner(): Result> } \ No newline at end of file diff --git a/data/userinfo/src/main/java/com/hmh/hamyeonham/userinfo/repository/DefaultUserInfoRepository.kt b/data/userinfo/src/main/java/com/hmh/hamyeonham/userinfo/repository/DefaultUserInfoRepository.kt index 4db0705a2..089a07f96 100644 --- a/data/userinfo/src/main/java/com/hmh/hamyeonham/userinfo/repository/DefaultUserInfoRepository.kt +++ b/data/userinfo/src/main/java/com/hmh/hamyeonham/userinfo/repository/DefaultUserInfoRepository.kt @@ -1,5 +1,6 @@ package com.hmh.hamyeonham.userinfo.repository +import com.hmh.hamyeonham.core.network.call.util.getResult import com.hmh.hamyeonham.core.network.mypage.MyPageService import com.hmh.hamyeonham.login.mapper.toUserInfo import com.hmh.hamyeonham.userinfo.model.UserInfo @@ -9,8 +10,10 @@ class DefaultUserInfoRepository @Inject constructor( private val myPageService: MyPageService ) : UserInfoRepository { override suspend fun getUserInfo(): Result { - return runCatching { - myPageService.getUserInfo().data.toUserInfo() - } + return myPageService.getUserInfo() + .getResult() + .mapCatching { response -> + response.toUserInfo() + } } -} +} \ No newline at end of file From 8056fe602366874767bd8d45a54cfa0dcdfb5530 Mon Sep 17 00:00:00 2001 From: kangyuri1114 Date: Sat, 11 Jan 2025 20:45:52 +0900 Subject: [PATCH 18/21] =?UTF-8?q?[feat]:=20=ED=99=95=EC=9E=A5=ED=95=A8?= =?UTF-8?q?=EC=88=98=20getResult()=20=EB=82=B4=20onFailure=20=EC=8B=9C=20t?= =?UTF-8?q?hrowable=20=EB=B0=98=ED=99=98=EC=9D=B4=20=EC=95=84=EB=8B=8C=20e?= =?UTF-8?q?rrorResponse=EB=A5=BC=20=EB=B0=98=ED=99=98=ED=95=98=EB=8F=84?= =?UTF-8?q?=EB=A1=9D=20=EC=98=88=EC=99=B8=EC=B2=98=EB=A6=AC=20=EC=84=B8?= =?UTF-8?q?=EB=B6=84=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../network/call/util/ResultExtensions.kt | 22 ++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/core/network/src/main/java/com/hmh/hamyeonham/core/network/call/util/ResultExtensions.kt b/core/network/src/main/java/com/hmh/hamyeonham/core/network/call/util/ResultExtensions.kt index 34929296e..ad3a24719 100644 --- a/core/network/src/main/java/com/hmh/hamyeonham/core/network/call/util/ResultExtensions.kt +++ b/core/network/src/main/java/com/hmh/hamyeonham/core/network/call/util/ResultExtensions.kt @@ -1,15 +1,31 @@ package com.hmh.hamyeonham.core.network.call.util +import com.hmh.hamyeonham.core.network.call.ApiException import com.hmh.hamyeonham.core.network.model.BaseResponse +import com.hmh.hamyeonham.core.network.model.ErrorResponse +import retrofit2.HttpException fun Result>.getResult(): Result { return this.fold( onSuccess = { response -> response.data?.let { Result.success(it) } - ?: Result.failure(IllegalStateException("response body is null")) + ?: Result.failure(IllegalStateException("Response body is null")) }, onFailure = { throwable -> - Result.failure(throwable) + val errorResponse = when (throwable) { + is HttpException -> { + val errorBody = throwable.response()?.errorBody()?.string() + ErrorResponse( + status = throwable.code(), + message = errorBody ?: "Unknown server error" + ) + } + else -> ErrorResponse( + status = -1, + message = throwable.message ?: "Unknown error occurred" + ) + } + Result.failure(ApiException(errorResponse)) } ) -} \ No newline at end of file +} From 9557ea7c608f6a8884b68e07ad5d3f1cdf74ae55 Mon Sep 17 00:00:00 2001 From: kangyuri1114 Date: Sun, 12 Jan 2025 23:03:48 +0900 Subject: [PATCH 19/21] =?UTF-8?q?[feat]:=20ResultCall=EC=97=90=EC=84=9C=20?= =?UTF-8?q?BaseResponse=EB=A5=BC=20=EC=A7=81=EC=A0=91=20=EC=B2=98?= =?UTF-8?q?=EB=A6=AC=ED=95=98=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../hamyeonham/core/network/call/ResultCall.kt | 17 +++++++++-------- .../repository/DefaultUserInfoRepository.kt | 6 ++---- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/core/network/src/main/java/com/hmh/hamyeonham/core/network/call/ResultCall.kt b/core/network/src/main/java/com/hmh/hamyeonham/core/network/call/ResultCall.kt index d73737231..7c0b1616a 100644 --- a/core/network/src/main/java/com/hmh/hamyeonham/core/network/call/ResultCall.kt +++ b/core/network/src/main/java/com/hmh/hamyeonham/core/network/call/ResultCall.kt @@ -1,5 +1,6 @@ package com.hmh.hamyeonham.core.network.call +import com.hmh.hamyeonham.core.network.model.BaseResponse import com.hmh.hamyeonham.core.network.model.ErrorResponse import okhttp3.Request import okio.IOException @@ -12,7 +13,7 @@ import retrofit2.Retrofit import timber.log.Timber class ResultCall( - private val call: Call, + private val call: Call>, private val retrofit: Retrofit, ): Call>{ @@ -21,10 +22,10 @@ class ResultCall( override fun enqueue(callback: Callback>) { // Callback> 객체를 인자로 받아 Call 객체의 enqueue() 메서드 호출 - call.enqueue(object : Callback { + call.enqueue(object : Callback> { // onResponse() : HTTP 요청 성공 시 호출 - override fun onResponse(call: Call, response: Response) { + override fun onResponse(call: Call>, response: Response>) { val responseBody = response.body() // response.isSuccessful : HTTP 응답 코드가 200~299 사이인지 여부 반환(성공 여부) @@ -33,12 +34,12 @@ class ResultCall( if(responseBody == null) { callback.onResponse( this@ResultCall, - Response.success(Result.failure(ApiException(getBodyNullErrorResponse(response)))) + Response.success(Result.failure(RuntimeException("응답 body가 비었습니다."))) ) } else { // HTTP 요청 성공 callback.onResponse( this@ResultCall, - Response.success(response.code(), Result.success(responseBody)) + Response.success(Result.success(responseBody.data)) ) } } else { // HTTP 요청 실패 @@ -61,7 +62,7 @@ class ResultCall( } // onFailure() : HTTP 요청 실패 시 호출 - override fun onFailure(call: Call, t: Throwable) { + override fun onFailure(call: Call>, t: Throwable) { val message = when (t) { is IOException -> "네트워크 연결이 불안정합니다. 다시 시도해주세요." is HttpException -> "${t.code()} : 서버 통신 중 문제가 발생했습니다. 다시 시도해주세요." @@ -80,7 +81,7 @@ class ResultCall( } // 응답 Body가 null인 경우 임시 ErrorResponse 객체 생성 - private fun getBodyNullErrorResponse(response: Response) = ErrorResponse( + private fun getBodyNullErrorResponse(response: Response>) = ErrorResponse( status = response.code(), message = "response body is null" ) @@ -93,7 +94,7 @@ class ResultCall( // execute() : HTTP 요청을 동기적으로 실행. 성공 시 Response> 반환, 실패 시 Exception 발생 // 주로 테스트 용도 override fun execute(): Response> { - return Response.success(Result.success(call.execute().body() ?: throw NullPointerException("응답 body가 비었습니다."))) + return Response.success(Result.failure(RuntimeException("execute() 메서드는 사용할 수 없습니다."))) } // isExecuted() : HTTP 요청이 이미 실행되었는지 여부 반환. diff --git a/data/userinfo/src/main/java/com/hmh/hamyeonham/userinfo/repository/DefaultUserInfoRepository.kt b/data/userinfo/src/main/java/com/hmh/hamyeonham/userinfo/repository/DefaultUserInfoRepository.kt index 089a07f96..aa1ed4520 100644 --- a/data/userinfo/src/main/java/com/hmh/hamyeonham/userinfo/repository/DefaultUserInfoRepository.kt +++ b/data/userinfo/src/main/java/com/hmh/hamyeonham/userinfo/repository/DefaultUserInfoRepository.kt @@ -1,6 +1,5 @@ package com.hmh.hamyeonham.userinfo.repository -import com.hmh.hamyeonham.core.network.call.util.getResult import com.hmh.hamyeonham.core.network.mypage.MyPageService import com.hmh.hamyeonham.login.mapper.toUserInfo import com.hmh.hamyeonham.userinfo.model.UserInfo @@ -11,9 +10,8 @@ class DefaultUserInfoRepository @Inject constructor( ) : UserInfoRepository { override suspend fun getUserInfo(): Result { return myPageService.getUserInfo() - .getResult() - .mapCatching { response -> - response.toUserInfo() + .mapCatching { baseResponse -> + baseResponse.data.toUserInfo() } } } \ No newline at end of file From a15978a5629d7dfb6fb10f382a6b70412eb5630c Mon Sep 17 00:00:00 2001 From: kangyuri1114 Date: Mon, 3 Feb 2025 02:28:37 +0900 Subject: [PATCH 20/21] =?UTF-8?q?[feat]:=20UserInfoResponse=20=EA=B8=B0?= =?UTF-8?q?=EB=B3=B8=EA=B0=92=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../hamyeonham/core/network/mypage/model/UserInfoResponse.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/network/src/main/java/com/hmh/hamyeonham/core/network/mypage/model/UserInfoResponse.kt b/core/network/src/main/java/com/hmh/hamyeonham/core/network/mypage/model/UserInfoResponse.kt index 2be44beb0..44575ad26 100644 --- a/core/network/src/main/java/com/hmh/hamyeonham/core/network/mypage/model/UserInfoResponse.kt +++ b/core/network/src/main/java/com/hmh/hamyeonham/core/network/mypage/model/UserInfoResponse.kt @@ -6,7 +6,7 @@ import kotlinx.serialization.Serializable @Serializable data class UserInfoResponse( @SerialName("name") - val name: String, + val name: String = "", @SerialName("point") - val point: Int + val point: Int = 0 ) From d51749846e0b4471178d287e792613d97edfb789 Mon Sep 17 00:00:00 2001 From: kangyuri1114 Date: Mon, 3 Feb 2025 02:59:12 +0900 Subject: [PATCH 21/21] =?UTF-8?q?[feat]:=20call=20=EB=8D=B0=EC=9D=B4?= =?UTF-8?q?=ED=84=B0=ED=98=95=20=EC=88=98=EC=A0=95=20Call>?= =?UTF-8?q?=20->=20Call?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/network/call/ResultCall.kt | 25 ++++++++----------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/core/network/src/main/java/com/hmh/hamyeonham/core/network/call/ResultCall.kt b/core/network/src/main/java/com/hmh/hamyeonham/core/network/call/ResultCall.kt index 7c0b1616a..82b25aadd 100644 --- a/core/network/src/main/java/com/hmh/hamyeonham/core/network/call/ResultCall.kt +++ b/core/network/src/main/java/com/hmh/hamyeonham/core/network/call/ResultCall.kt @@ -13,44 +13,41 @@ import retrofit2.Retrofit import timber.log.Timber class ResultCall( - private val call: Call>, + private val call: Call, private val retrofit: Retrofit, -): Call>{ +) : Call> { // enqueue() : HTTP 요청을 비동기적으로 실행. 요청 결과를 전달받기 위해 Callback>를 인자로 받음 // enqueue() 메서드를 Custom override fun enqueue(callback: Callback>) { // Callback> 객체를 인자로 받아 Call 객체의 enqueue() 메서드 호출 - call.enqueue(object : Callback> { + call.enqueue(object : Callback { // onResponse() : HTTP 요청 성공 시 호출 - override fun onResponse(call: Call>, response: Response>) { + override fun onResponse(call: Call, response: Response) { val responseBody = response.body() // response.isSuccessful : HTTP 응답 코드가 200~299 사이인지 여부 반환(성공 여부) if (response.isSuccessful) { // HTTP 요청은 성공했지만 body가 빈 경우 - if(responseBody == null) { + if (responseBody != null) { callback.onResponse( this@ResultCall, - Response.success(Result.failure(RuntimeException("응답 body가 비었습니다."))) + Response.success(Result.success(responseBody)) ) } else { // HTTP 요청 성공 callback.onResponse( this@ResultCall, - Response.success(Result.success(responseBody.data)) + Response.success(Result.failure(RuntimeException("응답 body가 비었습니다."))) ) } } else { // HTTP 요청 실패 - val errorResponse = try { + val errorResponse = retrofit.responseBodyConverter( ErrorResponse::class.java, ErrorResponse::class.java.annotations - ).convert(response.errorBody()!!) - } catch (e: Exception) { - null - } ?: getBodyNullErrorResponse(response) + ).convert(response.errorBody()!!) ?: getBodyNullErrorResponse(response) callback.onResponse( this@ResultCall, @@ -62,7 +59,7 @@ class ResultCall( } // onFailure() : HTTP 요청 실패 시 호출 - override fun onFailure(call: Call>, t: Throwable) { + override fun onFailure(call: Call, t: Throwable) { val message = when (t) { is IOException -> "네트워크 연결이 불안정합니다. 다시 시도해주세요." is HttpException -> "${t.code()} : 서버 통신 중 문제가 발생했습니다. 다시 시도해주세요." @@ -81,7 +78,7 @@ class ResultCall( } // 응답 Body가 null인 경우 임시 ErrorResponse 객체 생성 - private fun getBodyNullErrorResponse(response: Response>) = ErrorResponse( + private fun getBodyNullErrorResponse(response: Response) = ErrorResponse( status = response.code(), message = "response body is null" )