본문으로 건너뛰기
페이지 목차
이 페이지에서 검색

로컬 LLM

이 페이지에 묻기

로컬 LLM · 현재 차시와 목차 본문에서만 찾아 답합니다. 답을 지어내지 않고 해당하는 대목을 그대로 보여 주며, 여기에 없으면 없다고 알려 드립니다.

생성형 AI가 아니라 이 페이지 본문을 찾아 그대로 보여 주는 방식입니다. 외부로 나가는 요청이 없습니다.

LOCAL · LLM

로컬 LLM

생성 수정

로컬 모델 실행과 GPU·메모리 이해부터 서빙·RAG·도구 호출·업무형 앱 구현까지 차례로 살펴봅니다.

42개 문서 · 5일차 · 40 / 42

39차시 · 성능 테스트 및 최적화

지도 위치 : 5일차 · 프로젝트 7단계 · ①~⑤ 다섯 층 전체를 숫자로 | 이전: 38차시 Function Calling 및 서비스 통합 | 다음: 40차시 프로젝트 발표 및 평가 키워드 : 응답속도, TPS, Throughput, GPU 메모리 측정 및 최적화

이 차시를 다 읽으면

  1. 33차시의 성능 목표(SLO)를 시나리오 · 동시성 단계 · 지표 로 이루어진 측정 계획으로 바꿀 수 있다.
  2. 동시성 단계별 부하 테스트 표를 채우고, SLO가 깨지는 지점을 찾을 수 있다.
  3. 느릴 때 Prefill인가 Decode인가 → KV 캐시 부족인가 → 앱 서버인가 의 순서로 병목을 판정할 수 있다.
  4. 최적화를 한 번에 하나씩 적용하고 before/after 표로 판정할 수 있다.
  5. 최적화 후 평가셋을 다시 돌려 품질 회귀를 확인해야 하는 변경을 고를 수 있다.
  6. 숫자마다 측정 조건 을 함께 기록할 수 있다.

0. 이 차시의 판별 축

#축왼쪽 (0)오른쪽 (1)이 축으로 갈리는 것큰 축 (README 5장)
1한 건의 시간 ↔ 전체 처리량TTFT · TPOT · E2E (상담원 한 명의 체감)Throughput · req/s (서버 전체)동시성을 올릴 때 무엇이 오르고 무엇이 나빠지나한 건의 시간 ↔ 전체 처리량 (⑤ 파생)
2어디가 느린가계산 병목 (Prefill → TTFT)메모리 병목 (Decode → TPOT)손볼 곳이 달라짐계산 병목 ↔ 메모리 병목 (① 파생)
3어느 구간인가모델 서버 직접앱 서버 경유느린 것이 모델인가 앱인가이 차시의 축 (3절 구간별 측정)
4빠른가 ↔ 맞는가성능 지표품질 지표 (평가셋)최적화가 품질을 깎았나README 7장 문장 2 (트레이드오프)

앞에서 이어집니다 — 14차시 (측정 규칙: 워밍업, 고정 출력 길이, 중앙값 · p95, 변수 하나), 22차시 (동시 요청 부하 측정), 23차시 (vLLM 최적화 옵션)를 프로젝트 하나에 적용합니다. 다른 점은 통과선이 있다 는 것입니다. 3일차에는 "몇이 나왔다"로 끝났지만, 39차시는 33차시 NFR-01 — "동시 10명 TTFT p95 < 1초" — 을 넘었는가 못 넘었는가 를 판정합니다.


1. 측정 계획 — SLO를 시험으로 바꾸기

1.1 지표 회수 (14 · 22차시)

지표정의축 1의 어느 쪽문의봇에서 누가 느끼나
TTFT요청 ~ 첫 토큰한 건상담원: "누르고 얼마나 기다리나"
TPOT(E2E − TTFT) ÷ (출력 토큰 − 1)한 건상담원: "초안이 흘러나오는 속도"
E2E Latency요청 ~ 응답 완료한 건결과 카드가 뜰 때까지
TPS (요청 하나)출력 토큰 ÷ 생성 시간한 건—
Throughput모든 요청의 출력 토큰 합 ÷ 전체 경과 시간전체팀 전체가 하루에 처리하는 양
req/s완료 요청 수 ÷ 전체 경과 시간전체—
GPU 메모리 · KV 캐시 사용률 · 대기 요청 수nvidia-smi, /metrics자원병목 판정 (3절)

