본문 바로가기
Android

[Doit 깡샘의 안드로이드 앱 프로그래밍 with 코틀린] 정리 18 - Retrofit 라이브러리

by 들풀민들레 2022. 2. 28.
본 글은 [Doit 깡샘의 안드로이드 앱 프로그래밍 with 코틀린 - 이지스퍼블리싱 (2022)] 의 내용을 발췌한 것입니다.

좀더 자세한 내용은 책 혹은 인강을 통해 확인해 주세요.

 

 

 

 

Retrofit은 스퀘어에서 만든 HTTP 통신을 간편하게 만들어 주는 라이브러리입니다. Retrofit은 1 버전과 2 버전이 있지만 Retrofit2가 2015년에 나왔으므로 지금 Retrofit이라고 하면 대부분 Retrofit2라고 봐도 무방합니다. 따라서 이 책에서 소개하는 Retrofit은 Retroft2를 의미합니다.

 

 

Retrofit을 이용하려면 먼저 프로그램의 구조를 이해해야 합니다. Retrofit은 네트워크 통신 정보만 주면 그대로 네트워크 프로그래밍을 대신 구현해 줍니다.
이 그림에서 인터페이스는 코틀린의 interface 키워드로 직접 만들어야 합니다. 그리고 인터페이스의 함수는 통신할 때 필요합니다. 즉, a(), b() 함수를 호출해서 통신하겠다는 의미입니다. 그런데 인터페이스에는 함수를 선언만 하며 통신할 때 필요한 어떤 코드도 담지 않습니다.


이렇게 만든 인터페이스를 Retrofit에 알려 주면 인터페이스 정보를 보고 실제 통신할 때 필요한 코드를 담은 서비스 객체를 만들어 줍니다. 여기서 서비스는 안드로이드 컴포넌트가 아니라 통신을 하게 해준다는 의미의 서비스입니다.
Retrofit은 우리가 알려 준 인터페이스를 바탕으로 서비스를 만들므로 인터페이스에 선언한 함수를 그대로 포함합니다. 이 서비스의 함수를 호출하면 Call 객체를 반환하는데, 이 Call 객체의 enqueue() 함수를 호출하는 순간 통신을 수행합니다.


지금까지 설명한 Retrofit 동작 방식을 정리하면 다음과 같습니다.

 

1. 통신용 함수를 선언한 인터페이스를 작성합니다.
2. Retrofit에 인터페이스를 전달합니다.
3. Retrofit이 통신용 서비스 객체를 반환합니다.
4. 서비스의 통신용 함수를 호출한 후 Call 객체를 반환합니다.
5. Call 객체의 enqueue() 함수를 호출하여 네티워크 통신을 수행합니다.

 

라이브러리 선언


Retrofit을 이용하려면 빌드 그래들의 dependencies 항목에 다음처럼 라이브러리를 등록해야 합니다.

 

implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.google.code.gson:gson:2.8.6'
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'

첫 번째 라이브러리는 Retrofit을 이용할 때 필수이며 나머지 2개는 다른 라이브러리를 이용할 수도 있습니다. Retrofit은 JSON이나 XML 데이터를 모델(VO 클래스) 객체로 변환해 주는데 이때 JSON, XML을 파싱하는 라이브러리가 필요합니다. 따라서 구글에서 만든 gson 라이브러리를 사용하고자 com.google.code.gson 을 등록했으며, Retrofit에서 gson을 이용해 모델 객체로 변환해 주는 com.squareup.retrofit2:converter-gson을 함께 등록했습니다. 만약 파싱 라이브러리가 바뀌면 converter 라이브러리도 그에 맞게 바꿔야 합니다. Retrofit은 다음과 같은 converter 라이브러리를 제공합니다.

 

• Gson: com.squareup.retrofit2:converter-gson
• Jackson: com.squareup.retrofit2:converter-jackson
• Moshi: com.squareup.retrofit2:converter-moshi
• Protobuf: com.squareup.retrofit2:converter-protobuf
• Wire: com.squareup.retrofit2:converter-wire
• Simple XML: com.squareup.retrofit2:converter-simplexml
• JAXB: com.squareup.retrofit2:converter-jaxb
• Scalars(primitives, boxed, and String): com.squareup.retrofit2:converter-scalars

 

모델 클래스 선언


모델 클래스란 서버와 주고받는 데이터를 표현하는 클래스입니다. 흔히 VOvalue-object 클래스라고도 하며 JSON, XML 데이터를 파싱해 모델 클래스 객체에 담는 것을 자동화해 줍니다. 만약 서버에서 넘어오는 JSON 데이터가 다음과 같다고 가정해 보겠습니다.

 

{
    "id": 7,
    "email": "michael.lawson@reqres.in",
    "first_name": "Michael",
    "last_name": "Lawson",
    "avatar": "https://reqres.in/img/faces/7-image.jpg"
}

원래는 JSON 데이터를 코드에서 직접 파싱해서 이용해야 하는데, 데이터를 담을 모델 클래스를 선언하고 클래스 정보만 알려 주면 모델 클래스의 객체를 알아서 생성하고 그 객체에 데이터를 담아 줍니다. 모델 클래스는 상위 타입에 제약이 없으므로 어떤 클래스를 상속받거나 인터페이스를 구현할 필요는 없습니다. 순전히 개발자가 작성하는 클래스입니다.
앞의 JSON 정보를 담을 모델 클래스는 다음처럼 작성할 수 있습니다.

 

data class UserModel(
    var id: String,
    @SerializedName("first_name")
    var firstName: String,
    // @SerializedName("last_name")
    var lastName: String,
    var avatar: String,
    var avatarBitmap: Bitmap
)

 

모델 클래스의 프로퍼티에 데이터가 자동으로 저장되는 기본 규칙은 데이터의 키와 프로퍼티 이름을 매칭하는 것입니다. 예를 들어 id라는 키값은 id 프로퍼티에 저장됩니다. 만약 키와 프로퍼티 이름이 다를 때는 @SerializedName이라는 애너테이션으로 명시해 주면 됩니다.


코드에서 주석으로 지정한 @SerializedName("first_name")의 의미는 first_name이라는 키의 데이터가 firstName 프러퍼티에 저장된다는 의미입니다. 그런데 키와 프로퍼티 이름이 다르더라도 밑줄 다음에 오는 단어의 첫 글자를 대문자로 바꾼 프로퍼티명이 있을 때는 @Serial izedName 애너테이션을 사용하지 않아도 됩니다. 예를 들어 키가 last_name이면 자동으로 lastName 프로퍼티에 저장됩니다.


모델 클래스를 만들 때 서버의 데이터와 상관없는 프로퍼티를 선언해도 됩니다. 코드를 보면 avatarBitmap이라는 프로퍼티를 선언했는데 서버로부터 넘어오는 JSON에는 이와 관련된 데이터가 없습니다. 이처럼 모델에 서버 연동과 상관없는 데이터를 담는 프로퍼티를 선언해도 됩니다.


서버의 데이터가 복잡할 때는 모든 데이터를 하나의 모델 클래스로 표현하지 않고 여러 클래스로 분리한 후 조합해서 사용할 수도 있습니다. 예를 들어 목록 화면을 구성하는 서버 데이터가 다음처럼 전달된다고 가정해 보겠습니다.