Following system colour scheme Selected dark colour scheme Selected light colour scheme

Python 개선 제안 한국어 번역

PEP 261 – “와이드” 유니코드 문자 지원

Author:
Paul Prescod <paul at prescod.net>
Status:
Final
Type:
Standards Track
Created:
27-Jun-2001
Python-Version:
2.2
Post-History:
27-Jun-2001

Table of Contents

번역·라이선스 안내

이 비공식 한국어 번역은 원문 Copyright 절의 Public Domain 조건에 따라 제공합니다. 원저자와 공식 원문은 그대로 표시합니다. 수정되지 않은 기준 원문 · 공식 최신판

초록

Python 2.1의 유니코드 문자는 2**16 - 1까지의 서수 값만 가질 수 있습니다. 이 범위는 유니코드에서 기본 다국어 평면(Basic Multilingual Plane)이라고 알려진 범위에 해당합니다. 현재 유니코드에는 다른 “평면”에 속하는 문자들도 있습니다. 유니코드에서 주소 지정이 가능한 가장 큰 문자의 서수 값은 17 * 2**16 - 1 (0x10ffff)입니다. 가독성을 위해 이 값을 TOPCHAR라고 부르고, 이 범위에 있는 문자를 “와이드 문자”라고 부르겠습니다.

용어집

문자
단독으로 쓰일 때는 Python 유니코드 문자열에서 주소 지정이 가능한 단위를 의미합니다.
코드 포인트
코드 포인트는 0과 TOPCHAR 사이의 정수입니다. 유니코드를 정수에서 문자로의 매핑이라고 생각한다면, 각 정수가 코드 포인트입니다. 하지만 0과 TOPCHAR 사이의 정수 중 문자에 매핑되지 않는 정수도 코드 포인트입니다. 그중 일부는 언젠가 문자에 사용될 것입니다. 일부는 절대 문자에 사용되지 않는 것이 보장됩니다.
코덱
물리적 인코딩(예: 디스크에 있거나 네트워크에서 들어오는 것)과 논리적인 Python 객체 사이를 변환하는 함수들의 집합입니다.
인코딩
추상적인 문자를 물리적인 비트와 바이트로 표현하는 메커니즘입니다. 인코딩을 사용하면 다른 유니코드 소프트웨어와 호환되는 방식으로 유니코드 문자를 디스크에 저장하고 네트워크를 통해 전송할 수 있습니다.
서로게이트 쌍
하나의 논리적 문자를 나타내는 두 개의 물리적 문자입니다. 32비트 코드 포인트를 두 개의 16비트 코드 포인트로 표현하기 위한 규약의 일부입니다.
유니코드 문자열
“문자열 의미론”(예: 대소문자 변환, 정규 표현식 호환성 등)을 갖는 코드 포인트의 시퀀스를 나타내는 Python 타입입니다. unicode() 함수로 생성합니다.

제안하는 해결책

한 가지 해결책은 단순히 최대 서수 값을 더 큰 값으로 늘리는 것입니다. 안타깝게도 이 아이디어를 간단하게 구현하는 유일한 방법은 문자당 4바이트를 사용하는 것입니다. 이렇게 하면 대부분의 유니코드 문자열 크기가 두 배로 늘어납니다. 모든 사용자에게 이 비용을 부담시키지 않도록, Python 2.2는 4바이트 구현을 빌드 시점 옵션으로 허용할 것입니다. 사용자는 와이드 문자를 중시할지, 아니면 메모리를 절약하는 쪽을 택할지 선택할 수 있습니다.

4바이트 옵션은 “wide Py_UNICODE”라고 부릅니다. 2바이트 옵션은 “narrow Py_UNICODE”라고 부릅니다.

