Okhttp는 REST API, HTTP 통신을 간편하게 구현할 수 있도록 다양한 기능을 제공해주는 라이브러리 입니다.
그리고 Okhttp는 Retrofit이라는 라이브러리의 베이스가 됩니다.
REST는 Representational State Transfer라는 용어의 약자로서 HTTP의 주요 저자 중 한 사람인 로이 필딩이 그 당시 웹(HTTP) 설계의 우수성에 비해 제대로 사용되지 못하는 모습에 웹의 장점을 최대한 활용할 수 있는 아키텍쳐로 REST를 발표하였고 그 아키텍쳐를 이용해 만든 API를 REST API라고 합니다.
특징을 정리하자면 다음과 같습니다.
라우팅이란? 클라이언트의 요청에 대한 결과을 어떻게 이어줄 것인가 하는 처리방법에 대한 것을 말합니다.
URI를 이용한 접근 : 모든 개체를 리소스로 보고, 리소스에 고유번호를 부여
URL 디자인 원칙 : 자원에 대한 처리를 주소에 나타내지 않는다(HTTP method는 내부적으로 처리하도록), 어떤 자원인지 주소에 명확하게 나타냅니다.
자원(URI)
메서드(HTTP METHOD)
표현
URL(Uniform resource Locator) - 통합 자원 식별자로 인터넷에 있는 자원을 나타내는 유일한 주소를 말합니다.
URI(Uniform resource Identifier) - 네트워크 상에서 자원 위치를 알려주기 위한 규약을 말합니다.
요청의 종류를 서버에 알리기 위해 사용하는 것을 말합니다.
메서드의 종류로는
가 있습니다.
Retrofit는 서버와 클라이언트 간 http 통신을 위한 인터페이스 입니다.
클라이언트가 서버에게 요청을 하고 서버는 클라이언트에 응답을 하는 과정 중간에서 매개체 역할을 해줍니다.
Okhttp는 서버와 HTTP,HTTP/2 프로토콜 통신을 위한 클라이언트 라이브러리인데 만약 Android에서 Okhttp를 사용하지 않고 HTTP로 통신하기 위해서는 다음과 같은 과정을 통해야합니다.
하지만 Okhttp는 이러한 부분을 해줍니다. 그래서 사용하는 과정에서 Retrofit을 사용하는데 Retrofit은 type-safe한 HTTP 클라이언트 라이브러리로 내부 코드에서 Okhttp 클라이언트를 디폴트로 선언하기에 base가 된다는 것입니다.
그러면 OkHttp3를 사용안하고 Retrofit만 쓰면 되는거 아니야?? 라고 할 수 있지만 몇 가지 상황에서는 직접 OkHttp를 사용할 필요가 있습니다.
// 코드 예시
val httpClient = OkHttpClient.Builder()
.addInterceptor { chain ->
val request = chain.request()
val newRequest = request.newBuilder()
.header("User-Agent", "MyCustomUserAgent")
.build()
chain.proceed(newRequest)
}
.cache(Cache(File("cacheDirectory"), 10 * 1024 * 1024))
.readTimeout(30, TimeUnit.SECONDS)
.build()
val retrofit = Retrofit.Builder()
.baseUrl("https://api.example.com/")
.client(httpClient)
.build()
OkHttpClient.Builder를 사용하여 사용자 정의 인터셉터를 추가하고, 캐시 전략을 설정하며 타임아웃을 설정합니다. 사용자 정의 인터셉터는 User-Agent라는 헤더를 추가했고 캐시 전략은 10MB 크기의 캐시 디렉토리를 사용합니다. 이렇게 함으로써 요청/응답을 수정하거나, 캐싱 전략을 조절하거나, 타임아웃 설정을 변경할 수 있습니다.
// 코드 예시
val client = OkHttpClient()
val request = Request.Builder()
.url("wss://example.com")
.build()
val listener = object : WebSocketListener() {
override fun onOpen(webSocket: WebSocket, response: Response) {
webSocket.send("Hello, WebSocket!")
}
override fun onMessage(webSocket: WebSocket, text: String) {
println("Received message: $text")
}
}
client.newWebSocket(request, listener)
client.dispatcher.executorService.shutdown()
OkHttp를 사용하여 웹소켓에 연결하고 메시지를 전송 및 수신합니다.웹소켓 리스너를 사용하여 웹소켓 이벤트를 처리할 수 있습니다. 연결이 시작되면 Listener에 설정한 메시지를 출력할 수 있도록 하였습니다. 그 후에는 받는 값을 수신받도록 코드가 작성되어 있습니다.
val dispatcher = Dispatcher().apply {
maxRequestsPerHost = 1
}
val client = OkHttpClient.Builder()
.dispatcher(dispatcher)
.build()
val request = Request.Builder()
.url("https://example.com/")
.build()
client.newCall(request).enqueue(object : Callback {
override fun onFailure(call: Call, e: IOException) {
// Handle error
}
override fun onResponse(call: Call, response: Response) {
// Handle response
}
})
OkHttpClient.Builder를 사용하여 Dispatcher를 설정합니다. 동일한 호스트에 대한 최대 요청 수를 제한함으로써 중복 요청을 제거할 수 있습니다. 이 경우, 각 호스트에 대한 최대한 요청 수를 1로 설정하여 한번 요청한 호스트에는 재요청을 안하도록 설정할 수 있습니다.
이러한 상황에서는 Retrofit이 제공하는 기능만으로는 부족하기에 OkHttp를 사용하여 더 많은 제어를 할 필요가 있습니다.