UnicodeScalar
유니코드 문자 1개에 해당하는 코드 포인트값을 담고 있는 데이터이다. UnicodeScalar
는 4바이트 유니코드 값 1개에 대응되기 때문에 UInt32
타입으로 변환하거나, UInt32
값으로부터 생성해낼 수 있다.
let i:Uint32 = 0xac01
let c = UnicodeScalar(i)
print(c)
let v:UInt32 = c.value
Swift의 Character
타입은 글자 1개를 나타내는 자료형이지만, 유니코드 문자 중에서는 여러 개의 코드 값이 하나로 합쳐진 글자들이 있기 때문에 1개의 Character
타입 값은 1개 혹은 그 이상의 UnicodeScalar
값으로 표현된다.
예를 들어 한글 "학"
은 1개의 글자로 그 자체로 유니코드 코드포인트 값 1개에 대응될 수도 있지만, 한글자모 "ㅎ" + "ㅏ" + "ㄱ"
의 조합일 수도 있다. 이 경우에는 코드 포인트값은 3개이지만, 글자로는 1개로 취급된다.
예를 들어 한글 “학”의 경우를 보자.
let a = "학"
let c = a.unicodeScalars[a.unicodeScalars.startIndex].value
print(String(format:"0x%x", c))
// 0xd559 (45617)
print("학 ==> 학")
print("글자 수: \(a.characters.count)") // 1
print("코드 수: \(a.unicodeScalars.count)") //
print("\n")
"학"
의 유니코드 코드포인트 값은 45617
로 하나의 코드로 된 문자이다. 그리고 당연히 1개의 글자로 되어 있다. 이를 유니코드의 초중종성 분리를 통해 각각의 자모로 분리해보자.
// 각각의 자모 인덱스로 분리
let x = (c - 0xac00) / 28 / 21
let y = ((c - 0xac00) / 28) % 21
let z = (c - 0xac00) % 28
// 각각의 자모 인덱스로부터 자모 코드값 생성
let i = UnicodeScalar(0x1100 + x) // 0x1100 -> 초성 'ㄱ'
let j = UnicodeScalar(0x1161 + y) // 0x1161 -> 중성 'ㅏ'
let k = UnicodeScalar(0x11a6 + 1 + z) // 0x11A6 -> 종성 {받침없음}
print("분해된 자모: \(i), \(j), \(k)")
// 분해된 자모: ㅎ, ㅏ, ㄱ
이 때 분해된 각 자모의 값은 0x1112
, 0x1161
, 0x11A8
이 된다. 이 자모코드값을 이용해서 문자열 "학"
은 다음과 같이 쓸 수 있다.
let compositedString = "\u{1112}\u{1161}\u{11A8}"
print("자모코드를 합성한 문자열: \(compositedString)")
// 학
이 세 개의 자모 코드는 하나의 문자를 표시하도록 조합되기 때문에, 표현상 한 글자 짜리 문자열이 된다.
print("ㅎㅏㄱ ==> 학")
print("글자 수: \(compositedString.characters.count)") // 1
print("코드 수: \(compositedString.unicodeScalars.count)") // 3
하지만 글자 수는 1개이지만 학(0xD559)
와 달리 3개의 코드포인트로 저장되어 있고 표시하는 글자는 같다. 그리고 이 두 개는 문자열로 표현되는 경우 내부에 저장된 데이터는 각각 다르지만
print(a == compositedString)
// true
동일한 값으로 간주된다.
다루는 방법
문자열 타입에서 .unicodeScalars
프로퍼티를 이용해서 해당 문자열의 유니코드 코드 포인트뷰를 얻을 수 있다. 이는 UnicodeScalarView
타입으로, Slicable
, SequenceType
, ExtensibleCollectionType
, RangeReplaceableColloectionType
등의 프로토콜을 따르고 있어서 배열과 유사하게 서브스크립팅을 하거나 append, insert, remove등의 조작을 통해 manipulate할 수 있다.
또한 앞서 언급한 바와 같이 내부적으로 하나의 코드 포인트는 UInt32
타입의 정수값으로 취급되므로, 유니코드 스칼라 타입을 이용하여 유니코드 코드값을 문자로 변환하는 것도 가능하다.