대부분의 동작은 wide 환경과 narrow 환경에서 똑같습니다.

  • 0 <= i < 2**16 (0x10000)에 대해 unichr(i)는 항상 길이가 1인 문자열을 반환합니다.
  • 2**16 <= i <= TOPCHAR에 대해 unichr(i)는 wide Python 빌드에서 길이가 1인 문자열을 반환합니다. narrow 빌드에서는 ValueError를 발생시킵니다.

    쟁점

    현재 Python에서는 Python 문자 하나로 표현할 수 없는 \U 리터럴도 허용합니다. 이 경우 “서로게이트 쌍(surrogate pair)”이라고 부르는 Python 문자 두 개가 만들어집니다. 앞으로 narrow Python 빌드에서는 이를 금지해야 합니까?

    찬성:

    Python은 이미 큰 유니코드 리터럴 문자 이스케이프 시퀀스에 대해 서로게이트 쌍을 구성하는 것을 허용합니다. 이는 기본적으로 narrow Python 빌드에서도 “와이드 문자”를 간단히 만들 수 있도록 설계된 것입니다. 이는 유니코드 리터럴 문법이 기본적으로 unicode-escape 코덱을 호출하는 짧은 형식의 방법이라는 점을 고려하면 어느 정도 논리적이기도 합니다.

    반대:

    이 방식으로 서로게이트를 쉽게 만들 수는 있지만, 사용자는 여전히 슬라이싱, 인덱싱, 출력 등에 주의해야 합니다. 그래서 유니코드 리터럴이 서로게이트를 지원하지 않아야 한다는 의견도 있었습니다.

    쟁점

    유니코드 코드 포인트에 해당하지 않는 문자도 Python에서 만들 수 있게 해야 합니까? 할당되지 않은 유니코드 코드 포인트는 당연히 허용해야 합니다(언제든 할당될 수 있기 때문입니다). 그러나 TOPCHAR보다 큰 코드 포인트는 유니코드에서 절대 사용하지 않는다는 것이 보장됩니다. 그래도 이러한 코드 포인트에 접근할 수 있도록 허용해야 합니까?

    찬성:

    Python 사용자가 자신이 무엇을 하는지 안다고 생각한다면, 유니코드 명세를 어기지 못하도록 굳이 막아야 할 이유가 있습니까? 어쨌든 8비트 문자열에 ASCII가 아닌 문자가 들어가는 것도 막지 않습니다.

    반대:

    코덱을 비롯해 유니코드를 처리하는 코드는 유니코드 명세에서 허용하지 않는 이러한 문자에 주의해야 합니다.
  • ord()는 항상 unichr()의 역함수입니다.
  • sys 모듈에는 현재 인터프리터에서 유니코드 문자열에 들어갈 수 있는 문자의 가장 큰 서수를 나타내는 정수 값이 있습니다. sys.maxunicode는 Python의 좁은 빌드에서는 2**16-1(0xffff)이고, 넓은 빌드에서는 TOPCHAR입니다.

    쟁점:

    TOPCHAR와 unichr의 실제 정의역 상한이 서로 다르다면, 각각에 접근하는 상수를 따로 두어야 합니까? 'wide'와 'narrow' 값을 가질 수 있는 sys.unicodewidth를 두자는 제안도 있었습니다.
  • 모든 Python 유니코드 문자는 정확히 하나의 유니코드 코드 포인트를 나타냅니다(즉, Python 유니코드 문자 = 추상 유니코드 문자입니다).
  • 코덱은 “와이드 문자”(UCS-4에서는 직접 표현되고, UTF-8과 UTF-16에서는 가변 길이 시퀀스로 표현됨)를 지원하도록 업그레이드될 것입니다. 이것이 구현에서 아직 남아 있는 주요 부분입니다.
  • 유니코드 세계에는 32비트 코드 포인트를 두 개의 16비트 코드 포인트로 인코딩하는 관례가 있습니다. 이를 “서로게이트 쌍”이라고 합니다. Python의 코덱은 이 관례를 채택하여, 좁은 Python 빌드에서 32비트 코드 포인트를 서로게이트 쌍으로 인코딩할 것입니다.

    쟁점

    코덱이 서로게이트를 생성하지 않고 대신 와이드 문자를 오류로 처리하도록 지시하는 방법이 있어야 합니까?

    찬성:

    고정 폭 문자만 다루고 서로게이트는 신경 쓸 필요가 없는 코드를 작성하고 싶을 수도 있습니다.

    반대:

    이를 코덱에 어떻게 전달할지에 대한 명확한 제안이 없습니다.
  • “서로게이트용으로 예약된” 코드 포인트를 부적절하게 사용하는 문자열을 만드는 데에는 아무런 제한이 없습니다. 이를 “고립된 서로게이트”라고 합니다. 코덱은 파일에서 이러한 문자를 읽어 들이는 것을 허용하지 않아야 하지만, 문자열 리터럴이나 unichr()를 사용하여 만들 수는 있습니다.

