인코딩과 로케일
인코딩과 로케일 (Encodings and Locales)
Racket에서 바이트 스트림과 문자 간의 변환이 어떻게 이뤄지는지, 그리고 언어별 문자열 해석을 담당하는 로케일이 무엇인지 알아봐요. 포트에서 문자를 읽을 때의 UTF-8 규칙과 로케일 매개변수 동작을 다룹니다.
출처: Racket Reference
본문
13.1.1 인코딩과 로케일
포트가 read-char나 read 같은 문자 기반 연산에 제공되면, 포트의 바이트를 읽어 문자들의 UTF-8 인코딩으로 해석합니다. 따라서 단일 문자를 읽으려면 여러 바이트를 읽어야 할 수 있고, char-ready? 같은 프로시저는 문자가 사용 가능한지 판단하기 위해 스트림에서 여러 바이트를 peek해야 할 수 있어요. 유효한 UTF-8 인코딩에 해당하지 않는 바이트 스트림의 경우, read-char 같은 함수는 스트림이 유효한 인코딩이 아님을 알아내기 위해 스트림에서 한 바이트 앞을 peek해야 할 수도 있어요.
입력 포트가 문자를 읽는 맥락에서 유효한 UTF-8 인코딩이 아닌 바이트 시퀀스를 만들면, 유효하지 않은 시퀀스를 구성하는 바이트는 문자 #\uFFFD로 변환됩니다. 구체적으로, 바이트 255와 254는 항상 #\uFFFD로 변환되고, 192에서 253 범위의 바이트는 유효한 UTF-8 인코딩을 형성하는 바이트가 뒤따르지 않으면 #\uFFFD를 만들며, 128에서 191 범위의 바이트는 앞선 192~253 범위의 바이트가 시작한 유효한 인코딩의 일부가 아니면 #\uFFFD로 변환돼요. 달리 말하면, 일련의 바이트를 문자로 읽을 때, 전체 바이트 시퀀스가 유효한 UTF-8 인코딩이 되도록 최소한의 바이트 집합만 #\uFFFD의 인코딩으로 바꿔요.
UTF-8이나 다른 인코딩을 사용한 변환을 돕는 프로시저는 Byte Strings을 참고하세요. 다른 문자 인코딩을 쓰는 포트로부터 UTF-8 기반 포트를 얻으려면 reencode-input-port와 reencode-output-port도 참고하세요.
로케일(locale)은 사용자의 언어별 문자 시퀀스 해석에 대한 정보를 담습니다. 특히 로케일은 문자열이 어떻게 "알파벳순으로 정렬"되는지, 소문자가 대문자로 어떻게 변환되는지, 그리고 대소문자를 무시하고 문자열을 어떻게 비교하는지를 결정해요. string-ci=? 같은 문자열 연산은 현재 로케일에 민감하지 않지만, string-locale-ci=? 같은 연산은(〔Strings〕 참고) 현재 로케일과 일관된 결과를 만들어요.
로케일은 또한 코드 포인트 시퀀스를 바이트 시퀀스로 인코딩하는 특정 방식을 지정합니다. Racket은 일반적으로 로케일의 이 측면을 무시하는데, 몇 가지 눈에 띄는 예외가 있어요: Racket에 바이트 문자열로 전달된 명령줄 인자는 로케일의 인코딩을 사용해 문자 문자열로 변환되고; 다른 프로세스에 바이트 문자열로 전달되는 명령줄 문자열은(〔subprocess〕 통해) 로케일의 인코딩을 사용해 바이트 문자열로 변환되며; 환경 변수는 로케일의 인코딩을 사용해 문자열과 상호 변환되고; 파일 시스템 경로는 (표시 목적으로) 로케일의 인코딩을 사용해 문자열과 상호 변환되며; 마지막으로 Racket은 string->bytes/locale 같은 함수를 제공해 로케일별 인코딩을 명시적으로 호출할 수 있게 합니다.
Unix 사용자는 LC_ALL 같은 환경 변수를 설정해 로케일을 선택합니다. Windows와 Mac OS에서는 운영 체제가 로케일을 설정하는 다른 메커니즘을 제공해요. Racket 내부에서는 current-locale 매개변수를 설정해 현재 로케일을 바꿀 수 있어요. Racket 안의 로케일 이름은 문자열이고, 사용 가능한 로케일 이름은 플랫폼과 그 구성에 따라 달라지지만, "" 로케일은 현재 사용자의 기본 로케일을 뜻합니다. Windows와 Mac OS에서 ""의 인코딩은 항상 UTF-8이고, 로케일 민감 연산은 운영 체제의 네이티브 인터페이스를 사용해요. (특히 Mac OS에서 LC_ALL과 LC_CTYPE 환경 변수를 설정하는 것은 로케일 ""에 영향을 주지 않습니다. 원하면 getenv와 current-locale을 사용해 환경이 지정하는 로케일을 명시적으로 설치하세요.) 현재 로케일을 #f로 설정하면 로케일 민감 연산이 로케일 비민감이 되는데, 이는 대소문자 연산에 유니코드 매핑을 사용하고 인코딩에 UTF-8을 사용한다는 뜻이에요.
(current-locale) → (or/c string? #f)(current-locale locale) → void? locale : (or/c string? #f)
string-locale-ci=? 같은 프로시저의 현재 로케일을 결정하는 parameter예요.
매개변수를 #f로 설정해 로케일 민감성을 비활성화하면, 문자열이 완전히 이식 가능한 방식으로 비교되는데, 이는 표준 프로시저와 같아요. 그 외에는 문자열이 로케일 설정에 따라(C 라이브러리의 setlocale 의미로) 해석됩니다. "" 로케일은 항상 현재 머신의 기본 로케일에 대한 별칭이고, 기본값이에요. "C" 로케일도 항상 사용 가능한데, 로케일을 "C"로 설정하는 것은 문자열 연산이 처음 128개 문자로 제한될 때만 #f로 로케일 민감성을 비활성화하는 것과 같아요. 다른 로케일 이름은 플랫폼별로 다릅니다.
write로 문자열이나 문자를 출력하는 것은 이 매개변수의 영향을 받지 않고, 심볼의 대소문자나 정규식도 마찬가지예요 (〔Regular Expressions〕 참고).