.NET 10 및 Angular Signals 기반의 '로컬 퍼스트(Local-First)' 엔터프라이즈 RAG (벡터 메모리) 아키텍처
요약
.NET 10, SQLite, Angular Signals를 활용하여 클라우드 의존성을 제거한 '로컬 퍼스트' 엔터프라이즈 RAG 아키텍처를 구축했습니다. 외부 라이브러리 없이 순수 C#으로 코사인 유사도 엔진을 구현하고, Google Gemini 임베딩을 지원하는 공급자 불가지론적 구조를 통해 모델 전환의 유연성을 확보했습니다.
핵심 포인트
- 클라우드 벡터 DB 의존성을 제거하고 SQLite를 활용한 로컬 퍼스트 인프라 구축
- Microsoft.Extensions.AI와 Google GenAI SDK를 통합하는 공급자 불가지론적 임베딩 래퍼 구현
- 외부 라이브러리 없이 고성능 코사인 유사도 계산 엔진을 순수 C#으로 직접 구현
- Angular 기반의 결정론적 해싱을 통해 SQLite 내 데이터 중복 및 비대화 방지
저의 .NET AI Architect Laboratory 프로젝트 개발 3단계 동안, 저는 외부의 비용이 많이 드는 클라우드 기반 벡터 데이터베이스 의존성(Vendor Lock-in)을 완전히 제거했습니다. 대신, .NET 10 코어, 로컬 SQLite 레이어, 그리고 Angular Signals를 기반으로 작동하는 로컬 퍼스트(Local-First) 엔터프라이즈 RAG 인프라를 구축했습니다. 제가 수행한 작업은 다음과 같습니다:
실험적 프리뷰 패키지 의존성 정리
지속적으로 버전 불일치, 불안정한 구조, 그리고 NU1904와 같은 취약성 경고를 유발했던 실험적인 SemanticKernel.Connectors 및 VectorData.Abstractions 프리뷰 패키지를 프로젝트에서 완전히 제거했습니다. 저는 아키텍처를 프레임워크 자체의 네이티브하고 안정적이며 장기 지원(LTS)되는 엔터프라이즈 패키지에 고정했습니다.
공급자 불가지론적(Provider-Agnostic) 임베딩 기질
저는 Microsoft의 새로운 엔터프라이즈 AI 표준(Microsoft.Extensions.AI)과 Google의 공식 GenAI SDK를 함께 추상화하는 GoogleEmbeddingGenerator라는 순수 C# 래퍼(wrapper)를 작성했습니다. 저는 Gemini text-embedding-004 모델에 의해 생성된 고차원 double[] 배열을 .NET 인터페이스가 기대하는 float[] 벡터로 동적으로 캐스팅(cast)했습니다.
아키텍처적 이점: 핵심 엔드포인트 아키텍처의 코드를 단 한 줄도 수정하지 않고, Program.cs 내부의 IoC (DI) 레지스트리만 변경함으로써 향후 단계에서 OpenAI 또는 완전히 로컬인 LLM 모델(Ollama/Llama 등)로 전환할 수 있는 완전한 유연성을 제공했습니다.
의존성 없는 순수 C# 코사인 유사도(Cosine Similarity) 엔진
벡터 간의 의미론적 근접성을 계산하기 위해, 무거운 외부 수학 라이브러리나 제3자 Python 서비스에 대한 의존성이 전혀 없는 엔진을 제작했습니다.
저는 .NET core에서 직접 실행되는 메모리 효율적이고 고성능의 코사인 유사도 행렬을 구현했습니다: public static float CosineSimilarity(float[] vectorA, float[] vectorB) { if (vectorA.Length != vectorB.Length) throw new ArgumentException("Vectors must have the same identical dimensions."); float dotProduct = 0.0f, normA = 0.0f, normB = 0.0f; for (int i = 0; i < vectorA.Length; i++) { dotProduct += vectorA[i] * vectorB[i]; normA += vectorA[i] * vectorA[i]; normB += vectorB[i] * vectorB[i]; } return (normA == 0.0f || normB == 0.0f) ? 0.0f : dotProduct / ((float)Math.Sqrt(normA) * (float)Math.Sqrt(normB)); } 데이터 증가 방지를 위한 결정론적 중복 제거 (Deterministic Deduplication Against Data Inflation)
시스템에 동일한 코드 블록이나 파일을 연속적으로 추가하는 경우 SQLite 테이블이 비대해지는 것을 방지하기 위해, 저는 파일 경로를 기반으로 Angular 프런트엔드 레이어(memory-dashboard.component.ts) 내부에 결정론적 Base64 경로 해싱 메커니즘을 구축했습니다. 각 파일 콘텐츠에 대해 엄격하게 고유하고 확정적인 Id가 생성되도록 보장함으로써, 저는 SQLite 네이티브 ON CONFLICT(Id) DO UPDATE 제약 조건을 트리거했고 데이터베이스 내의 중복 행 생성을 완벽하게 제거할 수 있었습니다.
지식 증강 에이전시 플로우 (Knowledge-Augmented Agency Flow)
저는 이렇게 생성한 로컬 벡터 메모리를 저희 자율 다중 도구 에이전트(/api/architect/inspect-autonomous)와 통합했습니다. 에이전트가 아키텍처 분석 작업을 받으면, 물리적 디스크의 파일을 직접 스캔하기 전에 백그라운드에서 이 로컬 SQLite 벡터 레이어에 쿼리를 실행합니다. 예를 들어, 사용자가 “프런트엔드 접근 포트를 검토해 주세요”와 같은 일반적인 목표를 제시하면, 저희 시맨틱 검색 엔진은 로컬 메모리에서 언급되지 않은 CORS 설정 코드 스니펫을 가져와 에이전트의 실시간 시스템 컨텍스트(Prompt)에 주입합니다. 그 결과, 에이전트는 현지화된 엔터프라이즈 도메인 경험으로 완전히 무장한 결정을 생성하게 됩니다.
🖥️ 대시보드 RAG 패널 미리보기
통합된 RAG 패널의 라이브 스크린 아티팩트(artifact)는 다음과 같이 작동합니다:
반응형 관리 보드: Angular Signals & Tailwind UI
저는 Angular의 반응형 시그널 (Signals) 아키텍처와 다크 테마의 Tailwind CSS v3 인터페이스를 사용하여 이 전체 로컬 벡터 스트림을 시각화했습니다. 단일 반응형 상태 플래그 (state flag)에 의해 구동되는 이 시스템은 코드 분석기 (Code Analyzer) 룸과 지식 RAG (Knowledge RAG) 룸 사이를 지연 시간 없이 매끄럽게 전환하며, 전체 제어 흐름을 하나의 콕핏 (cockpit)으로 변환합니다.
🔗 코드 살펴보기
다음 단계는 3단계 완료 후 진행될 '자동 코드 인제스션 파이프라인 (Automatic Code Ingestion Pipeline) 개발 (4단계)'입니다. 이 단계에서는 백그라운드에서 수정된 코드를 자동으로 추적하고 로컬 메모리를 즉시 업데이트하게 됩니다.
👉 GitHub 저장소: github.com/muratsuzen/dotnet-ai-lab
모델 그 자체는 우리가 대여하는 엔진일 뿐입니다. 진정한 가치는 아키텍처의 기질 (architectural substrate), 컨텍스트 (context), 그리고 그 주변에 우리가 구축하는 문서화에 있습니다. 이 실험실은 그 여정에 대한 저의 영구적인 디지털 로그북입니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기