로컬 LLM의 활용

개요

진료, 법률 상담, 심리 상담, 회의…

"말"로 이루어지는 일은 기록, 요약이 늘 숙제입니다.

늘 고객과의 대화를 상담 중 직접 타이핑하는 문제입니다.

대화가 끝난뒤 대화녹음을 들으며 타이핑 하는것도 쉽지 않습니다.😩


녹음을 글로 바꿔주는 서비스(STT, Speeach To Text),

그걸 요약해 주는 AI는 이미 흔합니다.


그런데 한 가지 걸리는 점이 있죠. 😕

회의, 상담시 녹음된 파일을 글자로 변환하기 위해 내 PC에서 외부로 보내야하고,

변환된 글자를 요약하기 위해 또 외부 LLM으로 보내야 합니다.

과연 회의내용, 환자, 의뢰인의 이야기를 외부 서버로 보내도 되는 걸까?


그래서 모든 처리를 내 PC 안에서 끝내는 앱을 만들어 봤습니다.

이름은 Azimuth Scribe 입니다.


이번 글에서는 앱을 소개하면서, 이 앱의 핵심인 로컬 LLM을 클라우드 LLM과 비교해 보고,

개발 중에 만난 삽질기까지 함께 공유합니다.

(일부 그림과 표는 Claude AI를 활용해 제작했습니다. 😁)


Azimuth Scribe 가 하는 일

흐름은 단순합니다. 녹음 → 글 → 요약, 딱 4단계입니다.

[Azimuth Scribe 사용 4단계]

프로그램 화면은 아래처럼 위에서 아래로, 왼쪽에서 오른쪽으로 따라가면 되도록 구성했습니다.

[프로그램 화면 구성 (재현 도식)]

예를 들어 진료 상황을 녹음해 "진료 기록" 서식으로 요약하면 아래와 같은 결과가 나옵니다.

(가상의 대화입니다.)

[진료 대화 요약 예시 (가상)]


두 개의 AI가 일한다

이 앱 안에서는 서로 다른 AI 두 개가 순서대로 일합니다.

단계 모델 역할
① 음성 → 글 Whisper (faster-whisper) 소리를 텍스트로 변환 (STT)
② 글 → 요약 Qwen3 (Ollama로 실행) 텍스트를 지정한 서식으로 정리


Whisper는 음성을 입력받아 텍스트를 출력하는 인코더-디코더 트랜스포머입니다.

학원 머신러닝 강좌에서 배운 그 트랜스포머 구조가 그대로 쓰이는 거죠.

이 앱의 기본 모델 large-v3는 약 15억 개 안팎의 파라미터로 알려져 있습니다.


Qwen3는 대화형 언어모델(LLM)이고, 기본값은 40억(4B) 파라미터 급의 작은 모델입니다.

Ollama라는 도구가 이 모델을 내 PC에서 돌려주고, 앱은 내 PC 안의 주소(127.0.0.1)로만 말을 겁니다.


로컬 LLM vs 클라우드 LLM

이 글의 핵심입니다.

"AI는 그냥 클라우드(웹, API)로 쓰면 되지, 굳이 내 PC에서?" 라는 생각이 들 수 있습니다.

결론부터 말하면 어느 쪽이 더 좋다가 아니라 무엇이 더 중요한가의 문제입니다.

[클라우드 서비스와 로컬 처리의 데이터 흐름]

한눈에 비교

항목 로컬 LLM 클라우드 LLM
데이터 내 PC 밖으로 나가지 않음 외부 서버로 전송됨
성능 모델 크기가 제한됨 (4B~14B급이 현실적) 훨씬 큰 모델 사용 가능
비용 무료 모델 + 내 PC 전기·장비 사용량·구독 과금이 흔함
인터넷 모델 설치 후엔 불필요 항상 필요
준비 설치와 설정이 필요 계정만 있으면 바로 사용
관리 버전·장애를 내가 직접 관리 서비스가 알아서 업데이트·관리
통제 모델 버전 고정, 재현 가능 모델이 바뀌거나 종료될 수 있음


로컬 LLM의 장점

  • 프라이버시: 내용이 외부 서버로 전송되지 않으니, 민감한 대화를 다룰 때 가장 큰 장점.
  • 오프라인 동작: 모델만 설치해 두면 인터넷이 없어도 동작.
  • 비용 예측 가능: 쓸수록 늘어나는 사용료가 없음. (대신 PC와 전기 비용)
  • 통제와 재현성: 모델과 설정(온도 0.2 등)을 고정해서 같은 방식으로 계속 사용.


