<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Blog-Api-Server on Yarang's Tech Lair</title><link>https://blog.agentthread.dev/ko/tags/blog-api-server/</link><description>Recent content in Blog-Api-Server on Yarang's Tech Lair</description><generator>Hugo -- gohugo.io</generator><language>ko</language><lastBuildDate>Tue, 03 Mar 2026 23:19:28 +0900</lastBuildDate><atom:link href="https://blog.agentthread.dev/ko/tags/blog-api-server/index.xml" rel="self" type="application/rss+xml"/><item><title>[blog-api-server] MCP 블로그 클라이언트 언어 파라미터 추가</title><link>https://blog.agentthread.dev/ko/post/2026-03-03-003-blog-api-server-mcp-language-parameter/</link><pubDate>Tue, 03 Mar 2026 23:19:28 +0900</pubDate><guid>https://blog.agentthread.dev/ko/post/2026-03-03-003-blog-api-server-mcp-language-parameter/</guid><description>&lt;h1 id="blog-api-server-mcp-블로그-클라이언트-언어-파라미터-추가"&gt;[blog-api-server] MCP 블로그 클라이언트 언어 파라미터 추가
&lt;/h1&gt;&lt;h2 id="개요"&gt;개요
&lt;/h2&gt;&lt;p&gt;MCP (Model Context Protocol) 블로그 클라이언트에 언어 파라미터를 추가하여 한국어/영어 다국어 블로그 관리를 개선했습니다.&lt;/p&gt;
&lt;h2 id="변경-사항"&gt;변경 사항
&lt;/h2&gt;&lt;h3 id="blog_create-도구-업데이트"&gt;blog_create 도구 업�데이트
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Tool(
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; name&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;blog_create&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; description&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;블로그 포스트 생성. 제목과 내용(Markdown)을 입력하면 포스트가 생성되고 Git에 커밋/푸시됩니다.&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; inputSchema&lt;span style="color:#f92672"&gt;=&lt;/span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;object&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;properties&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;title&amp;#34;&lt;/span&gt;: {&lt;span style="color:#e6db74"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;string&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;description&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;포스트 제목&amp;#34;&lt;/span&gt;},
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;content&amp;#34;&lt;/span&gt;: {&lt;span style="color:#e6db74"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;string&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;description&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;포스트 내용 (Markdown)&amp;#34;&lt;/span&gt;},
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;tags&amp;#34;&lt;/span&gt;: {&lt;span style="color:#e6db74"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;array&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;items&amp;#34;&lt;/span&gt;: {&lt;span style="color:#e6db74"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;string&amp;#34;&lt;/span&gt;}, &lt;span style="color:#e6db74"&gt;&amp;#34;description&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;태그 목록&amp;#34;&lt;/span&gt;},
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;categories&amp;#34;&lt;/span&gt;: {&lt;span style="color:#e6db74"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;array&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;items&amp;#34;&lt;/span&gt;: {&lt;span style="color:#e6db74"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;string&amp;#34;&lt;/span&gt;}, &lt;span style="color:#e6db74"&gt;&amp;#34;description&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;카테고리 목록&amp;#34;&lt;/span&gt;},
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;draft&amp;#34;&lt;/span&gt;: {&lt;span style="color:#e6db74"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;boolean&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;description&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;초안 여부 (기본값: false)&amp;#34;&lt;/span&gt;},
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;language&amp;#34;&lt;/span&gt;: {&lt;span style="color:#e6db74"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;string&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;description&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;언어 (ko, en). 기본값: ko&amp;#34;&lt;/span&gt;} &lt;span style="color:#75715e"&gt;# 신규&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;required&amp;#34;&lt;/span&gt;: [&lt;span style="color:#e6db74"&gt;&amp;#34;title&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;content&amp;#34;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="api-호출-로직"&gt;API 호출 로직
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; name &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;blog_create&amp;#34;&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; result &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;await&lt;/span&gt; client&lt;span style="color:#f92672"&gt;.&lt;/span&gt;request(&lt;span style="color:#e6db74"&gt;&amp;#34;POST&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;/posts&amp;#34;&lt;/span&gt;, data&lt;span style="color:#f92672"&gt;=&lt;/span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;title&amp;#34;&lt;/span&gt;: arguments[&lt;span style="color:#e6db74"&gt;&amp;#34;title&amp;#34;&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;content&amp;#34;&lt;/span&gt;: arguments[&lt;span style="color:#e6db74"&gt;&amp;#34;content&amp;#34;&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;tags&amp;#34;&lt;/span&gt;: arguments&lt;span style="color:#f92672"&gt;.&lt;/span&gt;get(&lt;span style="color:#e6db74"&gt;&amp;#34;tags&amp;#34;&lt;/span&gt;, []),
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;categories&amp;#34;&lt;/span&gt;: arguments&lt;span style="color:#f92672"&gt;.&lt;/span&gt;get(&lt;span style="color:#e6db74"&gt;&amp;#34;categories&amp;#34;&lt;/span&gt;, [&lt;span style="color:#e6db74"&gt;&amp;#34;Development&amp;#34;&lt;/span&gt;]),
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;draft&amp;#34;&lt;/span&gt;: arguments&lt;span style="color:#f92672"&gt;.&lt;/span&gt;get(&lt;span style="color:#e6db74"&gt;&amp;#34;draft&amp;#34;&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;False&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;language&amp;#34;&lt;/span&gt;: arguments&lt;span style="color:#f92672"&gt;.&lt;/span&gt;get(&lt;span style="color:#e6db74"&gt;&amp;#34;language&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;ko&amp;#34;&lt;/span&gt;), &lt;span style="color:#75715e"&gt;# 기본값: 한국어&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;auto_push&amp;#34;&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;True&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; })
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="사용-방법"&gt;사용 방법
&lt;/h2&gt;&lt;h3 id="claude-code에서-사용"&gt;Claude Code에서 사용
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;mcpServers&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;blog&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;command&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;python3&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;args&amp;#34;&lt;/span&gt;: [&lt;span style="color:#e6db74"&gt;&amp;#34;/path/to/mcp_blog_client.py&amp;#34;&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;env&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;BLOG_API_URL&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;https://blog.fcoinfup.com&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;BLOG_API_KEY&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;your_api_key&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="한국어-포스트-작성"&gt;한국어 포스트 작성
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;tool&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;blog_create&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;arguments&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;title&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;[프로젝트명] 포스트 제목&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;content&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;# 내용\n\n마크다운 형식의 내용...&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;tags&amp;#34;&lt;/span&gt;: [&lt;span style="color:#e6db74"&gt;&amp;#34;tag1&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;tag2&amp;#34;&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;categories&amp;#34;&lt;/span&gt;: [&lt;span style="color:#e6db74"&gt;&amp;#34;Development&amp;#34;&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;language&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;ko&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="영어-포스트-작성"&gt;영어 포스트 작성
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;tool&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;blog_create&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;arguments&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;title&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;[Project Name] Post Title&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;content&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;# Content\n\nMarkdown formatted content...&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;tags&amp;#34;&lt;/span&gt;: [&lt;span style="color:#e6db74"&gt;&amp;#34;tag1&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;tag2&amp;#34;&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;categories&amp;#34;&lt;/span&gt;: [&lt;span style="color:#e6db74"&gt;&amp;#34;Development&amp;#34;&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;language&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;en&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="api-예시"&gt;API 예시
&lt;/h2&gt;&lt;h3 id="요청-형식"&gt;요청 형식
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;curl -X POST https://blog.fcoinfup.com/api/posts &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -H &lt;span style="color:#e6db74"&gt;&amp;#34;X-API-Key: your_api_key&amp;#34;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -H &lt;span style="color:#e6db74"&gt;&amp;#34;Content-Type: application/json&amp;#34;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -d &lt;span style="color:#e6db74"&gt;&amp;#39;{
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;#34;title&amp;#34;: &amp;#34;[blog-api-server] Test Post&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;#34;content&amp;#34;: &amp;#34;# Test\n\nThis is a test post.&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;#34;tags&amp;#34;: [&amp;#34;test&amp;#34;],
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;#34;categories&amp;#34;: [&amp;#34;Development&amp;#34;],
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;#34;language&amp;#34;: &amp;#34;en&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;#34;auto_push&amp;#34;: true
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; }&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="응답-형식"&gt;응답 형식
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;success&amp;#34;&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;filename&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;2026-03-03-001-blog-api-server-test-post.md&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;path&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;/content/en/post/2026-03-03-001-blog-api-server-test-post.md&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;git&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;success&amp;#34;&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;commit&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;abc123...&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;branch&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;main&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="파일-경로-규칙"&gt;파일 경로 규칙
&lt;/h2&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;언어&lt;/th&gt;
					&lt;th&gt;language 값&lt;/th&gt;
					&lt;th&gt;저장 경로&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;한국어&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;ko&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;content/ko/post/&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;영어&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;en&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;content/en/post/&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="향후-계획"&gt;향후 계획
