UTF-8 엔코딩 한글 깨짐 문제 관련

최근에 본, @jamesnet214 님의 글과 관련하여 :

저도 지금 연산의 결과를 csv 파일에 넣어 엑셀로 보는 와중에 한글 깨짐 문제가 발생했었습니다.

문제의 코드는 아래와 같습니다.

var fileContents= "안, 녕, 何, 世, 요";
File.WriteAllText("test.csv", fileContents);

이 파일을 메모장, 워드패드, 노드패드, 비주얼 스튜디오, 비주얼 스튜디오 코드에서 열어 보면, 한글 깨짐이 없이 모두 정상적으로 표시됩니다.
그런데, 유독 Excel(과 Word)에서만 깨집니다.

이 문제의 원인과 해결 과정을 기록을 위해 남깁니다.

원인: Excel은 BOM Preamble 이 없을 경우, UTF-7로 인식한다.

텍스트 파일은 파일 컨텐츠 앞에, 문자의 엔코딩 방식을 나타내는 “BOM(Byte Order Mark) Preamble” 이라는 특수한 값을 가질 수 있습니다.

텍스트 파일을 읽는 프로그램은 BOM 정보를 기반으로, 엔코딩 방식을 인식합니다.
만약, BOM 이 명기되어 있지 않은 경우, 추측 알고리즘을 통해, 엔코딩 방식을 결정합니다.

대부분의 프로그램은 BOM 없이 UTF-8 로 엔코딩된 파일의 경우, 보통 문제 없이 UTF-8로 추측합니다.

하지만, 유독 오피스 제품군은 BOM 없으면, UTF-7으로 인식하는 행태를 보입니다.
UTF-7 은 ACSII 문자표의 문자코드 값에 한정하여, UTF-8 과 호환되고, 유니코드 문자 코드와는 호환되지 않습니다.

저가 직면한 문제는 Excel 의 이러한 행태로 인해 발생한 것입니다.

해결: 파일에 BOM 프리앰블을 추가

var fileContents= "안, 녕, 何, 世, 요";
File.WriteAllText("test.csv", fileContents, new UTF8Encoding(true));

수정 코드에 나타난 WriteAllText 메서드의 오버로드는 엔코딩 객체를 입력받습니다.
이 객체는 엔코딩 방식과, BOM을 삽입 여부에 대한 정보를 담고 있습니다.
생성자에 true를 넣으면, BOM을 먼저 추가하라는 의미입니다.

참고로, 아래의 방식은 모두 BOM을 추가하지 않는 방식입니다.

new UTF8Encoding(false)
new UTF8Encoding()
Encoding.UTF8
혹은 문제의 코드와 같이, 엔코딩 객체를 입력하지 않으면 됩니다.

주의: Preamble 은 스트림 포지션이 0일 경우에만 적용됨.

아시다시피, File.WriteAllText 는 내부에서 StreamWriter 객체를 사용합니다.
StreamWriter 는 프리앰블을 넣으라는 옵션이 있어도, 스트림 시작 지점이 아니면, BOM을 삽입하지 않습니다.

File.WriteAllText 는 파일이 없으면 새로 만들고, 존재하면 덮어 쓰기를 하기 때문에, 항상 새로운 스트림을 시작합니다. 그래서, BOM 프리앰블을 삽입하라는 옵션은 항상 적용됩니다.

참고: XAML 파일에 BOM 프리앰블을 넣어도 됩니다.

XAML은 xml 해더를 가지고 있기 때문에, 정식 xml 문서인데, xml 문서가 엔코딩 프리앰블을 가져도 xml로 인식하는데 아무런 문제가 없습니다. 비영문자를 표기하기 위해서는 오히려 있는 것이 더 좋습니다.

오피스 제품군 뿐만 아니라, 한글이 깨지는 문제가 발생한 경우, 대부분 BOM 프리앰블이 명시되지 않아 발생한 문제입니다. 이 경우, 파일에 BOM 프리앰블을 넣어주거나, 변경하면, 해결이 될 수도 있습니다.

프리앰블을 변경하는 하고자 하는 파일을 메모장으로 열어, [파일] => [다른 이름으로 저장] 을 선택한 후,
[저장] 버튼 옆의 [인코딩] 을 눌러 UTF(BOM) 을 선택하면

image

파일의 내용을 UTF-8 코드로 변환하고, 내용앞에 BOM 프리앰블이 추가됩니다.

비주얼 스튜디오에서도 동일하게, [파일] => [다른 이름으로 저장] 을 선택한 후,
[저장] 옆의 아래 삼각형을 누른 후, [인코딩하여 저장]을 선택하면,
image

아래와 같은 [고급 저장 옵션] 창이 뜨는데, 인코딩과 프리앰블 추가 여부를 변경할 수 있습니다.
image

마지막으로 Bing 부기장에게 BOM 프리앰블이 있는 경우와 없는 경우, 파일에 실제로 저장되는 값을 16진수 값으로 비교해 달라고 해보았습니다.

image

6개의 좋아요

@BigSquare 제가 작성한 글은 2021년 5월이에요~

계속해서 회자되는 것을 보니 질문 잘 했다는 생각이 드네요. :rofl:

2개의 좋아요

그렇군요.
최근 글에 올라와서, 아무 생각 없이 최근인 줄 알았습니다. ^^.

윈도우에서 한글 깨짐 문제는 꼭 잊을 만할 때 나타나서, 이참에 정리해봤습니다.

3개의 좋아요

좋은 내용 매번 올려 주셔서 감사합니다!! :smile:

3개의 좋아요