1.2 시나리오 — 부하의 모양

문의봇의 요청은 모양이 다릅니다. 한 가지 프롬프트로만 재면 실제와 다릅니다.

시나리오무엇입력 / 출력주로 걸리는 쪽
S1 결과 카드/api/triage (36차시)길다 / 짧다 (JSON)Prefill → TTFT
S2 답변 초안/api/reply 스트리밍 (37차시)길다 / 길다Decode → TPOT
S3 후속 요청 3턴째기록 포함 /api/reply더 길다 / 중간Prefill (37차시 3.3)
S4 도구 포함get_order 거치는 처리 (38차시)모델 호출 2회 + 도구앱 · 도구 구간

💡 입력은 33차시 평가셋의 실제 메일(가명) 에서 뽑습니다. 짧은 "안녕하세요" 프롬프트로 잰 숫자는 문의봇의 숫자가 아닙니다.

1.3 측정 조건 기록

[측정 ID] P-003
[날짜] 2026-12-06 15:20
[장비] RTX 4090 24GB / 드라이버 ___ / CUDA ___
[엔진] vLLM ___ (vllm --version 출력)
[모델 · 양자화] DR-001의 값
[기동 옵션] (35차시 명령 전체를 그대로 붙임)
[프롬프트 버전] triage.v2, reply.v1
[시나리오] S1:S2:S3 = 5:4:1, 입력 토큰 중앙값 ___ / 최대 ___
[생성 설정] temperature 0, max_tokens S1=300 S2=500
[동시성 · 요청 수] 10 동시, 200 요청, 워밍업 10 요청 제외
[측정 구간] vLLM 직접 / 앱 경유
[도구 · 명령] (실행한 명령 원문)

⚠️ 조건이 없는 숫자는 비교할 수 없습니다. "빨라졌습니다"만으로는 아무 정보도 되지 않습니다. 무엇이, 어떤 조건에서, 얼마에서 얼마로 바뀌었는지가 함께 있어야 숫자가 됩니다. "어떤 조건에서"가 바로 이 기록입니다. 40차시 발표에서 숫자를 말할 때 이 블록이 함께 갑니다.


2. 동시성 단계별 부하 테스트

2.1 왜 단계별인가

동시 10명만 재면 "통과/실패"만 압니다. 1 → 2 → 5 → 10 → 15 → 20으로 올리면 어디서 깨지는지 , 즉 여유가 얼마인지 압니다. 상담원이 12명으로 늘면 괜찮은가? 그 답이 15 · 20 줄에 있습니다.

2.2 ⭐ 부하 테스트 표 — 직접 채우는 표

시나리오 혼합(1.2절)으로, 측정 구간은 vLLM 직접 과 앱 경유 두 벌을 채웁니다.

동시성TTFT p50TTFT p95TPOT p95E2E p95Throughput (출력 tok/s)req/s오류KV 사용률 최대대기 요청 최대선점 경고SLO 통과?
1
2
5
10 (SLO)
15
20

2.3 표를 읽는 법

보이는 모양뜻배운 곳
동시성을 올리면 Throughput이 오르다가 평탄 해짐연속 배칭이 GPU를 채웠다. 그 뒤로는 줄만 길어짐21 · 22차시
Throughput이 오르는 동안 TTFT · TPOT도 조금씩 늘어남정상. 한 건의 시간을 조금 내주고 처리량을 산 것축 1
어느 지점부터 TTFT p95가 급격히 뜀대기열이 생겼다 → 3절 ②21차시
오류가 0이 아님타임아웃 · 컨텍스트 초과 · 앱 예외 → 로그부터35 · 37차시

⭐ 첫 줄이 이 차시의 핵심입니다. 앞에서 배운 "비동기는 빠른 게 아니다. 한 건의 시간은 같고 처리량이 늘어난다"(README 5.1 축 ⑥) 와 같은 구조입니다. vLLM의 연속 배칭도 한 건을 빠르게 하는 기술이 아니라 처리량을 늘리는 기술 입니다(21 · 22차시, README 5.3 "한 건의 시간 ↔ 전체 처리량").

2.4 무엇으로 재나

