파일명 자모 분리 문제

공부하는 감자·2024년 1월 4일
0

끄적끄적

목록 보기
1/1

들어가는 말

2023년 8월 25일에 작성했던 글입니다.

때는 한적한 금요일 오후. 구글 드라이브에서 공유 문서를 다운받았다. 그런데 드라이브에서는 정상적으로 표시되었던 파일 명이 다운받고 보니 자모음이 분리되어 있었다!

그러고보면 종종 이런 일이 있었다. 메일로 전달받은 파일의 명이 분리되어 온다거나 등등. 자모음이 분리되어도 알아볼 수는 있으니 그 동안은 다운 후 수정하는 식으로 사용했었는데, 다운받을 파일이 많아지니 귀찮아지기 시작했다.

그리하여 자모 분리가 왜 생기는 것인지, 해결방안으로는 무엇이 있을지 찾아보았다.

자음과 모음이 분리되는 이유

자모 분리 현상이라고도 부른다. “가나다” 라는 파일 명이 “ㄱㅏㄴㅏㄷㅏ” 처럼 분리되는 현상을 말한다. 이 현상은 주로 MAC 을 사용하는 유저가 업로드한 파일을 Window 유저에게 파일을 다운받을 때 발생한다.

이건 MacOS 와 WindowOS 에서 한글을 표시할 때 서로 다른 표준을 사용하기 때문이다.

모양이 같은 여러 문자들이 있을 때, 이를 기준에 따라 하나로 통합해주는 것을 유니코드 정규화(Unicode Normalization) 라고 한다. 이때, 기준으로는 NFC, NFD, NFKD, NFKC 가 있다.

이 기준들은 모두 표준이지만, 한글 파일명의 처리 시에는 NFC 가 표준이라고 한다. 이에 대해 흥미로운 글을 찾았는데, 같이 읽어보면 좋을 듯하다.

맥의 한글 파일명 자소/자모 분리에 대한 오해 : 클리앙

아무튼, 이 기준들 중 MacOS 는 하나의 문자를 분리하여 저장하는 NFD 방식을 사용하고, Window 는 한글을 하나의 문자로 저장하는 NFC 방식을 사용한다.

  • NFD: 정규형 정준 분해(Normalization Form Canonical Decomposition)
    모든 음절을 정준 분해한다. ex) 각 → ㄱ+ㅏ+ㄱ
  • NFC: 정규형 정준 결합(Normalization Form Canonical Composition)
    모든 음절을 정준 분해 후 정준 결합한다. ex) 각 → 각

여담으로 어느 사이트를 봐도 정준 결합이니, 정준 분해니 하는 단어를 쓰고 있는데, 나는 이 단어가 무슨 의미인지 모르겠다. 정준이라는 단어는 “정해진 표준” 혹은 “기준이 되는” 이라는 의미라는데, 그렇다면 정준 결합은 기준이 정해진 표준대로 결합 혹은 기준이 되는 결합이라는 의미인건가?

💡 자세한 설명은 하단 참고 사이트에 기재한 한글과 유니코드 참고

이를 좀 더 쉽게 정리해보자면.

MAC 은 파일 명을 자모 분리하여 저장하고 보여줄 때는 ‘모아서 보여주기’ 처리한다. 그리고 Window 는 파일 명을 합쳐서 저장하므로 보여줄 때도 별도 처리 없이 그대로 보여준다.

그럼 MAC 에서 저장한 파일을 Window 에서 열어볼 때를 생각해보자.

MAC 에서 파일 명의 자음과 모음을 분리하여 저장한 뒤 업로드를 한다. 그리고 Window 에서 해당 파일을 다운로드한다.

이때, Window 는 ‘모아서 보여주기’ 처리를 하지 않으므로 자모 분리되어 저장했던 파일명이 그대로 보이게 되는 것이다.

해결 방안

OS 에서 사용하는 방식이 다른 것이므로, 사용자가 불편함을 감수하는 수밖에 없다. 그러므로 해결 방안이라고 적기엔 애매하지만, 어찌되었건 몇 개 적어본다.

첫번째로, 아예 자소 분리되지 않게 저장한다.

영어를 사용한다거나, 한글을 사용한다면 MAC 에서 NFC 형식을 사용하는 프로그램을 사용한다.

