유니코드를 떠도는 유령 문자 — 존재하지 않는 한자가 표준에 남은 사연

어느 사전에도 없고, 아무도 읽는 법을 모르는 한자 열두 자가 오늘도 전 세계 모든 컴퓨터의 문자표 안에 살아 있다. 이것은 지우면 그만인 단순한 오타인가, 아니면 모든 표준이 짊어질 수밖에 없는 하위 호환성의 숙명인가.

도입

지금 당신이 쓰는 컴퓨터의 문자표 어딘가에는 彁라는 한자가 들어 있다. 이 글자는 유니코드 코드포인트 U+5F41로 정식 등록되어 있고, 일본어 입력기로 변환하면 후보에 뜨며, 웹페이지에도 문제없이 표시된다. 단 하나 문제가 있다. 아무도 이 글자가 무슨 뜻인지, 어떻게 읽는지 모른다는 것이다. 어느 한자 사전에도 이 글자의 표제어는 없다. 애초에 이 글자를 실제로 쓴 문헌이 세상에 존재하지 않는다. 그런데도 이 글자는 반세기 가까이 국가 표준과 국제 표준에 정식 등재된 채, 우리가 매일 쓰는 운영체제와 폰트 안에서 조용히 자리를 차지하고 있다.

폴 오리어리 매캔(Paul O’Leary McCann)은 자신의 블로그에 쓴 글 「A spectre is haunting Unicode(유령이 유니코드를 떠돈다)」에서 이런 글자들을 가리키는 일본어 표현을 소개한다. 유령 문자(幽霊文字, ゆうれい文字). 실체가 없는데도 표준의 문자표를 배회하는, 말 그대로 유령 같은 한자들이다. 이 글자들은 어느 악의적 해커가 심어 넣은 것도, 최신 소프트웨어의 버그도 아니다. 1978년에 제정된 일본어 문자 코드 표준을 만드는 과정에서 벌어진 몇 건의 단순한 실수가, 표준이라는 그릇에 담기는 순간 영구히 박제된 결과다. 이 작은 사건은 문자 인코딩의 역사와 표준의 관성에 관한, 생각보다 훨씬 깊은 이야기로 이어진다.

유령 문자란 무엇인가 — 표준에 실린 정체불명의 한자

유령 문자는 일본의 문자 코드 표준 JIS 기본 한자 집합에 들어 있으면서도 출전을 알 수 없는(典拠不明) 한자를 총칭한다. 여기서 배경 설명이 필요하다. JIS(일본공업규격)는 유니코드가 널리 보급되기 전, 일본어 문자를 컴퓨터로 다루기 위해 만든 국가 표준 문자 집합이다. 그 시초가 1978년 제정된 JIS C 6226(뒤에 JIS X 0208로 이름이 바뀐다)이다. 이 표준은 일본어를 쓰는 데 필요한 수천 자의 한자를 코드번호와 짝지어 정리한 거대한 표였다.

문제는 일본의 한자 사용 방식에 있다. 일본의 지명(地名)과 인명(人名)에는 일반 한자 사전에 실리지 않는 희귀하고 특이한 글자가 대단히 많다. 어느 시골 마을 하나, 어느 집안의 성씨 하나를 정확히 표기하려 해도 표준에 그 글자가 없으면 컴퓨터로 처리할 수 없다. 그래서 표준을 만드는 사람들은 전국의 지명·행정구역을 망라한 방대한 자료들을 뒤져 실재하는 한자를 최대한 긁어모았다. 그 대표적 출전이 『국토행정구획총람(国土行政区画総覧)』이다. 7권짜리에 각 권이 900쪽 안팎에 이르는 이 자료는, 페이지 참조 없이 개별 글자를 검증하기가 사실상 불가능할 만큼 방대했다. 그 밖에도 『표준코드용 한자표(標準コード用漢字表)』(1971년), 『행정정보처리용 기본한자(行政情報処理用基本漢字)』(1975년), 그리고 지금은 실물이 남아 있지 않은 『일본생명 수용 인명한자(日本生命収容人名漢字)』(1973년) 같은 자료가 참조되었다.

