OkHttp & Retrofit

sumi Yoo·2022년 10월 29일
0

OKHttp vs Retrofit

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

💡 Type-safe ?
예측가능한 결과만을 내는 것

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가 통신되는 모든 활동을 모니터링 할 수 있으며 서버 통신 시간 조절이 가능하다는 장점이 있다), 최고의 성능을 내기 위해서 둘 다 사용하는 게 보편적이다.

https://velog.io/@jeongminji4490/Android-OkHttp-Retrofit

0개의 댓글