<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>pow(zero_car, 2)</title>
        <link>https://velog.io/</link>
        <description>영차영차 열심히 개발 공부를 하고 있습니다.</description>
        <lastBuildDate>Wed, 25 Feb 2026 13:21:49 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>pow(zero_car, 2)</title>
            <url>https://velog.velcdn.com/images/hwang_gim/profile/a7a6d668-8684-431c-9e70-1fe7a804942f/image.jpg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. pow(zero_car, 2). All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/hwang_gim" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[Redis를 꼭 써야 할까요?]]></title>
            <link>https://velog.io/@hwang_gim/Redis%EB%A5%BC-%EA%BC%AD-%EC%8D%A8%EC%95%BC-%ED%95%A0%EA%B9%8C%EC%9A%94</link>
            <guid>https://velog.io/@hwang_gim/Redis%EB%A5%BC-%EA%BC%AD-%EC%8D%A8%EC%95%BC-%ED%95%A0%EA%B9%8C%EC%9A%94</guid>
            <pubDate>Wed, 25 Feb 2026 13:21:49 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/hwang_gim/post/db6614e6-6d35-4334-871d-36f6ba829151/image.png" alt=""></p>
<blockquote>
<p><strong>💡 프로프트(Propt) 프로젝트</strong>
한 번의 프롬프팅으로 여러 개의 답변을 얻을 수 있는 AI Agent용 MCP 도구입니다.
이번 글에서는 Propt 개발 중 고민했던 &#39;레디스 도입 여부&#39;에 대한 내용을 공유합니다.
프로프트가 궁금하다면, <a href="https://github.com/HwangGoeun/propt-backend">레포지토리</a>를 확인해보세요!</p>
</blockquote>
<br>

<p>Redis(레디스)는 참 매력적인 도구입니다.
빠르고, 적용도 간편하고, 무엇보다 인메모리 DB라는 점에서 TTL만 설정하면 불필요한 데이터가 쌓일 걱정이 없습니다.</p>
<p>프로프트의 게스트 로그인 기능을 구현하는 과정에서 자연스럽게 레디스 도입을 생각했습니다만, 고민 끝에 도입하지 않기로 했습니다.</p>
<p>왜 그런 선택을 했는지, 그 이유를 정리해보았습니다.</p>
<br>

<hr>
<br>

<h1 id="1-도입에-들어가는-비용">1. 도입에 들어가는 비용</h1>
<p>이때 말하는 &#39;비용&#39;이란, 단순히 금전적인 서버 비용만을 의미하지 않습니다.</p>
<ol>
<li>새로운 라이브러리를 도입하면서 발생하는 프로젝트 볼륨 증가</li>
<li>라이브러리의 업데이트에 맞추어 유지보수하는 데에 들어가는 비용</li>
<li>새로운 라이브러리를 학습하는 데에 들어가는 비용</li>
<li>Redis 연결 실패, 타임 아웃 등 새로운 에러 케이스 대응에 소요되는 비용</li>
<li>기존 라이브러리와의 호환성을 유지하는 데에 들어가는 비용</li>
</ol>
<p>이처럼 단순히 &#39;좋으니까 쓴다&#39;라고 하기엔, 도입 자체만으로 감수해야 할 잠재적 비용이 적지 않았습니다.</p>
<br>

<h1 id="2-대체-불가능-여부">2. 대체 불가능 여부</h1>
<p>Redis를 통해 구현하고자 했던 핵심 기능은 단순했습니다.</p>
<blockquote>
<p>게스트 로그인 정보를 저장하고, 24시간이 지나면 자동으로 삭제하기</p>
</blockquote>
<p>위 기능은 정말 Redis를 사용하는 것 말고는 구현할 수 있는 방법이 없는걸까요?
기존에 사용 중이던 RDBMS로는 불가능할까요?</p>
<p>결론부터 말하면, 가능했습니다!</p>
<p>현재 프로프트에서는 게스트 로그인 정보를 메인 DB에 저장하고, 생성 시간을 함께 기록하고 있습니다.
그리고 Cron 작업을 통해 새벽 3시마다 생성된 지 24시간이 지난 게스트 로그인 계정을 삭제하는 과정을 수행하고 있습니다.</p>
<p>Redis 없이도 충분히, RDBMS만으로 게스트 계정을 삭제할 수 있었습니다.</p>
<br>

