{"componentChunkName":"component---src-templates-blog-post-js","path":"/springboot/Spring-AI와-엣지-배포-LLM-서비스-아키텍처-구축-가이드/","result":{"data":{"site":{"siteMetadata":{"title":"Bottlehs Tech Blog","description":"웹·앱·AI 개발자 전병훈(bottlehs)의 기술 블로그. AI·LLM, JavaScript·Vue, Spring Boot, 알고리즘, 블록체인 실무 가이드를 다룹니다","siteUrl":"https://www.bottlehs.dev","author":{"name":"Jeon Byung Hun","summary":"개발을 즐기는 bottlehs - Engineer, MS, AI, FE, BE, OS, IOT, Blockchain, 설계, 테스트"},"social":{"github":"bottlehs","codepen":"bottlehs"}}},"markdownRemark":{"id":"7fcca3ff-5d7b-5f69-a0f6-033e4897b516","excerpt":"Spring 팀이 2024년 공개한 Spring AI는 LLM API 연동과 추론 워크플로우를 Spring Boot 애플리케이션에 자연스럽게 녹여준다. 동시에 기업들은 데이터 주권과 지연 시간 문제를 해결하기 위해 엣지(Edge…","html":"<p>Spring 팀이 2024년 공개한 Spring AI는 LLM API 연동과 추론 워크플로우를 Spring Boot 애플리케이션에 자연스럽게 녹여준다. 동시에 기업들은 데이터 주권과 지연 시간 문제를 해결하기 위해 엣지(Edge) 환경에서 모델을 실행하려는 요구가 커지고 있다. 이 글은 Spring AI를 활용해 엣지-클라우드 하이브리드 LLM 서비스를 설계하고 구현하는 방법을 제시한다.</p>\n<h2 id=\"1-spring-ai-개요\" style=\"position:relative;\"><a href=\"#1-spring-ai-%EA%B0%9C%EC%9A%94\" aria-label=\"1 spring ai 개요 permalink\" class=\"anchor-header before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>1. Spring AI 개요</h2>\n<ul>\n<li><strong>Spring Boot 친화성</strong>: <code class=\"language-text\">ChatClient</code>, <code class=\"language-text\">EmbeddingClient</code>, <code class=\"language-text\">ToolClient</code> 등 빈을 통해 OpenAI, Anthropic, Azure OpenAI, Ollama 등 다양한 백엔드를 추상화한다.</li>\n<li><strong>구성 기반 프로그래밍</strong>: <code class=\"language-text\">application.yml</code>에 <code class=\"language-text\">spring.ai.openai.*</code> 또는 <code class=\"language-text\">spring.ai.ollama.*</code>를 선언하여 환경을 쉽게 전환한다.</li>\n<li><strong>유연한 프롬프트 관리</strong>: 템플릿 엔진(<code class=\"language-text\">Thymeleaf</code>, <code class=\"language-text\">Mustache</code>, <code class=\"language-text\">Velocity</code>)을 통해 프롬프트를 코드와 분리하여 관리할 수 있다.</li>\n<li><strong>RAG 지원</strong>: <code class=\"language-text\">VectorStore</code> 추상화를 활용해 Elasticsearch, Redis, Milvus 등 다양한 벡터 스토어와 연동한다.</li>\n</ul>\n<h2 id=\"2-엣지-llm-배포-시나리오\" style=\"position:relative;\"><a href=\"#2-%EC%97%A3%EC%A7%80-llm-%EB%B0%B0%ED%8F%AC-%EC%8B%9C%EB%82%98%EB%A6%AC%EC%98%A4\" aria-label=\"2 엣지 llm 배포 시나리오 permalink\" class=\"anchor-header before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>2. 엣지 LLM 배포 시나리오</h2>\n<h3 id=\"2-1-왜-엣지인가\" style=\"position:relative;\"><a href=\"#2-1-%EC%99%9C-%EC%97%A3%EC%A7%80%EC%9D%B8%EA%B0%80\" aria-label=\"2 1 왜 엣지인가 permalink\" class=\"anchor-header before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>2-1. 왜 엣지인가?</h3>\n<ul>\n<li>데이터 주권: 고객 정보를 외부 클라우드에 보내지 않고 현장에서 처리한다.</li>\n<li>지연 시간: 제조 라인, 콜센터, 오프라인 매장에서 즉시 응답이 필요할 때 유리하다.</li>\n<li>비용 최적화: 대량 호출을 중앙 클라우드 모델로 보내는 비용보다 자체 추론이 유리할 수 있다.</li>\n</ul>\n<h3 id=\"2-2-엣지-환경-특성\" style=\"position:relative;\"><a href=\"#2-2-%EC%97%A3%EC%A7%80-%ED%99%98%EA%B2%BD-%ED%8A%B9%EC%84%B1\" aria-label=\"2 2 엣지 환경 특성 permalink\" class=\"anchor-header before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>2-2. 엣지 환경 특성</h3>\n<ul>\n<li>제한된 GPU/CPU: 양자화 모델, LoRA 어댑터, 온디맨드 로딩 전략이 필요하다.</li>\n<li>네트워크 제약: 중앙 서버와의 동기화, 모델 업데이트 배포를 고려해야 한다.</li>\n<li>운영 자동화: OTA(Over-the-Air) 업데이트, 헬스 체크, 리모트 로깅 체계가 필수다.</li>\n</ul>\n<h2 id=\"3-아키텍처-설계\" style=\"position:relative;\"><a href=\"#3-%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%98-%EC%84%A4%EA%B3%84\" aria-label=\"3 아키텍처 설계 permalink\" class=\"anchor-header before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>3. 아키텍처 설계</h2>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">사용자 → Spring Boot API Gateway → (프롬프트 필터) → 라우팅 로직\n                                     ├─ 엣지 추론 노드 (Ollama/ONNX Runtime)\n                                     └─ 클라우드 LLM 백엔드 (Azure OpenAI 등)</code></pre></div>\n<h3 id=\"3-1-구성-요소\" style=\"position:relative;\"><a href=\"#3-1-%EA%B5%AC%EC%84%B1-%EC%9A%94%EC%86%8C\" aria-label=\"3 1 구성 요소 permalink\" class=\"anchor-header before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>3-1. 구성 요소</h3>\n<ul>\n<li><strong>Spring Boot API Gateway</strong>: 인증, 요청 로깅, 정책 적용의 관문.</li>\n<li><strong>Spring AI 라우터</strong>: 추론 요청을 엣지 또는 클라우드로 분기. <code class=\"language-text\">ChatClient</code> 멀티 백엔드 구성이 핵심이다.</li>\n<li><strong>엣지 추론 노드</strong>: Ollama, TensorRT-LLM, vLLM 등을 사용해 경량 모델을 호스팅한다.</li>\n<li><strong>벡터 스토어</strong>: RAG 컨텍스트 제공을 위해 중앙 혹은 엣지에 Redis/Weaviate를 배치한다.</li>\n<li><strong>옵저버빌리티 스택</strong>: Prometheus, Grafana, OpenTelemetry를 통해 추론 지표를 수집한다.</li>\n</ul>\n<h3 id=\"3-2-라우팅-전략\" style=\"position:relative;\"><a href=\"#3-2-%EB%9D%BC%EC%9A%B0%ED%8C%85-%EC%A0%84%EB%9E%B5\" aria-label=\"3 2 라우팅 전략 permalink\" class=\"anchor-header before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>3-2. 라우팅 전략</h3>\n<ul>\n<li><strong>SLA 기반 라우팅</strong>: 응답 지연이 300ms 이하 필요 시 엣지 노드 우선.</li>\n<li><strong>정책 기반 라우팅</strong>: 개인정보 포함 여부에 따라 엣지 전용 모델을 사용한다.</li>\n<li><strong>비용 기반 라우팅</strong>: 월간 사용량이 임계치를 넘으면 대체 모델로 전환한다.</li>\n</ul>\n<p>Spring AI에서는 <code class=\"language-text\">DelegatingChatClient</code>를 구현해 조건별로 다른 <code class=\"language-text\">ChatClient</code> 빈을 선택할 수 있다.</p>\n<div class=\"gatsby-highlight\" data-language=\"java\"><pre class=\"language-java\"><code class=\"language-java\"><span class=\"token annotation punctuation\">@Component</span>\n<span class=\"token keyword\">public</span> <span class=\"token keyword\">class</span> <span class=\"token class-name\">PolicyAwareChatClient</span> <span class=\"token keyword\">implements</span> <span class=\"token class-name\">ChatClient</span> <span class=\"token punctuation\">{</span>\n\n    <span class=\"token keyword\">private</span> <span class=\"token keyword\">final</span> <span class=\"token class-name\">ChatClient</span> edgeClient<span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">private</span> <span class=\"token keyword\">final</span> <span class=\"token class-name\">ChatClient</span> cloudClient<span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">private</span> <span class=\"token keyword\">final</span> <span class=\"token class-name\">DataClassifier</span> classifier<span class=\"token punctuation\">;</span>\n\n    <span class=\"token keyword\">public</span> <span class=\"token class-name\">PolicyAwareChatClient</span><span class=\"token punctuation\">(</span><span class=\"token annotation punctuation\">@Qualifier</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"edgeChatClient\"</span><span class=\"token punctuation\">)</span> <span class=\"token class-name\">ChatClient</span> edgeClient<span class=\"token punctuation\">,</span>\n                                 <span class=\"token annotation punctuation\">@Qualifier</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"cloudChatClient\"</span><span class=\"token punctuation\">)</span> <span class=\"token class-name\">ChatClient</span> cloudClient<span class=\"token punctuation\">,</span>\n                                 <span class=\"token class-name\">DataClassifier</span> classifier<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n        <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>edgeClient <span class=\"token operator\">=</span> edgeClient<span class=\"token punctuation\">;</span>\n        <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>cloudClient <span class=\"token operator\">=</span> cloudClient<span class=\"token punctuation\">;</span>\n        <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>classifier <span class=\"token operator\">=</span> classifier<span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n\n    <span class=\"token annotation punctuation\">@Override</span>\n    <span class=\"token keyword\">public</span> <span class=\"token class-name\">ChatResponse</span> <span class=\"token function\">call</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">ChatRequest</span> request<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n        <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>classifier<span class=\"token punctuation\">.</span><span class=\"token function\">containsSensitiveData</span><span class=\"token punctuation\">(</span>request<span class=\"token punctuation\">.</span><span class=\"token function\">getMessages</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n            <span class=\"token keyword\">return</span> edgeClient<span class=\"token punctuation\">.</span><span class=\"token function\">call</span><span class=\"token punctuation\">(</span>request<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n        <span class=\"token punctuation\">}</span>\n        <span class=\"token keyword\">return</span> cloudClient<span class=\"token punctuation\">.</span><span class=\"token function\">call</span><span class=\"token punctuation\">(</span>request<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<h2 id=\"4-모델-배포-패턴\" style=\"position:relative;\"><a href=\"#4-%EB%AA%A8%EB%8D%B8-%EB%B0%B0%ED%8F%AC-%ED%8C%A8%ED%84%B4\" aria-label=\"4 모델 배포 패턴 permalink\" class=\"anchor-header before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>4. 모델 배포 패턴</h2>\n<h3 id=\"4-1-엣지-추론-노드-구성\" style=\"position:relative;\"><a href=\"#4-1-%EC%97%A3%EC%A7%80-%EC%B6%94%EB%A1%A0-%EB%85%B8%EB%93%9C-%EA%B5%AC%EC%84%B1\" aria-label=\"4 1 엣지 추론 노드 구성 permalink\" class=\"anchor-header before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>4-1. 엣지 추론 노드 구성</h3>\n<ul>\n<li><strong>컨테이너화</strong>: Docker + NVIDIA Container Toolkit으로 GPU를 관리한다.</li>\n<li><strong>모델 관리</strong>: OCI 레지스트리에 모델 파일(gguf, safetensors)을 저장하고 버전 태깅한다.</li>\n<li><strong>스타트업 스크립트</strong>: <code class=\"language-text\">docker compose</code>를 이용해 Ollama, 텔레메트리, 헬스체크 에이전트를 동시에 기동한다.</li>\n</ul>\n<h3 id=\"4-2-중앙-제어와-동기화\" style=\"position:relative;\"><a href=\"#4-2-%EC%A4%91%EC%95%99-%EC%A0%9C%EC%96%B4%EC%99%80-%EB%8F%99%EA%B8%B0%ED%99%94\" aria-label=\"4 2 중앙 제어와 동기화 permalink\" class=\"anchor-header before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>4-2. 중앙 제어와 동기화</h3>\n<ul>\n<li><strong>모델 배포 파이프라인</strong>: GitOps(ArgoCD) 또는 MLOps 도구(KServe, Seldon)로 엣지 노드에 배포한다.</li>\n<li><strong>피드백 루프</strong>: Spring Boot가 수집한 사용자 피드백을 중앙 데이터 레이크로 전송하여 재학습에 활용한다.</li>\n<li><strong>버전 롤백</strong>: 실패한 모델 롤아웃을 즉시 되돌릴 수 있도록 Canary 릴리스 전략을 사용한다.</li>\n</ul>\n<h2 id=\"5-보안과-거버넌스\" style=\"position:relative;\"><a href=\"#5-%EB%B3%B4%EC%95%88%EA%B3%BC-%EA%B1%B0%EB%B2%84%EB%84%8C%EC%8A%A4\" aria-label=\"5 보안과 거버넌스 permalink\" class=\"anchor-header before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>5. 보안과 거버넌스</h2>\n<ul>\n<li><strong>네트워크 분리</strong>: 엣지 노드는 전용 VPN 혹은 Zero Trust 네트워크로 보호한다.</li>\n<li><strong>프롬프트 방어</strong>: Spring AI의 <code class=\"language-text\">PromptTemplate</code>에 정책을 삽입하고, 응답 필터로 민감어를 차단한다.</li>\n<li><strong>비용 통제</strong>: 각 백엔드 호출량을 <code class=\"language-text\">MeterRegistry</code>에 기록해 월간 비용 리포트를 자동 생성한다.</li>\n<li><strong>감사 로그</strong>: 요청·응답 페이로드는 비식별화한 뒤 <code class=\"language-text\">AuditEventRepository</code>에 보관한다.</li>\n</ul>\n<h2 id=\"6-성능-최적화-팁\" style=\"position:relative;\"><a href=\"#6-%EC%84%B1%EB%8A%A5-%EC%B5%9C%EC%A0%81%ED%99%94-%ED%8C%81\" aria-label=\"6 성능 최적화 팁 permalink\" class=\"anchor-header before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>6. 성능 최적화 팁</h2>\n<ul>\n<li><strong>캐시된 컨텍스트</strong>: RAG 질의에 자주 사용되는 문서를 엣지 노드에 캐싱해 네트워크 왕복을 줄인다.</li>\n<li><strong>동시성 제어</strong>: Spring WebFlux와 <code class=\"language-text\">Project Reactor</code>를 활용해 비동기 추론 호출을 처리한다.</li>\n<li><strong>모델 압축</strong>: GPTQ, AWQ, LoRA 등 양자화 기법을 적용해 7B 모델도 경량 GPU에서 운영한다.</li>\n<li><strong>배치 추론</strong>: 대량 요청은 클라우드 백엔드에서 배치 처리 후 응답을 스트리밍한다.</li>\n</ul>\n<h2 id=\"7-운영-모니터링-대시보드-예시\" style=\"position:relative;\"><a href=\"#7-%EC%9A%B4%EC%98%81-%EB%AA%A8%EB%8B%88%ED%84%B0%EB%A7%81-%EB%8C%80%EC%8B%9C%EB%B3%B4%EB%93%9C-%EC%98%88%EC%8B%9C\" aria-label=\"7 운영 모니터링 대시보드 예시 permalink\" class=\"anchor-header before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>7. 운영 모니터링 대시보드 예시</h2>\n<ul>\n<li>추론 성공률</li>\n<li>평균 지연 및 퍼센타일(50/95/99)</li>\n<li>엣지 vs 클라우드 라우팅 비율</li>\n<li>모델 버전별 호출량</li>\n<li>사용자 피드백 점수(Thumbs Up/Down)</li>\n</ul>\n<p>OpenTelemetry를 통해 <code class=\"language-text\">spring.ai.client.response.latency</code> 같은 커스텀 메트릭을 노출하고, Grafana에 대시보드를 구성한다.</p>\n<h2 id=\"8-단계별-실행-로드맵\" style=\"position:relative;\"><a href=\"#8-%EB%8B%A8%EA%B3%84%EB%B3%84-%EC%8B%A4%ED%96%89-%EB%A1%9C%EB%93%9C%EB%A7%B5\" aria-label=\"8 단계별 실행 로드맵 permalink\" class=\"anchor-header before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>8. 단계별 실행 로드맵</h2>\n<ol>\n<li><strong>준비 단계</strong>: Spring AI 의존성을 프로젝트에 추가하고, 기본 <code class=\"language-text\">ChatClient</code>를 구성한다.</li>\n<li><strong>PoC 단계</strong>: 엣지 노드(예: Jetson, NUC)에 Ollama/ggml 모델을 설치하고 Spring Boot에서 호출한다.</li>\n<li><strong>하이브리드 정착</strong>: 정책 기반 라우팅, 캐시, 벡터 스토어를 연결한다.</li>\n<li><strong>운영화</strong>: 모니터링·알림·자동 롤백 체계를 구축한다.</li>\n<li><strong>지속 개선</strong>: 사용자 피드백 데이터를 기반으로 프롬프트와 모델을 지속적으로 최적화한다.</li>\n</ol>\n<hr>\n<p>Spring AI는 스프링 생태계에 자리 잡은 개발자 경험을 그대로 유지하면서 LLM 기능을 애플리케이션에 주입할 수 있게 한다. 여기에 엣지 추론 인프라를 결합하면 민감 데이터를 보호하고 지연 시간을 줄이는 동시에, 중앙 클라우드의 대규모 모델을 필요에 따라 호출하는 유연성을 확보할 수 있다. 하이브리드 아키텍처를 체계적으로 설계하고 운영 자동화를 갖춘다면, 엔터프라이즈 환경에서도 신뢰성 높은 LLM 서비스를 빠르게 론칭할 수 있다.</p>","tableOfContents":"<ul>\n<li><a href=\"/springboot/Spring-AI%EC%99%80-%EC%97%A3%EC%A7%80-%EB%B0%B0%ED%8F%AC-LLM-%EC%84%9C%EB%B9%84%EC%8A%A4-%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%98-%EA%B5%AC%EC%B6%95-%EA%B0%80%EC%9D%B4%EB%93%9C/#1-spring-ai-%EA%B0%9C%EC%9A%94\">1. Spring AI 개요</a></li>\n<li>\n<p><a href=\"/springboot/Spring-AI%EC%99%80-%EC%97%A3%EC%A7%80-%EB%B0%B0%ED%8F%AC-LLM-%EC%84%9C%EB%B9%84%EC%8A%A4-%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%98-%EA%B5%AC%EC%B6%95-%EA%B0%80%EC%9D%B4%EB%93%9C/#2-%EC%97%A3%EC%A7%80-llm-%EB%B0%B0%ED%8F%AC-%EC%8B%9C%EB%82%98%EB%A6%AC%EC%98%A4\">2. 엣지 LLM 배포 시나리오</a></p>\n<ul>\n<li><a href=\"/springboot/Spring-AI%EC%99%80-%EC%97%A3%EC%A7%80-%EB%B0%B0%ED%8F%AC-LLM-%EC%84%9C%EB%B9%84%EC%8A%A4-%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%98-%EA%B5%AC%EC%B6%95-%EA%B0%80%EC%9D%B4%EB%93%9C/#2-1-%EC%99%9C-%EC%97%A3%EC%A7%80%EC%9D%B8%EA%B0%80\">2-1. 왜 엣지인가?</a></li>\n<li><a href=\"/springboot/Spring-AI%EC%99%80-%EC%97%A3%EC%A7%80-%EB%B0%B0%ED%8F%AC-LLM-%EC%84%9C%EB%B9%84%EC%8A%A4-%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%98-%EA%B5%AC%EC%B6%95-%EA%B0%80%EC%9D%B4%EB%93%9C/#2-2-%EC%97%A3%EC%A7%80-%ED%99%98%EA%B2%BD-%ED%8A%B9%EC%84%B1\">2-2. 엣지 환경 특성</a></li>\n</ul>\n</li>\n<li>\n<p><a href=\"/springboot/Spring-AI%EC%99%80-%EC%97%A3%EC%A7%80-%EB%B0%B0%ED%8F%AC-LLM-%EC%84%9C%EB%B9%84%EC%8A%A4-%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%98-%EA%B5%AC%EC%B6%95-%EA%B0%80%EC%9D%B4%EB%93%9C/#3-%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%98-%EC%84%A4%EA%B3%84\">3. 아키텍처 설계</a></p>\n<ul>\n<li><a href=\"/springboot/Spring-AI%EC%99%80-%EC%97%A3%EC%A7%80-%EB%B0%B0%ED%8F%AC-LLM-%EC%84%9C%EB%B9%84%EC%8A%A4-%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%98-%EA%B5%AC%EC%B6%95-%EA%B0%80%EC%9D%B4%EB%93%9C/#3-1-%EA%B5%AC%EC%84%B1-%EC%9A%94%EC%86%8C\">3-1. 구성 요소</a></li>\n<li><a href=\"/springboot/Spring-AI%EC%99%80-%EC%97%A3%EC%A7%80-%EB%B0%B0%ED%8F%AC-LLM-%EC%84%9C%EB%B9%84%EC%8A%A4-%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%98-%EA%B5%AC%EC%B6%95-%EA%B0%80%EC%9D%B4%EB%93%9C/#3-2-%EB%9D%BC%EC%9A%B0%ED%8C%85-%EC%A0%84%EB%9E%B5\">3-2. 라우팅 전략</a></li>\n</ul>\n</li>\n<li>\n<p><a href=\"/springboot/Spring-AI%EC%99%80-%EC%97%A3%EC%A7%80-%EB%B0%B0%ED%8F%AC-LLM-%EC%84%9C%EB%B9%84%EC%8A%A4-%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%98-%EA%B5%AC%EC%B6%95-%EA%B0%80%EC%9D%B4%EB%93%9C/#4-%EB%AA%A8%EB%8D%B8-%EB%B0%B0%ED%8F%AC-%ED%8C%A8%ED%84%B4\">4. 모델 배포 패턴</a></p>\n<ul>\n<li><a href=\"/springboot/Spring-AI%EC%99%80-%EC%97%A3%EC%A7%80-%EB%B0%B0%ED%8F%AC-LLM-%EC%84%9C%EB%B9%84%EC%8A%A4-%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%98-%EA%B5%AC%EC%B6%95-%EA%B0%80%EC%9D%B4%EB%93%9C/#4-1-%EC%97%A3%EC%A7%80-%EC%B6%94%EB%A1%A0-%EB%85%B8%EB%93%9C-%EA%B5%AC%EC%84%B1\">4-1. 엣지 추론 노드 구성</a></li>\n<li><a href=\"/springboot/Spring-AI%EC%99%80-%EC%97%A3%EC%A7%80-%EB%B0%B0%ED%8F%AC-LLM-%EC%84%9C%EB%B9%84%EC%8A%A4-%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%98-%EA%B5%AC%EC%B6%95-%EA%B0%80%EC%9D%B4%EB%93%9C/#4-2-%EC%A4%91%EC%95%99-%EC%A0%9C%EC%96%B4%EC%99%80-%EB%8F%99%EA%B8%B0%ED%99%94\">4-2. 중앙 제어와 동기화</a></li>\n</ul>\n</li>\n<li><a href=\"/springboot/Spring-AI%EC%99%80-%EC%97%A3%EC%A7%80-%EB%B0%B0%ED%8F%AC-LLM-%EC%84%9C%EB%B9%84%EC%8A%A4-%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%98-%EA%B5%AC%EC%B6%95-%EA%B0%80%EC%9D%B4%EB%93%9C/#5-%EB%B3%B4%EC%95%88%EA%B3%BC-%EA%B1%B0%EB%B2%84%EB%84%8C%EC%8A%A4\">5. 보안과 거버넌스</a></li>\n<li><a href=\"/springboot/Spring-AI%EC%99%80-%EC%97%A3%EC%A7%80-%EB%B0%B0%ED%8F%AC-LLM-%EC%84%9C%EB%B9%84%EC%8A%A4-%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%98-%EA%B5%AC%EC%B6%95-%EA%B0%80%EC%9D%B4%EB%93%9C/#6-%EC%84%B1%EB%8A%A5-%EC%B5%9C%EC%A0%81%ED%99%94-%ED%8C%81\">6. 성능 최적화 팁</a></li>\n<li><a href=\"/springboot/Spring-AI%EC%99%80-%EC%97%A3%EC%A7%80-%EB%B0%B0%ED%8F%AC-LLM-%EC%84%9C%EB%B9%84%EC%8A%A4-%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%98-%EA%B5%AC%EC%B6%95-%EA%B0%80%EC%9D%B4%EB%93%9C/#7-%EC%9A%B4%EC%98%81-%EB%AA%A8%EB%8B%88%ED%84%B0%EB%A7%81-%EB%8C%80%EC%8B%9C%EB%B3%B4%EB%93%9C-%EC%98%88%EC%8B%9C\">7. 운영 모니터링 대시보드 예시</a></li>\n<li><a href=\"/springboot/Spring-AI%EC%99%80-%EC%97%A3%EC%A7%80-%EB%B0%B0%ED%8F%AC-LLM-%EC%84%9C%EB%B9%84%EC%8A%A4-%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%98-%EA%B5%AC%EC%B6%95-%EA%B0%80%EC%9D%B4%EB%93%9C/#8-%EB%8B%A8%EA%B3%84%EB%B3%84-%EC%8B%A4%ED%96%89-%EB%A1%9C%EB%93%9C%EB%A7%B5\">8. 단계별 실행 로드맵</a></li>\n</ul>","wordCount":{"words":612},"fields":{"slug":"/springboot/Spring-AI와-엣지-배포-LLM-서비스-아키텍처-구축-가이드/","image":null,"faq":[]},"frontmatter":{"title":"Spring AI와 엣지 배포 LLM 서비스 아키텍처 구축 가이드","date":"2025년 11월 7일","dateISO":"2025-11-07T00:00:00.000Z","updatedISO":null,"category":"springboot","description":"Spring AI 프로젝트와 엣지 추론 인프라를 결합하여 LLM 서비스를 설계하는 방법을 아키텍처, 구현 패턴, 운영 전략 관점에서 정리합니다.","tags":["Spring AI","Spring Boot","LLM 서비스","엣지 컴퓨팅","AI 아키텍처","Observability"]}}},"pageContext":{"slug":"/springboot/Spring-AI와-엣지-배포-LLM-서비스-아키텍처-구축-가이드/","previous":{"fields":{"slug":"/algorithm/퀵-정렬-quick-sort/"},"frontmatter":{"title":"퀵 정렬 (Quick Sort)","tags":["퀵 정렬","Quick Sort","정렬","알고리즘","Algorithm","JavaScript"]}},"next":{"fields":{"slug":"/blockchain/소버린-롤업과-모듈형-블록체인-아키텍처/"},"frontmatter":{"title":"소버린 롤업과 모듈형 블록체인 아키텍처","tags":["모듈형 블록체인","소버린 롤업","Rollup","블록체인 아키텍처","Celestia","EigenLayer"]}}}},"staticQueryHashes":["213619243","3262363727"]}