이렇게 수천 자를 손으로 옮겨 담는 과정에서 오류가 스며들었다. 존재하지 않는 글자가 표준에 실린 것이다. 매캔이 소개하는 가장 유명한 사례가 妛라는 글자다. 이 글자의 유래는 이렇다. 시가현 다가정에 𡚴原(あけんばら, 아켄바라)라는 지명이 있었고, 여기 쓰인 𡚴는 山 위에 女를 얹은 합자(合字)였다. 그런데 이 글자가 활자에 없었다. 그래서 자료의 판을 짤 때 山과 女를 따로 인쇄해 오려 붙인 뒤 복사했다. 문제는 그다음이다. 오려 붙인 두 종잇조각이 만나는 경계선, 즉 겹친 자리의 그림자 같은 인쇄 흔적이 복사본에서는 하나의 획처럼 보였고, 옮겨 적는 사람이 이를 진짜 가로획으로 오인해 그대로 전사한 것이다. 그렇게 원래 없던 획이 하나 더 붙은 妛라는 글자가 탄생했다. 종잇조각의 그림자가 한자의 획으로 둔갑한 셈이다.

1997년, JIS X 0208의 개정 작업이 진행되면서 이 정체불명의 글자들이 대체 어디서 왔는지 추적하는 조사가 시작되었다. 개정 원안 작성 위원회에서 위원장 시바노 고지(芝野耕司)와 연구자 사사하라 히로유키(笹原宏之)가 중심이 되어 1978년 원안을 만들 때 참조한 문헌들을 되짚어 나갔다. 그 결과는 개정 규격의 부속서 7 「구점 위치 상설(区点位置詳説)」에 정리되었다. 사사하라는 妛의 유래를 밝혀냈고, 그 성과는 1998년에 발표되었다. 조사 끝에 원래 출전을 갖지 못한 채 남은 글자는 열두 자였다. 墸, 壥, 妛, 彁, 挧, 暃, 椦, 槞, 蟐, 袮, 閠, 駲. 그런데 이 가운데 열한 자는 옛 자서(字書)에서 우연히 같은 형태가 발견되는 암합(暗合) 사례가 있었다. 즉 실수로 만들어졌더라도 어쩌다 실재했던 글자와 모양이 겹친 것이다. 오직 彁 한 글자만이 어떤 옛 자서에서도 같은 형태를 찾을 수 없는, 매캔의 표현대로 “명확한 출전도 역사적 전례도 없는” 진짜 유령이었다. 유력한 설명은 彊 같은 글자를 잘못 베껴 쓴 결과라는 것이지만, 그 구체적 경위는 끝내 밝혀지지 않았다.

왜 오류를 지울 수 없는가 — 하위 호환성이라는 감옥

정체가 밝혀졌다면, 그냥 지우면 되지 않을까. 표준에서 이 열두 자를 삭제하면 깔끔하지 않은가. 그러나 바로 이 지점에서 표준의 관성이라는 냉혹한 논리가 작동한다. 결론부터 말하면, 지울 수 없다.

첫 번째 이유는 유니코드가 JIS를 그대로 상속했다는 사실이다. 1993년에 나온 유니코드 1.1 시점에 이미 JIS 기본 한자가 통째로 유니코드에 수록되어 있었다. 유니코드는 처음부터 각국의 기존 문자 표준을 통합하는 것을 목표로 삼았고, 그 과정에서 가장 중요하게 여긴 원칙 중 하나가 왕복 변환 호환성(round-trip compatibility)이었다. 즉 JIS로 인코딩된 텍스트를 유니코드로 바꿨다가 다시 JIS로 되돌렸을 때, 원래와 한 글자도 다르지 않게 복원되어야 한다는 요구다. 이 무손실 왕복을 보장하려면 JIS에 존재하는 모든 코드 위치가 유니코드에도 일대일로 대응하는 자리를 가져야 한다. 그 글자가 실재하든, 유령이든 상관없다. 표준에 코드번호가 부여된 이상, 그것은 변환의 사슬 전체에서 보존되어야 하는 하나의 항목이다. 유령 문자는 이 무손실 계약에 무임승차해 유니코드로 건너왔다.