<h1 id="3-정말-필요할까">3. 정말 필요할까?</h1>
<p>솔직히 말해서, 아직 프로프트가 Redis가 필수적일 만큼의 트래픽이 발생하지 않습니다. 🤣</p>
<p>동시 접속자 수가 수천 명 단위도 아니고,
1ms 이내에 빠른 응답을 기대해야 하는 실시간성이 중요한 서비스도 아닙니다.</p>
<p>오히려 당장 중요하게 생각해야 할 부분은,</p>
<ul>
<li>프로프트의 사용법을 사용자로부터 빠르게 익히게 하는 방법</li>
<li>조금 더 적은 토큰을 사용해서 병렬 처리를 하도록 하는 방법</li>
<li>&#39;프롬프트&#39;와 &#39;프로프트&#39; 사이에서 LLM이 헷갈리지 않고 MCP를 수행하도록 하는 방법</li>
</ul>
<p>처럼 &#39;어떻게 사용자가 더 프로프트를 편하게 사용할 수 있을까?&#39;에 대해 더 고민해야 한다고 생각했어요.</p>
<p>지금 &#39;꼭!&#39; 필요하지 않은데,
성능을 위해, 개발 편의성을 위해 레디스를 도입한다는 생각이, 오버 엔지니어링이라고 느껴졌습니다.</p>
<hr>
<br>

<p>Redis는 정말 훌륭한 도구입니다.
언젠가 프로프트의 사용자가 급증한다면, 그때는 기쁜 마음으로 Redis를 도입하겠지요. 😁</p>
<p>하지만 &#39;지금&#39;의 저에게는 아직 필요하지 않다고 생각합니다.</p>
<p>좋은 도구를 통해 훌륭한 성능을 만들어내는 것도 개발자로서 정말 멋지지만,
한정된 자원 안에서 근거있는 선택을 통해 효율적인 결과를 내는 것도 개발자의 역할이 아닐까요?
&#39;아~ 개발했다~&#39; 하는 뿌듯함이 들었던 경험입니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[프롬프팅만으로 컨텍스트 분리가 가능할까? (feat. Claude Code)]]></title>
            <link>https://velog.io/@hwang_gim/%ED%94%84%EB%A1%AC%ED%94%84%ED%8A%B8%EB%A7%8C%EC%9C%BC%EB%A1%9C-%EC%BB%A8%ED%85%8D%EC%8A%A4%ED%8A%B8-%EB%B6%84%EB%A6%AC%EA%B0%80-%EA%B0%80%EB%8A%A5%ED%95%A0%EA%B9%8C-feat.-Claude-Code</link>
            <guid>https://velog.io/@hwang_gim/%ED%94%84%EB%A1%AC%ED%94%84%ED%8A%B8%EB%A7%8C%EC%9C%BC%EB%A1%9C-%EC%BB%A8%ED%85%8D%EC%8A%A4%ED%8A%B8-%EB%B6%84%EB%A6%AC%EA%B0%80-%EA%B0%80%EB%8A%A5%ED%95%A0%EA%B9%8C-feat.-Claude-Code</guid>
            <pubDate>Sun, 08 Feb 2026 13:00:17 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p><strong>💡 Propt 프로젝트</strong>
한 번의 프롬프팅으로 여러 개의 답변을 얻을 수 있는 <strong>AI Agent용 MCP 도구</strong>입니다.
이번 글에서는 Propt 개발 중 가장 깊게 고민했던 <strong>&#39;배치 실행 시 컨텍스트 분리&#39;</strong> 경험을 공유합니다.
Propt가 궁금하다면, <a href="https://github.com/HwangGoeun/propt-backend">레포지토리</a>를 확인해보세요!</p>
</blockquote>
<br />

<h2 id="1-문제의-시작-이전-답변에-영향을-받지-마세요">1. 문제의 시작: &quot;이전 답변에 영향을 받지 마세요&quot;</h2>
<p>Propt의 핵심 기능 중 하나는 <strong>배치 실행</strong>입니다. 예를 들어 선생님이 학생 A, B, C의 생활기록부를 작성한다고 가정해 봅시다.</p>
<p>우리는 보통 이렇게 기대합니다.</p>
<ul>
<li><strong>A 학생:</strong> &quot;A는 성실하고...&quot;</li>
<li><strong>B 학생:</strong> &quot;B는 창의적이고...&quot; (A의 내용과 무관하게 B만 평가)</li>
</ul>
<p>하지만 LLM에게 한 번의 대화로 여러 명의 평가를 요청하면 문제가 발생합니다.
LLM이 답변을 생성할 때 앞서 생성한 A 학생의 평가 내용이 B 학생 평가에 영향을 미치는 컨텍스트 오염이 발생하기 때문입니다.</p>
<blockquote>
<p>&quot;A 학생의 보고서와 달리, B 학생은...&quot;</p>
</blockquote>
<p>이런 식의 비교 표현이 나오거나, 앞선 답변의 톤앤매너를 억지로 따라가는 문제가 발생했습니다.</p>
<hr>
<br />