구간도구비고
vLLM 직접vLLM의 서빙 벤치마크 (최신은 vllm bench serve, 구버전은 benchmarks/benchmark_serving.py) 또는 AsyncOpenAI 동시 요청 스크립트이름 · 옵션은 버전 확인
앱 경유httpx 비동기 스크립트로 /api/triage · /api/reply(SSE) 호출SSE 첫 data: 도착 = TTFT
GPUnvidia-smi --query-gpu=utilization.gpu,memory.used,memory.total --format=csv -l 1메모리는 거의 일정 (기동 때 확보, 35차시 3절)
KV · 대기열/metrics의 실행 중 · 대기 요청 수, KV 캐시 사용률, 선점 수지표 이름은 버전마다 다름

⚠️ nvidia-smi의 memory.used로 KV 캐시가 꽉 찼는지 알 수 없습니다. vLLM은 기동 때 이미 확보해 두었기 때문입니다. KV가 얼마나 차 있는지는 /metrics 에서 봅니다.


3. ⭐ 병목 판정 순서

SLO를 못 넘었을 때 "모델이 느리다"고 결론 내리면 대개 틀립니다. 요청 한 건은 브라우저 → 앱 서버 → 모델 서버 → (도구) → 다시 앱 서버를 지나므로, 구간마다 시간을 따로 찍어야 어디서 느린지 압니다. 전체 시간 하나만 보면 범인을 모델로 몰기 쉽습니다. 아래 순서로 좁힙니다.

3.1 세 질문

순서질문무엇을 보나판정
①TTFT가 넘었나, TPOT가 넘었나?2.2절 표의 TTFT p95 · TPOT p95TTFT 쪽 → Prefill 또는 줄서기 / TPOT 쪽 → Decode
②KV 캐시가 모자라 줄을 서나?/metrics 대기 요청 수 > 0, KV 사용률 ≈ 100%, 선점 경고 로그그렇다면 TTFT가 늘어난 이유는 계산이 아니라 대기
③앱 서버 구간인가?같은 시나리오의 vLLM 직접 vs 앱 경유 차이직접은 통과, 경유는 실패 → 앱 쪽

3.2 판정별 손볼 곳

판정손볼 곳 (배운 차시)치르는 대가
Prefill (TTFT ↑, 대기 0, 입력이 김)시스템 프롬프트 · 예시 줄이기(36), 대화 기록 줄이기(37차시 3.3), 프리픽스 캐싱 확인(21), --max-num-batched-tokens 조정(23)프롬프트를 줄이면 품질 변화 가능
Decode (TPOT ↑)max_tokens 줄이기, 가중치 양자화 (34), 더 작은 모델초안 잘림 · 품질 변화
KV 부족 (대기 > 0, KV ≈ 100%, 선점)--max-model-len ↓, --kv-cache-dtype fp8, 가중치 양자화로 KV 자리 확보, --max-num-seqs 조정(23)긴 메일 잘림 · 품질 변화 가능
앱 서버 (직접은 통과, 경유는 실패)async def로 LLM 호출(36차시 5절 — 기다리는 동안 다른 요청을 처리), 클라이언트를 매 요청 새로 만들지 않기, 프록시 버퍼링 끄기(37차시 2.3), 도구 타임아웃(38)거의 없음

💡 앱 서버가 병목이면 모델 쪽을 손대지 않습니다. 대가가 "거의 없음"인 칸부터 고칩니다. 36차시 4.3절의 "원인이 지시 · 설정 쪽에 있으면 모델 교체는 답이 아니다"의 성능판입니다.

⚠️ Decode의 이론 상한은 34차시 4.2에서 계산했습니다(대역폭 ÷ 가중치 크기). 동시성 1에서 잰 TPS가 이 상한을 넘으면 측정이 잘못된 것이고, 상한에 크게 못 미치면 엔진 설정을 의심합니다(개발용 Ollama로 쟀다면 ollama ps의 CPU/GPU 분할부터, 12차시).


4. 최적화 — before / after

4.1 규칙

규칙이유
한 번에 하나만 바꿈두 개를 바꾸면 무엇 덕인지 모름 (14차시)
1.3절의 조건을 그대로 두고 바뀐 한 줄만 기록측정 ID로 before/after를 짝지음
바꾼 옵션은 35차시 기동 명령 · 34차시 DR-001 에도 반영40차시에 "왜 이 설정인가"를 답하려면
성능이 올라도 품질 회귀 확인 전에는 채택하지 않음4.3절

