Swift: Decode 시에 응답 데이터 변환하기
안녕하세요.
일반적으로 API 통신을 할 때, JSON 형식의 응답 데이터를 Data 타입에서 구조체로 미리 정의해 놓은 타입으로 변환하여 사용합니다.
이 과정을 디코딩이라고 부르는데요, 단순히 변환하는 것 뿐만 아니라 필요한 데이터로 가공 및 변환을 동시에 수행해야 하는 경우가 있습니다.
이번 글에서는 Decodable을 활용하여 JSON 디코딩 과정에서 데이터를 변환하는 방법을 정리해보겠습니다.
1️⃣ 보통의 Decodable
struct PostByUser: Decodable {
let title: String
let body: String
}
Swift 구조체에 Decodable을 채택하면 Data 타입의 데이터를 해당 구조체로 디코딩할 수 있게 됩니다.
2️⃣ 매칭된 키 값 변경을 위한 CodingKeys 사용
만약 JSON에서 created_at, updated_at과 같은 값이 추가되었다면, 이러한 키를 그대로 쓰기엔 Swift의 camelCase 네이밍 규칙과 맞지 않죠. 이럴 때 CodingKeys를 활용하여 키 값을 변경할 수 있습니다.
struct PostByUser: Decodable {
let title: String
let body: String
let createdAt: String
let updatedAt: String
enum CodingKeys: String, CodingKey {
case title, body
case createdAt = "created_at"
case updatedAt = "updated_at"
}
}
이제 created_at은 디코딩 과정에서 자동으로 createdAt으로, updated_at은 디코딩 과정에서 자동으로 updatedAt으로 변환됩니다.
3️⃣ 응답 데이터 변환하기
날짜를 추가한 것 까진 좋았는데, 응답 데이터가 이렇게 생겼다고 해봅시다.
{
"title": "안녕하세요.",
"body": "반갑습니다.",
"created_at": "2025-03-04T00:56:51.295Z",
"updated_at": "2025-03-04T00:56:51.295Z"
}
서버 측에서는 클라이언트가 어떤 포맷의 날짜를 사용할 것인지 알 수 없습니다.
그렇기 때문에 최대한 범용적이고 시스템이 처리하기에 가장 적합한 형식을 사용하고 있습니다. 이 값을 변환시켜봅시다.
변환 방법은 흔히 DateFormatter로 변환하는 방법과 같습니다.
응답으로 받은 String을 일단 Date 타입으로 변환하고, 변환시킬 dateFormat을 지정한 후 다시 String으로 변환합니다.
String -> Date -> String
struct PostByUser: Decodable {
...
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
// 변화 없음
title = try container.decode(String.self, forKey: .title)
body = try container.decode(String.self, forKey: .body)
let isoFormatter = ISO8601DateFormatter()
let outputFormatter = DateFormatter()
isoFormatter.formatOptions = [.withInternetDateTime, .withFullDate, .withDashSeparatorInDate, .withFractionalSeconds]
outputFormatter.dateFormat = "yyyy.MM.dd"
if let createdDate = dateFormatter.date(from: try container.decode(String.self, forKey: .createdAt)) {
createdAt = outputFormatter.string(from: createdDate)
} else {
createdAt = ""
}
if let updatedDate = dateFormatter.date(from: try container.decode(String.self, forKey: .updatedAt)) {
updatedAt = outputFormatter.string(from: updatedDate)
} else {
updatedAt = ""
}
}
}
Decoder를 통해서 인스턴스가 생성될 때, 보통의 키들은 그대로 넘어가고, 변환할 Date관련 값들은 dateFormatter를 거쳐 변환시킵니다.
이제 createdAt, updatedAt이 2025-03-04T00:56:51.295Z 형태에서 2025.03.04로 변환됩니다.
4️⃣ 마무리
이번 글에서는 Swift의 Decodable을 활용하여 JSON 디코딩 과정에서 데이터를 변환하는 방법을 살펴보았습다. 핵심 내용을 정리하자면:
✔ CodingKeys를 활용하면 JSON 키와 Swift 속성 이름을 매핑할 수 있다.
✔ init(from decoder:)를 사용하면 디코딩 과정에서 데이터를 가공할 수 있다.
감사합니다! 🚀