구현

새로운 define이 있습니다:

#define Py_UNICODE_SIZE 2

UCS2와 UCS4 중 어느 것이 사용 중인지 확인하려면 파생 매크로 Py_UNICODE_WIDE를 사용해야 하며, 이 매크로는 UCS-4가 사용 중일 때 정의됩니다.

새로운 configure 옵션이 있습니다:

–enable-unicode=ucs2 좁은 Py_UNICODE를 구성하며, 크기가 맞으면 wchar_t를 사용합니다
–enable-unicode=ucs4 넓은 Py_UNICODE를 구성하며, 크기가 맞으면 wchar_t를 사용합니다
–enable-unicode “=ucs2”와 같습니다
–disable-unicode 유니코드 기능을 완전히 제거합니다.

또한 언젠가는 --enable-unicode가 단순히 플랫폼의 wchar_t 폭을 기본값으로 사용하도록 하자는 제안도 있습니다.

Windows 빌드는 당분간 좁은 빌드로 유지될 것입니다. 넓은 문자에 대한 요청이 거의 없었고, 그 요청도 대부분 자신의 Python을 직접 구할 능력이 있는 숙련된 프로그래머들에게서 나왔으며, Windows 자체가 16비트 문자에 강하게 치우쳐 있기 때문입니다.

참고 사항

이 PEP는 유니코드를 사용하는 사람들이 디스크에 저장하거나 네트워크로 전송하는 파일에 4바이트 인코딩을 사용해야 한다는 뜻이 결코 아닙니다. 단지 그렇게 할 수 있도록 허용할 뿐입니다. 예를 들어, ASCII는 여전히 유효한 (7비트) 유니코드 인코딩입니다.

프로그래머를 위해 좁은(narrow) Python 빌드에서 서로게이트를 처리하는 모듈을 두어야 한다는 제안이 있었습니다. 누군가 이를 구현하려 한다면 그것은 별도의 PEP가 될 것입니다. 이는 문자, 단어, 줄 단위의 다른 종류의 인덱싱을 가능하게 하는 기능과 결합될 수도 있습니다.

거부된 제안

대체로 현상 유지

Python 문자는 16비트라고 공식적으로 정하고, 프로그래머가 서로게이트 쌍을 조합하여 애플리케이션 로직에서 넓은(wide) 문자를 직접 구현하도록 요구할 수도 있습니다. 32비트 문자를 전부 Python으로 작성해 에뮬레이션하면 매우 비효율적일 가능성이 높으므로 이는 큰 부담이 됩니다. 게다가 이렇게 추상화된 유사 문자열은 정규 표현식 엔진의 입력으로 허용되지 않습니다.

“공간 효율적인 유니코드” 타입

또 다른 유형의 해결책은 내부적으로는 효율적인 저장 방식을 사용하되 프로그래머에게는 넓은 문자라는 추상화를 제공하는 것입니다. 이러한 방식은 모두 채택된 해결책보다 훨씬 더 복잡한 구현을 필요로 합니다. 예를 들어 정규 표현식 엔진에 미치는 영향을 생각해 보십시오. 이론적으로는 향후 Python 코드를 깨뜨리지 않고 이 구현으로 옮겨 갈 수 있습니다. 향후의 Python은 좁은 Python에서 넓은 Python의 의미 체계를 “에뮬레이션”할 수도 있습니다. Guido는 지금 당장 그 구현을 맡을 의향이 없습니다.

두 개의 타입

16비트 타입과 함께 32비트 유니코드 타입을 도입할 수도 있습니다. 유니코드 타입이 단 하나만 있다고 가정하는 코드가 많습니다.

이 PEP는 가장 적은 노력이 드는 해결책입니다. 앞으로 몇 년 동안 32비트 유니코드 문자는 더 흔해질 것이며, 그에 따라 더 정교한 해결책이 필요하다는 확신을 얻게 되거나, (반대로) 단순히 넓은 유니코드 문자를 의무화하는 것이 적절한 해결책이라는 확신을 얻게 될 수도 있습니다. 현재 검토 중인 두 가지 선택지는 아무것도 하지 않는 것과 이 PEP를 따르는 것입니다.

참고 문헌

유니코드 용어집: http://www.unicode.org/glossary/