문제 상황 (Problem)
PowerShell 스크립트에서 한글을 출력하면 깨진다.
1
2
| Write-Host "보안 스캔 시작..."
# 출력: ë³´ì ìºì ììì...
|
JSON 파일을 읽어도 한글이 깨진다.
1
2
3
| $config = Get-Content -Path config.json -Raw | ConvertFrom-Json
Write-Host $config.description
# 출력: ì¤ì íì¼
|
Windows의 기본 인코딩이 CP949(또는 Windows-1252)라서 발생하는 문제다.
인코딩 기초 (Encoding Basics)
인코딩이란?
문자를 컴퓨터가 이해할 수 있는 바이트로 변환하는 규칙이다.
| 문자 | UTF-8 (3바이트) | CP949 (2바이트) |
|---|
| 한 | 0xED 0x95 0x9C | 0xC7 0xD1 |
| 글 | 0xEA 0xB8 0x80 | 0xB1 0xDB |
주요 인코딩
| 인코딩 | 설명 | 한글 지원 | 바이트 수 |
|---|
| UTF-8 | 유니코드, 전 세계 문자 | ✅ | 가변 (1-4바이트) |
| UTF-16 | 유니코드, Windows 내부 | ✅ | 고정 (2바이트) |
| CP949 | 한글 Windows 기본 | ✅ (한글만) | 2바이트 |
| Windows-1252 | 영문 Windows 기본 | ❌ | 1바이트 |
| ASCII | 영문, 숫자, 기호만 | ❌ | 1바이트 |
PowerShell 인코딩 설정
PowerShell은 여러 곳에서 인코딩을 설정해야 한다.
1. 콘솔 코드 페이지 (chcp)
Windows 콘솔의 문자 인코딩을 설정한다.
1
2
3
4
5
6
7
| # 현재 코드 페이지 확인
chcp
# 출력: Active code page: 949 (CP949, 한글 Windows 기본)
# UTF-8로 변경
chcp 65001
# 출력: Active code page: 65001 (UTF-8)
|
주요 코드 페이지
| 코드 페이지 | 인코딩 | 설명 |
|---|
| 949 | CP949 | 한글 Windows 기본 |
| 1252 | Windows-1252 | 영문 Windows 기본 |
| 65001 | UTF-8 | 유니코드 |
| 437 | OEM-US | DOS 기본 |
2. OutputEncoding
PowerShell이 외부 프로그램에 전달하는 문자열의 인코딩이다.
1
2
3
4
5
6
7
8
| # 현재 OutputEncoding 확인
$OutputEncoding
# 출력: IsSingleByte : True
# BodyName : iso-8859-1
# EncodingName : Western European (Windows)
# UTF-8로 변경
$OutputEncoding = [System.Text.Encoding]::UTF8
|
3. Console Encoding
콘솔 입출력의 인코딩을 설정한다.
1
2
3
4
5
6
7
| # 현재 Console Encoding 확인
[Console]::OutputEncoding
[Console]::InputEncoding
# UTF-8로 변경
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
[Console]::InputEncoding = [System.Text.Encoding]::UTF8
|
4. 파일 읽기/쓰기 기본 인코딩
Get-Content, Set-Content, Out-File 등의 기본 인코딩을 설정한다.
1
2
3
4
5
6
7
8
9
10
| # 기본 인코딩 확인 (PowerShell 5.1)
Get-Content -Path test.txt -Encoding Default # ASCII
# PowerShell 7+에서는 기본이 UTF-8 (No BOM)
# 모든 파일 관련 cmdlet의 기본 인코딩을 UTF-8로 설정
$PSDefaultParameterValues['*:Encoding'] = 'utf8'
$PSDefaultParameterValues['Out-File:Encoding'] = 'utf8'
$PSDefaultParameterValues['Set-Content:Encoding'] = 'utf8'
$PSDefaultParameterValues['Add-Content:Encoding'] = 'utf8'
|
완전한 UTF-8 설정 패턴
Windows Agent 스크립트에 사용한 표준 패턴이다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
| # Console encoding settings
try {
# 1. 콘솔 코드 페이지를 UTF-8(65001)로 변경
# 출력 버리기: $null = ... 2>&1
$null = cmd /c chcp 65001 2>&1
# 2. 외부 프로그램 전달 인코딩
$OutputEncoding = [System.Text.Encoding]::UTF8
# 3. 콘솔 입출력 인코딩
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
[Console]::InputEncoding = [System.Text.Encoding]::UTF8
# 4. 파일 관련 cmdlet 기본 인코딩
$PSDefaultParameterValues['*:Encoding'] = 'utf8'
$PSDefaultParameterValues['Out-File:Encoding'] = 'utf8'
$PSDefaultParameterValues['Set-Content:Encoding'] = 'utf8'
$PSDefaultParameterValues['Add-Content:Encoding'] = 'utf8'
} catch {
# 인코딩 설정 실패 시 무시 (일부 환경에서 권한 문제 발생 가능)
# 하지만 대부분의 경우 문제없이 동작
}
|
적용 전후 비교
1
2
3
4
5
6
7
8
9
10
| # Before: CP949 (기본)
Write-Host "보안 스캔 시작..."
# 출력: ë³´ì ìºì ììì... (깨짐)
# After: UTF-8 설정 적용
$null = cmd /c chcp 65001 2>&1
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
Write-Host "보안 스캔 시작..."
# 출력: 보안 스캔 시작... (정상)
|
UTF-8 BOM vs UTF-8 (No BOM)
BOM (Byte Order Mark)이란?
파일 맨 앞에 붙는 3바이트 마커: 0xEF 0xBB 0xBF
1
2
3
| UTF-8 BOM: EF BB BF 48 65 6C 6C 6F
UTF-8 No BOM: 48 65 6C 6C 6F
↑ BOM ↑ "Hello"
|
차이점
| 특성 | UTF-8 BOM | UTF-8 (No BOM) |
|---|
| 크기 | +3 바이트 | 원본 크기 |
| Windows 호환 | ✅ 우수 | ⚠️ 일부 도구 문제 |
| Unix/Linux 호환 | ⚠️ 일부 스크립트 문제 | ✅ 우수 |
| PowerShell 인식 | ✅ 자동 인식 | ⚠️ 명시 필요 |
| JSON/XML | ✅ 권장 | ✅ 동일 |
PowerShell에서 BOM 처리
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| # UTF-8 BOM으로 저장 (PowerShell 5.1 기본)
"안녕하세요" | Out-File -FilePath test.txt -Encoding UTF8
# UTF-8 No BOM으로 저장 (PowerShell 7+ 기본)
"안녕하세요" | Out-File -FilePath test.txt -Encoding utf8NoBOM
# BOM 확인
$bytes = [System.IO.File]::ReadAllBytes("test.txt")
if ($bytes.Length -ge 3 -and
$bytes[0] -eq 0xEF -and
$bytes[1] -eq 0xBB -and
$bytes[2] -eq 0xBF) {
Write-Host "UTF-8 BOM detected"
} else {
Write-Host "No BOM or different encoding"
}
|
파일 읽기/쓰기 인코딩
Get-Content
1
2
3
4
5
6
7
8
| # PowerShell 5.1 (기본: ASCII)
$content = Get-Content -Path config.json # ❌ 한글 깨짐
# UTF-8 명시
$content = Get-Content -Path config.json -Encoding UTF8 # ✅ 정상
# PowerShell 7+ (기본: UTF-8 No BOM)
$content = Get-Content -Path config.json # ✅ 정상
|
Set-Content
1
2
3
4
5
6
7
| # PowerShell 5.1
$data = "한글 데이터"
Set-Content -Path output.txt -Value $data -Encoding UTF8 # ✅ UTF-8 BOM
# PowerShell 7+
Set-Content -Path output.txt -Value $data # ✅ UTF-8 No BOM
Set-Content -Path output.txt -Value $data -Encoding utf8BOM # UTF-8 BOM
|
Out-File
1
2
3
4
5
6
| # PowerShell 5.1
"한글" | Out-File -FilePath output.txt # ❌ UTF-16 LE (기본)
"한글" | Out-File -FilePath output.txt -Encoding UTF8 # ✅ UTF-8 BOM
# PowerShell 7+
"한글" | Out-File -FilePath output.txt # ✅ UTF-8 No BOM
|
ConvertFrom-Json / ConvertTo-Json
1
2
3
4
5
6
7
8
9
10
| # JSON 파일 읽기 (UTF-8)
$json = Get-Content -Path config.json -Raw -Encoding UTF8 | ConvertFrom-Json
# JSON 파일 쓰기 (UTF-8)
$data = @{
name = "김철수"
description = "한글 설명"
}
$data | ConvertTo-Json -Depth 10 | Out-File -FilePath output.json -Encoding UTF8
|
실전 문제 해결
문제 1: 한글 파일명이 깨짐
1
2
3
4
5
6
7
| # ❌ 문제
Get-ChildItem "C:\Users\한글폴더"
# 오류: Cannot find path '...çNìÜíìë' because it does not exist.
# ✅ 해결
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
Get-ChildItem "C:\Users\한글폴더"
|
문제 2: REST API 응답 한글 깨짐
1
2
3
4
5
6
7
8
| # ❌ 문제
$response = Invoke-RestMethod -Uri "https://api.example.com/data"
Write-Host $response.message # 깨짐
# ✅ 해결
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
$response = Invoke-RestMethod -Uri "https://api.example.com/data" -ContentType "application/json; charset=utf-8"
Write-Host $response.message
|
문제 3: 로그 파일 한글 깨짐
1
2
3
4
5
6
7
8
9
10
| # ❌ 문제
"보안 스캔 완료" | Out-File -Append -FilePath log.txt
# 파일 열면: ë³´ì ìºì ìë£
# ✅ 해결 1: 인코딩 명시
"보안 스캔 완료" | Out-File -Append -FilePath log.txt -Encoding UTF8
# ✅ 해결 2: 기본 인코딩 설정
$PSDefaultParameterValues['Out-File:Encoding'] = 'utf8'
"보안 스캔 완료" | Out-File -Append -FilePath log.txt
|
PowerShell 5.1 vs 7+ 인코딩 차이
| 동작 | PowerShell 5.1 | PowerShell 7+ |
|---|
| Get-Content 기본 | ASCII | UTF-8 No BOM |
| Set-Content 기본 | ASCII | UTF-8 No BOM |
| Out-File 기본 | UTF-16 LE | UTF-8 No BOM |
| ConvertTo-Json | UTF-16 LE | UTF-8 |
| 콘솔 출력 | CP949/1252 | UTF-8 |
마이그레이션 팁
1
2
3
4
5
6
7
8
9
10
11
12
13
| # PowerShell 5.1 스크립트를 7+로 마이그레이션할 때
# Before (5.1)
Get-Content -Path file.txt -Encoding UTF8
Out-File -FilePath output.txt -Encoding UTF8
# After (7+) - 명시적 인코딩 불필요
Get-Content -Path file.txt
Out-File -FilePath output.txt
# 하지만 호환성을 위해 명시하는 것이 안전
Get-Content -Path file.txt -Encoding utf8
Out-File -FilePath output.txt -Encoding utf8
|
디버깅 팁
1. 현재 인코딩 확인
1
2
3
4
5
6
| Write-Host "=== Encoding Information ==="
Write-Host "Console Output Encoding: $([Console]::OutputEncoding.EncodingName)"
Write-Host "Console Input Encoding: $([Console]::InputEncoding.EncodingName)"
Write-Host "Output Encoding: $($OutputEncoding.EncodingName)"
Write-Host "Code Page: $(chcp)"
Write-Host "PowerShell Version: $($PSVersionTable.PSVersion)"
|
2. 파일 인코딩 감지
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
| function Get-FileEncoding {
param([string]$Path)
$bytes = [System.IO.File]::ReadAllBytes($Path)
# BOM 확인
if ($bytes.Length -ge 3) {
if ($bytes[0] -eq 0xEF -and $bytes[1] -eq 0xBB -and $bytes[2] -eq 0xBF) {
return "UTF-8 BOM"
}
}
if ($bytes.Length -ge 2) {
if ($bytes[0] -eq 0xFF -and $bytes[1] -eq 0xFE) {
return "UTF-16 LE"
}
if ($bytes[0] -eq 0xFE -and $bytes[1] -eq 0xFF) {
return "UTF-16 BE"
}
}
return "UTF-8 No BOM or ASCII"
}
# 사용 예
Get-FileEncoding -Path "config.json"
|
3. 인코딩 변환 스크립트
1
2
3
4
5
6
| # 모든 .ps1 파일을 UTF-8 BOM으로 변환
Get-ChildItem -Path . -Filter *.ps1 -Recurse | ForEach-Object {
$content = Get-Content -Path $_.FullName -Raw -Encoding UTF8
Set-Content -Path $_.FullName -Value $content -Encoding UTF8
Write-Host "Converted: $($_.Name)"
}
|
VS Code 설정
VS Code에서 PowerShell 스크립트를 작성할 때도 인코딩 설정이 중요하다.
settings.json
1
2
3
4
5
6
7
8
| {
"files.encoding": "utf8bom",
"files.autoGuessEncoding": true,
"[powershell]": {
"files.encoding": "utf8bom",
"files.eol": "\r\n"
}
}
|
.editorconfig
1
2
3
| [*.ps1]
charset = utf-8-bom
end_of_line = crlf
|
실전 팁 (Best Practices)
1. 스크립트 시작 부분에 인코딩 설정
1
2
3
| # 모든 PowerShell 스크립트 맨 위에
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
$PSDefaultParameterValues['*:Encoding'] = 'utf8'
|
2. JSON 파일은 UTF-8 (No BOM) 권장
1
2
| # JSON은 BOM 없이 저장 (표준)
$data | ConvertTo-Json -Depth 10 | Out-File -Encoding utf8NoBOM -FilePath config.json
|
3. 로그 파일은 UTF-8 BOM 사용
1
2
| # Windows에서 Notepad로 열 때 한글이 정상 표시됨
"로그 메시지" | Out-File -Append -Encoding UTF8 -FilePath app.log
|
4. 외부 프로그램 호출 시 주의
1
2
3
4
5
| # cmd.exe는 기본이 CP949
cmd /c dir # 한글 파일명 깨질 수 있음
# UTF-8로 변경 후 실행
cmd /c chcp 65001 '&' dir
|
결론 (Conclusion)
PowerShell의 인코딩 문제는 여러 설정을 모두 맞춰야 해결된다.
Key Takeaways
- chcp 65001: 콘솔 코드 페이지를 UTF-8로
- OutputEncoding: 외부 프로그램 전달 인코딩
- Console Encoding: 콘솔 입출력 인코딩
- PSDefaultParameterValues: 파일 cmdlet 기본 인코딩
- UTF-8 BOM: Windows 환경에서는 BOM 사용 권장
한 곳만 설정하면 안 됩니다. 4곳 모두 설정해야 완벽하게 해결됩니다.
1
2
3
4
5
| # 완벽한 UTF-8 설정 (4종 세트)
$null = cmd /c chcp 65001 2>&1
$OutputEncoding = [System.Text.Encoding]::UTF8
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
$PSDefaultParameterValues['*:Encoding'] = 'utf8'
|
도움이 되셨길 바랍니다! 😀