기존 프로젝트에 신규 API 2개를 추가하는 작업을 진행했다. 해당 작업을 진행하면서 주의할 부분을 2가지 알게되었다.
Query Parameter
HTTP Method는 GET이였고 Query Parameter를 전달받는 데 파라미터 중 하나가 배열로 전달받게 되어있었다.
async & await 문법을 활용하여 API 요청을 설계했는 데 URLQueryItem value에 Swift에서 배열자료형을 그대로 넣었는데 브라켓으로 인해 적합한 응답값이 내려오지 않았다.
알고보니 서버에서 브라켓을 인식할 수 있다면 상관없지만, 인식하지 못하는 경우 쉼표 구분자로 값을 전달하거나, 같은 키값을 여러번 넣는 방법을 통해 해결할 수 있다.
Alamofire 라이브러리에서는 변환이 자동으로 되거나 추가적인 인코딩설정을 진행할 수 있다.
❎
let nameList = ["철수", "영희"]
let queryParam = URLQueryItem(name: "nameList", value: nameList)
🅾️
let nameList = ["철수", "영희"]
let commaFormatNameList = nameList.joined(separator: ",")
let queryParam = URLQueryItem(name: "nameList", value: commaFormatNameList)
🅾️
let nameList = ["철수", "영희"]
let queryParam = nameList.map { URLQueryItem(name: "nameList", value: $0) }
기본적으로 서버에서는 API명세서에는 Number, Array등 각각 자료형을 명시하지만, 결국에 Query Parameter를 전달받을 때 모두 String으로 응답을 받는다. KakaoSDK에서 [String: Any] 자료형을 [URLQueryItem]으로 변경해주는 extension함수가 있는데 위의 이유로 모두 String으로 변경하는 것을 확인할 수 있다.
// Copyright 2019 Kakao Corp.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
extension Dictionary {
public var queryParameters: String {
var parts: [String] = []
for (key, value) in self {
let part = String(format: "%@=%@",
// ! optional unwrapping [ ]
String(describing: key).addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)!,
// ! optional unwrapping [ ]
String(describing: value).addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)!)
parts.append(part as String)
}
return parts.joined(separator: "&")
}
public var urlQueryItems: [URLQueryItem]? {
let queryItems = self.map { (key, value) in
URLQueryItem(name: String(describing: key),
value: String(describing: value))
}
return queryItems
}
}
Task
async & await 문법으로 API 작업을 진행하다가 실수한 부분은 Task는 비동기 작업인데 끝나고 진행할 코드를 Task 바깥에 넣어서 정상작동하지 않은 이슈가 있었다.
당연하지만 Task를 사용할 때 주의해서 사용해야겠다.
// 정상 동작 : requestMember 호출 -> requestMemberDetail 호출
❎
// requestMemberDetail 호출 -> requestMember 호출
Task {
let response = await requestMember()
print(response)
}
requestMemberDetail()
🅾️
// requestMember 호출 -> requestMemberDetail 호출
Task {
let response = await requestMember()
print(response)
requestMemberDetail()
}