먼저 글을 작성하기 전 안드로이드 진형에서 가장 많이 사용되는 네트워크 통신 라이브러리는 Retrofit이다.
나는 Retrofit을 사용하는 방법에 대해서만 알지 완전히 쏙쏙 사용하는 방법은 알지 못한다...
그래서 이번에 완벽 정리하는 겸해서 작성해보겠다.
Retrofit이란
먼저 GPT 선생에게 물어보자.
Retrofit은 Square 사에서 개발한 네트워크 통신 라이브러리로, REST API와 통신하기 위해 사용됩니다. Retrofit은 안드로이드 앱이 REST 기반 웹 서비스와 손쉽게 통신할 수 있게 해주며, 필요한 데이터를 빠르게 얻어오는 데 도움을 줍니다.
- Retrofit의 장점은 다음과 같습니다:
1. 통신 코드를 간결하게 작성할 수 있습니다.
2. 비동기와 동기 호출 모두를 지원합니다.
3. 다양한 데이터 변환을 지원합니다. (예: Gson, Jackson, Moshi 등)
4. 테스트가 용이합니다.
5. 캐싱, 인증, 로깅에 대한 요청/응답 수준의 제어 기능을 제공합니다.
이렇게 GPT가 요약을 해주니 너무나 맞는 말이다.
나는 자연스럽게 장점을 사용하고 있었다.
그럼 이제 한번 중요한 요소에 대해 작성해보자.
Retrofit 중요 구성요소
1. DTO : 'Data Transfer Object' 형태의 모델(Model) / JSON 타입 변환에 사용
2. Interface : 사용할 HTTP CRUD동작(메서드) 들을 정의해 놓은 인터페이스
3. Retrofit.Builder 클래스 : Interface를 사용할 인스턴스, baseUrl(URL) / Conterter(변환기) 설정
사용방법
1. Gradle 의존성 추가
- Retrofit / Converter (변환기) 라이브러리 추가
// Retrofit 라이브러리
implementation 'com.squareup.retrofit2:retrofit:2.6.4'
// Gson 변환기 라이브러리
implementation 'com.squareup.retrofit2:converter-gson:2.6.4'
// Scalars 변환기 라이브러리
implementation 'com.squareup.retrofit2:converter-scalars:2.6.4'
- Gson Converter - JSON 타입의 응답결과를 객체로 매핑(변환)해주는 Converter
- Scalars Converter - 응답결과를 String자체로 받아서 보여주는 Converter (사용자가 직접 변환시 사용)
- 그 외에 Moshi / Jackson 등등 여러 컨버터가 존재
1-1. 인터넷 권한 설정 'Permission-INTERNET'
- 메니페스트(Manifests) 파일에 인터넷 권한(퍼미션) 추가 - 네트워크 통신에 필요
- <uses-permission android:name="android.permission.INTERNET"/>
2. DTO / POJO - 모델 클래스 생성
- REST API로 받아올 데이터를 변환하여 매핑할 DTO 클래스 선언
- REST API의 응답 데이터 구조에 맞게 모델 클래스 선언 - 클래스명은 상관x
// REST API 응답데이터 구조
{
"userId": 1,
"id": 1,
"title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
"body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"
}
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
import com.google.gson.annotations.SerializedName
// DTO 모델 - PostResult Class 선언
data class PostResult(
@SerializedName("userId")
val userId: Int,
@SerializedName("id")
val id: Int,
val title: String, // @SerializedName으로 일치시켜 주지않을 경우엔 클래스 변수명이 일치해야함
@SerializedName("body")
val bodyValue: String // @SerializedName으로 일치시켜 주지않을 경우엔 클래스 변수명이 일치해야함
) {
override fun toString(): String {
return "PostResult(userId=$userId, id=$id, title='$title', bodyValue='$bodyValue')"
}
}
- JSON 데이터의 속성명과 변수명 + 타입(ex String,Int,Boolean) 일치 필수
: JSON - @SerializedName("속성명")으로 속성명 일치시켜주면 변수명 다르게도 가능
XML - @Element(name="속성명") XML은 @Element 애노테이션 사용
Interface 정의
- 사용할 메소드 선언
import retrofit2.Call
import retrofit2.http.GET
import retrofit2.http.Path
interface RetrofitService {
@GET("posts/{post}")
fun getPosts(@Path("post") post: String): Call<PostResult>
}
- @GET("posts/{post}") - 요청메소드 GET, baseUrl에 연결될 EndPoint 'posts/{post}
- 반환타입 Call<PostResult> - Call은 응답이 왔을때 Callback으로 불려질 타입
PostResult - 요청GET에 대한 응답데이터를 받아서 DTO 객체화할 클래스 타입 지정 - 메소드명 "getPosts" - 자유롭게 설정, 통신에 영향 x
- 매개변수 '@Path("post") String post' - 매개변수 post가 @Path("post")를 보고 @GET 내부 {post}에 대입
Retrofit 인스턴스 생성
- Retrofit.Build를 통해 Retrofit 인스턴스 생성
- baseUrl, Converter, Client 설정 부분 (baseUrl는 꼭 / 로 끝나야 함, 아니면 예외 발생)
- Converter는 여러개 등록 가능, 등록 순서대로 변환 가능여부 판단, 변환 불가능하면 다음 컨버터 확인 GsonConverter를 마지막에 넣는걸 추천 (Gson은 변환이 불가능해도 가능하다고 반응함) - Interface 객체 구현
- retrofit을 통한 객체 구현, 추상 메소드 중 사용할 메소드 Call 객체에 등록 - 동기 / 비동기 통신작업 실행
- 비동기 enqueue 작업으로 실행, 통신종료 후 이벤트 처리를 위해 Callback 등록
- onResponse 성공 / onFailure 실패 구분하여 메인스레드에서 처리할 작업 등록
(onResponse가 무조건 성공 X, 실패코드(3xx & 4xx 등)에도 호출 - isSuccesful() 확인이 필요