Claude Code에서 한글 조합이 깨지는 이유와 고치는 법 (데스크톱 · 모바일 SSH)

kunihiko haga·2026년 10월 5일

3줄 요약

  • 터미널에는 "조합 중"이라는 상태가 없습니다. 한글 조합은 전부 클라이언트(터미널 앱) 몫이고, Claude Code는 도착한 바이트만 봅니다
  • 그래서 깨지는 곳은 3군데뿐입니다. ① 조합 중인 글자를 어디에 그리나 ② "지우고 다시 쓰기" 바이트를 어떻게 읽나 ③ 클라이언트가 조합을 아예 안 하나
  • 각각 고치는 법이 다릅니다. 내 환경이 어디에 해당하는지 15줄짜리 스크립트로 확인할 수 있습니다

이런 증상, 겪어 보셨나요?

  • 한글을 치는데 조합 중인 글자가 화면 왼쪽 아래나 한 줄 아래에 떠 있다
  • 휴대폰에서 SSH로 붙어서 치면 ㄱ은 보이는데 ㅏ를 누르는 순간 글자가 사라진다
  • 안녕을 쳤는데 ㅇㅏㄴㄴㅕㅇ 으로 풀려서 들어간다
  • 문장 중간을 고치려고 커서를 옮겨서 한글을 치면, 커서 뒤의 글자가 잠깐 안 보인다

저는 SSH Term이라는 SSH 앱을 혼자 만들고 있습니다. 원래는 안드로이드 SSH 앱에서 일본어 입력이 안 돼서 만든 앱인데, 같은 문제를 한글로 겪는 분이 훨씬 많다는 걸 알고 한글 쪽을 계속 파고 있습니다.

위의 증상들, 겉보기는 비슷해도 원인이 전부 다릅니다. 하나씩 보겠습니다.


먼저 결론: 터미널에는 "조합 중"이 없다

PC에서 claude를 실행하면 구조는 이렇습니다.

키보드 → OS의 IME → 터미널 앱(iTerm2, Windows Terminal 등) → pty → Claude Code

IME가 ㅎ → 하 → 한을 조합하는 동안, 그 과정을 아는 건 터미널 앱까지입니다. 터미널 앱은 조합 중인 글자를 자기 화면 위에 겹쳐서 그려 줄 뿐이고, 조합이 끝나야 비로소 한의 UTF-8 바이트(ed 95 9c)를 pty에 씁니다.

pty는 그냥 바이트가 흐르는 파이프입니다. "지금 이 글자는 조합 중"이라고 알려 주는 표준 시퀀스가 없습니다. 그래서 Claude Code 같은 TUI 입장에서는 도착한 바이트가 전부입니다.

여기서 중요한 건 클라이언트가 한글을 어떤 바이트로 보내느냐입니다. 한을 칠 때, 클라이언트에 따라 3가지로 갈립니다.

방식보내는 바이트TUI가 받는 것
① 완성된 글자만 보낸다ed 95 9c한
② 지우고 다시 쓴다e3 85 8e 7f ed 95 98 7f ed 95 9cㅎ → 지우기 → 하 → 지우기 → 한
③ 조합하지 않고 낱자로 보낸다e3 85 8e e3 85 8f e3 84 b4ㅎㅏㄴ

7f는 DEL(백스페이스)입니다. ②는 조합 중인 글자를 서버에 미리 보내 놓고, 바뀔 때마다 지우고 새 글자를 다시 보내는 방식입니다. 모바일 SSH 앱에서 자주 보입니다.

PC의 터미널 앱은 대부분 ①입니다. 문제는 대부분 ②와 ③, 그리고 ①에서 "조합 중인 글자를 어디에 그리느냐"에서 생깁니다.


깨지는 곳 1: 조합 중인 글자가 엉뚱한 곳에 그려진다 (데스크톱)

터미널 앱은 조합 중인 글자를 진짜 커서 위치에 겹쳐 그립니다. 일반 셸이라면 커서가 입력 위치에 있으니 문제가 없습니다.

그런데 Claude Code 같은 TUI는 화면 전체를 자기가 다시 그립니다. 다 그린 뒤에 진짜 커서를 화면 아래쪽 같은 곳에 두면, 터미널은 그 자리에 조합 중인 글자를 그립니다. 그래서 조합 중인 한이 왼쪽 아래에 둥둥 떠 있는 증상이 납니다.

Claude Code는 이걸 여러 번에 걸쳐 고쳐 왔습니다. CHANGELOG에서 찾아보면 이렇습니다.

  • 2.0.68: IME 조합 창을 커서 위치에 오도록 수정
  • 2.1.84: 진짜 터미널 커서가 입력 캐럿을 따라가도록 수정 → 조합 중인 글자가 입력 줄 안에 그려짐
  • 그 뒤로도 claude agents 화면(2.1.160), Windows의 백그라운드 세션(2.1.153), /skills 검색창(2.1.282) 같은 화면별로 하나씩 고쳐짐

