개발일기

OkHttp Interceptor로 공통 로깅 및 에러 처리하기

뱅우 2025. 9. 22. 09:45
반응형
OkHttp Interceptor로 공통 로깅 및 에러 처리하기

안드로이드 앱에서 네트워크 요청은 Retrofit과 OkHttp를 함께 사용하는 경우가 많습니다. 이때 공통 로깅, 인증 토큰 주입, 에러 처리 등을 Interceptor에서 처리하면 코드를 깔끔하게 유지하고, 모든 API 요청·응답을 일관되게 다룰 수 있습니다.


1. Interceptor란?

OkHttp의 Interceptor는 네트워크 요청(Request)과 응답(Response)을 가로채어 추가 로직을 삽입할 수 있는 기능입니다. Retrofit의 OkHttpClient에 추가해 사용하며, 크게 두 가지로 나눕니다.

  • Application Interceptor: 애플리케이션 레벨에서 실행 (요청/응답 변환, 공통 헤더 추가 등)
  • Network Interceptor: 실제 네트워크 I/O 직전에 실행 (캐시, 압축, 네트워크 관련 작업)

2. 공통 로깅 Interceptor 구현

OkHttp에서 기본 제공하는 HttpLoggingInterceptor를 사용하면 손쉽게 요청·응답 로그를 확인할 수 있습니다.

val loggingInterceptor = HttpLoggingInterceptor().apply {
    level = HttpLoggingInterceptor.Level.BODY
}

val client = OkHttpClient.Builder()
    .addInterceptor(loggingInterceptor)
    .build()

val retrofit = Retrofit.Builder()
    .baseUrl("https://api.example.com/")
    .client(client)
    .addConverterFactory(GsonConverterFactory.create())
    .build()

위 코드를 적용하면 모든 요청·응답의 URL, 헤더, Body를 로그캣에서 확인할 수 있습니다.


3. 인증 토큰 자동 주입 Interceptor

매 API마다 인증 토큰을 수동으로 넣기보다 Interceptor를 이용해 자동으로 추가할 수 있습니다.

class AuthInterceptor(private val tokenProvider: () -> String?) : Interceptor {
    override fun intercept(chain: Interceptor.Chain): Response {
        val originalRequest = chain.request()
        val token = tokenProvider() ?: ""

        val newRequest = originalRequest.newBuilder()
            .addHeader("Authorization", "Bearer $token")
            .build()

        return chain.proceed(newRequest)
    }
}

// 사용
val client = OkHttpClient.Builder()
    .addInterceptor(AuthInterceptor { getAccessTokenFromPrefs() })
    .addInterceptor(loggingInterceptor)
    .build()

4. 공통 에러 처리 Interceptor

서버에서 에러 응답(401, 403, 500 등)을 받을 때 공통으로 처리하고 싶다면 Interceptor에서 Response를 검사하세요.

class ErrorHandlingInterceptor : Interceptor {
    override fun intercept(chain: Interceptor.Chain): Response {
        val response = chain.proceed(chain.request())

        when (response.code) {
            401 -> {
                // 인증 만료 처리 (로그아웃 or 토큰 갱신)
            }
            500 -> {
                // 서버 에러 처리
            }
        }

        return response
    }
}

val client = OkHttpClient.Builder()
    .addInterceptor(AuthInterceptor { getAccessTokenFromPrefs() })
    .addInterceptor(ErrorHandlingInterceptor())
    .addInterceptor(loggingInterceptor)
    .build()

5. Compose와 Interceptor 연계

Jetpack Compose 앱에서는 ViewModel에서 Retrofit Repository를 호출할 때 Interceptor로 인증·에러 처리를 자동화해 UI는 단순히 상태만 구독하도록 만들 수 있습니다. 이렇게 하면 ViewModel과 Repository 코드가 훨씬 깔끔해집니다.


6. 테스트 팁

  • MockWebServer를 이용해 Interceptor 동작 테스트 가능
  • TokenProvider를 DI로 주입하여 테스트 환경에서 가짜 토큰 사용
  • Response code 별 시나리오 작성으로 에러 처리 로직 검증

7. 요약

  • 공통 로깅/토큰 주입/에러 처리는 Interceptor에서 일원화
  • Retrofit + OkHttpClient.Builder에서 Interceptor 체인 구성
  • 테스트 가능한 구조로 DI와 MockWebServer 적극 활용

마무리:
Interceptor를 적절히 활용하면 네트워크 계층의 유지보수성을 크게 높일 수 있습니다. 특히 큰 앱에서 공통 로직을 한 곳에서 관리하려면 필수적인 패턴입니다.

반응형