🤖
1345 in / 5105 out / 6450 total tokens
Simon Willison이 자신의 LLM CLI 에코시스템을 대거 업데이트했다. 단순한 버전 bump가 아니라 구조적인 변화다. 게임 개발자가 익숙한 모듈화, 비동기 처리, 플러그인 아키텍처 관점에서 보면 이번 업데이트가 왜 중요한지 명확해진다.
🔥 핫 토픽
llm 0.30: CLI 도구의 정점
LLM CLI의 0.30 버전은 단순한 점진적 개선이 아니다. 이번 릴리스는 전체 아키텍처를 재설계한 마일스톤이다. 핵심은 플러그인 시스템의 완전한 분리와 비동기 처리 지원이다. 기존에는 동기 호출이 기본이었고, 일부 플러그인만 비동기를 지원했다. 0.30부터는 내부적으로 asyncio를 기본으로 돌리면서, 레거시 동기 플러그인도 자동으로 스레드 풀에서 실행해 호환성을 유지한다.
게임 서버 개발자 입장에서 이건 꽤 큰 소식이다. UE5 C++에서도 비동기 처리를 Tick 기반으로 돌리다가 AsyncTask로 넘어갈 때 겪었던 그 전환이다. I/O 바운드 작업을 메인 루프에서 분리해서 전체 처리량을 늘리는 패턴이다. LLM API 호출은 네트워크 지연이 크니, 비동기 처리가 필수적이다. 여러 모델에 동시에 요청을 날려서 응답 시간을 단축할 수 있게 됐다.
또 하나 중요한 건 설정 파일 구조의 변화다. 이제 모델 별칭(alias), 기본 파라미터, 로깅 설정을 YAML로 깔끔하게 관리한다. 프로젝트 단위로 .llm/config를 두고, 팀원들이 동일한 설정을 공유할 수 있다. 이건 게임 프로젝트에서 DefaultEngine.ini를 버전 관리에 넣는 것과 같은 맥락이다. 협업 시 설정 충돌을 줄여준다.
llm-all-models-async 0.1: 진짜 비동기의 시작
이 플러그인은 llm 0.30의 비동기 기능을 완전히 활용하도록 설계됐다. 이름에서 짐작할 수 있듯, 모든 등록된 모델에 비동기로 접근하는 통일된 인터페이스를 제공한다. 기존에는 OpenAI, Anthropic, 로컬 모델마다 서로 다른 호출 방식을 써야 했다. 이제는 하나의 async call로 추상화된다.
실무 관점에서 이게 왜 중요한가. 게임 개발에서도 백엔드 API를 호출할 때, A/B 테스트나 폴백 로직을 위해 여러 엔드포인트를 동시에 때려보는 경우가 있다. LLM도 마찬가지다. GPT-4o에 요청을 보내면서 동시에 Claude 3.5 Sonnet에도 요청해서, 더 빠른 응답을 받아쓰거나 결과를 비교하는 패턴이 가능해진다. 물론 비용이 두 배로 들긴 하지만, 프로덕션에서 응답 시간이 critical할 때 유용하다.
기술적으로는 asyncio.gather() 위에 깔끔한 래퍼를 얹은 형태다. 타임아웃 처리, 예외 격리, 부분 실패 시 fallback 같은 세부 로직이 내장돼 있다. 직접 짜면 꽤 귀찮은 보일러플레이트를 플러그인이 대신 처리해주는 셈이다. UE5에서 HttpManager 쓰는 것과 비슷한 편의성이다.
앞서 언급한 llm 0.30의 비동기 기반 위에 올라가는 첫 번째 "진짜" 비동기 플러그인이라는 점에서 의미가 크다. 이후 출시될 다른 플러그인들도 이 패턴을 따를 것으로 보인다.
출처: Simon Willison - llm-all-models-async 0.1
datasette-llm 0.1a4: 데이터베이스와 LLM의 만남
Datasette는 Simon Willison이 오랫동안 개발해온 데이터 탐색 도구다. SQLite 데이터베이스를 브라우저에서 탐색하고 쿼리할 수 있는 웹 인터페이스다. datasette-llm은 이 Datasette에 LLM 기능을 통합하는 플러그인이다. 0.1a4는 알파 버전이지만, 핵심 기능은 이미 안정적이다.
이 플러그인이 하는 일은 두 가지다. 첫째, 데이터베이스의 텍스트 컬럼에 대해 LLM으로 임베딩을 생성해서 벡터 검색을 가능하게 한다. 둘째, 자연어로 쿼리를 입력하면 SQL로 변환해 실행한다. RAG(검색 증강 생성) 파이프라인을 Datasette 안에서 바로 구축할 수 있다는 얘기다.
게임 개발자 입장에서 생각해보자. 게임 로그, 플레이어 행동 데이터, 인게임 채팅 기록 같은 텍스트 데이터가 SQLite로 쌓여 있다. 이걸 LLM으로 분석하고 싶은데, 파이썬 스크립트를 따로 짜거나 LangChain 같은 프레임워크를 세팅하려면 시간이 걸린다. datasette-llm을 쓰면 Datasette 인스턴스 하나만 띄워놓고 웹 UI에서 바로 실험할 수 있다.
기술적으로는 SQLite의 sqlite-vss 확장이나 외부 벡터 DB를 백엔드로 쓸 수 있다. 임베딩 모델은 OpenAI의 text-embedding-3-small이 기본이지만, Ollama로 로컬 모델도 가능하다. 데이터가 민감해서 클라우드 API를 못 쓰는 환경에서도 유용하다.
아직 알파라 프로덕션 직접 투입은 무리지만, 프로토타이핑이나 내부 툴로는 충분하다. Simon Willison의 프로젝트 특성상 알파라고 해서 코드 품질이 낮은 건 아니다. 오히려 API가 변경될 수 있다는 의미에 가깝다.
출처: Simon Willison - datasette-llm 0.1a4
llm-echo 0.4: 테스트 더블의 완성
llm-echo는 LLM 플러그인을 위한 "에코" 서비스다. 요청을 그대로 돌려주거나, 미리 정의된 응답을 반환한다. Mock 서버, 테스트 더블, 페이크(Fake) 구현이라고 불리는 패턴이다. 0.4 버전에서는 응답 지연 시뮬레이션, 에러 주입, 스트리밍 응답 테스트가 추가됐다.
이게 왜 중요한가. LLM을 쓰는 코드를 테스트할 때, 실제 API를 호출하면 비용이 들고 속도도 느리다. 하루에 몇 번이고 돌려야 하는 CI/CD 파이프라인에서는 더 큰 문제다. llm-echo를 쓰면 API 키 없이, 네트워크 없이 로컬에서 테스트할 수 있다. 응답 형식도 실제 OpenAI API와 동일하게 맞출 수 있다.
게임 개발에서도 비슷한 패턴을 쓴다. 백엔드 API가 아직 준비되지 않았을 때 Mock 서버를 띄워서 클라이언트 개발을 진행한다. UE5에서는 Automation Testing Framework와 함께 Mock 객체를 많이 쓴다. llm-echo는 LLM 영역에서 같은 문제를 해결한다.
0.4에서 추가된 기능들이 특히 반갑다. 타임아웃 테스트를 위해 의도적으로 30초 지연을 줄 수 있다. Rate limit 에러를 시뮬레이션해서 재시도 로직이 제대로 도는지 확인할 수 있다. 스트리밍 응답의 청크 단위 전송도 테스트 가능하다. 이런 엣지 케이스들은 실제 API로는 재현하기 어렵거나 비용이 많이 든다.
llm 0.30의 플러그인 아키텍처를 잘 보여주는 예시이기도 하다. 핵심 기능은 아니지만, 에코시스템의 건강함을 보여주는 지표다. 테스트 도구가 잘 갖춰져 있다는 건 프로덕션 사용자를 염두에 둔 설계라는 뜻이다.
출처: Simon Willison - llm-echo 0.4
💭 총평
Simon Willison의 이번 업데이트 묶음은 단순한 기능 추가가 아니라 생태계의 성숙을 보여준다. 코어(llm 0.30)가 비동기 기반으로 재설계되고, 그 위에 실용적인 플러그인들(all-models-async, datasette-llm)과 테스트 도구(llm-echo)가 올라가는 구조다.
게임 엔진으로 치면 언리얼 엔진 4에서 5로 넘어갈 때의 변화와 비슷하다. 겉으로 보이는 기능보다는 내부 아키텍처가 바뀌어서 앞으로 확장성이 좋아지는 변화다. 당장은 체감하기 어렵지만, 1년 뒤에는 "그때 바꾸길 잘했다"고 생각하게 될 종류의 업데이트다.
LLM CLI를 이미 쓰고 있다면 0.30으로 업그레이드하고, 아직이라면 지금이 시작하기 좋은 시점이다. 플러그인 생태계가 갖춰져 있어서, 복잡한 세팅 없이도 꽤 많은 걸 할 수 있다.
LLM CLI는 이제 "장난감"에서 "도구"로 넘어갔다. 비동기와 플러그인 아키텍처가 그 차이다.