제가 2.1.289에서 확인해 보니, 입력란에 가를 넣으면 진짜 커서가 정확히 가 바로 뒤 칸에 있었습니다.

다만 아직 열려 있는 보고도 있습니다.

  • 문장 중간에서 조합하면 커서 뒤 글자가 잠깐 안 보임 (#75507, macOS + iTerm2). 입력 내용은 그대로이고, 조합이 끝나면 다시 보입니다. 터미널이 조합 중인 글자를 커서 위에 겹쳐 그리는 방식과 TUI의 다시 그리기가 부딪히는 경우로 보고되어 있습니다
  • VS Code 내장 터미널에서 조합 중인 글자가 한 줄 아래에 보임 (#97389). 원인은 Claude Code가 아니라 VS Code의 실험 기능 Modern UI라고 정리되어 있습니다

고치는 법

  1. claude update로 최신 버전을 쓴다. 조합 위치 문제의 대부분은 이미 고쳐진 버전이 있습니다
  2. VS Code라면 설정에서 workbench.experimental.modernUI를 false 로 둔다 (#97389의 우회책)
  3. 긴 문장을 문장 중간 수정해 가며 써야 한다면, Ctrl+G로 외부 편집기를 열어서 거기서 쓴다. Claude Code 입력란 대신 평소 쓰는 편집기에서 한글을 다루게 됩니다

깨지는 곳 2: "지우고 다시 쓰기"를 TUI가 잘못 읽는다 (모바일 SSH)

2025년 12월에 이런 보고가 올라왔습니다 (#15705, 당시 Claude Code 2.0.76). iOS의 SSH 앱(Termius)으로 서버에 붙어서 Claude Code에 가를 치면, ㅏ를 누르는 순간 글자가 사라진다는 내용입니다.

보고자가 서버에서 실제로 받은 바이트를 찍어 봤더니 이랬습니다.

e3 84 b1  7f  ea b0 80
   ㄱ     DEL    가

위 표의 ② 방식입니다. 같은 앱의 Android판에서는 재현되지 않았고, 같은 iOS 환경에서도 Gemini CLI나 Codex CLI는 문제가 없었다고 합니다.

원인은 이슈 댓글에서 커뮤니티가 분석했습니다. ㄱ, DEL, 가가 한 덩어리로 도착하면, 입력 처리 코드가 이 덩어리를 "백스페이스가 섞인 입력"으로 보고 DEL만 처리한 뒤 나머지 글자(가)를 버리고 끝나 버린다는 것입니다. 그래서 ㄱ은 지워지고 가는 안 들어가서, 결과적으로 아무것도 안 남습니다.

지금은 어떨까? 2.1.289에서 직접 확인했습니다

pty로 claude를 띄우고, 입력란에 아래 바이트를 그대로 써 넣은 뒤 화면을 읽었습니다.

보낸 것입력란 결과
ㄱ DEL 가 를 한 덩어리로가 ✅
ㄱ / DEL / 가 를 0.3초 간격으로 따로가 ✅
ㅎ DEL 하 DEL 한 을 한 덩어리로한 ✅
ㄱ DEL 가 DEL 간 DEL 가나 (받침이 다음 글자로 넘어가는 경우)가나 ✅
ㅎ DEL 하 DEL 한 ㄱ DEL 그 DEL 글 을 한 덩어리로한글 ✅
ab 입력 → 왼쪽 화살표 → ㄱ DEL 가 (문장 중간)a가b ✅

2.1.289에서는 전부 제대로 들어갔습니다. CHANGELOG에서 이 수정에 해당하는 항목은 찾지 못했지만, 적어도 이 버전에서는 ② 방식이 깨지지 않습니다.

고치는 법

  1. 서버의 Claude Code를 최신으로 (claude update). 휴대폰 앱이 아니라 SSH로 붙는 서버 쪽 버전이 중요합니다
  2. 그래도 사라진다면, 아래 진단 스크립트로 바이트를 찍어서 이슈에 첨부하면 원인을 좁히기 쉽습니다

깨지는 곳 3: 클라이언트가 조합을 안 한다

같은 #15705에 다른 iOS 앱으로 시험한 댓글이 있습니다. 안녕을 치면 ㅇㅏㄴㄴㅕㅇ 으로 들어간다는 것입니다. 위 표의 ③ 방식입니다.

이건 서버에서는 고칠 수 없습니다. 클라이언트가 이미 낱자로 보내 버렸기 때문에, Claude Code든 bash든 받은 그대로 ㅇㅏㄴㄴㅕㅇ을 보여 줄 수밖에 없습니다.

고치는 법

  • 클라이언트를 바꾸거나, 클라이언트의 키보드 / 입력 설정을 바꾼다. 서버 쪽 설정(locale, 글꼴)으로는 해결되지 않습니다

내 환경은 어디에 해당할까? 바이트를 찍어 보자

#15705 보고자가 쓴 방법을 참고해서, 한 번에 도착한 바이트를 한 줄로 보여 주도록 바꿨습니다. 서버에 이 파일을 만들고, 문제가 나는 그 클라이언트로 SSH 접속한 상태에서 실행합니다.

# keylog.py — 도착한 바이트를 덩어리 단위로 보여 줍니다
import os, sys, termios, tty

fd = sys.stdin.fileno()
old = termios.tcgetattr(fd)
tty.setraw(fd)
try:
    print("키를 입력해 보세요. 끝내려면 Ctrl+C\r")
    while True:
        chunk = os.read(fd, 1024)  # 한 번에 도착한 바이트 = 한 줄
        if not chunk or chunk == b"\x03":
            break
        print(chunk.hex(" ") + "   " + repr(chunk.decode("utf-8", "replace")) + "\r")
finally:
    termios.tcsetattr(fd, termios.TCSADRAIN, old)
python3 keylog.py

가, 한을 쳐 보면 이런 식으로 나옵니다.

e3 84 b1 7f ea b0 80   'ㄱ\x7f가'
ed 95 9c   '한'

읽는 법은 간단합니다.

보이는 것방식해당하는 곳
ea~ed로 시작하는 3바이트만 (완성된 글자)①깨지는 곳 1
중간에 7f가 섞여 있다②깨지는 곳 2
e3 84 / e3 85 / e3 86으로 시작하는 낱자만 계속 나온다③깨지는 곳 3

참고로 e3 84 b1~e3 86 8e가 한글 낱자(ㄱ, ㅏ 같은 호환 자모), ea b0 80~ed 9e a3가 완성된 글자(가~힣)입니다.


정리: 증상별 고치는 법

증상원인고치는 법
조합 중인 글자가 왼쪽 아래 / 엉뚱한 곳에 보인다진짜 커서가 입력 위치에 없다claude update. VS Code는 workbench.experimental.modernUI 끄기
문장 중간에서 조합하면 뒤 글자가 안 보인다터미널의 겹쳐 그리기와 TUI 다시 그리기의 충돌 (열린 이슈)조합이 끝나면 돌아온다. 긴 수정은 Ctrl+G 외부 편집기
모바일에서 글자가 사라진다② 지우고 다시 쓰기를 예전 버전이 잘못 읽음서버의 Claude Code를 최신으로
ㅇㅏㄴㄴㅕㅇ처럼 풀린다③ 클라이언트가 조합하지 않음클라이언트 또는 키보드 설정을 바꾸기

모바일에서 가장 덜 깨지는 방법: 조합은 폰에서 끝내고, 완성된 글자만 보낸다

여기까지 보면 원칙은 하나입니다. TUI가 조합 과정을 볼 일이 없게 만들면 깨질 곳이 줄어듭니다.

SSH Term은 이 원칙대로 만들었습니다.

  • 터미널 화면에서 바로 칠 때: 조합 중인 글자는 앱이 커서 위치에 직접 그리고, 서버에는 조합이 끝난 글자만 보냅니다 (①). 지우고 다시 쓰기(②)를 보내지 않습니다
  • 한글 입력 모드: 안드로이드의 평범한 입력창에 문장을 끝까지 쓰고, 고치고, Enter로 한 번에 보냅니다. 키보드의 자동 완성이나 음성 입력도 그대로 쓸 수 있습니다
  • 여러 줄 지시: 입력 모드에서 줄을 바꿔 쓴 지시는 브래킷 붙여넣기(bracketed paste) 로 보냅니다. 붙여넣기로 받기 때문에 줄바꿈마다 전송되지 않고, 마지막 Enter만 따로 보냅니다
  • 외장 키보드: Ctrl+E로 입력 모드를 켜고 끕니다

Claude Code에 긴 지시를 한국어로 쓰는 일이 많다면, 입력 모드에서 다 쓰고 한 번에 보내는 쪽을 권합니다.

그리고 한 줄만 덧붙이면, SSH Term은 연결 설정에서 「호스트에서 셸 유지」를 켜면 셸을 호스트에 남겨 두기 때문에 Mosh 없이도 끊기지 않습니다. 지하철 터널에서 연결이 끊겨도 에이전트는 호스트에서 계속 돌고, 다시 붙으면 놓친 출력까지 이어서 보여 줍니다.

그래도 Mosh가 꼭 필요한 환경이라면 댓글로 알려 주세요. 다음에 무엇을 만들지 정할 때 참고합니다.


다운로드

구독 없이 1회 구매입니다.


마무리

한글이 깨질 때 "Claude Code가 한글을 못 한다"로 뭉뚱그리면 고칠 곳을 못 찾습니다. 조합은 누가 하고, 무슨 바이트가 오가는지를 나눠 보면 대부분은 버전 업데이트나 설정 하나로 끝납니다.

keylog.py로 찍어 본 결과가 위 표 어디에도 안 맞는다면, 댓글로 결과를 붙여 주세요. 같이 보겠습니다.

참고

0개의 댓글