로컬 LLM의 단점

  • 모델 크기의 한계: 내 PC에서 돌릴 수 있는 모델은 클라우드의 대형 모델보다 작다. 복잡한 추론, 방대한 지식에는 불리. (클라우드 대형 모델은 규모가 훨씬 크고 정확한 크기가 공개되지 않는 경우도 많음)
  • 하드웨어 요구: RAM, GPU 사양에 따라 속도 차이가 큼. CPU만으로도 되지만 느림.
  • 컨텍스트 길이 제한: 한 번에 읽을 수 있는 양(컨텍스트)을 늘리면 그만큼 메모리사용 증가.
  • 설치·유지보수는 내 몫: Ollama, 모델, 버전 호환까지 직접 챙겨야 함. (아래 삽질기 참고 😅)


클라우드 LLM의 장점과 단점

  • 장점: 최고 수준의 성능, 설치 불필요, 긴 문서 처리, 항상 최신 모델, 내 PC 사양과 무관
  • 단점: 데이터가 외부로 전송됨, 인터넷 필수, 사용량 과금, 서비스 정책·약관·장애·종료에 의존


그래서 이 앱은 왜 로컬을 선택했나

핵심은 "이 일에 최고 성능이 필요한가?" 입니다.

이 앱의 LLM이 하는 일은 어려운 추론이 아니라, 이미 있는 텍스트를 정해진 서식으로 정리하는 일입니다.

그래서 시스템 프롬프트에도 "원문에 있는 정보만 사용, 추측·진단 금지"를 넣었습니다.


창의력보다 충실함이 중요하니 온도(temperature)도 0.2로 낮게 잡았습니다.

반대로 민감한 내용을 다룬다는 점이 가장 중요한 조건이라, 작은 모델의 한계를 감수하고 로컬을 택했습니다.

(요약 품질은 모델과 대화 내용에 따라 달라지므로, 실제 업무에는 반드시 결과를 확인해야 합니다.)

[로컬 VS 클라우드]


LLM을 직접 다뤄보며 배운 것들

1. 컨텍스트가 넘치면 "지시문"이 잘린다

LLM은 한 번에 읽을 수 있는 토큰의 양(컨텍스트)이 정해져 있습니다.

기본값은 8,192 토큰이고, 한글은 영어보다 같은 글자 수에 토큰을 훨씬 많이 소모합니다.

문제는 입력이 넘칠 때입니다. 앞부분, 즉 "이렇게 정리해 줘"라는 지시문이 먼저 잘려나가 엉뚱한 결과가 나올 수 있습니다. 😧

그래서 앱은 요약을 시작하기 전에 예상 토큰 수를 미리 추정해서, 넘칠 것 같으면 경고하고 컨텍스트를 늘려서 실행할지 물어봅니다.


2. "생각 과정"은 출력하지 말아줘

Qwen3 같은 하이브리드 모델은 답하기 전에 <think> ... </think> 형태의 사고 과정을 먼저 출력하려 합니다.

기록 요약에는 방해가 되죠.

앱에서는 모델에게 빈 think 블록을 미리 채워서 사고 과정을 건너뛰게 하고, 혹시 출력되더라도 걸러냅니다.


3. 스트리밍으로 보여주기

긴 요약은 결과가 나오기까지 시간이 걸립니다.

그래서 토큰이 생성되는 대로 실시간으로 화면에 보여주고, 중간에 Stop으로 멈출 수 있게 했습니다. 기다림이 훨씬 덜 답답합니다. 😊


삽질 1: 가상환경으로 옮겼더니 STT가 죽었다

배포용으로 exe를 만들기 위해 깨끗한 가상환경에서 다시 빌드했습니다.

그런데 STT를 누르면 목록의 상태가 계속 Error... 😱

더 이상한 건, 하단 상태 표시줄에는 "STT completed."가 떠 있었다는 점입니다.


원인을 보니 오류 메시지를 상태 표시줄에 쓴 직후, 다음 작업을 처리하는 함수가 같은 자리에 "완료"를 덮어쓰고 있었습니다.

오류가 났는데 사용자는 그 이유를 볼 수 없는 UI였던 겁니다.


오류를 모아서 작업이 끝나면 메시지 창으로 보여주도록 고치자 진짜 원인이 나왔습니다.

TypeError: open() got an unexpected keyword argument 'metadata_errors'

