안드로이드 통신 라이브러리 요약

저는 안드로이드 앱을 개발하면 서버와 통신을 하기 위해서 편리한 방법인 Retrofit은 사용했다. 하지만 이러한 편리함을 알기 전에 왜 이렇게 편리하게 사용하는지 살펴보아야 할 것 같다.

초기에 안드로이드에서의 통신이라면 HttpClient를 사용하는 것이었다. HttpClient라고 해도 DefaultHttpClient라고 불리는 Apache HTTP Client와 AndroidHttpClient라는 Http Client 변종 등이 사용되고 있었다. 하지만, HttpClient에는 몇 가지 버그가 있어 2011년에는 Google의 Android Develpoers의 블로그에서 HttpUrlConnection이 권장되고 나서 이쪽이 주로 사용되고 있었다.

그후, Volley는 사용법이 복잡했던 HttpUrlConnection의 대안으로 Google이 만들었다는 것도 있고 표준 라이브러리로 사용되었다. Square의 OkHttp도 인기가 높고, 많이 사용되어왔다.

하지만 Android 5.1에서 HttpClient가 Deprecated된 후, HTTPClient에 의존하는 Volley도 Deprecated되었다. Square에서 만들어진 라이브러리인 OkHttp와 그 래퍼인 Retrofit은 단 하나 선택 같은 상태가 되었다.

Retrofit

Retrofit은 OkHttp의 상위 구현체로 enqueue와 excute를 사용하여 동기, 비동기 처리를 지원한다. 이러한 비동기 처리를 쉽게 지원하는 volley, retrofit 중에 무엇을 사용할지 고민했으나 인터페이스 내에 어노테이션으로 HTTP 메소드를 정의하여 그 행위를 알아보기 쉽게 표현하여 가독성이 높은 Retrofit을 사용했다. 추가적으로 Retrofit은 플러그인 형태로 클라이언트와 직렬화를 위한 convert를 선택할 수 있어 유지보수에 편하다.

반면에 volley는 이미지 캐시, 요청에 우선순위를 부여하는 등 추가적인 기능이 있지만 직렬화를 직접 세팅해줘야하고 멀티파트 업로드 시에도 리퀘스트의 재정의가 필요하다.

이렇듯 추가적인 기능이 더 많은건 volley이지만 간편하고 유지보수에 능하며 좀 더 REST api에 적합한 라이브러리라 생각되어 Retrofit을 사용했다.

Retrofit을 사용한 이유?

서버와 통신을 하려면 Http 통신을 해야한다. 기본적으로 HttpUrlConnection을 이용한 네트워크 통신이 있지만 매번 connection 설정, input / output stream 생성 및 할당 등 반복적인 작업이 발생한다. 이것을 도와주는 라이브러리가 Okhttp이다. 나는 Okhttp의 존재를 알기만 했고 사용해보지는 않았다.

Retrofit의 장점은 속도, 편의성, 가독성이 있다. 가장 비교하기 좋은 Okhttp는 사용시 대개 Asynctask를 통해 비동기로 실행하게 되는데 Asynctask가 성능상 느리다는 이슈가 있었다. Retrofit에서는 Asynctask를 사용하지 않고 자체적인 비동기 실행과 스레드 관리를 통해 속도를 훨씬 빠르게 끌어올렸다. 약 3~10배 차이가 난다고 한다.

또한 Okhttp에서도 쿼리스트링, request, response 설정 등 반복적인 작업이 필요한데, Retrofit에서는 이런 과정을 모두 라이브러리에 넘겨서 처리하도록 하였다. 따라서 사용자는 함수 호출시에 파라미터만 넘기면 되기에 훨씬 작업량이 줄어들고 사용하기 편리하다.

마지막으로 가독성이 매우 좋다. interface 내에 annotation을 사용하여 호출할 함수를 파라미터와 함께 정의해놓고, 네트워크 통신이 필요한 순간에 구현없이 해당 함수를 호출하기만 하면 통신이 이루어지기에 코드를 읽기가 매우 편하다. Asynctask를 쓰지 않기에 불필요하게 코드가 길어질 필요도 없으며, 콜백 함수를 통해 결과가 넘어오도록 되어있어 매우 직관적인 설계가 장점이다.

네트워크 통신에 Volley라는 라이브러리도 있지만 몇가지 문제점이 있었다. StringRequest 생성시 파라미터 값을 encoding해주어야 하는 불편함과 통신 실패시 ErrorResponse 안에 ResponseBody가 담기지 않는 문제가 있다.

구현 방법

application 클래스를 상속받은 ApplicationController라는 클래스를 만들고 싱글톤으로 구현하여 onCreate() 내부에 레트로핏 빌더를 이용해 클라이언트와 컨버터를 설정하고 인터페이스를 선택한다.

application 클래스를 상속받은 이유는?
메인 액티비티의 통신 부 이전에 retrofit에 대한 세팅을 하기 위해 상속받았다. application 클래스는 애플리케이션 컴포넌트들이 공통으로 사용하는 공유 클래스이다. 해당 클래스를 상속받아 구현한 클래스의 onCreate 메소드는 시스템의 진입점이 되어 가장 먼저 실행된다.

동기와 비동기란?

데이터를 받는 방식인 동기와 비동기. 이 둘의 개념에 대해서 알고 넘어가자.

  1. 동기(synchronous : 동시에 일어나는)

동기는 말 그대로 동시에 일어난다는 뜻이다. 요청과 그 결과가 동시에 일어난다는 약속인데, 바로 요청을 하면 시간이 얼마가 걸리던지 요청한 자리에서 결과가 즉시 주어져야 한다.

  • 요청과 결과가 한 자리에서 동시에 일어남
  • A 노드와 B 노ㄷ 사이의 작업 처리 단위를 동시에 맞추겠다.
  • 동기적 일처리 방식 : 순차적으로 일을 스스로 끝내 나가는 방식
  1. 비동기(Asynchronous : 동시에 일어나지 않는)

비동기는 동시에 일어나지 않는다를 의미한다. 요청과 결과가 동시에 일어나지 않을거라는 약속이다.

  • 요청한 결과가 그 자리에서 결과가 주어지지 않는다.
  • 노드 사이의 작업 처리 단위를 동시에 맞추지 않아도 된다.
  • 비동기적 일처리 방식 : 해야할 일을 위임하고 기다리는 방식

동기와 비동기는 상황에 따라서 각각의 장단점이 존재한다.
동기방식은 설계가 매우 간단하고 직관적이지만 결과가 주어질 때까지 아무것도 못하고 대기해야 하는 단점이 있고,
비동기방식은 동기보다 복잡하지만 결과가 주어지는데 시간이 걸리더라도 그 시간 동안 다른 작업을 할 수 있으므로 자원을 효율적으로 사용할 수 있다는 장점이 있다.

동기와 비동기 방식의 예는 아래의 블로그를 참고하자.

공부해서 남주자

참고