본문 바로가기
목차
Errors

[CLI] Power shell에서 한글 경로

by ds31x 2023. 6. 29.
728x90
반응형

시작

한글은 정말 훌륭한 언어이다.
표현력, 체계성, 가독성 면에서 매우 뛰어난 언어라고 생각한다.

 

다만 개발 환경에서는 가급적 한글이 포함된 경로(path)를 사용하지 않는 것을 강하게 권한다.
특히 오픈 소스 라이브러리를 많이 사용하는 환경일수록, 이 문제는 생각보다 자주 그리고 불필요하게 피곤한 디버깅의 원인이 된다.


사실상 UTF-8 시대인데도 왜 이런 문제가 남아 있을까?

요즘은 WSL, Linux, macOS 모두 UTF-8이 사실상의 기본 인코딩이다.
파일 이름, 터미널 입출력, 그리고 대부분의 라이브러리와 도구가 UTF-8을 전제로 동작한다.

Windows 역시 Unicode를 사용하지만, 내부적으로는 UTF-16LE를 표준 문자열 표현으로 채택하고 있다.
즉, 운영체제 차원에서 한글을 처리하지 못하는 문제는 아니다.

 

문제의 핵심은 다음 지점에 있다.

UTF-8과 UTF-16LE는 모두 한글 표현이 가능하지만,
Windows 위에서 동작하는 일부 도구와 라이브러리는

여전히 UTF-16LE가 아닌 char* 기반 문자열 처리를 유지하고 있으며,

이때 문자열 해석 기준으로 ACP(Windows ANSI Code Page)를 사용한다는 점이다.


혼재된 문자열 처리 방식의 예

대표적인 예로 cmd.exe를 들 수 있다.

  • cmd.exe 내부의 문자열 표현은 UTF-16LE를 사용한다.
  • 그러나 콘솔 입출력이나 ANSI API 경로에서는 현재 시스템 코드페이지가 개입한다.
  • 한국어 Windows의 경우, 이 코드페이지는 보통 CP949(MS949) 이다.

이처럼 하나의 환경 안에서

  • UTF-16LE 기반 처리(Wide API, wchar_t* 사용)와
  • ACP 기준의 char* 문자열 처리가

함께 존재하게 되면,

  • UTF-8 → UTF-16LE 변환이나
  • UTF-8 → ACP → UTF-16LE와 같은 중간 변환 과정이 올바르게 수행되지 않는 경우가 발생할 수 있다.

그 결과, 파일은 분명히 존재함에도 불구하고
경로를 찾지 못하거나, 접근에 실패하는 문제로 이어질 가능성이 생긴다.


참고: ACP (Windows ANSI Code Page)

ACP(Windows ANSI Code Page)
char* 문자열을 어떤 인코딩으로 해석할지를 결정하는 Windows의 시스템 코드페이지를 의미한다.

일반적으로 다음과 같다.

  • 한국어 Windows: 보통 CP949
  • 영어 Windows: 보통 CP1252

이 ACP의 값은 운영체제 언어 환경에 따라 달라지며,
char* 기반 문자열 처리를 사용하는 코드에서는 동작 결과에 직접적인 영향을 미친다.


Windows 에서 path(경로) 처리의 실제 구조

Windows에는 문자 처리를 위한 두 계층이 공존하고 있음.

  1. Unicode 기반 계층 (정상적이고 현대적인 방식)
    • UTF-16LE를 사용하는 Win32 Wide API
    • 예: CreateFileW, FindFirstFileW
    • 이 계층에서는 한글, 공백, 모든 Unicode 경로(path)가 정상 처리된다
    • 즉, 이 계층만 사용한다면 경로 문제는 발생하지 않는다.
  2. 레거시 문자열 기반 계층 (문제의 근원)
    • char* 문자열을 사용하는 ANSI/멀티바이트 계층
    • 내부적으로 Windows ANSI Code Page(ACP) 에 의존

특히 2번의 대표적인 예는 다음과 같다.

  • CreateFileA
  • fopen(char*)
  • 일부 C/C++ 런타임 함수
  • 일부 오픈 소스 라이브러리의 Windows 포팅 코드

경로 문제의 근원

  • 문자열이 레거시 char*로 전달될 경우, 인코딩 정보가 명시되어있지 않으므로
  • 이 경우, 이를 전달받는  Windows 런타임이나 라이브러리가 이를 ACP 기준 멀티바이트 문자열로 해석하는데,
  • 이 경우 ACP와 다르게 인코딩된 문자열 (중간의 도구나 라이브러리에서 UTF-8등을 사용하여 인코딩)이 전달된 경우 문제가 생김.

그 결과:

  • 같은 코드
  • 같은 경로 문자열
  • 같은 파일이 존재함에도 불구하고

Windows 언어 환경이나 실행 경로에 따라 동작이 달라질 수 있음.


Example: PowerShell + tar.exe(bsdtar)

 

