-
Notifications
You must be signed in to change notification settings - Fork 0
[Fix] 500대 네트워크 오류 대응 #379
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,58 @@ | ||||||
| package com.eatssu.android.di.network | ||||||
|
|
||||||
| import android.content.Context | ||||||
| import android.content.Intent | ||||||
| import com.eatssu.android.data.dto.response.BaseResponse | ||||||
| import com.eatssu.android.presentation.error.ErrorActivity | ||||||
| import com.google.gson.Gson | ||||||
| import okhttp3.Interceptor | ||||||
| import okhttp3.MediaType.Companion.toMediaTypeOrNull | ||||||
| import okhttp3.Protocol | ||||||
| import okhttp3.Response | ||||||
| import okhttp3.ResponseBody.Companion.toResponseBody | ||||||
| import java.io.IOException | ||||||
| import javax.inject.Inject | ||||||
|
|
||||||
|
|
||||||
| /** | ||||||
| * 네트워크 오류를 처리하는 인터셉터 | ||||||
| * IOException(SocketTimeoutException, UnknownHostException) 발생 시 AlertDialog를 띄우는 ErrorActivity로 이동 | ||||||
| */ | ||||||
| class NetworkErrorInterceptor @Inject constructor( | ||||||
| private val context: Context, | ||||||
| ) : Interceptor { | ||||||
|
|
||||||
| companion object { | ||||||
| private val gson = Gson() | ||||||
| } | ||||||
|
|
||||||
| override fun intercept(chain: Interceptor.Chain): Response { | ||||||
| val request = chain.request() | ||||||
|
|
||||||
| try { | ||||||
| return chain.proceed(request) | ||||||
| } catch (e: IOException) { | ||||||
| val intent = Intent(context, ErrorActivity::class.java).apply { | ||||||
| addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK) | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| putExtra("message", "서버 통신에 실패했습니다. 잠시 후 다시 시도해 주세요.") | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 에러 메시지와 인텐트 extra의 키("message")가 하드코딩되어 있습니다. 유지보수성과 다국어 지원을 위해 문자열은 예시: // ErrorActivity.kt
companion object {
const val EXTRA_MESSAGE = "error_message"
}
// strings.xml
<string name="network_error">서버 통신에 실패했습니다. 잠시 후 다시 시도해 주세요.</string>
// NetworkErrorInterceptor.kt
putExtra(ErrorActivity.EXTRA_MESSAGE, context.getString(R.string.network_error)) |
||||||
| } | ||||||
| context.startActivity(intent) | ||||||
|
|
||||||
| val baseResponse = BaseResponse<Void>( | ||||||
| isSuccess = false, | ||||||
| code = 500, // 서버 처리 오류인지 통신 불가인지 구분 | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 네트워크 오류를 나타내기 위해 예시: // NetworkErrorInterceptor.kt
companion object {
const val NETWORK_ERROR_CODE = 500
private val gson = Gson()
}
// IntroViewModel.kt
... else if (it.code != NetworkErrorInterceptor.NETWORK_ERROR_CODE) { ... |
||||||
| message = "서버 통신 실패", | ||||||
| ) | ||||||
| val json = gson.toJson(baseResponse) | ||||||
| val responseBody = json.toResponseBody("application/json".toMediaTypeOrNull()) | ||||||
|
|
||||||
| return Response.Builder() | ||||||
| .request(request) | ||||||
| .protocol(Protocol.HTTP_1_1) | ||||||
| .code(200) // HTTP 응답 코드는 200으로 해야 Retrofit에서 에러로 처리하지 않음 | ||||||
| .message("서버 통신 실패") | ||||||
| .body(responseBody) | ||||||
| .build() | ||||||
| } | ||||||
| } | ||||||
| } | ||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| package com.eatssu.android.presentation.error | ||
|
|
||
| import android.app.AlertDialog | ||
| import android.os.Bundle | ||
| import androidx.appcompat.app.AppCompatActivity | ||
| import com.eatssu.android.databinding.ActivityErrorBinding | ||
| import dagger.hilt.android.AndroidEntryPoint | ||
|
|
||
| @AndroidEntryPoint | ||
| class ErrorActivity : AppCompatActivity() { | ||
|
|
||
| override fun onCreate(savedInstanceState: Bundle?) { | ||
| super.onCreate(savedInstanceState) | ||
| val binding = ActivityErrorBinding.inflate(layoutInflater) | ||
| setContentView(binding.root) | ||
|
|
||
| showDialog() | ||
| } | ||
|
|
||
| private fun showDialog() { | ||
| val message = intent.getStringExtra("message") ?: "알 수 없는 문제가 발생했습니다. 잠시 후 다시 시도해 주세요." | ||
|
|
||
| AlertDialog.Builder(this) | ||
| .setTitle("알림") | ||
| .setMessage(message) | ||
| .setCancelable(false) | ||
| .setPositiveButton("확인") { _, _ -> finish() } | ||
| .setOnDismissListener { finish() } | ||
| .show() | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -59,7 +59,7 @@ class IntroViewModel @Inject constructor( | |
| .collect { | ||
| if (it.result == true) { //토큰이 있고 유효함 | ||
| _uiState.value = UiState.Success(IntroState.ValidToken) | ||
| } else { //토큰이 있어도 유효하지 않음 | ||
| } else if (it.code != 500) { // 토큰이 있어도 유효하지 않음 | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| _uiState.value = UiState.Error | ||
| _uiEvent.emit(UiEvent.ShowToast("로그인이 필요합니다")) | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| <?xml version="1.0" encoding="utf-8"?> | ||
| <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" | ||
| xmlns:app="http://schemas.android.com/apk/res-auto" | ||
| xmlns:tools="http://schemas.android.com/tools" | ||
| android:layout_width="match_parent" | ||
| android:layout_height="match_parent" | ||
| android:background="@color/primary" | ||
| tools:context=".presentation.error.ErrorActivity"> | ||
|
|
||
| <ImageView | ||
| android:layout_width="250dp" | ||
| android:layout_height="wrap_content" | ||
| android:scaleType="centerInside" | ||
| android:layout_margin="65dp" | ||
| android:src="@drawable/img_new_logo_white" | ||
| app:layout_constraintBottom_toBottomOf="parent" | ||
| app:layout_constraintEnd_toEndOf="parent" | ||
| app:layout_constraintStart_toStartOf="parent" | ||
| app:layout_constraintTop_toTopOf="parent" /> | ||
|
|
||
| </androidx.constraintlayout.widget.ConstraintLayout> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
현재
provideAuthOkHttpClient함수는BuildConfig.DEBUG값에 따라 두 개의 거의 동일한OkHttpClient.Builder블록을 가지고 있습니다. 로깅 인터셉터 추가 여부만 다른데, 이로 인해 코드 중복이 발생합니다. 아래와 같이 리팩토링하여 중복을 제거하고 가독성을 높일 수 있습니다.