Post

"내 GPU에선 뭐가 돌아가요?" VRAM 테트리스의 종말과 whichllm 심층 해부

"내 GPU에선 뭐가 돌아가요?" VRAM 테트리스의 종말과 whichllm 심층 해부

Repository: Andyyyy64/whichllm Core Concept: Hardware-aware Local LLM Benchmarking & Routing CLI Key Features: Recency-aware ELO, VRAM & KV Cache math, MoE active param calculation

[The Hook] 솔직히 다들 경험해 보셨잖아요. 금요일 퇴근 후, 깃허브 트렌딩이나 Hacker News에 뜬 새로운 SOTA(State-of-the-Art) 오픈소스 LLM을 보고 주말 내내 뻘짓하던 그 시간들 말입니다. “70B 모델인데 Q4 양자화(Quantization)하면 내 RTX 4090 24GB에 어떻게든 욱여넣을 수 있겠지?”라는 부푼 꿈을 안고 40GB가 넘는 GGUF 파일을 2시간 동안 다운로드받습니다. 하지만 결과는 처참하죠. 터미널에는 불길한 CUDA Out of Memory 에러가 뜨거나, 디스크 스왑이 발생해 어찌어찌 돌아가더라도 초당 1~2 토큰을 힘겹게 뱉어내는 끔찍한 속도(Throughput)에 결국 현타가 오고 맙니다. 현업에서 로컬 LLM을 돌려야 하는 인프라 엔지니어나 백엔드 개발자에게 모델 선택은 그야말로 지독한 ‘VRAM 테트리스’입니다. 흔히들 착각하는 “파라미터 크기 < VRAM”이라는 공식은 현대 LLM 생태계에서 완전히 박살 난 지 오래입니다. 컨텍스트 길이에 따른 KV 캐시(KV Cache) 팽창, GQA(Grouped Query Attention)의 메모리 오버헤드, 심지어 최근 대세가 된 MoE(Mixture of Experts) 모델의 ‘Active Parameters’ 활성화 비율까지 고려해야 하거든요. 이 복잡한 다차원 방정식을 매주 쏟아지는 수백 개의 신규 모델마다 엑셀로 계산하고 있을 순 없습니다. 그래서 오늘 밑바닥까지 뜯어볼 녀석이 바로 이 지독한 페인포인트를 정조준하고 나온 파이썬 CLI 툴, whichllm입니다. 처음 이 프로젝트를 발견했을 때 제 머릿속을 스친 생각은 두 가지였습니다. “와, 이거 진짜 현업의 가려운 곳을 정확히 긁어주네.” 그리고 “근데 이거 코드를 보니 진짜 믿고 내 로컬 프로덕션에서 실행해도 되는 건가?”

[TL;DR: The Core] whichllm은 단순한 VRAM 덧셈 뺄셈 계산기가 아닙니다. 내 로컬 하드웨어(GPU/RAM/CPU/OS)를 자동으로 스니핑하여 구동 가능성을 수학적으로 엄밀하게 계산하고, 최신 벤치마크 데이터(LiveBench, Chatbot Arena ELO 등)를 교차 검증해 ‘지금 당장 내 장비에서 가장 빠르고 똑똑하게 돌아가는 모델’을 랭킹으로 꽂아주는 실전용 하드웨어-LLM 매칭 라우팅 엔진입니다.

[Deep Dive: Under the Hood] 단순한 파이썬 래퍼(Wrapper) 스크립트라고 얕볼 수준이 아닙니다. 이 툴이 작동하는 밑바닥 아키텍처를 뜯어보면, 현재 로컬 AI 생태계가 마주한 메모리 대역폭(Memory Bandwidth)과 연산 병목(Compute Bottleneck)의 본질이 그대로 녹아있습니다. 이 툴이 어떻게 내 RTX 4090이나 Apple M3 Max에서 돌아갈 모델을 정확히 찍어내는지 그 수학적, 구조적 비밀을 파헤쳐보죠.

1. 정밀한 VRAM & KV Cache 시뮬레이터 기존의 멍청한 툴들은 모델의 가중치(Weight) 크기만 계산합니다. 하지만 whichllm은 모델의 아키텍처 메타데이터(HuggingFace config.json 등)를 파싱해 실제 런타임 메모리 풋프린트를 역산합니다. 예를 들어, Llama 3 기반 70B 모델을 Q4_K_M 양자화로 돌릴 때 단순히 가중치 VRAM만 필요한 게 아닙니다. 컨텍스트 윈도우(Context Window)를 8k로 설정했을 때 발생하는 KV Cache 용량은 GQA가 적용되었는지, 일반 Multi-Head Attention인지에 따라 기하급수적으로 달라집니다. 이 툴은 GQA 비율과 타겟 컨텍스트 길이를 바탕으로 (batch_size * seq_len * num_kv_heads * head_dim * 2 * 2) 공식을 내부적으로 시뮬레이션하여 런타임 OOM 발생 여부를 사전에 철저히 차단합니다.

