Android (안드로이드)

[Android] HTTP 통신 라이브러리 비교 / Volley · OkHttp · Retrofit

Oscar:) 2024. 1. 26. 14:04

 

 

3차례에 걸친 지난 포스팅에서 알아보았던

3가지 HTTP 통신 라이브러리를 비교하는 시간을 가져보겠다.

 

 

 


 

 

비교해볼 항목은 다음과 같다.

 

- 전체적인 사용법 (구현 난이도 파악)

- 백그라운드 스레드 & 메인 스레드 전환 처리

- JSON 자동 파싱 처리

- Type Safe

 

 

사용법 한 눈에 비교하기

 

✅ Volley

 

전체적인 코드는 다음과 같다.

String url = "http://...";

RequestQueue requestQueue = Volley.newRequestQueue(this);

StringRequest stringRequest = new StringRequest(Request.Method.GET, url,
    new Response.Listener<String>() {
        @Override
        public void onResponse(String response) {
        // TODO
        }
    }, new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError error) {
        // TODO
        }
    });

requestQueue.add(stringRequest);

 

 

요약)

1. RequestQueue 객체 초기화
2. Request 객체 초기화
3. RequestQueue에 Request 추가


*Request 초기화 시 Http Method · 요청할 주소 · 응답 리스너 지정


+ 요청 시 데이터 보내기
HashMap에 데이터 담아서 getParams() 메서드로 전송 등

 

 

 

다음과 같은 그림으로 표현할 수 있다.

 

 

 

비교적 구조가 단순해서 사용법을 익히기 쉽다.

 

 


 

✅ OkHttp

 

전체적인 코드는 다음과 같다.

String url = "http://...";

OkHttpClient client = new OkHttpClient();

Request request = new Request.Builder()
    .url(url)
    .get()
    .build();

client.newCall(request).enqueue(new Callback() {
    @Override
    public void onFailure(Call call, IOException e) {
        // TODO
    }
    @Override
    public void onResponse(Call call, Response response) throws IOException {

        runOnUiThread(new Runnable() {
            @Override
            public void run() {
            // TODO
            }
        });
        
    }
});

 

 

 

요약)

1. OkHttpClient 객체 초기화
2. Request 객체 초기화
3. OkHttpClient의 newCall() 메서드에 Request 지정 후 전송


* Request 초기화 시 Http Method · 요청할 주소 지정
* newCall() 메서드가 Call 객체를 반환하기에 Callback을 받아서 응답 후처리
* 응답 후 메인 스레드 자동 전환 x - UI 작업은 runOnUiThread()에서 처리


+ 요청 시 데이터 보내기
FormBody.Builder에 데이터 담아서 RequestBody로 래핑하여
Request에 추가하는 방식 등

 

 

 

다음과 같은 그림으로 표현할 수 있다.

 

 

 

 


 

✅ Retrofit

 

전체적인 코드는 다음과 같다.

// Activity

String url = "http://...";

Gson gson = new GsonBuilder().setLenient().create();

Retrofit retrofit = new Retrofit.Builder()
    .baseUrl(url)
    .addConverterFactory(ScalarsConverterFactory.create())
    .addConverterFactory(GsonConverterFactory.create(gson))
    .build();

RetrofitInterface retrofitInterface = retrofit.create(RetrofitInterface.class);
Call<Data> call = retrofitInterface.getData(name, age);

call.enqueue(new Callback<Data>() {
    @Override
    public void onResponse(@NonNull Call<Data> call, @NonNull Response<Data> response) {
    // TODO
    }
    @Override
    public void onFailure(Call<Data> call, Throwable t) {
    // TODO
    }
});


// Interface

@GET("세부 URL")
Call<Data> getData (
    @Query("name") String name,
    @Query("age") String age
);


// Data Class

@Expose
@SerializedName("name") String name;
@Expose
@SerializedName("age") String age;

public String getName() { return name; }
public String getAge() { return age; }

 

 

 

요약)

1. Retrofit 객체 초기화
2. Retrofit.create() 메서드로 Interface 객체 초기화
3. Interface의 메서드로 Call 객체 초기화
4. Call 객체로 요청 전송


* Retrofit 객체 초기화 시 변환기 장착 (Gson, Scalars 등)
* Call 객체 생성 시 타입 지정 (위 예제에서는 데이터 클래스)
* Interface에서 URL 세부경로 · Http Method 지정
* 요청 후 Callback을 받아서 응답 후처리


+ 요청 시 데이터 보내기
Interface에서 처리

 

 

 

다음과 같은 그림으로 표현할 수 있다.

 

 

 

인터페이스와 데이터 클래스 등

