
애플은 최근 몇 달간 온갖 버그로 골머리를 앓고 있습니다. 그런데 이번에는 아이폰의 텍스트 렌더링 기능에서 심각한 새로운 버그가 발견되었습니다. 텔루구(Telugu) 문자 하나가 문제를 일으키는데, 해당 문자가 포함된 알림을 받기만 해도 아이폰이 끝없는 부팅 루프에 빠질 수 있습니다. 왜 단 한 글자가 iOS에 이렇게 큰 문제를 일으키는지 자세히 살펴보겠습니다.
참고: 텔루구 문자 버그에 대한 수정 사항은 최신 버전의 iOS(11.2.6)에서 제공됩니다. 텔루구 문자 때문에 앱이나 기기가 멈춘 경우 iTunes를 통해 아이폰을 복원한 뒤 최신 버전의 iOS로 업데이트하세요. 아이폰이 부팅 루프에 갇혀 있다면 iTunes가 기기를 인식할 수 있도록 DFU(Device Firmware Update) 모드로 진입해야 할 수도 있습니다. 복원이 끝나면 미리 만들어 둔 최신 백업본에서 기기를 복원하세요.
텔루구란 무엇일까?

텔루구는 인도의 안드라프라데시 주와 텔랑가나 주, 그리고 야남(Yanam) 지역에서 사용되는 언어입니다. 아랍어 등 다른 브라흐미(Brahmic) 계열 문자 언어들과 마찬가지로, 텔루구는 유니코드 문자 집합의 특수 기능을 활용해 컴퓨터 화면에 글자를 표시합니다.
대부분의 라틴 문자는 ASCII 호환성을 위해 단일 8비트 유니코드 코드 포인트로 표현됩니다(예: 영문 대문자 A는 유니코드 코드 포인트 U+0041, 즉 2진수 01000001로 표현됩니다). 반면 스크립트 문자나 비라틴 문자를 사용하는 언어들은 일반적으로 여러 개의 유니코드 코드 포인트를 조합해 하나의 글자를 나타냅니다.
텔루구처럼 글자들을 클러스터(cluster) 형태로 결합하는 언어에서는 특히 그렇습니다. 영어의 장식용 합자(ligature)와 달리, 텔루구 글자들 사이의 연결은 언어학적으로 중요한 의미를 지닙니다. 이를 지원하기 위해 유니코드는 각각 고유한 코드 포인트를 가진 문자들을 서로 결합하는 복잡한 시스템을 갖추고 있습니다.
유니코드 코드 포인트의 방대한 수를 고려하면 거의 무한에 가까운 조합이 가능합니다. 이 코드 포인트들이 결합하여 읽을 수 있는 글자로 렌더링되는 것입니다. 덕분에 유니코드는 가능한 모든 텔루구 단어마다 별도의 코드 포인트를 할당할 필요가 없습니다. 대신 텔루구의 자음, 모음, 그리고 발음 구별 부호('비라마/virama')를 조합해 마치 하나의 글자처럼 보이는 단어를 만듭니다. 합자 규칙이 있는 아랍어 같은 다른 언어에도 동일한 원리가 적용됩니다.
크래시의 원인은 무엇일까?

문제는 코드 포인트 U+200C에 위치한 ZWNJ(Zero Width Non-Joiner, 폭 없는 비연결자)와 관련된 것으로 보입니다. ZWNJ는 인접한 두 문자가 일반적인 합자 형태로 연결되지 않도록 요청하는 제어 문자입니다. 영어에서는 ZWNJ가 ff가 표준 연결 합자로 인쇄되지 않게 하여 f 두 개를 분리해 표시합니다. 그런데 특정 네 개의 텔루구 코드 포인트(모두 하나의 클러스터로 결합되어야 함)와 결합하면, 어떤 이유에서인지 iOS가 결과물을 제대로 표시하지 못합니다.
애플의 San Francisco 폰트가 해당 문자를 표시하지 못한다는 설과, 애플이 사용하는 특정 렌더링 프로세스가 원인이라는 설이 있습니다. 정확한 원인이 무엇이든, 이 문자를 렌더링하려는 시도는 메시지와 WhatsApp부터 Springboard까지 렌더링을 담당하는 모든 프로그램을 극적으로 크래시시킵니다. 해당 문자('gya', '지식'을 의미)를 구성하는 유니코드 코드 포인트는 다음과 같습니다:
U+0C1Cja (
)U+0C4D비라마(virama), 즉 발음 구별 기호 (
)U+0C1Enya (
)U+200CZWNJ(폭 없는 비연결자)U+0C3Eaa (
)
하지만 ZWNJ만 탓할 수는 없습니다. ZWNJ는 무해한 가족 이모지(????)에서도 아무 문제 없이 사용됩니다. 특정 코드 포인트들의 특정 조합과 ZWNJ가 만나야 문제가 발생하는 것으로 보입니다. 더욱 아이러니한 점은, ZWNJ가 이 텔루구 클러스터의 렌더링에 실제로 아무런 영향을 주지 않거나, 애초에 존재해서는 안 되는 문자라는 사실입니다.
다른 브라흐미 계열 문자의 문제
텔루구만 이 문제를 겪는 것은 아닙니다. 벵골어와 데바나가리처럼 브라흐미 계열 문자에 유니코드를 비슷한 방식으로 사용하는 언어들도 같은 문제를 겪습니다. Manish Goregaokar는 정확한 크래시 사례를 더 깊이 분석한 흥미롭고 상세한 블로그 글을 작성했습니다:
데바나가리, 벵골어, 텔루구에서 다음 조건을 모두 만족하는 임의의 시퀀스
<consonant1, virama, consonant2, ZWNJ, vowel>:1.
consonant2가 후방 결합형(pstf/vatu)일 것
2.consonant1이 reph 형태를 만드는 글자가 아닐 것
3.vowel이 두 개의 글리프 구성 요소를 갖지 않을 것
결론: 애플은 왜 이 버그를 놓쳤을까?
이 버그가 어떻게 출시 과정을 통과했는지 이해하려면 애플의 입장이 되어볼 필요가 있습니다. 물론 이 문자 조합이 텔루구어에서 극히 드문 단어는 아닙니다. 하지만 아이폰은 수십 개 언어를 지원하며, 유니코드에는 문자 그대로 수십억 가지의 잠재적 조합이 존재합니다. 이렇게 방대한 경우의 수 속에서 출시 전에 유니코드 버그를 철저히 테스트하려면 정기적인 소프트웨어 업데이트 자체가 불가능해집니다.
그럼에도 이 오류가 이토록 큰 피해를 일으켜서는 안 됩니다. 문자 메시지 내용 때문에 휴대폰이 벽돌이 되어서는 안 됩니다. 돌이켜보면 당연한 이야기지만, Springboard를 크래시시키는 것보다는 해당 문자를 물음표 상자()로 표시하는 편이 훨씬 나았을 것입니다.