4.2 before / after 표 — 직접 채우는 표

#변경 (하나만)동시 10 TTFT p95TPOT p95Throughput최대 동시성 (기동 로그)분류 정확도주문번호 정확도지어낸 값채택?
0기준선 (35차시 설정)—
1프리픽스 캐싱 켜짐 확인 · 켜기
2시스템 프롬프트 단축 (triage.v3)
3max_tokens 조정
4--kv-cache-dtype fp8
5--max-model-len 조정
6(필요하면 34차시로) 가중치 양자화 변경

4.3 ⚠️ 품질 회귀 확인 — 평가셋을 다시 돌려야 하는 변경

변경품질에 영향?다시 할 것
프리픽스 캐싱계산 결과를 재사용할 뿐 — 이론상 출력은 같음평가셋 가볍게 (일부)
--max-num-seqs · --max-num-batched-tokens스케줄링만 바뀜. 수치상 미세한 차이는 가능평가셋 가볍게
--kv-cache-dtype fp8⚠️ 앞 토큰들의 K · V 정밀도가 낮아짐평가셋 전체
가중치 양자화 변경⚠️ 모델 자체가 달라짐 (34차시)평가셋 전체 + 34차시 매트릭스 갱신
프롬프트 단축⚠️ 지시 내용이 바뀜 (36차시)평가셋 전체
--max-model-len ↓긴 메일이 잘림평가셋 긴 메일 묶음
max_tokens ↓초안이 잘림finish_reason: length 비율 확인

⭐ README 7장 문장 2 — "품질 · 속도 · 메모리는 셋 다 가질 수 없다. 측정해서 고른다." — 를 실제로 하는 자리가 이 표입니다. TTFT가 30% 줄었는데 주문번호 정확도가 하한(95%) 아래로 떨어졌다면, 그 최적화는 채택하지 않습니다. 34차시의 순서(품질 하한이 먼저)가 최적화에서도 그대로입니다.

💡 회귀(Regression) — 예전에 잘 되던 것이 새 변경 때문에 다시 망가지는 현상 — 가 LLM 서비스에서는 "설정 하나 바꿨더니 분류 정확도가 떨어졌다" 로 나타납니다. 사람은 안 건드린 곳을 다시 시험하지 않으니, 프롬프트 · 설정이 바뀔 때마다 평가셋 실행이 자동으로 돌게 하는 것이 다음 단계입니다. 코드가 바뀔 때마다 자동으로 시험을 돌리는 이런 장치를 CI (지속적 통합)라고 부릅니다(40차시 개선사항).


5. 실습 — 맡기고 검수하기

지시

문의봇의 성능 테스트와 최적화를 해줘.

목표: 1.2절 시나리오 혼합으로 동시성 1/2/5/10/15/20 부하 테스트를 vLLM 직접과 앱 경유 두 구간에서 실행하고,
     33차시 SLO(동시 10명 TTFT p95 < 1초, 오류 0건) 통과 여부를 판정해.
     실패하면 3.1절 순서(TTFT/TPOT → KV·대기열 → 앱 구간)로 병목을 판정하고, 4.2절 변경을 하나씩 적용해.
맥락: 35차시 vLLM 서비스(기동 옵션 첨부), 37·38차시 앱 서버. 입력은 eval_v1.jsonl의 메일에서 뽑아.
     vLLM 벤치마크 도구는 설치된 버전의 문서 기준으로.
제약:
- 워밍업 요청은 버리고, temperature 0, max_tokens 고정. 1.3절 측정 조건 블록을 측정마다 남겨.
- 한 번에 옵션 하나만 바꿔. 서비스 재시작이 필요하면 바꿀 옵션을 먼저 보여줘.
- kv-cache-dtype, 양자화, 프롬프트, max-model-len을 바꾸면 반드시 평가셋을 다시 돌려 품질 칸을 채워.
- 성능이 올라도 품질 하한(분류 90%, 주문번호 95%, 지어낸 값 0건)을 깨면 '미채택'으로 표시해.
- 추측하지 말고 실행 명령, 벤치마크 출력 원문, /metrics 발췌를 붙여.
보고 형식:
1) 2.2절 부하 테스트 표 (직접 / 앱 경유 두 벌)
2) 병목 판정: [질문 | 본 지표 | 값 | 판정]
3) 4.2절 before/after 표 + 각 행의 측정 ID