<h2 id="2-프롬프트로-컨텍스트-분리해보기">2. 프롬프트로 컨텍스트 분리해보기</h2>
<h3 id="첫-번째-시도-독립적으로-처리해주세요">첫 번째 시도: &quot;독립적으로 처리해주세요&quot;</h3>
<p>가장 먼저 시도한 방법은 강력한 <strong>System Instruction</strong>이었습니다.
&quot;앞의 내용을 보지 말고 독립적으로 처리해!&quot;라고 지시하면 될 것이라 생각했습니다.</p>
<pre><code class="language-markdown">## 처리 방식
각 항목을 **독립적으로** 처리해주세요.

**핵심 원칙:**
- 각 항목은 별개의 요청으로 취급
- 항목 간 참조나 비교 없이 개별 처리
- &quot;다른 항목과 달리&quot; 등의 비교 표현 사용 금지</code></pre>
<p>결과는 어땠을까요?
얼핏 보면 성공한 것처럼 보였습니다. 학생 평가 예시에서는 비교 문구가 사라졌거든요.</p>
<p>하지만 <strong>&#39;점심 메뉴 추천&#39;</strong> 같은 창의성이 필요한 프롬프트에서 문제가 드러났습니다.
배치 실행을 돌렸더니 <strong>&quot;상황별로 다양하게 추천해 드립니다&quot;</strong>라며 메뉴가 겹치지 않게 일부러 다른 메뉴를 내놓는 현상이 발생했습니다.</p>
<p>즉, <strong>&#39;다양하게&#39;</strong> 주려고 노력한다는 것 자체가 이미 <strong>앞의 답변을 참조(Context Pollution)</strong> 하고 있다는 뜻이었습니다.</p>
<h3 id="두-번째-시도-구체적-금지-조건-명시">두 번째 시도: 구체적 금지 조건 명시</h3>
<p>추상적인 지시가 문제라면, <strong>구체적으로 금지</strong>하면 어떨까? 실행 가이드 상단에 금지 조건을 명시하는 방식으로 개선했습니다.</p>
<pre><code class="language-markdown">**주의사항:**
- 다른 항목의 내용을 언급하지 않음
- &quot;다른 항목과 달리&quot;, &quot;앞선 내용처럼&quot; 등의 표현 사용 금지
- 각 응답은 해당 항목만 보고 작성한 것처럼 구성</code></pre>
<p>&quot;독립적으로 처리해주세요&quot;는 모델이 해석하기 나름이지만, <strong>&quot;&#39;앞선 내용처럼&#39;이라는 표현을 쓰지 마세요&quot;</strong>는 탈출구가 없습니다. 이 방식으로 비교 표현은 확실히 사라졌고, 대부분의 경우 독립적인 결과를 얻을 수 있었습니다.</p>
<p>하지만 <strong>완벽하지는 않았습니다.</strong> 점심 메뉴 추천처럼 단순한 태스크에서는 여전히 앞선 응답을 의식한 흔적이 남아 있었습니다. 프롬프트 수준의 개선으로는 근본적인 한계가 있었던 겁니다.</p>
<hr>
<br />

