둘 다 같은 회사(Square)에서 만든 HTTP 통신 라이브러리다. OkHttp는 REST API, HTTP 통신을 간편하게 구현할 수 있도록 여러가지 기능을 제공한다. 그리고 이러한 OkHttp를 기반으로 더 Type-safe하고, 더 직관적으로 사용할 수 있도록 인터페이스로 만들어진 게 Retrofit이다. 따라서 완전히 다르진 않지만, 지원 기능과 용도 면에서 어느정도 차이가 있다.
먼저 이 두 라이브러리가 어떤 면에서 차이를 보이는지 코드를 통해 확인해보자. 미디엄에 이 둘의 차이를 잘 분석해놓은 글이 있어서 해당 글을 많이 참고했으니, 원문을 보고싶다면 아래 링크를 클릭해보자.
먼저 Retrofit부터 확인해보자. Retrofit에선 BASE URL을 인자로 전달하여 간단하게 객체를 생성한다.
Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create())
.baseUrl(BASE_URL)
.build()
다음으로 인터페이스를 생성하고, 원하는 요청 방식과 파라미터에 대해 정의한다.
interface wikiApiServe{
@GET(END_POINT)
fun hitCountCheckCall(
@Query(PARAM_ACTION) action: String,
@Query(PARAM_FORMAT) format: String,
@Query(PARAM_LIST) list: String,
@Query(PARAM_SRSEARCH) srsearch: String)
: Call<Model.Result>
}
이후 네트워크 호출을 할 때마다 미리 정의해놓은 인터페이스 메서드에 필요한 데이터들을 전달해서 호출할 수 있다.
wikiApiServe.hitCountCheckCall(
VALUE_QUERY, VALUE_JSON, VALUE_SEARCH, searchString)
반면 OkHttp에선 다음과 같이 수동으로 요청을 구성해야 한다. 물론 한다면 할 수야 있지만 URL을 입력하는 과정에서 오타가 날 수도 있고, 무엇보다 가독성 면에서 좋지 못하다.
val request = Request.Builder().url("$BASE_URL$BASE_PATH/?" +
"$PARAM_ACTION=$VALUE_QUERY&$PARAM_FORMAT=$VALUE_JSON&" +
"$PARAM_LIST=$VALUE_SEARCH&$PARAM_SRSEARCH=$searchString")
.build()
다음으로 네트워크 통신 시, 반환되는 응답 객체에 대해 두 라이브러리 간 어떤 차이가 있는지 알아보자. 알다시피 JSON은 자바나 코틀린에서 바로 사용할 수 있는 데이터 형식이 아니기 때문에 JSON을 데이터클래스로 변환해줄 컨버터를 사용해야 한다. 객체 생성 시 GSON Converter Factory를 연결했다면, Retrofit은 통신 성공 시 응답 객체의 body를 별도의 변환 과정 없이 바로 사용할 수 있다.
call?.enqueue(
object : Callback<Model.Result> {
override fun onFailure(call: Call<Model.Result>, t: Throwable) {
...
}
override fun onResponse(call: Call<Model.Result>,
response: Response<Model.Result>) {
response.body()?.let { //바로 사용 가능 }
}
반면 OkHttp에서는 반환받은 JSON 객체를 데이터클래스로 바로 변환해주지 못하기 때문에, 별도의 과정을 통해 직접 변환해서 사용해야 한다.
client.newCall(request).enqueue(
object : okhttp3.Callback {
override fun onFailure(call: okhttp3.Call, e: IOException) {
...
}
override fun onResponse(call: okhttp3.Call,
response: okhttp3.Response) {
response.body()?.let {
val result = Gson().fromJson(it.string(),
Model.Result::class.java)
useResult(result)
}
}
)
또한 결과가 반환된 직후 메인스레드에서 바로 사용할 수 있냐 없냐에도 차이가 있다. Retrofit의 경우 enqueue를 사용하면 네트워크 호출이 자동으로 백그라운드에서 이루어진다. 그리고 결과가 반환되면 자동으로 메인스레드에 전달되기 때문에 Toast와 같은 UI 관련 메서드에 결과값을 사용할 수 있다.
override fun onResponse(call: Call<Model.Result>,
response: Response<Model.Result>) {
Toast.makeText(...).show()
})
OkHttp도 enqueue를 사용하면 네트워크 호출이 자동으로 백그라운드에서 수행되지만, 결과가 반환되어도 여전히 백그라운드에 남아있기 때문에 결과값을 메인스레드에서 사용하기 위해서 runOnUiThread를 사용해야 한다.
override fun onResponse(call: okhttp3.Call,
response: okhttp3.Response) {
runOnUiThread {
Toast.makeText(...).show()
}
}
결론적으로, Retrofit을 사용하면 OkHttp로는 얻지 못하는 다음의 장점들을 느낄 수 있다.
1. 어노테이션(Annotation) 사용으로 코드의 가독성이 좋고, 직관적인 설계가 가능하다.
2. 통신 결과값을 JSON으로 변환해줄 필요가 없다.
3. 결과값을 메인스레드에서 바로 사용할 수 있다.
Retrofit은 훌륭한 가독성과 역직렬화할 필요가 없다는 면만 봐도 아주 쓸만한 라이브러리다. 그렇다고 무조건 Retrofit만 사용하는것은 아니다. Retrofit 역시 HTTP 통신을 할 때 OkHttp에 의존하고 있고, 두 라이브러리 모두 각각 이점을 가지고 있기 때문에(OkHttp의 경우 OkHttp Client에 네트워크 Intercepter를 통해 API가 통신되는 모든 활동을 모니터링 할 수 있으며 서버 통신 시간 조절이 가능하다는 장점이 있다), 최고의 성능을 내기 위해서 둘 다 사용하는 게 보편적이다.
https://medium.com/mobile-app-development-publication/okhttp-or-retrofit-for-android-fc00f7aa3daf
https://stackshare.io/stackups/okhttp-vs-retrofit
https://stackoverflow.com/questions/55075322/why-addconverterfactory-is-need-in-retrofit
https://stackoverflow.com/questions/16902716/comparison-of-android-networking-libraries-okhttp-retrofit-and-volley
https://imomelet.tistory.com/47
https://goni95.tistory.com/79