두 번째 이유는 유니코드 자체의 안정성 정책(stability policy)이다. 유니코드 컨소시엄은 일단 부여된 코드포인트는 절대로 회수하거나 다른 글자에 재할당하지 않는다는 규칙을 명문화해 두었다. 이유는 명백하다. 세상에는 이미 이 코드포인트로 저장된 문서·데이터베이스·파일이 무수히 존재한다. 만약 U+5F41이 어제까지 彁를 가리키다가 오늘 다른 글자로 바뀐다면, 과거에 저장된 모든 데이터가 조용히 오염된다. 하나의 오류를 지우는 대가로 수십 년치 데이터의 정합성을 깨뜨리는 것이다. 그래서 유니코드는 오류조차 지우지 않는 쪽을 택했다. 한 번 사전에 잘못 인쇄된 오식이, 그 사전이 세상의 표준이 된 순간 모두가 영원히 재현해야 하는 규범으로 굳어버린 것과 같다.

여기서 더 근본적인 사실 하나를 짚어야 한다. 오류를 지우지 못하는 것은 유니코드만이 아니라 일본 자신의 표준도 마찬가지였다는 점이다. 1997년 조사로 유령 문자의 정체가 상당 부분 밝혀졌음에도, JIS X 0208 개정판은 이 열두 자를 규격에서 빼는 대신 부속서에 그 사연을 기록하는 길을 택했다. 이미 이 코드 위치를 쓰는 워드프로세서·전용기·데이터가 일본 전역에 깔려 있었기 때문이다. 표준을 고치는 쪽이 표준을 따르는 쪽보다 언제나 늦다는, 널리 채택된 규격의 근본적 비대칭이 여기서 드러난다. 게다가 JIS와 유니코드를 잇는 변환표 자체가 하나의 영구 유산이 된다. 두 표준을 오가는 매핑이 한번 고정되면, 그 매핑을 쓰는 모든 소프트웨어가 특정 코드 위치의 존재를 전제하게 되고, 그중 하나만 빼도 연쇄적으로 대응 관계가 어긋난다. 유령 문자를 지우는 일은 글자 하나를 지우는 것이 아니라, 그 글자를 전제로 짜인 거대한 대응망 전체를 흔드는 일이 된다.

HN(해커뉴스) 토론에서는 이 사안이 유니코드의 더 큰 논쟁, 즉 CJK 통합 한자(Han unification)와 연결된다는 지적이 나왔다. 유니코드는 16비트 공간의 제약과 실용적 판단 아래, 중국·일본·한국에서 모양이 비슷한 한자들을 하나의 코드포인트로 통합했는데, 이 때문에 겉보기에 같은 글자가 폰트에 따라, 즉 중국어용 폰트냐 일본어용 폰트냐에 따라 다르게 그려지는 문제가 생긴다는 것이다. 통합에 찬성하는 쪽은 이 작업이 언어학자와 문헌학자로 이뤄진 존중받는 전문가 집단의 신중한 결과물이라고 옹호했고, 반대하는 쪽은 통합된 글자와 통합되지 않은 글자가 뒤섞여 텍스트 검색과 언어 처리에 실질적 혼란을 낳는다고 비판했다는 취지의 논의가 오갔다. 또한 일단 코드포인트가 부여되면 오류라도 되돌릴 수 없다는 이 영속성 원칙 자체가, 레거시 데이터의 안전을 지키는 동시에 실수를 화석처럼 박제한다는 양면성이 반복해서 지적되었다. 유령 문자는 바로 이 양면성의 가장 순수한 표본인 셈이다. 무손실 호환성이라는 미덕과 오류의 영구 보존이라는 부작용은 같은 동전의 양면이며, 어느 한쪽만 취할 방법은 없다.

유령과 함께 사는 법 — 엔지니어에게 주는 교훈

