WSL2 → Windows 클립보드 한글 깨짐 — clip.exe 는 CP949 로 읽는다
WSL2 에서 clip.exe 로 한글을 복사하면 메모장에서 깨진다. 원인은 시스템 ANSI 코드페이지 해석. PowerShell Set-Clipboard 또는 UTF-16LE BOM 으로 해결한다.
WSL2 셸에서 정리한 한글 텍스트를 Windows 메모장에 붙여넣으려고 clip.exe 에 파이프했다. 붙여넣으니 이렇게 나왔다.
echo "한글 테스트" | clip.exe
# Windows 메모장에서 Ctrl+V → �ѱ� ��Ʈ
영문만 있을 때는 멀쩡했다. 한글이 섞이는 순간에만 깨진다면 이 글이 맞는 자리다.
원인은 코드페이지 불일치
clip.exe 는 stdin 으로 들어온 바이트를 시스템 ANSI 코드페이지로 해석한다. 한국어 Windows 에서는 CP949 다.
WSL2 쪽 셸은 UTF-8 로 출력한다. 그래서 UTF-8 로 인코딩된 한글 바이트열이 CP949 표로 잘못 디코딩되면서 글자가 뭉개진다.
ASCII 범위의 영문·숫자는 두 코드페이지에서 바이트 값이 같다. 그래서 영문은 멀쩡하고 한글·이모지 같은 멀티바이트 문자에서만 터진다. 이 비대칭이 원인을 늦게 찾게 만든다 — “복사가 안 된다”가 아니라 “가끔 깨진다”로 체감되기 때문이다.
해결책 두 가지
① PowerShell Set-Clipboard — 이쪽을 쓴다
PowerShell 은 stdin 을 UTF-8 / UTF-16 으로 다루므로 한글이 그대로 보존된다.
# 단발 문자열
echo "한글" | powershell.exe -NoProfile -Command '$input | Set-Clipboard'
# 파일 — Windows 경로로 변환하고 인코딩을 명시한다
WIN_PATH=$(wslpath -w ./notes.md)
powershell.exe -NoProfile -Command "Get-Content -Path '$WIN_PATH' -Raw -Encoding UTF8 | Set-Clipboard"
파일을 넘길 때 wslpath -w 를 빼먹으면 안 된다. PowerShell 은 /home/... 형태의 경로를 모른다.
② clip.exe + UTF-16LE BOM
clip.exe 도 BOM(\xFF\xFE)이 앞에 붙은 UTF-16LE 입력은 유니코드로 인식한다.
{ printf '\xff\xfe'; echo -n "한글" | iconv -f UTF-8 -t UTF-16LE; } | clip.exe
PowerShell 을 띄우지 않으니 더 빠르다. 대신 한 줄이 길고 BOM 을 손으로 조립해야 한다. 스크립트 안에 넣을 거라면 ① 이 읽기 좋다.
함수로 고정하기
매번 파이프를 조립하는 대신 셸 함수로 만들어 ~/.zshrc 에 넣어뒀다.
# WSL2 한글 클립보드 복사 — Windows 메모장 호환
wclip() {
if [[ -t 0 && -n "$1" ]]; then
local winpath
winpath=$(wslpath -w "$1") || return 1
powershell.exe -NoProfile -Command "Get-Content -Path '$winpath' -Raw -Encoding UTF8 | Set-Clipboard"
else
powershell.exe -NoProfile -Command '$input | Set-Clipboard'
fi
}
세 가지 호출 방식이 다 통한다.
echo "한글" | wclip # 파이프 입력
cat notes.md | wclip # cat 파이프
wclip ./notes.md # 파일 경로 직접
분기 조건이 조금 낯설 수 있어 풀어 쓰면 이렇다.
-t 0— stdin 이 터미널이다. 즉 파이프로 들어온 게 없다.-n "$1"— 첫 인자가 비어 있지 않다.- 두 조건이 모두 참이면 파일 모드로 간다.
wslpath로 경로를 바꾸고Get-Content -Encoding UTF8로 읽는다. - 그 외에는 stdin 모드다. PowerShell 의
$input자동 변수로 파이프를 받는다.
파이프 입력이 있는데 인자도 준 경우는 파이프를 우선한다. 실수로 둘 다 넘겼을 때 파일이 조용히 무시되는 쪽이, 파이프 내용이 사라지는 쪽보다 낫다고 봤다.
반대 방향은 문제없다
Windows 에서 복사한 한글을 WSL2 셸에 붙여넣는 건 깨지지 않는다. 터미널이 UTF-8 로 디코딩하기 때문이다. 이건 단방향 문제다.
다만 powershell.exe Get-Clipboard 로 Windows 클립보드 내용을 WSL2 셸로 끌어올 때는 출력이 UTF-16LE 라 iconv 가 한 번 더 필요할 수 있다.
같은 뿌리의 다른 증상
이 코드페이지 불일치는 클립보드에만 나오는 게 아니다. powershell.exe -Command 로 한글이 든 문자열을 넘기는 모든 경로에서 같은 일이 벌어진다. 알림 쪽 사례는 WSL2 에서 Windows 토스트 알림 띄우기에 정리했고, 거기서는 -EncodedCommand 로 UTF-16LE base64 를 넘겨 우회했다.
참고로 tmux 안에서 OSC 52 로 복사가 안 되는 건 이것과 전혀 다른 원인이다. OSC 52 는 base64 로 실어 나르므로 코드페이지의 영향을 받지 않는다. 그쪽은 tmux 의 set-clipboard 기본값 문제다.