Ben'space

Claude Code 한국어 답변의 번역투, skill로 깎아내기

· dev-toolsai

Claude Code를 한국어로 쓰다 보면 자꾸 어색한 표현을 씁니다 “행동 규칙이 코드 작성 전체를 지배하므로”, “정합성이 높다”, “~에 의해 ~된다” — 한국어 화자가 일상에서 거의 쓰지 않는 영어 직역체입니다.

CLAUDE.md에 “자연스러운 한국어로 써” 같은 한 줄을 넣어도 안 고쳐지길래 아는 척 하면서 처음에는 저희 어휘력이 부족한가? 생각했습니다. 하지만 결국 지속적으로 제가 못 알아듣는 말을 Claude 가 하는게 반복이 되었고 좀 더 본질적인 해결책을 찾아보기 시작했습니다.

원인 분석

LLM이 한국어를 어색하게 만드는 원인은 두 가지가 알려져 있습니다.

1. 내부 reasoning이 영어로 진행

arXiv 2502.15603 연구는 다국어 LLM이 입력·출력 언어와 무관하게 의미 처리 단계에서 영어에 가까운 표현 공간을 거친 뒤 타깃 언어로 번역하는 구조라는 점을 보여줍니다. 한국어 출력에 영어가 배어있는 이유입니다.

2. 학습 데이터 자체에 번역이 포함

arXiv 2503.04369 (Lost in Literalism) 연구는 영-중 SFT 학습 데이터의 40.4%가 이미 번역투라는 점을 측정했습니다. GPT-4 번역 출력의 43%도 번역투로 분류됐어요. 모델이 어색한 한국어를 쓰는 게 모델 입장에서는 자연스러운 표현이라는 거죠.

같은 논문이 흥미로운 해결책을 제시합니다. “초안 → 별도 prompt로 자연스럽게 다시 써” 단계만 추가하면 GPT-4 기준 번역투 43%가 25% 수준으로 떨어집니다. 단순히 “자연스럽게 써”라는 style 지시만으로는 부족하고, 두 번째 pass를 분리하는 것 자체가 효과의 핵심이라는 겁니다.

시도 1: CLAUDE.md에 인라인 치환 표

처음엔 CLAUDE.md에 직접 치환 표를 넣었습니다.

## 말투
| ❌ 번역투 | ✅ 자연 한국어 |
| ----------------------------- | ------------------ |
| ~을 지배한다 (govern) | ~에 큰 영향을 준다 |
| ~에 의해 ~된다 | ~이 ~한다 (능동) |
| 정합성이 높다 (추상명사 주어) | 잘 맞는다 |
| ~을 보장한다 (ensure) | 꼭 ~하게 한다 |
...

확실히 효과는 있었어요. 표가 항상 컨텍스트에 있으니까 매 답변에서 자동 적용됐습니다. 그런데 두 가지 문제가 보였습니다.

첫째, 길이. 표를 늘리다 보니 CLAUDE.md가 빠르게 비대해졌습니다. Anthropic 공식 가이드는 200줄 이하를 권장하고, 커뮤니티에서 보는 실용 권장은 80-120줄 정도입니다. CLAUDE.md는 매 세션마다 컨텍스트에 통째로 로드되니까 길이가 곧 비용이고, 너무 길어지면 모델이 instruction을 잘 안 따른다는 보고도 있습니다. (참고로 MEMORY.md는 200줄 hard cap이 있어서 그 이상은 silently 잘리고요. CLAUDE.md는 byte 단위 64 KiB cap만 있지만 권장은 200줄입니다.)

둘째, 논문의 2-pass 효과를 못 살림. 인라인 표는 1-pass 라서 모델이 답변을 한 번에 쓰면서 표를 참고하는 거죠. 논문이 강조한 “초안과 polish를 별도 단계로 쪼개는 효과”는 나오지 않습니다.

시도 2: skill로 분리 + 2-pass 강제

그래서 치환 표 자체를 별도 skill로 분리했습니다 (github.com/urunimi/skills). ~/.claude/skills/korean-polish/SKILL.md.

skill 안에는 3단계 절차를 명시했어요.

  1. Step 1 — 초안: 사용자 질문에 대한 답을 일단 그대로 쓴다. 직역체가 새어 나와도 OK.
  2. Step 2 — Critique: 초안을 다시 읽으며 치환 표·검수 휴리스틱으로 번역투 패턴을 찾는다.
  3. Step 3 — 최종: critique에서 잡힌 곳을 고쳐 다시 쓴다.

CLAUDE.md는 한 줄로 압축됐습니다.

## 말투
- 기본 존댓말 (자연스러운 한국어).
- 한국어로 답변할 때 항상 `korean-polish` skill 호출 — 초안 → critique → 최종 2-pass로 번역투 제거.

