개요
노션에 정리해놓은 안드로이드 앱 개발 지식에 대한 내용을 하나씩 블로그로 옮기고 있는 중이다. 옮기면서 복습까지 할 수 있으니까 좋네.
오늘은 안드로이드에서 HTTP 통신을 위해 사용하는 라이브러리인 Retrofit2와 OkHTTP3에 대한 내용에 대해 정리해보겠다.
1. Retrofit2란?
Retrofit2는 Square 사에서 개발한 REST API를 호출하는 HTTP 클라이언트 라이브러리이다.
인터페이스 기반으로 API를 정의하고 간편하게 네트워크 요청을 처리할 수 있다.
* REST API
-> Representational State Transfer (REST) 아키텍처를 기반으로 한 웹 서비스 인터페이스이다.
-> 클라이언트와 서버 간의 통신을 HTTP 프로토콜을 이용해 수행한다.
-> 자원의 CRUD(Create, Read, Update, Delete) 작업을 HTTP 메서드(GET, POST ,PUT, DELETE)로 처리한다.
-> URL을 통해 리소스를 명확하게 식별하고, 무상태성(Stateless) 원칙을 따른다.
1-1. Retrofit 특징
1) Type-Safe한 HTTP 클라이언트
-> API 인터페이스를 통해 요청을 정의하고, 지정된 데이터 모델로 변환한다.
2) 비동기 및 동기 네트워크 요청을 지원
-> enqueue()로 비동기 요청
-> execute()로 동기 요청
3) OkHttp를 기반으로 확장 가능
-> OkHttp를 네트워크 계층(IP 전달)로 활용하며 그 위에 구축된다.
-> OkHttp의 Interceptor를 활용해 네트워크 요청을 조작할 수 있다.
4) 코루틴 및 Flow 지원
-> suspend fun을 활용해 Coroutine에서 안전하게 네트워크를 호출할 수 있다.
5) Dynamic Proxy 활용
-> Dynamic Proxy는 런타임에 동적으로 인터페이스의 구현체를 생성하는 기법이다.
-> 즉, 실행 중에 Proxy 객체를 생성해 메서드 호출을 가로채거나 추가적인 기능을 수행할 수 있다.
1-2 기본 사용법
Retrofit 설정 및 API 인터페이스 정의
interface ApiService {
@GET("users/{id}")
suspend fun getUser(@Path("id") userId: Int): Response<User>
}
val retrofit = Retrofit.Builder()
.baseUrl("https://api.example.com/")
.addConverterFactory(GsonConverterFactory.create())
.build()
.create(ApiService::class.java)
: Retrofit.Builder()
-> Retrofit 객체를 생성하기 위해 빌더 패턴을 사용한다.
: baseUrl
-> 그 뒤 baseUrl을 통해 기본 URL을 설정한다.
: addConverterFactory(GsonConverterFactory.create())
-> 서버에서 응답받은 데이터를 자동으로 JSON -> 객체로 변환해준다.
-> GsonConverterFactory.create()를 사용한다면 Gson을 활용한 JSON 변환이 가능해진다.
: build()
-> 설정한 내용을 기반으로 Retrofit 객체를 생성한다.
: create(ApiService::class.java)
-> 만들어 놓은 ApiService 인터페이스를 기반으로해서 Retrofit이 동적 프록시 객체를 생성한다. ( 원래 코틀린은 인터페이스를 객체화 시킬 수 없지만 동적 프록시를 통해 런타임에 Interface에 선언한 메서드 및 어노테이션 등을 Reflection을 사용해 처리한다.)
-> .create() 메소드를 분석했을 때, 위의 사진과 같이 영어가 쭉쭉 나오는데 중요한 부분은
-> "Create an implementation of the API endppoints defined by the code service interface"
-> 인터페이스에 정의된 API 엔드포인트들의 구현체를 생성한다.
그 뒤 enqueue나 execute를 통해 비동기, 동기적으로 받아오면 된다. 단, 코틀린을 사용할 경우 비동기 처리가 가능하기 때문에 굳이 enqueue를 쓰지 않아도 비동기 처리가 가능하다.
비동기 네트워크 요청 (enqueue)
val call = apiService.getUser(1)
call.enqueue(object : Callback<User> {
override fun onResponse(call: Call<User>, response: Response<User>) {
if (response.isSuccessful) {
Log.d("응답", response.body().toString())
}
}
override fun onFailure(call: Call<User>, t: Throwable) {
Log.e("에러", t.message.toString())
}
})
동기 네트워크 요청 (execute)
val response = apiService.getUser(1).execute()
if (response.isSuccessful) {
val user = response.body()
}
2. OkHTTP3
OkHttp는 실제로 HTTP 요청을 보내고, 응답을 받는 네트워크 엔진의 역할을 한다.
그렇기에 Retrofit은 내부적으로 OkHttp를 기본 네트워크 클라이언트로 사용한다.
Retrofit 내부적으로 쓰고 있다매 근데 왜 둘이 같이쓰냐?
-> OkHttp Client의 옵션 사용에 다양한 이점이 있다.
-> 네트워크 Interceptor를 통해 API가 통신하는 모든 활동을 모니터링 할 수 있다.
-> 커넥션 타임아웃을 통해 API 호출의 경과 시간에 따라 중단할 수 있다.
-> Retrofit의 파라미터, 쿼리, 헤더 등의 매핑작업과 결과 처리 작업 등의 반복되는 작업들을 편리하게 처리할 수 있다.
즉, Retrofit과 OkHttp3 둘의 장점을 모두 사용하기 위해 함께 쓰는 것이다.
1-1. OkHttp Interceptor
서버 요청과 응답을 중간에서 가로채(Interceptor) 원하는 값을 끼워서 요청하거나 응답을 원하는 형태로 변형할 수 있다.
: Application Interceptor
-> 어플리케이션과 OkHttp 코어 사이에서 요청 및 응답을 가로채는 역할을한다.
-> 주로 로그 추가, 공통 헤더 추가, 인증 토큰 처리, 캐싱 등을 담당한다.
-> 한 번만 실행되기 때문에, 동일한 요청을 재시도해도 같은 인터셉터가 다시 호출되지 않는다.
val client = OkHttpClient.Builder()
.addInterceptor { chain ->
val originalRequest = chain.request()
val newRequest = originalRequest.newBuilder()
.header("Authorization", "Bearer your_access_token")
.build()
chain.proceed(newRequest)
}
.build()
-> 위의 코드는 헤더에 인증 토큰을 추가하는 예제이다.
: Network Interceptor
-> 실제 통신에서 서버와 OkHttp 코어 사이에서 요청 및 응답을 가로채는 역할을 한다.
-> 요청이 네트워크를 통과하기 전후에 추가적인 조작을 수행할 수 있다.
-> 주로 응답 캐싱, 압축 해제, 로깅 등에 활용된다.
-> 리다이렉트와 같은 네트워크 이벤트도 감지할 수 있다.
val client = OkHttpClient.Builder()
.addNetworkInterceptor { chain ->
val request = chain.request()
val response = chain.proceed(request)
// 응답을 가로채서 로그 출력
println("Response received: ${response.code}")
response
}
.build()
실행 순서
Application Interceptor -> Network Interceptor -> 네트워크 -> Network Interceptor -> Application Interceptor
1-2. Retrofit과 OkHttp3 혼합
private val client = OkHttpClient.Builder()
.addNetworkInterceptor(commonNetworkInterceptor)
.build()
private val retrofit = Retrofit.Builder()
.baseUrl(BASE_URL)
.client(client)
.addConverterFactory(GsonConverterFactory.create())
.build()
OkHttp 또한 인스턴스를 빌더 패턴을 통해 생성해주고, 이를 client 메서드에 파라미터로 넣어주면 된다.
참고
https://joycehong0524.medium.com/android-studio-retrofit2-기본-사용법-retrofit-의문점-풀어헤치기-스압-f150db436add
'Android > Android' 카테고리의 다른 글
[Android] Proguard란? (1) | 2025.02.13 |
---|---|
[Android] 안드로이드 OS 구조 (0) | 2025.02.09 |
[Android] 컴포넌트 - Broadcast Receiver (1) | 2025.01.27 |
[Android] 컴포넌트 - ContentProvider (0) | 2025.01.23 |
[Android] LaunchMode (0) | 2024.10.31 |