재우니의 블로그

 

 

 

맥OS에서는 한글 파일명이 자모(초성, 중성, 종성)로 분리되어 저장되는 경우가 있습니다. 예를 들어, "파일"이라는 단어가 "ㅍㅏㅇㅣㄹ"처럼 분리되어 나타나는 현상입니다. 이는 맥OS가 유니코드 NFC(Normalization Form C) 방식이 아닌 NFD(Normalization Form D) 방식을 사용하여 파일명을 저장하기 때문입니다.

 

 

  • NFC(Normalization Form C): 한글 음절을 하나의 문자로 합친 형태.
  • NFD(Normalization Form D): 한글 음절을 초성, 중성, 종성으로 분리된 형태.

 

 

맥OS의 NFD 방식은 일부 파일 시스템이나 운영체제에서 호환성 문제를 일으키며, 특히 한국어 사용자가 불편을 겪게 됩니다. 예를 들어, 한글 파일명이 포함된 파일을 맥에서 윈도우로 이동하거나 네트워크를 통해 전송할 때 파일명이 깨지거나 검색에 문제가 발생할 수 있습니다.

 

 

사용법

 

zip 파일을 다운로드 받아 압축을 풀면 mac_jamo_korean_fixTool.exe 파일이 존재합니다.

 

자모가 분리된 파일 존재하는 폴더에 실행파일 exe 를 더블 클릭하면 해당 폴더 + 하위폴더까지 모두 대체해 줍니다.

 

 

MAC_한글자모분리교정_프로그램.zip
0.00MB


 

 

 

아래는 코드 설명입니다. 사용만 하시고자 하는 분은 내용 무시하셔도 됩니다.

 

해결 방법

이 문제를 해결하기 위해, 파일명과 폴더명을 NFC 방식으로 정규화하는 작업이 필요합니다. 이를 위해 C#을 이용해 EXE 프로그램을 만들고, 맥OS에서 자모가 분리된 파일명을 정규화하는 방법을 설명하겠습니다.

 

코드 설명: C# 프로그램으로 파일명 정규화하기

아래의 C# 프로그램은 현재 실행 중인 EXE 파일의 경로를 기준으로 해당 디렉토리와 모든 하위 디렉토리의 파일명과 폴더명을 NFC 형식으로 정규화합니다. 이를 통해 맥OS에서 자모 분리 문제를 해결할 수 있습니다.

 

 

using System;
using System.IO;
using System.Text;
using System.Reflection;

class HangulNormalizer
{
    static void Main(string[] args)
    {
        string exePath = Assembly.GetExecutingAssembly().Location;
        string rootPath = Path.GetDirectoryName(exePath);

        Console.WriteLine(String.Format("정규화할 경로: {0}", rootPath));

        if (Directory.Exists(rootPath))
        {
            NormalizeDirectory(rootPath);
            Console.WriteLine("정규화 작업이 완료되었습니다.");
        }
        else
        {
            Console.WriteLine("경로를 찾을 수 없습니다.");
        }

        Console.WriteLine("프로그램을 종료하려면 아무 키나 누르세요.");
        Console.ReadKey();
    }

    static void NormalizeDirectory(string path)
    {
        foreach (var file in Directory.GetFiles(path))
        {
            try
            {
                string fileName = Path.GetFileName(file);
                if (!IsNormalized(fileName) && !IsSystemOrHiddenFile(file))
                {
                    string normalizedFileName = fileName.Normalize();
                    string normalizedPath = Path.Combine(Path.GetDirectoryName(file), normalizedFileName);

                    if (!file.Equals(normalizedPath, StringComparison.OrdinalIgnoreCase))
                    {
                        File.Move(file, normalizedPath);
                        Console.WriteLine(String.Format("파일 정규화: {0} -> {1}", fileName, normalizedFileName));
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(String.Format("파일 정규화 중 오류 발생: {0}", ex.Message));
            }
        }

        foreach (var dir in Directory.GetDirectories(path))
        {
            try
            {
                string dirName = Path.GetFileName(dir);
                if (!IsNormalized(dirName) && !IsSystemOrHiddenDirectory(dir))
                {
                    string normalizedDirName = dirName.Normalize();
                    string normalizedDirPath = Path.Combine(Path.GetDirectoryName(dir), normalizedDirName);

                    if (!dir.Equals(normalizedDirPath, StringComparison.OrdinalIgnoreCase))
                    {
                        Directory.Move(dir, normalizedDirPath);
                        Console.WriteLine(String.Format("디렉토리 정규화: {0} -> {1}", dirName, normalizedDirName));
                        NormalizeDirectory(normalizedDirPath); // 정규화된 경로에서 재귀 호출
                    }
                    else
                    {
                        NormalizeDirectory(dir); // 동일 경로에서 재귀 호출
                    }
                }
                else
                {
                    NormalizeDirectory(dir);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(String.Format("디렉토리 정규화 중 오류 발생: {0}", ex.Message));
            }
        }
    }

    static bool IsNormalized(string input)
    {
        return input.IsNormalized();
    }

    static bool IsSystemOrHiddenFile(string path)
    {
        var attributes = File.GetAttributes(path);
        return (attributes & FileAttributes.Hidden) == FileAttributes.Hidden ||
               (attributes & FileAttributes.System) == FileAttributes.System;
    }

    static bool IsSystemOrHiddenDirectory(string path)
    {
        var attributes = File.GetAttributes(path);
        return (attributes & FileAttributes.Hidden) == FileAttributes.Hidden ||
               (attributes & FileAttributes.System) == FileAttributes.System;
    }
}

 

 

코드 실행 및 사용 방법

  1. 위 코드를 C# 콘솔 애플리케이션으로 Visual Studio나 .NET 환경에서 작성하고, EXE 파일로 컴파일합니다.
  2. 생성된 EXE 파일을 맥OS에서 자모 분리 문제가 있는 파일이 포함된 디렉토리로 이동합니다.
  3. EXE 파일을 실행하면, 자동으로 현재 디렉토리와 모든 하위 디렉토리의 파일명과 폴더명을 NFC 형식으로 정규화합니다.

 

결론

맥OS 환경에서 한글 파일명이 자모로 분리되는 문제는 파일 시스템의 문자 인코딩 방식 차이에서 발생합니다. 이를 해결하기 위해, C# 프로그램을 활용하여 파일명과 폴더명을 NFC 형식으로 정규화하면, 호환성과 사용성을 높일 수 있습니다.

 

 

이 프로그램은 맥OS뿐만 아니라 다양한 운영체제 환경에서 파일명 문제를 해결하고자 하는 사용자에게도 유용하게 사용될 수 있습니다. 프로그램을 실행하는 것만으로 정규화 작업이 자동으로 수행되므로, 파일 관리의 일관성과 편리성을 보장할 수 있습니다.