합동회사 코무라소프트
4장

Shift_JIS 와 일본어의 사정 — 다메 문자와 CP932

Shift_JIS 는 2 번째 바이트가 ASCII 영역에 파고드는 설계. 거기서 태어나는 「다메 문자」 문제와, 반각 가나·CP932·지금도 현역인 이유를 구조로부터 이해한다.

「ソフト」라고 입력하면 깨진다 — 거짓말 같은 진짜 버그

오래된 업무 시스템에서 「ソフト(소프트)」라는 단어를 저장하면, 왠지 그 행만 데이터가 무너진다. 파일 경로에 일본어 한자 「表」를 포함하는 폴더를 만들면 특정 도구가 실패한다. — Shift_JIS 의 현장에는, 이런 언뜻 오컬트 같은 버그의 전설이 있습니다. 이 장의 목표는, 이것을 구조로부터 설명할 수 있게 되는 것입니다.

Shift_JIS 는, Unicode 이전 시대에 「ASCII 와 공존하면서 일본어를 밀어 넣기」 위해 만들어진 일본어권의 레거시 인코딩입니다 — 한국어권의 EUC-KR/CP949 와 비슷한 위치라고 생각하면 이해하기 쉽습니다. ASCII 는 1 바이트 그대로, 전각 문자는 2 바이트로 나타냅니다.

ASCII
0x00〜0x7F 의 1 바이트. 영숫자는 그대로
반각 가나
0xA1〜0xDF 의 1 바이트(アイウエオ…). 전신 시대부터의 자산
전각 문자
1 번째 바이트 0x81〜0x9F, 0xE0〜0xFC + 2 번째 바이트 0x40〜0x7E, 0x80〜0xFC 의 2 바이트

문제는 2 번째 바이트의 범위입니다. 0x40〜0x7E 는, ASCII 의 영문자나 기호와 통째로 같은 값. 즉 전각 문자의 후반 1 바이트만 꺼내면, ASCII 의 기호와 구별이 되지 않습니다. 앞 장에서 본 UTF-8 의 「다바이트 문자의 구성 바이트는 모두 0x80 이상」이라는 보증이, 여기에는 없는 것입니다.

Shift_JIS 의 2 바이트 구조와, 「表」 = 95 5C 의 2 번째 바이트 0x5C 가 ASCII 의 백슬래시와 충돌하는 모습을 보여 주는 그림

「表」의 2 번째 바이트 0x5C 는, ASCII 에서는 백슬래시. 바이트 단위로 주사하는 프로그램에는 「表」의 후반이 기호로 보여 버립니다.

다메 문자 — 2 번째 바이트 0x5C 의 충돌

ASCII 의 0x5C 는 백슬래시 \(일본어 환경에서는 엔화 기호로 표시되는 일도 많은 문자)입니다. 많은 프로그래밍 언어나 설정 파일에서 「다음 1 문자를 특별 취급한다」는 이스케이프 기호로 사용됩니다.

여기서 Shift_JIS 의 「表」를 봅시다. 바이트 열은 95 5C2 번째 바이트가 딱 0x5C 입니다. Shift_JIS 를 의식하지 않고 바이트 단위로 문자열을 주사하는 처리계는, 95 다음의 5C 를 독립된 백슬래시로 오해하고, 다시 다음 바이트를 이스케이프로 소비합니다. 결과적으로 「表」의 후반이 먹혀 문자가 이지러지고, 이후의 해석이 연쇄적으로 어긋난다 — 서두의 「오컬트 버그」의 정체입니다.

2 번째 바이트가 0x5C 가 되는 문자는 「(83 5C)」 「(94 5C)」 「(95 5C)」 「十」 「予」 「構」 등 다수 있으며, 일본에서는 속칭 다메 문자(ダメ文字, 안 되는 문자)라고 불립니다. 어느 것이나 일상어에 평범하게 나타나는 문자라서, 「특정 단어일 때만 깨진다」는 재현 조건을 잡기 어려운 장애가 됩니다. 0x5C 이외에도, 2 번째 바이트가 "(0x22)나 |(0x7C) 등에 해당하는 조합으로 같은 종류의 문제가 일어날 수 있습니다.

소문제 4-1 — 2 바이트 구조와 다메 문자

