최재영의 개발 일지
GitHubLinkedIn

macOS에서 한글 파일명이 깨지는 이유(NFD)

기타1분 읽기

증상

macOS에서 만든 한글 파일명이 Windows나 Linux, 또는 일부 프로그램에서 자모가 분리되어 보이는 현상이 있다. 예를 들어 김범수 - 지나간다.opusㄱㅣㅁㅂㅓㅁㅅㅜ - ㅈㅣㄴㅏㄱㅏㄴㄷㅏ.opus처럼 풀어져서 표시된다.

맥의 Finder에서 파일명을 한글로 변경했을 때 이런 현상이 발생하고, 터미널에서 ls로 출력해보면 글자가 깨져서 나온다. 터미널에서 mv로 변경했을 때는 발생하지 않았다.

원인: 유니코드 정규화 (NFC vs NFD)

유니코드는 같은 글자를 표현하는 두 가지 방식을 정의하고 있다.

NFC (Normalization Form Composed) — 완성형

한글을 완성된 한 글자로 저장하는 방식이다.

"한" = U+D55C (1개의 코드 포인트)

Windows, Linux 등 대부분의 시스템이 이 방식을 사용한다.

NFD (Normalization Form Decomposed) — 분해형

한글을 초성 + 중성 + 종성으로 분해하여 저장하는 방식이다.

"한" = ㅎ(U+1112) + ㅏ(U+1161) + ㄴ(U+11AB) (3개의 코드 포인트)

macOS의 파일시스템(APFS, HFS+)이 이 방식을 사용한다.

비교

NFC (완성형)NFD (분해형)
저장 방식U+D55C (1개)U+1112 U+1161 U+11AB (3개)
사용 환경Windows, LinuxmacOS
눈에 보이는 차이없음 (같은 글자로 렌더링)없음 (같은 글자로 렌더링)
바이트 수적다많다

눈으로 보기에 같은 글자이지만 내부적으로 다른 바이트 시퀀스이기 때문에, NFD를 지원하지 않는 환경에서는 자모가 풀어져서 보이게 된다.

확인 방법

Python으로 파일명의 정규화 형태를 확인할 수 있다.

import os, unicodedata

for f in os.listdir('/path/to/dir'):
    is_nfc = unicodedata.is_normalized('NFC', f)
    print(f'NFC={is_nfc}  {f}')

macOS에서 생성한 한글 파일명은 대부분 NFC=False로 표시된다.

해결 방법

NFD로 저장된 파일명을 NFC로 변환하면 된다.

Python (macOS 기본 설치)

python3 -c "
import os, unicodedata
path = '/path/to/dir'
for f in os.listdir(path):
    nfc = unicodedata.normalize('NFC', f)
    if f != nfc:
        os.rename(os.path.join(path, f), os.path.join(path, nfc))
        print('변환:', nfc)
"

convmv (전용 도구)

# 설치
brew install convmv

# 미리보기 (실제 변환하지 않음)
convmv -f utf8 -t utf8 --nfc /path/to/dir/*

# 실제 변환
convmv -f utf8 -t utf8 --nfc --notest /path/to/dir/*

Python은 macOS에 기본 포함되어 있어서 별도 설치 없이 바로 사용할 수 있다. convmv는 Homebrew 설치가 필요하지만 명령어가 더 간결하다.