유령 문자 이야기는 흥미로운 트리비아로 끝나지 않는다. 여기에는 표준을 다루는 모든 엔지니어에게 통하는 구조적 교훈이 있다. 핵심은 이것이다. 널리 채택되는 표준은 사실상 추가만 가능한(append-only) 시스템이라는 것. 한번 들어간 항목은 옳든 그르든 영원히 남는다. 그렇다면 오류를 잡을 수 있는 유일하게 값싼 지점은 항목이 표준에 들어가기 직전, 입구뿐이다. 입구를 통과한 오류를 나중에 걷어내는 비용은 사실상 무한대로 발산한다. 유령 문자를 만든 것은 대단히 정교한 공격이 아니라, 오려 붙인 종잇조각의 그림자를 획으로 착각한 소박한 전사 실수였다. 그리고 바로 그 소박한 실수가, 검증 없이 표준에 흘러들어가는 순간 반세기를 살아남았다.

낙관적으로 보면, 유령 문자가 오늘날 끼치는 실질적 해악은 거의 없다. 코드포인트 몇 개를 차지하고 폰트에 글리프 몇 개를 요구하는 정도이며, 유니코드의 광대한 코드 공간에서 이 정도는 반올림 오차에도 못 미친다. 오히려 이 글자들은 뜻밖의 제2의 삶을 얻기도 했다. 아무 의미도 배정되지 않은 백지 같은 존재라는 점 때문에, 진짜 유령인 彁는 리듬 게임 beatmania IIDX와 太鼓の達人(태고의 달인) 같은 작품에서 정체불명·초자연의 분위기를 내는 소재로 실제로 쓰였다. 오류가 창작의 재료로 재활용된 것이다.

비관적으로 보면, 이것은 규모가 커진 모든 표준이 짊어지는 부채의 축소판이다. 유니코드에는 유령 문자 말고도 CJK 통합 과정에서 생긴 별도의 유령들, 폐기(deprecated)되었지만 삭제는 못 하는 코드포인트들, 호환성만을 위해 존재하는 중복 문자들이 겹겹이 쌓여 있다. 이모지의 결합 규칙처럼 새로 추가되는 복잡성도 결국 같은 원리 위에 얹힌다. 현실적인 결론은 그 중간에 있다. 표준의 오류는 지우는 것이 아니라 안고 가는 것이며, 그렇기에 무엇을 표준에 넣을지 결정하는 최초의 순간에 최대의 검증을 집중해야 한다. 삭제가 불가능한 시스템에서 품질을 지키는 방법은 사후 정정이 아니라 사전 통제뿐이다.

결론

그렇다면 처음의 질문으로 돌아가자. 유령 문자는 지우면 그만인 오타인가, 아니면 표준의 숙명인가. 답은 둘 다다. 그 기원은 종잇조각의 그림자를 획으로 오인한, 어이없을 만큼 사소한 오타였다. 그러나 그 오타가 국가 표준을 거쳐 국제 표준으로 상속되고, 무손실 호환성과 영속성 원칙이라는 두 겹의 계약으로 봉인되는 순간, 그것은 더 이상 지울 수 있는 실수가 아니라 시스템의 일부가 되었다. 오류의 영구 보존은 결함이 아니라, 과거의 데이터를 지키기 위해 유니코드가 의식적으로 치르는 대가다.

彁는 앞으로도 지워지지 않을 것이다. 우리는 이 유령들과 계속 함께 살아갈 것이고, 대부분은 그 존재조차 모른 채 지나갈 것이다. 다음에 당신이 어떤 표준의 스펙 문서에 새 항목 하나를 추가하려 할 때, 잠시 이 열두 자를 떠올려 보면 어떨까. 지금 무심코 넣는 이 한 줄이, 반세기 뒤 누군가의 컴퓨터 안에서 아무도 뜻을 모르는 유령으로 배회하게 될지도 모른다. 표준에 무언가를 넣는다는 것은, 그것을 영원히 책임진다는 뜻이다.


출처: