2023년이 얼마 남지 않았네요....ㅠ
고로.. Hashable
이 2023년의 마지막 포스트가 되겠네요 ㅎㅎ
public protocol Hashable: Equatable {
var hashValue: Int { get }
func hash(into hasher: inout Hasher)
func _rawHashValue(seed: Int) -> Int
}
해당 오픈 소스 코드는 swift > stdlib > public > core > Hashable.swift에서 자세히 볼 수 있습니다.
정수 해시 값을 생성하기 위해
Hasher
로 해시될 수 있는 유형입니다.Set
또는Dictionary Key
로Hashable
프로토콜을 준수하는 모든 타입을 사용할 수 있습니다. 표준 라이브러리의 많은 타입은Hashable
을 준수합니다.String
,Int
,Float
및Bool
, 심지어Set
도 기본적으로 해시 가능합니다.Optional
,Array
,Ranges
와 같은 일부 다른 유형은 해당 타입 인수가 동일하게 구현되면 자동으로 해시 가능해집니다.사용자 정의 타입도
Hashable
이 가능합니다. 연관된 값 없이 열거형을 정의하면Hashable
적합성을 자동으로 얻고,hash(into:)
메서드를 구현하여 다른 사용자 정의 타입에Hashable
적합성을 추가할 수 있습니다. 저장된 프로퍼티가 모두Hashable
인 구조체와 모든Hashable
관련 값이 있는 열거형 타입의 경우 컴파일러는 자동으로hash(into:)
구현을 제공할 수 있습니다.값을 해싱하는 것은
Hasher
타입으로 표시되는 해시 함수에 필수 구성 요소를 공급하는 것을 의미합니다. 필수 구성 요소는 유형의Equatable
구현에 기여하는 구성 요소입니다. 동일한 두 인스턴스는hash(into:)
의Hasher
에 동일한 값을 동일한 순서로 공급해야 합니다.
공식문서는 Hashable을 어떻게 사용하는지를 집중적으로 알려주고 있습니다.
그런데 hashValue
, Hasher
이런 개념들은 해당 문서만 보고 이해하기에는 아리송합니다.
hashValue
hashValue
는 어떤 데이터가 와도 64비트짜리 정수로 치환됩니다. 즉 암호화 작업을 한다고 생각하면 이해가 쉬울 거 같습니다. 원본 데이터를 특정 규칙에 따라 처리하여 간단한 숫자로 만든 것이고, 2개의 데이터 비교시 데이터가 동일할 때 둘의 해시값은 같습니다.
Hasher
Set 및 Dictionary에서 사용되는 범용 해시 함수입니다.
Hasher는 임의의 바이트 시퀀스를 정수 해시 값으로 매핑하는 데 사용할 수 있습니다.
combine()
메서드를 변경하는 일련의 호출을 사용하여 해셔에 데이터를 공급할 수 있습니다. 해시 입력이 끝나면finalize()
를 호출하여 해시 값을 검색할 수 있습니다.
var hasher = Hasher()
hasher.combine(23)
hasher.combine("Hello")
let hashValue = hasher.finalize()
Swift 프로그램 실행 내에서 Hasher는 완전히 동일한 바이트 시퀀스가 공급되는 한 프로그램 종료가 항상 동일한 해시 값을 생성하도록 보장합니다. 그러나 기본 해시 알고리즘은 눈사태 효과를 나타내도록 설계되었습니다. 즉, 시드 또는 입력 바이트 시퀀스가 약간 변경되면 일반적으로 생성된 해시 값이 크게 변경됩니다.
또 모르는 개념이 나왔습니다! 눈사태 효과라... 느낌상 나비효과처럼 작은 변화가 전체적으로 변화를 주는 개념같이 생각이 됩니다.
눈사태 효과는 암호학 용어로, 원문(Plaintext)의 한 비트의 변화가 최종 암호문(Ciphertext)에 큰 변화를 주는 효과입니다.
설명이 너무 간단한 거 같지만.. 너무 깊게 파면 암호학까지 공부하게 될 거 같아서 여기까지만 알아보기로 했습니다...ㅎㅎ
그러면 조금 더 코드를 뜯어볼까요?
func hash(into hasher: inout Hasher)
이 값의 필수 구성 요소를 지정된
Hasher
에 공급하여 해시합니다.Hashable
프로토콜을 준수하도록 이 메서드를 구현하세요. 해싱에 사용되는 구성 요소는 타입의==
연산자 구현에서 비교되는 구성 요소와 동일해야 합니다. 이러한 각 구성 요소와 함께hasher.combine(_:)
을 호출하세요.
hash(into:)
구현 시 제공된hasher
인스턴스에서finalize()
를 호출하지 않거나 다른 인스턴스로 바꾸지 마세요. 그렇게 하면 나중에 컴파일 시간 오류가 발생할 수 있습니다.
오~ 미리 Hasher
에 대해 공부하길 잘한 거 같네요👍
Swift 표준 라이브러리에 속한 타입들은 기본적으로 Hashable
을 채택하고 있어서 사용자 정의 타입에 Hashable
을 채택해도, 저장 프로퍼티가 모두 표준 라이브러리에 속한 타입들이라 따로 이 메서드를 구현해본 적은 없는 거 같아요.
설명을 읽어보니, 해당 값을 Hasher
로 암호화하는 기능을 하는 메서드로 보입니다.
func _rawHashValue(seed: Int) -> Int
원시 최상위 해싱 인터페이스. 일부 표준 라이브러리 타입(주로 기본 라이브러리)은 이를 전문화하여 작은 복원력 오버헤드를 제거합니다.
소스 코드 주석에 딱 이렇게만 쓰여있어서 으잉? 하고 따로 공식문서가 있는지 찾아보았으나... 이 메서드에 대한 공식 문서는 없더라고요. 그래서 이 부분은 몰루? 상태로 넘어가야될 거 같습니다.. (더 성장해서 오겠습니다😅)
Hash
자체는 데이터의 암호화를 위해 사용되는 알고리즘입니다.
Swift에서는Dictionary
나Set
의 특정 요소를 검색하기 위한 수단으로 많이 사용됩니다.Array
와 다르게 순서라는 개념이 존재하지 않기 때문이죠.
오늘은 간단하게 Hashable
에 대해 공부해보았습니다.
연말이다보니, 조금은 드문드문 포스팅하고 있지만... 다음주부터는 열심히 올리려고 합니다!