세팅해야 할 파일도 많고, 구조가 비교적 복잡하다.

 

 


 

요청 시 네트워크 스레드 자동 생성 + 응답 반환 시 메인 스레드 자동 전달 유무

 

 

안드로이드에서 통신을 하기 위해서는 지켜야할 규칙이 있다.

 

 

- 네트워크 작업은 기본적으로 백그라운드 스레드에서 동작해야만 한다.

 

- 네트워크 작업 후, 그 결과를 UI에 표현할 때는 메인 스레드에서 동작해야만 한다.

 

 

 

이제 라이브러리를 비교해보자.

 

 

✅ Volley, Retrofit

 

요청 시 : 자동으로 백그라운드 스레드에서 작업

응답 후 : 자동으로 메인 스레드로 돌아가서 처리

 

 


 

✅ OkHttp

 

요청 시 : 자동으로 백그라운드 스레드에서 작업

응답 후 : 자동으로 메인 스레드 전환이 안 되어서, 별도의 스레드 작업 필요

 

 


 

 

 3가지 라이브러리 모두,

요청 시 네트워크 작업은 자동으로 백그라운드 스레드에서 처리한다.

 

그래서 굳이 작성할 필요가 있나 싶지만, 이전에 사용했던

HttpURLConnection 같은 경우 요청 시 · 응답 후 모두 별도의 스레드 작업이 필요했다.

 

당연한 일이 아니라는 것을 인지해야 한다.

 

 

 


 

JSON 데이터 파싱

 

 

대부분의 API는 JSON 형식으로 날아온다.

JSON을 파싱하는 방법도 중요한 요소 중 하나다.

 

 

차이점을 확인해보자.

 

 

✅ Volley, OkHttp

 

응답 후 받은 JSON 데이터를 별도로 파싱해야 한다.

 

 


 

✅ Retrofit

 

Retrofit 객체에 Gson 컨버터를 장착하고,

데이터 클래스에 @SerializedName 어노테이션을 사용함으로써

 

별도로 JSON 데이터를 파싱할 필요 없다.

 

 


 

Type Safe

 

 

단순히 직역하면 '안전한 타입'

즉 '타입에 안정적이다' 라고 생각할 수 있다.

 

 

Java는 타입 때문에 런타임 시 예외가 발생하는 것에 민감하기 때문에

기본적으로 Type Safe를 정말 중요하게 생각한다.

 

하다못해 변수를 선언할 때도 int / String 등 타입을 지정해주고,

ArrayList를 제네릭 없이 생성하면 경고가 표시되기도 한다.

 

 

 

이제 라이브러리를 비교해보며 Type Safe를 확인해보자.

 

 

✅ Volley

 

Request를 선언할 때부터 StringRequest / JsonObjectRequest 등

요청과 응답에 대한 타입을 지정해 준다.

 

 


 

✅ OkHttp

 

별도로 타입을 지정해 주는 곳이 없다.

 

 


 

✅ Retrofit

 

Call 객체에 제네릭(<>)으로 타입을 지정하여

응답을 어떻게 받을 것인지 정할 수 있다.

 

 


 

종합

 

 

위에서 비교해본 내용을 표로 간단히 정리해보면 다음과 같다.

 

  Volley OkHttp Retrofit
숙련 난이도 비교적 쉬움 보통 비교적 어려움
네트워크 통신 시 자동으로 백그라운드 스레드 처리 O O O
응답 반환 시 자동으로 메인 스레드 전달 처리 O X O
JSON 자동 파싱 유무 X X O
Type Safe O X O

 

 

비교한 내용만 보았을 때,

Retrofit이 전반적으로 좋은 평가를 받았다.

 

 


 

기타 1 - Retrofit과 OkHttp의 관계

 

 

위 [종합] 탭에서 표를 보면, OkHttp가 압도적으로 빈약해 보일 수 있다.

하지만 OkHttp는 현재까지도 사랑 받는 라이브러리다.

 

그 이유는 Retrofit과의 관계에서 알 수 있다.

 

 

Retrofit은 OkHttp의 상위 호환이라며 출시되었다.

 

그럼 대부분의 사람들은 다음과 같이 생각할 수 있다.

 

'Retrofit이 OkHttp의 모든 기능을 포함하고 있지 않을까?'

 

 

 

 

 

하지만 실제로 사용하다 보면, 위 그림은 틀렸다는 것을 알 수 있다.

 

두 라이브러리는 교집합이 있을 뿐이다.

 

 

 

 

대표적인 예시로, OkHttp에서는 Interceptor 클래스를 제공한다.

 

Interceptor는 통신 과정을 모니터링할 수 있게끔 해주는 클래스다.

 

 

