[Android Kotlin] Retrofit2 사용방법 - Interface와 Data Class까지
공공데이터 등 REST API를 사용해야 할 일은 정말정말 많습니다. 이때 사용할 수 있는 오픈소스 라이브러리인 Retrofit의 사용방법을 설명드리겠습니다.
REST API란?
- REST는 Http를 조금 더 효율적으로 사용하기 위한 아키텍처입니다.
HTTP Method
- POST : 리소스 생성
- GET : 리소스 조회 및 출력
- PUT : 리소스 수정
- PATCH : 리소스 수정
- DELETE : 리소스 삭제
둘 다 리소스 수정 기능을 하지만 PUT과 PATCH에는 차이점이 있습니다.
PUT은 해당 리소스의 전체를 교체하는 의미를 지녔지만, PATCH는 일부를 변경하는 의미를 지녔습니다.
HTTP 응답 코드
- 1** : 요청을 받았으며 프로세스를 계속함 (정보)
- 2** : 클라이언트의 요청을 정상적으로 수행 (성공)
- 3** : 요청 완료를 위해 추가적인 작업 조치가 필요함 (리다이렉션)
- 4** : 요청의 문법이 잘못되었거나 요청을 처리할 수 없음 (클라이언트 오류)
- 5** : 서버가 명백히 유효한 요청에 대해 실패함 (서버 오류)
build.gradle (Module: app)
implementation 'com.google.code.gson:gson:2.8.5'
implementation 'com.squareup.retrofit2:retrofit:2.6.0'
implementation 'com.squareup.retrofit2:converter-gson:2.6.0'
AndroidManifest.xml
<uses-permission android:name="android.permission.INTERNET" />
retrofit에 관한 모듈을 추가해주고 인터넷을 사용하기 때문에 Manifest에 인터넷 권한도 추가해줍니다.
이제 Retrofit 사용 방법에 대해 알아보겠습니다.
경기데이터드림에서 제공하는 공공 API를 활용해 코드를 작성해보겠습니다. 경기데이터드림의 여러 데이터 중 지역화폐 가맹점 현황을 보여주는 api를 예시로 들겠습니다.
위와 같은 조건의 공공데이터를 읽어오는 방법을 알아보겠습니다.
MainActivity.kt
val regionRetrofit = Retrofit.Builder()
.baseUrl("https://openapi.gg.go.kr")
.addConverterFactory(GsonConverterFactory.create())
.build()
var regionServer: RetrofitService? = regionRetrofit.create(RetrofitService::class.java)
위와 같이 경기데이터드림의 URL인 "https://openapi.gg.go.kr"을 baseUrl로 지정해줍니다. 요청주소 뒤의 "RegionMnyFacltStus"까지 넣지 않는 이유가 있습니다. 이 부분은 path로 처리되며 코드의 재사용성을 높이기 위함입니다.
만약
- https://api.go.kr/user_name
- https://api.go.kr/user_address
- https://api.go.kr/user_phone
위와 같은 요청을 필요로 한다고 가정하겠습니다. 변하지 않는 "https://api.go.kr" 을 baseUrl로 하고 뒤의 user_* 을 Interface에서 조절한다면 RetrofitService 객체를 여러 번 생성하지 않아도 되는 것입니다.
RetrofitService.kt (Interface)
interface RetrofitService {
@GET("/RegionMnyFacltStus")
fun getInfo(@Query("Type")Type:String,
@Query("KEY")KEY:String,
@Query("pIndex")pIndex:Int? = null,
@Query("pSize")pSize:Int? = null) : Call<DataClass>
}
이렇듯 baseUrl 외에 path(지역화폐 가맹점 현황)에 해당하는 "RegionMnyFacltStus"는 인터페이스에서 선언해주는 것이 코드의 재사용성을 높일 수 있습니다.
경기데이터드림에서 요구하는 기본인자를 @Query 형태로 보낼 수 있습니다. 이때, pIndex와 pSize는 Nullable로 처리해주었습니다. 경기데이터드림에서 제공하는 기본값이 정해져있어 null로 보내도 되기 때문입니다.
후에 getInfo() 메소드를 사용할 시 선택적으로 값을 기입할 수 있습니다.
DataClass
data class DataClass(var RegionMnyFacltStus:List<Map<String, List<Map<String,Any>>>>?=null)
경기데이터드림에서 제공하는 API의 데이터 구조가 너무나도 복잡해 DataClass의 구조가 복잡해졌습니다.
쉬운 예시를 들겠습니다.
사용하고자 하는 API의 response body가
{
"body":{
"name" : "철수",
"address" : "강남",
"phone_number" : "010-000-0000"
}
}
처럼 되어있다고 가정하겠습니다. (response body는 Postman에서 확인 가능합니다)
이럴 경우에 DataClass는 아래와 같이 됩니다.
data class DataClass(var body:DataClassBody)
data class DataClassBody(var name:String, var address:String, var phone_number:String)
MainActivity.kt
regionServer?.getInfo("json", "")?.enqueue(object : Callback<DataClass>{
override fun onFailure(call: Call<DataClass>, t: Throwable) {t.printStackTrace()}
override fun onResponse(call: Call<DataClass>, response: Response<DataClass>) {
var name = response?.body()?.body?.name
var address = response?.body()?.body?.address
var phoneNum = response?.body()?.body?.phone_number
}
})
- 앞서 선언해둔 regionServer와 getInfo() 메소드, DataClass를 사용합니다.
- getInfo()의 인자값으로 API에서 요구하는 값을 넣어야 합니다. (pIndex, pSize = null 처리함)
- onResponse()와 onFailure()를 오버라이딩합니다.
- onResponse() 내에서 response로 요청한 데이터에 접근할 수 있습니다.
- response?.body()?.* 의 형식으로 접근할 수 있습니다.