Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CallAdapter로 리팩토링한다. #534

Open
wants to merge 7 commits into
base: dev
Choose a base branch
from

Conversation

rhkrwngud445
Copy link
Collaborator

@rhkrwngud445 rhkrwngud445 commented Nov 7, 2023

🔥 연관 이슈

📝 작업 요약

CallAdapter 적용

🔎 작업 상세 설명

주요 클래스는 EdonymyeonCall 과 ApiResponseMapper입니다
EdonymyeonCall에서 Retrofit interface의 리턴타입을 커스텀합니다.

sealed class인 ApiResponse 타입으로 리턴하며 구조는 아래와 같습니다.

  • ApiResponse
    • Success
    • Failure
      • HttpError
      • NoAuthError (인증정보 없는 경우를 따로 만들었습니다)
      • NetworkError
      • UnknownApiError

위 값을 Repository까지 가지고 옵니다. 그리고 ApiResponseMapper를 통해서 Result로 변환합니다.

fun <T, R> ApiResponse<T>.toResult(
    handleSuccess: ((T, Headers) -> R)? = null,
): Result<R> {
    return when (this) {
        is ApiResponse.Success -> {
            val resultData: R = handleSuccess?.invoke(data, headers) ?: data as R
            Result.success(resultData)
        }

        is ApiResponse.Failure -> {
            val exception = when (this) {
                is ApiResponse.Failure.NoAuthError -> ApiException.NoAuthException(
                    errorResponse.errorCode,
                    errorResponse.errorMessage,
                )

                is ApiResponse.Failure.HttpError -> ApiException.HttpError(
                    errorResponse.errorCode,
                    errorResponse.errorMessage,
                )

                is ApiResponse.Failure.UnknownApiError -> ApiException.UnknownApiError(throwable)
                is ApiResponse.Failure.NetworkError -> ApiException.NetworkError(throwable)
            }
            Result.failure(exception)
        }
    }
}

위 코드에서 Success에 대한 처리만 유심히 보시면 됩니다.
고려한 경우의 수가 3가지 있는데,

  1. domain모델로 변환하는 경우
  2. Response의 headers()를 사용하는 경우
  3. 변환이 필요없는 경우

해결 과정은 아래와 같습니다.

  • T타입으로 받아 R타입의 Result로 리턴합니다. 이는 1번 경우를 고려한 설계입니다.
  • headers를 EdonymyeonCall에서 가져옵니다. 그리고 onSuccess시에 같이 담아줍니다. 2번에 해당됩니다.
  • 변환이 필요없는 경우 람다를 null로 분기 처리하여, apiCall.toResult() 다음과 같이 쓸 수 있게 만들었습니다. 3번에 해당됩니다.

에러처리 적용시킨 것 최종 푸쉬 해놓았는데, 아래 두가지 문제가 아직 있습니다
authRepository가 모든 ViewModel에서 들고 있는 문제 -> 필요한 ViewModel에서 가지고 있다가 분기처리
에러 분기처리가 중복되는 문제 -> BaseViewModel에 UiState를 두어서 해결할 수 있을 것 같습니다

이는 따로 이슈파서 추후 진행하도록 하겠습니다

🌟 리뷰 요구 사항

리뷰 예상 시간 및 집중 리뷰 부분을 작성해주세요.

Copy link

github-actions bot commented Nov 7, 2023

Test Results

43 tests   43 ✔️  0s ⏱️
  8 suites    0 💤
  8 files      0

Results for commit 973b179.

♻️ This comment has been updated with latest results.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

오류처리를 개선한다(feat: CallAdapter)
1 participant