문장을 의미 단위로 나누기 — 그리고 두 번의 잘못된 길
EasyDictation을 만드는 팀입니다. 영어 학습자를 위한 받아쓰기 연습을 만들며, 스크립트 생성과 구 나누기, 번역 파이프라인을 직접 운영합니다.

모든 것은 의견 게시판의 글 하나에서 시작했습니다:

작은 수정처럼 들렸습니다. 조각을 짧게 만들고 내보내면 끝. 그런데 파고들수록 분명해졌습니다. 이건 애초에 길이의 문제가 아니었습니다. 어디를 자르느냐의 문제였습니다. 제대로 이름을 붙이면, 영어 문장을 의미 단위로 어떻게 나누느냐입니다. 그리고 그것을 푼 순간, 훨씬 어려운 문제가 태어났습니다. 그 구들을 어떻게 번역해야 사람들에게 거짓을 가르치지 않을 수 있는가?
두 이야기를 다 적었습니다. 우리가 자신 있게 틀렸던 두 번까지요.
1부 — 짧게 자르기는 쉽고, 제대로 자르기는 어렵습니다
가장 빠른 방법은 기계적인 것입니다. 조각마다 다섯 단어, 또는 쉼표마다 자르기. 해 봤습니다. 이런 조각이 나옵니다:
"the big" / "red car that I" / "bought last week"
산수로는 완벽합니다. 듣기 연습으로는 쓸모가 없습니다. *"the big"*과 "red car" 사이에서 멈추는 사람은 없습니다. 그렇게 자른 조각은 실제 말에 존재하지 않는 리듬을 훈련시킵니다. 더 나쁜 건, 뜻이 없는 조각을 머리에 붙들고 있으라고 요구하는 점입니다. 단기 기억은 뜻 없는 것에 형편없기로 유명합니다.
그래서 질문을 다시 썼습니다. 절대로 자르면 안 되는 곳은 어디인가?
2부 — 손으로 쓴 분할 규칙: 왜 실패했는가
앉아서 영어가 단어를 묶는 방식을 바탕으로 "여기서는 절대 끊지 않는다" 규칙을 적었습니다. 이 안쪽은 끊지 않습니다:
- 한정사 + 명사 — the big red car
- 전치사 + 목적어 — in the garden, of a week
- 조동사 + 동사 — has been, did not answer
- 동사 + 불변화사 — give up, look after
- "to" + 동사 — to share
- 고유명사와 직함 — New York City, Dr. Jane Smith
- 숫자, 날짜, 금액, 단위
- 굳은 표현과 복합명사 — on the other hand, climate change
- 소유격 + 명사 — John's car
여기에 당연해 보이는 하나를 더했습니다. 기능어 하나로 조각을 끝내지 않는다 — "of" 하나만 매달린 조각을 만들지 않기.
그리고 구현을 시작했습니다. 거기서 무너졌습니다.
어떤 *"of"*가 홀로 남았는지 알려면 그것이 어느 구에 속하는지 알아야 하고, 그건 문장을 파싱해야 한다는 뜻입니다. 게다가 계속 나빠졌습니다:
- 같은 단어 "up": *"give up"*에서는 동사에 붙어 있어야 하는 불변화사입니다. *"walked up the hill"*에서는 뒤에 오는 것에 속한 전치사입니다. 글자만 보는 코드에게 둘은 똑같습니다.
- **"New York City"**는 통째로 남아야 하는데, 고유명사 인식기를 따로 붙이지 않으면 코드는 그게 고유명사인지 알 수 없습니다.
- **"1,000"**의 쉼표는 끊을 자리가 절대 아니고, **"In 2020, we…"**의 쉼표는 완벽한 자리입니다. 같은 글자입니다.
- *"to share"*의 *"to"*는 부정사이고, *"went to London"*의 *"to"*는 전치사입니다.
규칙을 하나 더할 때마다 예외가 셋 태어났습니다. 절반쯤 갔을 때 고개를 들고 우리가 무엇을 만들고 있는지 알아차렸습니다. 영어 파서였습니다. 그리고 다 만들어도, 충분히 까다로운 현실의 문장 하나에 여전히 질 것이었습니다.
그러고 나서, 받아들이기까지 부끄럽게도 오래 걸린 꽤 뻔한 깨달음이 왔습니다. 지금의 언어 모델이 바로 이 일의 명수라는 것. *"give up"*과 *"walked up"*을 가르고, *"New York City"*가 한 덩어리임을 알고, 어느 쉼표가 호흡이고 어느 쉼표가 자릿수 구분인지 아는 것 — 그건 모델이 수십억 개의 영어 문장에서 배운 바로 그것입니다. 우리는 모델이 이미 가진 능력을 손으로 코딩하고 있었습니다.
그래서 역할을 뒤집었습니다:
- 규칙은 코드에서 나와 지시문이 되었습니다. 위의 "여기서는 절대 끊지 않는다" 목록 전체가 이제 프롬프트에 있습니다.
- 경계는 100% 모델이 정합니다. 코드는 아무것도 만들어내지 않습니다. 단어 수를 맞추려는 채워넣기도, 크기 상한도 없습니다.
- 코드는 코드가 실제로 잘하는 일, 검증으로 물러났습니다:
- 원래 단어 목록과 모든 토큰을 대조합니다. 모델이 문장부호는 빠뜨릴 수 있지만, 단어 하나가 바뀌거나 없으면 그 결과 전체를 버리고 대체안으로 갑니다.
- 단어별 타임스탬프로 조각마다 시간을 맞춥니다. 그래서 재생을 누르면 정확히 그 구에 떨어집니다.
- 모든 조각을 원래 문장에 되짚어 연결합니다. 나중에 우리를 살려 준 세부입니다.
작지만 크게 중요했던 변화 하나: 원시 단어를 다시 이어 붙인 문자열이 아니라 문장부호가 살아 있는 스크립트를 모델에 줍니다. 쉼표와 마침표는 녹음이 남긴 가장 강한 호흡 단서입니다. 그걸 벗겨 내는 건 우리가 가진 최고의 증거를 버리는 일입니다.
3부 — 무슨 기준으로 나눌 것인가: 의미 단위와 억양 단위
자르는 일을 모델에 맡긴다는 건 마음대로 하게 둔다는 뜻이 아닙니다. 무슨 기준으로 자를지는 여전히 우리가 말해 줘야 했고, 여기서는 느낌이 아니라 근거가 필요했습니다.
사람은 단어를 따로따로 말하지 않습니다. 말은 의미 단위(sense group)로 짜여 있습니다.
의미 단위란 하나의 생각을 담아 한 호흡에 말하는 단어 묶음이고, 멈춤은 단위와 단위 사이에 떨어지며 단위 안에서는 절대 떨어지지 않습니다.
언어학에서 이 단위는 월러스 체이프가 말한 억양 단위입니다. 이어지는 말의 흐름을 듣는 사람의 제한된 주의의 초점에 맞는 크기로 잘라내는 중간 층위의 운율 단위입니다. 이건 미적인 이야기가 아닙니다. 영어 말하기의 기억에서 억양 단위가 하는 역할에 대한 연구가 따로 있습니다.
인지심리학의 조각을 하나 더합니다. 작업 기억은 대략 7±2개 단위를 담고(밀러, 1956), 뒤의 연구는 이를 약 4±1개로 낮췄습니다(코완, 2001). 우리의 가장 짧은 단계가 2~4단어인 이유가 정확히 이것입니다. "짧으려고 짧게"가 아니라, 아직 소리를 잡으려 애쓰는 동안 단기 기억에 들어갈 만큼 짧게입니다.
그리고 우리를 가장 안심시킨 부분: 전문 자막 제작자들은 이 문제를 오래전에 정리해 두었습니다. BBC 자막 지침은 자막을 자연스러운 언어적 경계에서 나누어 각 줄이 하나의 온전한 언어 단위를 이루도록 요구하고, 반드시 피할 분할을 이름까지 붙여 적어 둡니다 — 관사와 명사, 전치사와 뒤에 오는 구, 접속사와 뒤에 오는 절, 대명사와 동사 — 그러면서 절 경계에서 나누기를 선호합니다.
2부에서 우리가 적었던 "여기서는 절대 끊지 않는다" 목록과 거의 그대로 겹칩니다. 우연이 아닙니다. 둘 다 같은 곳에서 나왔으니까요. 영어가 단어를 묶는 방식입니다. 우리는 방송 자막 제작자들이 이미 닦아 둔 길을 다시 걷고 있었고, 그것이 우리가 옳은 방향으로 걷고 있다고 믿게 해 준 근거였습니다.
구 나누기 세 단계 — 그리고 왜 셋인가
그 근거가 있으면 세 단계는 더는 임의의 숫자가 아닙니다:
| 단계 | 크기 | 근거 | 어울리는 때 |
|---|---|---|---|
| 또박또박 | 2~4단어 | 작업 기억의 덩어리 한계(≈4±1) | 처음 시작할 때, 또는 빠른 말 |
| 자연스럽게 | 5~9단어, 절 크기 | 억양 단위 + "절 경계 선호" | 평소 연습 |
| 유창하게 | 문장 전체 | 완결된 의미 단위 | 더 긴 줄을 붙들 수 있게 된 뒤 |
각 단계는 진행 상황을 따로 기억하므로, 수업 중간에 단계를 바꿔도 지금까지 한 일이 사라지지 않습니다.
계획에 없던 이점: 말하기 연습
의미 단위로 자르니 다른 것이 열렸습니다. 조각 하나가 정확히 한 호흡이기 때문에, 구 단위로 쉐도잉할 수 있습니다. 숨이 모자라지 않게 조각 전체를 말하고, 원어민이 멈추는 자리에서 멈추게 됩니다.
25단어 문장을 한 번에 쉐도잉해 보면 절반쯤에서 막히고 아무도 끊지 않는 자리에서 끊게 됩니다. 조각 단위 쉐도잉은 다른 운동입니다. 개별 단어의 발음만이 아니라 영어 말의 리듬을 훈련하는 것입니다. 한 번의 분할이 듣기와 말하기 둘 다에 쓰입니다.
듣기 연습의 세 단계(듣기 → 받아쓰기 → 쉐도잉)가 처음이신가요? 먼저 쓴 글을 읽어 보세요 — 이 글은 이미 2~3단계에 있다고 보고 씁니다.
첫 번째 교훈: 분할은 나누는 작업이 아니라 언어적 판단이다. 그리고 문제가 순전히 언어적일 때, 가장 잘 푸는 것은 우리가 쓴 코드가 아니라 그 언어를 배운 모델입니다. 우리 일은 지시를 정확히 세우고 가차없이 검증하는 것입니다.
4부 — 구 단위 번역: 더 어려운 문제
분할을 풀고 나니 보기 싫은 이음매가 드러났습니다. 네 단어짜리 조각마다 여전히 문장 전체의 번역이 떠 있었습니다. *"our brain is working"*을 입력하는 동안 그 아래에 번역 한 줄이 통째로 앉아 있는 셈입니다. 군더더기이고, 게다가 아직 듣지 않은 부분을 미리 알려 버립니다.
"조각마다 따로 번역하면 되지"는 뻔한 말처럼 들립니다. 하지만 여기에는 서로 싸우는 제약 세 개가 있습니다:
- 조각은 그것이 뜻하는 것을 뜻해야 한다 → 문장 전체 문맥이 필요하다.
- 그런데 문장의 나머지를 드러내면 안 된다.
- 그리고 옆 조각의 단어를 빌려오면 안 된다.
잘못된 길 1: 문장 번역을 잘라 나눠 붙이기
빈틈없어 보이는 생각이었습니다. 문장 번역은 이미 맞으니, 그걸 조각들에 나눠 배분하면 된다. 조각들을 이어 붙이면 원래 번역이 돌아오니, 더한 것도 잃은 것도 없다.
얌전한 문장에서는 아름다웠습니다:
"I was appointed six months ago," → "저는 여섯 달 전에 임명되었고," "and the more I've spoken about feminism," → "그리고 페미니즘에 대해 말할수록,"
그러다 이 문장을 만났습니다:
"It's an environmental issue which, like the growing amounts of plastic waste, isn't going away."
"of plastic waste," 조각에 배정된 번역은 "플라스틱 쓰레기가 점점 늘어나는," 이었습니다.
이어 붙이면 문장은 여전히 완벽합니다. 하지만 학습자가 보고 있는 것은 "of plastic waste" 네 단어이고, 그 뜻이 "플라스틱 쓰레기가 점점 늘어나는"이라고 듣고 있습니다. *"growing"*은 앞 조각에 속한 단어입니다. 우리는 방금 거짓을 가르쳤습니다.
세부를 보세요. 또 *"of"*입니다. 분할에서 우리를 무너뜨리고, 번역에서 돌아와 다시 무너뜨렸습니다.
다시 붙였을 때 맞는 것과 조각마다 맞는 것은 같지 않다. 언어마다 단어 순서를 다르게 바꾸므로, 전체로는 충실한 분배가 부분에서는 틀릴 수 있습니다.
잘못된 길 2: 조각마다 번역하되, 완성된 번역도 함께 넘겨주기
정신을 차리고 조각을 하나씩 따로 번역하기로 바꿨습니다. 문맥으로 영어 문장 전체 와 기존 번역을 함께 넘기면 단어 선택이 일관될 것이라고 생각했습니다.
결과:
"of plastic waste," → "점점 늘어나는 플라스틱 쓰레기,"
여전히 오염되어 있습니다. 완성된 번역이 눈앞에 놓이면 모델은 번역을 멈추고 그 번역을 다시 나누는 일로 돌아가기 때문입니다. 없애려던 목발을 우리가 손수 건네준 셈이었습니다.
잘못된 문맥은 문맥이 없는 것보다 나쁘다.
실제로 통한 것
프롬프트에서 완성된 번역을 완전히 뺐습니다. 영어 문장 전체만 남기고, 그것을 딱 한 가지 일에만 씁니다. 단어의 뜻을 가려내는 일입니다. 그리고 무딘 지시 하나를 더했습니다. 이 조각에 있는 단어만 번역하라. 다른 조각에 속한 단어라면 여기 나와서는 안 된다.
"of plastic waste," → "플라스틱 쓰레기의," ✓ "the growing amounts" → growing을 제자리에 둡니다
역할을 갈라 놓으면 싸우던 제약 셋이 풀립니다. 영어 문장은 문맥을 주고, 번역되는 것은 그 조각의 단어뿐입니다.
마지막 함정: 맞는 것으로는 부족하고, 안정적으로 맞아야 합니다
첫 판본은 비용을 아끼려고 한 번의 호출에 25문장을 담았습니다. 그러자 모델이 각 문장의 조각 개수를 잘못 세기 시작했고, 개수가 어긋나면 그 문장 전체가 무효가 됩니다. 채워진 비율은 137개 조각 중 58개였습니다. 학습자의 절반 이상이 여전히 옛 문장 전체 번역을 보게 되는 셈입니다.
아주 평범한 수정 두 개:
- 묶음을 작게 — 호출마다 항목이 줄면 모델이 자리를 잃지 않습니다.
- 실패한 문장은 하나씩 다시 시도 — 항목 하나짜리 호출은 거의 틀리지 않습니다.
결과는 137개 중 137개. 그리고 그 대가를 지연으로 치르지 않도록, 호출은 알맞은 상한 안에서 동시에 돌립니다.
5부 — 화면: 구 번역과 문장 전체
이 모든 것을 지나고 나서 학습자가 보는 것은 조용하고 단순합니다:
- 조각마다 자기 번역이 붙습니다. 입력한 만큼만 정확히 이해합니다.
- 문장의 마지막 조각에서는 문장 전체 번역도 나옵니다. 부분과 전체를 다 얻고, 미리 알려지는 것도 없습니다. 문장을 끝낸 뒤에야 도착하니까요.
- 없으면 조용히 물러납니다. 조각이 하나뿐인 문장이나 모델이 처리하지 못한 문장은 문장 전체 번역으로 조용히 돌아갑니다. 빈칸은 없습니다.
그리고 번역은 베트남어만이 아닙니다. 설정에서 고른 모국어를 따르고, 언제든 바꿀 수 있으므로 같은 수업이 자기 언어로 나옵니다:
우리에게 남은 것
지나온 거리를 보세요. 초기에는 유튜브의 무료 자막에 기댔습니다. 철자 오류, 문장부호 오류, 때로는 아예 틀린 단어가 있었고, 듣기 연습에 가장 나빴던 건 줄바꿈을 영상 화면에 맞춰 했다는 점입니다. 뜻에 맞춘 게 아니고요. 자막 한 줄이 어디서 끝나는지는 영어가 아니라 영상 플레이어가 내린 결정이었습니다.
오늘 같은 영상은 이렇게 지나갑니다. AI 스크립트 생성 → 언어학에 근거한 세 단계 조각 나누기 → 토큰 단위 검증 → 단어별 시간 맞추기 → 모든 조각마다 자기 모국어로 된 전용 번역 → 그리고 제대로 나오지 않은 것은 다시 시도. 전부 이미 나와 있습니다 — 업데이트 기록을 보세요.
비용은 몇 배로 올랐습니다. 이제 영상 하나에 모델 호출이 훨씬 많이 들어가고, 재시도가 더해지고, 언어 수만큼 다시 곱해집니다. 실제로 나가는 청구서입니다.
하지만 이 글의 두 문제는 같은 자리에서 시작했습니다. 이미 작동하고 있었지만, 우리가 충분히 좋다고 여기지 않은 것. 기계적인 분할도 작동했습니다. 조각마다 문장 전체 번역을 보여주는 것도 작동했습니다. 번역을 잘라 나눠 붙이는 것은 솔직히 우아해 보였습니다.
다만 옳지 않았습니다. 그리고 작동하는 것과 옳은 것 사이의 그 틈이, 학습자가 실제로 느끼는 부분입니다.
이 글은 정확히 의견 하나에서 시작했습니다 — 맨 위의 그 스크린샷입니다. 제품에서 아직 "되긴 하는데 뭔가 어긋난" 느낌이 드는 것이 있다면 보내 주세요.