받을 증거

  • 측정마다 측정 조건 블록 (1.3절)과 실행 명령 · 출력 원문
  • /metrics 발췌 (대기 요청 수 · KV 사용률 · 선점), nvidia-smi 로그
  • before/after 각 행의 평가셋 실행 결과

내가 직접 볼 것

볼 것이걸로 아는 것 / 왜 내가 보는가
동시성 10 줄의 TTFT p95 와 SLO판정은 내가 합니다. "대체로 빠릅니다"는 판정이 아닙니다
Throughput이 평탄해지는 동시성상담원이 늘 때 장비를 늘려야 하는 지점
직접 vs 앱 경유의 차이차이가 크면 모델을 건드릴 필요가 없습니다
채택한 변경마다 품질 칸이 채워져 있는가빈칸이면 품질 회귀를 모른 채 채택한 것
측정 조건 블록의 vLLM 버전 · 기동 옵션40차시 발표에서 "어떤 조건에서의 숫자인가"를 답해야 합니다
상담원 화면에서 직접 10명 흉내 (창 여러 개)숫자와 체감이 크게 다르면 측정 시나리오가 실제와 다른 것

산출물 체크리스트 (39차시)

  • 측정 계획 (시나리오 S1~S4, 혼합 비율, 입력 출처)
  • 측정 조건 블록 (측정 ID별)
  • 부하 테스트 표 (동시성 6단계 × 직접 / 앱 경유)
  • SLO 판정 (NFR-01 통과 / 미달, 깨지는 동시성)
  • 병목 판정표 (3.1절 세 질문)
  • before/after 표 (한 행 한 변경, 품질 칸 포함)
  • 갱신된 기동 명령 · DR-001 (채택한 변경 반영)

부록 A. 스스로 확인하기

#질문답이 있는 곳
1TTFT와 TPOT는 상담원에게 각각 어떤 체감인가?1.1
2짧은 인사 프롬프트 하나로만 측정하면 안 되는 이유는?1.2
3측정 조건 블록에 꼭 들어갈 항목 다섯 가지는?1.3
4동시성을 단계별로 올리는 이유는?2.1
5Throughput이 평탄해진 뒤 동시성을 더 올리면 무엇이 생기나?2.3
6KV 캐시가 찼는지를 nvidia-smi로 알 수 없는 이유는?2.4
7병목 판정의 세 질문을 순서대로 말하면?3.1
8앱 서버가 병목일 때 손볼 곳과 대가는?3.2
9평가셋을 전체 다시 돌려야 하는 변경 세 가지는?4.3
10성능이 올랐는데 채택하지 않는 경우는?4.3

부록 B. 자주 하는 실수

실수바로잡기
"동시 10명만 재면 된다"⚠️ 통과 여부만 압니다. 단계별로 올려 여유를 봄
"nvidia-smi가 꽉 찼으니 KV 부족"❌ 기동 때 확보한 것. KV 사용률은 /metrics
"느리니까 모델을 더 작게"❌ 먼저 구간 판정 . 앱 서버가 원인이면 모델을 건드릴 이유가 없음
"옵션 세 개를 바꿨더니 빨라졌다"❌ 무엇 덕인지 모름. 하나씩
"kv fp8로 빨라졌으니 채택"⚠️ 평가셋 전체 재실행 후에
"평균 TTFT 0.6초, 통과"⚠️ SLO는 p95 . 평균은 느린 상담원을 숨깁니다
"숫자만 표에 적으면 된다"❌ 측정 조건 이 없으면 비교도 발표도 못 합니다

부록 C. NotebookLM 복습 프롬프트

이 39차시 노트만 근거로 6문제를 내줘. 비전공자 기준으로.
"한 건의 시간과 전체 처리량", "병목 판정의 세 질문", "품질 회귀 확인이 필요한 변경", "측정 조건 기록"은 반드시 포함해줘.
답은 내가 답한 다음에 채점하고, 틀린 이유를 노트의 절 번호를 근거로 설명해줘.