Claude Code가 내뱉는 의미 없는 헛소리들
Semantic nonsense from Claude Code
핵심 요약
Claude가 벤치마크 점수를 위해 의미론적으로 밀도 높은 헛소리를 남발하며, 코딩 작업 시 가독성과 명확성을 심각하게 저해한다는 분석입니다.
- 의미론적 헛소리 — 모델이 지능적인 척하기 위해 밀도 높은 문장을 생성하지만 실제로는 논리적 결함이 많음
- 코딩 가독성 저하 — 모호한 전문 용어와 압축된 표현으로 인해 코드 구현 의도를 파악하기 어려움
- 모델의 근본적 한계 — 벤치마크 점수를 높이기 위해 모델을 특정 방향으로 유도하는 학습 방식의 부작용
- 대안적 해결책 — Claude의 출력을 다른 모델(Grok 등)로 전달해 명확하게 다시 작성하게 하는 방식 도입
지난 두 달 동안, Claude가 내놓는 결과물을 도저히 읽을 수가 없다는 불만이 점점 늘고 있어. 사람들이 잘 모르는 것 같은데, 진짜 문제는 단순히 말이 길다거나, 어려운 단어를 쓴다거나, 내용을 너무 압축하려 한다거나, 전문 용어를 남발해서가 아니야. 내 생각에 진짜 문제는 Claude가 내놓는 글의 70%가 그냥 개소리라는 거야. 특히 컨텍스트가 200k를 넘어가면 더 심해져.
사람들은 Opus나 Fable이 일부러 말을 길게 늘어뜨린다는 걸 잘 몰라. 이 모델들은 진짜 지능이 있는 게 아니라, 의미론적으로 밀도가 높은 공간으로 유도되게끔 해서 "똑똑한 척"을 하는 거야. 그래야 똑똑한 통찰이 나올 확률이 높아지거든. 학습 데이터상에서 똑똑한 통찰들은 보통 의미 밀도가 높은 텍스트에 들어있으니까. 벤치마크 점수를 잘 받으려면 연구소들은 모델이 의미 밀도가 높은 결과물을 내놓도록 유도해야 해. 그게 똑똑한 결과물일 확률이 가장 높으니까.
근데 사람들은 이 모델들이 근본적으로 인간처럼 사고하지 않는다는 걸 몰라. 그래서 결과물을 꼼꼼히 읽어보면 의미적으로 말이 안 되는 부분이 엄청 많아. LLM은 똑똑한(혹은 솔직히 말해 고상한) 말투나 글에서 자주 쓰이는 표현들을 가져다 쓰는데, 앞뒤 문맥이 그런 표현을 쓸 법한 상황이면 그냥 갖다 붙이는 거야. 그 표현의 의미가 앞선 문맥과 논리적으로 일치하는지는 전혀 고려하지 않아. 모델의 결과물이 논리적으로 맞아 보이는 건, 인간이 만든 데이터가 워낙 방대해서 모델이 그냥 인간 흉내만 내도 대부분의 경우 논리적으로 보이기 때문이야.

"전쟁의 한 해" 속에 "둥지를 튼다"
뭐, 이런 예시들은 그냥 비유나 은유일 뿐이고 논리적 내용이 중요한 글은 아니니까 별 상관없다고 생각할 수도 있겠지. 그래, 그럴 수 있어.
문제는 코딩이야.
Claude한테 네 코드베이스가 따라야 할 아키텍처를 설명할 때, 이 녀석이 똑같은 사이비 지식 수준의 헛소리를 늘어놓으면 Claude가 정확히 뭘 한 건지, 내가 뭘 원하는 건지 파악하기가 너무 어려워져. 내가 최근에 겪은 예시를 하나 보여줄게.
단계들을 정직하게 다시 자르기(The phases re-cut honestly).
Claude가 구현 단계를 어떻게 다르게 나눌지 설명하면서 이 문구를 썼어. 근데 이 문구는 문맥 안에서도 전혀 말이 안 돼(글 끝에서 문맥을 확인할 수 있어). "다시 자르기(re-cut)"가 무슨 뜻이야? "정직하게(honestly)"는 또 무슨 의미고? 도대체 뭘 어떻게 "정직하게" 다시 자른다는 거야? 알고 보니 여기서 "정직하게"는 "커밋이 실제로 컴파일되게 하겠다"는 뜻이었어. 근데 "정직하게"라는 말에서 그걸 어떻게 유추해? 정상적인 사람이라면 "B 단계 커밋이 컴파일이 안 되니까 C 단계를 B 단계에 합치겠다"고 말할 거야. Claude는 나중에 두 단계를 합치겠다고 직접 말까지 했으면서, 저런 식으로 써서 컨텍스트를 아끼는 것도 아니야.
[...] 차단기에 의해 거부된 레인 프레스는 노 스트라이크 스킵으로 유지된다
Claude는 의미가 빽빽하게 들어찬 절을 만드는 걸 좋아하는데, 문구를 너무 압축해버려서 한 문장이 여러 가지 의미로 해석될 여지를 남겨둠. 의미적 모호함은 Claude랑 작업하기 힘든 또 다른 큰 이유임. 여기서 "a lane press"라는 말도 여러 의미로 해석될 수 있는데, 내 코드베이스에서 "lane"(난 자식 작업(child operation)을 지칭할 때 이 단어를 쓴 적이 없는데, 그냥 지 맘대로 이 단어를 씀)은 CLI를 통해 버튼을 누르는 작업일 수도 있고, 그냥 아무 키나 누르는 걸 수도 있거든. Claude는 대체 무슨 종류의 'press'를 말하는 건지 명확하게 설명 안 함. "refused by a blocker"가 무슨 뜻인지도 안 알려줌. 내 코드베이스에서 작업이 거부되는 경로는 한두 개가 아님. 작업이 조건(predicate)을 충족하지 못해서 시작부터 막히는 걸 수도 있고, 누르려고 시도하다가 OS랑 연결된 저수준 어댑터에서 에러가 터진 걸 수도 있음. 아니면 모든 작업에 즉시 중단을 명령하고 새로운 하위 작업 생성을 거부하는 강제 취소(forced cancellation) 때문에 가로막힌 걸 수도 있지. 난 "blocker"라는 단어를 코드에 쓴 적도 없는데 대체 누가 "blocker"라는 건지, 뭐가 거부됐다는 건지 도통 알 수가 없음(이미 코드에 "predicate_check"나 "cancellationtoken" 같이 거부 유형별로 정의를 다 해놨는데도 이러니까 진짜 짜증 남). 그냥 "조건 체크 실패함"이라고 말해주면 될 걸, 굳이 지 맘대로 있지도 않은 전문 용어를 지어내서 불필요한 모호함만 만들고 있음.

