Swift에서 URL을 다루는 법이 다양하다는 것을 알게되었습니다.
그래서 URL 다루기 심화편?! 을 이번 글에서 다뤄보려고 합니다.
URL 구조도
authority 저 부분이 저렇게 불리는 줄은 이번 공부하면서 첨음 알았습니다.
본인은 그냥 host라 불렀던 부분이라ㅎㅎ...
본인을 포함해서 많은 iOS 개발자 분들은 아마 URL을 만들 때
let helloWorldUrl = URL(string: "https://api.github.com/repos/octocat/Hello-World/issues?sort=updated&direction=asc")
이런식으로 만들고 있을 거라고 생각합니다. (저만 그런가??)
여기서 좀 더 확장성 좋고 명시적인 방법을 소개하려고 합니다.
extension URL {
init(staticString: StaticString) {
self.init(string: "\(staticString)")!
}
}
let safeUrl = URL(staticString: "https://api.github.com/repos/octocat/Hello-World/issues?sort=updated&direction=asc")
물론 유동적인 URL의 경우 옵셔널 언랩핑을 통해서 안전하게 다뤄야하겠지만
static한(하드코딩 된) URL의 경우 그런 절차가 필요하지 않습니다.
이처럼 편리한 extension을 사용해줍시다!
보통 host 부분을 잡아두고 여러 path들을 조합하여 네트워크 요청이나 웹페이지를 띄웁니다.
이럴경우 보통 host string에 path를 append하여 만들고는 합니다.
string에 append하여 URL을 조합하여 만들 경우 "/"를 빼먹거나 하나 더 추가되는 실수가 자주 일어납니다.
좀 더 명시적이고 안전한 방법을 살펴봅시다!
// '/'가 없어도 잘 동작합니다!!
let baseURL = URL(string: "https://www.matteomanferdini.com/")!
let mvvmURL = URL(string: "mvvm", relativeTo: baseURL)!
print(mvvmURL.absoluteString) // https://www.matteomanferdini.com/mvvm
이렇게 만들 경우 좀 더 명시적인 것 뿐만 아니라 '/' 이슈 걱정없이 사용할 수 있습니다!
URL의 특정 부분을 잘라내거나 query param 부분을 빼오거나 넣을 때
정규식을 이용해서 잘라내거나 수많은 if문을 대입해서 로직을 짜는 경우가 많습니다.
일단 다음은 각 URL의 부분부분을 가져오는 방법입니다.
let safeUrl = URL(staticString: "https://api.github.com/repos/octocat/Hello-World/issues?sort=updated&direction=asc")
print(safeUrl.scheme) // https
print(safeUrl.host) // api.github.com
print(safeUrl.path) // /repos/octocat/Hello-World/issues
print(safeUrl.query) // sort=updated&direction=asc
하지만 이것뿐만으로는 query 부분을 Dictionary나 Array로 빼내거나 주입할 때 여러 로직들을 대입해야합니다.
이때 필요한 것이 URLComponents 입니다.
// query param array로 빼내기
let safeUrl = URL(staticString: "https://api.github.com/repos/octocat/Hello-World/issues?sort=updated&direction=asc")
let components = URLComponents(url: safeUrl, resolvingAgainstBaseURL: false)!
print(components.queryItems!) // [sort=updated, direction=asc]
// query param 주입하기
var components = URLComponents(string: "https://api.github.com")!
components.path = "/repos/octocat/Hello-World/issues"
components.queryItems = [
URLQueryItem(name: "sort", value: "updated"),
URLQueryItem(name: "direction", value: "asc")
]
print(components.url!) // https://api.github.com/repos/octocat/Hello-World/issues?sort=updated&direction=asc
실무에서 URL의 path라던가 query parameter를 잘 못 대입하는 실수로 이슈들이 자주 일어납니다.
위와 같은 방법들을 이용한다면 그 실수가 덜하지 않을까 생각됩니다!