하지만 OkHttp의 상위 호환인 Retrofit에서는 Interceptor를 사용할 수 없다.

 

OkHttpClient okHttpClient = new OkHttpClient.Builder()
    .addInterceptor(new Interceptor() {
    ...
    })
    .build();

Retrofit retrofit = new Retrofit.Builder()
    .client(okHttpClient)
    .build();

 

위 예시처럼, OkHttpClient를 만들고 거기에 Interceptor를 붙인 후

Retrofit에 OkHttpClient를 붙여 사용해야 한다.

 

 

 

또 다른 예시로, OkHttp에서는 통신 시간 제한에 관련된 함수도 제공하는데

Retrofit에서는 제공하지 않는다.

 

이것도 위 Interceptor와 마찬가지로 사용할 수 있다.

OkHttpClient okHttpClient = new OkHttpClient.Builder()
    .connectTimeout(30, TimeUnit.SECONDS)
    .readTimeout(30, TimeUnit.SECONDS)
    .build();

Retrofit retrofit = new Retrofit.Builder()
    .client(okHttpClient)
    .build();

 

 

이렇듯, 아무리 각광받는 Retrofit도 일부 기능은 OkHttp에서 가져오게끔 설계되었다.

 

그래서 이 2개의 라이브러리를 함께 사용하는 프로젝트가 많다.

 

 

 


 

기타 2 - 많은 개발자가 Retrofit을 사용하는 이유

 

 

위에서 3가지 라이브러리를 비교해 보았고,

각자 어느정도의 강점은 가지고 있다는 것을 확인했다.

 

하지만 많은 개발자들은 Retrofit을 선호하고,

본인도 강력 추천한다.

 

그에 대한 이유는 위 [종합] 탭에서 비교한 점수가 높아서도 있지만,

다른 이유도 포함된다고 생각한다.

(개인적인 의견이 많이 들어있다)

 

 

 

✅ 트렌드

 

개발자라는 직종은 트렌드에 민감해야 한다.

Retrofit은 안드로이드 Http 통신에 있어서 트렌드라 볼 수 있다.

 

그렇게 생각하는 근거는 다음과 같다.

 

 

● 최신 기술

 

트렌드에 민감하다는 것은 최신 기술에 민감한 것과 밀접한 관련이 있다.

 

 

각 라이브러리의 출시 일자는 다음과 같다.

 

OkHttp : 2013-05-06

Volley : 2013-05-21

Retrofit : 2016-03-12

 

*OkHttp3 / Retrofit2 기준

 

상용화 기준으로 Retrofit2가 압도적이다.

 

 


 

 

● Google 공식 권장

 

Retrofit은 Square 사에서 만들었다.

그리고 Google은 Volley를 만들었다.

 

하지만 Google은 자기 회사의 기술이 아닌 Retrofit을 선택했다.

 

자신의 기술을 포기하고 다른 기술을 선택하는 것도 모자라, 널리 홍보하고 있다.

 

 

다음은 안드로이드 공식 문서 - HTTP 통신 파트다.

 

 

여러 라이브러리 중, Retrofit이 제일 상단에 작성되어 있다.

 

 

 

다음은 안드로이드 공식 문서의 앱 권장 아키텍처다.

 

 

Retrofit을 통신에 사용하라고 권장하는 것을 확인할 수 있다.

 

 

우리는 안드로이드 개발자로서,

Google에서 권장하는 방식을 따라야할 최소한의 의무가 있다.

 

 


 

 

● 기업이 선호하는 라이브러리

 

다음은 구인구직 사이트에서 캡쳐해 온 일부 내용이다.

 

 

안드로이드 개발 시장에서는 Retrofit 사용 경험을 높게 평가한다.

= 현재 대다수의 안드로이드 개발자는 Retrofit을 사용한다.

 

 


 

✅ 현업 개발자 대상 투표

 

실제로 현업 개발에서 Retrofit을 사용하는 비중을 확인해 보았다.

 

안드로이드 개발자 지인 8명에게 투표 조사를 했고, 결과는 다음과 같았다.

 

 

 

투표한 이유도 같이 받았는데, 정리하면 다음과 같다.

 

- JSON 자동 파싱이 정말 편리하다.

- 코드 세분화로 인해 유지·보수성 및 가독성이 좋다.

- Google에서 권장하기 때문에 사용한다.

- 최신 기술이 최고다.

 

 

 


 

 

 

이번 포스팅에서는 통신 라이브러리 3가지를 비교해 보았다.

 

거의 Retrofit을 사용해야 한다는 결과를 도출했지만,

어디까지나 권장일 뿐이다.

 

 

자신의 상황에 알맞은 라이브러리를 선택하는 것도 중요하다고 생각한다.