응답 모델 정의하기
rates, source, market_session, data_updated_at을 모델에 보존하고 금액 계산에는 Decimal을 사용하세요.
swift · ExchangeRateClient.swiftcopy
import Foundation
final class NoRedirects: NSObject, URLSessionTaskDelegate {
func urlSession(_ session: URLSession, task: URLSessionTask, willPerformHTTPRedirection response: HTTPURLResponse, newRequest request: URLRequest, completionHandler: @escaping (URLRequest?) -> Void) {
completionHandler(nil)
}
}
struct Latest: Decodable {
let base: String
let source: String
let marketSession: String
let dataUpdatedAt: String
let rates: [String: Decimal]
}
struct ExchangeRateClient {
let session: URLSession
let apiKey: String?
func latest(base: String) async throws -> Latest {
let normalizedBase = base.uppercased()
guard normalizedBase.count == 3, normalizedBase.allSatisfy({ $0.isASCII && $0.isLetter }) else {
throw URLError(.badURL)
}
guard var components = URLComponents(string: "https://api.exchangerate.dev/v1/latest/\(normalizedBase)") else {
throw URLError(.badURL)
}
components.queryItems = [URLQueryItem(name: "symbols", value: "EUR,GBP,JPY")]
guard let url = components.url else { throw URLError(.badURL) }
var request = URLRequest(url: url)
request.timeoutInterval = 10
if let apiKey { request.setValue("Bearer \(apiKey)", forHTTPHeaderField: "Authorization") }
let (data, response) = try await session.data(for: request)
guard let http = response as? HTTPURLResponse, (200..<300).contains(http.statusCode) else {
throw URLError(.badServerResponse)
}
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
return try decoder.decode(Latest.self, from: data)
}
}키를 서버에 두기
모바일 앱은 자체 backend를 호출하고 backend가 Authorization을 추가해야 합니다. 서버 Swift는 환경 변수에서 키를 읽을 수 있습니다.
swift · server setupcopy
let key = ProcessInfo.processInfo.environment["EXCHANGERATE_API_KEY"]
let session = URLSession(configuration: .ephemeral, delegate: NoRedirects(), delegateQueue: nil)
let client = ExchangeRateClient(
session: session,
apiKey: key
)
let latest = try await client.latest(base: "USD")
print(latest.rates["EUR"] as Any, latest.source, latest.dataUpdatedAt)상태와 최신성 처리하기
디코드 전에 HTTP 상태를 확인하고 401과 429를 구분해 처리하세요.
환율의 맥락을 함께 저장하세요
일일 보고서는 하루 한 번, 운영 대시보드는 한 시간마다 호출하면 됩니다. 429가 오면 즉시 재시도하지 말고 주기를 줄이세요.
- 출처와 시간과 함께 환율을 저장합니다.
- 자동화와 분석에 사용합니다.
- 실행 가능한 가격으로 취급하지 않습니다.