한글 파일명이 읽히지 않는 문제, 그리고 개발자로서의 고민
개발을 하다 보면 예상치 못한 문제를 마주할 때가 있습니다. 이번 테스트 서버에서 이미지가 읽히지 않는 상황을 경험했는데, 그 원인을 추적하는 과정에서 한글 파일명과 Unicode의 미묘한 차이, 그리고 운영체제별 처리 방식을 발견했습니다. 이를 통해 한글을 개발에 활용하는 데 있어 고려해야 할 점을 돌아보게 되었습니다.
문제의 발견: 이미지 파일명이 읽히지 않는 상황
테스트 서버에서 특정 이미지가 노출되지 않는 문제가 발생했습니다. 흔히 발생할 수 있는 단순한 문제(파일 누락, 경로 오류 등)라고 생각했지만, 확인해보니 파일은 정확한 경로에 존재했고, 문제는 다른 곳에 있었습니다.
- 한글 → 영문 변경 시 정상 동작
이미지 파일명을 한글에서 영문으로 바꾸면 문제가 사라집니다. - 동일 서버에서 일부 한글 파일은 정상
모든 한글 파일명이 문제를 일으키는 것은 아니었기에, 더욱 혼란스러웠습니다. - 한글 파일명을 되돌렸더니… 정상 작동?
파일명을 원래 한글로 다시 바꾸었더니 이번에는 정상적으로 동작하는 경우도 있었습니다.
이 같은 현상은 한글 파일명 자체의 문제라기보다는, 한글이 운영체제나 파일 시스템에 저장될 때 다른 형태로 인식될 수 있다는 점이 원인이었습니다.
문제의 원인: 한글과 Unicode의 관계
한글을 포함한 모든 문자는 내부적으로 Unicode라는 표준에 따라 코드 포인트로 표현됩니다.
하지만 문제는 같은 한글을 표현하는 방식이 조합형(NFC) 과 분리형(NFD) 등으로 나뉠 수 있고, 운영체제나 파일 시스템별로 이를 다르게 취급한다는 데서 발생합니다.
이를 이해하기 위해 "배너"라는 단어를 예로 들어보겠습니다.
1. 조합형(NFC) vs. 분리형(NFD)
- 조합형(NFC):
“배너” 같은 단어를 하나의 코드 포인트(예: U+BAA8, U+B124)로 저장 - 분리형(NFD):
같은 단어도 초성·중성·종성으로 나누어 여러 코드 포인트(예: U+1107, U+1161, …)로 저장
예시: “배너”
- NFC(조합형):
- 배(
U+BAA8
), 너(U+B124
) → “배너”
- 배(
- NFD(분리형):
- (초성 ᄇ)
U+1107
, (중성 ㅐ)U+1161
, (초성 ᄂ)U+1102
, (중성 ㅓ)U+1161
- 결과적으로는 똑같이 “배너”처럼 보이지만, 코드 포인트 배열이 다름
- (초성 ᄇ)
2. 운영체제별 한글 파일명 처리 방식
- macOS(APFS): 내부적으로 NFD(분리형) 를 주로 사용
- Windows(NTFS, FAT): 내부적으로 NFC(조합형) 을 주로 사용
- Linux(ext4 등): 대체로 NFC를 사용하는 편이지만, 배포판이나 설정에 따라 다를 수 있음
서로 다른 정규화 방식을 사용하는 운영체제 간에 파일을 주고받으면, 같은 “배너.jpg” 파일도 사실은 다른 이름처럼 취급될 수 있습니다. 이때, 서버에서는 “파일이 이미 존재하는데 왜 못 찾을까?” 하는 혼란이 생기는 것입니다.
실무에서 흔히 겪는 문제 사례
Git 저장소에서의 충돌
맥OS 환경에서 커밋된 파일명이 분리형(NFD)으로 저장되었다면, 윈도우 환경에서 이 저장소를 받아올 때 파일명이 달라진 것으로 인식되어 충돌이 발생합니다.CI/CD 파이프라인 실패
빌드 서버(예: Linux)에서 스크립트로 파일들을 복사·배포하는 과정에서, 서버 내부에서 문자 정규화가 섞이면 파일명을 인식하지 못해 스크립트가 실패할 수 있습니다.클라우드 스토리지
AWS S3나 GCP Storage에 업로드하는 경우, 한글 파일명을 올렸는데 운영체제에서 NFD/NFC 변환을 다르게 처리해 “파일이 존재하지 않는다”는 에러가 날 때가 있습니다.
Unicode 문제 해결을 위한 도구
String.prototype.normalize()
JavaScript에서는 이러한 Unicode 표현 차이를 해결하기 위해 String.prototype.normalize()
메서드를 제공합니다.
문자열을 NFC, NFD, NFKC, NFKD 등의 정규화 형태로 변환할 수 있어, 파일명이나 문자열 비교 시 유용합니다.
정규화 형태의 종류
- NFC (Canonical Composition)
- 조합형으로 표현.
- 예: "배너" →
U+BAA8 U+B124
.
- NFD (Canonical Decomposition)
- 분리형으로 표현.
- 예: "배너" →
U+1107 U+1161 U+1102 U+1161
.
- NFKC (Compatibility Composition)
- NFC와 유사하나, 호환 가능한 문자(예: 형식 문자 등)를 통합.
- 예:
①
→1
.
- NFKD (Compatibility Decomposition)
- NFD와 유사하나, 호환 가능한 문자까지 분해.
- 예:
①
→1
.
normalize()
사용 예시
const fileName1 = "배너"; // NFC
const fileName2 = "배너"; // NFD
console.log(fileName1 === fileName2); // false
// 정규화 후 비교
console.log(fileName1.normalize('NFC') === fileName2.normalize('NFC')); // true
어디에 활용할 수 있을까?
- 파일명 처리: 업로드된 파일명을 NFC로 통일
- DB 저장 및 검색: DB에 입력하기 전, 동일한 형태(NFC or NFD)로 변환
- 문자열 비교/정렬: UI에서 문자열 정렬 시, 예기치 못한 순서 꼬임 방지
한국인 개발자로서 한글 활용의 중요성
한글을 사용하는 데 있어서, 이런 기술적 문제가 때때로 걸림돌이 되기도 합니다. 그럼에도 불구하고 한글을 적극적으로 활용하는 것은 다음과 같은 이점이 있습니다.
- 의미 전달의 정확성
“주택담보대출” 같은 용어는 영어 “Mortgage Loan”으로 어느 정도 설명이 되지만, 세밀한 뉘앙스를 살리기는 어렵습니다. - 효율적이고 직관적인 표현
영어보다 짧은 글자로 풍부한 의미를 담을 수 있어, 변수명·주석 등에서 더 빠른 이해가 가능합니다. - 서비스 특화
국내 사용자 대상으로 서비스를 개발할 때, 영어만 사용하면 오히려 사용성이 떨어집니다. 한글로 기능명이나 에러 메시지 등을 명확히 전달할 수 있습니다.
한글 활용 시 고려해야 할 점
- 로케일 설정
- 서버 OS나 DB, 앱 프레임워크 설정에서 한글 로케일이 올바르게 지정되어 있는지 확인
- 코드 정규화 정책
- Git, CI/CD 파이프라인 등 협업 환경에서 “파일명·문자열은 항상 NFC로 통일한다” 같은 정책 수립
- 글로벌 협업 시
- 전 세계 개발자와 협업하거나, 오픈소스 기여 시 한글 변수를 사용할 경우 의사소통 장벽이 생길 수 있으므로 주의
체크리스트: 한글 파일명·문자열 처리 시 유의 사항
- 운영체제별/파일 시스템별 한글 처리 방식
- macOS(NFD), Windows(NFC), Linux(다양) 등 서로 다른 환경 고려
- 문자열 정규화 로직
- JavaScript, Python 등에서 제공하는 normalize 함수를 활용해 통일
- Git/CI 파이프라인
- 저장소에 올라가는 파일을 자동으로 정규화하는 스크립트 혹은 Git 훅(hook) 설정
- DB 및 검색 엔진
- 한글 문자열 검색 시 DB 정규화 정책이 맞는지 확인
- 협업 가이드
- 팀 내에서 “한글 변수명/파일명 사용 범위”와 “글로벌 협업 시 대안” 등을 미리 합의
결론: 한글, 지양이 아닌 지향의 대상
개발자는 문제를 해결하는 사람입니다. 한국인 개발자로서 한글을 적극 활용하면서도, 그 과정에서 예상되는 문제(조합형 vs 분리형, 운영체제별 차이 등)를 잘 이해하고 관리해야 합니다.
한글은 우리의 언어이자 강점이며, 더 나은 서비스를 만드는 도구가 될 수 있습니다. “한글 사용 = 문제”가 아니라, “한글 사용 시 나타나는 문제를 해결할 지식과 경험”을 갖추는 것이 중요합니다. 이 과정을 통해 우리는 국내 개발 환경을 풍요롭게 만들 수 있을 것입니다.