공공 데이터 포털은 공공기관이 관리하는 공공데이터를 제공하는 창구이다. Oepn API 말고도 파일데이터나 시각화 자료까지도 접근, 이용할 수 있다. 뿐만 아니라 내가 원하는 데이터가 현재 제공되지 않는다면 별도로 제공 신청 프로세스도 밟을 수 있다고 한다.
이 글에서는 청약 관련 조회 API를 신청해서 가볍게 화면에 뿌려주는 것까지 진행해보려 한다.
Step 1. 아래 공공 데이터 포털 사이트에 접속/회원 가입 후, 메인화면 검색창에서 내가 사용하고자 하는 API 서비스를 검색하면 된다.
공공 데이터 포털 사이트 : https://www.data.go.kr/index.do |
Step 2. 사용하고자 하는 Open API 활용 신청하기. 사용하고자 하는 API는 승인절차가 "자동승인", 혹은 "일반승인"으로 나눠지는 것 같다. 여기서 내가 신청한 API는 "자동승인"이라 간단한 신청 절차서 작성 후 바로 활용이 가능했다.
Step3. 마이페이지 > 활용 > 내가 신청한 서비스를 확인할 수 있다. 해당 서비스 진입 후, api 문서와 함께 인증키를 확인할 수 있다. 해당 api 요청 시 인증키를 사용하여야 하고, 응답 시에는 api 문서를 참고해서 데이터 클래스를 만들어야 하므로 잘 저장해두자.
Step4. retrofit2를 사용하기 위해 안드로이드 프로젝트에서 기본 설정을 진행한다.
retrofit은 안드로이드에서REST api 통신을 지원하기 위한 라이브러리다. 기존의 사용자가 http 통신을 위해 HttpURLConnection을 성립시키고 결과를 받아오는 과정이 다소 복잡하다. 여기에 더해서 AsyncTask가 deprecate되면서 서버와의 비동기 통신을 위해 골머리를 앓게 되는데.. retrofit은 Call 인터페이스의 enqueue을 통해 비동기 구현이 가능하다.(call 인터페이스의 enqueue를 이용하지 않고 rxjava, rxkotlin를 사용하여 비동기 처리할 수도 있다.) *retrofit guide : https://square.github.io/retrofit/ |
[Call 인터페이스의 enqueue]
/**
* Asynchronously send the request and notify {@code callback} of its response or if an error
* occurred talking to the server, creating the request, or processing the response.
*/
void enqueue(Callback<T> callback);
- 권한, 의존성 설정
retrofit을 사용하기 앞서서 Manifest 권한 설정과 retrofit2를 사용하기 위해 gradle에 의존성을 추가해야 한다. 그래들 최신 버전은 retrofit github https://github.com/square/retrofit 링크를 통해 확인할 수 있다.
[AndroidManifest.xml]
<!-- Http 통신을 하기 위해 인터넷 권한 허용 -->
<uses-permission android:name="android.permission.INTERNET" />
[Module단 gradle]
// json <-> 객체 변환하기 위해 사용
implementation 'com.google.code.gson:gson:2.8.7'
/**
* retrofit 네트워크 라이브러리 관련
*/
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
Step5. RetrofitClient 생성하기
위에서 저장해두었던 endPoint 주소가 BASE_URL로 두었음을 볼 수 있다. (endPoint 주소 뒤에 "/"를 꼭 추가한다.)
object RetrofitClient {
/* Open API End Point Url */
private const val BASE_URL = "https://api.odcloud.kr/api/ApplyhomeInfoDetailSvc/v1/"
private var instance: Retrofit? = null
open fun getInstance() : Retrofit {
if (instance == null) {
instance = Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build()
} // end if
return instance!!
}
}
Step6.응답 DTO 만들기
공공 api에서 사용하고자 하는 서비스의 응답 model을 참고해서 resoponse Class를 만든다. 응답 데이터가 너무 방대하니, 일단 이 글에서는 주택관리번호, 주택명, 공급위치 3개의 데이터만을 가져오는 것으로 하겠다.
[공공 데이터 포털 api 문서]
getAPTLttotPblancDetail_model{
HOUSE_MANAGE_NO integer
주택관리번호
PBLANC_NO integer
공고번호
HOUSE_NM string
주택명
HSSPLY_ADRES string
공급위치
TOT_SUPLY_HSHLDCO integer
공급규모
RCRIT_PBLANC_DE string
모집공고일 (YYYY-MM-DD)
... (생략)
}
위의 api 문서를 참고하여 아래와 같이 DTO를 구현했다. 유의깊게 보아야 할 부분은 리스트부가 되는 부분은 별도로 data class를 만든 부분과 Gson 라이브러리의 @SerializedName 애노테이션이다. api 통신을 통해 받은 응답 json이 우리가 원하는 객체로 변환될 때, @SerializedName에 설정한 값을 가진 JSON 컬럼이 애노테이션이 선언된 변수로 반영된다. (아래에서는 응답 json의 HOUSE_MANAGE_NO -> houseManageNo로)
[aptLttotPblancDetailDTO.kt]
data class AptLttotPblancDetailResponse(
@SerializedName("page")
val page: Int,
@SerializedName("perPage")
val perPage: Int,
@SerializedName("matchCount")
val matchCount: Int,
@SerializedName("totalCount")
val totalCount: Int,
@SerializedName("currentCount")
val currentCount: Int,
@SerializedName("data")
val data: MutableList<AptItem>
)
data class AptItem(
@SerializedName("HOUSE_MANAGE_NO")
val houseManageNo: Int,
@SerializedName("HOUSE_NM")
val houseNm: String?,
@SerializedName("HSSPLY_ADRES")
val houseAddr: String?
)
Step7.API Interface 만들기.
응답 데이터 클래스가 완성됐으니, 실제로 api를 요청파트를 만들어야 한다. 이때에도 api 문서나 사용하는 공공 api 목록에서 요청 컬럼이나 형식을 참고해서 작성한다. (page, perPage 이외에도 다양한 요청 컬럼이 있지만 선택사항이므로 빠른 구현을 위해 생략한다.)
[CyApiService.kt]
/**
* 청약 API
*/
interface CyApiService {
companion object {
private const val authKey = "부여받은 서비스키"
}
// 주택관리번호, 공고번호, 공고지역코드, 모집공고일 값을 이용하여 APT 분양정보의 상세정보를 제공
@GET("getAPTLttotPblancDetail")
fun getAPTLttotPblancDetail(
@Query("page")
page: Int = 1,
@Query("perPage")
perPage: Int = 10,
@Query("serviceKey")
serviceKey: String = authKey
) : Call<AptLttotPblancDetailDTO>
}
Step8.api 통신 / 뷰 데이터 셋팅
[MainActivity.kt]
private fun requestAptCyList() {
val cyListService = RetrofitClient.getInstance().create(CyApiService::class.java)
val listCall = cyListService.getAPTLttotPblancDetail()
listCall.enqueue(object : Callback<AptLttotPblancDetailDTO> {
override fun onResponse(
call: Call<AptLttotPblancDetailDTO>,
response: Response<AptLttotPblancDetailDTO>
) {
if (response.isSuccessful && response.code() == 200) {
cyListAdapter?.let {
it.setAptListItem(response.body()?.data ?: mutableListOf())
}
} // end if
}
override fun onFailure(call: Call<AptLttotPblancDetailDTO>, t: Throwable) {
// 실패
Log.e("main_error", t.stackTrace.toString());
}
})
}
작업 소스 : https://github.com/markim94/Blog/tree/main/OpenApiProject
+ 또한 해당 프로젝트에서 액티비티의 종속성 소거를 위해 binding adapter를 적용한 포스팅도 작성해두었습니다. (https://markim94.tistory.com/163)
'▶개발 > Android' 카테고리의 다른 글
Binding Adapter(결합 어댑터) 예제를 통해 이해하기 (0) | 2022.04.16 |
---|---|
안드로이드12 상태바/내비바 배경, 아이콘 색상 설정 (0) | 2022.04.07 |
[Android] 안드로이드 액티비티 전환과 부가데이터(Intent) (0) | 2018.10.08 |
[Android] 안드로이드 레이아웃:Relative Layout (0) | 2018.10.07 |
[Android] 안드로이드 레이아웃:Frame Layout (0) | 2018.10.03 |