참고: Windows 10(1803 이후) 및 Windows 11에는 libarchive 기반의 tar.exe(bsdtar)가 기본 포함되어 있으며, PowerShell에서 별도 설치 없이 바로 사용할 수 있음.

 

참고: 현재는 tar.exe(bsdtar)에 이같은 문제를 회피하는 코드들이 보강되어 최신 버전에선 아래의 문제가 재현되지 않을 수 있음.

 

다음과 같은 한글 경로에 파일이 존재한다고 가정:

c:\work\실험\data.txt

PowerShell cmdlet을 사용하면 해당 파일은 정상적으로 접근됨.

PS> Test-Path 'C:\work\실험\data.txt'
True

PS> Get-Content 'C:\work\실험\data.txt'
hello

 

같은 PowerShell 환경에서,

Windows에 기본 포함된 tar.exe를 사용해 해당 파일을 압축하려고 하면

다음과 같은 오류가 발생하는 경우가 있음:

PS> cd "C:\work\"
PS> tar -cf out.tar "실험\data.txt"
tar: Failed to open '실험\data.txt'
tar: Cannot stat: No such file or directory

 

파일은 분명히 존재함에도 불구하고, tar.exe는 해당 경로를 찾지 못하고 실패한다.
(보통 에러 메시지에서  "실험"이 깨져서 나옴)

 

이는 PowerShell의 문제가 아니라,
tar.exe(bsdtar)가 Windows에서 일부 코드경로(main(char** argv))에서  char* 기반 문자열 처리를 사용하며

이 과정에서 Windows ANSI Code Page(ACP)에 의존하는 경로 해석 계층이 개입할 수 있음

 

Windows와 POSIX 도구 사이의 경계에서,
UTF-16LE로 표현된 경로 문자열이
char* 기반 문자열로 변환·처리되는 과정 중
Windows ANSI Code Page(ACP)가 개입하면서
경로 문자열 해석이 어긋나 문제가 발생한다.

구체적으로,
CRT(C Run-Time Library)는
wchar_t*로 표현된 UTF-16LE 유니코드 문자열을
ACP(한국어 Windows에서는 CP949)를 기준으로
멀티바이트 char* 문자열로 인코딩 변환하는데,
tar.exe(bsdtar)와 같은 POSIX 기반 도구의 내부 로직은
char* 문자열을 UTF-8로 인코딩된 것으로 가정하는 경우가 많음.

그 결과,
실제 NTFS에 존재하는 경로 문자열과
내부적으로 해석된 문자열이 불일치하여
파일이 존재함에도 불구하고
접근에 실패하는 문제가 발생할 수 있다.

디버깅의 관점에서 본 한글 경로 문제

이 문제의 가장 나쁜 점은 다음과 같다.

  • path(경로) 문자열은 겉보기엔 정상임.
  • log(로그)에도 특별한 이상이 없다
  • 실제 해당 경로에 자원이 있음에도 오류 메시지는 단순히 “파일을 찾을 수 없다”로만 나옴.

하지만 실제 원인은:

  • char* 기반 처리 여부
  • 내부 API가 Wide API인지 ANSI API인지
  • ACP 해석이 개입했는지 여부 등과 같은 같은 보이지 않는 내부 계층에 있다.

PowerShell, Python, CMake, Make, 오픈 소스 라이브러리가 섞이면
어디서 문제가 발생했는지 추적하기가 매우 어려워진다.


참고: OS별 인코딩

OS별로 보면 차이는 더 명확해진다

WSL, Linux, macOS

  • UTF-8이 기본임
  • 거의 대부분의 도구 체인이 UTF-8로 일관됨
  • 이는 일관된 path 문자열 처리 가정을 가능하게함.

Windows

  • 내부 문자열 표준은 UTF-16LE
  • 그러나 레거시 char* + Windows ANSI Code Page(ACP) 계층이 여전히 존재
  • 여전히 도구와 라이브러리에 따라 처리 방식이 혼재됨
  • 오픈소스 라이브러리를 프로젝트 도입시 문제 발생 지점의 추적이 매우 어려움.

권장되는 path

그래서 실무적인 결론은 공백문자나 한글이 들어간 path(경로)를 사용하지 않는 것임:

 

문제를 만들지 않는 경로:

C:\work\
D:\dev\
/home/user/project

 

문제를 만들 가능성이 높은 경로:

C:\Users\홍길동\
D:\내 문서\실험 프로젝트\

개발 도구 생태계가 아직 모든 경로 문자열을 일관된 Unicode 인코딩로 처리하지 않음에 주의해야 하다.


핵심 요약

  • Windows는 내부적으로 UTF-16LE 를 사용한다.
  • 문제가 되는 것은 Windows ANSI Code Page(ACP) 에 의존하는 레거시 char* 기반 처리다.
  • 때문에 실무에서는 다음을 명심할 것:
    • 개발 환경에서는 공백과 한글이 포함된 경로를 사용하지 않는 것이 가장 안전.
728x90