범인은 황당하게도 최신버전이었습니다.


faster-whisper가 오디오를 읽을 때 쓰는 PyAV(av) 라이브러리의 최신 버전(ver 19)에서 faster-whisper가 넘기던 인자가 사라져, 두 라이브러리가 어긋난 것입니다.

전에 쓰던 전역 환경에는 av 18.1.0이 남아 있어서 멀쩡히 동작했던 거죠.

(가상환경은 최신 버전을 새로 설치하니까요.)

[버전이 원인]


pip install "av==18.1.0"
pip freeze > requirements.txt


교훈 2가지

  • 동작하는 환경의 버전은 반드시 기록해 두자. (requirements.txt)
  • 오류 메시지를 숨기는 UI는 디버깅의 적이다. 오류는 사용자에게, 그리고 개발자에게 보여야 한다.


삽질 2: exe로 배포하기 (PyInstaller)

Python 앱을 exe로 만들 때 PyInstaller를 많이 씁니다. 이때 -F(onefile)를 쓸지, 폴더 형태(onedir, 기본값)로 만들지 고르게 됩니다.


저는 폴더 형태를 선택했습니다. 이유는 아래와 같습니다.

실행할 때마다 압축을 푸는 onefile보다 시작이 빠르고 백신 오탐도 상대적으로 적습니다.


PyQt6에서 PySide6으로 환승 글에서 다룬 LGPL 때문입니다. Qt를 교체 가능한 별도 파일(DLL)로 두는 형태가 LGPL 조건을 지키기에 유리합니다.

그리고 빌드할 때는 깨끗한 가상환경에서 해야 불필요한 패키지가 섞이지 않아 용량이 줄어듭니다.


저의 경우 exe가 약 80MB → 14MB로 줄었습니다. (환경에 따라 다릅니다.)


내 PC 밖으로 안 나간다는 걸 어떻게 믿지?

"외부로 전송하지 않는다"는 말은 쉽지만, 믿어달라고만 하면 설득력이 없습니다.

외부로 나가면 개인정보보호법을 위반하여 법적인 처벌이 뒤따릅니다.


그래서 스스로 확인하는 방법을 매뉴얼에 적어 두었습니다.

  • 방화벽 테스트: 앱의 외부 통신을 차단해도, 모델이 설치되어 있다면 녹음·STT·요약이 정상 동작해야 합니다.
  • 통신 내역 공개: 요약은 내 PC의 Ollama(127.0.0.1)와만 통신하고, 외부 통신은 최초 1회 Whisper 모델 다운로드뿐입니다.
  • 네트워크 모니터링: 직접 확인하고 싶다면 네트워크 모니터링 도구로 앱의 통신 대상을 살펴볼 수 있습니다.


하지만, 로컬 처리가 곧 법적 면책은 아닙니다.

녹음에 대한 동의, PC 접근 통제, 파일 보관·삭제는 사용하는 분의 책임이며, 소속 기관의 규정과 관련 법령을 확인해야 합니다. 또 AI의 음성 인식·요약 결과는 틀릴 수 있으니 이름, 숫자, 날짜, 약 이름은 반드시 원본과 대조해 주세요.



설치해 보기

필요한 것은 Ollama, 요약 모델(Qwen), Azimuth Scribe 세 가지입니다. (Whisper 모델은 첫 실행 때 자동으로 내려받습니다.)

[설치 3단계]


ollama pull qwen3:4b-instruct

자세한 설치 방법과 사용법은 사용자 매뉴얼(PDF)에 정리해 두었습니다.


다운로드: 깃 허브 링크

시연 영상: 유튜브 링크


마무리

정리하면,

  • 로컬 LLM의 최대 장점은 프라이버시와 통제·비용↓, 단점은 모델 크기·하드웨어·유지보수
  • 클라우드 LLM의 최대 장점은 성능과 편의, 단점은 데이터 전송과 종속성, 비용↑
  • 이 앱처럼 "이미 있는 글을 정리"하는 일에는 작은 로컬 모델로도 충분히 쓸 만하고, 민감한 내용이라면 더 큰 의미가 있다.


여러분이라면 어떤 일에 로컬 LLM을 써보고 싶으신가요?

궁금한 점은 댓글로, 감사합니다. 😊

댓글

이 블로그의 인기 게시물

Qt Designer 설치하기

MFC기반 화면 캡쳐앱 만들기

파이썬을 활용한 PID 제어기 GUI 구현