Interceptor는 OkHttp와 Alamofire의 구성 요소로, 로깅, 인증, 캐싱 및 재시도를 위해 HTTP 요청과 응답을 가로챕니다. Square (2026)에 따르면, 올바르게 구성된 인터셉터는 네트워크 디버깅 시간을 40% 줄이고 오류 처리를 표준화합니다. Application Interceptor는 요청당 한 번 실행되고, Network Interceptor는 각 리디렉션마다 실행됩니다.
주요 내용
Interceptor는 HTTP 클라이언트에 주입되어 서버로 전송되기 전의 요청과 애플리케이션에 도달하기 전의 응답을 가로채고 수정하는 소프트웨어 구성 요소입니다. 모바일 개발에서 인터셉터는 교차 관심사를 처리합니다: 자동 인증 토큰 주입, 시간 측정이 포함된 트래픽 로깅, 일시적인 네트워크 오류 시 재시도, 실시간 데이터 압축 및 복호화. Interceptor 아키텍처는 Chain of Responsibility 패턴을 기반으로 합니다 — 각 인터셉터는 요청을 수정하거나, 실행하거나, 사용자 정의 응답을 반환하여 체인을 중단할 수 있습니다.
OkHttp에서 인터셉터는 체인을 형성합니다. 각 Interceptor는 원래 요청이 있는 Chain 객체를 받고 chain.proceed(request)를 호출하여 다음 인터셉터로 제어를 전달합니다. 응답을 받은 후, 인터셉터는 Response를 분석하거나, 수정하거나, 오류 시 요청을 재시도하거나, 캐싱을 위한 사용자 정의 응답을 반환할 수 있습니다. OkHttpClient.Builder에 인터셉터를 추가하는 순서가 실행 순서를 결정합니다: 가장 먼저 추가된 것이 전송 시 가장 먼저, 수신 시 가장 마지막에 실행됩니다.
OkHttp는 인터셉터를 두 가지 유형으로 구분합니다. Application Interceptor (addInterceptor)는 애플리케이션 코드와 OkHttp 사이에서 실행됩니다: chain.proceed() 호출 한 번 — 리디렉션에 관계없이 서버에 한 번의 요청. Network Interceptor (addNetworkInterceptor)는 헤더 형성 및 연결 후 OkHttp 내부에서 실행되며, 각 리디렉션, 재시도 또는 인증 시도 시 발동됩니다. 이 구분은 특정 작업에 적합한 인터셉터 유형을 선택하는 데 중요합니다.
class LoggingInterceptor : Interceptor {
override fun intercept(chain: Interceptor.Chain): Response {
val request = chain.request()
Log.d("HTTP", "${request.method} ${request.url}")
val startTime = System.currentTimeMillis()
val response = chain.proceed(request)
val duration = System.currentTimeMillis() - startTime
Log.d("HTTP", "${response.code} in ${duration}ms")
return response
}
}
val client = OkHttpClient.Builder()
.addInterceptor(LoggingInterceptor())
.addNetworkInterceptor(CacheInterceptor())
.build()
LoggingInterceptor — 메서드, URL, 응답 코드 및 실행 시간을 로깅하는 Application Interceptor. addInterceptor()를 통해 추가하면 리디렉션 시 중복 없이 사용자 요청당 하나의 로그가 보장됩니다. CacheInterceptor는 HTTP 요청 형성 후 OkHttp 내부에서만 볼 수 있는 서버의 Cache-Control 헤더를 고려하기 위해 Network Interceptor로 추가됩니다.
애플리케이션이 요청을 하면 서버가 302 또는 301 리디렉션으로 응답할 수 있습니다. Application Interceptor는 모든 리디렉션 후 최종 응답만 봅니다 — 중간에 몇 개의 요청이 있었는지 알 수 없습니다. Network Interceptor는 중간 요청을 포함한 모든 요청과 응답을 봅니다. Square (2026)에 따르면, Network Interceptor는 연결 수준에서 압축된 데이터(gzip)도 볼 수 있지만, Application Interceptor는 이미 압축 해제된 응답을 받습니다. 실제 네트워크 호출 수를 계산하려면 Network Interceptor를 사용하세요.
Alamofire는 두 가지 프로토콜을 결합한 RequestInterceptor 프로토콜을 제공합니다: 전송 전 요청을 수정하는 RequestAdapter와 오류 시 재시도하는 RequestRetrier입니다. 이 분리를 통해 적응(헤더, 토큰 추가)과 재시도 정책(지수 백오프, 시도 제한, 오류 유형 확인)을 유연하게 결합할 수 있습니다. RequestInterceptor는 두 프로토콜을 모두 준수하는 단일 구조체 또는 클래스로 구현됩니다.
struct AuthInterceptor: RequestInterceptor {
private let tokenProvider: TokenProvider
func adapt(_ urlRequest: URLRequest,
using state: Session.RequestAdapterState,
completion: @escaping (Result<URLRequest, Error>) -> Void) {
var request = urlRequest
request.setValue("Bearer \(tokenProvider.token)",
forHTTPHeaderField: "Authorization")
completion(.success(request))
}
func retry(_ request: Request,
for session: Session,
dueTo error: Error,
completion: @escaping (RetryResult) -> Void) {
if error is URLError {
completion(.retryWithDelay(1))
} else {
completion(.doNotRetry)
}
}
}
AuthInterceptor는 Swift에서 adapt를 통해 Bearer 토큰을 추가하고, 1초 지연으로 retry를 통해 URLError(네트워크 손실, 시간 초과) 시 자동으로 요청을 재시도합니다. 적응과 재시도를 분리하면 독립적으로 테스트할 수 있습니다 — 재시도 로직에 영향을 주지 않고 적응에 대한 단위 테스트를 작성할 수 있습니다. Alamofire (2026)에 따르면, RequestInterceptor는 iOS 프로젝트에서 인증 관리를 중앙화하는 표준 방법입니다.
로깅 — 가장 일반적인 사용 사례. Interceptor는 URL, 메서드, 헤더, 요청 및 응답 본문, 실행 시간을 기록합니다. 디버그 빌드에서는 Charles Proxy와 Wireshark를 대체하고, 릴리스 빌드에서는 요청 컨텍스트가 포함된 충돌 보고서에 도움이 됩니다. OkHttp는 logging-interceptor 라이브러리의 HttpLoggingInterceptor를 NONE, BASIC, HEADERS, BODY 레벨로 사용합니다. BODY 레벨은 전체 요청 및 응답 본문을 로깅합니다 — 디버그에서만 사용하세요.
액세스 토큰이 만료되면 Interceptor가 401 응답을 가로채고, 토큰 갱신 API를 호출하며, 새 토큰으로 원래 요청을 재시도합니다. OkHttp에서는 Authenticator 또는 response.code 확인이 있는 사용자 정의 Interceptor를 통해 구현됩니다. Authenticator는 응답 헤더에만 접근할 수 있지만, Interceptor는 전체 본문에 접근할 수 있습니다. Alamofire에서는 RequestRetrier를 통해 토큰 갱신 후 .retry를 반환합니다. OWASP (2026)에 따르면, Interceptor를 통한 자동 토큰 갱신은 자격 증명 유출 위험을 줄입니다.
Content-Type, Accept-Language, User-Agent, Device-ID — 모든 요청에 필요한 헤더. Interceptor는 각 API 메서드에서 중복 없이 중앙에서 추가합니다. User-Agent는 앱 시작 시 한 번 형성됩니다: “AppName/1.0 (Android 14; Pixel 8)”. Accept-Language는 기기 시스템 언어에서 가져옵니다. Alamofire (2026)에 따르면, Interceptor를 통한 중앙 집중식 헤더 관리는 잘못된 헤더 오류를 30% 줄입니다.
| 시나리오 | OkHttp | Alamofire |
|---|---|---|
| 로깅 | HttpLoggingInterceptor | EventMonitor |
| 인증 토큰 | Authenticator + Interceptor | RequestInterceptor |
| 헤더 | addInterceptor | RequestAdapter |
| 재시도 | 재시도가 있는 Interceptor | RequestRetrier |
| 캐싱 | CacheInterceptor | CachedResponseHandler |
OkHttp에서 Interceptor를 추가하는 순서는 전체 체인의 동작을 결정합니다. 가장 먼저 추가된 인터셉터는 요청 전송 시 가장 먼저, 응답 수신 시 가장 마지막에 실행됩니다. 로깅의 경우 Interceptor를 먼저 추가하세요 — 다른 인터셉터의 모든 수정 사항이 포함된 최종 요청을 볼 수 있습니다. 압축의 경우 마지막에 추가하여 압축이 최종 데이터에 적용되도록 합니다. 인증의 경우 재시도 전에 추가하여 다음 시도 전에 토큰이 갱신되도록 합니다.
릴리스 빌드에서는 BuildConfig.DEBUG 또는 의존성 주입을 통해 로깅을 비활성화하세요. 캐싱에는 addNetworkInterceptor를 사용하세요 — Network Interceptor는 서버의 Cache-Control 헤더를 보고 캐싱 정책을 올바르게 해석합니다. 인증에는 addInterceptor(Application)를 사용하세요 — 이렇게 하면 인증 헤더를 보내지 않아야 하는 타사 도메인으로의 리디렉션 시 재가로채기를 방지합니다. okhttp-testing-support의 MockWebServer를 사용하여 각 Interceptor를 격리하여 테스트하세요 — 요청을 가로채고 미리 준비된 응답을 반환하므로 실제 서버 없이 인터셉터 로직을 검증할 수 있습니다.
각 Interceptor는 요청 시간에 약간의 지연을 추가합니다. 3-4개의 인터셉터(로깅, 인증, 압축, 캐싱)가 있는 일반적인 체인에서 오버헤드는 요청당 5밀리초 미만입니다. Interceptor가 차단 작업을 수행할 때 문제가 발생합니다: 동기 토큰 갱신 API 호출, 파일에 큰 로그 쓰기, 요청 본문 암호화. 이러한 모든 작업은 비동기식이거나 백그라운드 스레드에서 실행되어야 합니다. Square (2026)에 따르면, OkHttp는 Dispatcher 스레드 풀에서 Interceptor를 실행합니다 — 하나의 인터셉터를 차단하면 전체 체인이 지연됩니다.
자주 묻는 질문
addInterceptor(Application)는 애플리케이션과 OkHttp 사이에서 한 번 실행되며, 리디렉션이나 연결 압축을 보지 못합니다. addNetworkInterceptor(Network)는 각 네트워크 호출 시 OkHttp 내부에서 실행되며, 리디렉션, 재시도 및 압축 후 데이터를 봅니다. 로깅과 인증에는 Application, 캐싱에는 Network를 선택하세요.
인터셉터는 response.code == 401을 확인하고, Retrofit 또는 URLSession을 통해 비동기 토큰 갱신 API를 호출하고, 새 토큰을 저장한 후 원래 요청을 재시도합니다. OkHttp에서는 Basic Auth에 Authenticator를, 갱신이 있는 Bearer에 Interceptor를 사용합니다. Alamofire에서는 오류 유형 확인과 함께 retry를 사용합니다.
네 — Interceptor에서의 무거운 작업(큰 본문 로깅, 암호화, 동기 API 호출)은 응답 시간을 증가시킵니다. 비동기 콜백을 사용하고, BuildConfig.DEBUG를 통해 디버그 빌드에서만 로깅을 제한하며, intercept 메서드에서 차단 작업을 수행하지 마세요.
Authenticator는 401 응답을 위한 특수 인터셉터로, Basic Auth 또는 Bearer 토큰을 구현합니다. Authenticator는 요청 본문에 접근할 수 없으며 전송 전에 헤더를 수정할 수 없습니다 — 인증 오류 응답만 처리합니다. 반면 Interceptor는 실행의 모든 단계에서 요청을 수정할 수 있습니다.
OkHttp에서는 Interceptor를 OkHttpClient.Builder에 전달합니다 — 이 클라이언트의 모든 요청이 이를 통과합니다. Alamofire에서는 Session 구성에 RequestInterceptor를 추가합니다. 여러 클라이언트를 사용하는 경우(예: 다른 API용), Builder 패턴을 사용하여 공통 인터셉터가 있는 기본 Builder를 만듭니다.
요약
턴키 방식의 모바일 애플리케이션을 개발해 드립니다
IT Sectr는 2017년부터 스타트업과 기업을 위한 iOS 및 Android 애플리케이션을 만듭니다. 저희가 상담해 드리고 최적의 솔루션을 제안하겠습니다.