<h2 id="3-왜-프롬프트로-분리가-안-될까-🤔">3. 왜 프롬프트로 분리가 안 될까? 🤔</h2>
<p>이 현상을 이해하기 위해 LLM의 작동 원리를 다시 파고들었고, <strong>LLM은 태생적으로 컨텍스트 분리가 불가능하다</strong>는 결론에 도달했습니다.</p>
<h3 id="🧠-llm은-자기회귀적autoregressive-모델이다">🧠 LLM은 자기회귀적(Autoregressive) 모델이다</h3>
<p>LLM은 다음 단어를 예측할 때 <strong>&#39;이전의 모든 텍스트&#39;</strong>를 근거로 삼습니다.
단일 채팅창에서 <code>[답변 A]</code>가 생성되는 순간, 이것은 즉시 <code>[답변 B]</code>를 생성하기 위한 <strong>과거의 문맥(Context)</strong>이 되어버립니다.</p>
<h3 id="🦜-디코딩-전략의-한계">🦜 디코딩 전략의 한계</h3>
<p>논문 *<a href="https://proceedings.iclr.cc/paper_files/paper/2024/file/34899013589ef41aea4d7b2f0ef310c1-Paper-Conference.pdf">Closing the Curious Case of Neural Text Degeneration</a><em>에서는, 확률이 높은 단어를 순서대로 선택하는 탐욕적 디코딩(Greedy Decoding)이 텍스트의 반복과 퇴행을 유발한다는 점을 지적합니다. 이 문제를 완화하기 위해 샘플링 기반 디코딩을 사용하더라도, 모델이 참조하는 컨텍스트 자체는 변하지 않습니다. 즉, *</em>디코딩 전략을 바꿔도 이전 답변이 컨텍스트에 남아있는 한 영향은 피할 수 없습니다.**</p>
<p>결국 프롬프트로 &quot;참조하지 마&quot;라고 하는 것은, <strong>&quot;코끼리는 생각하지 마&quot;</strong>라고 말하는 것과 똑같았습니다.</p>
<hr>
<br />

<h2 id="4-해결책-물리적-컨텍스트-분리-🔑">4. 해결책: 물리적 컨텍스트 분리 🔑</h2>
<p>완벽하게 컨텍스트를 분리하기 위해서는 같은 세션을 사용하는 것이 아닌, 서로 다른 세션을 사용하면서 물리적으로 컨텍스트를 분리해야만 했습니다.</p>
<h3 id="첫-번째-발견-claude-code의-task-subagent">첫 번째 발견: Claude Code의 Task (Subagent)</h3>
<p>처음 발견한 것이 <strong>Claude Code의 Task 도구(Subagent)</strong>였습니다.</p>
<p>Claude Code 환경에서 새로운 하위 에이전트(Subagent)를 생성해 작업을 위임하는 기능으로, <strong>각 Subagent가 독립된 컨텍스트를 가집니다.</strong></p>
<p><img src="https://github.com/HwangGoeun/propt-backend/raw/main/images/subagent.png" alt="Subagent 구조"></p>
<p>테스트 결과, 각 실행이 서로에게 전혀 영향을 주지 않는 완벽한 격리가 확인됐습니다.</p>
<p><strong>하지만 문제가 있었습니다.</strong></p>
<p>Subagent는 <strong>Claude Code에서만 지원되는 기능</strong>입니다. Propt는 Claude Desktop을 포함한 다양한 AI 에이전트에서 동작해야 하는 MCP 도구이므로, Claude Code 전용 기능에 의존할 수 없었습니다.</p>
<h3 id="최종-선택-headless-mode-claude--p">최종 선택: Headless Mode (<code>claude -p</code>)</h3>
<p>그래서 선택한 것이 <strong>Claude의 Headless Mode</strong>입니다.</p>
<pre><code class="language-bash">claude -p &#39;사과의 건강 효과에 대해 분석해주세요&#39; &gt; &quot;batch_result_A.md&quot;
claude -p &#39;사과의 요리 활용법에 대해 분석해주세요&#39; &gt; &quot;batch_result_B.md&quot;
claude -p &#39;사과의 보관 방법에 대해 분석해주세요&#39; &gt; &quot;batch_result_C.md&quot;</code></pre>
<p>각 <code>claude -p</code> 호출은 <strong>완전히 독립된 프로세스</strong>로 실행됩니다. Subagent와 동일한 수준의 컨텍스트 분리를 보장하면서도, <strong>터미널이 있는 어디서든 실행할 수 있습니다.</strong></p>
<p>비용 측면에서는 API를 N번 호출하는 것과 동일하지만, 별도의 백엔드 인프라 없이 CLI만으로 실행할 수 있다는 점이 장점입니다.</p>
<p>Propt의 <code>propt_prepare_batch</code> 도구는 템플릿과 변수 세트를 받아 이 명령어들을 자동으로 생성합니다.</p>
<pre><code class="language-typescript">const commands = items.map((item) =&gt; {
  const escapedPrompt = escapeForShell(promptWithInstruction);
  const toolsOption = needsTools ? &quot; --allowedTools &#39;Bash,Write,Read,Edit&#39;&quot; : &#39;&#39;;
  return `claude -p &#39;${escapedPrompt}&#39;${toolsOption} &gt; &quot;batch_result_${item.id}.md&quot;`;
});</code></pre>
<p>사용자는 MCP를 통해 자연어로 요청하기만 하면, Propt가 명령어를 생성하고 실행합니다. 단, <code>claude -p</code>는 Claude Code CLI이므로 실행 환경에 Claude Code가 설치되어 있어야 합니다.</p>
<table>
<thead>
<tr>
<th align="center"></th>
<th align="center">Subagent (Task)</th>
<th align="center">Headless Mode (<code>claude -p</code>)</th>
</tr>
</thead>
<tbody><tr>
<td align="center">컨텍스트 분리</td>
<td align="center">완벽</td>
<td align="center">완벽</td>
</tr>
<tr>
<td align="center">Claude Desktop 지원</td>
<td align="center">❌</td>
<td align="center">✅</td>
</tr>
<tr>
<td align="center">Claude Code 지원</td>
<td align="center">✅</td>
<td align="center">✅</td>
</tr>
<tr>
<td align="center">결과 수집</td>
<td align="center">부모가 자동 수집</td>
<td align="center">파일로 저장</td>
</tr>
</tbody></table>
<p>Subagent가 더 깔끔한 방식이었지만, <strong>MCP 도구로서의 범용성</strong>을 위해 Headless Mode를 선택했습니다.</p>
<hr>
<br />

