파워셸 5.1 한글 깨짐, BOM 없는 ps1 과 출력 인코딩 해결

먼저 결론
증상: 한글이 든 .ps1 이 예약 실행에서 결과 코드 1로 죽고, 파워셸 출력을 받은 프로그램에서는 한글 경로 비교가 늘 거짓이 됩니다.
원인: 파워셸 5.1 은 BOM 없는 스크립트와 출력을 모두 CP949 로 다룹니다.
해결: 스크립트는 UTF-8 BOM 으로 저장하고, 출력을 받을 때는 명령 맨 앞에서 OutputEncoding 을 UTF-8 로 바꿉니다.

윈도우 기본 파워셸 5.1 은 한글을 두 방향에서 깨뜨립니다. 들어오는 스크립트 파일을 읽을 때 한 번, 결과를 내보낼 때 한 번입니다. 둘 다 오류 없이 조용히 틀리는 경우가 많아서 원인을 찾기까지 오래 걸렸습니다.

오류가 나거나, 아무 오류 없이 틀리거나

첫 번째로 겪은 일은 매일 02:00 에 도는 야간 작업이 아침마다 죽어 있던 것입니다. 작업 스케줄러의 LastTaskResult 는 1 이었고, 스크립트가 만들어야 할 로그 파일조차 생기지 않았습니다. 같은 파일을 손으로 powershell -File 로 돌리니 그제야 파싱 오류가 보였습니다.

Unexpected token '숇큺?뚯씠??=' in expression or statement.

긴 배치 스크립트 하나는 한글 변수 이름이 통째로 깨지면서 이런 문법 오류를 28건 냈습니다. 반대로 한글 정규식으로 로그를 기다리는 감시 스크립트는 오류가 하나도 없었는데, 매칭에 영원히 실패하며 무한 대기에 빠졌습니다.

두 번째는 출력 쪽입니다. 백그라운드로 도는 노드 프로그램이 파워셸로 프로세스 명령줄을 받아 "내 설치 경로가 들어 있나"로 자기 프로세스인지 가렸습니다. 그런데 비교가 늘 거짓이라 자기 자신을 남의 것으로 보고 10분마다 죽였다 켰고, 하루 144회 재시작이 쌓였습니다. 이때도 오류는 없었습니다.

세 번째는 git commit -m 에 히어스트링을 넘겼을 때 메시지 안의 큰따옴표에서 글이 잘리고, 뒷부분이 파일 경로로 읽혀 커밋이 실패한 일입니다.

5.1 의 기본 인코딩이 CP949 다

증상 원인
예약 실행 결과 코드 1, 로그 없음 BOM 없는 UTF-8 스크립트를 ANSI(한국어 윈도우 = CP949)로 읽어 파싱 실패
한글 정규식이 영원히 안 맞음 같은 이유로 패턴 글자가 깨져서 비교 대상이 달라짐
한글 경로 비교가 늘 거짓 파워셸은 CP949 로 내보내는데 노드는 UTF-8 로 읽음
커밋 메시지가 큰따옴표에서 잘림 5.1 이 네이티브 exe 인자 속 큰따옴표를 이스케이프하지 않음(7.3 에서 고쳐졌다고 알려짐)

함정이 하나 더 있습니다. 구문 검사를 Get-Content -Raw -Encoding UTF8 로 읽어서 하면 UTF-8 로 읽었으니 통과합니다. 하지만 -File 실행에는 인코딩 옵션이 없어 CP949 로 읽고 죽습니다. 검사는 초록인데 예약 실행만 실패하는 이유가 이것입니다.

들어오는 쪽과 나가는 쪽을 따로 고친다

1. 한글이 든 .ps1 은 UTF-8 BOM 으로 다시 저장

BOM 이 있으면 5.1 도 UTF-8 로 알아봅니다. 편집기에 따라 BOM 없이 저장되므로 아래 한 줄로 다시 씁니다.

$p = "C:\scripts\nightly.ps1"
$c = Get-Content $p -Raw -Encoding UTF8
[System.IO.File]::WriteAllText($p, $c, (New-Object System.Text.UTF8Encoding $true))

가능하면 스크립트 안에서는 한글 대신 ASCII 패턴으로 매칭하고, 데이터 파일은 [System.IO.File]::ReadAllText(경로, 인코딩) 로 인코딩을 밝혀 읽습니다.

2. 파워셸 출력을 다른 프로그램이 읽을 때

명령 맨 앞에 출력 인코딩을 UTF-8 로 바꾸는 문장을 붙입니다.

powershell -NoProfile -Command "[Console]::OutputEncoding=[Text.Encoding]::UTF8; Get-CimInstance Win32_Process | Select-Object ProcessId, CommandLine"

경로로 자기 것인지 가릴 때는 한글이 없는 고유한 꼬리(예: \worker\run_worker.py)로도 비교합니다. 글자판이 또 어긋나도 판정이 무너지지 않습니다.

3. 커밋 메시지는 파일로

git commit -F .\commit_msg.txt

4. 긴 배치는 파이썬으로

결국 가장 안전했던 길은 긴 배치를 파이썬으로 짜고, 파워셸은 그것을 띄우는 얇은 시작 명령으로만 쓰는 것이었습니다.

확인 방법

  • 예약 작업을 Start-ScheduledTask 로 한 번 돌리고 Get-ScheduledTaskInfo 의 LastTaskResult 가 0 인지, 로그가 생겼는지 봅니다.
  • 구문 검사를 믿지 말고 반드시 powershell -File 로 실제 실행해 봅니다.
  • 출력을 받는 프로그램은 받은 문자열을 그대로 로그에 찍어 한글이 멀쩡한지 눈으로 봅니다.

같이 알아 두면 좋은 5.1 의 특징도 있습니다. robocopy 종료 코드 0에서 7은 모두 성공이라 0 이 아니라고 실패로 처리하면 오탐이 납니다. 삼항 연산자와 null 병합 연산자는 5.1 에 없어서 if/else 로 써야 합니다.

확인한 환경

항목 내용
운영체제 한국어 윈도우(기본 코드 페이지 CP949)
파워셸 Windows PowerShell 5.1
실행 방식 작업 스케줄러, powershell -File, 노드에서 호출

관련 글

이 글의 내용은 2026년 10월 5일에 마지막으로 확인했습니다. 틀린 곳을 발견하시면 연락처로 알려 주세요.