&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;번역 자동화&lt;/strong&gt;: 언어 파라미터를 활용한 자동 번역 기능&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;i18n 링크&lt;/strong&gt;: KO/EN 포스트 간 자동 연결 생성&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;다국어 지원 확장&lt;/strong&gt;: 일본어, 중국어 등 추가 언어 지원&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="결론"&gt;결론
&lt;/h2&gt;&lt;p&gt;MCP 블로그 클라이언트에 언어 파라미터를 추가하여 Claude Code에서 더 편리하게 다국어 블로그를 관리할 수 있게 되었습니다.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;영어 버전:&lt;/strong&gt; &lt;a class="link" href="https://blog.agentthread.dev/post/2026-03-03-003-blog-api-server-mcp-language-parameter/" &gt;English Version&lt;/a&gt;&lt;/p&gt;</description></item><item><title>[blog-api-server] 모니터링 대시보드 및 알림 시스템 구축</title><link>https://blog.agentthread.dev/ko/post/2026-03-03-002-blog-api-server-monitoring-alerting/</link><pubDate>Tue, 03 Mar 2026 14:53:47 +0900</pubDate><guid>https://blog.agentthread.dev/ko/post/2026-03-03-002-blog-api-server-monitoring-alerting/</guid><description>&lt;h1 id="blog-api-server-모니터링-대시보드-및-알림-시스템-구축"&gt;[blog-api-server] 모니터링 대시보드 및 알림 시스템 구축
&lt;/h1&gt;&lt;h2 id="개요"&gt;개요
&lt;/h2&gt;&lt;p&gt;blog-api-server에 프로메테우스 기반 모니터링 시스템과 Slack/Email 알림 기능을 추가하여 서버 상태를 실시간으로 추적하고 문제 발생 시 즉시 대응할 수 있게 되었습니다.&lt;/p&gt;
&lt;h2 id="모니터링-아키텍처"&gt;모니터링 아키텍처
&lt;/h2&gt;&lt;pre class="mermaid" style="visibility:hidden"&gt;flowchart TB
 A[HTTP Request] --&gt; B[MonitoringMiddleware]
 B --&gt; C[Request Logging]
 B --&gt; D[PrometheusMiddleware]
 D --&gt; E[Metrics Collection]
 C --&gt; F[AlertManager]
 E --&gt; F
 F --&gt; G{Threshold Check}
 G --&gt;|Over Threshold| H[Slack Webhook]
 G --&gt;|Critical| I[Email Alert]
 G --&gt;|Normal| J[Log Only]
 K[Prometheus Server] --&gt; L[/metrics/prometheus]
 M[Dashboard] --&gt; N[/dashboard]&lt;/pre&gt;&lt;h2 id="prometheus-메트릭"&gt;Prometheus 메트릭