<h2 id="5-그럼-propt의-가치는-무엇인가">5. 그럼 Propt의 가치는 무엇인가?</h2>
<p>&quot;그냥 Claude에서 직접 <code>claude -p</code> (Headless 모드) 쓰면 되는 거 아니야?&quot;라는 의문이 들 수 있습니다.
하지만 개발자가 아닌 일반 사용자가 터미널에서 JSON 파일을 만들고 명령어를 치는 것은 쉽지 않습니다.</p>
<p>Propt는 이 기술적 기능을 <strong>사용자 친화적인 경험(UX)</strong>으로 포장했습니다.</p>
<table>
<thead>
<tr>
<th align="center">기능</th>
<th align="center">Claude Headless 모드</th>
<th align="center"><strong>Propt</strong></th>
</tr>
</thead>
<tbody><tr>
<td align="center"><strong>사용 대상</strong></td>
<td align="center">개발자/파워유저</td>
<td align="center"><strong>일반 사용자</strong></td>
</tr>
<tr>
<td align="center"><strong>실행 방법</strong></td>
<td align="center">터미널 명령어 직접 입력</td>
<td align="center"><strong>MCP 도구로 자연어 대화</strong></td>
</tr>
<tr>
<td align="center"><strong>템플릿 관리</strong></td>
<td align="center">❌ (파일로 직접 관리)</td>
<td align="center"><strong>✅ 웹 UI에서 저장/관리</strong></td>
</tr>
<tr>
<td align="center"><strong>변수 치환</strong></td>
<td align="center">❌ (수동 수정)</td>
<td align="center"><strong>✅ <code>{변수}</code> 자동 치환</strong></td>
</tr>
</tbody></table>
<p>기술적으로는 Claude의 기능을 활용하지만, <strong>템플릿 관리 + 변수 자동화 + 웹 UI</strong>를 결합하여 누구나 쉽게 LLM 배치 작업을 할 수 있도록 가치를 더했습니다.</p>
<hr>
<br />

<h2 id="6-마치며">6. 마치며</h2>
<p>이번 프로젝트를 통해 &quot;안 되면 되게 하라&quot;는 식의 코딩보다는, &quot;AI 모델의 특성을 이해하고 그에 맞춰 설계하는 것&quot;이 얼마나 중요한지 깨달았습니다.</p>
<p>프롬프트 엔지니어링으로 해결하려던 문제를 모델의 아키텍처적 한계로 인식하고, 적절한 도구를 찾아 해결하는 과정 자체가 큰 배움이었습니다.</p>
<p>혹시 LLM으로 배치 작업을 구현하면서 비슷한 고민을 하고 계신 분들께 이 글이 도움이 되길 바랍니다!</p>
<hr>
<br />

<h3 id="reference">Reference</h3>
<ul>
<li><a href="https://github.com/HwangGoeun/propt-backend">GitHub - Propt Backend</a></li>
<li><a href="https://proceedings.iclr.cc/paper_files/paper/2024/file/34899013589ef41aea4d7b2f0ef310c1-Paper-Conference.pdf">Closing the Curious Case of Neural Text Degeneration</a></li>
</ul>
]]></description>
        </item>
    </channel>
</rss>