Shift_JIS 의 구조로부터, 왜 특정 문자만이 트러블을 일으키는지를 끌어냅니다.

Q1. Shift_JIS 의 구조 설명으로 올바른 것은 어느 것입니까.

Q2. Shift_JIS 에서 일본어 한자 「表」는 95 5C 의 2 바이트입니다. 이 문자를 포함하는 문자열을, 0x5C 를 이스케이프 기호(백슬래시)로 특별 취급하는 처리계에 통과시키면 깨지는 일이 있습니다. 이유는 어느 것입니까.

Q3. 이른바 「다메 문자」에 해당하는 예의 조합으로 올바른 것은 어느 것입니까.

CP932 — 「Shift_JIS」를 자칭하는 방언

또 1 가지 현장 지식이 기종 의존 문자입니다. 원 숫자 ①, ㈱, 로마 숫자 Ⅱ, 「髙」(사다리 다카) — 이것들은 원래 JIS 규격의 문자 집합에는 없고, 제조사가 독자적으로 추가한 문자였습니다. Windows 는 이것들을 받아들인 확장판 CP932 를 「Shift_JIS」로 사용하고 있습니다.

즉, 세간에서 「Shift_JIS 파일」이라 불리는 것의 다수는, 정확하게는 CP932 입니다. 같은 이름을 자칭하는, 미묘하게 다른 표가 여럿 있다 — ① 이 든 데이터를 엄밀한 Shift_JIS 로 변환하려 하면 실패하고, 환경에 따라 깨지는 문자가 달라진다는 성가신 사정의 뿌리입니다. 「Shift_JIS 관련 트러블에서는, 진짜 표는 CP932 가 아닐까」라고 한 단계 의심하는 것이 실무의 요령입니다.

그런데도 Shift_JIS 가 현역인 이유

웹의 세계는 UTF-8 로 거의 통일되었습니다. 그런데도 Shift_JIS(CP932)가 사라지지 않는 것은, 인코딩의 이행이 「나만 바꾸면 되는」 문제가 아니기 때문입니다. 파일을 주고받는 상대 — Excel 의 종래 형식 CSV, 오랜 세월 가동하는 기간 시스템, 금융·행정계의 고정 길이 파일 연계 — 의 보조가 갖추어지지 않는 한, 주고받는 부분에는 오래된 인코딩이 계속 남습니다.

그래서 이 강좌에서는 Shift_JIS 를 「과거의 유물」이 아니라 「지금도 추리의 대상이 되는 현역 용의자」로 다룹니다. UTF-8 파일을 Shift_JIS 로 읽는다, Shift_JIS 파일을 UTF-8 로 읽는다 — 이 양방향 오독 패턴의 구별법은, 제 7 장 종합 연습의 주역입니다.

소문제 4-2 — 반각 가나·CP932·현역인 이유

Shift_JIS 주변의 실무 지식을 마무리합니다.

Q4. Shift_JIS 에서의 반각 가나(アイウエオ…)의 설명으로 올바른 것은 어느 것입니까.

Q5. CP932 와 Shift_JIS 의 관계로 올바른 것은 어느 것입니까.

Q6. UTF-8 이 표준이 된 현재도, Shift_JIS(CP932)를 다루는 장면이 남아 있는 이유로 가장 적절한 것은 어느 것입니까.

이 장에서 가져갈 것

  • Shift_JIS 는 ASCII 1 바이트 + 전각 2 바이트이지만, 2 번째 바이트가 ASCII 의 값 범위(0x40〜0x7E)에 파고든다
  • 다메 문자 = 2 번째 바이트가 0x5C 등의 기호에 해당하는 문자(ソ 83 5C·能 94 5C·表 95 5C 등). 이스케이프 처리와 충돌하여 데이터가 깨진다
  • 반각 가나는 0xA1〜0xDF 의 1 바이트. Windows 의 「Shift_JIS」의 실체는 기종 의존 문자가 든 CP932
  • Excel 의 CSV 나 레거시 연계 때문에 지금도 현역. 오독 패턴의 추리 대상으로서 인연은 계속된다

다음 장은 Unicode 쪽의 또 하나의 인코딩, UTF-16 으로. 이번에는 「바이트 수」가 아니라 「문자 수를 세는 방법」이 함정이 됩니다.