개요
Codable 프로토콜은 Swift에서 데이터 타입을 JSON이나 다른 외부 표현으로 인코딩하거나 디코딩할 수 있도록 도와주는 프로토콜이다
이 글에서는 Codable 프로토콜의 기본 개념을 간단하게 알아보고 직렬화(Serialization)와 역직렬화(Deserialization)의 개념을 살펴본다
그리고 JSON 역직렬화 과정에서 프로퍼티 값이 다른 경우, CodingKeys를 통해 커스텀한 디코딩 과정을 구현하는 방법에 대해 정리한다
- Codable 프로토콜
- 데이터 변환의 기본 개념(직렬화/역직렬화)
- CodingKeys와 중첩 키 처리
Codable 프로토콜
Codable는 Swift에서 데이터를 직렬화와 역직렬화할 수 있도록 제공되는 프로토콜이다
이는 아래에서 볼 수 있듯이, Encodable과 Decodable 두 프로토콜을 조합한 타입 별칭으로 정의된다
typealias Codable = Decodable & Encodable
Swift로 파일 저장, 네트워크 통신, 데이터베이스 처리와 같은 작업에서 데이터를 직렬화하고 역직렬화하는 과정을 Codable 프로토콜을 이용하면, 쉽고 안전하게 수행하는 데 주로 사용된다
Encodable과 Decodable
Encodable과 Decodable은 데이터를 외부 표현으로 인코딩하거나, 외부 표현에서 디코딩할 수 있는 프로토콜이다

Encodable
데이터를 JSON 등 외부 형식으로 변환할 수 있도록 encode(to:) 메서드를 사용해 인코딩 작업을 수행한다
Decodable
외부 형식(예: JSON)에서 데이터를 읽어올 수 있도록 init(from:) 초기화 메서드를 사용해 디코딩 작업을 수행한다
데이터 변환의 기본 개념
현대 소프트웨어 개발에서는 데이터를 다양한 형식으로 변환하여 저장하거나 전송하고, 다시 원래의 구조로 복원하는 과정이 필수적이다
이 과정은 주로 직렬화와 역직렬화라는 개념으로 정리된다
여기에 더해, 직렬화와 역직렬화를 세부적으로 구분한 작업인 인코딩(Encoding)과 디코딩(Decoding)이 존재한다
직렬화(Serialization)
데이터 구조나 객체를 저장하거나 전송할 수 있도록 특정 형식으로 변환하는 과정이다
그 결과물로 바이트 스트림(예: Data), JSON 문자열 등이 존재할 수 있다
JSONEncoder
Swift에서는 Encodable 프로토콜을 통해 객체를 JSON과 같은 형식으로 변환할 수 있다
이 작업은 JSONEncoder를 사용하여 수행된다
struct User: Encodable {
let name: String
let age: Int
}
let user = User(name: "HS", age: 26)
let jsonData = try? JSONEncoder().encode(user)
역직렬화(Deserialization)
저장되거나 전송된 데이터를 다시 원래의 데이터 구조나 객체로 변환하는 과정이다
그 결과물로 JSON 데이터를 Swift 객체(예: 구조체, 클래스)로 변환한다
JSON, XML, 바이트 스트림 등의 형식을 Swift의 객체나 구조체로 복원하는 데 사용된다
JSONDecoder
Swift에서는 Decodable 프로토콜을 통해 JSON 데이터를 객체로 복원할 수 있다
이 작업은 JSONDecoder를 사용하여 수행된다
let jsonString = """
{
"name": "Alice",
"age": 30
}
"""
let jsonData = jsonString.data(using: .utf8)!
let user = try? JSONDecoder().decode(User.self, from: jsonData)
CodingKeys
Swift의 Codable(=Encodable&Decodable) 프로토콜을 사용하면 데이터를 직렬화하거나 역직렬화할 때 매우 간편하고 타입 안전한 방식으로 작업할 수 있다
Codable을 채택한 타입에서는 JSON의 키와 Swift의 프로퍼티 이름이 동일한 경우 자동으로 매핑된다
하지만 JSON 키 이름과 Swift의 구조체나 클래스 프로퍼티 이름이 일치하지 않을 경우, 데이터 매핑 과정에서 문제가 발생할 수 있는데, 이를 해결하기 위해 Swift는 CodingKeys라는 열거형을 사용한다
- CodingKeys는 String 및 CodingKey를 준수하는 enum
- 열거형의 각 케이스는 JSON 키를 나타내며, Swift 프로퍼티 이름과 JSON 키가 다를 경우 매핑을 정의 가능
struct Todo: Decodable {
let identifier: Int
let userId: Int
let title: String?
let completed: Bool
enum CodingKeys: String, CodingKey {
case identifier = "id"
case userId
case title
case completed
}
}
let data: Data = await fetchRequest() // Todo들로 이뤄진 JSON
let decoder = JSONDecoder()
let todos = try? decoder.decode([Todo].self, from: data)
중첩 키 처리
let jsonString = """
{
"id": 1,
"user": {
"id": 42,
"name": "Alice"
},
"title": "Learn Swift",
"completed": true
}
"""
let jsonData = jsonString.data(using: .utf8)!
do {
let decoder = JSONDecoder()
let todo = try decoder.decode(Todo.self, from: jsonData)
} catch {
print("Decoding failed with error: \\(error)")
}
가령 위와 같은 JSON 데이터를 처리한다면, 다음과 같이 Decodable 객체에 Decoder를 인자로 사용하는 생성자에서 Decoder의 container를 통해 각 요소를 직접 decode 수행시키면 된다
이때 중첩 키는 container의 nestedContainer(keyedBy:forKey:) 메서드를 통해 처리한다
struct Todo: Decodable {
let identifier: Int
let userId: Int
let completed: Bool
let title: String
// JSON.user에 존재하는 내용을 위해 구현
struct User: Codable {
let id: Int
let name: String
}
// CodingKeys로 매핑 정의(JSON.id->Todo.identifier)
enum CodingKeys: String, CodingKey {
case identifier = "id"
case user
case title
case completed
}
enum UserKeys: String, CodingKey {
case id
case name
}
// 커스텀 디코더 수행
init(from decoder: Decoder) throws {
/// CodingKeys를 기반 키로 가지는 Decoder container 생성
let container = try decoder.container(keyedBy: CodingKeys.self)
self.identifier = try container.decode(Int.self, forKey: .identifier)
self.completed = try container.decode(Bool.self, forKey: .completed)
self.title = try container.decode(String.self, forKey: .title)
/// 중첩 키 처리
let userContainer = try container.nestedContainer(keyedBy: UserKeys.self, forKey: .user)
self.userId = try userContainer.decode(Int.self, forKey: .id)
}
}
마무리
Codable 프로토콜은 네트워크 통신, 파일 작업 등에서 데이터 직렬화와 역직렬화 과정을 간소화시킬 수 있다
특히 JSON 데이터를 다룰 때, JSONEncoder와 JSONDecoder를 통해 간결하고 타입 안전한 코드를 작성할 수 있게 도와주는데, 이를 활용하여 더욱 효율적이고 안전한 Swift 애플리케이션을 개발할 수 있다
'iOS+ > Swift' 카테고리의 다른 글
| Swift Concurrency (0) | 2025.01.26 |
|---|---|
| URLSession을 이용한 네트워킹 작업 (0) | 2025.01.12 |
| ARC(Automatic Reference Counting) (0) | 2025.01.05 |
| Transferable (0) | 2024.09.08 |
| Swift 명령어와 Swift Package (0) | 2024.06.16 |