skill description에 “사용자가 한국어로 질문하거나 한국어 응답을 명시적으로 요구하면 항상 호출” 이라고 하면 Claude Code의 skill 자동 매칭이 잡아줍니다. CLAUDE.md는 한 줄만 차지하고, 치환 표 18행 + 검수 휴리스틱 5개는 skill 호출 시점에만 로드돼요.

치환 표 일부를 옮겨와 보면 이런 식입니다.

❌ 번역투 (영어 원형)✅ 자연 한국어
~을 지배한다 (govern, dominate)~에 큰 영향을 준다
~에 의해 ~된다 (be … by)~이 ~한다 (능동)
정합성이 높다 (추상명사 주어)잘 맞는다
~을 보장한다 (ensure)꼭 ~하게 한다
~을 촉진한다 (facilitate)~을 쉽게 만든다
~함으로써 (by V-ing)~해서 / ~하면
~의 활용 (the use of)~을 쓰는 것
이는 ~을 의미한다 (this means)즉 ~이다

검수 휴리스틱은 패턴 자체를 잡는 룰입니다.

  • 추상명사가 주어인 문장 (X의 활용은 ..., Y의 존재는 ...)
  • 영어 단어가 1:1로 매핑돼 나온 곳 (govern → 지배, ensure → 보장, facilitate → 촉진)
  • 수동형 연속 (~된다, ~받는다가 두 번 이상 이어짐)
  • 명사화 + 가벼운 동사 (~의 수행, ~의 처리)
  • “이는 ~이다” 패턴 (“This is …” 직역)

효과 비교

같은 질문에 대한 답을 두 단계로 나란히 놓고 보면 차이가 또렷합니다.

초안 (1-pass)

치환 표의 활용은 답변 작성 시 자연스러운 패턴 회피를 가능하게 합니다. 표가 컨텍스트에 존재함으로써 추상명사가 주어로 사용되거나 영어 직역이 그대로 노출되는 함정으로부터 보호받을 수 있다는 점이 큰 장점입니다.

Critique

  • 활용은 ... 가능하게 합니다 — 추상명사 주어 + “use of X makes Y possible” 직역
  • 존재함으로써 — by-construction 직역
  • 함정으로부터 보호받을 수 있다 — “be protected from” 수동 직역

최종

표를 보고 답변 쓸 때 패턴을 자연스럽게 피하게 돼요. 추상명사로 문장 시작하거나 영어 직역을 그대로 쓰는 함정에 덜 빠지죠.

같은 의미인데 읽는 느낌이 완전히 다릅니다. 초안은 “AI가 쓴 글” 티가 나고, 최종은 사람이 쓴 글에 가깝습니다.

모든 답변에 2-pass를 거칠 필요는 없다

매 답변마다 초안 → critique → 최종을 거치면 비용도, 답변 길이도 부담입니다. 짧고 단순한 답변에서는 critique가 오히려 잡음이 돼요. 그래서 skill 안에 분기 규칙을 넣어 뒀습니다.

  • 1-pass로 끝내는 경우: 답변이 1-3 문장이거나, 단순 사실 확인, 짧은 안내일 때. 코드·표·고유명사가 답변의 대부분일 때. 사용자 질문이 “X 있어?”, “Z 해줘” 같은 단답형일 때.
  • 2-pass로 가는 경우: 답변이 1문단 이상이거나, 추상적 설명·의견·트레이드오프 분석. 사용자 질문이 “왜”, “어떻게”, “설명해줘” 같은 explanatory 질문일 때.

애매하면 2-pass로 갑니다. 비용보다 자연스러움이 우선이고, 직역체가 가장 자주 새는 곳이 추상적 설명이거든요. 짧은 답변에서 critique를 거쳐도 잡을 게 별로 없습니다.

정리

  • “자연스러운 한국어로 써” 한 줄로는 안 고쳐집니다. LLM의 영어 reasoning 공간과 학습 데이터 자체의 번역투가 원인이에요.
  • 치환 표를 CLAUDE.md에 넣는 것도 좋지만 파일이 비대해집니다.
  • skill로 분리하고 “초안 → critique → 최종” 3단계를 명시하면 CLAUDE.md는 한 줄, 표는 호출 시점에만 로드, 2-pass 효과도 살아납니다.
  • self-critique를 별도 단계로 쪼개면 정확도가 올라간다는 게 핵심입니다.

참고로 skill 호출이 자동으로 안 잡히면 UserPromptSubmit hook으로 한국어 입력 감지 시 reminder를 주입하는 방법도 있습니다. 저는 이전보다 훨씬 나아져서 이대로 좀더 사용을 해보고 있는데 자동 매칭이 잘 되면 그때 hook을 붙일 계획입니다.

설치

Claude Code에서:

/plugin marketplace add urunimi/skills
/plugin install korean-polish@urunimi-skills
On this page