ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Swift] - Character와 EGC(Extended Grapheme Cluster)
    iOS/SWIFT 2025. 3. 14. 11:26
    728x90
    반응형

    학습을 하다 알게된 점이 생겨 급하게 포스팅을 한다.

    과제로 코드를 작성하다가 문득 이런 생각이 들었다.

    Character는 거의 사용해본적이 없는데 무슨 용도일까?

     

    이 의문을 해결하기 위해 Character를 처음부터 조사하기 시작했다.

     

    바로 본론으로 가보자

    let text = "ㅁㄴㅇㄹ"
    let chars: [Character] = Array(text)	//["ㅁ", "ㄴ", "ㅇ", "ㄹ"]

     

    "ㅁㄴㅇㄹ"은 4개의 한글 자음으로 구성된 문자열이고, 개별 문자(Character)들은 각각 하나의 유니코드 스칼라로 표현된다.

    Array(text)를 호출하면 Swift는 String을 Character 배열로 분리한다.

     

    자 여기서 유니코드 스칼라가 뭐냐

     

    유니코드 스칼라 (Unicode Scalar)

     

    U+0000 ~ U+10FFFF 범위 내의 숫자 값으로  유니코드(Unicode)에서 특정 문자를 표현하는 가장 기본적인 단위

     

    예시)

    A U+0041
    U+AC00
    🔥 U+1F525
    👩‍🚀 여러 개의 유니코드 스칼라

     

    여기서 눈에 띄는 점은 유니코드 스칼라가 여러개가 존재한다는 것이다. 

    그 말은 즉, 어떤 문자는 하나 이상의 유니코드 스칼라로 표현될 수 있다는 점이다.

     

    여기서 우린 EGC를 알아야한다.

     

    EGC(Extended Grapheme Cluster)

     

    사용자가 “한 글자”라고 인식하는 문자 단위

     

    맨 위에서 본 한글의 자음인 "ㅁ,ㄴ,ㅇ,ㄹ" 들도 예시에서 봤던 "👩‍🚀"도 다 "한 글자"인 문자 단위다.

     

    "👩‍🚀" <- 이런 복잡한 이모지나 한글 같은 경우 자음과 모음의 합이기 때문에 유니코드 스칼라로 표현하면 여러개다.

    하지만 EGC로 표현하면 한개로 인식한다.

     

    예제로 보자

    let koreanText = "가"
    let emojiText = "👩‍🚀"
    
    // 유니코드 스칼라 개수 출력
    print(koreanText.unicodeScalars.count)	//2
    print(emojiText.unicodeScalars.count)	//5
    
    print(koreanText.count)	//1
    print(emojiText.count)	//1

     

     

    그래서 하고 싶은 말이 무엇이냐.

     

    실제로는 몇 개의 유니코드를 가지고 있어도 내부적으로는 EGC로 취급한다는 얘기다. (신기하군..)

    Character의 내부는 각기 다른 유니코드 스칼라를 연속적으로 저장해 메모리 주소를 불러오는 방식을 사용한다.

    그래서 우리는 Character를 하나의 문자로 다룰 수 있다.

     

    그러면 [Character]는 어떻게 처리될까?

     

    우리는 Array의 특징을 이렇게 알고 있을 것이다. (연속적으로 데이터를 할당하는 방식을 사용하는 컬렉션 타입)

     

    하지만 [Character] 타입의 경우, 각 문자(즉, Character 객체)가 표현하는 유니코드 스칼라의 개수가 다르기 때문에, 실제 메모리에서 연속적으로 데이터를 할당할 수 없다. 예를 들어, “가”는 두 개의 유니코드 스칼라()로 이루어져 있고, “👩‍🚀”는 여러 유니코드 스칼라가 결합된 EGC다.

     

    따라서 [Character]는 문자 하나하나가 각기 다른 크기를 가지기 때문에, 연속 할당 방식 대신 비연속 할당 방식을 사용한다. 즉, 각기 다른 유니코드를 저장하고, 각 저장된 메모리의 주소를 연속적으로 할당하는 방식으로 [Character]가 사용된다.

     

    String 타입도 마찬가지다. 예를 들어, "가👩‍"와 같은 문자열의 경우, Swift의 String은 실제로 비연속 할당 방식을 사용한다. 그 이유는 String이 각각 다른 유니코드 스칼라들을 포함하고 있기 때문이다. 각 문자들이 가질 수 있는 크기구성 요소가 다르므로, String은 메모리에서 연속적인 할당을 사용하지 않고 비연속적인 할당 방식으로 다룬다.

     

    정리하자면 Charcter자체는 연속적으로 메모리에 할당되지만, Character가 여러개인 [Charcter]는 각 요소별로 크기가 다르기 때문에 각각의 요소는 다른 메모리에 저장되는 것이다. (예 : ㄱ - 0x0001,ㅏ - 0x0002, 👩‍🚀의 한 조각 - 0xaa111)

     

    조금만 깊게 생각해보니 개념 자체는 알 것 같다.

    이 부분을 고려해 코드를 작성하면 더 도움이 될것이다.

    'iOS > SWIFT' 카테고리의 다른 글

    [Swift] - 배열 루프를 순회하는 방식(enumerated,indices,Range(0..<arr.count))  (0) 2025.03.20
    [Swift] - mutating  (0) 2024.02.06
    [SWIFT] - 제네릭(Generic)  (0) 2023.06.14
    [SWIFT] Lazy #8  (1) 2022.12.19
    [SWIFT] 타입프로퍼티 #7  (0) 2022.10.10
Designed by Tistory.