https://explorer89.tistory.com/274
해시란? Hash, Hashable
Hash란?데이터를 관리, 유지하는 자료구조로 데이터들을 해시 함수를 통해 key로 분류하고, 그 key에 따라 value를 저장하는 형태를 뜻합니다.즉, "Hash"는 데이터를 고유한 숫자 값으로 변환하는 과정
explorer89.tistory.com
1. Equatable이란?
Equatable은 "두 값이 같은지 비교할 수 있는 능력"을 제공하는 프로토콜입니다.
이 프로토콜을 채택한 타입은 "== 연산자"를 구현해야 합니다.
struct Item: Equatable {
let id: Int
let name: String
}
// `Equatable`을 채택하면 Swift가 자동으로 `==`를 구현해줌
let itemA = Item(id: 1, name: "Apple")
let itemB = Item(id: 1, name: "Apple")
let itemC = Item(id: 2, name: "Orange")
print(itemA == itemB) // true (id와 name이 모두 동일)
print(itemA == itemC) // false (id가 다름)
2. Hashable과 Equatable의 관계
Hashable은 데이터를 고유한 해시 값으로 변환하는 능력을 제공하지만, Equatable을 반드시 필요로 합니다.
- 해시 값만으로 데이터의 고유성을 100% 보장할 수 없습니다.
예를 들어, 두 다른 객체가 우연히 동일한 해시 값을 가질 수도 있습니다. => 이걸 해시 충돌이라고 함 - 따라서, Hashable은 해시 값이 동일한 경우 == 연산을 통해 두 객체가 실제로 같은지 최종 확인합니다.
3. Swift 구조체의 특별한 기능
구조체는 기본적으로 값 타입이기 때문에, Equatable이나 Hashable을 쉽게 사용할 수 있도록 설계돼 있어요.
- 만약 구조체가 모든 속성이 Equatable하거나 Hashable한 타입으로 구성되어 있다면, Swift는 자동으로 Equatable과 Hashable을 구현해줍니다.
struct Section: Decodable, Hashable {
let id: Int
let type: String
let title: String
let subtitle: String
let items: [String]
}
let sectionA = Section(id: 1, type: "Type1", title: "Title1", subtitle: "Subtitle1", items: ["Item1"])
let sectionB = Section(id: 1, type: "Type1", title: "Title1", subtitle: "Subtitle1", items: ["Item1"])
print(sectionA == sectionB) // true (자동으로 Equatable 동작)
4. 직접 Equatable을 선언하지 않아도 되는 이유
(1) Hashable만 채택해도 충분:
- Hashable을 선언하면, Swift가 Equatable도 포함해서 자동으로 구현해줍니다.
- 예를 들어, Hashable을 사용하기 위해 내부적으로 == 연산이 필요하므로 Swift가 자동으로 이를 제공합니다.
(2) struct의 값 타입 특성:
- struct는 값 타입으로 동작하기 때문에, Swift는 값 타입의 모든 속성이 동일하면 자동으로 "같다"고 판단하도록 구현해요.
- 따라서, 따로 Equatable을 선언하거나 ==를 구현하지 않아도 Swift가 이를 처리합니다.
🔴 만약 Hashable을 직접 구현한다면, Swift가 자동으로 제공하는 == 연산자나 hash(into:)를 사용할 수 없게 되므로, 이를 명시적으로 구현해야 합니다.
struct Item: Hashable {
let id: Int
let name: String
// 직접 구현: 해시 값 계산
func hash(into hasher: inout Hasher) {
hasher.combine(id) // 특정 속성(id)만 해시 계산에 사용
}
// 직접 구현: 동등 비교
static func == (lhs: Item, rhs: Item) -> Bool {
return lhs.id == rhs.id // id만 비교 기준
}
}
let itemA = Item(id: 1, name: "Apple")
let itemB = Item(id: 1, name: "Orange")
print(itemA == itemB) // true (id만 비교)
print(itemA.hashValue == itemB.hashValue) // true (id만 해시 값에 포함)
이 경우, Hashable을 제대로 작동하게 하려면:
- hash(into:) 메서드에서 어떤 속성을 해시 값 계산에 사용할지 명시해야 하고,
- == 연산자에서 동등 비교의 기준을 직접 정의해야 합니다.
'정보' 카테고리의 다른 글
SOLID 원칙이란? (0) | 2024.12.17 |
---|---|
디자인 패턴 - 싱글톤 패턴 (0) | 2024.12.17 |
해시란? Hash, Hashable (1) | 2024.12.15 |
Static Dispatch vs Dynamic Dispatch (1) | 2024.12.13 |
클래스와 구조체가 섞여 있을 때... (0) | 2024.12.13 |