후자의 경우, 반디집은 NFC 와 NFD 형식을 모두 지원하므로 그를 이용하는 식으로 피할 수 있겠다.

두번째로, (Window 에서) 다운로드 후 직접 수정해준다.

물론 이 방법은 파일의 수가 많아지거나 파일 명이 길 경우 극심히 귀찮아지는 바를 안다.

이 글을 작성하고 있는 나조차 당연히 이 방법을 쓰고 싶지 않다.

마지막으로, MAC 혹은 Window 에서 NFD 를 NFC 로 변환해주는 프로그램으로 변환한다.

생각보다 인터넷에 검색해보면 여러 사람들이 변환 프로그램을 개발하여 올려두었다. 설치하지 않아도 되게 개발해둔 것도 있으므로 편하게 사용할 수 있다.

하단 참고 사이트에 변환하는 법과 프로그램 설치 없이 자모를 다시 합쳐주는 사이트 링크를 걸어뒀다.

NFD to NFC

물론 이미 만들어진 것만 쓸게 아니라, 스스로 구현해볼 줄도 알아야하지 않을까?

자바스크립트에는 normalize() 라는 메소드가 있다. “문자열.normalize()” 로 사용하며, 파라미터로 유니코드 정규화 방식을 넘기면 해당 방식에 따라 정규화된 형태로 반환해준다.

string.normalize([form])
  • form: “NFC”, “NFD”, “NFKC”, “NFLD” 중 하나. 생략되거나 Undefined 라면 “NFC”가 적용된다.

예제

먼저 테스트를 위해 문자열을 유니코드 문자열로 변환 시키는 작업을 진행했다.

그 후, normalize() 를 사용하여 각각 NFD 와 NFC 로 변환해보았다.

콘솔로 출력해보면 모두 자모음이 합쳐진 상태로 보이는데, 제대로 된 건지 확인하기 위해 두 결과를 비교하는 것까지 해봤다.

💡 브라우저에 따라 자모 분리된 상태 그대로 보일 수도 있다

// 문자열 => 유니코드 문자열
const str = "안녕하세요?";
console.log("원본 문자열: " + str);

const unicode = str.split("").map(function(s) {
  return String.fromCharCode(s.charCodeAt(0));
}).join("");
console.log("유니코드로 변환: " + unicode);

// 정규형 정준 분해 (NFD)
const sNFD = unicode.normalize("NFD");
console.log("To NFD: " + sNFD);

// 정규형 정준 결합 (NFC)
const sNFC = sNFD.normalize("NFC");
console.log("To NFC: " + sNFC);

// 결과 비교
console.log("원본 문자열은 NFD 인가? " + (str === sNFD));
console.log("원본 문자열은 NFC 인가? " + (str === sNFC));
console.log("NFC 와 NFD 비교: " + (sNFC === sNFD));

자모 분리되지 않은 문자열의 실행 결과

결과물을 메모장에 옮겨서 확인해보면 이렇게 된다.

메모장에서 다시 확인한 결과

마찬가지로 자모 분리된 문자열을 넣었을 경우

자보 분리된 문자열의 실행 결과

접는 말

처음에는 가볍게 정리해보려고 했는데, 테스트 코드를 짜는 과정에서 유니코드 문자열로 변환이 제대로 안되는 바람에 시간이 한참 걸렸다. 가볍게 하려고 했는데 시간이…

charCodeAt(index) 를 이용해 유니코드는 얻었는데, 이걸 포인트 코드라고 하는 “\u0000” 형식으로 변경이 안되어서 한참 헤맸다.

처음엔 "\\u" + str.charCodeAt(index).toString(16) 을 썼는데, 이렇게 쓰니까 normalize 가 안됐다. 아마 유니코드 문자열이 아니라 일반 문자열로 인식된 것 같다.

아무튼 이걸로 오늘의 작은 호기심 끝.

참고 사이트

한글과 유니코드

NFC와 NFD 서로 변환하기

파일명 자모 분리 해결 (프로그램 설치 없이) : 클리앙

profile
책을 읽거나 강의를 들으며 공부한 내용을 정리합니다. 가끔 개발하는데 있었던 이슈도 올립니다.

0개의 댓글