“임베딩 차원이 높을수록 무조건 좋은가?”
“청크 길이는 얼마나 줘야 해? 그냥 길게 하면 좋은 거 아닌가?”
RAG를 처음 만들 때 고민하게 되는 점들인데, 차원 수(d), 최대 토큰 길이(context length), 청크 사이즈(chunk size) 세 가지가 서로 물려 돌아가는 구조라는 걸 몸으로 깨닫게 되었다.
이번 글은 그 경험을 바탕으로
차원 수 선택법 → 메모리/속도 트레이드오프 → 임베딩 모델의 최대 길이 → 청크 사이즈 설계법까지 전체를 하나로 정리해본 내용이다.
1. 임베딩(Embedding)이란?
우리가 사용하는 자연어 문장은 기계 입장에서 보면 그저 문자열일 뿐이다.
하지만 AI 모델은 문자열로는 의미를 계산할 수 없다.
그래서 문장 하나를 숫자 벡터로 바꿔주는데, 이 변환 과정을 임베딩이라고 부른다.
즉, 임베딩은:
- 문장 → 숫자 벡터
- 단어/문단/문서의 의미를 숫자로 표현하는 방식
- 검색·추천·분류에서 공통적으로 쓰이는 핵심 기술
이라고 이해하면 된다.

2. 그렇다면 임베딩 차원(d)은?
임베딩 차원은 벡터의 길이다.
예를 들어 모델이 다음과 같다고 해보자
- 384차원 모델
- 768차원 모델
- 1024차원 모델
이 모델들은 모두 같은 문장을 입력받지만, 이를 표현할 때 사용하는 숫자의 개수가 다르다.
“사과는 과일이다.”
→ [0.12, -0.04, 0.22, ...] (길이 384)
→ [0.91, -0.11, 0.03, 0.25, 0.44, 0.42 ...] (길이 768)
즉,
임베딩 차원(d) = 한 문장을 표현하기 위해 사용하는 숫자의 개수 = 문장을 벡터로 표현할 때 사용할 수 있는 ‘의미 저장 공간의 크기’
한 청크를 d차원 실수 벡터로 매핑한 결과의 길이, 이게 바로 임베딩 차원이다.
이 d는 모델이 학습 중 의미를 담을 수 있는 용량이다.
3. 차원이 다르면 의미 표현 방식이 달라질까?
임베딩 모델은 차원이 높아질수록 더 많은 정보 축(axis)을 사용할 수 있다.
그래서 직관적으로는 이렇게 이해하면 편하다.
✔ 차원이 낮으면 (256~384)
- 덜 세밀한 의미 표현
- 더 압축된 정보 -> 가벼움 -> 계산·저장이 빠름
✔ 차원이 높으면 (768~1024+)
- 미세한 의미 차이를 더 잘 구분
- 비슷하지만 다른 문장들을 더 정확히 분리
- 대신 메모리가 많이 들고 계산량이 증가
그렇다고 “차원이 큰 게 무조건 좋다”는 것도 아니다. 차원이 올라가면 다음 부작용도 함께 따라온다.
- 벡터 저장 용량이 그대로 증가
- 검색 시 연산량 증가
- (진짜 중요) 허브니스(Hubness): 특정 벡터가 너무 자주 Top-k로 등장
그래서 차원은 무작정 높게 쓰는 게 아니라,
데이터 양 / 질 / 문서 길이 / 성능 요구사항에 따라 조절해야 한다.
이 기본 개념 위에서
“청크 길이”,
“검색 성능”,
“메모리·속도 트레이드오프”가 모두 이어진다.
이 부분은 뒤에서 더 깊게 설명할 예정이다.
4. 임베딩 차원은 모델이 이미 정해 놓는다
그러면 임베딩 차원을 내가 마음대로 설정 할 수 있는가? 답은 X..
사용자가 차원을 직접 정하는 게 아니라, 임베딩 모델이 학습될 때 이미 구조가 정해진다. 그래서 모델별로 사용해야하는 임베딩 차원수가 정해져있다.
예를 들어
- bge-base → 768차원
- bge-small → 384차원
- E5-base → 768차원
- MiniLM-L6 → 384차원
- OpenAI text-embedding-3-small → 1536차원
- text-embedding-3-large → 3072차원
그래서 차원을 고려하지 않고 임베딩 모델만 변경하면 에러나는 원인이 바로 이것이다.
그래서 RAG 구축 시 첫 번째 체크는 “우리 모델의 임베딩 차원이 정확히 몇인가?” 이다.
5. 임베딩 모델의 최대 토큰 길이(max_length)
임베딩 차원이 무엇인지 감이 잡혔다면, 그다음으로 꼭 알아야 하는 게 하나 있다.
임베딩 모델은 한 번에 넣을 수 있는 문서 길이, 즉 max_length가 정해져 있다.
생각보다 많은 사람들이 여기서 실수를 하는데, 바로 "임베딩 모델마다 처리할 수 있는 최대 토큰 길이가 다르다”는 점이다.
| 모델 | 최대 길이 |
| bge-base / large | 512 tokens |
| E5-base / large | 512 tokens |
| SBERT 계열 | 512 tokens |
| OpenAI text-embedding-3 계열 | 8192 tokens |
이 차이가 왜 중요하냐면,
문서가 모델이 허용하는 최대 길이를 넘어가면 뒤가 통째로 잘려(truncation) 의미가 사라진다.
그리고 검색 품질은 자연스럽게 흔들리게 된다.
실제로 청크를 700~900 토큰으로 잘라놓고 “RAG 품질이 안 좋아요”라고 말하는 경우가 많은데,
대부분은 모델이 512 이상을 애초에 못 먹는다는 사실을 몰랐던 것에서 발생한다.
6. 청크 사이즈 정하기 -> max_length × 0.7~0.8
max_length=512인 모델을 쓴다면 청크는 320~380 tokens 정도로 잘라야 한다.
그 이상을 욕심내면 토크나이저 특성에 따라 금방 500을 넘겨서 잘린다.
청크를 짧게 잡아야 하는 이유는 다음과 같다:
- 한국어는 토큰화 효율이 낮아 길이가 금방 늘어남
- 마크다운/공백/HTML 등 메타데이터로 토큰 수 급등
- 잘린 순간 의미 정보가 손실됨
- 임베딩의 품질이 곧 검색 품질로 직결됨
그래서 실무에서는 거의 공식처럼 다음을 적용한다.
반대로 GPT 임베딩처럼 8k를 지원하면
청크를 5000~6000 tokens까지 길게 가져가도 전혀 문제가 없다.
긴 문서 RAG에서 압도적인 성능 차이가 발생하는 이유도 여기 있다.
7. 차원(d)과 청크 길이 함께 고려!
임베딩 차원(d)은 “문장을 얼마나 정밀하게 담는가”,
최대 길이(max_length)는 “문장을 얼마나 길게 담는가”를 결정하는 요소다.
따라서 실무에서는 이 둘을 항상 묶어서 조정한다.
예를 들어보자.
📌 시나리오 A — 한국어 문단 중심 RAG
- 문서가 길고 의미 밀도 높음
→ 768차원 + 청크 320~380 tokens (512 모델 기준)
이 조합이 가장 안정적이다.
📌 시나리오 B — FAQ/고객센터처럼 짧은 텍스트
- 문장 길이가 짧아 차원 과투자 불필요
→ 384~512 차원 + 청크 150~200 tokens
📌 시나리오 C — 수백만 문서 + 응답시간 엄격
- 속도와 메모리가 가장 중요
→ 384차원 + 청크 250~350 tokens
→ 필요하면 Cross-Encoder로 재랭킹
📌 시나리오 D — OpenAI 8k embedding 사용
- 청크 길이를 5000~6000까지 확장 가능
→ 긴 문서 검색 정확도 대폭 증가
이걸 정리하면:
문서가 길면 차원을 크게, 문서가 짧으면 차원을 작게
모델의 max_length 안에서 청크를 최대한 효율적으로 자르는 전략이 필요
이라는 공식이 나온다.
허브니스(Hubness)
고차원 공간에서는 일부 벡터가 이유 없이 다양한 문장과 “비슷한 것처럼” 느껴지는 현상이 발생한다.
이게 바로 허브니스다.
증상은 간단하다:
- 특정 문서가 검색 결과 Top-k에 지나치게 자주 등장한다
- 문서 간 거리 분포가 비정상적으로 좁아진다
그리고 해결책도 이미 정리가 잘 되어 있다.
✔ 허브니스 완화법
- L2 정규화 (가장 기본)
- PCA/OPQ 등 차원 축소
- Mutual Proximity / Local Scaling
- ANN → Cross-Encoder 2단계 검색
특히 Cross-Encoder 기반 Rerank는
한국어 RAG에서 확실히 품질 안정화 효과가 있다.
모델 교체 시 가장 흔한 두 가지 실수
❌ 1) Elasticsearch dense_vector dims를 모델 차원과 다르게 설정
- 모델은 768
- ES는 384로 설정되어 있음
→ 즉시 색인 실패
❌ 2) 모델 max_length보다 훨씬 긴 청크를 사용
- 모델 제한: 512 tokens
- 청크: 650 tokens
→ 뒷부분 날아감 → 검색 품질 급락
둘 다 정말 자주 발생하는 실수라서
임베딩 파이프라인을 만들 때 가장 먼저 체크해야 한다.
임베딩 설계 체크리스트
마지막으로 실제 프로젝트에서 내가 가장 많이 사용하는 규칙들을 정리하면 다음과 같다.
✔ 1) 모델 max_length 먼저 확인
가장 중요한 출발점이다.
- 대부분 512
- OpenAI는 8192
✔ 2) 청크 길이 = max_length × 0.7~0.8
- 512 → 350 tokens
- 8192 → 5500~6000 tokens
✔ 3) 차원(d)은 문서 길이와 도메인 복잡도에 따라 선택
- 긴 문서 RAG: 768
- 짧은 텍스트: 384
- 대규모 인덱스: 384~512
- Rerank 사용 예정이면 차원 낮아도 OK
✔ 4) 임베딩은 무조건 L2 normalize
(코사인 안정화)
✔ 5) 필요하면 2단계 검색(ANN → Cross-Encoder Rerank)
특히 한국어 장문에 유효함.
마무리
많은 사람들이 차원(d)과 청크 길이를 각각 독립된 요소로 생각한다.
하지만 실제로 좋은 RAG 시스템을 만들려면
이 둘을 하나의 세트로 보고 설계해야 한다.
- 문장을 얼마나 촘촘하게 담을 것인가(차원)
- 문서를 얼마나 길게 넣을 수 있는가(max_length)
- 우리는 얼마나 잘게 쪼개서 넣을 것인가(chunking)
이 세 가지를 균형 있게 맞춰야
RAG의 검색 품질이 안정적으로 유지된다.
나 역시 이 관계를 제대로 이해한 뒤에야
RAG 품질이 흔들리지 않고 안정되는 느낌을 확실히 받았다.
'AI > Natural language processing' 카테고리의 다른 글
| [Agentic AI] 하네스 엔지니어링이란? | 핵심 요소부터 구축 예제까지 (0) | 2026.04.30 |
|---|---|
| Window/Linux에서 Opencode설치 및 실행 방법 (0) | 2026.01.30 |
| [NLP] Text-to-SQL 기반 Agentic AI 3-Tier 데이터 분석 에이전트 개발 (0) | 2025.11.10 |
| [NLP] docker container 내 Reranker 모델 로드 에러 해결 (0) | 2025.10.21 |
| LLM 파라미터: GPT-4 vs GPT-5 샘플링·제어 정리 (0) | 2025.09.30 |