[Android] OkHttp & Retrofit

Minji Jeong·2022년 5월 12일
5

Android

목록 보기
14/39
post-thumbnail
안드로이드 스튜디오에서 네트워크 작업을 할 때 주로 사용하는 대표적인 라이브러리로 OkHttp, Retrofit이 있다. 요즘은 Retrofit을 주로 쓰고 부가적인 기능을 위해 OkHttpClient를 Retrofit 객체에 연결해서 사용하는 듯 한데, 개발을 하다보니 Retrofit이 더 좋은 것 같긴 한데 정확히 뭐가 더 좋은지 궁금하기도 하고, 이 참에 공부하면서 블로그에 남기고자 이렇게 글을 쓰게 되었다.

OKHttp vs Retrofit

둘 다 같은 회사(Square)에서 만든 HTTP 통신 라이브러리다. OkHttp는 REST API, HTTP 통신을 간편하게 구현할 수 있도록 여러가지 기능을 제공한다. 그리고 이러한 OkHttp를 기반으로 더 Type-safe하고, 더 직관적으로 사용할 수 있도록 인터페이스로 만들어진 게 Retrofit이다. 따라서 완전히 다르진 않지만, 지원 기능과 용도 면에서 어느정도 차이가 있다.

💡 Type-safe ?

예측가능한 결과만을 내는 것

먼저 이 두 라이브러리가 어떤 면에서 차이를 보이는지 코드를 통해 확인해보자. 미디엄에 이 둘의 차이를 잘 분석해놓은 글이 있어서 해당 글을 많이 참고했으니, 원문을 보고싶다면 아래 링크를 클릭해보자.

👍 https://medium.com/mobile-app-development-publication/okhttp-or-retrofit-for-android-fc00f7aa3daf

1. Network

먼저 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()

2. Result

다음으로 네트워크 통신 시, 반환되는 응답 객체에 대해 두 라이브러리 간 어떤 차이가 있는지 알아보자. 알다시피 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가 통신되는 모든 활동을 모니터링 할 수 있으며 서버 통신 시간 조절이 가능하다는 장점이 있다), 최고의 성능을 내기 위해서 둘 다 사용하는 게 보편적이다.

References

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

profile
Mobile Software Engineer

0개의 댓글