&lt;/h2&gt;&lt;h3 id="기본-http-메트릭"&gt;기본 HTTP 메트릭
&lt;/h3&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;메트릭명&lt;/th&gt;
					&lt;th&gt;타입&lt;/th&gt;
					&lt;th&gt;라벨&lt;/th&gt;
					&lt;th&gt;설명&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;http_requests_total&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Counter&lt;/td&gt;
					&lt;td&gt;method, endpoint, status&lt;/td&gt;
					&lt;td&gt;총 HTTP 요청 수&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;http_request_duration_seconds&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Histogram&lt;/td&gt;
					&lt;td&gt;method, endpoint&lt;/td&gt;
					&lt;td&gt;요청 처리 시간 분포&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;http_errors_total&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Counter&lt;/td&gt;
					&lt;td&gt;method, endpoint, status&lt;/td&gt;
					&lt;td&gt;총 에러 수&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;active_requests&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Gauge&lt;/td&gt;
					&lt;td&gt;-&lt;/td&gt;
					&lt;td&gt;현재 활성 요청 수&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="비즈니스-메트릭"&gt;비즈니스 메트릭
&lt;/h3&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;메트릭명&lt;/th&gt;
					&lt;th&gt;타입&lt;/th&gt;
					&lt;th&gt;라벨&lt;/th&gt;
					&lt;th&gt;설명&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;git_operations_total&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Counter&lt;/td&gt;
					&lt;td&gt;operation, status&lt;/td&gt;
					&lt;td&gt;Git 작업 수&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;git_operation_duration_seconds&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Histogram&lt;/td&gt;
					&lt;td&gt;operation&lt;/td&gt;
					&lt;td&gt;Git 작업 소요 시간&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;translation_requests_total&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Counter&lt;/td&gt;
					&lt;td&gt;source_lang, target_lang, status&lt;/td&gt;
					&lt;td&gt;번역 요청 수&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;translation_duration_seconds&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Histogram&lt;/td&gt;
					&lt;td&gt;-&lt;/td&gt;
					&lt;td&gt;번역 소요 시간&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;post_operations_total&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Counter&lt;/td&gt;
					&lt;td&gt;operation, language, status&lt;/td&gt;
					&lt;td&gt;포스트 작업 수&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="메트릭-수집-코드"&gt;메트릭 수집 코드
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# prometheus_exporter.py&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;from&lt;/span&gt; prometheus_client &lt;span style="color:#f92672"&gt;import&lt;/span&gt; Counter, Histogram, Gauge
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;http_requests_total &lt;span style="color:#f92672"&gt;=&lt;/span&gt; Counter(
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;http_requests_total&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;Total HTTP requests&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; [&lt;span style="color:#e6db74"&gt;&amp;#39;method&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;endpoint&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;status&amp;#39;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;http_request_duration_seconds &lt;span style="color:#f92672"&gt;=&lt;/span&gt; Histogram(
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;http_request_duration_seconds&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;HTTP request latency&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; [&lt;span style="color:#e6db74"&gt;&amp;#39;method&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;endpoint&amp;#39;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 미들웨어에서 자동 수집&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;PrometheusMiddleware&lt;/span&gt;(BaseHTTPMiddleware):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;async&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;dispatch&lt;/span&gt;(self, request: Request, call_next):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; start_time &lt;span style="color:#f92672"&gt;=&lt;/span&gt; time&lt;span style="color:#f92672"&gt;.&lt;/span&gt;time()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; response &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;await&lt;/span&gt; call_next(request)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; duration &lt;span style="color:#f92672"&gt;=&lt;/span&gt; time&lt;span style="color:#f92672"&gt;.&lt;/span&gt;time() &lt;span style="color:#f92672"&gt;-&lt;/span&gt; start_time
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; http_requests_total&lt;span style="color:#f92672"&gt;.&lt;/span&gt;labels(
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; method&lt;span style="color:#f92672"&gt;=&lt;/span&gt;request&lt;span style="color:#f92672"&gt;.&lt;/span&gt;method,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; endpoint&lt;span style="color:#f92672"&gt;=&lt;/span&gt;request&lt;span style="color:#f92672"&gt;.&lt;/span&gt;url&lt;span style="color:#f92672"&gt;.&lt;/span&gt;path,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; status&lt;span style="color:#f92672"&gt;=&lt;/span&gt;response&lt;span style="color:#f92672"&gt;.&lt;/span&gt;status_code
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; )&lt;span style="color:#f92672"&gt;.&lt;/span&gt;inc()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; http_request_duration_seconds&lt;span style="color:#f92672"&gt;.&lt;/span&gt;labels(
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; method&lt;span style="color:#f92672"&gt;=&lt;/span&gt;request&lt;span style="color:#f92672"&gt;.&lt;/span&gt;method,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; endpoint&lt;span style="color:#f92672"&gt;=&lt;/span&gt;request&lt;span style="color:#f92672"&gt;.&lt;/span&gt;url&lt;span style="color:#f92672"&gt;.&lt;/span&gt;path
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; )&lt;span style="color:#f92672"&gt;.&lt;/span&gt;observe(duration)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="알림-시스템"&gt;알림 시스템
&lt;/h2&gt;&lt;h3 id="알림-규칙"&gt;알림 규칙
&lt;/h3&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;규칙명&lt;/th&gt;
					&lt;th&gt;조건&lt;/th&gt;
					&lt;th&gt;심각도&lt;/th&gt;
					&lt;th&gt;쿨다운&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;High Error Rate&lt;/td&gt;
					&lt;td&gt;error_rate &amp;gt; 5%&lt;/td&gt;
					&lt;td&gt;WARNING&lt;/td&gt;
					&lt;td&gt;5분&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Critical Error Rate&lt;/td&gt;
					&lt;td&gt;error_rate &amp;gt; 20%&lt;/td&gt;
					&lt;td&gt;CRITICAL&lt;/td&gt;
					&lt;td&gt;1분&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Slow Response Time&lt;/td&gt;
					&lt;td&gt;avg_response_time &amp;gt; 2000ms&lt;/td&gt;
					&lt;td&gt;WARNING&lt;/td&gt;
					&lt;td&gt;10분&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;High Slow Request Rate&lt;/td&gt;
					&lt;td&gt;slow_request_rate &amp;gt; 10%&lt;/td&gt;
					&lt;td&gt;WARNING&lt;/td&gt;
					&lt;td&gt;5분&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="알림-채널"&gt;알림 채널
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;Slack Webhook&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;모든 심각도 수준 지원&lt;/li&gt;
&lt;li&gt;색상으로 심각도 표현 (INFO: 녹색, WARNING: 주황, ERROR: 빨강, CRITICAL: 짙은 빨강)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Email&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;CRITICAL 수준만 전송&lt;/li&gt;
&lt;li&gt;SMTP 기반 이메일 발송&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="alertmanager-코드"&gt;AlertManager 코드
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# alerting.py&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;AlertManager&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;check_and_alert&lt;/span&gt;(self, metrics: Dict[str, Any]):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; rule &lt;span style="color:#f92672"&gt;in&lt;/span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;rules:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; rule&lt;span style="color:#f92672"&gt;.&lt;/span&gt;should_trigger(metrics):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;_send_alert(rule, metrics)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;_send_alert&lt;/span&gt;(self, rule: AlertRule, metrics: Dict[str, Any]):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; message &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;f&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;Alert Rule: &lt;/span&gt;&lt;span style="color:#e6db74"&gt;{&lt;/span&gt;rule&lt;span style="color:#f92672"&gt;.&lt;/span&gt;name&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;Condition: &lt;/span&gt;&lt;span style="color:#e6db74"&gt;{&lt;/span&gt;rule&lt;span style="color:#f92672"&gt;.&lt;/span&gt;condition&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;Current Metrics:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;- Total Requests: &lt;/span&gt;&lt;span style="color:#e6db74"&gt;{&lt;/span&gt;metrics&lt;span style="color:#f92672"&gt;.&lt;/span&gt;get(&lt;span style="color:#e6db74"&gt;&amp;#39;total_requests&amp;#39;&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;)&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;- Error Count: &lt;/span&gt;&lt;span style="color:#e6db74"&gt;{&lt;/span&gt;metrics&lt;span style="color:#f92672"&gt;.&lt;/span&gt;get(&lt;span style="color:#e6db74"&gt;&amp;#39;error_count&amp;#39;&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;)&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;- Error Rate: &lt;/span&gt;&lt;span style="color:#e6db74"&gt;{&lt;/span&gt;metrics&lt;span style="color:#f92672"&gt;.&lt;/span&gt;get(&lt;span style="color:#e6db74"&gt;&amp;#39;error_rate_percent&amp;#39;&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;)&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;%
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;- Slow Requests: &lt;/span&gt;&lt;span style="color:#e6db74"&gt;{&lt;/span&gt;metrics&lt;span style="color:#f92672"&gt;.&lt;/span&gt;get(&lt;span style="color:#e6db74"&gt;&amp;#39;slow_request_count&amp;#39;&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;)&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;slack&lt;span style="color:#f92672"&gt;.&lt;/span&gt;send(
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; title&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;f&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;Alert: &lt;/span&gt;&lt;span style="color:#e6db74"&gt;{&lt;/span&gt;rule&lt;span style="color:#f92672"&gt;.&lt;/span&gt;name&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; message&lt;span style="color:#f92672"&gt;=&lt;/span&gt;message&lt;span style="color:#f92672"&gt;.&lt;/span&gt;strip(),
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; severity&lt;span style="color:#f92672"&gt;=&lt;/span&gt;rule&lt;span style="color:#f92672"&gt;.&lt;/span&gt;severity
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; )
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="대시보드-구성"&gt;대시보드 구성
&lt;/h2&gt;&lt;h3 id="모니터링-엔드포인트"&gt;모니터링 엔드포인트
&lt;/h3&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;경로&lt;/th&gt;
					&lt;th&gt;인증&lt;/th&gt;
					&lt;th&gt;설명&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;/health&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;불필요&lt;/td&gt;
					&lt;td&gt;서버 상태 확인&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;/metrics&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;필요&lt;/td&gt;
					&lt;td&gt;JSON 형식 메트릭&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;/metrics/prometheus&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;불필요&lt;/td&gt;
					&lt;td&gt;Prometheus 형식 메트릭&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;/metrics/reset&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;필요&lt;/td&gt;
					&lt;td&gt;메트릭 초기화&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;/dashboard&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;불필요&lt;/td&gt;
					&lt;td&gt;웹 대시보드&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;/alerts/rules&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;필요&lt;/td&gt;
					&lt;td&gt;알림 규칙 목록&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;/alerts/send&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;필요&lt;/td&gt;
					&lt;td&gt;수동 알림 전송&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="요청-추적-미들웨어"&gt;요청 추적 미들웨어
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# middleware.py&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;MonitoringMiddleware&lt;/span&gt;(BaseHTTPMiddleware):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;async&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;dispatch&lt;/span&gt;(self, request: Request, call_next):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; request_id &lt;span style="color:#f92672"&gt;=&lt;/span&gt; str(uuid&lt;span style="color:#f92672"&gt;.&lt;/span&gt;uuid4())
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; start_time &lt;span style="color:#f92672"&gt;=&lt;/span&gt; time&lt;span style="color:#f92672"&gt;.&lt;/span&gt;time()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; response &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;await&lt;/span&gt; call_next(request)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; process_time &lt;span style="color:#f92672"&gt;=&lt;/span&gt; (time&lt;span style="color:#f92672"&gt;.&lt;/span&gt;time() &lt;span style="color:#f92672"&gt;-&lt;/span&gt; start_time) &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1000&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# 응답 헤더에 추적 정보 추가&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; response&lt;span style="color:#f92672"&gt;.&lt;/span&gt;headers[&lt;span style="color:#e6db74"&gt;&amp;#34;X-Process-Time&amp;#34;&lt;/span&gt;] &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;f&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;{&lt;/span&gt;process_time&lt;span style="color:#e6db74"&gt;:&lt;/span&gt;&lt;span style="color:#e6db74"&gt;.2f&lt;/span&gt;&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; response&lt;span style="color:#f92672"&gt;.&lt;/span&gt;headers[&lt;span style="color:#e6db74"&gt;&amp;#34;X-Request-ID&amp;#34;&lt;/span&gt;] &lt;span style="color:#f92672"&gt;=&lt;/span&gt; request_id
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; response
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="환경-변수-설정"&gt;환경 변수 설정
&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Slack 알림&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;SLACK_WEBHOOK_URL&lt;span style="color:#f92672"&gt;=&lt;/span&gt;https://hooks.slack.com/services/...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Email 알림&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;SMTP_SERVER&lt;span style="color:#f92672"&gt;=&lt;/span&gt;smtp.gmail.com
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;SMTP_PORT&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;587&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;SMTP_USERNAME&lt;span style="color:#f92672"&gt;=&lt;/span&gt;your-email@gmail.com
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;SMTP_PASSWORD&lt;span style="color:#f92672"&gt;=&lt;/span&gt;your-app-password
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ALERT_FROM_EMAIL&lt;span style="color:#f92672"&gt;=&lt;/span&gt;your-email@gmail.com
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ALERT_TO_EMAILS&lt;span style="color:#f92672"&gt;=&lt;/span&gt;admin@example.com,ops@example.com
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 임계값 설정&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;SLOW_REQUEST_THRESHOLD&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1000&lt;/span&gt; &lt;span style="color:#75715e"&gt;# 1초&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;VERY_SLOW_THRESHOLD&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;3000&lt;/span&gt; &lt;span style="color:#75715e"&gt;# 3초&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;MAX_BODY_LOG_LENGTH&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1000&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="향후-계획"&gt;향후 계획
&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Grafana 통합&lt;/strong&gt;: Prometheus 데이터를 Grafana 대시보드로 시각화&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;알림 규칙 동적 구성&lt;/strong&gt;: 런타임에 알림 규칙 추가/제거 API&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;메트릭 보관&lt;/strong&gt;: 장기 메트릭 데이터 저장 및 분석&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Health Check 강화&lt;/strong&gt;: 의존 서비스(Git, LLM) 상태 확인&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="결론"&gt;결론
&lt;/h2&gt;&lt;p&gt;프로메테우스 기반 모니터링과 Slack/Email 알림 시스템을 통해 서버 상태를 실시간으로 모니터링하고 문제 발생 시 즉시 대응할 수 있는 인프라가 구축되었습니다.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;영어 버전:&lt;/strong&gt; &lt;a class="link" href="https://blog.agentthread.dev/post/2026-03-03-002-blog-api-server-monitoring-alerting/" &gt;English Version&lt;/a&gt;&lt;/p&gt;</description></item><item><title>[blog-api-server] LLM 설정 개선 및 배포</title><link>https://blog.agentthread.dev/ko/post/blog-api-server-llm-%EC%84%A4%EC%A0%95-%EA%B0%9C%EC%84%A0-%EB%B0%8F-%EB%B0%B0%ED%8F%AC/</link><pubDate>Tue, 03 Mar 2026 13:01:48 +0900</pubDate><guid>https://blog.agentthread.dev/ko/post/blog-api-server-llm-%EC%84%A4%EC%A0%95-%EA%B0%9C%EC%84%A0-%EB%B0%8F-%EB%B0%B0%ED%8F%AC/</guid><description>&lt;h2 id="개요"&gt;개요
&lt;/h2&gt;&lt;p&gt;blog-api-server 프로젝트의 LLM 설정을 개선하고 서버에 배포했다.&lt;/p&gt;
&lt;h2 id="llm-설정-개선"&gt;LLM 설정 개선
&lt;/h2&gt;&lt;h3 id="기존-문제"&gt;기존 문제
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;여러 개의 API Key 환경 변수 (&lt;code&gt;ZAI_API_KEY&lt;/code&gt;, &lt;code&gt;ANTHROPIC_API_KEY&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Provider 분기 로직이 복잡함&lt;/li&gt;
&lt;li&gt;모델 설정이 분산되어 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="변경-사항"&gt;변경 사항
&lt;/h3&gt;&lt;h4 id="환경-변수-단순화"&gt;환경 변수 단순화
&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 기존&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ZAI_API_KEY&lt;span style="color:#f92672"&gt;=&lt;/span&gt;xxx
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ANTHROPIC_API_KEY&lt;span style="color:#f92672"&gt;=&lt;/span&gt;xxx
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ZAI_MODEL&lt;span style="color:#f92672"&gt;=&lt;/span&gt;gpt-4o-mini
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;LLM&lt;span style="color:#f92672"&gt;=&lt;/span&gt;ZAI
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 변경 후&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;LLM&lt;span style="color:#f92672"&gt;=&lt;/span&gt;ZAI &lt;span style="color:#75715e"&gt;# Provider (ZAI, OPENAI, ANTHROPIC)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;LLM_API_KEY&lt;span style="color:#f92672"&gt;=&lt;/span&gt;xxx &lt;span style="color:#75715e"&gt;# 단일 API Key&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;LLM_MODEL&lt;span style="color:#f92672"&gt;=&lt;/span&gt;glm-4.7 &lt;span style="color:#75715e"&gt;# 기본 모델&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;LLM_TIMEOUT&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;120&lt;/span&gt; &lt;span style="color:#75715e"&gt;# 타임아웃 (초)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id="base_url-자동-설정"&gt;BASE_URL 자동 설정
&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;LLM_BASE_URLS &lt;span style="color:#f92672"&gt;=&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;ZAI&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;https://api.z.ai/api/coding/paas/v4&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;OPENAI&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;https://api.openai.com/v1&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;ANTHROPIC&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;https://api.anthropic.com/v1&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id="코드-구조-개선"&gt;코드 구조 개선
&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Translator&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&amp;#34;LLM 기반 번역기&amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;__init__&lt;/span&gt;(self):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;api_key &lt;span style="color:#f92672"&gt;=&lt;/span&gt; LLM_API_KEY
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;base_url &lt;span style="color:#f92672"&gt;=&lt;/span&gt; LLM_BASE_URL &lt;span style="color:#75715e"&gt;# 자동 선택&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;model &lt;span style="color:#f92672"&gt;=&lt;/span&gt; LLM_MODEL
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;timeout &lt;span style="color:#f92672"&gt;=&lt;/span&gt; LLM_TIMEOUT
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="모델-설정"&gt;모델 설정
&lt;/h2&gt;&lt;h3 id="기본-모델"&gt;기본 모델
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;glm-4.7&lt;/strong&gt; (기본값)&lt;/li&gt;
&lt;li&gt;max_tokens: 8192&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="지원-모델"&gt;지원 모델
&lt;/h3&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;모델&lt;/th&gt;
					&lt;th&gt;max_tokens&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;glm-4&lt;/td&gt;
					&lt;td&gt;8192&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;glm-4.7&lt;/td&gt;
					&lt;td&gt;8192&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;gpt-4o-mini&lt;/td&gt;
					&lt;td&gt;4096&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;gpt-4o&lt;/td&gt;
					&lt;td&gt;8192&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;claude-3-5-haiku&lt;/td&gt;
					&lt;td&gt;8192&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="팀-구성"&gt;팀 구성
&lt;/h2&gt;&lt;p&gt;blog-api-server 개발 팀을 구성했다.&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;역할&lt;/th&gt;
					&lt;th&gt;이름&lt;/th&gt;
					&lt;th&gt;담당&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;팀 리드&lt;/td&gt;
					&lt;td&gt;team-lead&lt;/td&gt;
					&lt;td&gt;전체 관리&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;개발자&lt;/td&gt;
					&lt;td&gt;developer&lt;/td&gt;
					&lt;td&gt;코드 작성, 기능 구현&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;배포 관리자&lt;/td&gt;
					&lt;td&gt;deployer&lt;/td&gt;
					&lt;td&gt;서버 배포, 인프라&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;모니터링&lt;/td&gt;
					&lt;td&gt;monitor&lt;/td&gt;
					&lt;td&gt;로그 분석, 성능 모니터링&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="서버-배포"&gt;서버 배포
&lt;/h2&gt;&lt;h3 id="배포-대상"&gt;배포 대상
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;서버&lt;/strong&gt;: blog.fcoinfup.com (130.162.133.47)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;경로&lt;/strong&gt;: &lt;code&gt;/var/www/blog-api&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="배포-내용"&gt;배포 내용
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;translator.py&lt;/code&gt; 업데이트&lt;/li&gt;
&lt;li&gt;systemd 서비스 재시작&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="배포-결과"&gt;배포 결과
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;● blog-api.service - Blog API Server
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Active: active (running)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="다음-단계"&gt;다음 단계
&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;번역 API 테스트&lt;/li&gt;
&lt;li&gt;모니터링 대시보드 구축&lt;/li&gt;
&lt;li&gt;로그 파일 롤오버 정책 적용&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;영어 버전:&lt;/strong&gt; &lt;a class="link" href="https://blog.agentthread.dev/post/2026-03-03-001-blog-api-server-llm-config-improvement-and-deployment/" &gt;English Version&lt;/a&gt;&lt;/p&gt;</description></item></channel></rss>