2. MoE (Mixture of Experts) Active Parameter 연산과 메모리 대역폭 로직 이 프로젝트에서 가장 인상 깊었던 엔지니어링 포인트입니다. 최근 오픈소스 LLM 씬은 Qwen3.6-27B 같은 MoE 구조가 지배하고 있죠. 전체 파라미터가 27B라도, 실제 추론 시 토큰당 활성화되는 파라미터(Active Parameters)는 14B 수준에 불과할 수 있습니다. 즉, VRAM에는 27B 모델 전체를 적재해야 하지만, 실제 초당 토큰 처리 속도(Throughput, t/s)는 14B 모델의 메모리 대역폭(Memory Bandwidth)을 따라갑니다. whichllm은 이 MoE의 하드웨어적 특성을 정확히 반영해 속도(Speed) 점수는 활성 파라미터 기준으로, 품질(Quality) 점수는 전체 파라미터 기준으로 분리하여 랭킹을 산출합니다.

평가 항목기존 VRAM 계산 툴 (e.g., 단순 스크립트, 스프레드시트)whichllm 아키텍처의 접근 방식실무적 인사이트
메모리 적재FP16/양자화 기준 정적인 파일 크기만 대조GQA 여부, 타겟 컨텍스트 윈도우 KV Cache 오버헤드 동적 합산실행 전 OOM 100% 차단, 안정적인 워커 노드 구성 가능
초당 속도 (t/s)총 파라미터 크기에 반비례한다고 단순 1차원 가정MoE 구조 인식 (Total vs Active Params), GPU 메모리 대역폭 반영100 t/s가 나올지, 15 t/s가 나올지 병목 지점을 정밀 예측
품질(Quality) 평가파라미터 수가 클수록 무조건 똑똑하다고 평가Quantization 손실률 패널티 부여 (Q8 vs Q3 역전 현상 반영)하드웨어에 맞춘 양자화 타협 시나리오 최적화
데이터 신선도하드코딩된 룩업 테이블 (업데이트 안 됨)런타임 시 --refresh로 LiveBench, Chatbot Arena ELO Fetch1달 전 SOTA 모델이 오늘 출시된 14B 모델에 밀리는 현실 반영

3. Recency-Aware (최신성 기반) ELO 페널티 시스템 AI 생태계에서는 3개월 전 출시된 70B 모델이 오늘 나온 14B 모델보다 멍청한 경우가 허다합니다. 이 툴은 벤치마크 데이터를 수집할 때 ‘출시일 기반 페널티(Time-decay)’ 로직을 적용합니다. 오래된 벤치마크 점수는 신뢰도를 강제로 낮추고, 최신 계통(Lineage)의 모델에 가중치를 주어 “단순히 덩치만 큰 구형 모델”을 랭킹 밑바닥으로 던져버립니다.

아래는 CLI가 백그라운드에서 동작할 때 내부적으로 어떤 제약 조건들을 평가하는지 이해하기 쉽도록 재구성한 프로파일링 JSON 구조 예시입니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// ~/.cache/whichllm/internal_eval_state.json (구동 원리 이해를 위한 의사 코드)
{
  "hardware_profile": {
    "detected_gpu": "NVIDIA GeForce RTX 4090",
    "vram_gb": 24.0,
    "cuda_cores": 16384,
    "memory_bandwidth_gbps": 1008
  },
  "constraints": {
    "max_quantization_degradation_pct": 5.0, // 품질 하락 5% 초과  리스트에서 제외
    "min_throughput_ts": 15.0, // 실사용 가능한 최소 15 t/s 속도 방어선
    "context_window_target": 8192 // 8k 컨텍스트 토큰 여유분 강제 확보
  },
  "scoring_weights": {
    "livebench_coding": 0.45,
    "chatbot_arena_elo": 0.35,
    "recency_time_decay_bonus": 0.20
  }
}

