대부분 RESTful API통신을 소개하기위해서 GithubAPI를 예제로 활용하여 소개하지만 이 포스트에서는 도로명 주소 API를 사용하도록 하겠습니다. (진행중인 프로젝트에 마침 도로명 주소 API를 사용하기 때문입니다...ㅋㅋㅋㅋ) Alamofire를 사용해 구현해볼 화면은 간단하게 키워드를 입력받아 검색하면 가장 처음 나타나는 주소 하나만 Label로 출력해주는 화면입니다.
1. 도로명주소 API key 발급
도로명 주소 API를 사용하기 위해서는 도로명주소 API 홈페이지에 들어가서 사용신청을 먼저 해야합니다.
위 링크로 접속하게 되면 바로 신청할 수 있습니다!
이번에 사용해야할 API는 "도로명주소 API"에서 "검색 API"입니다. 업체명이나 URL은 회사에서 사용하는게 아니기 때문에 개인 이름이나 닉네임, 그리고 URL에는 블로그 주소를 적어주셔도 됩니다. 서비스 용도는 개발로 설정하고 본인이 원하는 인증 기간을 설정해주시면됩니다!
신청을 완료하면 위와같이 승인키가 나오게됩니다. (해당 사이트에서는 별도의 로그인 과정이 없기때문에 다시 승인키를 조회하기 어려운 것 같으니 메모장이나 다른 공간에 적어두어야할 것 같습니다!)
1-1 도로명 주소 Key 테스트
받은 승인키가 잘 동작하는지 확인하기 위해 Postman으로 API호출 테스트를 진행해봅니다.
API호출하기 위해 호출 형태가 어떻게 되는지 먼저 찾아봅니다.
GET이든 POST든 상관없어보이고.. 요청변수로 "confmKey, currentPage, countPerPage, keyword"가 반드시 필요하고 "resultType"이 선택적으로 들어가는 변수네요! 그럼 Postman으로 먼저 보내봅시다. 아래와 같이 URL과 변수들을 입력하고 "강남"이란 키워드를 넣어서 검색 API를 호출해보면 정상적으로 응답이 오는것을 확인 할 수 있습니다. (승인키가 정상적으로 동작하는데까지 처리시간이 좀 있어서 승인받고 1~2분 후에 호출하면 정상적으로 동작하는 것 같습니다.)
2. 응답 데이터 모델링 (Codable)
API를 요청하고 나서 응답 데이터를 우리가 원하는 데이터형태로 받기위해 데이터 클래스를 먼저 정의해줍니다.
위에 Postman에서 오는 응답 데이터의 형태를 보거나 도로명주소 API 홈페이지에 제공되는 문서에서 응답형태를 보고 정의하면 됩니다.
응답으로 오는 형태가 다음과 같기 때문에 동일한 구조로 데이터 클래스를 정의해줍니다. Codable을 사용하여 정의하기 때문에 응답으로 오는 데이터 필드의 이름과 변수명과 동일하게 맞춰주어야 제대로 파싱됩니다. 저는 읽기 쉽게 depth마다 다른 struct로 정의하였습니다.
// JusoResponse.swift
struct JusoResponse: Codable {
var results: JusoResults!
}
struct JusoResults: Codable {
var common: Common!
var juso: [Juso]!
}
struct Common: Codable {
var errorCode: String!
var currentPage: String!
var totalCount: String!
var errorMessage: String!
}
struct Juso: Codable {
var roadAddr: String!
var jibunAddr: String!
}
3. Alamofire 호출
// ViewController.swift
class ViewController: UIViewController {
...
...
@objc
private func onTapSearch() {
let keyword = mainView.field.text!
if !keyword.isEmpty {
findAddress(keyword: keyword) { [weak self] (jusoResponse) in
guard let self = self else { return }
if (!jusoResponse.results.juso.isEmpty) {
// 뷰에있는 결과라벨에 텍스트 설정
self.mainView.resultLabel.text = "지번: \(jusoResponse.results.juso[0].jibunAddr!)\n도로명: \(jusoResponse.results.juso[0].roadAddr!)"
}
}
}
}
private func findAddress(keyword: String, completion: @escaping ((JusoResponse) -> Void)) {
let url = "http://www.juso.go.kr/addrlink/addrLinkApi.do"
let parameters: [String: Any] = ["confmKey": "devU01TX0FVVEgyMDIwMDYwMTEzNTgxMzEwOTgxNjE=",
"currentPage": "1",
"countPerPage":"10",
"keyword": keyword,
"resultType": "json"]
Alamofire.request(url, method: .get, parameters: parameters).responseJSON { [weak self] (response) in
guard let self = self else { return }
if let value = response.value {
if let jusoResponse: JusoResponse = self.toJson(object: value) {
completion(jusoResponse)
} else {
print("serialize error")
}
}
}
}
private func toJson<T: Decodable>(object: Any) -> T? {
if let jsonData = try? JSONSerialization.data(withJSONObject: object) {
let decoder = JSONDecoder()
if let result = try? decoder.decode(T.self, from: jsonData) {
return result
} else {
return nil
}
} else {
return nil
}
}
}
검색 버튼을 누를때마다 onTapSearch()함수가 호출되고 TextField에 적혀진 텍스트를 받아와서 findAddress함수를 호출하여 주소 API를 호출하는 방식입니다. 실제 Alamofire를 통해 API를 호출하는 함수는 findAddress함수입니다.
Alamofire를 사용해 호출할때 인자로 들어가는 변수는 Dictionary(name: value) 형태로 정의하여 넣어줍니다.
API호출 이후에 응답 데이터는 콜백형태로 주기때문에 @escaping을 사용했습니다. responseJSON형태로 받고나서 JSONDecoder()를 사용하면 Codable로 정의된 JusoResults모델형태로 맵핑되어 받아집니다. (모델을 잘못 정의하면 파싱하는부분에서 에러가 발생합니다.)
맵핑이 되면 이제 사용자가 원하는 대로 사용할 수 있습니다.
'iOS' 카테고리의 다른 글
📱Github action을 사용해서 iOS프로젝트 자동으로 테스트시키기 (0) | 2020.07.30 |
---|---|
📱iOS 인스타그램 API로 내 포스트 가져오기 (Alamofire API) (0) | 2020.07.29 |
📱iOS Stretchy header 오토 레이아웃으로 구현하기 (Snapkit) (0) | 2020.05.31 |
📱화면 절반만 차지하는 iOS모달 구현하기 (0) | 2020.05.15 |
[iOS/Swift5] 스토리보드 없이 횡스크롤 UICollectionView 만들기 (0) | 2020.02.08 |