27편에서 로봇은 말을 다 알아들었고, 병목은 말귀였습니다. 그런데 그 말귀를 맡은 언어 모델이 속으로 무엇을 했는지는 한 번도 들여다보지 않았습니다. 문장을 넣으면 숫자 세 개가 나오는 상자로만 썼으니까요. 이번 노트는 그 상자를 열어 본 기록입니다. 모델 일곱 개를 같은 문장으로 시험했고, 생각을 시키면 무엇이 달라지는지, 그리고 그 생각을 GPU가 아닌 곳에서 시키면 얼마나 기다려야 하는지 쟀습니다.
27편에서 열지 않은 상자
27편의 구조를 다시 정리하면 이렇습니다. 사람이 “왼쪽으로 돌면서 천천히 걸어”라고 말하면, 컴퓨터 안에서 돌아가는 언어 모델이 이 문장을 숫자 세 개로 바꿉니다. 앞으로 가는 속도 vx, 옆으로 가는 속도 vy, 제자리에서 도는 속도 wz입니다. G1의 보행 정책은 이 세 숫자만 받아서 걷습니다. 보류해 둔 문장 30개 중 27개를 qwen3 14B가 맞혔고, 맞힌 명령은 로봇이 30번 모두 따라 걸었습니다.
그때 기록한 것은 출력 숫자, 맞았는지 틀렸는지, 문장당 걸린 시간 세 가지뿐이었습니다. 왜 그렇게 해석했는지는 몰랐습니다. 게다가 그때는 모델의 “생각 단계”를 꺼 둔 채로 썼습니다. 그래서 이번에는 세 가지를 묻기로 했습니다.
- 출력 형식을 강제하는 도구는 정확도에 얼마나 기여했을까요?
- 생각을 시키면 정확도가 오를까요? 오른다면 시간은 얼마나 더 들까요?
- 모델이 틀릴 때, 생각 속 어디에서 말귀가 끊길까요?
여기에 질문 하나가 더 붙었습니다. 실물 로봇에 이 기능을 넣는다면 언어 모델을 어디에서 돌려야 할까요? 지금은 RTX 4060 Ti GPU에서 돌리지만, 앞으로 할 실험이 이 GPU를 통째로 쓸 예정이라 언어 모델을 CPU로 옮길 수 있는지도 알아야 했습니다.
용어 세 개
생각 단계(thinking) 는 모델이 답을 내기 전에 혼잣말로 문제를 풀어 보는 과정입니다. “빨리 걸으면서 오른쪽으로 크게 틀어”를 받으면 “빨리는 0.9, 오른쪽 회전은 음수, 크게는 0.5″처럼 따져 본 뒤에 답을 적습니다. 요즘 모델 상당수가 이 기능을 갖고 있고, 켜고 끌 수 있는 모델도 있습니다. 이 혼잣말은 사람에게 보여 줄 답과 따로 돌려받을 수 있어서, 이번 실험에서는 문장마다 전부 저장했습니다.
구조화 출력 은 모델이 정해진 형식으로만 답하게 막는 도구입니다. 이번에 쓴 ollama라는 실행 도구에 “vx, vy, wz 세 숫자가 든 JSON만 허용”이라는 규칙(스키마)을 넘기면, 모델은 그 형식에서 벗어난 글자를 아예 고를 수 없게 됩니다. 27편은 이 방식이었습니다. 끄면 모델이 자유롭게 쓴 글에서 첫 번째 JSON을 찾아 꺼냅니다.
토큰 은 모델이 글을 읽고 쓰는 단위입니다. 대략 단어 조각 하나라고 보면 됩니다. 모델이 답을 쓰는 속도는 “초당 몇 토큰”으로 재고, 생각을 길게 할수록 토큰을 많이 써서 시간이 늘어납니다.
어려운 문장 48개를 새로 썼습니다
처음에는 27편의 보류 문장 30개로 비교하려 했습니다. 그런데 qwen3 14B가 27개, gpt-oss 20B가 28개를 맞혀서 다들 천장에 붙어 있었습니다. 이 상태로는 어떤 조건을 바꿔도 차이가 보이지 않습니다. 그래서 더 어려운 문장 48개를 새로 썼습니다. 여섯 묶음에 8개씩입니다.
| 묶음 | 무엇을 시험하나 | 예 |
|---|---|---|
| A 복합 | 성분 둘 이상을 한 문장에 | 최대 속도로 달리면서 왼쪽으로 살짝 틀어 |
| B 부정·정정 | 말을 뒤집거나 고쳐 말하기 | 오른쪽 말고 왼쪽, 아니 그냥 오른쪽으로 돌아 |
| C 단위·숫자 | 단위 환산과 범위 밖 숫자 | 초속 1미터로 가면서 오른쪽으로 초당 10도 돌아 |
| D 간접·관용 | 숫자가 없는 말투 | 서두를 것 없어, 산책하듯이 |
| E 옆걸음·회전 혼동 | 옆으로 갈지 돌지 갈리는 말 | 오른쪽을 봐 |
| F 영어·오타 | 섞인 말과 틀린 철자 | 천천히 strafe right, 오룬쪽으로 돌아 |
정답은 성분마다 허용 범위로 적었습니다. 예를 들어 “천천히”는 vx 0.15~0.45입니다. 세 성분이 모두 범위 안이면 맞힌 것으로 셉니다. “오른쪽으로 가”처럼 사람도 옆걸음인지 회전인지 갈리는 문장은 범위 하나로 정답을 적을 수 없어서 뺐습니다.
규칙도 하나 정했습니다. 이 48문장은 결과를 보기 전에 저장소에 고정했고, 결과를 본 뒤에는 고치지 않습니다. 결과를 보고 정답표를 고치기 시작하면 시험이 아니라 맞춤이 되기 때문입니다. 뒤에서 보겠지만 이 규칙 때문에 손대고 싶은 문장이 실제로 생겼습니다.
모델 일곱 개와 조건
전부 이 PC에서 ollama로 돌린 공개 모델입니다. 유료 API 모델은 이번에 넣지 않았습니다.
| 모델 | 크기 | 생각 단계 |
|---|---|---|
| qwen3 1.7B, 4B, 8B, 14B | 밀집 | 켜고 끌 수 있음 |
| gemma4 12B | 밀집 | 켜고 끌 수 있음 |
| exaone3.5 7.8B | 밀집, 한국어 특화 | 없음 |
| gpt-oss 20B | 전문가 혼합 | 끌 수 없고 양만 조절(low, medium, high) |
밀집 모델은 글자 하나를 쓸 때마다 모든 파라미터를 씁니다. 전문가 혼합(MoE) 모델은 파라미터를 여러 “전문가” 묶음으로 나눠 두고, 글자마다 그중 일부만 씁니다. gpt-oss 20B는 파라미터가 200억 개지만 한 번에 쓰는 것은 36억 개쯤입니다. 이 차이는 나중에 CPU에서 중요해집니다.
조건은 출력 방식(스키마 강제, 자유 출력)과 생각(끔, 켬, 그리고 gpt-oss의 세 단계)을 엮었습니다. 문장 세트는 어려운 48개, 27편의 보류 30개와 조정 30개까지 세 개를 전부 돌렸습니다. 결과 파일은 31개가 나왔습니다. 온도(무작위성)는 0이라 같은 장비에서 다시 돌리면 같은 답이 나오므로 반복은 하지 않았습니다. 아래 숫자는 특별히 적지 않으면 어려운 48문장 기준입니다. 규칙 기반 대조군(27편의 키워드·숫자 규칙)은 25점입니다.
첫 번째 답: 형식 강제는 점수를 올리지 않았습니다
스키마를 켠 것과 끈 것을 모델별로 비교했더니 점수가 같거나 1점 차이였습니다. 자유 출력에서 JSON을 못 찾은 경우도 모든 조건을 합쳐 한 번뿐이었습니다. 구조화 출력은 “형식을 맞춰 주는” 도구일 뿐, 이 과제에서 정확도를 올려 주지는 않았습니다.
예외가 하나 있었는데, 이게 이번 실험에서 가장 먼저 눈에 띈 장면입니다. qwen3 4B는 스키마를 켜면 20점, 끄면 40점이었습니다. 지연은 0.5초에서 14초로 뛰었습니다. 생각 단계를 꺼 두었는데도요. 응답을 열어 보니 이랬습니다.
Okay, let's tackle this problem. So, the user says, "빨리 걸으면서 오른쪽으로 크게 틀어".
I need to convert this into the three control values: vx, vy, wz.
...
So the answer should be {"vx": 0.9, "vy": 0, "wz": -0.5}
</think>
{"vx": 0.9, "vy": 0, "wz": -0.5}
생각을 끄라고 했지만, 형식을 강제하지 않자 답 칸에서 영어로 평균 3,700자를 추론한 뒤 답을 적었습니다. 스키마를 켜면 첫 글자부터 {만 쓸 수 있으니 이 틈이 막힙니다. 그러니까 4B에게 스키마는 정확도를 올리는 도구가 아니라 생각할 틈을 막는 도구였습니다. 같은 모델이 생각 단계를 정식으로 켜고 스키마를 쓴 조건에서도 40점이 나와서, 20점이 오른 이유는 형식이 아니라 생각이었다는 걸 확인할 수 있었습니다.
두 번째 답: 생각은 점수를 올립니다, 모델에 따라

| 모델 | 생각 끔 | 생각 켬 | 문장당 시간 (끔 → 켬) |
|---|---|---|---|
| qwen3 1.7B | 9 | 12 | 0.3초 → 4.9초 |
| qwen3 4B | 20 | 40 | 0.5초 → 14초 |
| qwen3 8B | 33 | 43 | 0.6초 → 12초 |
| qwen3 14B | 35 | 46 | 0.8초 → 14초 |
| gemma4 12B | 44 | 38 | 1.5초 → 27초 |
| gpt-oss 20B | 38 (low) | 45 (medium), 45 (high) | 1.6초 → 4.7초, 13초 |
| exaone3.5 7.8B | 25 | 기능 없음 | 0.6초 |
qwen3는 4B 이상에서 생각을 켜면 10~20점이 오르고, 시간은 17~28배 늘었습니다. 가장 높은 점수는 생각을 켠 qwen3 14B의 46점이었습니다. gpt-oss는 medium과 high가 같은 45점이라, high는 시간만 세 배 가까이 더 썼습니다. 이 과제에 필요한 생각의 양에는 상한이 있다는 뜻입니다.
생각이 되레 해가 된 모델도 있었습니다. gemma4는 생각을 끄고도 44점으로 이번 실험에서 생각 없이 가장 잘했는데, 생각을 켜면 38점으로 떨어지고 문장당 27초가 걸렸습니다. 이 이야기는 바로 다음 절에서 이어집니다.
크기 쪽에서는 두 가지가 보였습니다. 1.7B는 생각을 켜도 12점이었고, 생각이 4,096토큰 상한에 걸려 끝나지 않은 문장도 나왔습니다. 너무 작은 모델은 생각을 끝맺지 못합니다. 그리고 한국어 특화 모델인 exaone 7.8B는 25점으로 규칙 대조군과 같았습니다. 한국어를 잘 아는 것과, 한국어 문장을 정해진 숫자 체계로 옮기는 것은 다른 능력이었습니다.

정확도와 시간을 한 그림에 놓으면 고를 수 있는 선택지가 보입니다. 2초 안에 40점을 넘은 것은 생각을 끈 gemma4 하나였고, 45점 이상은 전부 5초 넘게 생각한 결과였습니다.
세 번째 답: 생각과 답이 따로 노는 모델
gemma4가 생각을 켜고 틀린 문장의 생각을 읽다가 이상한 걸 발견했습니다. “초속 2미터로 뛰어”의 생각은 이렇게 끝납니다.
vx: The user wants a speed of 2 m/s. However, the constraint for vx is 0.0 to 1.2.
Since 2 > 1.2, I must cap it at the maximum allowed value (1.2).
...
{"vx": 1.2, "vy": 0, "wz": 0}
생각 끝에 정답을 적어 놓고, 실제로 내보낸 답은 {"vx": 0, "vy": 0, "wz": 0}이었습니다. “몸을 왼쪽으로 돌려”에서는 생각에 wz 0.4라고 적고 답으로 -0.4를 냈습니다. 부호가 뒤집혔습니다.
그래서 모든 “생각 켬” 결과에서, 생각 끝에 적힌 JSON과 실제 답이 다른 횟수를 셌습니다.
| 모델 | 생각에 답이 적힌 문장 | 답과 다름 | 생각은 맞고 답은 틀림 |
|---|---|---|---|
| gemma4 12B | 47 / 48 | 14 | 7 |
| qwen3 4B | 47 / 48 | 0 | 0 |
| gpt-oss 20B high | 48 / 48 | 0 | 0 |
| qwen3 8B, 14B | 12, 6 / 48 | 1, 1 | 0, 0 |
gemma4만 그랬습니다. 생각의 답을 그대로 썼다면 38점이 아니라 45점이었습니다. 생각 자체는 잘했는데, 생각을 마친 뒤 스키마에 맞춰 답을 쓰는 단계에서 그 결론을 이어받지 못한 겁니다.
원인이 스키마인지 확인하려고, gemma4의 생각을 켠 채 스키마만 빼고 48문장을 다시 돌렸습니다. 44점이 나왔습니다. 생각과 답이 어긋난 문장은 14개에서 1개로 줄었고, 남은 1개는 생각이 4,096토큰 상한에 걸려 답을 못 쓴 경우였습니다. 형식을 강제하는 장치가 gemma4의 생각과 답 사이를 끊고 있었던 겁니다. 다만 44점은 생각을 끈 점수와 같고 시간은 문장당 31초로 20배였으니, 이 과제에서 gemma4에게 생각은 득이 없었습니다.
그러니 “생각을 켰더니 점수가 떨어졌다”는 결과는 생각이 해롭다는 뜻이 아니었습니다. 생각과 답을 잇는 고리가 출력 형식 강제와 부딪혀 끊긴 것이었습니다. 첫 번째 답에서 스키마가 정확도에 기여하지 않는다고 했는데, 이 모델에서는 오히려 생각을 켠 정확도를 깎았습니다. 생각을 열어 보지 않았다면, 점수만 보고 “gemma4는 생각하면 나빠진다”고 잘못 결론 냈을 겁니다.
말귀는 어디서 끊기나

묶음별로 나눠 보면 생각을 켠 강한 조건들은 A부터 D까지 거의 다 맞힙니다. 마지막까지 남는 것은 E 옆걸음·회전 혼동입니다. GPU에서 돌린 21개 조건을 합쳐 가장 많이 틀린 문장은 이랬습니다.
| 문장 | 틀린 조건 | 정답표 |
|---|---|---|
| turn right slowly while walking | 21 / 21 | 천천히 걸으며 오른쪽으로 회전 |
| 오른쪽을 봐 | 16 / 21 | 제자리에서 오른쪽으로 회전 |
| 왼쪽을 향해 | 14 / 21 | 제자리에서 왼쪽으로 회전 |
| 오른쪽으로 방향만 바꿔, 가지는 말고 | 14 / 21 | 제자리에서 오른쪽으로 회전 |
| 앞으로 가면서 오른쪽으로 몸을 틀어 | 14 / 21 | 걸으며 오른쪽으로 회전 |
생각을 읽어 보면 모델마다 끊기는 방식이 달랐습니다.
- “오른쪽을 봐” 를 생각 끈 qwen3 14B는 vx·vy·wz 전부 0으로 답했습니다. 생각 켠 같은 모델은 “보는 건 고개나 상체를 돌리는 일인데, 주어진 숫자는 이동 명령이라 해당하는 동작이 없다”고 따진 뒤에 역시 0을 냈습니다. 틀렸다고 채점했지만, 솔직히 사람에게 물어도 갈릴 수 있는 해석입니다.
- “왼쪽을 향해” 를 gpt-oss medium은 “향해는 회전이 아니라 이동 방향”이라고 읽고 왼쪽 옆걸음으로 답했습니다. 반대로 생각 켠 qwen3 14B는 제자리 왼쪽 회전으로 맞혔습니다.
- “turn right slowly while walking” 은 21개 조건이 전부 틀렸습니다. 1.7B와 exaone을 뺀 모든 조건이 걸음은 보통 속도(vx 0.5), 회전은 “살짝”(wz -0.15)으로 답했습니다. slowly를 회전에 붙인 겁니다. 정답표는 slowly를 걸음에 붙였습니다. 영어 문법으로는 모델 쪽 해석이 더 자연스럽습니다. 시스템 지시문에 “살짝 0.15″라는 회전 예시가 있는 것도 한몫했을 겁니다.
앞에서 정한 규칙대로 이 문장들의 정답표는 고치지 않았습니다. 대신 이렇게 적어 둡니다. 어려운 세트의 마지막 몇 점은 모델의 말귀 문제와 정답표의 애매함이 섞여 있습니다. 46점과 48점 사이의 차이는 모델 탓만은 아닙니다. 남는 실수가 “사람도 헷갈릴 문장”으로 몰린다는 것 자체가, 이 과제에서 모델이 넘어야 할 다음 벽이 해석의 애매함이라는 신호이기도 합니다. 실제 로봇이라면 여기서 되묻게 만드는 쪽이 정답일 겁니다.
CPU로 옮기면
같은 모델과 설정을 이 PC의 CPU(Ryzen 5 5600X, 6코어, DDR4 32GB)로 돌렸습니다. ollama는 요청마다 GPU에 올릴 층 수를 정할 수 있어서, 0으로 주면 서버를 다시 켜지 않고도 그 요청만 CPU로 돕니다.

| 모델·설정 | 점수 (GPU / CPU) | 문장당 (GPU / CPU) | 배수 |
|---|---|---|---|
| qwen3 8B 생각 끔 | 33 / 32 | 0.6초 / 4.5초 | 7배 |
| qwen3 14B 생각 끔 | 35 / 36 | 0.8초 / 6.3초 | 8배 |
| gpt-oss 20B low | 38 / 39 | 1.6초 / 9.5초 | 6배 |
| gemma4 12B 생각 끔 | 44 / 45 | 1.5초 / 20초 | 14배 |
| gpt-oss 20B medium | 45 / 44 | 4.7초 / 35초 | 7배 |
| qwen3 14B 생각 켬 | 46 / 44 | 14초 / 121초 | 8배 |
언어 모델이 글자 하나를 쓸 때마다 모델 전체를 메모리에서 한 번 읽어야 해서, 쓰는 속도는 대략 메모리 대역폭을 모델 크기로 나눈 값이 됩니다. GPU 메모리는 초당 약 288GB, 이 PC의 메인 메모리는 약 40GB를 읽으니 7~8배 차이가 납니다. 실측과 맞습니다.
예외 둘이 이 계산에서 나옵니다.
- gpt-oss는 CPU에서 쓰는 속도가 빠릅니다. 전문가 혼합이라 글자마다 읽는 양이 작아서, CPU에서 초당 8.8토큰으로 qwen3 14B(3.8토큰)의 두 배 이상이었습니다. 그래서 CPU에서 가장 균형이 좋은 조합은 gpt-oss low였습니다. 10초 안에 39점입니다.
- gemma4는 CPU에서 14배 느려집니다. 답을 쓰는 속도보다, 지시문을 읽는 속도가 초당 26토큰까지 떨어진 탓입니다. GPU에서 가장 효율이 좋던 모델이 CPU에서도 좋다는 보장은 없었습니다.
장비가 바뀌면 점수도 1~2점 흔들렸습니다. 온도가 0이어도 장비마다 계산 순서가 달라 아주 작은 수치 차이가 생기고, 그게 “오른쪽” 부호 하나를 뒤집기도 합니다. 그래서 장비 사이의 1~2점 차이는 실력 차이로 읽지 않았습니다.
측정 중에 도구의 함정도 하나 밟았습니다. ollama가 알려 주는 “생성한 토큰 수”가, 출력 형식을 강제한 조건에서는 생각 토큰을 빼고 셉니다. 처음에는 gpt-oss가 문장당 18토큰만 쓴다고 나와서 지연 9.7초가 설명되지 않았습니다. 시간으로 거꾸로 셈하면 77토큰이었습니다. 그래서 생각의 양은 저장한 생각 원문의 글자 수로 비교했습니다. 측정 도구도 검증 대상이라는 R02의 교훈이 여기서도 그대로였습니다.
그래서 로봇에는 무엇을 달아야 하나
보행 정책은 1초에 50번씩 돌아야 하지만, 언어 모델은 사람이 말할 때 한 번만 돌면 됩니다. 허용되는 지연이 밀리초가 아니라 초 단위라서, 둘을 다른 장비에 놓아도 됩니다. 그러면 언어 모델을 어디에 둘지는 “얼마나 정확해야 하고, 얼마나 기다릴 수 있는가”로 정해집니다. 이번 숫자로 정리하면 이렇습니다.
| 쓰임 | 필요한 것 | 이번 결과로 고르면 |
|---|---|---|
| 실시간 조종 (1~2초 안에 반응) | 생각 없이 정확한 모델 + GPU | gemma4 12B 생각 끔, GPU 1.5초, 44점 |
| 느려도 되는 지시 (10초 안팎) | CPU나 작은 서버 | gpt-oss 20B low, CPU 9.5초, 39점 |
| 정확도 최우선 (수십 초 허용) | 생각하는 모델 | qwen3 14B 생각 켬, GPU 14초, 46점 |
생각이 필요 없을 만큼 쉬운 명령이 대부분이라면 작은 장비로도 충분합니다. 어려운 명령까지 맞혀야 한다면 생각이 필요하고, 그 생각을 실시간으로 하려면 GPU급 장비가 필요합니다. 실물 로봇의 하드웨어가 바뀐다면, 바뀌는 쪽은 걷는 쪽이 아니라 말을 알아듣는 쪽입니다.
한계
- 문장 세트는 직접 쓴 48개이고, 정답표에는 앞에서 본 것처럼 애매한 문장이 섞여 있습니다. 세트를 고정했으니 점수끼리는 공정하게 비교되지만, 점수의 절대값을 “말귀 능력”으로 읽으면 안 됩니다.
- 온도 0으로 한 번씩만 돌렸습니다. 같은 장비에서는 결정적이지만, 문장을 조금 바꿔 말했을 때의 흔들림은 재지 않았습니다.
- 시스템 지시문은 27편 것 하나만 썼습니다. 지시문을 고치면 E 묶음 같은 혼동은 줄어들 수 있습니다. 다만 그건 모델이 아니라 지시문을 시험하는 일이라 이번 범위에서 뺐습니다.
- 유료 API 모델은 비교하지 않았습니다. 이번 과제는 문장당 토큰이 적어 비용은 작겠지만, 이 시리즈는 오프라인 환경을 기준으로 했습니다.
- CPU 측정은 이 PC 한 대입니다. ARM 서버처럼 구조가 다른 장비는 메모리 대역폭에 따라 결과가 크게 다를 수 있습니다.
종합
- 출력 형식을 강제하는 도구는 정확도를 올리지 않았습니다. 대신 qwen3 4B에게서는 생각할 틈을 막아 20점을 깎았습니다.
- 생각은 점수를 올립니다. qwen3 4B 이상은 10~20점이 올랐고, 시간은 17~28배 늘었습니다. gpt-oss는 medium에서 이미 상한에 닿았습니다.
- gemma4는 생각을 켜면 점수가 떨어졌습니다. 생각을 읽어 보니 생각은 맞았는데 답이 그 결론을 이어받지 못한 경우가 7번 있었습니다. 스키마를 빼자 어긋남이 사라졌습니다. 형식 강제가 생각과 답 사이를 끊고 있었습니다.
- 마지막까지 남는 실수는 옆걸음과 회전을 가르는 문장에 몰렸습니다. 그중 일부는 사람에게도 애매한 말입니다.
- CPU로 옮기면 7~8배 느려집니다. 전문가 혼합 모델은 덜 느려지고, gemma4는 14배 느려졌습니다. 생각까지 시키면 문장당 30초에서 2분이라 실시간 명령으로는 쓸 수 없습니다.
27편의 결론은 “병목은 말귀”였습니다. 이번에 그 말귀를 열어 보니, 말귀는 생각으로 늘었고 생각할 시간은 장비가 정했습니다. 어떤 장비에 얼마만큼의 생각을 맡길지는, 로봇이 얼마나 기다려 줄 수 있는지에 달려 있습니다.
이 시리즈의 전체 글 목록 → 시리즈 목차