[Pragmatic Use Cases] 그렇다면 이걸 현업에서 어떻게 써먹을 수 있을까요? “내 컴퓨터에서 뭐 돌아가요?” 확인용 장난감을 넘어, 엔터프라이즈 환경이나 CI/CD 파이프라인에서 응용할 수 있는 딥한 실무 시나리오 두 가지를 제시합니다.

시나리오 1: 인프라 도입 전 “Reverse Lookup” (비용 최적화 설계) 실무에서 가장 많이 받는 압박 중 하나가 “이번에 오픈소스 70B 모델로 사내 온프레미스 RAG 시스템 구축할 건데, GPU 서버 스펙 어떻게 발주할까요?” 입니다. 이때 감으로 “대충 A100 80GB 2장이면 넉넉하겠죠?”라고 답했다간 수천만 원의 예산이 공중분해 될 수 있습니다. whichllmplan 서브커맨드는 이 역산(Reverse Calculation)을 완벽히 해결합니다.

1
$ whichllm plan "meta-llama/Meta-Llama-3-70B-Instruct" --quant "Q5_K_M" --min-speed 25

이 명령어를 실행하면, 해당 모델을 초당 25토큰 이상의 쾌적한 속도로 서빙하기 위해 필요한 최소 VRAM과 요구 메모리 대역폭을 역산합니다. 그 결과로 추천 GPU 인스턴스 티어(예: RTX 3090 2Way 구성, 혹은 Mac Studio M2 Ultra 128GB)를 정확히 출력해주죠. 인프라 아키텍트에게는 수천만 원짜리 실수를 막아주는 빛과 소금 같은 기능입니다.

시나리오 2: 이기종 클러스터에서의 다이내믹 모델 라우팅 (Dynamic Snippet Injection) 사내에 굴러다니는 유휴 자원을 모아 분산 추론 클러스터를 구성한다고 가정해봅시다. 어떤 워커 노드는 RTX 4060(8GB)이 달려있고, 어떤 노드는 M3 Max(36GB) 맥북입니다. 여기에 분산 추론 엔진을 띄울 때, 각 디바이스의 스크립트에 하드코딩으로 모델을 지정하는 건 끔찍한 레거시를 만드는 지름길입니다. 이때 파이썬 부트스트랩 스크립트에 whichllm snippet 기능을 연동해 동적 라우팅을 구현할 수 있습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import subprocess
import json

def bootstrap_local_worker():
    # 현재 노드의 하드웨어를 스니핑하여 코딩용 최적 모델을 JSON으로 반환받음
    result = subprocess.run(
        ["whichllm", "--profile", "coding", "--json", "--top", "1"],
        capture_output=True, text=True
    )
    
    if result.returncode != 0:
        raise RuntimeError("하드웨어 프로파일링 실패")
        
    best_model_info = json.loads(result.stdout)[0]
    model_id = best_model_info["model_id"]  # e.g., "Qwen/Qwen3.6-27B"
    quant_level = best_model_info["recommended_quant"] # e.g., "Q5_K_M"

    print(f"[{best_model_info['hardware']}] 워커 초기화 중... 타겟 라우팅 모델: {model_id} ({quant_level})")
    
    # 이후 Ollama CLI 또는 vLLM 엔진으로 해당 모델을 자동 Pull 및 서빙 시작
    # subprocess.run(["ollama", "run", f"{model_id}:{quant_level}"])

if __name__ == "__main__":
    bootstrap_local_worker()

이렇게 추상화 레이어를 구성하면, 8GB 노드는 알아서 Llama-3-8B 수준의 가벼운 모델을 물고, 36GB 맥북은 Qwen3.6-27B 모델을 다운받아 클러스터에 동적으로 합류합니다. 완벽한 하드웨어 디커플링(Hardware Decoupling)이 탄생하는 순간이죠.

[Honest Review & Trade-offs] 자, 지금까지 기술적 우수성을 칭찬했으니 이제 시니어 10년 차의 깐깐한 시선으로 이 툴의 불편한 민낯을 가차 없이 벗겨보겠습니다. 무턱대고 실무에 도입하기엔 치명적인 리스크들이 도사리고 있습니다.

