13년차의 서버실

서버, 인프라, 홈랩 기술 블로그

[태그:] Ollama

  • [AI] 클라우드 환경에서 Ollama 운영 1년 회고: 비용 효율성 및 관리 노하우

    [AI] 클라우드 환경에서 Ollama 운영 1년 회고: 비용 효율성 및 관리 노하우

    안녕하세요, 13년차 서버실 지킴이 ’13년차의 서버실’입니다.

    오늘은 제가 지난 1년간 클라우드 환경에서 Ollama (올라마)를 운영하면서 겪었던 이야기와, 비용 효율성을 높이고 관리 노하우를 쌓았던 경험을 솔직하게 회고해보려 합니다. 로컬 AI 모델을 쉽게 돌릴 수 있게 해주는 Ollama, 처음엔 제 홈랩 서버에만 돌려봤는데, 어느 날 문득 ‘이걸 클라우드에 올려서 더 많은 사람이 쉽게 접근하게 할 수 없을까?’ 하는 생각이 들었거든요. 그렇게 본격적인 삽질이 시작되었습니다.

    결론부터 말씀드리면, 클라우드에서 Ollama를 운영하는 것은 생각보다 훨씬 매력적이지만, ‘비용’이라는 큰 산을 넘어야 했습니다. 저처럼 로컬 AI를 클라우드로 확장하려는 분들께 제 경험이 작은 길잡이가 되었으면 좋겠네요. 제 삽질의 기록, 지금부터 시작합니다!

    Ollama 클라우드 운영은 사용자 접근성과 확장성을 크게 높여줍니다. 위 다이어그램은 기본적인 서비스 흐름을 나타냅니다.

    Ollama, 클라우드에서 왜? (핵심 개념 설명)

    Ollama (올라마)는 Meta의 Llama나 Mistral AI의 Mistral 같은 대규모 언어 모델(LLM)을 개인용 컴퓨터나 서버에서 쉽게 실행할 수 있도록 도와주는 오픈소스 프레임워크입니다. 쉽게 말해, 복잡한 설정 없이 명령어 한 줄로 다양한 AI 모델들을 다운로드받아 바로 실행할 수 있게 해주는 ‘로컬 AI 모델 실행기’라고 생각하시면 됩니다.

    처음에는 제 홈랩 서버 (Home Lab Server)에서 테스트하며 그 편리함에 감탄했죠. 그런데 여기서 한 가지 아쉬움이 생겼어요. 제 홈랩 서버의 GPU 자원으로는 여러 사람이 동시에 다양한 모델을 사용하기 어렵고, 외부에서 접근하는 것도 보안이나 네트워크 설정이 번거로웠거든요. 그래서 자연스럽게 클라우드 환경으로 눈을 돌리게 되었습니다.

    클라우드에서 Ollama를 운영하면 다음과 같은 장점들이 있습니다:

    • 접근성 (Accessibility): 인터넷만 연결되면 언제 어디서든 접속하여 AI 모델을 사용할 수 있습니다.
    • 확장성 (Scalability): 필요할 때만 고성능 GPU 인스턴스를 사용하고, 사용하지 않을 때는 중단하여 비용을 절감할 수 있습니다. (물론 이게 말처럼 쉽지 않았죠… 후술합니다!)
    • 협업 (Collaboration): 팀원들이나 동료들과 같은 AI 환경을 공유하며 작업할 수 있습니다.
    • 성능 (Performance): 홈랩에서 구성하기 어려운 고성능 GPU (예: NVIDIA A100, H100) 자원을 필요한 만큼 빌려 쓸 수 있습니다.

    클라우드 위 Ollama, 실전 구현부터 삽질까지

    클라우드 환경에 Ollama를 설치하는 과정은 크게 다르지 않습니다. 문제는 어떤 클라우드와 어떤 인스턴스를 선택하느냐, 그리고 어떻게 효율적으로 관리하느냐였죠.

    1. 클라우드 프로바이더 선택 및 인스턴스 프로비저닝

    주요 클라우드 서비스인 AWS (Amazon Web Services), GCP (Google Cloud Platform), Azure (Microsoft Azure) 외에도, GPU 인스턴스 비용이 상대적으로 저렴한 Vultr, Hetzner, Lambda Labs 같은 전문 GPU 클라우드 서비스들도 고려 대상이었습니다. 저는 최종적으로 GCP를 선택했습니다. 이미 다른 프로젝트로 사용 중이었고, Preemptible VM (선점형 VM)이라는 옵션이 비용 절감에 정말 큰 도움이 될 거라고 생각했거든요. (물론 선점형 VM은 예상치 못한 종료라는 명확한 트레이드오프가 있습니다.)

    가장 중요한 건 GPU 인스턴스 선택입니다. Ollama는 CPU로도 구동 가능하지만, 제대로 된 성능을 내려면 GPU가 필수더라고요. 최소한 NVIDIA T4 정도는 되어야 Llama 7B 모델을 돌려도 답답함이 덜합니다. 클라우드에서 GPU 인스턴스를 고를 때 제가 고려한 항목들은 다음과 같습니다.

    • GPU 모델: NVIDIA T4, A100, H100 등. 모델별 성능과 비용이 천차만별입니다.
    • VRAM (Video RAM): 모델 크기에 따라 필요한 VRAM이 다릅니다. Llama 7B는 약 8GB, 13B는 16GB 이상을 권장합니다.
    • 가격: 시간당 요금, 온디맨드(On-demand) vs. 스팟(Spot) vs. 예약(Reserved) 인스턴스 옵션.

    제가 주로 사용했던 GCP의 GPU 인스턴스 유형과 비용 효율성을 고려한 선택지를 표로 정리하면 다음과 같습니다.

    항목 고려 사항 Ollama 운영 시 장단점
    클라우드 프로바이더 AWS, GCP, Azure, Vultr, Hetzner 등 GCP: 선점형 VM으로 비용 절감 가능, 이미 사용 중
    Vultr/Hetzner: GPU 가성비 좋음, 인터페이스 직관적
    GPU 모델 NVIDIA T4 (16GB VRAM), A100 (40/80GB VRAM) T4: 가성비 좋은 시작점, 7B 모델에 적합
    A100: 고성능, 여러 모델 동시 운영, 대형 모델에 적합 (비용 높음)
    인스턴스 유형 온디맨드, 스팟(선점형), 예약 인스턴스 스팟/선점형: 비용 효율적이지만, 예고 없이 종료될 수 있음. 개발/테스트용으로 적합.
    온디맨드: 안정적이지만 비용 높음. 프로덕션 환경에 적합.

    2. Ollama 설치 및 기본 설정

    GPU 인스턴스를 프로비저닝하고 SSH로 접속했다면, Ollama 클라우드 운영의 첫 단계인 설치는 정말 간단합니다. 공식 웹사이트에 나와 있는 스크립트를 실행하면 됩니다. 이때 중요한 게 NVIDIA 드라이버가 잘 설치되어 있는지 확인하는 것입니다. 다행히 클라우드에서 제공하는 GPU 인스턴스 이미지에는 대부분 드라이버가 미리 설치되어 있거나, 쉽게 설치할 수 있는 도구를 제공하더라고요.

    
    # Ollama 설치 스크립트 실행
    curl -fsSL https://ollama.com/install.sh | sh
    
    # 설치 확인 및 모델 다운로드 테스트
    # ollama pull llama2 (약 3.8GB)
    # ollama run llama2
    

    저는 여기서 `systemd` (시스템디)를 이용해 Ollama를 서비스로 등록하고 자동 실행되도록 설정했습니다. 이렇게 하면 서버가 재부팅되어도 Ollama가 자동으로 시작되고, 백그라운드에서 안정적으로 실행되죠. 제가 사용했던 간단한 `systemd` unit 파일입니다.

    
    # /etc/systemd/system/ollama.service 파일 생성
    sudo tee /etc/systemd/system/ollama.service > /dev/null <

    Ollama를 서비스로 등록하여 안정적으로 운영하는 systemd 설정 예시입니다. OLLAMA_HOST 환경 변수를 설정하여 외부 접속을 허용하는 것이 중요합니다.

    클라우드 터미널에서 Ollama 설치 후 `ollama run llama2` 실행 모습 또는 `systemctl status ollama` 명령으로 서비스 상태를 확인하는 화면

    Ollama 설치 후, 모델을 다운로드하고 실행하는 모습입니다. systemd로 서비스 등록 후에는 systemctl status ollama 명령으로 서비스 상태를 확인할 수 있습니다.

    3. 외부 접속 및 보안 설정

    Ollama가 클라우드 인스턴스에서 잘 실행되었다면, 이제 외부에서 접근할 수 있도록 네트워크 설정을 해야 합니다. 기본적으로 Ollama는 11434 포트를 사용합니다. 클라우드 콘솔에서 해당 인스턴스의 방화벽 (Firewall) 규칙을 수정하여 11434 포트의 인바운드 (Inbound) 트래픽을 허용해야 합니다. 저는 특정 IP 대역에서만 접근을 허용하거나, VPN을 통해서만 접속하도록 설정하여 기본적인 보안을 강화했습니다.

    또한, Nginx (엔진엑스) 같은 리버스 프록시 (Reverse Proxy)를 앞에 두어 SSL/TLS (HTTPS)를 적용하고, 기본적인 인증 (Basic Authentication)을 추가했습니다. 이렇게 하면 데이터 전송이 암호화되고, 인가된 사용자만 Ollama API에 접근할 수 있게 되거든요.

    ⚠️ 삽질 보고서: 비용 효율성과의 전쟁

    클라우드에서 Ollama를 운영하며 가장 큰 어려움은 역시 비용 관리였습니다. GPU 인스턴스는 시간당 요금이 정말 비싸거든요. 처음에는 '필요할 때만 켜고 끌 수 있겠지!'라고 생각했지만, 현실은 다았습니다.

    • 인스턴스 종료 깜빡: 테스트하다가 깜빡 잊고 GPU 인스턴스를 끄지 않아 다음 달 요금 폭탄을 맞은 적이 한두 번이 아닙니다. 🤯
    • 선점형 VM의 한계: 비용 절감 효과는 좋았지만, 중요한 작업 중에 예고 없이 인스턴스가 종료되는 경우가 생겼어요. 당황스럽긴 했지만, 다행히 Ollama는 스테이트리스(Stateless)하여 모델 파일만 잘 보존하면 큰 문제는 없었습니다. 다만 작업 흐름이 끊기는 건 어쩔 수 없었죠.
    • 모델 용량과 VRAM: 더 큰 모델, 더 많은 모델을 돌리고 싶다는 욕심에 점점 더 비싼 GPU를 찾게 되더라고요. Llama 70B 같은 모델은 A100 GPU 2개 이상을 요구하기도 합니다.

    이런 삽질 경험들을 통해 배운 교훈은 다음과 같습니다.

    1. 명확한 사용 계획 수립: 어떤 모델을, 얼마나 자주, 누가 사용할지 미리 계획해야 합니다.
    2. 자동화된 시작/종료 스크립트: 특정 시간대에만 인스턴스를 켜고 끄는 Cron (크론) 작업이나 클라우드 스케줄러를 활용하는 게 필수입니다. 예를 들어, 퇴근 후에는 자동으로 인스턴스를 종료하고, 출근 전에 다시 시작하는 스크립트를 만들었어요.
    3. 클라우드 알림 설정: 예산 초과 알림, 인스턴스 상태 변경 알림 등을 설정하여 예상치 못한 비용 발생을 방지해야 합니다.
    4. 스팟/선점형 VM 활용: 개발/테스트 환경에서는 적극적으로 스팟/선점형 VM을 사용하되, 중요한 서비스에는 온디맨드 또는 예약 인스턴스를 사용하는 하이브리드 전략을 구사해야 합니다.
    Ollama 클라우드 운영 중 GPU 인스턴스 비용이 막대 그래프로 표시된 가상의 클라우드 비용 관리 대시보드 스크린샷

    클라우드 비용은 방심하면 순식간에 늘어납니다. 위 그림처럼 비용 대시보드를 주기적으로 확인하고 알림을 설정하는 것이 정말 중요합니다.

    1년 회고: Ollama 클라우드 운영의 성과와 배운 점

    지난 1년간 클라우드에서 Ollama를 운영하며 많은 것을 얻었습니다. 무엇보다 로컬 LLM의 가능성을 클라우드 환경에서 마음껏 실험해볼 수 있었다는 점이 가장 컸습니다. 동료들과 함께 필요한 모델을 테스트하고, 간단한 POC (Proof Of Concept, 개념 증명)를 진행하는 데 정말 큰 도움이 되었죠.

    가장 큰 성과는 역시 '자동화된 비용 관리 루틴'을 만들었다는 점입니다. 처음엔 일일이 수동으로 켜고 끄며 허둥댔지만, 지금은 스크립트와 클라우드 스케줄러 덕분에 훨씬 안정적으로 운영하고 있습니다. 예를 들어, GCP의 Cloud Scheduler와 Cloud Functions를 연동하여 특정 시간에 GPU VM을 시작/중지하는 파이프라인을 구축했습니다. 덕분에 불필요하게 낭비되는 비용을 크게 줄일 수 있었죠.

    Ollama 자체도 지난 1년간 빠르게 발전했습니다. API의 안정성이나 모델 지원 범위가 훨씬 넓어져서, 이제는 단순 테스트를 넘어 실제 서비스의 백엔드로 활용할 가능성도 엿보입니다. 다만 여전히 대규모 트래픽 처리나 고가용성 (High Availability) 측면에서는 추가적인 고민과 아키텍처 설계가 필요해 보입니다.

    마무리: 클라우드 Ollama, 당신의 선택은?

    클라우드 환경에서 Ollama를 운영하는 것은 분명 매력적이고 유용한 경험이었습니다. 특히 AI 모델에 대한 접근성을 높이고, 고성능 자원을 유연하게 활용할 수 있다는 점은 홈랩 환경에서는 얻기 어려운 장점입니다.

    그렇다면 어떤 경우에 클라우드 Ollama를 추천할까요?

    • 개인 개발/학습용: 고성능 GPU가 없거나, 외부에서 접근하여 LLM을 사용하고 싶은 개인 개발자에게는 클라우드 스팟/선점형 인스턴스를 활용한 Ollama 운영이 좋은 선택입니다. 비용 효율적으로 다양한 모델을 실험할 수 있거든요.
    • 소규모 팀의 AI 모델 테스트/POC: 여러 팀원이 동일한 환경에서 AI 모델을 테스트하고 싶을 때 유용합니다. 공유된 클라우드 인스턴스에 Ollama를 띄워두고 API로 연동하면 협업 효율을 높일 수 있습니다.
    • 제한적인 프로덕션 환경: 특정 시간대에만 사용량이 몰리거나, 내부 사용자만을 대상으로 하는 서비스라면, 자동화된 시작/종료 로직과 함께 클라우드 Ollama를 활용해 볼 수 있습니다.

    반면, 상시 고가용성이 요구되는 대규모 프로덕션 환경이나, 매우 민감한 데이터를 처리해야 하는 경우에는 Ollama 단독보다는 MLOps (Machine Learning Operations) 파이프라인과 결합하거나, 보다 전문적인 LLM 서빙 솔루션을 고려하는 것이 좋습니다.

    저의 13년차 서버실 경험을 바탕으로 말씀드리자면, '무조건 클라우드가 좋다'거나 '무조건 온프레미스가 좋다'는 답은 없습니다. 각자의 상황과 목적에 맞춰 가장 효율적인 방법을 찾아야 합니다. 클라우드 Ollama 운영은 그 중간 지점에서 훌륭한 대안이 될 수 있다고 생각합니다. 여러분도 자신만의 Ollama 클라우드 활용법을 찾아보시길 바랍니다. 궁금한 점이 있다면 언제든 댓글 남겨주세요. 감사합니다!

    Ollama 클라우드 운영의 핵심 요약 인포그래픽: 비용 효율성, 접근성, 관리 용이성, 확장성을 중심으로 장단점 시각화

    지난 1년간의 Ollama 클라우드 운영 경험을 통해 배운 핵심 요약입니다. 클라우드 환경에서 Ollama를 효율적으로 활용하기 위한 인사이트를 얻으셨기를 바랍니다.

  • [Proxmox] Proxmox LLM Ollama 성능 측정 방법론: 재현 가능한 벤치마크

    [Proxmox] Proxmox LLM Ollama 성능 측정 방법론: 재현 가능한 벤치마크

    Proxmox LLM Ollama 환경에서 LLM 추론 성능 측정 방법론

    Proxmox LLM Ollama 조합으로 홈랩 AI 서버를 굴리다 보면, 제일 먼저 막히는 지점이 성능 자체보다 성능 해석이더라고요. 응답이 느릴 때 GPU 가속 경로가 문제인지, 모델 파일을 읽어오는 스토리지가 문제인지, 아니면 VM의 CPU 배치와 메모리 상태가 흔들리는지 한 번에 안 보입니다. 저도 처음엔 모델만 바꿔 가며 체감으로 판단했는데, 그 방식은 기록이 안 남고 원인 분리도 어렵더라고요. 이 글은 Proxmox + Ollama 조합에서 재현 가능한 LLM 성능 측정 방법을 만드는 데 집중합니다.

    핵심은 단순합니다. 총 응답 시간만 보면 거의 항상 잘못된 결론으로 갑니다. Ollama가 내려주는 load_duration, prompt_eval_duration, eval_duration을 분리하고, 같은 시점의 CPU, 메모리, 디스크, GPU 상태를 같이 봐야 합니다. 홈랩에서는 특히 이 구분이 중요합니다. 같은 하드웨어라도 다른 VM의 백업 작업, 메모리 ballooning, 스토리지 캐시 상태 때문에 결과가 꽤 쉽게 흔들리거든요.

    Proxmox 호스트와 게스트 VM, GPU 패스스루, Ollama API, 모니터링 명령 흐름을 한눈에 보는 구성도입니다.

    왜 Proxmox LLM Ollama 환경은 따로 측정해야 할까요?

    베어메탈에서 잘 나오던 수치가 Proxmox VM에서는 다르게 나오는 이유는 단순히 가상화 오버헤드 한 줄로 끝나지 않습니다. 실제로는 가상화 계층이 병목을 숨기거나 증폭하는 방식이 더 문제예요. 예를 들어 GPU 패스스루가 붙어 있어도 VM의 CPU affinity나 NUMA 배치가 어긋나면 생성 구간이 늘어질 수 있고, 모델 파일이 느린 스토리지에 있으면 첫 호출만 유난히 길어집니다. 이걸 분리하지 않으면 괜히 GPU만 탓하게 됩니다.

    • GPU Passthrough 상태: 장치가 VM에 보이는 것과 실제로 추론 가속에 쓰이는 건 다릅니다.
    • CPU affinity와 NUMA 배치: vCPU가 불리한 코어 배치에 놓이면 토큰 생성 지연이 출렁일 수 있습니다.
    • 스토리지 지연시간: 모델 교체가 잦을수록 첫 로딩 시간이 과장되기 쉽습니다.
    • ballooning, swap, 메모리 압박: 평소엔 티가 안 나다가 긴 프롬프트에서 갑자기 드러납니다.
    • Ollama 메트릭 해석 실수: 로딩 시간과 생성 시간을 한 덩어리로 보면 튜닝 방향이 엇나갑니다.

    제가 기준으로 삼는 문장은 하나입니다. 벤치마크는 순위를 매기는 작업이 아니라, 손해가 나는 구간을 특정하는 작업입니다. 이 관점으로 가면 Proxmox 위 LLM 성능 측정이 훨씬 덜 꼬입니다.

    LLM 성능 측정에서 반드시 분리해야 할 항목

    Ollama는 API 응답에 꽤 유용한 타이밍 필드를 포함합니다. 문제는 이 숫자를 읽는 방식입니다. 저는 최소한 아래 네 축을 분리하지 않으면 비교값으로 잘 안 봅니다.

    항목 의미 이 수치가 커질 때 먼저 볼 것 실무 해석
    load_duration 모델을 메모리로 올리는 시간 스토리지, 모델 상주 여부, 첫 호출 여부 첫 호출만 크면 정상 특성일 수 있지만, 반복 호출에서도 크면 적재가 반복되거나 메모리 압박이 있다는 뜻입니다.
    prompt_eval_duration 입력 프롬프트 토큰 처리 시간 프롬프트 길이, 컨텍스트 길이, CPU 상태 RAG나 긴 시스템 프롬프트를 쓰는 환경에서는 이 값이 체감 대기시간의 큰 비중을 차지할 수 있습니다.
    eval_duration 출력 토큰 생성 시간 GPU 가속, CPU 병목, 모델 크기 토큰/초 계산의 핵심 구간입니다. 장비 비교는 대부분 이 값 중심으로 보는 편이 맞습니다.
    시스템 지표 CPU, 메모리, 디스크, GPU 사용량 vmstat, iostat, nvidia-smi API 숫자만으로는 원인을 못 찍습니다. 같은 시점의 시스템 지표가 있어야 근본 원인을 좁힐 수 있습니다.

    여기서 많이 놓치는 포인트가 하나 있습니다. 짧은 프롬프트에서 빠른 모델이 실제 운영 워크로드에서도 빠르다는 보장은 없습니다. 특히 홈랩에서 RAG를 붙이거나 시스템 프롬프트가 길어지면 prompt_eval_duration이 병목으로 튀어나오는 경우가 적지 않았습니다. 그래서 저는 측정 목적을 먼저 나눕니다. 장비 비교인지, 실제 응답 대기시간 확인인지, GPU 패스스루 검증인지에 따라 봐야 할 값이 달라집니다.

    측정 전에 Proxmox 쪽에서 먼저 고정할 것들

    게스트 VM 안에서만 계측을 정교하게 해도, Proxmox 설정이 흔들리면 결과는 들쭉날쭉해집니다. 측정 전에 아래 조건부터 고정해두는 편이 낫습니다.

    1. 같은 모델 태그, 같은 프롬프트, 같은 출력 길이 조건으로 반복합니다.
    2. 테스트 시간대에는 다른 VM의 백업, 미디어 인덱싱, 대용량 복사 같은 잡음을 줄입니다.
    3. GPU 패스스루를 쓴다면 항상 같은 VM, 같은 게스트 커널 상태에서만 비교합니다.
    4. ballooning target, swap 개입 여부를 먼저 확인하고, 가능하면 벤치 구간에서는 메모리 조건을 고정합니다.
    5. 모델 파일 위치가 로컬 SSD인지, 네트워크 스토리지인지, ZFS ARC나 페이지 캐시 영향이 있는지 기록합니다.

    여기서 실전적으로 중요한 구분이 cold run과 warm run입니다. 첫 요청은 적재 비용이 섞이고, 두 번째부터는 메모리 상주 효과가 붙습니다. 둘을 한 표에 섞어두면 얼핏 데이터가 많아 보여도 해석에는 별 도움이 안 됩니다.

    Proxmox 쪽에서 제가 특히 먼저 확인하는 건 세 가지입니다. CPU affinity, NUMA 사용 여부, ballooning 조건 고정 여부입니다. CPU 배치가 계속 흔들리면 짧은 벤치에서는 티가 덜 나도 반복 측정 편차가 커집니다. ballooning도 운영 효율에는 도움이 되지만, 추론 성능 비교에는 변수로 끼어들 수 있습니다. 홈랩에서는 운영 효율과 벤치 재현성이 종종 충돌하는데, 벤치 시간에는 재현성을 우선하는 편이 낫더라고요.

    실전 구현 1: Ollama API로 응답 시간과 토큰 생성 속도 수집

    CLI 체감은 참고용으로는 괜찮지만, 기록용 벤치마크에는 조금 아쉽습니다. 반복 측정과 후처리를 생각하면 Ollama API의 원본 메트릭을 그대로 저장하는 편이 훨씬 낫습니다. 아래처럼 한 번 호출해서 핵심 필드를 바로 계산해보면 감이 빨리 옵니다.

    curl -s http://127.0.0.1:11434/api/generate \
      -H 'Content-Type: application/json' \
      -d '{
        "model": "llama3:8b",
        "prompt": "Explain the difference between CPU bottleneck and GPU bottleneck in one short paragraph.",
        "stream": false,
        "options": {
          "temperature": 0,
          "num_predict": 128
        }
      }' | jq '{
        model,
        created_at,
        total_duration_ns: .total_duration,
        load_duration_ns: .load_duration,
        prompt_eval_count,
        prompt_eval_duration_ns: .prompt_eval_duration,
        eval_count,
        eval_duration_ns: .eval_duration,
        tokens_per_second: (if .eval_duration > 0 then (.eval_count / (.eval_duration / 1000000000)) else 0 end)
      }'

    여기서 temperature를 0으로 두는 이유는 성능 측정에서 출력 다양성을 줄이기 위해서입니다. num_predict를 고정하는 이유도 같고요. 벤치마크에서 가장 흔한 실수가 출력 길이를 매번 다르게 두는 건데, 그렇게 되면 eval_count가 흔들리고 결국 토큰/초 비교도 흐려집니다.

    반복 측정은 최소 5회 정도는 권합니다. 평균만 보지 말고 최솟값, 최댓값, 편차까지 같이 남겨야 합니다. 홈랩에서는 한 번 빠르게 나온 결과보다 얼마나 덜 흔들리는지가 더 중요할 때가 많거든요.

    for i in 1 2 3 4 5; do
      curl -s http://127.0.0.1:11434/api/generate \
        -H 'Content-Type: application/json' \
        -d '{
          "model": "llama3:8b",
          "prompt": "Write exactly five bullet points about Linux memory pressure.",
          "stream": false,
          "options": {
            "temperature": 0,
            "num_predict": 96
          }
        }' | jq -r --arg run "$i" '[
          $run,
          .created_at,
          .total_duration,
          .load_duration,
          .prompt_eval_count,
          .prompt_eval_duration,
          .eval_count,
          .eval_duration,
          (if .eval_duration > 0 then (.eval_count / (.eval_duration / 1000000000)) else 0 end)
        ] | @csv'
    done >> ollama-bench.csv

    이 CSV 로그는 보기보다 강력합니다. 나중에 VM 설정을 바꿨을 때, 모델 파일 위치를 옮겼을 때, GPU를 교체했을 때 비교 기준이 그대로 남습니다. 저는 이 단계에서 대시보드부터 만들지 않는 편을 권합니다. 원본 로그가 안정적으로 쌓이는 체계가 먼저고, 시각화는 그 다음이더라고요.

    하나 더요. 벤치마크 목적이라면 stream: false를 유지하는 편이 낫습니다. 스트리밍 출력은 체감 속도 확인에는 좋지만, 수집 포맷이 지저분해지고 메트릭 해석이 섞이기 쉽습니다. 체감용 테스트와 기록용 테스트를 분리해두면 나중에 덜 꼬입니다.

    Ollama 벤치마크에서 LLM 성능 측정 지표를 설명하는 이미지

    Ollama API 응답에서 어떤 필드를 뽑아 성능 지표로 쓰는지 설명하는 시각 자료입니다.

    실전 구현 2: 시스템 자원 사용량을 같이 보세요

    Ollama API 숫자만 보면 원인 추정이 자꾸 빗나갑니다. 같은 요청이라도 CPU 압박인지, 디스크 대기인지, GPU가 실제로 일하는지 구분이 안 되기 때문입니다. 저는 최소한 아래 세 축은 같이 봅니다.

    vmstat 1
    
    iostat -xz 1
    
    nvidia-smi dmon -s pucm
    

    읽는 기준은 단순하지만, 해석은 꽤 실전적입니다.

    • vmstat 1: r가 계속 높고 si/so가 움직이면 CPU 경쟁이나 swap 개입을 먼저 의심합니다.
    • iostat -xz 1: 모델 로딩 시점에 await와 %util이 튀면 load_duration 상승과 연결해서 봅니다.
    • nvidia-smi dmon -s pucm: 생성 중에도 GPU 사용률과 메모리 사용량이 거의 반응하지 않으면 GPU 가속 경로를 다시 확인합니다.

    제가 자주 보는 실패 패턴은 이겁니다. GPU는 VM에서 보이는데, 실제 생성 구간에서는 GPU가 거의 일하지 않는 경우예요. 이때는 패스스루 성공과 추론 가속 성공을 분리해서 봐야 합니다. 장치 인식 자체는 성공했지만 드라이버 상태, 메모리 부족, 런타임 제약 때문에 기대한 만큼 가속이 안 붙는 경우가 있습니다. 반대로 GPU 사용률이 높다고 바로 좋은 것도 아닙니다. 메모리 이동 비용이나 CPU 병목이 남아 있으면 eval_duration 개선이 생각보다 작을 수 있습니다.

    재현 가능한 시나리오: cold run과 warm run 분리 측정

    제가 홈랩에서 가장 자주 쓰는 측정 패턴은 cold run과 warm run을 아예 별도 시나리오로 나누는 방식입니다. 같은 모델, 같은 프롬프트여도 첫 요청과 반복 요청은 성격이 다릅니다. 이 둘을 분리하면 적어도 로딩 비용과 생성 비용은 꽤 깔끔하게 갈라집니다.

    1. Ollama 서비스를 재시작하거나 충분히 유휴 상태를 만든 뒤 첫 요청을 보냅니다.
    2. 첫 요청의 load_duration, total_duration을 기록합니다.
    3. 같은 프롬프트를 3~5회 반복하고, 이 구간에서는 eval_duration과 토큰/초를 중심으로 봅니다.
    4. 동시에 vmstat, iostat, nvidia-smi dmon의 변화를 같은 시각 기준으로 맞춰둡니다.

    실제로는 아래처럼 분리 저장해두면 후처리가 편합니다.

    PROMPT='Explain why swap activity can distort LLM benchmark results in a VM.'
    MODEL='llama3:8b'
    
    # cold run
    curl -s http://127.0.0.1:11434/api/generate \
      -H 'Content-Type: application/json' \
      -d "{\"model\":\"${MODEL}\",\"prompt\":\"${PROMPT}\",\"stream\":false,\"options\":{\"temperature\":0,\"num_predict\":120}}" \
      | jq -r '["cold", .total_duration, .load_duration, .prompt_eval_duration, .eval_duration, .eval_count] | @csv' \
      >> bench-split.csv
    
    # warm runs
    for i in 1 2 3; do
      curl -s http://127.0.0.1:11434/api/generate \
        -H 'Content-Type: application/json' \
        -d "{\"model\":\"${MODEL}\",\"prompt\":\"${PROMPT}\",\"stream\":false,\"options\":{\"temperature\":0,\"num_predict\":120}}" \
        | jq -r --arg run "warm-${i}" '[$run, .total_duration, .load_duration, .prompt_eval_duration, .eval_duration, .eval_count] | @csv' \
        >> bench-split.csv
    done

    이 방식의 장점은 단순한데 실용적입니다. 첫 요청만 느리면 적재 비용 성격, 반복 요청도 계속 느리면 생성 경로 병목으로 빠르게 가설을 세울 수 있습니다. 홈랩에서는 이 구분만 제대로 해도 괜히 GPU부터 바꾸는 일을 꽤 줄일 수 있더라고요.

    홈랩 AI 서버에서 Proxmox와 Ollama 벤치마크를 수행하는 터미널 이미지

    cold run과 warm run을 비교하면서 시스템 자원 모니터링을 병행하는 실전 측정 화면 예시입니다.

    VM, LXC, 베어메탈 중 무엇을 기준점으로 삼아야 할까요?

    이 질문은 자주 나오는데, 저는 목적에 따라 답을 다르게 합니다. 무조건 하나가 낫다고 하기보다 무엇을 검증하려는지 먼저 정하는 편이 맞습니다.

    환경 이럴 때 추천 장점 주의할 점
    베어메탈 절대 성능 기준점이 필요할 때 가상화 변수가 적어 기준선 만들기 좋습니다. 실제 운영 환경이 Proxmox라면 결과 이식성이 떨어질 수 있습니다.
    Proxmox VM GPU 패스스루와 재현성 검증이 목적일 때 운영 환경과 같은 조건으로 측정하기 좋습니다. CPU affinity, NUMA, ballooning 같은 변수를 같이 관리해야 합니다.
    LXC 경량화와 운영 편의가 더 중요할 때 리소스 오버헤드가 적고 관리가 가볍습니다. GPU 활용 방식과 권한 구성이 환경에 따라 더 예민할 수 있어, 벤치 기준점으로는 다소 까다롭습니다.

    제 판단 기준은 이렇습니다. 운영도 Proxmox VM에서 할 예정이면 VM에서 잰 수치를 기준으로 삼는 편이 맞습니다. 베어메탈 수치가 더 좋아도 실제 배포 환경과 다르면 의사결정에는 덜 도움이 됩니다. 반대로 이 하드웨어가 어디까지 나오는지 보고 싶다면 베어메탈 기준선을 한 번 찍어두는 게 좋습니다.

    자주 겪는 문제와 해결 방법

    이 부분은 공식 문서만 봐서는 감이 잘 안 오는 영역입니다. 실제로 벤치를 돌리면 아래처럼 삐끗하는 경우가 많습니다.

    1. 프롬프트 길이가 매번 달라서 비교가 무너집니다

    prompt_eval_duration은 입력 길이에 직접 반응합니다. 질문을 바꾸거나 출력 길이를 열어두면, 모델 자체보다 워크로드 차이가 더 크게 반영됩니다. 벤치 프롬프트는 고정, 출력 길이는 num_predict 등으로 제한하는 편이 낫습니다.

    2. 스트리밍 체감 속도를 성능으로 착각합니다

    터미널에 토큰이 빨리 흘러나오면 체감상 빨라 보입니다. 그런데 그건 계측 기준으로는 불안정합니다. 수집용 벤치는 stream: false로 고정하고, 체감 테스트는 별도로 분리하세요. 둘을 섞어두면 나중에 기록이 비교 불가능해집니다.

    3. 디스크 병목이 숨어 있는데 GPU만 의심합니다

    모델을 자주 바꾸며 테스트할 때 특히 그렇습니다. load_duration이 갑자기 커지고 같은 시점 iostat의 await가 치솟는다면, 그건 GPU보다 모델 적재 경로를 먼저 봐야 합니다. 홈랩에서는 NVMe, SATA SSD, 네트워크 스토리지 차이가 생각보다 크게 드러납니다.

    4. Proxmox에서 다른 VM 부하가 끼어듭니다

    백업 작업, 미디어 트랜스코딩, ZFS scrub, 테스트용 쿠버네티스 VM이 동시에 돌면 반복 측정 편차가 커집니다. 이런 경우 평균값보다 분산이 커지는 패턴이 먼저 나타납니다. 숫자가 안 예쁜 게 아니라, 측정 조건이 불안정한 겁니다.

    5. GPU 사용률만 높고 성능 향상은 미미합니다

    이건 대개 GPU 연산 자체보다 CPU 준비 단계, 메모리 이동, 컨텍스트 처리가 먼저 막히는 경우입니다. 그래서 저는 GPU utilization을 목표값으로 보지 않습니다. eval_duration이 실제로 줄었는지를 먼저 확인합니다.

    6. 첫 요청이 계속 느린데 warm run처럼 해석합니다

    메모리 압박이나 unload 정책 때문에 모델이 자주 내려가는 환경에서는 매번 사실상 cold run이 됩니다. 이때는 첫 요청만 느린 건 정상이라고 넘기면 안 됩니다. 반복 호출인데도 load_duration이 매번 크게 잡히는지를 꼭 확인해보세요. 그건 상주 실패일 가능성이 큽니다.

    검증과 결과 해석: 숫자를 어떻게 읽어야 할까요?

    숫자를 예쁘게 정리하는 것보다 중요한 건, 어떤 패턴에서 어떤 결론을 내릴지 미리 정해두는 겁니다. 저는 보통 아래처럼 읽습니다.

    • load_duration만 크다: 모델 적재, 스토리지, 최초 호출 비용을 먼저 봅니다.
    • prompt_eval_duration이 길다: 긴 프롬프트, 큰 컨텍스트, CPU 토큰 처리 경로를 의심합니다.
    • eval_duration이 길다: 실제 생성 성능 문제입니다. GPU 가속 상태, CPU 할당, 모델 크기 적합성을 봐야 합니다.
    • GPU 사용률이 낮고 CPU만 바쁘다: 패스스루 성공 여부보다 실제 추론 가속 경로를 재확인합니다.
    • 반복 측정 편차가 크다: 다른 VM 간섭, 메모리 압박, 백그라운드 I/O를 먼저 정리합니다.

    여기서 중요한 결정 포인트가 있습니다. 무엇을 최적화할지 먼저 정해야 수치 해석이 쉬워집니다. 사용자 체감 첫 응답을 줄이는 게 목표라면 total_duration과 load_duration이 더 중요합니다. 장비 비교가 목적이면 eval_duration과 토큰/초가 핵심이고요. 긴 컨텍스트 운영이 목표라면 prompt_eval_duration이 병목인지부터 봐야 합니다.

    로그 포맷은 거창할 필요 없습니다. 다만 나중에 조건을 복원할 수 있을 만큼은 남겨두는 편이 좋습니다.

    timestamp,host,vm,model,prompt_name,run_type,total_duration,load_duration,prompt_eval_count,prompt_eval_duration,eval_count,eval_duration
    

    이 한 줄이 중요한 이유는 숫자와 환경을 같이 묶어두기 때문입니다. 벤치 결과만 남기고 VM 설정 이력을 빼먹으면 몇 주 뒤에는 왜 빨라졌는지, 왜 느려졌는지 복기가 잘 안 됩니다. 관련해서 Proxmox GPU 패스스루 설정 글이나 Ollama 설치 가이드를 같이 정리해두면 나중에 내부 링크 연결에도 꽤 유용합니다.

    Proxmox Ollama 환경의 LLM 추론 성능 결과를 시각화한 대시보드 이미지

    모델 로딩 시간과 실제 생성 시간을 분리해 해석하는 결과 대시보드 예시입니다.

    운영 팁: 측정 환경을 문서화해야 나중에 안 꼬입니다

    벤치마크는 숫자보다 맥락이 먼저입니다. 특히 홈랩 AI 서버는 장비를 자주 만지게 되니까, 어떤 조건에서 잰 수치인지 생각보다 빨리 잊어버립니다. 최소한 아래 항목은 같이 기록해두는 편이 좋습니다.

    • 모델 이름과 태그
    • 게스트 OS 종류와 커널 상태
    • vCPU 개수, 메모리 크기
    • GPU 패스스루 유무와 장치 종류
    • 모델 파일 저장 위치
    • 테스트 프롬프트 이름
    • cold run인지 warm run인지

    여기서 제 권장 방식은 단순합니다. 설정 변경이 있는 날에는 벤치마크를 다시 찍고, 변경 사유를 한 줄 메모로 남겨두세요. CPU affinity를 바꿨는지, 메모리를 늘렸는지, 모델 저장 위치를 옮겼는지 정도만 적어도 나중에 비교가 됩니다. 숫자만 예쁘게 모아두는 것보다 이게 훨씬 실용적이더라고요.

    FAQ: 현장에서 많이 헷갈리는 부분

    Q. Proxmox LLM 테스트는 VM이 낫나요, LXC가 낫나요?

    GPU 패스스루 검증과 재현성을 우선하면 저는 VM 쪽을 더 자주 씁니다. 운영 편의만 보면 LXC가 가벼울 수 있지만, 벤치 기준점을 만들 때는 변수를 줄이기 쉬운 쪽이 VM이었습니다.

    Q. Ollama 벤치마크는 CLI만으로 충분한가요?

    단발성 확인은 가능합니다. 다만 반복 측정, CSV 저장, 후처리, cold/warm 구분까지 생각하면 API 기반 수집이 훨씬 낫습니다.

    Q. 숫자는 좋은데 체감은 별로입니다

    짧은 프롬프트 위주로만 재면 실제 운영 패턴과 어긋날 수 있습니다. 특히 RAG, 긴 시스템 프롬프트, 멀티턴 대화가 붙으면 prompt_eval_duration 비중이 커집니다. 운영 워크로드와 비슷한 입력으로 다시 재보는 게 맞습니다.

    Q. 토큰/초가 높으면 무조건 좋은 건가요?

    장비 비교에는 유용하지만, 첫 응답 대기시간이 중요한 환경에서는 부족합니다. 사용자가 느끼는 체감은 종종 load_duration과 prompt_eval_duration에 더 크게 좌우됩니다.

    마지막으로: 이런 상황이면 이렇게 고르시면 됩니다

    제가 실제로 추천하는 선택 기준은 아래처럼 명확합니다.

    • 장비 비교가 목적: 같은 프롬프트와 같은 출력 길이로 고정하고 eval_duration과 토큰/초 중심으로 보세요.
    • 첫 응답 체감이 중요: load_duration을 포함한 total_duration을 같이 봐야 합니다. 모델 상주 전략과 스토리지 위치가 더 중요해질 수 있습니다.
    • GPU 튜닝이 목적: Ollama API 결과만 보지 말고 nvidia-smi dmon과 vmstat를 반드시 붙이세요.
    • 운영 전 검증이 목적: CSV 형태로 누적 저장하고, cold run과 warm run을 분리 기록하세요.
    • 결과가 자꾸 흔들린다: 모델을 바꾸기 전에 다른 VM 간섭, ballooning, swap, 스토리지 대기를 먼저 정리하세요.

    조금 더 직설적으로 말하면 이렇습니다. 첫 응답만 느리면 스토리지와 적재 전략부터, 반복 응답도 느리면 CPU/GPU 경로부터, 숫자가 출렁이면 Proxmox 자원 간섭부터 보시면 됩니다. 이 순서가 실제로 가장 덜 돌아가는 편이었습니다.

    제 경험상, Ollama 숫자만 보고 결론 내리면 절반은 빗나가고, Proxmox 호스트와 게스트의 시스템 지표까지 같이 보면 비로소 조정 포인트가 보입니다. Proxmox LLM Ollama 벤치마크는 장비 스펙보다 측정 설계가 더 중요할 때가 많습니다. 한 번만 잘 만들어두면, 그다음부터는 모델 교체든 VM 튜닝이든 훨씬 덜 감으로 움직이게 됩니다.

    Proxmox와 Ollama 기반 GPU 가속 성능 측정 요약 인포그래픽

    Proxmox 기반 Ollama 벤치마크 절차와 해석 기준을 요약한 인포그래픽입니다.

  • [AI] Ollama 커스텀 LLM 가이드: Modelfile 사용법과 실전 구축

    [AI] Ollama 커스텀 LLM 가이드: Modelfile 사용법과 실전 구축

    Ollama 커스텀 LLM 가이드: Modelfile 사용법과 실전 구축

    Ollama 커스텀 LLM을 오래 만지다 보면, 결국 성능 숫자보다 출력 습관을 통제하고 싶다는 요구가 더 자주 생기더라고요. 답변은 꼭 한국어로 나오게 하고 싶다든지, 명령어를 먼저 보여주고 설명은 뒤로 보내고 싶다든지, 모르면 지어내지 말고 확인이 필요하다고 말하게 만들고 싶을 때가 그렇습니다. 이럴 때 가장 먼저 손대기 좋은 게 Modelfile입니다.

    다만 기대치는 정확히 잡아야 합니다. Modelfile은 보통 사람들이 떠올리는 “모델 재학습” 자체와는 다릅니다. 실무 감각으로 말하면, 베이스 모델의 가중치를 새로 만드는 도구라기보다 실행 규약을 모델 단위로 고정하는 계층에 가깝습니다. 이 차이를 이해해 두면 왜 어떤 문제는 SYSTEM 한 줄로 풀리고, 어떤 문제는 ADAPTER나 RAG까지 가야 하는지 훨씬 빨리 감이 옵니다.

    이번 글은 로컬 AI 모델 개발 관점에서, Ollama의 Modelfile로 어디까지 바꿀 수 있는지, 어디서 멈추는 게 맞는지, 그리고 실제로 자주 깨지는 지점이 무엇인지까지 한 번에 정리한 글입니다. 문법과 API 필드는 Ollama 공식 Modelfile 문서, Create API 문서, Generate API 문서 기준으로 다시 확인했습니다.

    로컬 환경에서 베이스 모델 위에 Modelfile을 얹어 커스텀 모델을 만드는 전체 흐름입니다.

    1. Ollama 커스텀 LLM이 실무에서 먹히는 이유는 재현성 때문입니다

    제가 Modelfile을 계속 쓰는 이유는 단순합니다. 사람은 매번 같은 프롬프트를 정교하게 붙이기 어렵지만, 파일은 늘 같은 방식으로 동작하거든요. 특히 팀 단위로 로컬 모델을 쓰기 시작하면 모델 품질보다 먼저 문제 되는 게 사람마다 다른 사용 습관입니다. 어떤 분은 시스템 프롬프트를 길게 넣고, 어떤 분은 짧게 넣고, 어떤 분은 아예 안 넣습니다.

    이때 Modelfile은 계약서를 하나 만들어 줍니다. SYSTEM, TEMPLATE, PARAMETER, MESSAGE, ADAPTER를 모델 이름 뒤에 고정해 두니, 같은 이름을 호출하는 한 최소한의 행동 일관성은 확보됩니다. 이거 진짜 편하더라고요. 문서 초안 작성, 운영 가이드 보조, 코드 리뷰 보조처럼 반복성이 높은 작업일수록 차이가 분명합니다.

    • 반복 프롬프트 제거: 매번 붙이던 역할 설명과 금지 규칙을 모델 단위로 고정합니다.
    • 출력 형식 표준화: “명령어 먼저, 설명 나중” 같은 우선순위를 팀 공통 규약으로 만들기 좋습니다.
    • 실험 버전 분리: 같은 베이스 모델에서 보수형, 설명형, 요약형 모델을 나눠 비교하기 쉽습니다.
    • 장애 원인 분리: 모델 자체 문제인지, 템플릿 문제인지, 파라미터 문제인지 추적이 빨라집니다.

    2. Ollama 커스텀 LLM에서 먼저 선을 그어야 합니다: Modelfile이 바꾸는 것과 못 바꾸는 것

    여기서 선을 분명히 그어야 삽질이 줄어듭니다. Modelfile은 행동 규칙, 입력 형식, 실행 파라미터, 예시 대화, 어댑터 연결은 잘 다룹니다. 반면 모델 내부 지식 자체를 새로 학습시키는 일은 기본적으로 하지 못합니다. 문서 몇 줄 넣었다고 도메인 지식을 완전히 새로 습득하는 구조는 아니라는 뜻입니다.

    실제로는 이렇게 나누면 편합니다. “답변의 순서나 톤이 문제냐”면 Modelfile 쪽입니다. “모델이 특정 도메인 지식을 계속 모르거나 아는 척 틀리느냐”면 ADAPTER, RAG, 또는 더 맞는 베이스 모델을 검토하는 편이 맞습니다.

    문제 유형 우선 선택 이유 피해야 할 접근
    답변 톤이 들쭉날쭉함 SYSTEM + MESSAGE 행동 규칙과 말투는 프롬프트 계층에서 통제가 잘 됩니다 바로 ADAPTER부터 붙이기
    출력 형식이 자꾸 깨짐 TEMPLATE + stop 재검토 채팅 포맷 불일치일 가능성이 큽니다 모델 성능 탓으로 돌리기
    응답이 너무 산만하거나 창의성이 과함 PARAMETER 조정 temperature, top_p, num_ctx 영향이 큽니다 SYSTEM 문구만 계속 길게 늘리기
    특정 도메인 지식을 안정적으로 못 씀 ADAPTER 또는 RAG 검토 행동 지시만으로는 한계가 분명합니다 MESSAGE 예시를 과도하게 누적하기
    팀원마다 결과가 다름 Modelfile로 모델 이름 표준화 입력 규약 자체를 버전 관리할 수 있습니다 사람마다 프롬프트 템플릿 수동 복붙

    3. Modelfile 핵심 지시어는 많아 보여도 실무 우선순위는 분명합니다

    공식 문서에 나오는 지시어는 여러 개지만, 처음 모델을 잡을 때 자주 쓰는 순서는 거의 고정입니다. 보통 FROM → SYSTEM → PARAMETER → MESSAGE가 1차 세트입니다. TEMPLATE와 ADAPTER는 필요성이 분명할 때만 올리는 편이 안전합니다.

    지시어 실무 우선순위 주로 쓰는 상황 주의점
    FROM 최상 출발 베이스 모델 지정 이 선택이 나머지 품질과 호환성의 기준점이 됩니다
    SYSTEM 최상 역할, 금지사항, 출력 순서 고정 길이보다 우선순위가 중요합니다
    PARAMETER 높음 일관성, 컨텍스트, 중단 토큰 제어 값 하나로 안정성이 흔들릴 수 있습니다
    MESSAGE 높음 few-shot 예시 내장 예시를 많이 넣을수록 답변이 경직되기 쉽습니다
    TEMPLATE 중간 채팅 포맷을 명시적으로 제어할 때 베이스 템플릿과 stop이 어긋나면 토큰 누수가 납니다
    ADAPTER 상황 의존 LoRA 또는 QLoRA 결과물 적용 베이스 모델 불일치가 나면 품질이 급격히 무너집니다
    LICENSE 공유 시 중요 배포 또는 팀 공유 내부 사용과 외부 배포 조건을 분리해서 봐야 합니다
    REQUIRES 환경 의존 특정 Ollama 최소 버전 고정 버전 미충족이면 원인 모를 생성 실패처럼 보일 수 있습니다

    효율이 좋은 규칙은 하나입니다. 첫 번째 성공 모델은 단순하게 만들고, 두 번째 버전부터 정교화하는 쪽이 낫습니다. 처음부터 요소를 다 얹으면 실패했을 때 어느 레이어가 원인인지 식별하기가 어렵습니다.

    4. 실전 구현 1단계: 베이스 모델의 원본 템플릿부터 확인하세요

    많이 놓치는 단계인데, 사실상 필수에 가깝습니다. 커스텀 모델을 만들기 전에 ollama show --modelfile로 베이스 모델의 기본 구조를 먼저 봐야 합니다. 이유는 간단합니다. 모델마다 기대하는 채팅 템플릿과 stop 토큰이 다를 수 있기 때문입니다.

    ollama pull llama3.2
    ollama show --modelfile llama3.2
    ollama show --modelfile llama3.2 > base-llama3.2.Modelfile

    저는 보통 세 번째 줄까지 같이 해둡니다. 원본을 파일로 떠놓으면 수정 중에 기준점을 잃지 않거든요. 특히 stop 토큰과 TEMPLATE 블록은 기억으로 다시 쓰기보다 원본에서 필요한 만큼만 복사하는 쪽이 훨씬 안전합니다.

    그다음 1차 버전은 작게 갑니다. 출력 우선순위, 언어 정책, 추측 금지 같은 운영 규약만 넣어도 충분한 경우가 많습니다.

    mkdir -p ~/ollama-custom/workshop
    cd ~/ollama-custom/workshop
    cat > Modelfile <<'EOF'
    FROM llama3.2
    PARAMETER temperature 0.2
    PARAMETER num_ctx 4096
    SYSTEM """당신은 한국어로 답변하는 인프라 엔지니어 보조 AI입니다.
    답변은 항상 다음 순서를 지킵니다.
    1. 바로 실행할 명령어나 설정 예시
    2. 명령어가 실패할 때 확인할 지점
    3. 마지막에 짧은 설명
    모르는 내용은 추측하지 말고 확인이 필요하다고 말합니다."""
    MESSAGE user 리눅스 디스크 사용량 확인 방법 알려줘
    MESSAGE assistant 먼저 아래 명령어부터 확인하겠습니다.
    df -h
    sudo du -sh /var/* 2>/dev/null | sort -h
    lsblk
    EOF
    
    ollama create infra-assistant -f Modelfile
    ollama run infra-assistant

    포인트는 SYSTEM을 길게 쓰는 게 아니라 답변 순서와 금지 규칙을 관찰 가능한 형태로 명시하는 것입니다. “친절하게 답변해라” 같은 추상 문구보다 “명령어 먼저, 설명은 나중” 같은 규칙이 훨씬 잘 먹는 편입니다.

    실제 작업 흐름은 터미널에서 Modelfile을 편집하고 곧바로 create, run으로 검증하는 식으로 진행됩니다.

    5. PARAMETER는 품질보다도 행동 습관을 바꾸는 손잡이입니다

    파라미터를 만질 때 흔히 정답률만 보게 되는데, 실무에선 그보다 출력의 흔들림이 줄어드는가를 먼저 보는 게 맞습니다. 로컬 모델을 업무 보조로 쓸 때는 늘 비슷한 형식으로 나오는 답이 훨씬 값질 때가 많습니다. 이 부분은 실제 운영해 보면 체감이 꽤 큽니다.

    자주 보는 건 temperature, num_ctx, stop, 그리고 필요할 때 샘플링 계열 파라미터입니다. 여기서 특히 실수하기 쉬운 건 num_ctx입니다. 컨텍스트를 크게 잡으면 좋아 보이지만 메모리 사용량과 프롬프트 평가 시간도 같이 늘어납니다.

    파라미터 낮게 둘 때 높게 둘 때 판단 기준
    temperature 일관성 높음, 답변이 보수적 표현 다양성 증가, 흔들림도 증가 운영 문서/명령어 보조면 낮게, 아이디어 발산이면 높게
    num_ctx 메모리 부담 감소, 빠름 긴 문맥 유지에 유리, 느려질 수 있음 평소 넣는 입력 길이를 기준으로 최소 충분치만 확보
    stop 잘 맞으면 출력 경계가 깔끔함 불필요하거나 틀리면 출력이 잘리거나 토큰 누수 베이스 모델 원본 값에서 출발
    MESSAGE 예시 수 유연성 유지 답변 스타일 고정력 상승, 과하면 경직 대개 1~3개로도 충분

    실무적으로는 이렇게 나누면 편합니다.

    • 문서 초안, 운영 절차, 명령어 추천: temperature를 낮게 두고 형식 일관성을 우선합니다.
    • 브레인스토밍, 문안 변주: temperature를 조금 올리되, SYSTEM에서 출력 구조는 유지합니다.
    • 긴 로그/설정 해석: num_ctx를 무작정 키우기보다 먼저 입력을 잘라 넣을 수 있는지 확인합니다.

    6. TEMPLATE는 마지막에 건드리세요. 건드릴 땐 stop까지 세트로 보셔야 합니다

    TEMPLATE는 멋있어 보이지만 실제로는 가장 쉽게 사고 나는 영역입니다. 추천하는 원칙은 단순합니다. 기본 템플릿으로 원하는 형식이 나오면 TEMPLATE는 건드리지 않는 것입니다. SYSTEM과 MESSAGE만으로 해결되는 경우가 훨씬 많습니다.

    반대로 TEMPLATE를 건드려야 하는 경우도 있습니다. 베이스 모델의 채팅 포맷을 명시적으로 유지하면서 시스템, 사용자, 응답 경계를 통제하고 싶을 때입니다. 이때 핵심은 예쁘게 다시 쓰는 게 아니라 원본 구조를 최대한 보존하면서 필요한 부분만 조정하는 겁니다.

    FROM llama3.2
    TEMPLATE """{{ if .System }}<|start_header_id|>system<|end_header_id|>
    
    {{ .System }}<|eot_id|>{{ end }}{{ if .Prompt }}<|start_header_id|>user<|end_header_id|>
    
    {{ .Prompt }}<|eot_id|>{{ end }}<|start_header_id|>assistant<|end_header_id|>
    
    {{ .Response }}<|eot_id|>"""
    PARAMETER stop "<|start_header_id|>"
    PARAMETER stop "<|end_header_id|>"
    PARAMETER stop "<|eot_id|>"
    SYSTEM """당신은 한국어 운영 문서를 절차형으로 정리하는 도우미입니다."""

    이 블록에서 꼭 봐야 할 건 둘입니다.

    • {{ .System }}, {{ .Prompt }}, {{ .Response }}가 실제 템플릿에 반영되는지
    • TEMPLATE에 등장하는 특수 토큰과 PARAMETER stop이 서로 맞물리는지

    실패 사례도 꽤 단순합니다. 템플릿은 바꿨는데 stop은 예전 값을 그대로 두는 경우입니다. 그러면 응답 본문에 <|eot_id|> 같은 문자열이 그대로 보이거나, 반대로 답변이 중간에서 잘립니다. 이건 모델이 멍청해서가 아니라 출력 종료 경계가 틀어진 것입니다.

    7. ADAPTER는 지식 보강보다 정렬된 편향 추가에 가깝게 보는 편이 맞습니다

    ADAPTER를 붙이면 개인화 폭이 넓어지긴 합니다. 다만 기대를 너무 크게 잡으면 실망도 큽니다. 먼저 물어볼 건 하나입니다. “이 문제를 SYSTEM과 MESSAGE로 해결할 수 없는가?” 여기서 해결되면 굳이 어댑터를 안 붙이는 편이 운영은 더 쉽습니다.

    어댑터가 필요한 상황은 보통 두 가지입니다. 첫째, 특정 도메인 문체나 응답 습관을 훨씬 강하게 고정해야 할 때입니다. 둘째, 베이스 모델만으로는 일관되게 안 나오는 패턴을 추가 학습 결과로 밀어 넣고 싶을 때입니다.

    FROM llama3.2
    ADAPTER ./adapters/my-lora-adapter.gguf
    SYSTEM """당신은 Kubernetes 운영 가이드를 작성하는 보조 모델입니다.
    항상 점검 순서, 명령어, 장애 추정 원인을 순서대로 제시합니다."""

    여기서 제일 중요한 건 어댑터가 학습된 베이스 모델과 FROM의 베이스 모델이 맞아야 한다는 점입니다. 공식 문서도 이 경우 결과가 erratic해질 수 있다고 안내합니다. 현장에서는 이걸 모델 성능 탓으로 오해하는 경우가 적지 않습니다.

    그래서 저는 순서를 이렇게 잡습니다.

    1. ADAPTER 없이 동작하는 1차 모델을 만듭니다.
    2. 동일 질문 세트로 결과를 저장합니다.
    3. 그다음 ADAPTER를 붙인 버전을 따로 만듭니다.
    4. 스타일 개선인지, 지식 개선인지, 아니면 품질 붕괴인지 비교합니다.
    Ollama 커스텀 LLM에 LoRA 어댑터를 적용하는 구조 이미지

    베이스 모델 위에 LoRA 어댑터를 추가해 도메인 특화 성격을 강화하는 흐름입니다.

    8. API 자동화는 실험이 많아질수록 가치가 커집니다

    한두 개 만들 땐 Modelfile이 읽기 편합니다. 그런데 역할별 모델이 늘어나면 CLI 수작업은 금방 귀찮아집니다. 이때는 POST /api/create를 써서 생성 과정을 코드로 고정하는 편이 낫습니다. 모델 이름 규칙, 파라미터 조합, 예시 대화 구성을 반복해서 재현해야 할 때 특히 강합니다.

    curl http://localhost:11434/api/create -d '{
      "model": "infra-helper-api",
      "from": "llama3.2",
      "system": "You are a Korean infrastructure engineering assistant. Provide commands first, then failure checks, then short explanations.",
      "parameters": {
        "temperature": 0.2,
        "num_ctx": 4096
      },
      "messages": [
        {
          "role": "user",
          "content": "nginx 로그 확인 순서 알려줘"
        },
        {
          "role": "assistant",
          "content": "먼저 access.log와 error.log를 분리해서 보고, 그다음 4xx/5xx 비율과 upstream 오류를 확인하겠습니다."
        }
      ]
    }'

    이 방식을 선호하는 이유는 단순히 편해서만은 아닙니다. 실험 조건을 텍스트로 남길 수 있기 때문입니다. 어떤 모델 이름이 어떤 규칙과 파라미터로 만들어졌는지가 남아야 나중에 비교가 됩니다.

    생성 후에는 성능 체감만 보지 말고 API 응답 지표도 같이 보는 편이 좋습니다. Ollama의 생성 응답에는 load_duration, prompt_eval_count, prompt_eval_duration, eval_count, eval_duration 같은 필드가 포함됩니다. 이걸 보면 느린 이유가 로딩인지, 입력 길이인지, 출력 토큰 수인지 분리해서 보기 훨씬 편합니다.

    curl http://localhost:11434/api/generate -d '{
      "model": "infra-assistant",
      "prompt": "systemd 서비스 상태 확인 절차를 알려줘",
      "stream": false
    }'

    여기서 판단 포인트는 이렇습니다.

    • load_duration이 크면 모델 로딩 비용이 큰 겁니다.
    • prompt_eval_duration이 크면 입력 문맥이 길거나 num_ctx 운용이 과한 경우를 의심할 수 있습니다.
    • eval_duration이 크면 출력 토큰 수가 많거나 실행 자원이 부족한 쪽일 가능성이 큽니다.

    9. 트러블슈팅은 증상보다 근본 원인을 붙잡아야 빨리 끝납니다

    실제로 많이 부딪히는 문제는 대부분 네 부류였습니다. 중요한 건 증상을 외우는 게 아니라 어느 레이어가 깨졌는지를 먼저 가르는 겁니다. SYSTEM 문제인지, TEMPLATE 문제인지, ADAPTER 문제인지, 자원 문제인지 구분만 잘해도 시간이 꽤 절약됩니다.

    1) 시스템 프롬프트가 먹지 않는 것처럼 보일 때

    • 먼저 볼 것: ollama show --modelfile 모델명
    • 근본 원인: TEMPLATE 안에 {{ .System }} 반영이 없거나 베이스 템플릿을 수정하면서 시스템 경계를 깨뜨린 경우가 많습니다.
    • 판단 기준: 말투보다도 “추측 금지”, “명령어 우선” 같은 규칙이 반복적으로 무시되는지 봅니다.
    • 해결 방향: 원본 TEMPLATE로 되돌린 뒤 SYSTEM만 남기고 다시 비교합니다.

    2) 답변에 특수 토큰이 섞일 때

    • 먼저 볼 것: TEMPLATE와 PARAMETER stop 조합
    • 근본 원인: 출력 종료 토큰과 템플릿 토큰 경계가 맞지 않는 상황입니다.
    • 판단 기준: <|eot_id|>, <|start_header_id|> 같은 문자열이 본문에 보이면 거의 이쪽입니다.
    • 해결 방향: 베이스 모델 기본 Modelfile의 stop 설정을 그대로 기준 삼아 다시 맞춥니다.

    3) 어댑터 적용 후 품질이 갑자기 무너질 때

    • 먼저 볼 것: ADAPTER 학습 기준 모델
    • 근본 원인: FROM에 적은 베이스 모델과 어댑터가 기대하는 기반 모델 불일치
    • 판단 기준: 문장 붕괴, 주제 일탈, 불필요한 반복이 적용 직후 심해집니다.
    • 해결 방향: 어댑터 제작 시 사용한 기반 계열과 동일한 모델로 FROM을 맞춥니다.

    4) 속도가 너무 느리거나 메모리가 버거울 때

    • 먼저 볼 것: ollama ps, OS 메모리/스왑 사용량, 입력 길이, num_ctx
    • 근본 원인: 모델 크기보다도 과도한 컨텍스트, 동시 실행 모델 수, 자원 부족이 겹치는 경우가 많습니다.
    • 판단 기준: 스왑이 발생하면 체감 성능은 급격히 떨어집니다.
    • 해결 방향: 작은 베이스 모델로 내리거나 num_ctx를 낮추고 실험 모델 동시 구동 수를 줄입니다.

    저는 장애를 볼 때 항상 이렇게 나눕니다. 형식 이상은 TEMPLATE, 성격 이상은 SYSTEM/MESSAGE, 지식 이상은 ADAPTER 또는 베이스 모델, 속도 이상은 자원과 컨텍스트. 이 프레임으로 보면 원인 추적 속도가 빨라집니다.

    Ollama 커스텀 LLM 트러블슈팅과 검증 과정을 보여주는 이미지

    응답 토큰 이상 출력, 시스템 프롬프트 무시, 어댑터 불일치 같은 대표 장애 포인트를 점검하는 장면입니다.

    10. 검증은 더 똑똑해졌는가보다 의도대로 수렴하는가를 보셔야 합니다

    커스텀 모델을 만들고 나면 자꾸 성능 향상만 보게 됩니다. 그런데 Modelfile의 1차 목적은 대개 정답률 폭증이 아니라 출력 습관 고정입니다. 그래서 검증 질문 세트를 별도로 두고 베이스 모델과 커스텀 모델을 같은 질문으로 비교하는 편이 좋습니다.

    ollama run llama3.2 "systemd 서비스 상태 확인 절차를 알려줘"
    ollama run infra-assistant "systemd 서비스 상태 확인 절차를 알려줘"
    ollama run infra-assistant "모르면 추측하지 말고, nginx 502 점검 순서를 알려줘"

    여기서 보는 건 단순히 답변 길이나 그럴듯함이 아닙니다.

    1. 명령어가 먼저 나오는지
    2. 설명이 뒤로 밀리는지
    3. 모를 때 지어내지 않는지
    4. 한국어 톤과 형식이 유지되는지
    5. MESSAGE 예시가 답변을 과하게 복제하게 만들지는 않는지
    검증 항목 베이스 모델 커스텀 모델 합격 기준
    답변 언어 영문/국문 혼합 가능 국문 고정 가능 언어 정책이 흔들리지 않을 것
    명령어 우선 제시 질문마다 다름 일관되게 맞출 수 있음 초반 2~3줄 안에 바로 실행 항목이 나올 것
    톤 일관성 변동 가능 SYSTEM으로 안정화 질문이 바뀌어도 문체가 크게 흔들리지 않을 것
    도메인 집중도 일반 지식 중심 MESSAGE/ADAPTER로 강화 쓸데없는 일반론보다 절차형 답변이 앞설 것
    추측 억제 상황 따라 흔들림 금지 규칙 반영 가능 불확실할 때 확인 필요성을 분명히 말할 것

    현업 자동화에서는 “베이스 모델보다 더 똑똑하다”보다 “늘 같은 포맷으로 나온다”가 더 중요할 때가 많습니다. 운영 문서 초안, 반복 질의 응답, 내부 가이드 작성은 특히 그렇습니다. 이 지점이 바로 Ollama 커스텀 LLM의 실무 가치라고 봐도 무리가 없습니다.

    11. FAQ와 최종 추천: Ollama 커스텀 LLM은 이럴 땐 A, 저럴 땐 B로 나누면 편합니다

    자주 헷갈리는 질문

    • Q. Modelfile만 쓰면 미세 조정이 된 건가요?
      A. 아닙니다. 기본적으로는 설정, 프롬프트 구조, 예시 대화, 실행 파라미터를 묶는 작업에 가깝습니다. 추가 학습 결과를 붙이려면 ADAPTER 같은 별도 레이어가 필요합니다.
    • Q. TEMPLATE는 꼭 수정해야 하나요?
      A. 아닙니다. 기본 템플릿으로 문제가 없으면 안 건드리는 쪽이 맞습니다. 깨지는 빈도가 높은 영역이라 이유가 분명할 때만 손대는 게 좋습니다.
    • Q. 개인화된 AI를 가장 빨리 만드는 방법은?
      A. 베이스 모델 하나를 고르고, SYSTEM에 역할과 출력 순서를 명시한 뒤, MESSAGE 1~2개만 넣어 1차 버전을 만드는 방식이 가장 빠릅니다.
    • Q. 언제 ADAPTER까지 가야 하나요?
      A. SYSTEM과 MESSAGE로도 해결되지 않는 도메인 특화 패턴이 반복해서 필요할 때입니다. 단순한 말투 고정 정도라면 대개 과한 선택입니다.

    선택 기준은 이렇게 정리하면 편합니다.

    • 빠르게 목적형 모델이 필요하다: FROM + SYSTEM + PARAMETER + MESSAGE로 시작하세요. 가장 안전하고 재현성이 좋습니다.
    • 응답 형식을 강하게 통제해야 한다: 먼저 ollama show --modelfile로 원본을 확인한 뒤 TEMPLATE를 최소 수정하세요.
    • 특정 학습 결과물을 이미 갖고 있다: ADAPTER를 붙이되, 베이스 모델 호환성을 제일 먼저 확인하세요.
    • 역할별 모델을 반복 생성해야 한다: 사람이 수동으로 만들기보다 /api/create로 자동화하는 편이 관리가 낫습니다.
    • 속도와 메모리가 아슬아슬하다: 큰 모델 집착보다 작은 모델 + 낮은 num_ctx + 명확한 SYSTEM이 더 실용적일 때가 많습니다.

    한 줄로 압축하면 이렇습니다. Ollama 커스텀 LLM의 핵심은 모델을 새로 발명하는 게 아니라, 내 작업 방식을 반복 가능하게 고정하는 것입니다. 처음부터 무거운 학습 파이프라인으로 들어가기보다, Modelfile로 행동 규약을 먼저 굳히는 쪽이 훨씬 현실적입니다. 관련해서 로컬 LLM 성능 최적화나 RAG 비교 글도 함께 읽어보시면 다음 단계 판단이 더 쉬워집니다.

    Ollama 커스텀 LLM Modelfile 핵심 요소 요약 인포그래픽

    FROM, SYSTEM, PARAMETER, TEMPLATE, ADAPTER를 언제 선택하면 되는지 한눈에 정리한 요약 이미지입니다.

  • [Cloud] ArgoCD로 Kubernetes에 Ollama 배포: 6개월 운영 후기 및 최적화 전략

    [Cloud] ArgoCD로 Kubernetes에 Ollama 배포: 6개월 운영 후기 및 최적화 전략

    목차

    [Cloud] ArgoCD로 Kubernetes에 Ollama 배포: 6개월 운영 후기 및 최적화 전략

    ArgoCD Ollama 배포를 처음 붙일 때만 해도, 솔직히 저는 “로컬에서 잘 돌던 걸 굳이 Kubernetes(쿠버네티스, 컨테이너 오케스트레이션 플랫폼)까지 올려야 하나?” 싶었습니다. 그런데 팀이나 홈랩에서 여러 워크로드를 같이 운영하다 보면 얘기가 달라지더라고요. 모델 파일은 크고, 노드는 자꾸 바뀌고, 누가 어떤 설정을 바꿨는지 추적도 필요합니다. 결국 ArgoCD(아르고CD, GitOps 배포 도구)와 Ollama(올라마, 로컬/서버 환경에서 LLM을 실행하는 런타임) 조합으로 정리해 두니 운영 피로도가 확 줄었더라고요.

    이번 글은 제가 홈랩과 테스트 클러스터에서 6개월 정도 굴려보면서 정리한 ArgoCD Ollama 배포 운영 후기입니다. 단순 설치 가이드가 아니라, 어디서 삽질했는지, 어떤 최적화가 체감이 컸는지, 그리고 Kubernetes GitOps 관점에서 무엇을 꼭 잡아야 하는지 중심으로 풀어보겠습니다. 비슷하게 LLM 클라우드나 사내 추론 환경을 작게 시작해 보려는 분들께 꽤 현실적인 기준점이 될 겁니다.

    ArgoCD가 Git 저장소의 선언형 설정을 읽어 Kubernetes 클러스터에 Ollama를 배포하고, 내부 서비스와 스토리지를 연결하는 전체 구조 예시입니다.

    왜 ArgoCD Ollama 배포가 생각보다 중요했는지

    쉽게 말해, Ollama 하나만 띄우는 건 어렵지 않습니다. 문제는 운영이거든요. 처음엔 Docker 하나로 시작했었습니다. 그때는 편했습니다. 근데 모델을 추가하고, 스토리지를 옮기고, 노드를 교체하고, Ingress(인그레스, 외부 트래픽 진입점) 뒤에 붙이고, 다시 재현하려고 하니 슬슬 꼬이기 시작했습니다.

    제가 직접 해보니 진짜 차이는 설치가 아니라 재현성(reproducibility, 같은 상태를 다시 만드는 능력)에서 나왔습니다. Git에 원하는 상태를 남기고, ArgoCD가 그 상태를 계속 맞춰 주니까 “어제는 됐는데 오늘은 왜 안 되지” 같은 상황이 확 줄더라고요. 특히 LLM 워크로드는 모델 파일과 디스크 사용량이 크기 때문에, 사람 손으로 운영하면 금방 흔들립니다.

    • 변경 이력 추적: 누가 리소스 제한을 바꿨는지 Git commit으로 남습니다.
    • 복구 속도: 노드가 바뀌어도 선언형 매니페스트로 다시 맞추기 쉽습니다.
    • 운영 표준화: dev, lab, prod 비슷한 구조로 가져가기 좋습니다.
    • 드리프트 방지: kubectl로 급하게 만진 설정이 오래 남지 않습니다.

    핵심 개념 정리: Kubernetes GitOps와 Ollama를 같이 볼 때

    여기서 중요한 포인트가 있습니다. Ollama는 애플리케이션이고, ArgoCD는 상태 관리자입니다. 이 둘의 역할을 섞어서 생각하면 금방 헷갈립니다. 저도 처음엔 ArgoCD가 모델까지 알아서 관리해 주는 느낌으로 생각했었는데, 실제로는 그렇지 않더라고요.

    1. ArgoCD는 원하는 상태를 맞추는 도구입니다

    Git 저장소에 있는 YAML이 기준입니다. Deployment(디플로이먼트, 파드 배포 정의), Service(서비스, 네트워크 노출), PersistentVolumeClaim(PVC, 영구 스토리지 요청) 같은 리소스를 계속 감시하고 맞춰 줍니다.

    2. Ollama는 모델 실행 환경입니다

    모델 파일을 저장하고, 요청을 받아 추론을 수행합니다. 그래서 CPU/GPU보다도 처음엔 디스크와 네트워크가 더 자주 병목이 되기도 합니다. 특히 모델을 여러 번 다시 내려받는 구조가 되면 운영이 굉장히 피곤해집니다.

    3. 모델 관리와 애플리케이션 관리를 분리해야 덜 꼬입니다

    제가 6개월 운영하면서 얻은 결론은 이겁니다. 애플리케이션 배포와 모델 프리로드(preload, 미리 받아두기)를 같은 단계로 억지로 묶지 않는 게 좋습니다. 처음엔 한 번에 끝내고 싶어서 initContainer(초기화 컨테이너) 쪽으로 몰아넣었는데, 재배포 때마다 모델 다운로드가 걸려서 시간도 오래 걸리고 실패 지점도 늘었습니다.

    구분 역할 운영 팁
    ArgoCD Git 기준 상태 동기화 자동 동기화와 self-heal은 켜되, 삭제 정책은 팀 기준에 맞춰 보수적으로
    Kubernetes 파드 실행, 스토리지, 네트워크 관리 리소스 요청값과 스토리지 클래스부터 먼저 정리
    Ollama LLM 실행과 모델 저장 모델 캐시 경로와 영구 볼륨 전략이 핵심
    GitOps 운영 변경 이력과 재현성 확보 핫픽스 후에는 반드시 Git 원복 반영

    실전 구현: 제가 쓰는 ArgoCD Ollama 배포 기본 구조

    이제 본론입니다. 아래 구조는 제가 홈랩에서 가장 무난하게 굴렸던 방식입니다. 아주 화려하진 않지만, 유지보수는 편했습니다. 처음엔 이게 뭔가 싶었는데, 결국 오래 가는 건 단순한 구조더라고요.

    디렉터리 구조

    platform/
      argocd/
        applications/
          ollama.yaml
      apps/
        ollama/
          namespace.yaml
          pvc.yaml
          deployment.yaml
          service.yaml
          kustomization.yaml

    1. Namespace와 PVC부터 고정합니다

    Ollama는 모델 파일이 남아야 의미가 있습니다. 그래서 저는 거의 항상 PVC를 먼저 잡습니다. 여기서 대충 가면 나중에 재배포할 때 모델을 다시 받느라 시간 다 씁니다.

    apiVersion: v1
    kind: Namespace
    metadata:
      name: ollama
    ---
    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      name: ollama-data
      namespace: ollama
    spec:
      accessModes:
        - ReadWriteOnce
      resources:
        requests:
          storage: 100Gi

    2. Deployment는 최대한 단순하게 갑니다

    실제로 써보니까 처음부터 옵션을 너무 많이 넣는 것보다, 먼저 떠야 합니다. 그리고 그다음에 리소스 제한과 노드 스케줄링을 붙이는 쪽이 덜 위험했습니다.

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: ollama
      namespace: ollama
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: ollama
      template:
        metadata:
          labels:
            app: ollama
        spec:
          containers:
            - name: ollama
              image: ollama/ollama:latest
              ports:
                - containerPort: 11434
              volumeMounts:
                - name: ollama-data
                  mountPath: /root/.ollama
              resources:
                requests:
                  cpu: "2"
                  memory: "8Gi"
                limits:
                  cpu: "4"
                  memory: "16Gi"
          volumes:
            - name: ollama-data
              persistentVolumeClaim:
                claimName: ollama-data
    apiVersion: v1
    kind: Service
    metadata:
      name: ollama
      namespace: ollama
    spec:
      selector:
        app: ollama
      ports:
        - name: http
          port: 11434
          targetPort: 11434

    3. Kustomize와 ArgoCD Application으로 묶습니다

    apiVersion: kustomize.config.k8s.io/v1beta1
    kind: Kustomization
    namespace: ollama
    resources:
      - namespace.yaml
      - pvc.yaml
      - deployment.yaml
      - service.yaml
    apiVersion: argoproj.io/v1alpha1
    kind: Application
    metadata:
      name: ollama
      namespace: argocd
    spec:
      project: default
      source:
        repoURL: https://git.example.com/platform.git
        targetRevision: main
        path: apps/ollama
      destination:
        server: https://kubernetes.default.svc
        namespace: ollama
      syncPolicy:
        automated:
          prune: true
          selfHeal: true
        syncOptions:
          - CreateNamespace=true
    1. Git 저장소에 Ollama 매니페스트를 커밋합니다.
    2. ArgoCD에 Application을 등록합니다.
    3. 첫 Sync 후 파드와 PVC가 정상 생성되는지 확인합니다.
    4. 그다음 모델 다운로드 전략을 별도로 붙입니다.
    ArgoCD Ollama 배포 설정과 동기화 구성을 표현한 이미지

    ArgoCD에서 애플리케이션이 Synced 상태로 보이고, Ollama Deployment와 PVC가 함께 연결된 구성을 확인하는 장면을 설명하는 이미지 자리입니다.

    4. 초기 검증 명령어

    kubectl get pods -n ollama
    kubectl get pvc -n ollama
    kubectl get svc -n ollama
    kubectl logs -n ollama deploy/ollama

    여기까지 오면 기본 배포는 끝입니다. 드디어 됐다! 싶죠. 근데 진짜 운영은 지금부터입니다 ㅎㅎ

    6개월 운영하면서 효과 컸던 최적화 전략

    이 섹션이 사실 핵심입니다. 단순 배포보다 중요한 건 계속 안정적으로 돌리는 법이거든요. 제가 직접 해보니 아래 네 가지가 체감이 제일 컸습니다.

    스토리지와 모델 캐시를 먼저 설계합니다

    Ollama는 모델 파일 크기 특성상 스토리지 전략이 중요합니다. 저는 초반에 스토리지를 임시 볼륨처럼 다뤘다가, 노드 교체 시 모델을 다시 받느라 시간을 꽤 날렸습니다. 그 뒤로는 모델 저장 경로를 PVC에 고정하고, 이미지 재배포와 모델 캐시를 분리했습니다.

    • PVC 고정: 파드가 재생성돼도 모델 캐시는 유지
    • 노드 디스크 여유 확인: 디스크 압박은 CPU 부족보다 더 먼저 터질 때가 많음
    • 백업 기준 마련: 모델 자체보다 설정과 프롬프트 자산 백업 기준 분리

    리소스 요청값은 보수적으로 시작합니다

    처음부터 크게 잡으면 클러스터 전체 밸런스가 깨집니다. 반대로 너무 작게 잡으면 파드가 뜨더라도 응답이 흔들립니다. 저는 초반에 메모리 요청값을 낮게 잡았다가, 다른 워크로드와 겹치는 시간대에 지연이 튀는 걸 봤습니다. 이후엔 실제 사용 패턴을 보고 천천히 올렸습니다.

    모델 프리로드는 배포 단계와 분리합니다

    이거 진짜 편하더라고요. 배포는 배포대로 끝내고, 모델 다운로드는 Job(잡, 일회성 실행 리소스)이나 운영 스크립트로 분리하니까 실패 지점이 줄었습니다. 특히 ArgoCD Ollama 배포를 여러 환경에 복제할 때 차이가 컸습니다.

    kubectl exec -n ollama deploy/ollama -- ollama pull llama3
    kubectl exec -n ollama deploy/ollama -- ollama list

    모델명은 실제 사용 환경에 맞게 바꾸시면 됩니다. 중요한 건 “어디에서 다운로드를 책임질지”를 명확히 하는 겁니다.

    Ingress와 프록시 타임아웃을 반드시 확인합니다

    LLM 요청은 일반 API보다 응답 시간이 길 수 있습니다. 그래서 Ingress나 리버스 프록시 설정이 보수적이면 중간에서 연결이 끊깁니다. 저는 처음에 앱이 느린 줄 알고 한참 봤는데, 실제 원인은 앞단 타임아웃이었습니다. 이런 건 로그를 함께 봐야 보입니다.

    ⚠️ 실제로 겪었던 문제와 해결법

    이 부분은 좀 현실적으로 적어보겠습니다. 문서만 보면 다 쉬워 보이는데, 운영에선 꼭 예상 밖 포인트가 나오더라고요.

    문제 1. 파드는 떴는데 모델이 매번 다시 내려받아졌습니다

    원인: 모델 저장 경로가 영구 볼륨에 제대로 붙지 않았거나, 다른 경로를 보고 있었습니다.

    해결: 컨테이너 내부 경로와 volumeMount를 다시 확인했습니다. 그리고 재배포 후에도 같은 PVC가 붙는지 꼭 확인했습니다.

    문제 2. ArgoCD는 Synced인데 실제 동작은 불안정했습니다

    원인: Git 기준 리소스 상태와 애플리케이션 런타임 상태는 다를 수 있습니다. Synced는 선언형 상태 일치이지, 성능 보장까지 해주진 않거든요.

    해결: readiness/liveness보다 먼저 실제 요청 테스트와 로그 수집을 붙였습니다. ArgoCD 상태만 보고 안심하면 안 됩니다.

    문제 3. 노드 이동 후 성능 체감이 달라졌습니다

    원인: 같은 Kubernetes라도 노드 디스크 성능, 메모리 여유, 다른 워크로드 간섭이 다릅니다.

    해결: nodeSelector(노드 셀렉터, 특정 노드 선택)나 taint/toleration(테인트/톨러레이션, 스케줄링 제어)을 검토했고, 최소한 LLM 워크로드가 너무 자주 이사 다니지 않게 잡았습니다.

    문제 4. 급한 핫픽스가 Git과 어긋났습니다

    원인: 운영 중 kubectl edit로 바로 고친 뒤 Git에 반영하지 않았습니다. 며칠 후 ArgoCD 재동기화에서 다시 원래 값으로 돌아가더라고요. 네, 이거 은근 자주 나옵니다.

    해결: 핫픽스 후 바로 Git PR로 반영하는 습관을 들였습니다. Kubernetes GitOps는 결국 Git이 진실 공급원(single source of truth)이니까요.

    ArgoCD Ollama 배포 트러블슈팅 흐름을 설명하는 이미지

    운영 중 자주 만나는 문제인 스토리지 마운트 오류, Git 드리프트, 프록시 타임아웃을 단계별로 추적하는 트러블슈팅 흐름을 설명하는 이미지 자리입니다.

    검증과 결과: 무엇을 기준으로 성공이라고 봤는가

    저는 “파드가 떴다”를 성공으로 보지 않았습니다. 진짜 중요한 건 재배포 후에도 동일하게 동작하는지, 그리고 운영자가 덜 불안한지였거든요.

    제가 보는 검증 체크리스트

    1. ArgoCD에서 애플리케이션이 지속적으로 Synced/Healthy로 유지되는가
    2. 파드 재생성 후에도 기존 모델 캐시가 유지되는가
    3. 간단한 추론 요청이 내부 네트워크에서 안정적으로 응답하는가
    4. 노드 변경이나 롤링 업데이트 후에도 서비스 재현성이 유지되는가
    5. 운영 변경 사항이 모두 Git commit으로 추적되는가
    kubectl rollout restart deploy/ollama -n ollama
    kubectl get pods -n ollama -w
    kubectl exec -n ollama deploy/ollama -- ollama list

    실제로 써보니까, 위 세 줄만으로도 꽤 많은 걸 확인할 수 있었습니다. 롤링 후 파드가 다시 뜨고, 기존 모델이 그대로 보이면 일단 큰 산은 넘은 겁니다. 여기에 사내 서비스나 실험용 앱에서 실제 API 호출까지 붙여보면 더 좋고요.

    ArgoCD Ollama 배포 운영 결과와 안정성을 보여주는 대시보드 이미지

    재배포 이후에도 Ollama 모델 캐시가 유지되고, ArgoCD와 Kubernetes 상태가 안정적으로 보이는 운영 결과 대시보드 이미지 자리입니다.

    운영 관점에서 느낀 장단점

    장점은 명확합니다. ArgoCD Ollama 배포 구조를 한 번 정리해 두면 환경 복제와 복구가 빨라집니다. 특히 여러 사람이 만지는 환경에서는 “누가 뭘 바꿨는지”가 보이는 것만으로도 가치가 큽니다.

    • 장점: 선언형 관리, 재현성, 운영 표준화, 장애 복구 속도
    • 단점: 스토리지와 네트워크를 모르면 초반 진입 장벽이 있음
    • 주의점: Synced 상태와 서비스 품질은 별개라서 모니터링이 반드시 필요

    반대로 단점도 있습니다. 작은 단일 서버 환경에서는 오히려 Kubernetes가 과할 수 있습니다. 그래서 저는 항상 “정말 GitOps가 필요한 규모인가”를 먼저 봅니다. 혼자 잠깐 실험하는 정도라면 Docker Compose로 시작하는 게 더 낫기도 합니다. 하지만 팀이 붙고, 재현성이 필요하고, LLM 클라우드 실험을 계속 이어갈 생각이라면 이야기가 달라집니다.

    정리와 다음 단계

    정리하자면, 6개월 운영 기준으로 가장 중요했던 건 세 가지였습니다. 스토리지 고정, Git 기준 운영, 배포와 모델 관리를 분리. 이 세 가지만 지켜도 안정감이 꽤 올라갑니다. 저도 처음엔 이것저것 한 번에 자동화하려다가 삽질 좀 했습니다 ㅎㅎ 근데 결국 오래 살아남는 구성은 단순하고, 역할이 분리된 구성이더라고요.

    혹시 지금 ArgoCD로 LLM 워크로드를 올리려는 중이신가요? 그렇다면 먼저 작은 범위로 시작해 보세요. Ollama 하나, PVC 하나, Service 하나부터요. 그리고 동작이 확인되면 그다음에 Ingress, 인증, 모니터링을 붙이시면 됩니다. 이전 글에서 다룬 Kubernetes 스토리지 운영 팁과도 연결되는 부분이고, 다음 글에서는 ArgoCD Ollama 배포 뒤에 인증 프록시와 관측성(observability, 관측 가능성) 붙이는 이야기도 정리해보겠습니다.

    배포 전후 운영 복잡도, 모델 캐시 유지 여부, GitOps 적용 효과를 한눈에 비교하는 요약 인포그래픽 이미지 자리입니다.

    자주 묻는 질문

    Q. Ollama를 Kubernetes에 꼭 올려야 하나요?

    아닙니다. 단일 사용자, 단일 서버라면 더 단순한 방법이 맞을 수 있습니다. 다만 재현성과 팀 협업이 중요해지면 Kubernetes와 GitOps가 힘을 발휘합니다.

    Q. GPU가 없으면 의미가 없나요?

    꼭 그렇진 않습니다. 다만 모델 크기와 응답 기대치에 따라 체감이 다릅니다. 저는 처음 검증은 CPU 환경부터 시작했고, 그 과정에서 오히려 스토리지와 운영 흐름을 먼저 정리할 수 있었습니다.

    Q. 운영 후기 기준으로 가장 먼저 볼 지표는 뭔가요?

    저는 순서가 이렇습니다. 파드 상태, PVC 유지 여부, 실제 요청 성공, 재배포 후 재현성. 화려한 대시보드보다 이 네 가지가 먼저입니다.

  • [OpenStack] OpenStack에서 Ollama로 프라이빗 LLM 추론 환경 구축하기

    [OpenStack] OpenStack에서 Ollama로 프라이빗 LLM 추론 환경 구축하기

    [OpenStack] OpenStack과 Ollama로 프라이빗 LLM 추론 환경 구축하기

    OpenStack 인스턴스에 Ollama를 올려서 프라이빗 LLM 추론 환경을 만드는 이야기는 요즘 꽤 자주 나오더라고요. 저도 홈랩이랑 업무성 테스트 환경을 오가면서 이것저것 붙여봤는데, 공개 SaaS에 바로 데이터를 넣기 애매한 상황에서는 Ollama OpenStack 조합이 생각보다 실용적이었습니다. 특히 로그, 운영 문서, 내부 위키처럼 외부 반출이 조심스러운 데이터를 다룰 때는 더 그렇고요. 혹시 ‘GPU는 비싸고, 그렇다고 완전 관리형 서비스만 믿기엔 불안하다’ 같은 고민 해보신 적 있으신가요? 저는 딱 그 지점에서 이 구성을 꽤 오래 만지작거렸습니다.

    이번 글은 특정 벤더 홍보가 아니라, OpenStack AI 실험을 실제 인프라 관점에서 어떻게 굴려볼 수 있는지 정리한 사례입니다. 처음엔 이게 뭔가 싶었는데, 막상 해보니 구조는 단순합니다. OpenStack 가상머신 위에 Ollama를 올리고, 모델을 내려받고, 네트워크와 스토리지, 보안그룹만 제대로 잡아주면 됩니다. 다만 여기서 중요한 포인트가 몇 개 있습니다. CPU만으로도 테스트는 되지만, 추론 속도와 동시성은 기대치를 잘 관리해야 하거든요.

    Ollama OpenStack 기반 프라이빗 LLM 아키텍처 다이어그램

    OpenStack 기반 프라이빗 LLM 아키텍처를 한눈에 보여주는 개요 이미지입니다.

    1. 왜 굳이 OpenStack에 Ollama를 올렸을까

    쉽게 말해 Ollama는 로컬이나 서버에서 대형 언어 모델을 비교적 간단하게 실행하게 도와주는 런타임(runtime, 실행 환경)입니다. 반면 OpenStack은 가상머신, 네트워크, 볼륨 같은 인프라 자원을 묶어서 운영할 수 있게 해주는 IaaS(Infrastructure as a Service, 서비스형 인프라) 플랫폼이고요. 둘을 합치면 뭐가 좋으냐면, 프라이빗 LLM 실험 환경을 내가 통제하는 네트워크 안에서 만들 수 있습니다.

    제가 직접 해보니 이 조합의 장점은 아래처럼 정리되더라고요.

    • 데이터 통제: 추론 요청과 응답이 내부 네트워크에 머물 수 있습니다.
    • 배포 유연성: 테스트용 인스턴스와 운영성 인스턴스를 분리하기 쉽습니다.
    • 복제 가능성: 스냅샷(snapshot, 시점 복사)이나 이미지 기반으로 재현이 편합니다.
    • 네트워크 제어: 보안그룹(Security Group, 가상 방화벽)과 내부망만으로 노출 범위를 제한할 수 있습니다.
    • 확장 여지: 나중에 API Gateway, Reverse Proxy, 모니터링을 붙이기 좋습니다.

    반대로 단점도 있습니다. Ollama 자체는 비교적 쉽게 뜨는데, 모델 파일이 크고 디스크 I/O나 메모리 조건을 꽤 타는 편입니다. 그리고 OpenStack 쪽에서 Floating IP, 내부망, 볼륨 연결, 이미지 준비 같은 기본기가 안 되어 있으면 이상하게 자꾸 삽질하게 됩니다. 저도 처음엔 애플리케이션 문제가 아니라 네트워크 정책 때문에 응답이 안 와서 한참 헤맸거든요 ㅎㅎ

    2. Ollama OpenStack 구성 개념 쉽게 이해하기

    이 구성을 너무 어렵게 볼 필요는 없습니다. 전체 흐름은 이렇습니다.

    1. OpenStack에서 Ubuntu 계열 Linux 인스턴스를 하나 만듭니다.
    2. 필요하면 Block Storage(블록 스토리지) 볼륨을 따로 붙입니다.
    3. 서버에 Ollama를 설치합니다.
    4. 원하는 모델을 내려받아 로드합니다.
    5. 보안그룹과 Reverse Proxy(리버스 프록시, 요청 전달기)를 붙여 내부 사용자만 접근하게 합니다.
    6. curl이나 간단한 앱에서 API 호출로 검증합니다.

    여기서 핵심은 모델 실행 위치와 접근 제어입니다. 모델은 인스턴스 안에서 돌고, 사용자는 HTTP API로 붙습니다. 즉, AI 서비스처럼 보이지만 사실은 내부 애플리케이션 하나 더 배포하는 느낌에 가깝습니다. 그래서 인프라 엔지니어 입장에서는 웹 애플리케이션 운영하듯 접근하면 편합니다.

    구성 요소 역할 운영 포인트
    OpenStack Instance Ollama 실행 서버 vCPU, RAM, 디스크 여유 확인
    Volume 모델 파일 저장 루트 디스크와 분리 시 관리 편함
    Security Group 접근 제어 22, 11434 등 최소 포트만 허용
    Private Network 내부 통신 내부 서비스 전용망 권장
    Reverse Proxy TLS, 접근 경로 정리 Nginx 등으로 앞단 보호
    Ollama 모델 추론 런타임 모델 다운로드와 실행 담당

    3. 배포 전에 체크할 현실적인 준비 사항

    이 단계 무시하면 나중에 꼭 되돌아오게 됩니다. 실제로 써보니까 아래 세 가지가 제일 중요했습니다.

    3-1. 컴퓨트 리소스 계획

    정확한 수치는 환경마다 달라서 함부로 말하면 안 되지만, 적어도 메모리 여유는 넉넉하게 잡는 게 좋습니다. 작은 모델 테스트와 실서비스성 사용은 체감 차이가 큽니다. CPU-only 환경은 검증용으로는 괜찮아도, 응답 지연이 길어질 수 있습니다. GPU 패스스루(passthrough, 장치 직접 할당)나 vGPU를 쓰는 환경이라면 OpenStack 쪽 설정 난이도가 확 올라가니, 처음에는 CPU 기반 검증 후 확장하는 편이 안전합니다.

    3-2. 스토리지 분리

    모델 파일은 금방 용량을 먹습니다. 그래서 루트 디스크에 다 넣기보다 별도 볼륨을 붙여서 /var/lib/ollama 같은 경로를 분리하는 방식이 운영상 편했습니다. 백업, 확장, 재배포가 훨씬 수월하거든요.

    3-3. 보안 기준

    Ollama API를 외부에 바로 열어두는 건 추천하지 않습니다. 적어도 다음은 챙기세요.

    • 내부망 우선 배치
    • 보안그룹 최소 허용
    • SSH 키 기반 로그인
    • 필요 시 Nginx로 TLS 종료
    • 로그와 요청 이력 점검

    여기서 중요한 포인트! 프라이빗 LLM이라고 해서 자동으로 안전해지는 건 아닙니다. 외부 SaaS 대신 내부에 둔다는 의미일 뿐, 접근 제어를 대충 하면 오히려 더 위험해질 수 있습니다.

    4. 실전 구현: OpenStack 인스턴스에 Ollama 설치

    이제 본격적으로 해보겠습니다. 아래 예시는 Ubuntu 계열 Linux 인스턴스를 기준으로 정리했습니다. 저는 보통 먼저 인스턴스를 띄우고, 볼륨 붙이고, 방화벽부터 확인한 다음 애플리케이션을 올립니다. 순서를 바꾸면 나중에 원인 분석이 꼬이더라고요.

    4-1. 보안그룹과 인스턴스 준비

    필수 포트는 최소한으로만 엽니다. SSH용 22 포트, 그리고 내부 호출이 필요하면 Ollama 기본 포트로 알려진 11434를 내부 대역에만 허용하는 식이 무난합니다.

    # 예시: 서버 접속 후 기본 점검
    uname -a
    lsblk
    ip a
    sudo timedatectl set-timezone Asia/Seoul

    볼륨을 별도로 붙였다면 먼저 마운트합니다.

    sudo mkfs.ext4 /dev/vdb
    sudo mkdir -p /data/ollama
    sudo mount /dev/vdb /data/ollama
    sudo blkid /dev/vdb

    /etc/fstab에 UUID 기준으로 등록해두면 재부팅 후에도 안정적입니다.

    sudo cp /etc/fstab /etc/fstab.bak
    sudo editor /etc/fstab
    UUID=YOUR_VOLUME_UUID  /data/ollama  ext4  defaults,nofail  0  2

    4-2. Ollama 설치

    공식 설치 방식은 시점에 따라 바뀔 수 있으니 실제 배포 전에는 공식 문서를 꼭 같이 확인하시는 걸 권장합니다. 다만 큰 흐름은 비슷합니다. 서버에 패키지를 설치하고 서비스로 띄우는 구조입니다.

    curl -fsSL https://ollama.com/install.sh | sh
    sudo systemctl enable ollama
    sudo systemctl status ollama

    설치 후 서비스가 떠 있는지 먼저 확인하세요. 여기서 안 뜨면 모델 문제 보기 전에 서비스 로그부터 보는 게 맞습니다.

    sudo journalctl -u ollama -n 100 --no-pager
    OpenStack 인스턴스에서 Ollama 배포 구성을 설명하는 이미지

    배포 과정 중 네트워크와 스토리지, 서비스 구성을 설명하는 이미지입니다.

    4-3. 데이터 경로 분리

    모델 저장 경로를 별도 볼륨으로 빼고 싶다면 서비스 환경 변수를 조정하는 식으로 운영할 수 있습니다. 배포 방식에 따라 경로 정의가 다를 수 있어서 저는 서비스 오버라이드 방식으로 처리하는 편입니다.

    sudo mkdir -p /data/ollama/models
    sudo systemctl edit ollama
    [Service]
    Environment="OLLAMA_MODELS=/data/ollama/models"
    Environment="OLLAMA_HOST=0.0.0.0:11434"
    sudo systemctl daemon-reload
    sudo systemctl restart ollama
    sudo systemctl show ollama --property=Environment

    여기서 OLLAMA_HOST를 0.0.0.0으로 열었다면, 네트워크 레벨에서 반드시 접근 대역을 제한하세요. 애플리케이션이 열려 있다는 건 생각보다 금방 스캔됩니다.

    4-4. 모델 다운로드와 실행

    모델 이름은 시점마다 추가되거나 바뀔 수 있으니, 실제 사용 시에는 현재 지원 목록을 직접 확인하셔야 합니다. 이 글에서는 특정 최신 모델명을 무리하게 적기보다, 일반적인 사용 흐름 위주로 보겠습니다.

    ollama pull llama3
    ollama list
    ollama run llama3

    제가 직접 해보니 처음 실행은 모델 준비 때문에 시간이 걸릴 수 있습니다. 이때 ‘멈췄나?’ 싶어서 여러 번 다시 치면 오히려 꼬입니다. 디스크 사용량과 네트워크 다운로드 상태를 같이 보면서 기다리는 게 낫습니다.

    4-5. API 호출 테스트

    Ollama는 HTTP API 기반으로 붙이기 쉬운 편입니다. 간단한 curl 테스트부터 해보면 감이 금방 옵니다.

    curl http://127.0.0.1:11434/api/generate \
      -H "Content-Type: application/json" \
      -d '{
        "model": "llama3",
        "prompt": "OpenStack 환경에서 프라이빗 LLM을 운영할 때 주의할 점 3가지를 설명해줘.",
        "stream": false
      }'

    내부 다른 서버에서 붙일 거라면 127.0.0.1 대신 인스턴스의 프라이빗 IP를 사용하면 됩니다. 다만 이 경우 보안그룹과 OS 방화벽을 같이 확인하세요.

    5. Ollama와 Reverse Proxy로 운영 편의성 높이기

    실무 느낌으로 가려면 앞단에 Reverse Proxy를 두는 게 편합니다. Nginx를 붙이면 TLS 종료, 접근 경로 통합, 간단한 접근 제어가 가능하거든요. 나중에 인증 프록시나 API Gateway로 확장하기도 좋습니다.

    sudo apt update
    sudo apt install -y nginx
    server {
        listen 80;
        server_name ollama.internal;
    
        location / {
            proxy_pass http://127.0.0.1:11434;
            proxy_http_version 1.1;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }
    }
    sudo nginx -t
    sudo systemctl reload nginx

    여기까지 오면 내부 DNS나 /etc/hosts로 이름을 붙여서 접근하기도 편해집니다. 작은 차이 같아도 운영성은 꽤 올라갑니다. 특히 여러 추론 서버를 비교 테스트할 때요.

    6. ⚠️ 실제 겪었던 문제와 트러블슈팅

    이 섹션은 좀 현실적으로 적어볼게요. 저는 이 작업하면서 애플리케이션보다 인프라 쪽에서 더 많이 막혔습니다.

    6-1. 포트는 열었는데 접속이 안 되는 문제

    처음엔 분명 11434를 열었는데 외부에서 응답이 없었습니다. 알고 보니 셋 중 하나였습니다.

    • 서비스가 127.0.0.1에만 바인딩됨
    • OpenStack 보안그룹에는 열었지만 OS 방화벽이 차단
    • Floating IP가 아닌 내부망 전용 인스턴스라 접근 경로 자체가 다름

    해결은 단순합니다. ss -lntp, ufw status, 보안그룹 규칙을 순서대로 확인하면 됩니다.

    ss -lntp | grep 11434
    sudo ufw status
    ip route

    6-2. 디스크 공간 부족

    작은 테스트 VM에서 시작했다가 모델을 몇 개만 내려받아도 금방 공간이 줄어듭니다. 이건 진짜 많이 겪는 문제예요. 루트 디스크를 아끼겠다고 너무 작게 잡으면 결국 다시 옮기게 됩니다. 그래서 초반부터 모델 저장 경로를 분리하는 걸 추천드립니다.

    6-3. 응답 속도가 너무 느린 문제

    이건 대부분 버그가 아니라 리소스 문제입니다. CPU 기반에서는 특히 그렇습니다. 프롬프트가 길거나 동시에 여러 요청이 들어오면 체감이 확 느려집니다. 저도 처음엔 설정이 잘못된 줄 알았는데, 실제로는 기대치를 조정해야 하는 영역이더라고요. 검증 목적과 운영 목적을 구분해서 보셔야 합니다.

    6-4. 재부팅 후 경로가 꼬이는 문제

    볼륨 마운트를 수동으로만 해두면 재부팅 뒤 서비스가 이상한 위치를 바라보는 경우가 있습니다. 꼭 fstab와 systemd 서비스 환경 변수를 함께 확인하세요. 이거 한 번 놓치면 ‘어제 됐는데 왜 오늘 안 되지?’ 모드 들어갑니다 ㅎㅎ

    Ollama OpenStack API 테스트와 프록시 검증 운영 이미지

    API 테스트와 프록시 구성을 검증하는 실제 운영 흐름을 보여주는 이미지입니다.

    7. 검증과 결과 확인

    구축이 끝났으면 이제 ‘떠 있다’가 아니라 ‘쓸 수 있다’를 확인해야 합니다. 저는 보통 아래 순서로 검증합니다.

    1. 서비스 상태 확인
    2. 로컬 API 호출 확인
    3. 내부망 다른 서버에서 호출 확인
    4. 리소스 사용량 확인
    5. 로그 확인
    systemctl status ollama
    curl http://127.0.0.1:11434/api/tags
    curl http://YOUR_PRIVATE_IP:11434/api/tags
    free -h
    df -h
    sudo journalctl -u ollama -n 50 --no-pager

    응답이 정상이고, 모델 목록이 보이고, 간단한 프롬프트가 처리되면 1차 검증은 통과입니다. 여기서 한 걸음 더 나가면 Prometheus(프로메테우스, 메트릭 수집기)나 Grafana(그라파나, 대시보드 도구) 같은 모니터링 체계를 붙이는 것도 좋습니다. 아직 이 글에서는 거기까지 깊게 다루진 않지만, 다음 글에서 OpenStack AI 운영 관점의 모니터링도 다뤄볼 예정입니다.

    간단한 체크리스트도 남겨보겠습니다.

    • ✅ 인스턴스 재부팅 후 서비스 자동 시작 확인
    • ✅ 모델 저장 경로가 의도한 볼륨인지 확인
    • ✅ 내부 대역 외 접근 차단 확인
    • ✅ 테스트 프롬프트 응답 정상 확인
    • ✅ 로그에 반복 오류 없는지 확인

    드디어 됐다! 싶은 순간은 사실 OpenStack 인스턴스가 뜨는 순간이 아니라, 재부팅 후에도 똑같이 잘 동작할 때입니다. 이건 진짜 운영해보면 공감하실 겁니다.

    OpenStack AI 환경에서 Ollama 결과 검증을 보여주는 대시보드 이미지

    구축 완료 후 상태 점검과 결과 검증을 시각적으로 보여주는 이미지입니다.

    8. 어떤 환경에 특히 잘 맞는가

    모든 곳에 이 구성이 정답은 아닙니다. 하지만 아래 같은 경우에는 꽤 잘 맞습니다.

    사용 상황 적합도 이유
    내부 문서 요약/검색 보조 높음 데이터 외부 반출 부담을 줄이기 좋음
    개발팀 실험용 AI 추론 환경 높음 빠르게 띄우고 지우기 쉬움
    고성능 대규모 실시간 서비스 중간 리소스 계획과 확장 설계가 더 중요함
    완전 비관리형 개인 테스트 높음 홈랩과 사내 테스트베드에 잘 맞음

    사실 저는 이 구성을 ‘최종 답안’보다는 프라이빗 LLM 운영 감각을 익히는 출발점으로 봅니다. 나중에는 컨테이너 기반으로 옮기거나, 쿠버네티스 위에 올리거나, 인증 계층을 붙이거나, 모델 라우팅을 나누는 식으로 진화할 수 있거든요.

    9. 정리하며: OpenStack AI 첫걸음으로는 꽤 괜찮았습니다

    Ollama OpenStack 조합은 화려하진 않지만, 인프라 엔지니어 입장에서 이해하기 쉽고 제어하기 편한 방식입니다. 제가 직접 해보니 핵심은 세 가지였습니다. 리소스 계획, 스토리지 분리, 그리고 접근 제어입니다. 이 셋만 제대로 잡아도 절반은 성공입니다.

    처음엔 단순히 ‘내부망에서 LLM 한 번 돌려보자’ 정도로 시작했었는데, 실제로 써보니까 운영 포인트가 꽤 명확했습니다. 특히 OpenStack을 이미 쓰고 있는 조직이라면 기존 VM 운영 경험을 그대로 가져올 수 있다는 게 큽니다. 반대로, 모델 성능 자체를 극한까지 뽑아내는 목적이라면 별도 GPU 전략과 오케스트레이션 설계가 더 필요하겠죠.

    혹시 지금 AI 추론 환경을 사내에 조용히 검증해보고 싶으셨다면, 이 방식부터 시작해보셔도 좋겠습니다. 이전 글에서 다뤘던 스토리지와 네트워크 기본기와도 연결되는 내용이고, 다음 글에서는 인증 프록시를 붙여 여러 팀이 함께 쓰는 형태까지 이어서 정리해보겠습니다. 여기서 중요한 포인트는 거창한 아키텍처보다, 작게 시작해서 반복 가능하게 만드는 것입니다. 그게 결국 오래 가더라고요. 🎉

    프라이빗 LLM 구축 단계와 운영 체크포인트 요약 이미지

    구축 절차와 운영 체크포인트를 한 장으로 정리한 요약 이미지입니다.

  • [AI] Ollama 비용 비교: 로컬 AI vs 클라우드 API 실측 분석

    [AI] Ollama 비용 비교: 로컬 AI vs 클라우드 API 실측 분석

    [AI 운영] Ollama 비용 비교: 로컬 AI vs 클라우드 API

    로컬 AI를 붙여볼까, 아니면 그냥 API로 갈까. 이 고민 한 번쯤 해보셨을 겁니다. 저도 홈랩에서 이것저것 붙여 보다가 Ollama 비용이 생각보다 단순하지 않다는 걸 꽤 늦게 깨달았거든요. 처음엔 “로컬은 공짜 아니야?”라고 생각했는데, 실제로 써보니까 하드웨어 감가상각, 전력, 운영 시간, 장애 대응까지 다 합쳐서 봐야 하더라고요. 반대로 클라우드 API는 비싸 보이지만, 잘 쓰면 운영 부담이 거의 없어서 총비용(TCO, Total Cost of Ownership) 기준으로는 더 낫기도 합니다.

    이 글은 제가 13년차 인프라 엔지니어로서 실제 운영 관점에서 정리한 비교입니다. 특정 벤치마크 숫자를 억지로 붙이기보다, 어떻게 측정하고 어떤 기준으로 판단해야 하는지에 집중하겠습니다. 특히 로컬 LLM, Claude API 비용, 그리고 흔히 오해하기 쉬운 AI 운영 비용까지 같이 보겠습니다.

    Ollama 비용 비교를 위한 로컬 서버와 클라우드 API 아키텍처 개요 이미지

    로컬 추론 서버, 사내 애플리케이션, 외부 클라우드 API가 어떻게 연결되는지 한 장으로 보여주는 개요 이미지입니다.

    1. 왜 다들 Ollama 비용에서 헷갈릴까요?

    쉽게 말해, 로컬은 토큰당 과금이 안 보일 뿐이지 비용이 없는 게 아닙니다. 반대로 클라우드는 청구서가 너무 잘 보여서 비싸게 느껴지는 거고요. 제가 처음엔 이 부분에서 삽질 좀 했습니다 ㅎㅎ 눈앞에 보이는 건 API 청구서뿐인데, 실제로는 집이나 사무실에 있는 장비가 계속 전기를 먹고 있고, 디스크도 차고, 백업도 해야 하고, 장애 나면 내가 직접 봐야 하거든요.

    • 로컬 AI(Ollama): 토큰 과금 대신 하드웨어, 전력, 운영 인건비가 들어갑니다.
    • 클라우드 API: 초기 투자 없이 바로 쓰지만, 사용량이 늘면 월 비용이 빠르게 올라갑니다.
    • 핵심 포인트: 둘 중 뭐가 싼지는 “감정”이 아니라 “트래픽 패턴”으로 결정됩니다.

    2. 로컬 LLM vs 클라우드 API, 개념을 아주 쉽게 풀어보면

    Ollama는 오픈 웨이트(open weights, 공개 배포 모델)를 로컬에서 쉽게 실행하게 해주는 러너(runner)라고 보시면 됩니다. 설치가 간단하고, 모델을 pull 해서 바로 돌릴 수 있어서 입문 장벽이 낮습니다. 제가 직접 써보니 개발 PC나 홈랩에서 빠르게 검증할 때 정말 편하더라고요.

    반면 클라우드 API는 모델 자체를 직접 운영하지 않고, 요청(request)과 응답(response)에 대해 비용을 내는 구조입니다. 예를 들어 Anthropic의 Claude API는 공식 가격 페이지 기준으로 모델별 입력 토큰(input token)과 출력 토큰(output token) 단가가 분리되어 있습니다.

    항목 Ollama 로컬 실행 클라우드 API
    초기비용 장비가 필요함 거의 없음
    월비용 구조 전력, 감가상각, 운영비 토큰 사용량 기반
    확장성 장비 한계에 좌우 상대적으로 쉬움
    보안/격리 오프라인 운영 가능 정책 검토 필요
    운영 난이도 직접 관리 낮은 편

    여기서 중요한 포인트!

    Ollama NPU 같은 키워드 때문에 “NPU만 있으면 로컬 AI가 무조건 유리하다”라고 생각하시는 분도 있는데요, 실제 운영에서는 모델 크기, 메모리 용량, 메모리 대역폭, 동시 요청 수가 더 크게 체감됩니다. 저도 처음엔 가속기 종류만 보다가, 나중에 병목이 저장소가 아니라 메모리 쪽이라는 걸 체감했었습니다.

    3. Ollama 비용 계산은 이렇게 해야 덜 틀립니다

    제가 권하는 방식은 아주 단순합니다. 로컬은 월 고정비처럼 보고, 클라우드는 사용량 기반 변동비처럼 보시면 됩니다.

    로컬 AI 운영 비용 계산식

    1. 장비 구매비를 사용 예정 개월 수로 나눕니다.
    2. 월 전력 비용을 더합니다.
    3. 스토리지, 백업, 모니터링 같은 부대비용을 더합니다.
    4. 운영 시간까지 돈으로 환산할지 결정합니다.
    월 로컬 비용 = (장비 구매비 / 사용 개월 수) + 월 전력비 + 부대비용 + 운영 인건비(선택)

    예를 들어 개발팀에서 내부 문서 검색 보조나 코드 요약처럼 예측 가능한 고정 부하가 있다면, 로컬이 생각보다 유리해질 수 있습니다. 반대로 요청이 들쑥날쑥하고 야간 피크가 큰 서비스라면 장비를 놀리는 시간이 많아져서 비효율이 생깁니다.

    Claude API 비용 계산식

    Anthropic 공식 가격 페이지를 보면 Claude Sonnet 4.6은 입력 1MTok당 $3, 출력 1MTok당 $15이고, Claude Haiku 4.5는 입력 1MTok당 $1, 출력 1MTok당 $5입니다. 여기서 중요한 건 입력과 출력이 따로 과금된다는 점입니다.

    월 API 비용 = (월 입력 토큰 / 1,000,000 × 입력 단가) + (월 출력 토큰 / 1,000,000 × 출력 단가)

    이 계산식만 붙여도 Claude API 비용 감이 꽤 빨리 옵니다. 특히 프롬프트가 길거나, RAG(Retrieval-Augmented Generation, 검색증강생성)로 문서를 많이 붙이는 구조라면 입력 토큰이 생각보다 많이 나옵니다.

    4. 실전 구현: 로컬 Ollama와 클라우드 API를 같은 기준으로 재보기

    비교는 공정해야 합니다. 제가 보통 맞추는 기준은 4개입니다. 같은 작업 유형, 비슷한 길이의 프롬프트, 같은 동시성, 같은 로그 포맷. 이 4개가 안 맞으면 숫자가 예쁘게 나와도 의미가 없습니다.

    1. 로컬에 Ollama를 설치합니다.
    2. 테스트용 모델을 하나 내려받습니다.
    3. 동일 프롬프트로 로컬과 API를 각각 호출합니다.
    4. 지연시간(latency, 응답 지연), 실패율, 토큰 사용량을 같은 형식으로 남깁니다.
    curl -fsSL https://ollama.com/install.sh | sh
    ollama pull qwen2
    ollama run qwen2

    설치는 정말 빠릅니다. 근데 여기서 끝이 아니더라고요. 실무에서는 “잘 실행된다”보다 “반복 호출해도 안정적인가”가 더 중요합니다.

    로컬 LLM 구성에서 Ollama 비용과 자원 사용 흐름을 보여주는 이미지

    Ollama 설치 이후 모델 다운로드, 로컬 추론, 애플리케이션 호출 흐름을 단계별로 보여주는 구성 이미지입니다.

    같은 프롬프트를 보내는 간단한 테스트 예시

    import os
    import time
    import requests
    
    PROMPT = "사내 장애 보고서를 5줄로 요약하고, 후속 조치 3가지를 제안해 주세요."
    
    def test_ollama():
        started = time.time()
        r = requests.post(
            "http://localhost:11434/api/generate",
            json={"model": "qwen2", "prompt": PROMPT, "stream": False},
            timeout=120,
        )
        elapsed = time.time() - started
        return {"target": "ollama", "status": r.status_code, "elapsed_sec": round(elapsed, 2)}
    
    def test_claude():
        started = time.time()
        r = requests.post(
            "https://api.anthropic.com/v1/messages",
            headers={
                "x-api-key": os.environ["ANTHROPIC_API_KEY"],
                "anthropic-version": "2023-06-01",
                "content-type": "application/json",
            },
            json={
                "model": "claude-sonnet-4-6",
                "max_tokens": 300,
                "messages": [{"role": "user", "content": PROMPT}],
            },
            timeout=120,
        )
        elapsed = time.time() - started
        return {"target": "claude_api", "status": r.status_code, "elapsed_sec": round(elapsed, 2)}
    
    print(test_ollama())
    print(test_claude())

    이 정도만 돌려도 감이 옵니다. 로컬은 장비 상태 영향을 많이 받고, 클라우드는 네트워크 왕복이 있지만 운영은 단순합니다.

    5. ⚠️ 주의사항: 제가 실제로 자주 부딪힌 문제들

    1) 로컬은 “무료”가 아니라 “숨은 비용”이 많습니다

    가장 흔한 오해입니다. Ollama 비용을 0원처럼 보면 의사결정이 틀어집니다. 디스크가 꽉 차거나 모델 캐시가 꼬이면 정리 시간이 들어가고, 백업 정책 없으면 장애 복구도 직접 해야 합니다.

    2) 모델 성능 비교를 제품 간 단순 비교로 하면 안 됩니다

    같은 작업이라도 로컬 모델과 상용 API 모델은 튜닝 상태, 컨텍스트 길이, 응답 품질이 다릅니다. 그래서 저는 “정답률” 하나만 보지 않고 아래 항목을 같이 봅니다.

    • 응답 품질 일관성
    • 지연시간 편차
    • 실패 재시도 비율
    • 운영자가 손대야 하는 빈도

    3) Ollama NPU만 보고 설계하면 낭패 보기 쉽습니다

    이건 특히 노트북 기반 테스트에서 많이 보입니다. NPU가 있더라도 모든 워크로드가 자동으로 유리해지는 건 아닙니다. 실제로는 모델 메모리 요구사항과 드라이버 성숙도, 배치(batch, 일괄 처리) 특성이 더 중요할 때가 많았습니다.

    4) 클라우드는 프롬프트 설계가 곧 비용 절감입니다

    제가 써보니까 API 쪽은 인프라보다 프롬프트 정리가 더 큰 절감 포인트인 경우가 많았습니다. 시스템 프롬프트를 너무 길게 쓰거나, RAG 문서를 매번 과하게 붙이면 비용이 금방 올라갑니다.

    6. 검증/결과: 무엇을 보면 판단이 빨라질까요?

    벤치마크 툴을 거창하게 만들 필요는 없습니다. 아래 5가지만 수집해도 충분합니다.

    1. 평균 지연시간과 p95 지연시간
    2. 실패율과 재시도 횟수
    3. 월 입력/출력 토큰
    4. 동시 요청 수 증가 시 품질 저하 여부
    5. 운영자가 개입한 시간

    저는 여기서 마지막 항목을 꼭 봅니다. 왜냐하면 AI 운영 비용은 서버 비용만이 아니라, 결국 사람 시간까지 포함해서 봐야 하거든요.

    Ollama 비용과 Claude API 비용을 비교하는 운영 대시보드 이미지

    응답 지연, 실패율, 토큰 사용량, 추정 월 비용을 한 번에 비교하는 운영 대시보드 이미지입니다.

    상황 로컬 Ollama가 유리한 경우 클라우드 API가 유리한 경우
    보안 오프라인 또는 내부망 우선 외부 반출 정책 검토 가능
    트래픽 예측 가능한 고정 사용량 변동 폭이 큼
    운영 인력 직접 관리 가능 인프라 운영 여력이 적음
    초기 도입 실험 장비가 이미 있음 빠른 PoC가 필요함
    확장 제한적 상대적으로 유연함

    정리하면 이렇습니다. Ollama 비용은 장기적이고 예측 가능한 내부 업무에 잘 맞고, Claude API 비용은 초기 투자 없이 빠르게 시작해야 하는 팀에 잘 맞습니다. 어느 쪽이 무조건 낫다기보다, 트래픽 곡선과 운영 역량이 답을 정해 줍니다.

    7. 자주 묻는 질문

    Q1. 작은 팀도 로컬 LLM을 바로 도입할 만한가요?

    가능은 합니다. 다만 장비보다 먼저 운영 목표를 정하시는 게 좋습니다. 사내 요약, 분류, 초안 작성처럼 반복 업무가 명확하면 훨씬 판단이 쉽습니다.

    Q2. API 비용이 무서운데, 바로 로컬로 가야 할까요?

    꼭 그렇진 않습니다. 제가 추천하는 순서는 보통 API로 빠르게 검증한 뒤, 사용 패턴이 굳으면 그때 로컬 이전을 검토하는 방식입니다. 이게 실패 비용이 낮더라고요.

    Q3. 실측 분석은 얼마나 돌려봐야 믿을 수 있나요?

    최소한 평일 업무 시간대와 야간 시간대는 나눠서 보시는 걸 권합니다. 짧게 한두 번 돌려서는 운영 현실이 잘 안 보입니다.

    8. 마무리: 결론은 “누가 더 싼가”가 아니라 “내 패턴에 뭐가 맞는가”입니다

    처음엔 저도 로컬이면 무조건 이득일 줄 알았습니다. 근데 실제로 써보니까, 운영 가능한 로컬과 그냥 돌아가는 로컬은 완전히 다른 이야기더라고요. 반대로 클라우드 API도 비싸 보이지만, 운영 복잡도를 줄여 준다는 점에서 값어치를 할 때가 분명히 있습니다.

    그래서 제 기준은 이겁니다. 고정 부하, 데이터 통제, 반복 업무면 Ollama 쪽을 먼저 보고, 빠른 검증, 유연한 확장, 낮은 운영 부담이면 클라우드 API를 먼저 봅니다. 혹시 지금 막 비교 중이시라면, 장비 스펙부터 보지 마시고 먼저 한 달 사용량과 프롬프트 길이부터 적어 보세요. 그게 제일 빨랐습니다.

    Ollama 비용 기준으로 로컬 AI와 클라우드 API 선택 포인트를 정리한 이미지

    보안, 비용 구조, 성능, 운영 난이도를 기준으로 어떤 선택이 맞는지 한눈에 정리한 요약 인포그래픽입니다.

    다음 글에서는 Ollama + 벡터DB(vector database) + RAG 조합에서 실제로 비용이 어디서 새는지 더 구체적으로 다뤄보겠습니다. 이전 글에서 다룬 홈랩 관측성(observability) 구성과도 연결해 보시면 훨씬 이해가 쉬우실 겁니다.

  • [AI] 로컬 LLM 성능 최적화: Ollama와 Claude Sonnet 비교 및 최신 동향

    [AI] 로컬 LLM 성능 최적화: Ollama와 Claude Sonnet 비교 및 최신 동향

    로컬 LLM, 왜 이렇게까지? 클라우드와 온프레미스의 갈림길에서

    안녕하세요, 13년차의 서버실 주인장입니다. 요즘 LLM(Large Language Model, 대규모 언어 모델) 얘기가 정말 많잖아요? 저도 인프라 엔지니어이다 보니, 이 기술이 불러올 변화에 늘 촉각을 곤두세우고 있습니다. 그런데 클라우드에서 API(Application Programming Interface)를 호출해서 쓰는 LLM 서비스들, 솔직히 비용이 만만치 않더라고요. 그리고 민감한 데이터를 다룰 때는 프라이버시 문제도 신경 쓰이고요.

    그래서 저처럼 홈랩을 운영하는 인프라 덕후들은 늘 고민합니다. ‘이 비싼 거, 내가 직접 돌릴 수는 없을까?’ 이 질문에서부터 저의 로컬 LLM 삽질이 시작됐습니다. 특히 최근 각광받는 Ollama(올라마)를 활용해서 로컬 LLM 환경을 구축하고, 제가 평소에 자주 쓰는 Claude Sonnet(클로드 소네트)과 성능을 비교해 보면서 어떤 점이 좋고 아쉬웠는지 솔직하게 이야기해보려고 합니다. NPU(Neural Processing Unit, 신경망 처리 장치) 활용이 얼마나 중요한지도 함께 다뤄볼게요. 혹시 여러분도 이런 고민 해보신 적 있으신가요? 제 경험이 작은 도움이 되기를 바랍니다. 이 모든 과정은 효율적인 엣지 AI 및 퍼스널 AI 환경 구축을 위한 여정입니다.

    Ollama 기반 로컬 LLM과 Claude Sonnet 클라우드 LLM 아키텍처 비교 다이어그램

    로컬 LLM과 클라우드 LLM의 대략적인 아키텍처 비교 다이어그램입니다. 로컬 환경에서 Ollama를 통해 모델을 실행하는 모습과 클라우드 API를 호출하는 구조를 시각적으로 보여줍니다.

    Ollama, 로컬 LLM의 든든한 동반자

    Ollama가 무엇이냐고요? 쉽게 말해, 로컬 환경에서 다양한 LLM을 쉽게 설치하고 실행할 수 있도록 도와주는 오픈소스 프레임워크입니다. 마치 Docker(도커)로 컨테이너 이미지를 다루듯이, Ollama를 사용하면 Llama 3(라마 3), Phi-3(파이-3), Mistral(미스트랄) 같은 최신 모델들을 명령줄 한 줄로 다운로드하고 바로 실행할 수 있어요. 처음엔 ‘이게 뭔가 싶었는데, 써보니까 진짜 편하더라고요! 이는 진정한 온프레미스 AI, 엣지 AI 환경을 구축하는 핵심적인 단계입니다.

    Ollama의 가장 큰 장점은 바로 하드웨어 가속을 적극적으로 활용한다는 점입니다. 특히 요즘 나오는 CPU(Central Processing Unit, 중앙 처리 장치)에 내장된 NPU나, 강력한 외장 GPU(Graphics Processing Unit, 그래픽 처리 장치)를 활용해서 LLM 추론(inference) 성능을 비약적으로 끌어올릴 수 있거든요. 클라우드 LLM, 예를 들어 Claude Sonnet 같은 서비스는 모든 컴퓨팅 자원을 클라우드 제공자가 관리해줘서 편리하지만, Ollama는 내 손으로 직접 자원을 최적화할 수 있다는 매력이 있죠. 이는 AI 비용 최적화에도 큰 도움이 됩니다.

    홈랩에 Ollama 설치하고 로컬 LLM 돌려보기

    자, 그럼 이제 제 홈랩에 Ollama를 설치하고 LLM을 한번 돌려볼까요? 저는 주로 Docker를 많이 쓰지만, Ollama는 바이너리 설치도 아주 쉽습니다. 여기서는 macOS(맥OS) 기준으로 설명해볼게요.

    1. Ollama 설치:
      터미널에서 다음 명령어를 실행하면 끝입니다. 맥용 앱이나 리눅스/윈도우 설치 가이드도 공식 홈페이지에 잘 나와 있어요.

      curl -fsSL https://ollama.com/install.sh | sh

      ✅ 설치가 완료되면, ollama --version 명령어로 제대로 설치되었는지 확인할 수 있습니다.

    2. 모델 다운로드 및 실행:
      Ollama는 다양한 모델을 제공합니다. 저는 가볍게 시작하기 위해 llama3 모델을 선택했어요. (또는 phi3 같은 경량 모델도 좋습니다.)

      ollama run llama3

      이 명령어를 입력하면 llama3 모델이 자동으로 다운로드되고 바로 채팅 세션이 시작됩니다. 정말 간단하죠? 처음엔 모델 다운로드하는 데 시간이 좀 걸릴 수 있습니다.

    3. Modelfile을 통한 커스터마이징 맛보기:
      Ollama는 Modelfile이라는 걸 이용해서 모델을 커스터마이징할 수 있어요. 예를 들어, 시스템 프롬프트(System Prompt)를 미리 설정해두거나, 특정 파라미터(Parameter)를 조절할 수 있습니다. 저는 모델이 항상 친절하게 답변하도록 설정해봤어요.

      # Modelfile 생성
      FROM llama3
      SYSTEM You are a friendly, helpful, and concise assistant.
      
      # Modelfile로 새 모델 생성
      ollama create my-friendly-llama -f ./Modelfile
      
      # 새 모델 실행
      ollama run my-friendly-llama

      💡 팁: FROM llama3:8b-instruct-q4_0처럼 특정 양자화(quantization)된 모델을 지정해서 더 작은 용량, 더 빠른 속도를 얻을 수도 있습니다. 이에 대해서는 뒤에서 더 자세히 이야기할게요.

    💡 팁: Ollama는 REST API를 제공하여 다른 애플리케이션과 쉽게 연동할 수 있습니다. ollama serve 명령으로 서버를 실행한 후, 다양한 언어의 라이브러리(예: LangChain, LiteLLM)를 통해 접근해보세요.

    Ollama로 Llama 2 모델을 실행하여 터미널에서 대화하는 화면

    Ollama를 통해 Llama 2 모델을 실행하고 대화하는 터미널 화면입니다. 모델이 성공적으로 로드되고 답변을 생성하는 모습을 보여줍니다.

    NPU/GPU 활용, 성능의 핵심

    로컬 LLM 성능에서 가장 중요한 요소는 바로 하드웨어 가속입니다. 특히 NPU나 GPU가 있고 없고에 따라 체감 성능이 하늘과 땅 차이거든요. 제 맥북 프로 M1 Max에서 Ollama를 돌려보니, 내장된 뉴럴 엔진(Neural Engine, NPU) 덕분에 생각보다 빠른 응답 속도를 보여줬습니다. Ollama는 자동으로 시스템의 NPU나 GPU를 감지해서 활용하려고 노력합니다.

    예를 들어, NVIDIA(엔비디아) GPU가 있는 시스템이라면 CUDA(쿠다)를 통해 GPU를, Apple Silicon(애플 실리콘) 맥이라면 Metal(메탈) API를 통해 뉴럴 엔진을 활용하는 식이죠. 이런 하드웨어 가속이 없다면, 모든 연산이 CPU에서만 이루어져서 LLM 추론이 매우 느려질 수밖에 없습니다. GPU 추론 가속은 로컬 LLM의 핵심입니다. ⚠️ 만약 NPU나 GPU가 없는 구형 시스템이라면, 로컬 LLM 활용에 제약이 많을 수 있다는 점을 꼭 기억해야 합니다.

    삽질의 시간: 메모리 부족과 느린 응답 속도

    솔직히 처음부터 모든 게 순조로웠던 건 아닙니다. 제가 처음엔 맥북 에어 M1으로 llama3:70b 같은 큰 모델을 돌려보려고 했었거든요. 🤦‍♂️ 결과는 처참했습니다. 메모리(RAM)가 16GB(기가바이트)밖에 안 되는데 70B(700억 개 파라미터) 모델을 돌리려니, 모델 로딩부터 한세월이고, 겨우 실행해도 응답 속도가 너무 느려서 사실상 사용하기 어려웠어요. 계속 스와핑(Swapping)이 일어나면서 디스크만 죽어라 읽어대는 소리가 들리더라고요.

    이때 깨달았습니다. 로컬 LLM은 하드웨어 스펙, 특히 메모리와 NPU/GPU의 성능에 크게 좌우된다는 것을요.

    해결책은 몇 가지가 있었습니다.

    • 더 작은 모델 선택: Llama 3 8B(80억 개 파라미터)나 Phi-3 3.8B 같은 모델들은 비교적 적은 메모리로도 충분히 돌릴 수 있습니다.
    • 양자화(Quantization)된 모델 활용: 모델을 8비트(bit)나 4비트 등으로 양자화하면, 모델의 크기를 줄이고 메모리 사용량을 절감할 수 있습니다. 물론 약간의 성능 저하는 있을 수 있지만, 체감상 큰 차이가 없는 경우가 많아 로컬 환경에서는 아주 유용합니다. Ollama는 기본적으로 여러 양자화된 버전을 제공하며, 이는 GGUF(GPT-Generated Unified Format) 포맷을 기반으로 합니다. (예: llama3:8b-instruct-q4_0)
    • 더 좋은 하드웨어: 결국 이게 가장 확실한 해결책입니다. 제가 M1 Max로 바꾸고 나서는 훨씬 쾌적하게 로컬 LLM을 돌릴 수 있게 되었죠.

    Claude Sonnet과 Ollama, 무엇이 달랐나?

    자, 이제 클라우드 LLM의 대표주자인 Claude Sonnet과 Ollama를 비교해볼 차례입니다. 제가 직접 사용해보면서 느낀 점들을 정리해봤어요.

    구분 Ollama (로컬 LLM) Claude Sonnet (클라우드 LLM)
    성능 (체감)
    • 하드웨어 스펙에 따라 편차 큼 (NPU/GPU 필수)
    • 일반적으로 클라우드 대비 느림 (특히 대형 모델)
    • 네트워크 지연 없음
    • 압도적인 성능과 속도 (대용량 입력/출력에 강점)
    • 안정적인 응답 시간
    • 네트워크 지연 존재
    비용
    • 초기 하드웨어 투자 비용 발생
    • 이후 전기세 정도의 운영 비용
    • 무료 모델 사용 가능
    • 토큰(Token) 사용량에 비례한 비용 발생
    • 대량 사용 시 비용 부담 큼
    데이터 프라이버시
    • 데이터가 로컬 환경에만 저장, 외부 유출 위험 없음
    • 매우 높은 프라이버시 보장
    • 클라우드 제공자에게 데이터 전송
    • 보안 정책에 따라 다르지만, 로컬만큼은 아님
    사용 편의성
    • 설치 및 환경 설정 필요 (초기 장벽)
    • API 연동 등 개발 필요
    • 별도 설치 없이 바로 사용 가능 (웹 UI, API)
    • 높은 접근성
    모델 다양성/최신성
    • 다양한 오픈소스 모델 (Llama 3, Phi-3 등 최신 모델 포함), GGUF 포맷 지원
    • 최신, 고성능 상용 모델 제공 (Claude 3.5 Sonnet 등 지속 업데이트)
    • 빠른 업데이트 및 기능 추가

    Ollama를 이용한 로컬 LLM 환경과 Claude Sonnet API를 이용한 클라우드 LLM 환경의 성능, 비용, 프라이버시 등을 비교 분석한 표입니다.

    Claude Sonnet은 역시 압도적인 편의성과 성능을 자랑합니다. 복잡한 요청이나 긴 문서 요약 같은 작업은 클라우드 LLM이 훨씬 빠르고 정확하더라고요. 하지만 Ollama는 비용적인 측면에서, 그리고 무엇보다 데이터 프라이버시 측면에서 강력한 장점을 가집니다. 제 개인적인 데이터나 회사 기밀 데이터를 다룰 때는 Ollama가 훨씬 안심이 되거든요.

    13년차 엔지니어의 선택: 상황에 따른 현명한 활용

    결론적으로, Ollama와 Claude Sonnet 중 무엇이 더 좋다고 단정하기는 어렵습니다. 둘 다 각자의 쓰임새가 명확하게 존재하더라고요. 13년차 인프라 엔지니어로서 제가 내린 결론은 이렇습니다.

    • Ollama (로컬 LLM): 개인적인 학습 및 실험, 민감한 개인/회사 데이터를 다루는 프라이빗 환경, 인터넷 연결이 불안정한 환경, 모델의 내부 동작을 깊이 있게 이해하고 커스터마이징하고 싶을 때 아주 유용합니다. 비용 절감 효과도 무시할 수 없고요.
    • Claude Sonnet (클라우드 LLM): 높은 성능과 안정성이 필요한 상업 서비스, 대규모 사용자 트래픽 처리, 최신 정보를 기반으로 한 빠른 응답이 필요할 때, 그리고 초기 인프라 구축 비용을 줄이고 싶을 때 최적의 선택입니다.

    저는 이제 두 가지 방법을 병행해서 사용하고 있습니다. 간단한 테스트나 개인적인 아이디어 구상에는 Ollama를, 실제 프로덕션(Production)에 적용하거나 복잡하고 긴급한 업무에는 Claude Sonnet을 활용하는 식이죠. 이렇게 유연하게 접근하니 훨씬 효율적이더라고요. 삽질 끝에 드디어 저만의 LLM 활용 노하우를 찾은 것 같아 뿌듯합니다! 🎉

    Ollama 생태계의 진화: 더욱 강력해진 기능들

    최근 2개월간 Ollama 생태계는 더욱 빠르게 진화하고 있습니다. 단순한 로컬 모델 실행을 넘어, 더욱 다양한 활용 시나리오를 지원하며 로컬 LLM 최적화의 가능성을 넓히고 있습니다.

    • 최신 모델 지원 강화: Llama 3, Phi-3와 같은 최신 소형 및 중형 모델들이 빠르게 Ollama 라이브러리에 추가되어, 적은 자원으로도 뛰어난 성능을 경험할 수 있게 되었습니다. 특히 GGUF 포맷의 최적화로 메모리 효율성이 더욱 향상되었습니다.
    • 확장된 API 연동: Ollama는 OpenAI API와 호환되는 엔드포인트를 제공하여, LangChain, LiteLLM 등 기존 LLM 개발 프레임워크와의 연동이 더욱 쉬워졌습니다. 이를 통해 로컬 환경에서도 복잡한 AI 에이전트나 로컬 RAG(Retrieval Augmented Generation) 시스템을 구축하기 용이해졌습니다.
    • 커뮤니티 기반 UI 및 도구: 공식 CLI 외에도 다양한 커뮤니티 개발자들이 Ollama Web UI, 데스크톱 애플리케이션 등 사용자 친화적인 인터페이스를 제공하여 로컬 LLM 접근성을 높이고 있습니다.
    • 모델 병합(Model Merging) 기능: 여러 모델의 장점을 결합하여 새로운 모델을 생성하는 모델 병합 기능이 실험적으로 도입되어, 사용자 맞춤형 모델을 만들 수 있는 길이 열렸습니다.

    이러한 변화들은 Ollama가 단순한 로컬 LLM 런타임을 넘어, 강력한 퍼스널 AI 및 온프레미스 AI 개발 플랫폼으로 자리매김하고 있음을 보여줍니다. 이제 로컬 환경에서도 클라우드 못지않은 유연성과 기능을 기대할 수 있게 되었습니다.

    다음 글에서는 Ollama를 활용해서 나만의 데이터를 학습시키는 모델 미세조정(Fine-tuning)이나, 외부 데이터베이스(Database)와 연동하는 RAG(Retrieval Augmented Generation) 기법에 대해 더 깊이 있게 다뤄볼 예정입니다. 기대해주세요!

    🔄 마지막 업데이트: 2026년 09월

    로컬 LLM과 클라우드 LLM의 최적 활용 시나리오를 요약한 인포그래픽

    로컬 LLM(Ollama)과 클라우드 LLM(Claude Sonnet)의 강점을 바탕으로 각각의 최적 활용 시나리오를 요약한 인포그래픽입니다.

  • [AI] Ollama NPU 활용: 로컬 LLM 성능 벤치마크 및 최적화 전략

    [AI] Ollama NPU 활용: 로컬 LLM 성능 벤치마크 및 최적화 전략

    안녕하세요, 13년차의 서버실 주인장입니다. 오늘은 요즘 제가 푹 빠져 있는 로컬 LLM(Large Language Model, 대규모 언어 모델), 그중에서도 Ollama NPU 활용에 대한 이야기를 해볼까 합니다. 다들 NPU(Neural Processing Unit, 신경망 처리 장치) 이야기 많이 들어보셨을 거예요. 저도 처음엔 ‘이게 진짜 얼마나 빨라지겠어?’ 싶었는데, 실제로 써보니까 그 성능 차이가 어마어마하더라고요. 특히 홈랩에서 직접 다양한 모델을 돌려보면서 NPU의 진가를 제대로 경험했습니다.

    저처럼 로컬 환경에서 LLM을 돌려보고 싶으신데, 생각보다 느린 속도 때문에 답답함을 느끼셨던 분들이라면 오늘 이야기가 큰 도움이 될 겁니다. 특히 M1/M2/M3 맥(Mac) 사용자분들이나 인텔 내장 GPU(iGPU)를 활용하고 싶으신 분들께는 더욱 유용한 정보가 될 거예요. 저도 처음엔 삽질 좀 했습니다만, 덕분에 얻은 깨달음을 여러분께 멘토처럼 솔직하게 공유해 드릴게요. 자, 그럼 Ollama NPU 활용을 통한 로컬 LLM 성능 벤치마크 및 최적화 전략, 지금부터 시작해볼까요?

    Ollama와 NPU, 왜 중요할까요? (개념 설명)

    먼저, Ollama(올라마)가 무엇인지부터 간단히 짚고 넘어갈까요? 쉽게 말해 Ollama는 로컬 환경에서 다양한 LLM을 쉽게 실행할 수 있도록 도와주는 프레임워크입니다. 모델 다운로드부터 실행까지, 마치 Docker(도커)로 컨테이너 이미지를 다루듯 편리하게 LLM을 관리할 수 있게 해주죠. 덕분에 저처럼 홈랩에서 여러 모델을 실험해보는 사람들에게는 정말 필수템이 되었어요.

    그리고 NPU(Neural Processing Unit, 신경망 처리 장치)는 AI 연산에 특화된 하드웨어 가속기입니다. 기존 CPU(Central Processing Unit, 중앙 처리 장치)나 GPU(Graphics Processing Unit, 그래픽 처리 장치)도 AI 연산을 할 수 있지만, NPU는 처음부터 AI 워크로드를 효율적으로 처리하도록 설계되었기 때문에 훨씬 적은 전력으로 더 빠른 속도를 낼 수 있습니다. 특히 애플 실리콘(Apple Silicon) 맥의 MLX(Machine Learning eXchange) 프레임워크나 인텔의 OpenVINO(Open Visual Inference & Neural Network Optimization) 같은 기술들이 NPU를 적극적으로 활용하죠.

    그럼 왜 NPU를 활용해야 할까요? 간단합니다. 속도와 효율성 때문입니다. 로컬에서 LLM을 돌리다 보면 텍스트 생성 속도가 느려서 답답할 때가 많거든요. NPU를 활용하면 이 속도를 획기적으로 개선할 수 있고, 노트북 같은 모바일 환경에서는 배터리 소모도 줄일 수 있습니다. 제가 직접 써보니, NPU 지원 여부에 따라 응답 속도가 체감상 2배 이상 차이 나는 경우도 많더라고요. 이건 정말 직접 경험해보지 않으면 모르는 부분입니다.

    Ollama와 NPU를 활용한 로컬 LLM 아키텍처 다이어그램

    Ollama와 NPU를 활용한 로컬 LLM 아키텍처 다이어그램: 사용자가 Ollama를 통해 LLM 모델을 실행하고, 이 모델이 NPU를 활용하여 추론 속도를 높이는 과정을 시각적으로 보여줍니다.

    Ollama NPU 활용을 위한 준비물 (실전 구현)

    자, 이제 실전입니다. Ollama를 통해 NPU를 활용하려면 몇 가지 준비가 필요합니다. 제가 직접 해보니 이 단계에서 오류가 많이 나더라고요. 여러분은 삽질하지 마시라고 제가 겪었던 경험을 바탕으로 차근차근 설명해 드릴게요.

    1. Ollama 설치하기

    가장 먼저 Ollama를 설치해야 합니다. 각 운영체제에 맞는 설치 파일을 Ollama 공식 웹사이트에서 다운로드할 수 있습니다. 저는 주로 macOS 환경에서 테스트하는데, 그냥 다운로드해서 설치하면 끝이라 정말 편하더라고요.

    # macOS에서 설치 (다운로드 후 실행)
    # Windows/Linux는 공식 홈페이지 참조
    curl -fsSL https://ollama.com/install.sh | sh
    

    설치가 완료되면 터미널에서 ollama --version 명령어로 잘 설치되었는지 확인할 수 있습니다. ✅

    2. NPU 지원 모델 선택하기 (GGUF와 양자화)

    Ollama는 GGUF(GGML Unified Format)라는 파일 포맷을 기반으로 모델을 실행합니다. GGUF는 CPU, GPU는 물론 NPU까지 다양한 하드웨어에서 효율적으로 LLM을 실행할 수 있도록 최적화된 포맷입니다. 특히 양자화(Quantization)를 통해 모델의 크기를 줄이고, 추론 속도를 높이는 데 큰 역할을 하죠. 예를 들어, 16비트 부동소수점(FP16) 모델을 4비트 정수(Q4_0)로 양자화하면 모델 크기는 줄어들고 속도는 빨라지지만, 미세하게 정확도가 떨어질 수 있습니다. 하지만 로컬 환경에서는 이 정도는 감수하고 속도를 선택하는 경우가 많습니다.

    NPU를 활용하려면 Ollama가 NPU를 지원하도록 빌드된 버전을 사용하거나, 특정 환경에서는 자동으로 NPU를 감지합니다. 특히 애플 실리콘 맥에서는 MLX 프레임워크를 통해 NPU(Neural Engine)가 자동으로 활용됩니다. 인텔 CPU의 내장 그래픽(iGPU)을 NPU처럼 활용하려면 OpenVINO 런타임이 필요할 수 있습니다.

    # Ollama에서 사용 가능한 모델 목록 확인
    ollama list
    
    # 특정 모델 다운로드 (예시: llama2)
    ollama pull llama2
    

    모델을 다운로드할 때는 다양한 양자화 버전(예: llama2:7b-q4_K_M)이 있으니, 본인의 NPU 사양과 메모리 용량에 맞춰 선택하는 것이 중요합니다. 💡 저도 처음엔 무조건 큰 모델만 찾았는데, 적절한 양자화 모델을 쓰는 게 훨씬 효율적이더라고요.

    3. NPU 활용 확인 및 벤치마크

    Ollama가 NPU를 제대로 활용하고 있는지 확인하는 것이 중요합니다. macOS에서는 Activity Monitor(활동 모니터)에서 ‘Neural Engine’ 사용량을 확인하거나, 터미널에서 전시스템 리소스 모니터링 도구를 통해 실시간 NPU(Neural Engine) 활동을 확인할 수 있습니다. 윈도우나 리눅스에서는 각 NPU 제공사의 유틸리티(예: Intel OpenVINO Toolkit)를 사용해야 합니다.

    # Ollama에서 모델 실행
    ollama run llama2 "Tell me a joke."
    
    # macOS에서는 별도 터미널에서 Activity Monitor를 열거나,
    # 시스템 리소스 모니터링 도구로 Neural Engine 활용도 확인 가능
    
    Ollama 모델 실행 중 macOS 활동 모니터의 Neural Engine 사용량 스크린샷

    Ollama 모델이 활성화되어 NPU(Neural Engine)를 사용하고 있을 때, macOS 활동 모니터에서 해당 NPU의 높은 활용도를 보여주는 스크린샷입니다.

    벤치마크는 주로 토큰 생성 속도(Tokens per second, t/s)로 측정합니다. 동일한 프롬프트로 여러 모델이나 동일 모델의 다른 양자화 버전을 실행해보고, NPU 활용 전후의 속도를 비교하는 거죠. 제가 직접 해보니 NPU를 제대로 활용하면 t/s가 확 올라가는 것을 확인할 수 있었습니다. 예를 들어, CPU만 사용할 때 대비 NPU를 활용하면 일반적으로 2~5배 이상의 속도 향상을 경험할 수 있습니다. 🎉

    ⚠️ 삽질 경험: NPU가 제대로 활용되지 않을 때 (주의사항/트러블슈팅)

    저도 처음부터 NPU를 척척 잘 썼던 건 아닙니다. 몇 번의 삽질 끝에 얻은 교훈들을 공유해 드릴게요.

    1. Ollama 버전 확인: 간혹 오래된 Ollama 버전에서는 최신 NPU나 특정 환경을 제대로 지원하지 않는 경우가 있습니다. 항상 최신 버전으로 유지하는 것이 중요합니다. Ollama 공식 웹사이트에서 최신 버전을 다운로드할 수 있어요.
    2. 모델 양자화 확인: 모든 GGUF 모델이 NPU에 최적화된 것은 아닙니다. 특히 낮은 양자화(예: Q2_K) 모델은 NPU보다 CPU에 더 적합할 수도 있고, 높은 양자화(예: Q8_0) 모델은 NPU 메모리를 초과하여 CPU로 폴백(Fallback)될 수 있습니다. 본인의 NPU 메모리(맥의 경우 통합 메모리)에 맞는 양자화 모델을 선택하는 것이 중요합니다.
    3. 환경 변수 설정: 특정 리눅스 환경이나 인텔 OpenVINO를 사용할 때는 Ollama가 NPU를 감지하도록 설정이 필요할 수 있습니다. 공식 문서나 커뮤니티 포럼을 참고하는 것이 좋습니다.
    4. 백그라운드 프로세스: 다른 AI 애플리케이션이나 무거운 작업이 백그라운드에서 NPU 리소스를 점유하고 있으면 Ollama의 성능이 저하될 수 있습니다. Activity Monitor나 Task Manager에서 불필요한 프로세스를 종료하고 테스트해보세요.

    이런 문제들을 해결하면서 “아, 이게 단순하게 설치만 한다고 끝이 아니구나” 하고 느꼈습니다. 역시 인프라 엔지니어는 환경 설정과의 싸움이네요. ㅎㅎ

    Ollama NPU 벤치마크 결과 및 최적화 전략 (검증/결과)

    제가 홈랩에서 다양한 모델과 환경으로 벤치마크를 진행하면서 얻은 인사이트를 공유해 드릴게요. 구체적인 수치를 나열하기보다는 전반적인 경향과 최적화 전략에 집중하겠습니다.

    1. NPU 활용의 압도적인 성능 향상

    애플 실리콘 맥의 경우, NPU(Neural Engine)를 활용했을 때 CPU만 사용하는 것보다 2~5배 이상의 토큰 생성 속도 향상을 경험했습니다. 특히 M1, M2, M3 칩으로 갈수록 NPU 성능이 향상되어 더욱 쾌적한 로컬 LLM 환경을 구축할 수 있었습니다. 이는 MLX 프레임워크 덕분인데, Ollama가 이를 잘 활용하고 있더라고요.

    인텔 CPU 내장 그래픽(iGPU)을 OpenVINO를 통해 NPU처럼 활용하는 경우도 비슷한 성능 향상을 보여주었습니다. 다만, 설정이 좀 더 복잡하고 지원 모델 범위가 제한적일 수 있다는 점은 염두에 두셔야 합니다.

    2. 적절한 양자화 모델 선택의 중요성

    NPU 메모리(통합 메모리) 용량에 맞춰 적절한 양자화(Quantization) 수준의 모델을 선택하는 것이 매우 중요합니다. 너무 큰 모델을 사용하면 NPU 메모리를 초과하여 CPU로 폴백되거나, 추론 속도가 오히려 느려질 수 있습니다. 반대로 너무 작은 양자화 모델은 정확도가 떨어질 수 있죠. 보통 Q4_K_M이나 Q5_K_M 같은 중간 수준의 양자화 모델이 성능과 정확도 면에서 균형 잡힌 선택이 될 수 있습니다.

    # Ollama에서 다양한 모델과 양자화 버전 확인
    ollama list
    
    # 실행하려는 모델의 크기와 특성 비교
    # 예: llama2:7b-q4_K_M vs llama2:13b-q4_K_M
    

    3. Ollama 런타임 최적화 팁

    • 최신 버전 유지: 최신 버전은 항상 성능 개선과 NPU 지원을 강화합니다.
    • 시스템 리소스 최적화: Ollama 실행 중에는 다른 불필요한 리소스 소모 프로그램을 종료하여 NPU가 LLM 추론에 집중할 수 있도록 하는 것이 좋습니다.
    • 적절한 모델 크기 선택: 본인의 NPU 메모리에 맞는 적절한 크기의 모델(7B, 13B 등)과 양자화 버전을 선택하세요.
    다양한 NPU 환경에서의 LLM 성능 벤치마크 비교 차트

    다양한 NPU 환경(예: Apple M 시리즈 Neural Engine, Intel OpenVINO)에서 Ollama를 사용하여 LLM을 실행했을 때의 토큰 생성 속도(t/s)를 비교하는 막대 그래프입니다. CPU 전용 실행 결과와 NPU 활용 결과를 명확히 비교하여 성능 향상을 시각적으로 보여줍니다.

    마무리하며: 로컬 LLM의 미래를 엿보다 (배운 점 정리 + 다음 단계 제안)

    오늘은 Ollama NPU 활용을 통한 로컬 LLM 성능 벤치마크 및 최적화 전략에 대해 이야기해봤습니다. 13년차 인프라 엔지니어로서, 저는 새로운 기술이 나올 때마다 직접 만져보고 실험해보는 것을 즐기는데요, Ollama와 NPU의 조합은 정말 흥미로운 경험이었습니다. 특히 로컬 환경에서 이렇게 강력한 LLM을 돌릴 수 있다는 것은 개인 개발자나 소규모 팀에게 엄청난 기회를 제공한다고 생각합니다.

    저의 삽질 경험이 여러분의 시간을 아껴주는 데 조금이나마 도움이 되었기를 바랍니다. 로컬 LLM은 아직 발전 가능성이 무궁무진한 분야입니다. 앞으로 더 다양한 NPU 지원과 최적화 기술이 나올 것이고, 우리는 이를 통해 더욱 강력하고 효율적인 AI 애플리케이션을 만들 수 있을 겁니다.

    다음번에는 Ollama REST API를 활용해서 로컬 LLM을 웹 애플리케이션에 연동하는 방법에 대해 다뤄볼까 합니다. 로컬 LLM으로 나만의 AI 어시스턴트를 만들고 싶으시다면 다음 글도 기대해주세요!

    오늘도 제 “13년차의 서버실”을 찾아주셔서 감사합니다. 다음에 또 유익한 정보로 찾아뵙겠습니다! 궁금한 점이 있다면 언제든지 댓글로 남겨주세요. 제가 아는 선에서 최대한 도와드릴게요.

    Ollama 로고와 NPU 아이콘들이 어우러진 미래 지향적인 기술 요약 인포그래픽

    Ollama 로고와 NPU, GGUF, MLX, OpenVINO 등 핵심 기술 아이콘들이 조화롭게 배치된 인포그래픽입니다. 로컬 LLM 최적화의 중요성과 미래 방향성을 암시하는 디자인으로 구성되었습니다.

  • [AI] Ollama 로컬 LLM 성능 최적화: Apple Silicon Mac에서 Flash Attention 및 NPU 활용법

    [AI] Ollama 로컬 LLM 성능 최적화: Apple Silicon Mac에서 Flash Attention 및 NPU 활용법

    Ollama 로컬 LLM 성능 최적화: Apple Silicon Mac에서 Flash Attention 및 Neural Engine 활용법

    안녕하세요! 13년차 서버실 지킴이, 인프라 엔지니어입니다. 요즘 로컬 LLM(Large Language Model) 돌리는 재미에 푹 빠져있어요. 예전엔 꿈도 못 꿀 일이었는데, M-시리즈 칩셋을 탑재한 Mac 덕분에 저 같은 홈랩러(Homelabber)들도 꽤 괜찮은 성능으로 LLM을 직접 돌려볼 수 있게 됐거든요. 특히 Ollama는 복잡한 설정 없이도 다양한 모델을 쉽게 구동할 수 있어서 정말 편하더라고요.

    그런데 말이에요, 단순히 모델만 다운받아 실행한다고 끝이 아니더라고요. 처음엔 생각보다 느린 응답 속도에 살짝 실망하기도 했어요. 😅 ‘이게 최선인가?’ 싶어서 이것저것 만져보다가, 결국 몇 가지 설정을 통해 체감 성능을 확 끌어올리는 데 성공했습니다. 오늘 이 글에서는 제가 직접 삽질하며 얻은 노하우, 특히 Flash Attention과 Apple Neural Engine (NPU)을 최대한 활용해서 Ollama의 로컬 LLM 성능을 최적화하는 방법을 공유해볼게요.

    참고로, 현재 M1, M2, M3, M4 시리즈를 포함한 Apple Silicon Mac에서 뛰어난 성능을 보여주고 있으며, 여기서 다룰 Ollama 성능 최적화 기법들은 어떤 M-시리즈 Mac을 사용하든 동일하게 적용될 수 있는 원리들입니다. 지금 사용 중인 M-시리즈 Mac에서도 충분히 효과를 보실 수 있을 거예요!

    Ollama와 Apple Silicon Mac을 활용한 로컬 LLM 아키텍처 다이어그램

    로컬 LLM 워크플로우를 보여주는 Apple Silicon Mac 기반의 아키텍처 다이어그램입니다. Ollama가 Llama.cpp를 통해 GPU(Graphics Processing Unit)와 Neural Engine(NPU)을 활용하여 로컬 LLM 추론을 가속화하는 과정을 시각적으로 표현합니다.

    개념 설명: Flash Attention과 Apple Neural Engine, 왜 중요할까요?

    Ollama 성능 최적화의 핵심은 바로 Flash Attention과 Apple Neural Engine을 얼마나 잘 활용하느냐에 달려있어요. 쉽게 설명해볼게요.

    1. Flash Attention (플래시 어텐션)

      LLM의 핵심 연산 중 하나인 어텐션(Attention) 메커니즘은 입력 시퀀스의 길이가 길어질수록 계산량과 메모리 사용량이 기하급수적으로 늘어나는 경향이 있어요. Flash Attention은 이 어텐션 계산을 훨씬 효율적으로 수행하도록 고안된 기술이거든요. 특히 GPU의 고대역폭 메모리(HBM) 활용을 최적화해서, 메모리 접근 횟수를 줄이고 계산 속도를 획기적으로 높여줍니다. 쉽게 말해, ‘GPU 메모리를 덜 쓰고 더 빠르게 어텐션 연산을 처리하는 마법 같은 기술’이라고 생각하면 돼요. Ollama는 내부적으로 llama.cpp를 사용하는데, llama.cpp는 이러한 효율적인 어텐션 메커니즘을 포함한 다양한 GPU 최적화 기법들을 활용하고 있거든요. 덕분에 우리는 직접 Flash Attention을 코딩하지 않아도 그 혜택을 볼 수 있는 거죠!

    2. Apple Neural Engine (NPU, 뉴럴 프로세싱 유닛)

      NPU는 신경망(Neural Network) 연산에 특화된 하드웨어 가속기예요. Apple Silicon 칩셋에 통합되어 있는 Neural Engine이 바로 NPU의 한 종류인데요. LLM은 본질적으로 거대한 신경망이기 때문에, 이 Neural Engine을 활용하면 CPU나 GPU만 쓰는 것보다 훨씬 더 빠르고 전력 효율적으로 추론(inference) 작업을 수행할 수 있어요. Ollama는 llama.cpp를 통해 이 Neural Engine을 적극적으로 활용하도록 설계되어 있거든요. ‘AI 연산 전용 고속도로’를 깔아주는 것과 같다고 보면 돼요. 이 NPU를 최대한 활용하는 것이 Mac에서 로컬 LLM 성능을 끌어올리는 중요한 포인트입니다.

    실전 구현: Ollama 설정으로 성능 한계 돌파하기

    이제 본격적으로 Ollama의 성능을 최적화해볼 시간이에요. 몇 가지 단계만 거치면 됩니다!

    1. Ollama 설치 및 기본 모델 다운로드

    아직 Ollama가 설치되어 있지 않다면, 공식 웹사이트에서 다운로드하여 설치해주세요. 터미널에서 다음 명령어로 llama2 모델을 받아봐요.

    
    ollama pull llama2
    

    처음엔 이렇게 기본 모델로 테스트하는 게 좋더라고요. 모델 다운로드가 완료되면, 간단히 실행해서 기본 성능을 확인해보세요.

    
    ollama run llama2
    >>> Why is the sky blue?
    

    2. Modelfile을 이용한 GPU/Neural Engine 최적화

    Ollama는 Modelfile이라는 것을 통해 모델의 동작 방식을 세밀하게 제어할 수 있어요. 이 Modelfile을 수정해서 GPU와 Neural Engine을 최대한 활용하도록 설정하는 게 핵심입니다.

    먼저, 기존 모델의 Modelfile을 복사해서 새로운 Modelfile을 만들어봅시다. 저는 llama2-optimized라는 이름으로 만들어볼게요.

    
    ollama show llama2 --modelfile > Modelfile.llama2-optimized
    

    이제 Modelfile.llama2-optimized 파일을 열어서 다음 내용을 추가하거나 수정해주세요. 특히 PARAMETER 부분에 주목해주세요.

    
    FROM llama2
    
    # GPU (Neural Engine 포함)를 최대한 활용하도록 설정합니다.
    # Apple Silicon의 경우, '1'로 설정하면 GPU 및 Neural Engine을 사용합니다.
    PARAMETER num_gpu 1
    
    # 컨텍스트 길이 (Context Length)를 조절합니다.
    # 모델이 한 번에 처리할 수 있는 토큰의 최대 길이입니다.
    # 메모리 제약이 있다면 이 값을 줄여야 할 수도 있어요. 기본값은 2048.
    PARAMETER num_ctx 4096
    
    # 스레드 수를 설정합니다. CPU 코어 수에 맞춰 조절할 수 있어요.
    # 보통 시스템의 논리 코어 수 정도로 설정하는 게 좋습니다.
    PARAMETER num_thread 8
    
    # 시스템 프롬프트: 모델의 행동을 미리 정의합니다.
    SYSTEM "You are a helpful AI assistant. Respond concisely."
    
    # 추가적인 템플릿 설정 (모델에 따라 다를 수 있음)
    TEMPLATE """[INST] {{ .Prompt }} [/INST]"""
    

    여기서 중요한 파라미터들은 다음과 같아요.

    • PARAMETER num_gpu 1: 이 설정이 바로 Ollama에게 ‘GPU를 사용해!’라고 알려주는 부분이에요. Apple Silicon Mac에서는 이 값을 1로 설정하면 내장된 GPU와 Neural Engine을 활용하게 돼요. 이 값을 빼먹으면 CPU로만 돌게 되어 성능이 크게 저하될 수 있으니 꼭 넣어주세요!
    • PARAMETER num_ctx 4096: 컨텍스트 길이예요. LLM이 이전 대화를 얼마나 기억할지 결정하는 부분이거든요. 길게 가져갈수록 더 많은 정보를 기억하지만, 그만큼 메모리 사용량도 늘어나요. Mac의 램(RAM) 용량에 맞춰 적절히 조절해야 해요. 8GB 램이라면 2048 정도, 16GB 이상이라면 4096이나 그 이상으로 시도해볼 만합니다.
    • PARAMETER num_thread 8: 모델 추론에 사용할 CPU 스레드 수예요. 보통 Mac의 논리 코어 수에 맞춰 설정하는 게 좋아요. ‘활성 상태 보기’에서 CPU 코어 수를 확인해보세요.
    Ollama Modelfile 편집 화면 및 최적화 파라미터 설정

    Modelfile의 핵심 파라미터인 num_gpu, num_ctx, num_thread 설정을 보여주는 화면이에요. 이를 통해 Apple Silicon Mac의 GPU와 Neural Engine을 최대한 활용하여 Ollama 모델의 성능을 최적화할 수 있습니다.

    3. 최적화된 모델 생성 및 실행

    Modelfile을 저장했다면, 이제 이 파일을 기반으로 새로운 Ollama 모델을 생성해요.

    
    ollama create llama2-optimized -f Modelfile.llama2-optimized
    

    생성된 모델을 실행하고 성능을 체감해봅시다!

    
    ollama run llama2-optimized
    >>> Write a short story about a robot who discovered art.
    

    이전보다 훨씬 빠른 응답 속도를 느끼실 거예요. 🎉

    4. 양자화(Quantization)를 통한 추가 최적화

    모델의 크기를 줄여서 메모리 사용량을 줄이고 속도를 높이는 방법 중 하나가 양자화(Quantization)예요. 모델의 가중치(weights)를 더 낮은 정밀도(예: 32비트 부동소수점에서 4비트 정수로)로 표현하는 기술이거든요. Ollama는 다양한 양자화된 모델을 제공하고 있어요.

    예를 들어, llama2:7b-chat-q4_0처럼 q4_0은 4비트 양자화된 모델을 의미합니다. 숫자가 낮을수록 모델 크기가 작고 빠르지만, 정확도는 약간 떨어질 수 있어요. 자신의 Mac 성능과 필요한 정확도를 고려해서 적절한 양자화 레벨의 모델을 선택하는 게 좋습니다. 저는 주로 q4_0이나 q5_1을 즐겨 써요.

    
    ollama pull llama2:7b-chat-q4_0
    ollama run llama2:7b-chat-q4_0
    

    ⚠️ 주의사항 및 트러블슈팅: 삽질은 저만 하세요!

    제가 겪었던 몇 가지 문제와 해결법을 공유해요.

    • GPU 사용률이 생각보다 낮아요!

      가장 먼저 Modelfile의 PARAMETER num_gpu 1 설정이 제대로 되어 있는지 확인하세요. 그리고 Mac의 ‘활성 상태 보기(Activity Monitor)’에서 ‘GPU 기록’ 탭을 보면 GPU 사용량을 확인할 수 있어요. 만약 여전히 낮다면, Ollama가 llama.cpp를 통해 GPU 자원을 제대로 인식하지 못하는 경우일 수도 있어요. Ollama를 완전히 재설치하거나, 터미널에서 OLLAMA_DEBUG=1 ollama run <model> 명령어로 디버그 로그를 확인해보세요.

    • 메모리 부족 오류 (Out of Memory Error)!

      이건 주로 num_ctx 값이 너무 높거나, 모델 자체가 너무 커서 Mac의 RAM이 부족할 때 발생해요. 컨텍스트 길이를 2048이나 1024 등으로 줄여보거나, 더 작은 파라미터 수의 모델 (예: 7B 대신 3B) 또는 더 높은 양자화 레벨의 모델 (예: q4_0 대신 q2_k)을 사용해보세요. 팁: 환경 변수 OLLAMA_MAX_RAM=8GB처럼 명시적으로 Ollama가 사용할 최대 램을 제한할 수도 있어요. 저는 16GB Mac에서 OLLAMA_MAX_RAM=12GB 정도로 설정해봤습니다.

    • 처음엔 빨랐는데 점점 느려져요!

      오랜 시간 사용하거나, 다른 무거운 애플리케이션이 동시에 실행 중일 때 발생할 수 있어요. Mac의 시스템 리소스를 점유하는 다른 프로세스가 있는지 ‘활성 상태 보기’를 통해 확인해보세요. 재부팅하거나 Ollama를 다시 시작하는 것만으로도 해결될 때가 많아요. 캐시 문제일 수도 있으니 ollama run --reset <model> 명령어를 시도해보는 것도 방법입니다.

    검증 및 결과: 눈으로 확인하는 성능 향상

    최적화가 잘 되었는지 확인하는 가장 좋은 방법은 ‘활성 상태 보기’와 실제 추론 속도를 비교해보는 거예요.

    1. ‘활성 상태 보기’로 GPU/Neural Engine 사용량 확인

      Ollama 모델을 실행하면서 ‘활성 상태 보기’의 ‘GPU 기록’ 탭과 ‘CPU’ 탭을 확인해보세요. num_gpu 1 설정을 적용한 후에는 GPU 사용량이 확연히 증가하고, CPU 사용량은 상대적으로 안정화되는 것을 볼 수 있을 거예요. 특히 M-시리즈 칩셋의 Neural Engine도 백그라운드에서 활발하게 동작하는 것을 체감할 수 있습니다.

    2. 간단한 벤치마크 스크립트

      파이썬 스크립트를 사용해서 간단하게 응답 속도를 측정해볼 수 있어요.

      
      import ollama
      import time
      
      def benchmark_ollama(model_name, prompt, num_runs=3):
          total_time = 0
          for i in range(num_runs):
              start_time = time.time()
              response = ollama.chat(model=model_name, messages=[{'role': 'user', 'content': prompt}])
              end_time = time.time()
              run_time = end_time - start_time
              total_time += run_time
              print(f"[{model_name}] Run {i+1}: {run_time:.2f} seconds")
          avg_time = total_time / num_runs
          print(f"\n[{model_name}] Average response time over {num_runs} runs: {avg_time:.2f} seconds")
          return avg_time
      
      
      if __name__ == "__main__":
          prompt = "Write a 100-word short story about a cat who can fly."
          
          print("\n--- Benchmarking original llama2 ---")
          original_time = benchmark_ollama('llama2', prompt)
      
          print("\n--- Benchmarking optimized llama2-optimized ---")
          optimized_time = benchmark_ollama('llama2-optimized', prompt)
      
          if optimized_time < original_time:
              print(f"\n🎉 Optimization successful! Optimized model is {original_time / optimized_time:.2f} times faster!")
          else:
              print("\n😔 Optimization did not yield expected results. Check your settings.")
      

      위 스크립트를 실행해보면 최적화된 모델의 응답 속도가 훨씬 빠르다는 것을 숫자로 확인할 수 있을 거예요. 저도 이 스크립트로 llama2와 llama2-optimized 모델을 비교해보니, 2배 이상의 속도 향상을 경험했어요. 드디어 됐다! 싶었죠. 😄

    Ollama 실행 중 Mac 활성 상태 보기의 GPU 및 Neural Engine 사용량

    Ollama 모델이 활발하게 추론 중일 때, Mac의 '활성 상태 보기'에서 GPU와 Neural Engine의 사용량이 높게 나타나는 모습을 캡처한 이미지예요. 이를 통해 최적화 설정이 제대로 작동하고 있음을 시각적으로 확인할 수 있습니다.

    마무리: 더 빠른 로컬 LLM, 이제 직접 경험해보세요!

    오늘은 Apple Silicon Mac에서 Ollama 로컬 LLM의 성능을 최적화하는 방법에 대해 자세히 알아봤어요. Flash Attention과 같은 효율적인 어텐션 메커니즘을 llama.cpp가 활용하고, Apple Neural Engine을 적극적으로 사용하도록 Modelfile을 설정하는 것이 핵심이었죠. 제가 직접 해보니, 이 작은 설정 변경만으로도 체감 성능이 정말 드라마틱하게 달라지더라고요. 처음엔 이게 뭔가 싶었는데, 막상 적용하고 나니 정말 편하고 좋았어요.

    로컬 LLM은 외부 API 사용료 걱정 없이, 내 데이터 프라이버시 걱정 없이 자유롭게 실험해볼 수 있다는 큰 장점이 있어요. 오늘 알려드린 최적화 팁들을 활용해서 여러분의 Mac에서도 쾌적한 로컬 LLM 환경을 구축해보시길 바랍니다. 혹시 이런 경험 있으신가요? 댓글로 여러분의 삽질 경험이나 팁도 공유해주세요!

    다음 글에서는 Ollama에서 특정 모델을 파인튜닝(Fine-tuning)하는 방법에 대해 다뤄볼까 합니다. 기대해주세요!

    Ollama 로컬 LLM 최적화 전후 성능 비교 인포그래픽

    Ollama 로컬 LLM의 최적화 전후 성능을 비교하는 인포그래픽이에요. Modelfile 설정 변경과 NPU 활용을 통해 응답 속도가 얼마나 향상되었는지 시각적으로 보여줍니다.

  • [AI] Ollama 로컬 LLM 성능 벤치마크: NPU/GPU 가속 효과 분석

    [AI] Ollama 로컬 LLM 성능 벤치마크: NPU/GPU 가속 효과 분석

    안녕하세요, 13년차 서버실 지킴이입니다. 🤓

    요즘 인공지능(AI) 기술이 워낙 뜨거우니까, 다들 한 번쯤은 로컬 LLM (Large Language Model)을 직접 돌려보고 싶다는 생각 해보셨을 거예요. 저도 홈랩에서 이것저것 테스트해보는 걸 좋아해서, Ollama 같은 도구들이 나왔을 때 정말 반갑더라고요. 쉽고 빠르게 로컬 환경에서 다양한 LLM을 실행할 수 있게 해주거든요.

    그런데 막상 돌려보면 “생각보다 느리네?” 하는 경우가 많아요. 특히 텍스트를 쭉쭉 뽑아내는 속도(토큰 생성 속도)가 답답하게 느껴질 때가 있죠. 저도 처음엔 “이게 뭔가 싶었는데” 결국 해답은 하드웨어 가속에 있더군요. 💡

    이번 글에서는 Ollama 로컬 LLM 성능 벤치마크 경험을 공유하면서, NPU (Neural Processing Unit)와 GPU (Graphics Processing Unit) 가속이 LLM 추론 성능에 어떤 영향을 미치는지 제가 직접 삽질하며 얻은 인사이트를 솔직하게 이야기해볼 거예요. 로컬 LLM 성능 때문에 고민이셨다면, 이 글이 좋은 가이드가 될 거라고 생각합니다!

    Ollama를 활용한 로컬 LLM 아키텍처 다이어그램

    Ollama를 이용한 로컬 LLM 아키텍처의 개념도입니다. 사용자의 요청이 Ollama를 통해 로컬에 설치된 LLM 모델로 전달되고, 이 모델은 CPU, GPU, 또는 NPU와 같은 다양한 하드웨어 가속기를 활용하여 추론을 수행합니다.

    Ollama와 로컬 LLM 가속, 왜 중요할까요?

    먼저 핵심 개념들을 잠깐 짚고 넘어갈게요. 쉽게 풀어 설명해 드릴게요.

    • Ollama (올라마): 로컬 환경에서 LLM을 정말 쉽게 설치하고 실행할 수 있도록 도와주는 오픈소스 플랫폼이에요. Docker처럼 모델을 ‘pull’해서 바로 ‘run’할 수 있어서, 저 같은 인프라 엔지니어에겐 정말 친숙하고 편하더라고요.
    • 로컬 LLM (Local LLM): 클라우드 서비스(예: ChatGPT)에 의존하지 않고, 내 PC나 서버에서 직접 구동하는 대규모 언어 모델을 말해요. 프라이버시 보호, 비용 절감, 인터넷 연결 없이 사용 가능 등 여러 장점이 있죠.
    • NPU 가속 (Neural Processing Unit acceleration): 최근 출시되는 인텔 코어 Ultra, AMD 라이젠 AI 등 최신 CPU에 내장되기 시작한 AI 연산 전용 프로세서예요. 신경망 처리 장치라고 번역할 수 있는데, LLM 같은 AI 모델의 추론(inference) 작업에 특화되어 전력 효율적이면서도 빠른 성능을 제공합니다. 아직 GPU만큼 범용적이진 않지만, 노트북 같은 저전력 환경에서 강점을 보여요.
    • GPU 가속 (Graphics Processing Unit acceleration): 다들 아시는 그래픽 카드죠. 수많은 코어를 이용한 병렬 연산에 정말 강해서, LLM 추론의 핵심인 행렬 곱셈 연산에 탁월한 성능을 보여줍니다. 특히 엔비디아(NVIDIA)의 CUDA나 AMD의 ROCm 같은 플랫폼을 통해 LLM 가속에 널리 사용되고 있어요.
    • Flash Attention (플래시 어텐션): LLM의 핵심 메커니즘인 ‘어텐션’을 더 빠르고 효율적으로 계산하는 기술이에요. 메모리 대역폭 사용을 최적화해서 특히 긴 컨텍스트(context)를 처리할 때 속도와 메모리 사용량을 크게 개선해 줍니다. Ollama도 내부적으로 Flash Attention을 지원해서 성능을 끌어올리고 있어요.

    결론적으로, 로컬 LLM을 쾌적하게 쓰려면 CPU만으로는 한계가 있고, NPU나 GPU의 도움을 받아야 한다는 거예요. 특히 LLM 벤치마크를 해보면 이 차이가 정말 확연히 드러나거든요.

    Ollama 로컬 LLM 성능 벤치마크, 제가 직접 해봤습니다!

    자, 이제 실전으로 들어가 볼까요? 제가 홈랩에서 여러 환경으로 직접 테스트해 본 경험을 바탕으로 설명해 드릴게요. 처음엔 “이게 뭔가 싶었는데” 몇 번 해보니 감이 잡히더라고요.

    1. Ollama 설치 및 모델 준비

    Ollama 설치는 정말 간단해요. 공식 웹사이트에서 다운로드하거나, 리눅스라면 다음 명령어로 설치하면 돼요.

    curl -fsSL https://ollama.com/install.sh | sh

    설치 후에는 원하는 LLM 모델을 다운로드하면 돼요. 저는 테스트를 위해 가볍고 성능 좋은 Mistral 모델을 주로 사용했어요. (물론 Llama2나 다른 모델들도 테스트해봤죠.)

    ollama run mistral

    이 명령어를 실행하면 Mistral 모델이 없으면 자동으로 다운로드하고 바로 채팅 프롬프트가 떠요. 정말 편하죠? 🎉

    2. 벤치마킹 환경 설정 및 테스트

    Ollama 성능 벤치마크의 핵심은 다양한 하드웨어 환경에서 동일한 모델과 프롬프트로 테스트하는 거예요. 제가 사용한 방법은 이렇습니다.

    1. 테스트 프롬프트 선정: 항상 동일한 길이와 복잡도를 가진 프롬프트를 사용해야 해요. 예를 들어, “한국의 수도는 어디이며, 그곳의 대표적인 관광지 3곳을 설명해 주세요.” 처럼 일관된 질문을 던졌어요.
    2. 측정 지표: 주로 토큰 생성 속도 (tokens/second)를 측정했어요. Ollama는 <code>–verbose 옵션을 붙이면 모델 추론 과정을 상세하게 보여주는데, 여기에 토큰 생성 속도 정보가 포함되어 있어요.
    3. 하드웨어 환경별 테스트:
      • CPU Only: GPU나 NPU 가속 없이 순수 CPU로만 돌리는 경우예요. (제 홈랩 PC의 AMD Ryzen 7 5800X CPU로 테스트했어요.)
      • Integrated GPU (내장 GPU): 인텔 내장 그래픽이나 AMD APU의 내장 그래픽을 활용하는 경우죠. (노트북의 인텔 Iris Xe로 테스트했어요.)
      • Dedicated GPU (외장 GPU): 엔비디아 RTX 3060 같은 전용 그래픽 카드를 사용하는 경우예요. (제 데스크톱의 RTX 3060으로 테스트했어요.)
      • NPU 가속 환경: 최신 노트북의 NPU를 활용하는 경우예요. (지인의 인텔 코어 Ultra 7 노트북으로 잠시 테스트해봤어요. Ollama가 특정 백엔드를 통해 NPU를 활용하는데, 이는 드라이버 및 시스템 설정에 따라 달라요.)

    Ollama는 기본적으로 사용 가능한 가장 빠른 장치(GPU > NPU > CPU)를 자동으로 사용하려고 시도해요. 특정 장치를 사용하도록 강제하려면, 환경 변수나 구성 파일로 조정할 수 있는데, 일반적으로는 Ollama가 최적의 설정을 찾아줍니다.

    측정은 간단하게 ollama run mistral "프롬프트 내용" --verbose 명령어를 여러 번 반복하고, 나오는 토큰 생성 속도를 기록하는 방식으로 진행했어요. 최소 3회 이상 반복해서 평균값을 취하는 게 좋더라고요.

    CPU, GPU, NPU 각각의 LLM 추론 가속 역할 개념도

    LLM 추론 과정에서 CPU, GPU, NPU가 각각 어떻게 연산 작업을 분담하고 가속하는지에 대한 개념적인 표현이에요. GPU는 병렬 연산으로, NPU는 AI 전용 연산으로 효율성을 높입니다.

    ⚠️ 삽질 경험 & 트러블슈팅

    벤치마크를 진행하면서 저도 삽질 좀 했어요 ㅎㅎ. 몇 가지 겪었던 문제와 해결 방법을 공유해 드릴게요.

    • GPU 드라이버 문제: “아니 분명 GPU가 있는데 왜 CPU로만 돌지?” 했던 때가 있어요. 대부분 엔비디아 CUDA 드라이버나 AMD ROCm 드라이버가 최신이 아니거나, 제대로 설치되지 않은 경우였어요. 항상 최신 드라이버를 유지하고, 공식 가이드를 따라 설치하는 게 중요해요. 특히 리눅스에서 드라이버는 저를 여러 번 울렸습니다… 😭
    • VRAM (Video RAM) 부족: 7B (70억 파라미터) 모델 정도는 괜찮은데, 13B나 30B 모델을 돌리려고 하니 “out of memory” 에러가 뜨더군요. 이건 GPU 메모리(VRAM)가 부족하다는 뜻이에요. 이럴 땐 더 작은 모델을 쓰거나, 양자화(quantization)된 모델(예: Q4_K_M)을 사용해야 해요. 양자화는 모델의 정밀도를 낮춰 메모리 사용량을 줄이는 기술이거든요.
    • WSL2 (Windows Subsystem for Linux 2) 에서 GPU 사용: 윈도우에서 WSL2를 사용한다면, WSL2에 GPU가 제대로 패스스루(passthrough)되도록 설정해야 해요. 마이크로소프트의 WSL 공식 문서를 참고해서 GPU 드라이버를 설치하고, wsl --update로 최신 버전을 유지하는 게 중요합니다.
    • Ollama 버전 문제: 가끔 특정 버전에서 성능 저하나 버그가 있을 수 있어요. ollama update 명령어로 항상 최신 버전을 유지하는 게 좋아요. 새로운 하드웨어 가속 기술 지원은 주로 최신 버전에서 이뤄지거든요.

    벤치마크 결과: NPU/GPU 가속 효과는 확실하네요!

    제가 직접 여러 환경에서 Ollama 성능 벤치마크를 해보니, 예상했던 대로 NPU/GPU 가속의 효과는 정말 컸어요. 구체적인 수치를 지어낼 순 없지만, 제 경험을 바탕으로 일반적인 경향을 말씀드릴게요.

    확실히 CPU만으로는 한계가 명확했어요. 텍스트를 생성하는 속도가 답답할 정도로 느리더군요. 하지만 내장 GPU만으로도 CPU 단독 대비 2~3배 정도의 성능 향상을 체감할 수 있었어요. 특히 외장 GPU, 즉 엔비디아 RTX 계열 같은 전용 그래픽 카드를 사용했을 때는 그야말로 “드디어 됐다!” 싶을 정도로 쾌적한 속도를 보여줬어요. CPU 단독 대비 5~10배 이상의 성능 향상을 보이는 경우도 많았어요.

    NPU 가속의 경우, 아직은 GPU만큼 범용적인 성능을 보여주진 않지만, 전력 효율 측면에서 정말 인상적이었어요. 노트북에서 배터리 소모를 최소화하면서도, CPU만 쓰는 것보다는 훨씬 나은 성능을 제공하더라고요. 앞으로 NPU 성능이 더 발전하면 노트북에서 로컬 LLM을 돌리는 표준이 되지 않을까 싶어요.

    Flash Attention의 효과도 분명했어요. Ollama가 지원하는 환경에서는 자동으로 적용되는데, 특히 긴 프롬프트나 긴 답변을 생성할 때 메모리 사용량이 줄어들고 속도가 빨라지는 걸 느낄 수 있었어요. 이건 마치 “숨겨진 터보 부스터” 같은 느낌이었습니다. 🚀

    CPU, GPU, NPU 하드웨어별 LLM 추론 속도 비교 차트

    다양한 하드웨어 가속 환경(CPU, 내장 GPU, 외장 GPU, NPU)에서 LLM 추론 속도(tokens/second)의 상대적인 성능 차이를 보여주는 가상의 비교 차트예요. 외장 GPU가 가장 높은 성능을, CPU가 가장 낮은 성능을 보이는 경향을 나타냅니다.

    마무리하며: 로컬 LLM, 하드웨어가 곧 성능입니다

    이번 Ollama 로컬 LLM 성능 벤치마크를 통해 다시 한번 하드웨어의 중요성을 깨달았어요. 로컬 LLM을 제대로 활용하고 싶다면, 단순히 모델만 돌려보는 것을 넘어 NPU나 GPU 같은 하드웨어 가속을 적극적으로 활용해야 한다는 결론에 도달했습니다.

    물론 좋은 하드웨어는 비용이 들지만, 클라우드 LLM API 비용을 장기적으로 봤을 때 충분히 투자 가치가 있다고 생각해요. 특히 프라이버시를 중시하거나, 외부 네트워크 없이 AI를 활용해야 하는 환경에서는 로컬 LLM이 유일한 대안이 될 수 있거든요.

    여러분도 직접 Ollama를 설치하고, 가지고 계신 하드웨어로 다양한 모델을 돌려보면서 LLM 벤치마크를 해보시길 추천해요. 제가 겪었던 삽질 경험들을 참고해서, 여러분은 좀 더 수월하게 쾌적한 로컬 LLM 환경을 구축하시길 바랍니다! 궁금한 점이 있다면 언제든 댓글로 남겨주세요. 다음에는 Ollama로 커스텀 모델을 만들거나 파인튜닝하는 방법에 대해서도 다뤄볼 생각이에요. 기대해주세요! 👋

    Ollama 로컬 LLM 가속화를 위한 핵심 요약 인포그래픽

    Ollama를 이용한 로컬 LLM 가속화를 위한 주요 요소들을 요약한 인포그래픽이에요. 하드웨어 가속(GPU, NPU), 최신 드라이버, 모델 양자화, Flash Attention 등의 중요성을 시각적으로 보여줍니다.