첫째, “이거 100% AI가 짜낸 슬롭(Slop) 코드 아니야?”라는 보안 및 신뢰성 리스크입니다. 실제로 Hacker News를 비롯한 글로벌 커뮤니티에서 이 리포지토리는 엄청난 논란의 중심에 섰습니다. 커밋 히스토리의 패턴, 마크다운 문서의 과장된 어투, 심지어 코드베이스의 예외 처리 로직들이 ‘전형적인 Claude 3.5 Sonnet이나 GPT-4o가 무지성으로 생성한 Vibe-coding의 결과물’이라는 비판이 쏟아졌죠. 심지어 HN 홍보용 마케팅 스크립트까지 AI로 생성했다는 정황이 포착되었습니다. 알 수 없는 소스에서 로컬 환경의 하드웨어 스펙을 깊숙이 읽어 들이고 벤치마크 핑계를 대며 외부 통신을 수행하는 파이썬 코드를 띄운다? 보안에 민감한 엔터프라이즈 환경에서는 절대 용납할 수 없는 붉은 깃발(Red Flag)입니다. 오픈소스라지만, 이런 출처가 모호한 툴을 프로덕션 서버에서 함부로 돌리는 건 내 목줄을 쥐여주는 꼴입니다.

둘째, 벤치마크 맹신이 낳는 확증 편향(Bias)의 한계입니다. README에서는 최신 ELO 랭킹과 LiveBench를 교차 반영한다고 자랑하지만, 벤치마크 점수가 여러분이 마주한 실무의 ‘비즈니스 도메인 해결 능력’을 100% 대변하지는 않습니다. whichllm은 최근 벤치마크를 휩쓸고 있는 Qwen 계열(특히 Qwen3.6-27B)을 무지성으로 1위에 꽂아버리는 강한 경향성을 보입니다. 만약 여러분의 실무가 한국어 금융 도메인 텍스트 분류이거나 특수한 사내 로그 파싱이라면, 글로벌 벤치마크 점수보다 해당 도메인 데이터로 파인튜닝된 구형 아키텍처 모델이 압도적으로 나을 수 있습니다. 툴이 제공하는 점수는 그저 ‘일반적인 수학/코딩/영어 벤치마크’의 파이썬 평균 내기일 뿐, 도메인 특화 능력을 정량화하지 못한다는 치명적인 맹점이 있습니다.

셋째, 심각한 생태계 의존성과 벤더 락인(API Drift) 리스크입니다. 이 툴은 HuggingFace의 오픈 LLM 리더보드와 Chatbot Arena 같은 외부 벤치마크 사이트를 크롤링하고 파싱하여 동적으로 데이터를 가져옵니다. 만약 HuggingFace가 내일 당장 API 스키마를 변경하거나, Arena 사이트가 DOM 구조를 개편한다면 어떻게 될까요? 이 툴은 그날부로 장님이 되어버립니다. 철저히 외부 서비스의 자비에 기대어 있는 모래성 같은 아키텍처라는 뜻입니다.

[Closing Thoughts] 그럼에도 불구하고, 저는 whichllm이 제시하는 문제 해결의 패러다임 자체에는 기립 박수를 보내고 싶습니다. 그동안 우리는 “내 장비에 어떤 LLM을 올려야 할까?”라는 핵심적인 질문을 레딧(Reddit)의 카더라 통신이나 무식한 ‘다운로드 후 기도하기(Try & Error)’ 방식으로만 대처해 왔습니다. 하지만 이 툴은 ‘하드웨어 스펙과 모델의 물리적 요구사항 사이의 수학적 매칭’이라는 가장 엔지니어다운 정답의 방향성을 제시했습니다.

비록 코드가 AI로 대충 짜여진 냄새가 진동하고 벤치마크 편향의 리스크가 명확하지만, 이 프로젝트가 쏘아 올린 개념적 추상화는 매우 중요합니다. 앞으로 vLLM이나 Ollama, SGLang 같은 메이저 추론 엔진 자체에 이러한 ‘하드웨어 프로파일링 기반 동적 최적화 라우팅’ 기능이 네이티브로 내장될 날이 머지않았다고 확신합니다. 당장 내일 회사에서 로컬 LLM을 띄워야 한다면, 무지성으로 허깅페이스 인기 순위 1등 모델을 다운로드하기 전에 로컬 샌드박스 환경에서 이 툴의 매칭 로직을 한 번쯤 뜯어보시길 권합니다. 적어도 여러분의 황금 같은 주말 시간 4시간 정도는 거뜬히 아껴줄 테니까요. 기술의 발전은 결국 개발자의 무의미한 삽질을 줄여주는 방향으로 흐르기 마련입니다. whichllm은 비록 완벽하지 않을지언정, 그 지독한 VRAM 삽질을 끝내기 위한 아주 영리하고 도발적인 첫걸음입니다.

References

  • https://github.com/Andyyyy64/whichllm
  • https://news.ycombinator.com/item?id=40375618 (Show HN Controversy)
This post is licensed under CC BY 4.0 by the author.