<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>devopslog</title>
    <link>https://devopslog.tistory.com/</link>
    <description>✔ Write down what comes to mind</description>
    <language>ko</language>
    <pubDate>Sun, 5 Apr 2026 06:41:07 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>디클냥</managingEditor>
    <image>
      <title>devopslog</title>
      <url>https://tistory1.daumcdn.net/tistory/7445477/attach/203de98a968643d5be4d4f31c261bc78</url>
      <link>https://devopslog.tistory.com</link>
    </image>
    <item>
      <title>agent-browser: AI 에이전트를 위한 브라우저 자동화 CLI</title>
      <link>https://devopslog.tistory.com/228</link>
      <description>&lt;p&gt;&lt;code&gt;agent-browser&lt;/code&gt;는 AI 에이전트가 웹 브라우저를 직접 다루도록 만든 CLI 도구입니다. 단순히 클릭과 입력만 하는 자동화 스크립트가 아니라, 페이지 구조를 스냅샷으로 읽고, ref 기반으로 요소를 조작하고, 세션과 상태를 유지하고, 네트워크와 디버그 정보까지 함께 다룰 수 있도록 설계되어 있습니다.&lt;/p&gt;
&lt;p&gt;DevOps 관점에서 보면 이 도구의 매력은 분명합니다. 사람이 브라우저에서 하던 반복 작업을 쉘 명령으로 옮길 수 있고, AI 에이전트가 사용할 수 있는 안정적인 웹 조작 인터페이스를 제공합니다. 특히 Playwright를 직접 코드로 짜는 방식보다, 탐색과 검증을 훨씬 빠르게 시도해볼 수 있습니다.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;1. agent-browser란 무엇인가?&lt;/h2&gt;
&lt;p&gt;agent-browser는 Vercel Labs가 공개한 브라우저 자동화 CLI입니다. README 기준으로는 &lt;strong&gt;빠른 Rust CLI&lt;/strong&gt;와 &lt;strong&gt;Node.js 데몬&lt;/strong&gt;이 함께 동작하는 구조이며, 내부적으로 Playwright 기반 브라우저를 관리합니다. 네이티브 바이너리를 사용할 수 없을 때는 Node.js 경로로 동작하는 fallback도 제공합니다.&lt;/p&gt;
&lt;p&gt;핵심은 AI 친화적인 조작 방식입니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;snapshot&lt;/code&gt;으로 현재 페이지의 접근성 트리를 읽습니다.&lt;/li&gt;
&lt;li&gt;각 요소는 &lt;code&gt;@e1&lt;/code&gt;, &lt;code&gt;@e2&lt;/code&gt; 같은 ref로 식별됩니다.&lt;/li&gt;
&lt;li&gt;이후 &lt;code&gt;click @e2&lt;/code&gt;, &lt;code&gt;fill @e3 &amp;quot;text&amp;quot;&lt;/code&gt;처럼 deterministic하게 조작합니다.&lt;/li&gt;
&lt;li&gt;필요하면 CSS selector, text selector, role 기반 locator도 함께 사용할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;즉, 사람처럼 브라우저를 “보면서” 다루는 도구이면서도, 에이전트가 읽고 실행하기 쉬운 형태로 정보가 정리됩니다.&lt;/p&gt;
&lt;h3&gt;동작 원리&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;사용자가 &lt;code&gt;open&lt;/code&gt;, &lt;code&gt;click&lt;/code&gt;, &lt;code&gt;fill&lt;/code&gt; 같은 명령을 입력합니다.&lt;/li&gt;
&lt;li&gt;Rust CLI가 명령을 빠르게 해석합니다.&lt;/li&gt;
&lt;li&gt;Node.js 데몬이 실제 브라우저 인스턴스를 제어합니다.&lt;/li&gt;
&lt;li&gt;브라우저 상태, 세션, 쿠키, 네비게이션 히스토리가 유지됩니다.&lt;/li&gt;
&lt;li&gt;필요하면 &lt;code&gt;snapshot&lt;/code&gt;, &lt;code&gt;get text&lt;/code&gt;, &lt;code&gt;network requests&lt;/code&gt;, &lt;code&gt;trace&lt;/code&gt; 같은 명령으로 현재 상태를 다시 관찰합니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;이 구조 덕분에 단발성 조작뿐 아니라, 여러 단계로 이어지는 웹 작업을 운영 도구처럼 다룰 수 있습니다.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;2. 주요 CLI 명령어&lt;/h2&gt;
&lt;p&gt;README를 기준으로 실무에서 자주 쓰는 명령을 묶으면 아래처럼 볼 수 있습니다.&lt;/p&gt;
&lt;h3&gt;이동과 기본 조작&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;agent-browser open &amp;lt;url&amp;gt;&lt;/code&gt;: URL로 이동합니다. &lt;code&gt;goto&lt;/code&gt;, &lt;code&gt;navigate&lt;/code&gt; 별칭도 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;agent-browser click &amp;lt;sel&amp;gt;&lt;/code&gt;: 요소를 클릭합니다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;agent-browser dblclick &amp;lt;sel&amp;gt;&lt;/code&gt;: 더블클릭합니다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;agent-browser focus &amp;lt;sel&amp;gt;&lt;/code&gt;: 요소에 포커스를 줍니다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;agent-browser type &amp;lt;sel&amp;gt; &amp;lt;text&amp;gt;&lt;/code&gt;: 입력합니다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;agent-browser fill &amp;lt;sel&amp;gt; &amp;lt;text&amp;gt;&lt;/code&gt;: 기존 값을 지우고 새로 채웁니다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;agent-browser press &amp;lt;key&amp;gt;&lt;/code&gt;: 키를 누릅니다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;agent-browser hover &amp;lt;sel&amp;gt;&lt;/code&gt;: 마우스를 올립니다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;agent-browser select &amp;lt;sel&amp;gt; &amp;lt;val&amp;gt;&lt;/code&gt;: 셀렉트 박스를 선택합니다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;agent-browser check &amp;lt;sel&amp;gt;&lt;/code&gt;, &lt;code&gt;uncheck &amp;lt;sel&amp;gt;&lt;/code&gt;: 체크박스를 조작합니다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;agent-browser scroll &amp;lt;dir&amp;gt; [px]&lt;/code&gt;: 스크롤합니다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;agent-browser scrollintoview &amp;lt;sel&amp;gt;&lt;/code&gt;: 요소를 화면으로 가져옵니다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;agent-browser drag &amp;lt;src&amp;gt; &amp;lt;tgt&amp;gt;&lt;/code&gt;: 드래그 앤 드롭을 수행합니다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;agent-browser upload &amp;lt;sel&amp;gt; &amp;lt;files&amp;gt;&lt;/code&gt;: 파일 업로드를 처리합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;예제:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;agent-browser open https://github.com
agent-browser click &amp;quot;#sign-in-button&amp;quot;
agent-browser fill &amp;quot;#email&amp;quot; &amp;quot;test@example.com&amp;quot;
agent-browser press Enter&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;정보 조회&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;agent-browser get text &amp;lt;sel&amp;gt;&lt;/code&gt;: 텍스트를 가져옵니다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;agent-browser get html &amp;lt;sel&amp;gt;&lt;/code&gt;: innerHTML을 가져옵니다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;agent-browser get value &amp;lt;sel&amp;gt;&lt;/code&gt;: input value를 가져옵니다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;agent-browser get attr &amp;lt;sel&amp;gt; &amp;lt;attr&amp;gt;&lt;/code&gt;: attribute 값을 읽습니다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;agent-browser get title&lt;/code&gt;: 페이지 제목을 가져옵니다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;agent-browser get url&lt;/code&gt;: 현재 URL을 확인합니다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;agent-browser get count &amp;lt;sel&amp;gt;&lt;/code&gt;: 일치하는 요소 개수를 셉니다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;agent-browser get box &amp;lt;sel&amp;gt;&lt;/code&gt;: bounding box를 가져옵니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;예제:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;agent-browser get title
agent-browser get url
agent-browser get text &amp;quot;h1&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;탐색과 대기&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;agent-browser snapshot&lt;/code&gt;: 접근성 트리를 출력합니다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;agent-browser find role &amp;lt;role&amp;gt; &amp;lt;action&amp;gt;&lt;/code&gt;: ARIA role 기반으로 찾습니다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;agent-browser find text &amp;lt;text&amp;gt; &amp;lt;action&amp;gt;&lt;/code&gt;: 텍스트 기반으로 찾습니다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;agent-browser find label &amp;lt;label&amp;gt; &amp;lt;action&amp;gt;&lt;/code&gt;: label 기반으로 찾습니다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;agent-browser find placeholder &amp;lt;ph&amp;gt; &amp;lt;action&amp;gt;&lt;/code&gt;: placeholder 기반으로 찾습니다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;agent-browser find testid &amp;lt;id&amp;gt; &amp;lt;action&amp;gt;&lt;/code&gt;: &lt;code&gt;data-testid&lt;/code&gt; 기반으로 찾습니다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;agent-browser wait &amp;lt;selector&amp;gt;&lt;/code&gt;: 요소가 보일 때까지 기다립니다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;agent-browser wait --text &amp;quot;Welcome&amp;quot;&lt;/code&gt;: 텍스트가 나타날 때까지 기다립니다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;agent-browser wait --url &amp;quot;**/dash&amp;quot;&lt;/code&gt;: URL 패턴을 기다립니다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;agent-browser wait --load networkidle&lt;/code&gt;: 로드 상태를 기다립니다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;agent-browser wait --fn &amp;quot;window.ready === true&amp;quot;&lt;/code&gt;: JS 조건을 기다립니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;예제:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;agent-browser snapshot -i
agent-browser find role button click --name &amp;quot;Submit&amp;quot;
agent-browser wait --load networkidle&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;세션, 상태, 디버그&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;agent-browser session&lt;/code&gt;: 현재 세션을 확인합니다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;agent-browser session list&lt;/code&gt;: 활성 세션 목록을 봅니다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;agent-browser cookies&lt;/code&gt;: 쿠키를 읽습니다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;agent-browser storage local&lt;/code&gt;: localStorage를 읽습니다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;agent-browser state save &amp;lt;path&amp;gt;&lt;/code&gt;: 상태를 저장합니다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;agent-browser state load &amp;lt;path&amp;gt;&lt;/code&gt;: 상태를 불러옵니다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;agent-browser trace start&lt;/code&gt;, &lt;code&gt;trace stop&lt;/code&gt;: Playwright trace처럼 기록합니다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;agent-browser console&lt;/code&gt;: 콘솔 메시지를 봅니다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;agent-browser errors&lt;/code&gt;: 페이지 에러를 확인합니다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;agent-browser inspect&lt;/code&gt;: DevTools를 엽니다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;agent-browser screenshot [path]&lt;/code&gt;: 스크린샷을 저장합니다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;agent-browser pdf &amp;lt;path&amp;gt;&lt;/code&gt;: PDF로 저장합니다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;agent-browser close&lt;/code&gt;: 브라우저를 닫습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;예제:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;agent-browser session list
agent-browser trace start
agent-browser screenshot result.png&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;운영에 유용한 옵션&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;--session &amp;lt;name&amp;gt;&lt;/code&gt;: 세션을 분리합니다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--profile &amp;lt;path&amp;gt;&lt;/code&gt;: 브라우저 프로필을 영속화합니다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--headers &amp;lt;json&amp;gt;&lt;/code&gt;: 특정 origin에 헤더를 주입합니다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--json&lt;/code&gt;: 머신이 읽기 쉬운 JSON 출력입니다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--headed&lt;/code&gt;: 브라우저 창을 실제로 띄웁니다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--cdp &amp;lt;port&amp;gt;&lt;/code&gt;: 기존 Chrome에 CDP로 연결합니다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--allowed-domains&lt;/code&gt;: 허용 도메인을 제한합니다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--confirm-actions&lt;/code&gt;: 위험한 액션에 승인을 요구합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;예제:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;agent-browser --session dev open https://example.com
agent-browser --headed snapshot -i
agent-browser --allowed-domains &amp;quot;example.com,*.example.com&amp;quot; open https://example.com&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h2&gt;3. 간단한 사이트 네비게이션과 데이터 가져오기&lt;/h2&gt;
&lt;p&gt;가장 기본적인 흐름은 다음과 같습니다.&lt;/p&gt;
&lt;h3&gt;1) 사이트 열기&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;agent-browser open https://example.com&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;2) 현재 페이지 구조 확인&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;agent-browser snapshot -i&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;-i&lt;/code&gt;는 interactive 요소만 보여주기 때문에 버튼, 링크, 입력칸을 빠르게 찾을 수 있습니다.&lt;/p&gt;
&lt;h3&gt;3) ref 기반으로 조작&lt;/h3&gt;
&lt;p&gt;스냅샷에서 &lt;code&gt;@e1&lt;/code&gt;, &lt;code&gt;@e2&lt;/code&gt; 같은 ref를 확인한 뒤 바로 씁니다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;agent-browser click @e2
agent-browser fill @e3 &amp;quot;test@example.com&amp;quot;
agent-browser press Enter&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;4) 데이터 추출&lt;/h3&gt;
&lt;p&gt;화면이 바뀌면 다시 읽습니다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;agent-browser get text @e1
agent-browser get html @e4
agent-browser get url&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;5) 필요하면 스크린샷과 종료&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;agent-browser screenshot result.png
agent-browser close&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;실제 운영에서는 이 패턴이 가장 자주 쓰입니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;페이지를 연다&lt;/li&gt;
&lt;li&gt;구조를 읽는다&lt;/li&gt;
&lt;li&gt;ref로 클릭한다&lt;/li&gt;
&lt;li&gt;텍스트를 가져온다&lt;/li&gt;
&lt;li&gt;필요하면 스냅샷을 다시 찍는다&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;검색 결과 확인, 관리자 화면 검증, 로그인 플로우 점검 같은 작업에 잘 맞습니다.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;4. Playwright 함수와 비교&lt;/h2&gt;
&lt;p&gt;agent-browser는 내부적으로 Playwright 계열의 브라우저 자동화를 활용하지만, 사용자는 CLI로 접근합니다. 그래서 같은 동작도 체감은 꽤 다릅니다.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;agent-browser&lt;/th&gt;
&lt;th&gt;Playwright&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;open https://site.com&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;page.goto(&amp;#39;https://site.com&amp;#39;)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;페이지 이동&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;click &amp;quot;#submit&amp;quot;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;page.locator(&amp;#39;#submit&amp;#39;).click()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;CSS selector 클릭&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;fill &amp;quot;#email&amp;quot; &amp;quot;a@b.com&amp;quot;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;page.locator(&amp;#39;#email&amp;#39;).fill(&amp;#39;a@b.com&amp;#39;)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;입력 값 채우기&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;find role button click --name &amp;quot;Submit&amp;quot;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;page.getByRole(&amp;#39;button&amp;#39;, { name: &amp;#39;Submit&amp;#39; }).click()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;접근성 기반 탐색&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;find text &amp;quot;Sign In&amp;quot; click&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;page.getByText(&amp;#39;Sign In&amp;#39;).click()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;텍스트 기반 탐색&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;wait --load networkidle&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;page.waitForLoadState(&amp;#39;networkidle&amp;#39;)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;로드 상태 대기&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;get text @e1&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;locator.textContent()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;텍스트 조회&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;snapshot&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;page.accessibility.snapshot()&lt;/code&gt;에 가까운 개념&lt;/td&gt;
&lt;td&gt;페이지 구조 확인&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;screenshot page.png&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;page.screenshot({ path: &amp;#39;page.png&amp;#39; })&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;스크린샷 저장&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h3&gt;차이점 정리&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Playwright&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;코드로 정밀하게 제어하기 좋습니다.&lt;/li&gt;
&lt;li&gt;테스트 코드와 CI에 붙이기 좋습니다.&lt;/li&gt;
&lt;li&gt;반복문, 분기, 예외 처리 같은 복잡한 로직을 자유롭게 넣을 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;agent-browser&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;CLI 중심이라 빠르게 시도하기 좋습니다.&lt;/li&gt;
&lt;li&gt;AI 에이전트가 바로 읽고 실행하기 쉽습니다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;snapshot&lt;/code&gt;과 &lt;code&gt;@e1&lt;/code&gt; ref 흐름이 안정적입니다.&lt;/li&gt;
&lt;li&gt;세션, 네트워크, 디버깅, 보안 옵션이 함께 들어 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;어떤 상황에 더 적합한가&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Playwright&lt;/strong&gt;: 제품 테스트 코드, CI 자동화, 세밀한 회귀 테스트&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;agent-browser&lt;/strong&gt;: 운영 점검, 에이전트 기반 웹 탐색, 빠른 수동 검증, 쉘에서의 즉석 자동화&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;실무적으로는 둘 중 하나만 고르기보다, 테스트는 Playwright로 두고 사람과 AI가 빠르게 다루는 운영 자동화는 agent-browser로 분리하는 식이 잘 맞습니다.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;5. tip&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;시작은 &lt;code&gt;snapshot -i&lt;/code&gt;가 가장 편합니다. 상호작용 요소만 먼저 보면 판단이 빨라집니다.&lt;/li&gt;
&lt;li&gt;가능하면 &lt;code&gt;@e1&lt;/code&gt; 같은 ref를 우선 쓰세요. selector보다 안정적인 경우가 많습니다.&lt;/li&gt;
&lt;li&gt;데이터는 &lt;code&gt;get text&lt;/code&gt;, &lt;code&gt;get html&lt;/code&gt;, &lt;code&gt;get url&lt;/code&gt;처럼 목적별로 분리해서 가져오는 편이 좋습니다.&lt;/li&gt;
&lt;li&gt;로그인 반복이 많다면 &lt;code&gt;--session-name&lt;/code&gt; 또는 &lt;code&gt;--profile&lt;/code&gt;을 써서 상태를 유지하세요.&lt;/li&gt;
&lt;li&gt;디버깅은 &lt;code&gt;--headed&lt;/code&gt;, &lt;code&gt;inspect&lt;/code&gt;, &lt;code&gt;trace&lt;/code&gt;를 같이 쓰면 훨씬 수월합니다.&lt;/li&gt;
&lt;li&gt;외부 사이트를 다룰 때는 &lt;code&gt;--allowed-domains&lt;/code&gt;와 &lt;code&gt;--confirm-actions&lt;/code&gt; 같은 보안 옵션을 함께 고려하는 편이 안전합니다.&lt;/li&gt;
&lt;li&gt;여러 단계를 한 번에 실행해야 하면 &lt;code&gt;batch&lt;/code&gt;를 검토해 보세요. 프로세스 시작 비용을 줄일 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;6. 맺음말&lt;/h2&gt;
&lt;p&gt;agent-browser는 단순한 브라우저 자동화 도구가 아니라, AI 에이전트와 운영자가 함께 쓸 수 있는 웹 조작 인터페이스에 가깝습니다.&lt;br&gt;Playwright처럼 정밀한 코딩 자동화와는 결이 다르지만, CLI 기반의 빠른 실험, 세션 유지, ref 기반 상호작용, 디버깅 기능까지 갖춰서 실무 친화성이 높습니다.&lt;/p&gt;
&lt;p&gt;특히 DevOps 관점에서는 “반복적인 웹 운영 작업을 얼마나 안전하고 빠르게 자동화할 수 있느냐”가 중요한데, agent-browser는 그 지점을 꽤 잘 공략하고 있습니다.&lt;/p&gt;
&lt;h2&gt;참고 자료&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/vercel-labs/agent-browser&quot;&gt;vercel-labs/agent-browser GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://playwright.dev/docs/locators&quot;&gt;Playwright Locators 문서&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://playwright.dev/docs/api/class-locator&quot;&gt;Playwright Locator API&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>devops</category>
      <category>AI</category>
      <category>browser-automation</category>
      <category>devops</category>
      <category>playwright</category>
      <category>Rust</category>
      <author>디클냥</author>
      <guid isPermaLink="true">https://devopslog.tistory.com/228</guid>
      <comments>https://devopslog.tistory.com/228#entry228comment</comments>
      <pubDate>Fri, 3 Apr 2026 22:25:52 +0900</pubDate>
    </item>
    <item>
      <title>프롬프트, 컨텍스트, 하네스 엔지니어링: AI 제어 기술의 진화</title>
      <link>https://devopslog.tistory.com/227</link>
      <description>&lt;p&gt;생성형 AI 모델(LLM)이 발전함에 따라, 단순히 모델에 질문을 던지는 것을 넘어 AI의 성능을 끌어올리고 원하는 결과를 안전하게 얻어내기 위한 방법론도 빠르게 진화해 왔습니다. 처음에는 AI와 &amp;#39;대화하는 법&amp;#39;을 조율했다면, 이제는 AI에게 &amp;#39;지식을 주입&amp;#39;하고, 나아가 능동적인 AI 에이전트가 활동할 수 있는 &amp;#39;안전하고 자동화된 운영 환경&amp;#39;을 구축하는 단계에 이르렀습니다.&lt;/p&gt;
&lt;p&gt;이 글에서는 인공지능 제어의 핵심 발전 흐름인 &lt;strong&gt;프롬프트 엔지니어링(Prompt Engineering)&lt;/strong&gt;, &lt;strong&gt;컨텍스트 엔지니어링(Context Engineering)&lt;/strong&gt;, 그리고 자율 에이전트의 부상과 함께 각광받는 &lt;strong&gt;하네스 엔지니어링(Harness Engineering)&lt;/strong&gt;의 정의와 특징, 발전 과정, 그리고 핵심 요소를 정리해 보겠습니다. 또한 각 개념을 직관적으로 이해할 수 있도록 대상 프로젝트 예시를 함께 소개합니다.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;1. 프롬프트 엔지니어링 (Prompt Engineering)&lt;/h2&gt;
&lt;h3&gt;정의 및 특징&lt;/h3&gt;
&lt;p&gt;프롬프트 엔지니어링은 AI 모델이 사용자가 의도한 최적의 결과물을 생성하도록 입력값(명령어, 프롬프트)의 구조와 질의 방식을 설계하고 최적화하는 기술입니다. 모델 자체를 재학습시키거나 가중치를 변경하는 과정 없이, Zero-shot, Few-shot, Chain-of-Thought 등 프롬프트의 정교한 튜닝만으로 일관되고 높은 품질의 텍스트 답변을 통제하는 것이 가장 큰 특징입니다.&lt;/p&gt;
&lt;h3&gt;발전 과정 및 이유&lt;/h3&gt;
&lt;p&gt;초기 LLM이 대중에게 공개되고 활용되던 시기, 사용자가 &amp;#39;어떤 단어와 논리 구조&amp;#39;로 질문하느냐에 따라 답변의 퀄리티가 하늘과 땅 차이로 벌어진다는 점이 확인되었습니다. 이 때문에 AI가 가진 잠재력을 최대로 끌어내고, 답변이 너무 장황해지거나 엉뚱한 포맷으로 출력되는 현상(형식 이탈)을 막으려면 시스템 프롬프트 레벨에서의 체계적인 가이드와 제약 부여 기술이 필수적으로 요구되면서 발전했습니다.&lt;/p&gt;
&lt;h3&gt;핵심 요소&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;지시어(Instruction)&lt;/strong&gt;: 수행할 작업에 대한 명료하고 구체적인 명령&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;배경 및 페르소나(Context/Persona)&lt;/strong&gt;: 모델에게 특정 역할 부여 (예: &amp;quot;당신은 10년 차 IT 리뷰어입니다&amp;quot;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;예시(Examples)&lt;/strong&gt;: 원하는 출력 형태(포맷, 어조 등)를 보여주는 샘플 데이터&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;제약 조건(Constraints)&lt;/strong&gt;: 금지어, 특정 포맷(JSON, Markdown 등) 강제, 글자 수 및 분량 제한&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;  예시 프로젝트: &amp;#39;이메일 요약 단축 봇 (Email Summarizer)&amp;#39;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;목표&lt;/strong&gt;: 길고 중언부언하는 난해한 이메일 내용을 3줄 요약으로 정제.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;설명&lt;/strong&gt;: 별도의 외부 데이터베이스나 추가 도구 연결은 하지 않습니다. 오로지 시스템 프롬프트 쪽에 &lt;code&gt;[지시: 입력된 이메일을 분석하여 핵심 내용만 3개의 불릿 포인트로 요약하고, 비즈니스 톤 앤 매너를 유지하시오]&lt;/code&gt;라는 단호하고 정교한 지침 문장을 설계하여 LLM에 전달하도록 파이프라인을 구성합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;2. 컨텍스트 엔지니어링 (Context Engineering)&lt;/h2&gt;
&lt;h3&gt;정의 및 특징&lt;/h3&gt;
&lt;p&gt;컨텍스트 엔지니어링은 사용자의 프롬프트 내용에만 전적으로 의존하지 않고, LLM이 답변할 때 필요한 &amp;#39;관련성 높은 외부 지식이나 맥락(Context)&amp;#39;을 시스템이 동적으로 검색하여 프롬프트 윈도우(컨텍스트 윈도우)에 주입해주는 기술입니다. 산업계에서 널리 쓰이는 &lt;strong&gt;RAG(Retrieval-Augmented Generation, 검색 증강 생성)&lt;/strong&gt;가 이 분야를 대표하는 아키텍처입니다.&lt;/p&gt;
&lt;h3&gt;발전 과정 및 이유&lt;/h3&gt;
&lt;p&gt;프롬프트 설계만으로는 모델이 한 번도 학습하지 않은 &amp;#39;최신 정보&amp;#39;나 외부에 공개되지 않은 &amp;#39;사내 기밀 데이터&amp;#39;에 관해 올바르게 답변하도록 만들 수 없습니다. 이것이 이른바 지식의 한계(Knowledge Cutoff)입니다. 모르는 내용을 그럴싸하게 꾸며내는 &lt;strong&gt;환각(Hallucination)&lt;/strong&gt; 현상을 극복하기 위해, 매번 비싼 비용을 들여 파인튜닝(Fine-Tuning)을 진행하는 대신 데이터베이스에서 직접 &amp;#39;참고 자료&amp;#39;를 꺼내어 모델에게 건네주는 형태의 엔지니어링이 주류로 자리 잡게 되었습니다.&lt;/p&gt;
&lt;h3&gt;핵심 요소&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;데이터 파싱 및 청킹(Chunking)&lt;/strong&gt;: 방대한 문서(PDF, Word)를 의미 있는 작은 단락 묶음으로 쪼개고 정제&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;임베딩(Embedding) 및 벡터 DB&lt;/strong&gt;: 텍스트를 고차원 숫자 벡터로 변환한 뒤, 기계적인 유사도 검색이 가능하도록 적재&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;검색 알고리즘(Retriever)&lt;/strong&gt;: 사용자의 실제 질문과 가장 유사(관련도 높음)한 문맥 단락을 민첩하게 색인&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;프롬프트 주입(Injection)&lt;/strong&gt;: 찾은 문서를 긁어와 &lt;code&gt;[참고자료]&lt;/code&gt; 블록으로 프롬프트에 동적 결합&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;  예시 프로젝트: &amp;#39;사내 보안 규정 Q&amp;amp;A 봇 (Sec-Policy Chatbot)&amp;#39;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;목표&lt;/strong&gt;: 신규 입사자가 사내 보안 지침에 대해 질문하면 최신 사내 문서를 바탕으로 근거 있는 답변 제공.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;설명&lt;/strong&gt;: 임직원이 &amp;quot;외부 USB 사용하려면 어떤 결재가 필요해?&amp;quot;라고 질문하면, 에이전트가 기업 내부망 벡터 DB를 검색해 며칠 전 개정된 &amp;quot;보안 지침 제12조 조항&amp;quot; 전문을 가져옵니다. 최종 프롬프트는 &lt;code&gt;[참고 문서: &amp;lt;가져온 규정&amp;gt;] 이 참고 문서를 바탕으로만 USB 사용 규정 질문에 답하시오.&lt;/code&gt; 형태로 합성되어 모델에 전달됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;3. 하네스 엔지니어링 (Harness Engineering)&lt;/h2&gt;
&lt;h3&gt;정의 및 특징&lt;/h3&gt;
&lt;p&gt;하네스 엔지니어링(Harness Engineering)은 스크립트 도구를 다루거나 스스로 코드를 작성하고 실행하는 자율성 높은 &lt;strong&gt;AI 에이전트(Agentic AI)가 통제 가능하고 안전한 물리적·논리적 환경(Harness, 구속구/안전벨트) 속에서 지속가능하게 목표를 완수할 수 있도록 샌드박스와 피드백 구조, 제어 런타임을 설계하는 시스템 공학&lt;/strong&gt;입니다.&lt;/p&gt;
&lt;h3&gt;발전 과정 및 이유&lt;/h3&gt;
&lt;p&gt;LLM이 단순한 텍스트 챗봇을 넘어서, 파일 시스템을 제어하고, CLI 터미널을 열어 명령어를 치거나, 외부 API 도구(MCP 등)를 실행하는 등 &lt;strong&gt;직접 행동(Action)&lt;/strong&gt;하기 시작했습니다. 도구를 쥐어준 덕택에 높은 성과를 얻을 수 있게 되었지만, 동시에 자율성이 높은 AI가 의도와 다르게 무한 루프로 돈다거나 시스템 핵심 데이터를 파괴하는 명령을 내릴 위험성도 급증했습니다. 이에 따라 모델 자체가 아니라 &amp;quot;모델 밖의 활동 무대이자 런타임 제어기&amp;quot;를 구축하여 에이전트의 행동 반경을 가두고 실행 후의 상태(결과 및 에러)를 관측하여 다시 AI에게 전달해주는 견고한 루프 환경이 필요해졌습니다.&lt;/p&gt;
&lt;h3&gt;핵심 요소&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;샌드박스 런타임 (Sandbox/Isolation)&lt;/strong&gt;: Docker 컨테이너, 임시 가상머신 등 에이전트가 마음껏 코드를 실행해보아도 호스트 시스템을 훼손하지 않는 격리 환경&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;권한 및 도구 제어 (Tool Action Boundary)&lt;/strong&gt;: 에이전트가 가용할 수 있는 도구(파일 읽기, 웹 검색 등)의 목록과 권한(파일 쓰기는 허용하지만 삭제는 금지 등)을 관리&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;가드레일과 승인 개입 (Guardrails &amp;amp; Human-in-the-loop)&lt;/strong&gt;: 위험한 행동(예: git push, DB drop)을 포착하면 자동 실행을 막고 사용자(인간)의 컨펌을 유도&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;자동화된 지속 평가 루프 (Eval &amp;amp; Feedback Loop)&lt;/strong&gt;: 에이전트가 어떤 파일을 수정했을 때 자동으로 테스트 코드를 구동하여, 실패할 경우 그 에러 로그를 캡처하여 다시 에이전트의 컨텍스트로 반환하여 스스로 고칠 수 있게 설계&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;  예시 프로젝트: &amp;#39;오토 코드 리팩토링 및 테스트 에이전트 (Autonomous Refactoring Agent)&amp;#39;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;목표&lt;/strong&gt;: 주어진 소스 코드의 성능을 개선하고 리팩토링하되, 모든 유닛 테스트가 100% 통과하도록 보장.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;설명&lt;/strong&gt;: AI 에이전트는 프로덕션 서버가 아닌 무균실 같은 &lt;strong&gt;격리된 도커(Docker) 샌드박스 하네스&lt;/strong&gt; 내부에 투입됩니다. 에이전트가 소스 코드를 자율적으로 수정하면, 하네스 시스템이 이를 감지해 즉시 &lt;code&gt;pytest&lt;/code&gt;나 &lt;code&gt;npm run test&lt;/code&gt;를 수행합니다. 테스트가 깨지면, 하네스가 에러 트레이스백 로그를 긁어다가 &amp;quot;테스트에 2개 실패했으니 이 로그를 보고 코드를 다시 수정해&amp;quot; 라며 에이전트에게 자동 피드백을 던져줍니다. 에이전트는 이 환경의 벽을 넘어갈 수 없으며 모든 하네스의 제어 규칙을 만족(테스트 통과)할 때만이 비로소 결과물을 메인 브랜치로 커밋할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;맺음말 요약&lt;/h2&gt;
&lt;p&gt;이 세 가지 엔지니어링 분야는 각기 따로 노는 것이 아니라, 생성형 AI의 한계를 극복하기 위해 단계별로 레이어를 쌓아올리며 진화해 온 결과물입니다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;프롬프트 엔지니어링&lt;/strong&gt;: AI에게 상황을 설명하고 &lt;strong&gt;&amp;quot;똑똑하게 말하는 법(형식과 지시)&amp;quot;&lt;/strong&gt;을 가르친 통제 기술&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;컨텍스트 엔지니어링&lt;/strong&gt;: AI의 뇌에 없는 외부 지식(문서 검색)을 가져와 &lt;strong&gt;&amp;quot;읽을 거리(진실된 맥락)&amp;quot;&lt;/strong&gt;를 더해주는 정교한 검색 파이프라인 기술&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;하네스 엔지니어링&lt;/strong&gt;: 도구를 쥐고 직접 행동하는 AI에게 &lt;strong&gt;&amp;quot;안전벨트와 울타리가 쳐진 작업장&amp;quot;&lt;/strong&gt;을 만들어 주어, 문제를 치지 않고 지속적인 피드백 속에 임무를 달성하도록 이끄는 환경 제어 기술&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;앞으로 &amp;#39;Agentic AI&amp;#39; 시대가 고도화될수록, 모델의 파라미터나 구조 그 자체만큼이나 &lt;strong&gt;해당 AI를 얼마나 넓고 안전한 하네스 환경에서 운영할 수 있는가&lt;/strong&gt;가 서비스 성패의 핵심적인 잣대가 될 것입니다.&lt;/p&gt;</description>
      <category>devops</category>
      <category>AI</category>
      <category>context-engineering</category>
      <category>devops</category>
      <category>harness-engineering</category>
      <category>llm</category>
      <category>prompt-engineering</category>
      <author>디클냥</author>
      <guid isPermaLink="true">https://devopslog.tistory.com/227</guid>
      <comments>https://devopslog.tistory.com/227#entry227comment</comments>
      <pubDate>Thu, 2 Apr 2026 12:55:42 +0900</pubDate>
    </item>
    <item>
      <title>macOS에서 MLX 환경 설치 및 운영 (Ollama와 비교)</title>
      <link>https://devopslog.tistory.com/226</link>
      <description>&lt;p&gt;최근 로컬 환경에서 대규모 언어 모델(LLM)을 구동하기 위한 도구들이 눈부시게 발전하고 있습니다. 특히 Apple Silicon(M칩 시리즈)을 탑재한 macOS에서는 디바이스의 하드웨어 리소스를 얼마나 잘 활용하는지에 따라 추론 속도와 메모리 효율이 크게 달라집니다.&lt;/p&gt;
&lt;p&gt;오늘은 Apple에서 직접 개발한 머신러닝 프레임워크인 &lt;strong&gt;MLX&lt;/strong&gt;에 대해 알아보고, 가장 대중적인 도구인 &lt;strong&gt;Ollama&lt;/strong&gt;와의 비교, 그리고 강력한 성능을 자랑하는 &lt;strong&gt;Qwen3.5 9B&lt;/strong&gt; 모델을 기준으로 로컬 환경을 구성하는 방법을 정리해 보겠습니다.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;1. MLX란 무엇인가?&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;MLX&lt;/strong&gt;는 Apple의 머신러닝 연구 팀(Apple Machine Learning Research)에서 Apple Silicon을 위해 특별히 설계한 배열(Array) 및 머신러닝 프레임워크입니다.&lt;br&gt;PyTorch나 JAX와 매우 유사한 Python API를 제공하면서도, Apple의 &lt;strong&gt;통합 메모리(Unified Memory)&lt;/strong&gt; 아키텍처를 가장 깊은 수준에서 최적화하여 사용할 수 있도록 만들어졌습니다.&lt;/p&gt;
&lt;p&gt;Ollama와의 근본적인 방향성 차이는 다음과 같습니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Ollama&lt;/strong&gt;: C++ 기반의 &lt;code&gt;llama.cpp&lt;/code&gt; 엔진을 래핑한 &lt;strong&gt;완성형 애플리케이션 및 플랫폼&lt;/strong&gt;입니다. 사용자가 복잡한 설정 없이도 모델을 쉽게 내려받고 즉시 API 서버 형태로 실행하는 데 초점이 맞춰져 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;MLX&lt;/strong&gt;: Apple 생태계를 위한 &lt;strong&gt;Python 라이브러리 및 프레임워크&lt;/strong&gt;입니다. 모델 아키텍처를 직접 제어하거나, 파인튜닝(Fine-Tuning), 새로운 구조 실험 등 개발자 및 연구자가 하드웨어 성능을 극대화해서 끌어쓰기 적합합니다. &lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;2. MLX vs Ollama: 성능 및 편의성 비교&lt;/h2&gt;
&lt;h3&gt;편의성과 사용자 경험 (UX)&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Ollama (승)&lt;/strong&gt;: 초기 구동과 편의성 면에서는 단연 Ollama가 압도적입니다. 터미널에서 &lt;code&gt;ollama run qwen2.5&lt;/code&gt; 명령어 한 줄이면 이미지 다운로드부터 실행까지 알아서 완료됩니다. Docker를 다루듯 직관적인 CLI를 제공합니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;MLX&lt;/strong&gt;: 기본적으로 Python 개발 환경(가상 환경 설정, pip 라이브러리 설치 등)을 다룰 줄 알아야 합니다. 일반 사용자에게는 진입장벽이 있을 수 있으나, Python 스크립트 기반 생태계에 모델을 직접 통합하려는 개발자에게는 오히려 친숙하고 유연합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;성능 (추론 속도 및 메모리 효율)&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;MLX (승)&lt;/strong&gt;: 순수 Apple Silicon 환경에서 극한의 성능과 최적화를 이끌어내는 데는 MLX가 더 우수합니다. 통합 메모리 대역폭을 네이티브 수준으로 활용하며, 새로운 모델 최적화나 양자화(Quantization), LoRA 어댑터 적용 등에 있어 오버헤드가 적어 처리 속도가 매우 빠릅니다. &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Ollama&lt;/strong&gt;: &lt;code&gt;llama.cpp&lt;/code&gt; 엔진도 Metal API를 딥하게 지원하여 매우 훌륭한 속도를 보여줍니다. 그러나 Apple이 직접 튜닝하는 MLX에 비해서 구조적 한계로 리소스 점유나 토큰 생성 속도에서 근소하게 밀리는 경우가 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;p&gt;&lt;strong&gt;결론&lt;/strong&gt;: 가장 쉽고 빠르게 LLM을 띄우고 싶다면 &lt;strong&gt;Ollama&lt;/strong&gt;를, Apple Silicon의 퍼포먼스를 끝까지 쥐어짜거나 직접 개발/튜닝을 병행하려면 &lt;strong&gt;MLX&lt;/strong&gt;를 추천합니다.&lt;/p&gt;
&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;hr&gt;
&lt;h2&gt;3. macOS에서 MLX 설치 및 환경 구성&lt;/h2&gt;
&lt;p&gt;MLX 환경 구성은 Python 기반의 독립된 영역(가상환경)을 만들어 진행하는 것이 가장 안전합니다.&lt;/p&gt;
&lt;h3&gt;1) Python 가상환경 구성 (uv 활용)&lt;/h3&gt;
&lt;p&gt;가장 빠르고 간편한 파이썬 패키지 매니저인 &lt;code&gt;uv&lt;/code&gt;를 사용해 환경을 구성하는 것을 권장합니다.&lt;br&gt;&lt;code&gt;uv&lt;/code&gt;를 사용하면 가상 환경 생성 및 패키지 설치 속도가 대폭 향상됩니다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# 폴더 생성 및 이동
mkdir mlx_env
cd mlx_env

# uv 설치 (macOS 기본 설치 방법)
curl -LsSf https://astral.sh/uv/install.sh | sh

# 파이썬 가상환경 생성 및 활성화
uv venv
source .venv/bin/activate&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;2) MLX 라이브러리 설치 (&lt;code&gt;mlx-lm&lt;/code&gt; vs &lt;code&gt;mlx-vlm&lt;/code&gt;)&lt;/h3&gt;
&lt;p&gt;MLX 생태계에는 모델 목적에 따라 크게 두 가지 패키지가 제공됩니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;mlx-lm&lt;/code&gt;&lt;/strong&gt;: 텍스트 생성을 위한 대규모 언어 모델(LLM)을 다룰 때 사용합니다. (예: Qwen, Llama, Mistral 등)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;mlx-vlm&lt;/code&gt;&lt;/strong&gt;: 텍스트와 이미지를 함께 처리하는 시각-언어 모델(VLM)을 다룰 때 사용합니다. (예: LLaVA, Qwen-VL, Pixtral 등)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;오늘은 텍스트 기반 LLM인 Qwen3.5를 다루므로 &lt;code&gt;mlx-lm&lt;/code&gt;을 설치하겠습니다. 빠른 설치를 위해 앞서 구성한 &lt;code&gt;uv&lt;/code&gt;를 활용합니다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# MLX 언어모델 전용 패키지 설치
uv pip install mlx-lm&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h2&gt;4. Qwen3.5 9B 모델 기준 로컬 환경 구성 및 Chat 활용&lt;/h2&gt;
&lt;p&gt;Qwen3.5 9B 모델은 뛰어난 한국어 이해력과 가벼운 사이즈 대비 높은 벤치마크 점수로 로컬 추론에 매우 적합합니다. Hugging Face에 업로드된 MLX용 양자화(Quantized) 모델을 다운받아 실행하는 방식을 사용합니다.&lt;/p&gt;
&lt;h3&gt;1) 터미널 기반 로컬 Chat 환경 구동&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;mlx-lm&lt;/code&gt;에는 터미널에서 바로 모델과 대화할 수 있는 챗봇 스크립트가 내장되어 있습니다. &lt;code&gt;Qwen3.5-9B-Instruct&lt;/code&gt;의 MLX 4-bit 양자화 모델을 실행해 보겠습니다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# 첫 실행 시 Hugging Face 모델(약 5~6GB)을 자동으로 다운로드합니다.
python -m mlx_lm.chat --model mlx-community/Qwen3.5-9B-Instruct-4bit&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;실행이 완료되면 아래와 같이 &lt;code&gt;Prompt:&lt;/code&gt; 입력창이 뜨며 즉시 대화를 시작할 수 있습니다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;Prompt: 안녕하세요! 당신은 누구인가요?
Qwen: 안녕하세요! 저는 Qwen입니다. 무엇을 도와드릴까요?&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;2) API 서버 모드로 실행하기 (OpenAI API 호환)&lt;/h3&gt;
&lt;p&gt;Python 애플리케이션이나 다른 프론트엔드 UI(Chatbox, LibreChat 등)와 연동하고 싶다면, 모델을 백그라운드 서버로 띄울 수 있습니다. &lt;code&gt;mlx-lm&lt;/code&gt;은 OpenAI 호환 API 서버 기능을 기본 지원합니다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# 서버 구동 (기본 포트 8080)
python -m mlx_lm.server --model mlx-community/Qwen3.5-9B-Instruct-4bit&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;--model&lt;/code&gt; 옵션이 필수인 이유&lt;/strong&gt;&lt;br&gt;&lt;code&gt;mlx_lm.server&lt;/code&gt;는 데몬 형태로 여러 모델을 관리하는 Ollama와 달리, &lt;strong&gt;서버를 띄울 때 단 하나의 특정 모델을 메모리에 올려 서빙하는 구조&lt;/strong&gt;입니다. 따라서 &lt;code&gt;--model&lt;/code&gt; 옵션을 통해 대상 모델(Hugging Face 레포지토리 주소 또는 로컬 경로)을 명시하지 않으면 구동 시 오류가 발생합니다.&lt;/p&gt;
&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;위 명령어 입력 시 로컬 웹서버가 구동되며, OpenAI API 형식과 호환되므로 &lt;code&gt;curl&lt;/code&gt; 명령어나 Python 코드에서 손쉽게 호출할 수 있습니다.&lt;/p&gt;
&lt;h4&gt;터미널에서 curl로 접속하기&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;curl http://localhost:8080/v1/chat/completions \
  -H &amp;quot;Content-Type: application/json&amp;quot; \
  -d &amp;#39;{
     &amp;quot;messages&amp;quot;: [{&amp;quot;role&amp;quot;: &amp;quot;user&amp;quot;, &amp;quot;content&amp;quot;: &amp;quot;MLX 환경의 장점을 세 줄로 요약해줘.&amp;quot;}],
     &amp;quot;temperature&amp;quot;: 0.7
   }&amp;#39;&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Python 코드로 접속하기 (&lt;code&gt;openai&lt;/code&gt; 라이브러리 활용)&lt;/h4&gt;
&lt;p&gt;서버가 OpenAI API 스펙을 따르기 때문에, 파이썬 스크립트에서도 기존 &lt;code&gt;openai&lt;/code&gt; 라이브러리를 그대로 사용해 접속할 수 있습니다.&lt;br&gt;먼저 &lt;code&gt;uv&lt;/code&gt;를 이용해 패키지를 설치합니다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;uv pip install openai&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;그리고 아래와 같은 파이썬 스크립트(&lt;code&gt;client.py&lt;/code&gt;)를 작성하여 실행합니다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;from openai import OpenAI

# 클라이언트 생성. base_url을 로컬 mlx 서버 주소로 변경하고 api_key는 임의의 문자열을 넣습니다.
client = OpenAI(
    base_url=&amp;quot;http://localhost:8080/v1/&amp;quot;,
    api_key=&amp;quot;not-needed&amp;quot; 
)

response = client.chat.completions.create(
    model=&amp;quot;mlx-community/Qwen3.5-9B-Instruct-4bit&amp;quot;, # 서버가 구동 중인 모델명
    messages=[
        {&amp;quot;role&amp;quot;: &amp;quot;user&amp;quot;, &amp;quot;content&amp;quot;: &amp;quot;MLX 환경의 장점을 세 줄로 요약해줘.&amp;quot;}
    ],
    temperature=0.7,
)

print(response.choices[0].message.content)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;이와 같이 구성하면 Ollama 못지않은 API 서빙 환경을, &lt;strong&gt;Apple Silicon에 최적화된 극한의 퍼포먼스&lt;/strong&gt;로 운영할 수 있습니다.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;마무리&lt;/h2&gt;
&lt;p&gt;지금까지 macOS 환경에서 MLX가 갖는 강점을 Ollama와 비교해 보고, Qwen3.5 9B 모델을 활용하여 나만의 고성능 로컬 AI 환경을 구축하는 방법을 확인했습니다. Python 환경과 명령어에 조금만 익숙해진다면, MLX를 통해 M칩이 가진 잠재력을 100% 활용할 수 있을 것입니다.&lt;/p&gt;</description>
      <category>devops</category>
      <category>devops</category>
      <category>llm</category>
      <category>macos</category>
      <category>MLX</category>
      <category>Ollama</category>
      <category>qwen</category>
      <author>디클냥</author>
      <guid isPermaLink="true">https://devopslog.tistory.com/226</guid>
      <comments>https://devopslog.tistory.com/226#entry226comment</comments>
      <pubDate>Thu, 2 Apr 2026 12:54:55 +0900</pubDate>
    </item>
    <item>
      <title>AI 에이전트를 길들이는 기술: 하네스 엔지니어링(Harness Engineering)의 모든 것</title>
      <link>https://devopslog.tistory.com/225</link>
      <description>&lt;h1&gt;하네스 엔지니어링(Harness Engineering)이란?&lt;/h1&gt;
&lt;p&gt;최근 AI 에이전트(AI Agent)의 발전과 함께 소프트웨어 개발 생태계에서 새롭게 대두되고 있는 개념이 바로 &lt;strong&gt;하네스 엔지니어링(Harness Engineering)&lt;/strong&gt;입니다. &lt;/p&gt;
&lt;p&gt;말과 마차를 연결하는 장비인 &amp;#39;하네스(마구)&amp;#39;에서 유래한 이 용어는, &lt;strong&gt;강력하지만 예측이 어려운 AI 에이전트가 안전하고 신뢰할 수 있는 방식으로 목표를 수행하도록 환경을 조성하고 관리하는 기술&lt;/strong&gt;을 의미합니다. 통제되지 않은 야생마 같은 AI 모델에 안장을 얹어 목적지까지 안전하게 이끄는 일련의 과정이라 할 수 있습니다.&lt;/p&gt;
&lt;h3&gt;궁극적인 목표&lt;/h3&gt;
&lt;p&gt;하네스 엔지니어링의 궁극적인 목표는 &lt;strong&gt;&amp;quot;AI를 단순한 조수(Copilot) 수준을 넘어, 신뢰할 수 있고 자율적인 동료(Agent)로 운영하는 시스템을 구축하는 것&amp;quot;&lt;/strong&gt;입니다. 이를 통해 개발자는 코드 작성 자체에 매달리기보다 AI가 잘 일할 수 있는 환경(도구, 권한, 컨텍스트)을 설계하고, 결과물의 품질과 안정성을 보장하는 아키텍트의 역할을 수행하게 됩니다.&lt;/p&gt;
&lt;hr&gt;
&lt;h1&gt;하네스 엔지니어링 이전의 AI 개발 방법론 비교&lt;/h1&gt;
&lt;p&gt;AI 개발 방법론은 시간이 지나며 점차 진화해 왔습니다. 하네스 엔지니어링이 등장하기 전의 방법론들과 어떠한 차별점이 있는지 살펴보겠습니다.&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;th&gt;한계 및 특징&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;프롬프트 엔지니어링&lt;br&gt;(Prompt Engineering)&lt;/strong&gt;&lt;/td&gt;
&lt;td&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;strong&gt;코파일럿 시대&lt;br&gt;(AI-Assisted Coding)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;AI가 제공하는 코드 조각(Snippet) 등의 결과물을 어떻게 활용할 것인가&lt;/td&gt;
&lt;td&gt;코드 리뷰, 통합 및 검증&lt;/td&gt;
&lt;td&gt;개발자가 전체 맥락을 쥐고 있고 AI는 보조 도구로만 쓰이며, AI 단독으로 문제를 끝까지 해결하지 못함.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;검색 증강 생성&lt;br&gt;(RAG)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;어떻게 AI에게 최신/정확한 외부 지식을 제공할 것인가&lt;/td&gt;
&lt;td&gt;데이터 파이프라인 구축, 청킹/임베딩 관리&lt;/td&gt;
&lt;td&gt;정보의 정확성과 환각(Hallucination) 방지에 뛰어나나, 지식의 참조 용도에 그치며 스스로 환경과 상호작용하는 자율성(Actionable)은 부족함.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;하네스 엔지니어링&lt;br&gt;(Harness Engineering)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;AI 에이전트가 시스템과 상호작용하는 &amp;#39;환경&amp;#39;과 보호막인 &amp;#39;가드레일&amp;#39;을 어떻게 구축할 것인가&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;에이전트 작업 공간(Workspace) 설계, 권한 및 통제, 워크플로우 기획&lt;/td&gt;
&lt;td&gt;AI가 여러 도구를 자율적으로 호출하며 복잡한 워크플로우를 완수할 수 있게 돕고, 예측 가능성 및 엔터프라이즈급 안정성을 확보.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h3&gt;  [심층 비교] oh-my-opencode 도구와의 추구 목표 및 방법론 차이&lt;/h3&gt;
&lt;p&gt;최근 CLI 기반 에이전트 환경에서 주목받는 &lt;strong&gt;oh-my-opencode&lt;/strong&gt; 같은 다중 에이전트 오케스트레이션 도구와 일반적인 통제 개념인 하네스 엔지니어링은 서로 맞닿아 있지만, 관점과 목표에서 뚜렷한 차이를 보입니다.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;구분&lt;/th&gt;
&lt;th&gt;oh-my-opencode 등 오케스트레이션 도구&lt;/th&gt;
&lt;th&gt;하네스 엔지니어링(Harness Engineering)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;핵심 목표&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;생산성 극대화를 위한 &amp;#39;Batteries-included&amp;#39; 워크플로우 제공&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;신뢰성 확보를 위한 &amp;#39;보편적 통제 환경 및 가드레일&amp;#39; 구축&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;접근 관점&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;도구 및 제품 중심 (Tool/Product-Centric)&lt;/td&gt;
&lt;td&gt;아키텍처 및 철학 중심 (Architecture-Driven)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;방법론&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;개발자가 복잡하게 환경을 세팅할 필요 없이, 역할이 부여된 전문가 에이전트(Architect, Frontend, Librarian 등)와 필수 도구(LSP, AST 등)를 &lt;strong&gt;플러그인 형태로 결합하여 즉시 실무에 투입&lt;/strong&gt;하는 데 초점을 둡니다.&lt;/td&gt;
&lt;td&gt;AI가 스스로 과대평가하는 함정에 빠지거나 컨텍스트가 소진되지 않도록, &lt;strong&gt;에이전트별 평가자 분리, 강력한 검증 루프, 치명적 권한 제어 등 시스템적 통제 장치를 어떻게 설계할지 연구&lt;/strong&gt;하는 데 초점을 둡니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;요약하자면:&lt;/strong&gt; &lt;code&gt;oh-my-opencode&lt;/code&gt;가 개발자를 위해 모든 것이 구비된 &lt;strong&gt;&amp;#39;전문가 용병단 풀세트&amp;#39;&lt;/strong&gt;를 제공하는 기성품 솔루션이라면, 하네스 엔지니어링은 강력한 AI 에이전트들이 탈선하지 않고 무사히 목적지에 도달하도록 &lt;strong&gt;&amp;#39;규칙, 검증 시스템, 인프라를 설계하는 근본적인 철학과 기술&amp;#39;&lt;/strong&gt;을 의미합니다. 실무에서는 하네스 엔지니어링의 안정성 철학 위에서 oh-my-opencode 같은 강력한 도구를 활용해 시너지를 내는 방향으로 진화하고 있습니다.&lt;/p&gt;
&lt;hr&gt;
&lt;h1&gt;하네스 엔지니어링이 해결하는 AI의 2가지 치명적 문제점&lt;/h1&gt;
&lt;p&gt;엔트로픽(Anthropic)이 분석한 바에 따르면, AI 에이전트에게 복잡하고 큰 과제를 맡길 때 크게 두 가지 문제가 발생합니다. 하네스 엔지니어링은 바로 이 문제들을 구조적으로 해결하는 데 초점을 맞춥니다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;컨텍스트 소진 현상 (Context Exhaustion)&lt;/strong&gt;&lt;br&gt; 대화가 길어지고 처리해야 할 정보(컨텍스트)가 쌓이면 AI는 앞서 지시받은 내용을 잊거나, 한계치에 다다랐다는 생각에 작업을 대충 빨리 마무리 지으려는 경향을 보입니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;해결책 (컨텍스트 리셋):&lt;/strong&gt; 한 명의 에이전트가 모든 작업을 끝까지 몰아서 하는 것이 아니라, 역할을 나누어 &amp;#39;교대 근무&amp;#39;를 시킵니다. 작업 내용을 요약(메모)하여 다음 에이전트에게 인수인계함으로써, AI가 항상 맑은 정신(초기화된 컨텍스트) 상태에서 높은 집중도를 유지하도록 보호합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;자기 평가의 함정 (Self-Evaluation Trap)&lt;/strong&gt;&lt;br&gt; AI는 자신이 작성한 코드를 스스로 평가하라고 하면, 치명적인 버그가 있어도 &amp;quot;이 정도면 훌륭하다&amp;quot;라며 관대하게 합격시켜 버리는 편향성을 갖습니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;해결책 (역할 분리):&lt;/strong&gt; 코드를 작성하는 AI(Generator)와 이를 평가하는 엄격한 AI(Evaluator)를 완전히 분리합니다. 요리사에게 자기 음식 평가를 맡기지 않고 냉정한 미식가를 따로 부르는 것과 같이, 자신을 비판하게 만드는 대신 별도의 엄격한 평가자를 세팅합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h1&gt;하네스 엔지니어링의 핵심 구조 및 워크플로우 설계&lt;/h1&gt;
&lt;p&gt;단순히 프롬프트를 잘 쓰는 것을 넘어, 에이전트가 잘 작동할 수 있는 &amp;#39;환경&amp;#39;과 &amp;#39;파이프라인&amp;#39;을 설계하는 것이 하네스 엔지니어링의 핵심 구체적 실행 방향입니다.&lt;/p&gt;
&lt;h2&gt;1. 다중 에이전트 분업 아키텍처 (Multi-Agent System)&lt;/h2&gt;
&lt;p&gt;가장 효과적인 하네스 시스템은 역할을 명확히 쪼개는 것에서 시작합니다. 대표적인 3+1 구조는 다음과 같습니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;오케스트레이터(Orchestrator):&lt;/strong&gt; 전체 파이프라인의 흐름을 지휘하는 총괄 역할입니다. 사용자의 요청을 받아 서브 에이전트들을 순차적으로 호출하며, 상태 관리(예: &lt;code&gt;cloude.md&lt;/code&gt; 같은 마크다운 파일 활용) 및 최종 완료 보고를 수행합니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;기획팀장(Planner):&lt;/strong&gt; 사용자의 단순한 한 줄 요청을 받아, 코딩에 들어가기 전 다수의 기능이 담긴 상세 설계서로 확장합니다. 인간이 미처 생각하지 못한 세부 기획까지 도맡습니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;개발자(Generator):&lt;/strong&gt; 상세 설계도를 바탕으로 코드 작성을 전담합니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;QA 엔지니어(Evaluator):&lt;/strong&gt; 완성된 결과물을 MCP 등을 활용해 직접 구동 및 테스트합니다. 불합격이면 어디가 왜 문제인지 구체적인 피드백을 작성합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;2. 강력한 검증 루프 (Validation Loops) 적용&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;피드백 사이클:&lt;/strong&gt; Evaluator의 맹렬한 피드백을 받은 Generator가 코드를 수정하고 다시 검증을 받는 반사적 루프(Reflection &amp;amp; Self-Correction)를 구축합니다. 이 루프는 조건부 합격을 달성할 때까지 자동으로 반복됩니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;치명적 권한 제어:&lt;/strong&gt; 검증 테스트 과정에서 데이터베이스 삭제, 핵심 설정 파일 수정 등은 AI 단독으로 실행하지 못하게 &amp;#39;사용자 확인(Human-in-the-loop)&amp;#39;을 거치도록 통제를 둡니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;3. 전략적인 평가 기준표 (Evaluation Criteria) 세팅&lt;/h2&gt;
&lt;p&gt;Evaluator가 깐깐하게 채점할 수 있도록 명확한 기준을 세워주어야 합니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;약점 극복 가중치 설정:&lt;/strong&gt; AI가 이미 쉽게 해결하는 &amp;#39;기능성&amp;#39;이나 &amp;#39;기술적 완성도&amp;#39;의 비중은 낮추고, AI 특유의 뻔한 산출물(AI Slop)이 나오기 쉬운 &amp;#39;디자인 품질&amp;#39;이나 &amp;#39;독창성&amp;#39; 항목에 가중치를 대폭 상향(예: 40~50%)합니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;비전 공유:&lt;/strong&gt; 이 기준표는 Generator에게도 사전에 공유되어, AI가 코딩을 시작하기 전부터 디자인 고품질을 목표로 삼게끔 기준점을 바꿔놓는 효과를 냅니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h1&gt;하네스 엔지니어링 도구 및 지원 현황 (LLM 에이전트 적용 사례 중심)&lt;/h1&gt;
&lt;p&gt;최근에는 자율형 LLM 에이전트들이 로컬 환경이나 IDE 깊숙이 통합되면서, 이들을 안전하게 통제하기 위한 하네스 엔지니어링 장치들이 도구 자체에 내재화되거나 표준화되고 있습니다. 대표적인 툴과 이를 활용한 실제 하네스 엔지니어링 구현 사례를 살펴보겠습니다.&lt;/p&gt;
&lt;h3&gt;1. 자율형 코딩 에이전트의 내장형 가드레일 (Claude Code, Gemini Code 등)&lt;/h3&gt;
&lt;p&gt;강력한 권한을 가진 CLI 기반 또는 IDE 통합 에이전트들은 그 자체로 하네스 엔지니어링의 통제 철학을 내재화하고 있습니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;휴먼 인 더 루프 (Human-in-the-loop) 예시:&lt;/strong&gt; 에이전트가 스스로 터미널을 조작하다가 &lt;code&gt;rm -rf&lt;/code&gt; 같은 파괴적인 명령어를 실행하려 하거나, 핵심 설정 파일(&lt;code&gt;.env&lt;/code&gt;, 빌드 스크립트 등)을 수정하려 할 때 실행을 멈추고 &lt;strong&gt;개발자의 승인(Yes/No)&lt;/strong&gt;을 즉각적으로 요구하도록 권한 제어가 작동합니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;작업 전 계획 검토 (Planning &amp;amp; Review) 예시:&lt;/strong&gt; 수십 개의 파일을 한 번에 제어하기 전, &amp;quot;어떤 파일을 어떻게 수정할 것인지&amp;quot;에 대한 실행 계획(Plan)을 명확하게 제시하여 사용자의 승인을 받게 함으로써 에이전트가 의도치 않은 방향으로 폭주하는 것을 차단합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;2. 에이전트 맞춤형 권한 통제 인프라 (MCP, Model Context Protocol)&lt;/h3&gt;
&lt;p&gt;AI 모델이 외부 도구와 통신하기 위한 표준 규격인 MCP는 하네스 엔지니어링 생태계에서 매우 훌륭한 &lt;strong&gt;&amp;#39;권한 및 환경 분리 인프라&amp;#39;&lt;/strong&gt;로 작용합니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;권한 분리(Least Privilege) 사례:&lt;/strong&gt; GitHub 정보를 읽어오는 에이전트를 만들 때, 저장소 변경을 막기 위해 &lt;strong&gt;&amp;#39;읽기 전용 MCP (Search/Read-only MCP)&amp;#39;&lt;/strong&gt; 서버만 연결합니다. 반대로 실제 배포를 담당하는 프로덕션 에이전트에게만 쓰기 권한이 부여된 MCP 서버를 연결함으로써, 시스템 단위의 안전한 가드레일을 손쉽게 구축할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;3. 멀티 에이전트 상호 견제 및 검증 루프 (LangGraph, AutoGen)&lt;/h3&gt;
&lt;p&gt;에이전트 한 명에게 코딩과 테스트를 모두 맡기면 자기 합리화의 함정에 빠집니다. 프레임워크를 이용해 역할이 다른 에이전트들의 상호 견제 파이프라인을 구축합니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;강제적 반사 루프(Reflexion Loop) 구현 사례:&lt;/strong&gt; LangGraph를 이용해 파이프라인을 짭니다. &amp;quot;① 코드 작성 에이전트 (Generator)&amp;quot;가 기능을 완성하면 프레임워크가 이를 즉각 &amp;quot;② 자동 테스트 에이전트 (QA/Evaluator)&amp;quot;에게 돌려보냅니다. QA 에이전트가 버그를 발견해 피드백과 함께 Reject 처리를 하면, 에이전트 ①이 핑계를 대지 못하고 코드를 강제로 재수정하도록 루프를 묶어버립니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;4. 무한 루프 차단 및 행동 모니터링 (LangSmith 등)&lt;/h3&gt;
&lt;p&gt;통제 범위를 벗어난 에이전트의 오작동 패턴을 파악하여 하네스 규칙을 보완하는 데 필수적입니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;실행 추적(Tracing)을 활용한 제어 사례:&lt;/strong&gt; 에이전트가 환각(Hallucination)에 빠져 존재하지 않는 API 도구를 무한 호출(Tool Call Loop) 하거나, 쓸데없는 컨텍스트를 과도하게 가져와 지연되는(Latency Spike) 상황을 즉각적으로 모니터링합니다. 관리자는 이를 기반으로 &amp;quot;특정 에이전트의 도구 호출 횟수를 제한&amp;quot; 하거나 &amp;quot;특정 도구를 분리&amp;quot;하는 식의 시스템 조치를 취할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;AI 기술의 발전으로 AI가 독립적인 결과물을 잘 만들어낼수록, 개발자의 핵심 역량은 점차 코드를 타이핑하는 데서 &amp;quot;가장 효율적이고 안전한 AI 노동 환경을 설계하는 하네스 엔지니어링&amp;quot;으로 옮겨갈 것입니다.&lt;/p&gt;</description>
      <category>devops</category>
      <category>AI</category>
      <category>AI Agent</category>
      <category>Harness Engineering</category>
      <category>llm</category>
      <category>MLOps</category>
      <author>디클냥</author>
      <guid isPermaLink="true">https://devopslog.tistory.com/225</guid>
      <comments>https://devopslog.tistory.com/225#entry225comment</comments>
      <pubDate>Mon, 30 Mar 2026 13:16:13 +0900</pubDate>
    </item>
    <item>
      <title>macOS 잠자기 방지 완벽 가이드: Amphetamine vs caffeinate 비교 및 클램쉘 모드 활용</title>
      <link>https://devopslog.tistory.com/224</link>
      <description>&lt;p&gt;macOS를 사용하다 보면 대용량 파일 다운로드, 긴 빌드 작업, 또는 백그라운드 스크립트 실행 등을 위해 화면이 꺼지거나 시스템이 잠자기에 들지 않도록 설정해야 할 때가 있습니다. 이를 위해 사용하는 대표적인 두 가지 방식이 &lt;strong&gt;CLI 기반의 &lt;code&gt;caffeinate&lt;/code&gt; 명령어&lt;/strong&gt;와 &lt;strong&gt;GUI 기반의 &lt;code&gt;Amphetamine&lt;/code&gt; 앱&lt;/strong&gt;입니다.&lt;/p&gt;
&lt;p&gt;이 글에서는 두 도구의 기능과 옵션을 면밀히 비교하고, 작업 환경에 따른 제어 방법, 그리고 맥북 유저들의 고민거리인 &lt;strong&gt;클램쉘 모드(Clamshell Mode)&lt;/strong&gt;에서의 동작 차이까지 종합적으로 정리해 보겠습니다.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;1. 내장 명령어 &lt;code&gt;caffeinate&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;caffeinate&lt;/code&gt;는 macOS에 기본 탑재된 커맨드라인 유틸리티로, 별도의 앱 설치 없이 터미널에서 즉시 사용할 수 있습니다. 스크립트나 자동화 파이프라인(DevOps)에 통합하기 매우 좋습니다.&lt;/p&gt;
&lt;h3&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;-d&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;디스플레이 잠자기 방지&lt;/strong&gt; (Prevent display sleep)&lt;/td&gt;
&lt;td&gt;프레젠테이션, 대시보드 모니터링 띄워두기&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-i&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;시스템 유휴 잠자기 방지&lt;/strong&gt; (Prevent system idle sleep)&lt;/td&gt;
&lt;td&gt;백그라운드 컴파일, 대용량 파일 다운로드 (화면은 꺼져도 시스템은 켜둠)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-m&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;디스크 유휴 잠자기 방지&lt;/strong&gt; (Prevent disk idle sleep)&lt;/td&gt;
&lt;td&gt;외장 하드디스크 I/O 작업 중 디스크 절전 방지&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-s&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;전원 연결 시 시스템 잠자기 방지&lt;/strong&gt; (System sleep, AC power only)&lt;/td&gt;
&lt;td&gt;전원이 연결된 상태에서만 안전하게 각성 유지&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-u&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;사용자 활성 상태로 선언&lt;/strong&gt; (Declare user active)&lt;/td&gt;
&lt;td&gt;화면이 꺼져있을 때 즉시 켜고 절전 모드로 가는 것을 방지&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-t [초]&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;특정 시간 동안 유지&lt;/strong&gt; (Timeout)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;caffeinate -t 3600&lt;/code&gt; (1시간 동안 잠자기 방지)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-w [PID]&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;특정 프로세스가 종료될 때까지 대기&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;caffeinate -w 1234&lt;/code&gt; (PID 1234가 끝날 때까지 방지)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;  실전 활용 팁:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;명령어와 함께 실행:&lt;/strong&gt; &lt;code&gt;caffeinate -i npm run build&lt;/code&gt; (빌드가 끝날 때까지만 시스템 유휴 잠금 방지)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;일반적인 백그라운드 봇 돌리기:&lt;/strong&gt; &lt;code&gt;caffeinate -i -s&lt;/code&gt; (화면은 꺼지되, 전원 연결 시 시스템은 상시 구동)&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;2. 서드파티 앱 &lt;code&gt;Amphetamine&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://apps.apple.com/us/app/amphetamine/id937984704&quot;&gt;Amphetamine&lt;/a&gt;은 macOS 생태계에서 가장 강력하고 널리 쓰이는 무료 잠자기 방지 앱입니다. 상태 표시줄(메뉴바)에 상주하며, 간단한 토글 액션과 함께 복잡한 &amp;#39;트리거(Trigger)&amp;#39; 기반의 자동화 기능을 제공합니다.&lt;/p&gt;
&lt;h3&gt;주요 기능 및 동작 제어&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;세션(Session) 기반 제어:&lt;/strong&gt; 무기한, 특정 시간(분/시간), 특정 앱이 실행 중일 때, 파일 다운로드가 완료될 때까지 등 상황에 맞게 각성 상태를 제어할 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;고급 트리거(Triggers):&lt;/strong&gt;&lt;ul&gt;
&lt;li&gt;특정 Wi-Fi 네트워크에 연결되었을 때 (예: 회사 네트워크)&lt;/li&gt;
&lt;li&gt;특정 블루투스 기기가 연결되었을 때&lt;/li&gt;
&lt;li&gt;AC 전원이 연결되었을 때&lt;/li&gt;
&lt;li&gt;배터리가 N% 이하로 떨어지면 잠자기 허용 (배터리 보호)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;드라이브 활성 유지 (Drive Keep Alive):&lt;/strong&gt; 무휴동 상태에서 외장 스토리지가 절전 모드에 들어가는 것을 막기 위해 주기적으로 빈 파일을 썼다 지우는 기능을 지원합니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;비활성 화면 보호 무효화:&lt;/strong&gt; 마우스 커서를 주기적으로 조금씩 움직이게 하여 사내 보안 정책 등으로 인해 강제로 화면이 잠기는 것을 방지할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;3. Amphetamine vs caffeinate 비교 요약&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;구분&lt;/th&gt;
&lt;th&gt;&lt;code&gt;caffeinate&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;&lt;code&gt;Amphetamine&lt;/code&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;종류&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;CLI 도구 (macOS 내장)&lt;/td&gt;
&lt;td&gt;GUI 앱 (Mac App Store 무료)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;적합한 사용자&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;개발자, 시스템 관리자, 터미널 헤비 유저&lt;/td&gt;
&lt;td&gt;일반 데스크톱 사용자, 세밀한 UI 제어 필요 유저&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;자동화 방식&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Shell 명령, 프로세스(PID) 연동&lt;/td&gt;
&lt;td&gt;Wi-Fi, 배터리 잔량, 특정 앱 실행 등의 물리/OS 환경&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;인터페이스&lt;/strong&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;strong&gt;설치 및 종속성&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;❌ (기본 탑재, 추가 설치 없음)&lt;/td&gt;
&lt;td&gt;✅ (App Store 설치 필요)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;4. 클램쉘 모드(Clamshell Mode)와 각성 제어&lt;/h2&gt;
&lt;p&gt;맥북 덮개를 닫은 상태로 모니터에 연결해 데스크톱처럼 사용하는 것을 &lt;strong&gt;클램쉘 모드&lt;/strong&gt;라고 합니다. &lt;/p&gt;
&lt;h3&gt;기본 시스템 제약&lt;/h3&gt;
&lt;p&gt;macOS는 기본적으로 &lt;strong&gt;&amp;quot;전원 연결 + 외부 디스플레이 연결 + 외부 입력장치(키보드/마우스) 작동&amp;quot;&lt;/strong&gt; 조건이 모두 충족될 때만 덮개를 닫았을 때 절전 모드로 진입하지 않습니다. &lt;/p&gt;
&lt;h3&gt;&lt;code&gt;caffeinate&lt;/code&gt;를 통한 클램쉘 제어 한계&lt;/h3&gt;
&lt;p&gt;터미널에서 &lt;code&gt;caffeinate -i&lt;/code&gt; 를 실행한 상태라도, 위 3가지 조건 없이 단순히 맥북 덮개를 닫으면 하드웨어적인 Sleep 명령이 우선 적용되어 절전 모드로 들어갑니다. &lt;strong&gt;즉, 순정 상태의 Mac에서는 &lt;code&gt;caffeinate&lt;/code&gt; 단독으로 모니터 없이 덮개를 닫은 채 서버처럼 구동할 수 없습니다.&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;&lt;code&gt;Amphetamine&lt;/code&gt;의 &amp;quot;Closed-Display Mode&amp;quot; 마법&lt;/h3&gt;
&lt;p&gt;Amphetamine은 설정을 통해 애플의 하드웨어 슬립 제약을 우회할 수 있습니다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;옵션 해제:&lt;/strong&gt; 설정에서 &lt;strong&gt;&amp;quot;Allow system sleep when display is closed&amp;quot; (디스플레이를 닫았을 때 시스템 잠자기 허용)&lt;/strong&gt; 체크를 해제하면 덮개를 닫아도 강제로 절전 모드로 가지 않게 막을 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;독립적인 백그라운드 구동:&lt;/strong&gt; 모니터나 전원조차 연결하지 않고도 덮개를 닫은 채 렌더링을 계속하거나, 로컬 서버를 유지할 수 있습니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;p&gt;⚠️ &lt;strong&gt;주의사항 (발열 이슈):&lt;/strong&gt; 덮개를 닫은 채 무거운 로드를 발생시키는 백그라운드 작업을 실행하고 통풍이 안 되는 가방 등에 넣으면 &lt;strong&gt;심각한 발열로 인해 기기에 영구적인 데미지&lt;/strong&gt;가 발생할 수 있습니다. 이 기능은 반드시 쿨링이 보장된 환경에서만 제한적으로 사용해야 합니다.&lt;/p&gt;
&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;hr&gt;
&lt;h2&gt;마무리&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;스크립트 빌드, 패키지 설치 등 &lt;strong&gt;&amp;quot;특정 작업이 끝날 때까지만 터미널에서 일시적 방어&amp;quot;&lt;/strong&gt;를 하고 싶다면 &lt;code&gt;caffeinate&lt;/code&gt;가 가장 빠르고 확실한 도구입니다.&lt;/li&gt;
&lt;li&gt;일상적인 업무(프레젠테이션, 화상 회의, 외장 드라이브 마운트 유지)나 &lt;strong&gt;강력한 클램쉘 모드 제어&lt;/strong&gt;가 필요할 때는 상태 표시줄에서 간단하게 트리거를 켤 수 있는 &lt;code&gt;Amphetamine&lt;/code&gt;을 추천합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;macOS 환경을 서버나 자동화 도구로 적극 활용하는 엔지니어라면, 상황에 맞게 두 가지 툴을 적절히 병행하여 사용하는 것이 최고의 생산성을 가져다줄 것입니다.&lt;/p&gt;</description>
      <category>devops</category>
      <category>Amphetamine</category>
      <category>Caffeinate</category>
      <category>clamshell</category>
      <category>devops</category>
      <category>macos</category>
      <category>Productivity</category>
      <author>디클냥</author>
      <guid isPermaLink="true">https://devopslog.tistory.com/224</guid>
      <comments>https://devopslog.tistory.com/224#entry224comment</comments>
      <pubDate>Tue, 10 Mar 2026 16:44:06 +0900</pubDate>
    </item>
    <item>
      <title>Claude Code 무료 플랜 활용 가이드 (Ollama, free-claude-code)</title>
      <link>https://devopslog.tistory.com/223</link>
      <description>&lt;p&gt;Claude Code를 쓰고 싶은데 유료 API 비용이 부담될 때, 실무에서는 보통 두 가지 경로를 사용합니다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;Ollama&lt;/code&gt; 기반 로컬 모델 연결&lt;/li&gt;
&lt;li&gt;&lt;code&gt;free-claude-code&lt;/code&gt; 같은 호환 레이어를 통해 &lt;code&gt;NVIDIA NIM&lt;/code&gt;, &lt;code&gt;OpenRouter&lt;/code&gt;, &lt;code&gt;LM Studio&lt;/code&gt; 백엔드 연결&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;이 글은 각 방식의 배경, 설치/설정 방법, 그리고 운영 시 주의점을 정리합니다.&lt;/p&gt;
&lt;h2&gt;왜 &amp;quot;무료 플랜&amp;quot; 구성이 필요한가&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;코드 에이전트는 반복 호출이 많아 토큰 비용이 빠르게 증가합니다.&lt;/li&gt;
&lt;li&gt;개인 프로젝트나 학습 단계에서는 응답 품질보다 비용 상한이 더 중요할 수 있습니다.&lt;/li&gt;
&lt;li&gt;팀 환경에서는 &amp;quot;무조건 최신 고가 모델&amp;quot;보다 &amp;quot;저비용 + 재현 가능한 워크플로&amp;quot;가 더 실용적입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;핵심은, Claude Code UX를 유지하면서 백엔드를 교체하는 것입니다.&lt;/p&gt;
&lt;h3&gt;방법 1) Ollama 이용&lt;/h3&gt;
&lt;h4&gt;개념&lt;/h4&gt;
&lt;p&gt;Ollama는 로컬에서 오픈 모델을 구동하는 런타임입니다.&lt;br&gt;즉, Anthropic의 Claude 모델을 직접 무료로 쓰는 방식이 아니라, Claude Code와 유사한 개발 플로우를 로컬 LLM으로 대체하는 접근입니다.&lt;/p&gt;
&lt;h4&gt;준비&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;충분한 로컬 리소스(메모리/VRAM)&lt;/li&gt;
&lt;li&gt;Ollama 설치&lt;/li&gt;
&lt;li&gt;코드 작업에 맞는 모델 선택 (&lt;code&gt;qwen&lt;/code&gt;, &lt;code&gt;llama&lt;/code&gt;, &lt;code&gt;deepseek-coder&lt;/code&gt; 계열 등)&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;설치&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# macOS (Homebrew)
brew install ollama

# Linux는 공식 설치 스크립트 또는 패키지 매니저로 설치&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;가장 쉬운 연동 (공식)&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;ollama launch claude&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;위 명령은 Claude Code 연동에 필요한 설정 과정을 대화형으로 진행합니다.&lt;/p&gt;
&lt;h4&gt;수동 환경 설정 예시&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# .bashrc or.zshrc 파일에 등록, 수동 등록 
export ANTHROPIC_BASE_URL=http://localhost:11434
export ANTHROPIC_AUTH_TOKEN=ollama
export ANTHROPIC_MODEL=qwen3-coder&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;실행 예시:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;claude --model &amp;quot;$ANTHROPIC_MODEL&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;모델 선택 팁&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;코드 작업에서는 tool-use 성능과 긴 컨텍스트(예: 64K 이상)를 우선 확인&lt;/li&gt;
&lt;li&gt;작은 모델은 저비용/저지연에 유리하지만, 복잡한 리팩터링 정확도는 낮아질 수 있음&lt;/li&gt;
&lt;li&gt;팀 표준 모델 1개 + 빠른 보조 모델 1개로 운영하면 품질/비용 균형을 잡기 쉽습니다&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Ollama의 Claude 지원 요약&lt;/h4&gt;
&lt;p&gt;Ollama v0.14.0 이상은 Anthropic Messages API를 구현해 Claude Code와 다른 Anthropic 클라이언트가 로컬 Ollama 모델을 그대로 사용할 수 있도록 합니다. 이 통합으로 스트리밍, 시스템 프롬프트, 툴 콜링, 확장된 &lt;code&gt;thinking&lt;/code&gt; 토큰, 멀티모달 입력, 서브에이전트 오케스트레이션 등이 Claude 환경과 동일하게 작동하며, 기본 엔드포인트(&lt;code&gt;http://localhost:11434&lt;/code&gt;)를 통해 Anthropic SDK와의 호환성도 유지됩니다. &lt;code&gt;ollama launch claude&lt;/code&gt; 명령은 이 환경 변수/모델 설정을 자동으로 구성하는 단계를 감쌉니다.&lt;/p&gt;
&lt;h4&gt;&lt;code&gt;cloud&lt;/code&gt; 태그 모델 사용법&lt;/h4&gt;
&lt;p&gt;Ollama의 cloud 모델은 로컬 GPU가 부족해도 큰 모델을 사용할 수 있는 방식입니다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Ollama 계정 로그인&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;ollama signin&lt;/code&gt;&lt;/pre&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;Claude Code에서 cloud 모델 지정 실행&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;claude --model glm-4.7:cloud&lt;/code&gt;&lt;/pre&gt;
&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;필요 시 &lt;code&gt;ollama launch&lt;/code&gt;에서 cloud 모델 직접 지정&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;ollama launch claude --model glm-4.7:cloud&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;메모:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;cloud 모델은 보통 로컬 &lt;code&gt;pull&lt;/code&gt; 없이 바로 사용 가능합니다.&lt;/li&gt;
&lt;li&gt;모델명 suffix는 모델마다 다를 수 있으므로 (&lt;code&gt;:cloud&lt;/code&gt;, &lt;code&gt;-cloud&lt;/code&gt;), &lt;code&gt;https://ollama.com/search?c=cloud&lt;/code&gt;에서 실제 이름을 확인하세요.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;장단점&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;장점: 완전 로컬, 비용 예측 용이, 개인정보 통제에 유리&lt;/li&gt;
&lt;li&gt;단점: 모델 품질/툴콜 안정성 편차, 로컬 머신 자원 소모&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;방법 2) free-claude-code 이용 (NVIDIA NIM / OpenRouter / LM Studio)&lt;/h3&gt;
&lt;h4&gt;개념&lt;/h4&gt;
&lt;p&gt;&lt;code&gt;free-claude-code&lt;/code&gt; 류 도구는 &amp;quot;Claude Code가 기대하는 인터페이스&amp;quot;와 &amp;quot;다른 LLM 제공자 API&amp;quot; 사이를 중계하는 래퍼입니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Claude Code 클라이언트는 기존처럼 사용&lt;/li&gt;
&lt;li&gt;실제 모델 추론은 NIM/OpenRouter/LM Studio로 전달&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;설치&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Claude Code 설정에 필요한 &lt;code&gt;free-claude-code&lt;/code&gt; 캐시를 로컬에 clone&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.env.example&lt;/code&gt;를 &lt;code&gt;.env&lt;/code&gt;로 복사해 기본 변수들을 채운 뒤 &lt;code&gt;uv&lt;/code&gt;/&lt;code&gt;pip&lt;/code&gt; 의존성을 설치&lt;/li&gt;
&lt;li&gt;backend(providers)별 API 키/엔드포인트를 &lt;code&gt;.env&lt;/code&gt;에 기록&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;git clone https://github.com/Alishahryar1/free-claude-code.git
cd free-claude-code
cp .env.example .env
# fill ANTHROPIC_BASE_URL, API keys, MODEL overrides in .env
pip install --upgrade pip
pip install -r requirements.txt&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;공통 설정 흐름&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;초기 설정: &lt;code&gt;free-claude-code setup&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;서버 실행: &lt;code&gt;free-claude-code&lt;/code&gt; (기본 &lt;code&gt;http://localhost:8082&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Claude Code가 로컬 프록시를 보도록 환경변수 지정&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;export ANTHROPIC_AUTH_TOKEN=freecc
export ANTHROPIC_BASE_URL=http://localhost:8082&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;모델을 즉시 지정하려면:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;export ANTHROPIC_AUTH_TOKEN=freecc:open_router/openai/gpt-4o-mini&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;참고: 토큰 뒤에 &lt;code&gt;:0.3&lt;/code&gt;처럼 temperature를 붙여서 실행 시점 제어도 가능합니다.&lt;/p&gt;
&lt;h4&gt;Provider별 환경변수 예시&lt;/h4&gt;
&lt;p&gt;각 공급자별로 필요한 기본 환경변수를 아래처럼 설정해두면, &lt;code&gt;free-claude-code&lt;/code&gt; 프록시가 해당 API로 요청을 포워딩합니다.&lt;/p&gt;
&lt;h4&gt;OpenRouter&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;export MODEL=open_router/openai/gpt-4o-mini
export OPENROUTER_API_KEY=&amp;lt;your_key&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;OpenRouter를 쓰려면 위처럼 &lt;code&gt;MODEL&lt;/code&gt; 접두사를 &lt;code&gt;open_router/&lt;/code&gt;로 두고, 오픈라우터 API 키를 함께 전달하면 됩니다.&lt;/p&gt;
&lt;h4&gt;Quick start 체크리스트 (README 기준)&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;레포를 클론하고 &lt;code&gt;.env.example&lt;/code&gt;을 &lt;code&gt;.env&lt;/code&gt;로 복사한 다음 환경에 맞게 값들을 채우고 요구되는 &lt;code&gt;pip&lt;/code&gt;/&lt;code&gt;uv&lt;/code&gt; 의존성을 설치합니다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ANTHROPIC_BASE_URL&lt;/code&gt;을 &lt;code&gt;http://localhost:8082&lt;/code&gt;로, &lt;code&gt;ANTHROPIC_AUTH_TOKEN&lt;/code&gt;을 &lt;code&gt;freecc&lt;/code&gt;로 설정한 뒤 &lt;code&gt;:provider/model&lt;/code&gt;을 추가해 특정 모델로 고정합니다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;uv run uvicorn server:app --host 0.0.0.0 --port 8082&lt;/code&gt;로 프록시 서버를 띄웁니다.&lt;/li&gt;
&lt;li&gt;같은 환경변수로 &lt;code&gt;claude&lt;/code&gt; 또는 VSCode 확장판을 실행해 Claude Code를 기동합니다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;claude-pick&lt;/code&gt; 별칭을 이용해 &lt;code&gt;.env&lt;/code&gt;를 바꾸지 않고도 제공자/모델 조합을 탐색합니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;이 체크리스트는 README의 Clone &amp;amp; Configure 섹션 내용을 옮긴 것으로, 각 명령을 순서대로 실행해 설정을 끝내면 Claude Code가 로컬 &lt;code&gt;free-claude-code&lt;/code&gt; 프록시를 통해 Anthropic 호환 모델을 이용합니다.&lt;/p&gt;
&lt;h4&gt;NVIDIA NIM (recommended — 40 req/min free)&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;export MODEL=nvidia_nim/stepfun-ai/step-3.5-flash
export NVIDIA_NIM_API_KEY=nvapi-your-key-here
export NIM_BASE_URL=https://api.stepfun.ai&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;NVIDIA NIM은 &lt;code&gt;nvidia_nim/&lt;/code&gt; 접두사를 쓰고, &lt;code&gt;NIM_BASE_URL&lt;/code&gt;로 엔드포인트를 설정하면 정해진 요청 속도로 무료 금액을 사용할 수 있습니다.&lt;/p&gt;
&lt;h4&gt;LM Studio&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;export MODEL=lmstudio/qwen2.5-coder:14b
export LM_STUDIO_BASE_URL=http://127.0.0.1:1234/v1&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;LM Studio를 백엔드로 쓰려면 &lt;code&gt;lmstudio/&lt;/code&gt; 접두사와 로컬 서버 주소를 지정하고, 필요한 경우 프록시에서 API 키를 점검하세요.&lt;/p&gt;
&lt;h4&gt;free-claude-code 기능&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;uvicorn server:app&lt;/code&gt; 프록시를 통해 트래픽을 중개하며 Claude 특화 &amp;quot;사소한 요청&amp;quot;을 걸러내고 &lt;code&gt;reasoning_content&lt;/code&gt;/`` thinking 태그를 Claude Code에 맞게 다시 포맷합니다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;MODEL={prefix}/{provider model}&lt;/code&gt; 형식으로 모델 전환을 강제하고, 접두사 오류는 프로바이더 호출 전에 검증 에러로 잡힙니다.&lt;/li&gt;
&lt;li&gt;리포에는 Discord/Telegram 봇, 음성 노트 업로드 처리, 프록시의 동시성 제한 같은 헬퍼가 포함되어 있어 레이트 리밋을 관리할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;실행 예시:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# 서버 실행
free-claude-code&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;연결 테스트:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;curl -s http://localhost:8082/health&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Claude Code 쪽 적용 포인트&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;ANTHROPIC_BASE_URL&lt;/code&gt;을 &lt;code&gt;http://localhost:8082&lt;/code&gt;로 지정&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ANTHROPIC_AUTH_TOKEN=freecc[:model]&lt;/code&gt; 패턴으로 모델 라우팅&lt;/li&gt;
&lt;li&gt;스트리밍 모드 사용 시 timeout 값을 늘려 긴 코드 생성 중 끊김을 방지&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.env&lt;/code&gt; 또는 셸 프로파일에 설정값을 저장하고, 팀 내 표준 이름을 통일&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;예시(&lt;code&gt;.env&lt;/code&gt;):&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-dotenv&quot;&gt;ANTHROPIC_BASE_URL=http://localhost:8082
ANTHROPIC_AUTH_TOKEN=freecc:open_router/openai/gpt-4o-mini
MODEL=open_router/openai/gpt-4o-mini
OPENROUTER_API_KEY=...&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;참고 문서&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;free-claude-code&lt;/code&gt; README: &lt;a href=&quot;https://github.com/Alishahryar1/free-claude-code?tab=readme-ov-file&quot;&gt;https://github.com/Alishahryar1/free-claude-code?tab=readme-ov-file&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Ollama Claude Code integration: &lt;a href=&quot;https://docs.ollama.com/integrations/claude-code&quot;&gt;https://docs.ollama.com/integrations/claude-code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Ollama docs: &lt;a href=&quot;https://ollama.com/docs&quot;&gt;https://ollama.com/docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Claude Code CLI: &lt;a href=&quot;https://www.anthropic.com/claude/docs/claude-code&quot;&gt;https://www.anthropic.com/claude/docs/claude-code&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;운영 팁&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;OpenRouter는 모델별 단가/지연이 다르므로 작업 유형(리팩터링/테스트 생성/문서화)별 모델을 분리하면 비용을 줄일 수 있습니다.&lt;/li&gt;
&lt;li&gt;NIM은 기업 환경에서 성능/보안 정책을 맞추기 쉽습니다.&lt;/li&gt;
&lt;li&gt;LM Studio는 완전 로컬 테스트에 좋지만 대형 코드베이스 작업에서는 모델 크기와 컨텍스트 한계를 먼저 확인해야 합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;무엇을 선택할까&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;개인 로컬 실험: &lt;code&gt;Ollama&lt;/code&gt; 또는 &lt;code&gt;LM Studio&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;다양한 상용/오픈 모델 빠른 비교: &lt;code&gt;OpenRouter&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;팀/기업 정책 중심 운영: &lt;code&gt;NVIDIA NIM&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;결론적으로, &amp;quot;Claude Code 무료 플랜&amp;quot;은 공식 무료 Claude 자체를 의미하기보다, Claude Code 사용 경험을 유지한 채 백엔드를 비용 효율적으로 대체하는 아키텍처 전략에 가깝습니다.&lt;/p&gt;
&lt;h2&gt;트러블슈팅&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;401/403&lt;/code&gt; 오류: API 키 누락, provider 불일치, 잘못된 권한 스코프 확인&lt;/li&gt;
&lt;li&gt;&lt;code&gt;404 model not found&lt;/code&gt;: &lt;code&gt;MODEL&lt;/code&gt; 접두사(&lt;code&gt;open_router/&lt;/code&gt;, &lt;code&gt;nvidia_nim/&lt;/code&gt;, &lt;code&gt;lmstudio/&lt;/code&gt;) 오타 확인&lt;/li&gt;
&lt;li&gt;&lt;code&gt;connection refused&lt;/code&gt;: 로컬 서버(Ollama/LM Studio/래퍼) 미실행 또는 포트 오타&lt;/li&gt;
&lt;li&gt;&lt;code&gt;claude&lt;/code&gt;에서 모델 선택이 꼬일 때: &lt;code&gt;claude-pick&lt;/code&gt; 별칭으로 모델 재선택 후 재시도&lt;/li&gt;
&lt;li&gt;응답 지연/타임아웃: 모델 크기 축소, 컨텍스트 길이 조정, timeout 상향&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;주의사항&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;각 서비스의 이용약관/요금/레이트리밋은 수시로 바뀌므로 배포 전 최신 문서를 다시 확인하세요.&lt;/li&gt;
&lt;li&gt;코드/비밀값이 외부 API로 전송될 수 있으므로, 저장소 필터링(&lt;code&gt;.env&lt;/code&gt;, 키, 고객 데이터) 정책을 먼저 적용하세요.&lt;/li&gt;
&lt;li&gt;팀 공용 환경에서는 &amp;quot;허용 모델 목록 + 최대 토큰 + 일일 예산&amp;quot;을 강제하는 가드레일을 두는 것이 안전합니다.&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>devops</category>
      <category>ai-agent</category>
      <category>claude</category>
      <category>claude-code</category>
      <category>devops</category>
      <category>lm-studio</category>
      <category>nvidia-nim</category>
      <category>Ollama</category>
      <category>openrouter</category>
      <author>디클냥</author>
      <guid isPermaLink="true">https://devopslog.tistory.com/223</guid>
      <comments>https://devopslog.tistory.com/223#entry223comment</comments>
      <pubDate>Tue, 10 Mar 2026 15:34:40 +0900</pubDate>
    </item>
    <item>
      <title>AI Agent 구현의 두 갈래: 일반 Tool Calling vs MCP 비교</title>
      <link>https://devopslog.tistory.com/222</link>
      <description>&lt;p&gt;AI 에이전트를 구축할 때, LLM이 외부 도구를 사용하게 만드는 과정은 필수적입니다. 하지만 최근 등장한 &lt;strong&gt;MCP(Model Context Protocol)&lt;/strong&gt;와 기존의 &lt;strong&gt;Function/Tool Calling&lt;/strong&gt;은 비슷해 보이면서도 구조적으로 큰 차이가 있습니다. 오늘은 이 두 방식의 특징과 실제 구현 관점에서의 차이를 상세히 비교해 보겠습니다.&lt;/p&gt;
&lt;h2&gt;1. 한눈에 보는 비교 요약&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&quot;left&quot;&gt;구분&lt;/th&gt;
&lt;th align=&quot;left&quot;&gt;일반 Tool Calling (기존 방식)&lt;/th&gt;
&lt;th align=&quot;left&quot;&gt;MCP (Model Context Protocol)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;핵심 개념&lt;/strong&gt;&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;함수 정의와 실행 로직의 수동 연결&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;도구의 정의와 실행이 결합된 표준화된 서버&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;실행 주체&lt;/strong&gt;&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;에이전트 애플리케이션 (Local, Tightly Coupled)&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;독립된 MCP 서버 (Remote/Isolated)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;통신 규격&lt;/strong&gt;&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;모델별 전용 API (OpenAI, Anthropic 등)&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;JSON-RPC 2.0&lt;/strong&gt; 표준 프로토콜&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;툴 목록 관리&lt;/strong&gt;&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;코드에 하드코딩, 앱 재배포 필요&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;서버에서 동적으로 &lt;code&gt;list_tools()&lt;/code&gt; 조회&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;확장성&lt;/strong&gt;&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;새 툴 추가 시 앱 코드 수정 및 재배포&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;MCP 서버만 추가·재시작하면 즉시 연동&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;상호운용성&lt;/strong&gt;&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;모델별 규격 변환 코드 직접 작성 필요&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;MCP 지원 클라이언트라면 어떤 모델이든 재사용&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;컨텍스트 제공&lt;/strong&gt;&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;주로 &amp;#39;액션(함수 호출)&amp;#39;에 집중&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;툴 + &lt;strong&gt;리소스(파일, DB)&lt;/strong&gt; + &lt;strong&gt;프롬프트 템플릿&lt;/strong&gt; 패키지&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;보안/격리&lt;/strong&gt;&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;에이전트 프로세스 내에서 직접 실행&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;실행 로직이 서버에 캡슐화, 권한 경계 명확&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;2. 일반 Tool Calling: &amp;quot;직접 요리하기&amp;quot; 방식&lt;/h2&gt;
&lt;p&gt;일반적인 방식에서 에이전트는 요리사(LLM)가 준 레시피(JSON)를 보고 &lt;strong&gt;직접 요리(함수 실행)&lt;/strong&gt;를 합니다.&lt;br&gt;실행 로직이 에이전트 코드 내부에 깊게 박혀 있는 구조(Tightly Coupled)입니다.&lt;/p&gt;
&lt;h3&gt;동작 흐름&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;사용자 요청
    ↓
에이전트 앱 (툴 스키마 정의 보유)
    ↓ (1) 툴 스키마 + 메시지 전달
LLM API
    ↓ (2) tool_calls JSON 반환
에이전트 앱 (if/else 분기로 직접 실행)
    ↓ (3) 로컬 함수 호출 → 결과 획득
LLM API (결과를 포함해 재호출)
    ↓ (4) 최종 텍스트 응답
사용자&lt;/code&gt;&lt;/pre&gt;&lt;h3&gt;구현 예시 (Python)&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;import json

# 1. 툴 정의 (JSON 스키마 — 에이전트 코드에 하드코딩)
tools = [
    {
        &amp;quot;type&amp;quot;: &amp;quot;function&amp;quot;,
        &amp;quot;function&amp;quot;: {
            &amp;quot;name&amp;quot;: &amp;quot;adder&amp;quot;,
            &amp;quot;description&amp;quot;: &amp;quot;두 정수를 더합니다.&amp;quot;,
            &amp;quot;parameters&amp;quot;: {
                &amp;quot;type&amp;quot;: &amp;quot;object&amp;quot;,
                &amp;quot;properties&amp;quot;: {
                    &amp;quot;a&amp;quot;: {&amp;quot;type&amp;quot;: &amp;quot;integer&amp;quot;},
                    &amp;quot;b&amp;quot;: {&amp;quot;type&amp;quot;: &amp;quot;integer&amp;quot;},
                },
                &amp;quot;required&amp;quot;: [&amp;quot;a&amp;quot;, &amp;quot;b&amp;quot;],
            },
        },
    }
]

# 2. LLM 호출
response = llm_client.chat.completions.create(
    model=&amp;quot;gpt-4o&amp;quot;,
    messages=messages,
    tools=tools,
)

# 3. 직접 매핑 및 실행 (에이전트가 실행 오너십 보유)
if response.choices[0].message.tool_calls:
    tool_call = response.choices[0].message.tool_calls[0]
    name = tool_call.function.name
    args = json.loads(tool_call.function.arguments)

    # 툴이 늘어날수록 if/else 분기가 계속 증가
    if name == &amp;quot;adder&amp;quot;:
        result = args[&amp;quot;a&amp;quot;] + args[&amp;quot;b&amp;quot;]   # 에이전트가 직접 실행!
    elif name == &amp;quot;another_tool&amp;quot;:
        result = another_local_func(**args)
    # ...

    # 결과를 메시지에 추가하고 재호출
    messages.append(response.choices[0].message)
    messages.append({
        &amp;quot;role&amp;quot;: &amp;quot;tool&amp;quot;,
        &amp;quot;tool_call_id&amp;quot;: tool_call.id,
        &amp;quot;content&amp;quot;: str(result),
    })
    final = llm_client.chat.completions.create(model=&amp;quot;gpt-4o&amp;quot;, messages=messages)
    print(final.choices[0].message.content)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;특징 요약&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;구현이 직관적이고 별도 인프라가 필요 없어 &lt;strong&gt;프로토타이핑에 적합&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;툴이 늘어날수록 &lt;code&gt;if/else&lt;/code&gt; 분기가 길어지고 유지보수 비용 증가&lt;/li&gt;
&lt;li&gt;OpenAI용 코드를 Anthropic/Gemini에 사용하려면 &lt;strong&gt;규격 변환 코드를 직접 작성&lt;/strong&gt; 필요&lt;/li&gt;
&lt;li&gt;에이전트 프로세스가 중단되면 툴 실행도 함께 중단&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;3. MCP Calling: &amp;quot;배달 주문하기&amp;quot; 방식&lt;/h2&gt;
&lt;p&gt;MCP 방식에서 에이전트는 요리사(LLM)의 요청을 보고 &lt;strong&gt;전문 식당(MCP 서버)에 주문(Call)&lt;/strong&gt;을 넣습니다.&lt;br&gt;에이전트는 내부 로직을 몰라도 표준 규격(JSON-RPC 2.0)만 맞추면 됩니다.&lt;/p&gt;
&lt;h3&gt;동작 흐름&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;사용자 요청
    ↓
에이전트 앱
    ↓ (1) list_tools() — 툴 목록 동적 조회
MCP 서버 (독립 프로세스)
    ↓ 툴 스키마 반환
에이전트 앱
    ↓ (2) 툴 스키마 + 메시지 전달
LLM API
    ↓ (3) tool_calls JSON 반환
에이전트 앱
    ↓ (4) call_tool() — 실행 위임 (JSON-RPC)
MCP 서버 (실행 오너십 보유)
    ↓ 결과 반환
에이전트 앱 → LLM 재호출 → 최종 응답
    ↓
사용자&lt;/code&gt;&lt;/pre&gt;&lt;h3&gt;구현 예시 (Python — mcp 라이브러리 사용)&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client

# 1. MCP 서버와 연결 (독립된 서버 프로세스)
server_params = StdioServerParameters(command=&amp;quot;python&amp;quot;, args=[&amp;quot;mcp_server.py&amp;quot;])

async with stdio_client(server_params) as (read, write):
    async with ClientSession(read, write) as session:
        await session.initialize()

        # 2. 툴 목록을 서버에서 동적으로 가져옴 — 하드코딩 불필요
        tools_result = await session.list_tools()
        mcp_tools = [
            {
                &amp;quot;type&amp;quot;: &amp;quot;function&amp;quot;,
                &amp;quot;function&amp;quot;: {
                    &amp;quot;name&amp;quot;: t.name,
                    &amp;quot;description&amp;quot;: t.description,
                    &amp;quot;parameters&amp;quot;: t.inputSchema,
                },
            }
            for t in tools_result.tools
        ]

        # 3. LLM 호출
        response = llm_client.chat.completions.create(
            model=&amp;quot;gpt-4o&amp;quot;,
            messages=messages,
            tools=mcp_tools,
        )

        # 4. 실행 위임 — 에이전트는 단순히 중계만 수행
        if response.choices[0].message.tool_calls:
            tool_call = response.choices[0].message.tool_calls[0]

            # MCP 서버로 실행 요청 위임 (실행 Ownership: Server)
            result = await session.call_tool(
                name=tool_call.function.name,
                arguments=json.loads(tool_call.function.arguments),
            )

            messages.append(response.choices[0].message)
            messages.append({
                &amp;quot;role&amp;quot;: &amp;quot;tool&amp;quot;,
                &amp;quot;tool_call_id&amp;quot;: tool_call.id,
                &amp;quot;content&amp;quot;: str(result.content),
            })
            final = llm_client.chat.completions.create(model=&amp;quot;gpt-4o&amp;quot;, messages=messages)
            print(final.choices[0].message.content)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;특징 요약&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;실행 로직이 MCP 서버에 캡슐화되어 &lt;strong&gt;보안성·격리성&lt;/strong&gt; 우수&lt;/li&gt;
&lt;li&gt;&lt;code&gt;list_tools()&lt;/code&gt;로 툴 목록을 동적으로 수신 — 서버 재시작만으로 신규 툴 적용&lt;/li&gt;
&lt;li&gt;한 번 만든 MCP 서버를 Claude, GPT, Gemini 등 &lt;strong&gt;여러 모델에서 공용&lt;/strong&gt; 사용 가능&lt;/li&gt;
&lt;li&gt;툴 외에도 &lt;strong&gt;Resources&lt;/strong&gt;(파일, DB 데이터)와 &lt;strong&gt;Prompt Templates&lt;/strong&gt;를 패키지로 제공&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;4. 핵심 차이점 상세 분석&lt;/h2&gt;
&lt;h3&gt;실행 오너십 (Ownership)&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&quot;left&quot;&gt;항목&lt;/th&gt;
&lt;th align=&quot;left&quot;&gt;Tool Calling&lt;/th&gt;
&lt;th align=&quot;left&quot;&gt;MCP&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td align=&quot;left&quot;&gt;실행 주체&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;에이전트 앱&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;MCP 서버&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;left&quot;&gt;프로세스 격리&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;❌ 동일 프로세스&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;✅ 독립 프로세스&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;left&quot;&gt;오너십 위치&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;에이전트 코드 내 하드코딩&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;서버 내 캡슐화&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;에이전트가 중단되어도 MCP 서버는 독립적으로 동작할 수 있습니다.&lt;/p&gt;
&lt;h3&gt;컨텍스트 제공 범위 (Context Sharing)&lt;/h3&gt;
&lt;p&gt;MCP는 툴(Tool), 리소스(Resource), 프롬프트 템플릿(Prompt)의 세 가지 원시 타입을 통해 모델에게 풍부한 컨텍스트를 전달합니다.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;MCP 서버가 제공하는 것
├── Tools      — 함수 호출 (기존 Tool Calling과 동일)
├── Resources  — 파일, DB 쿼리 결과 등 정적 컨텍스트
└── Prompts    — 재사용 가능한 프롬프트 템플릿&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;일반 Tool Calling은 주로 &lt;strong&gt;액션(함수 호출)&lt;/strong&gt;에만 집중하지만, MCP는 &lt;strong&gt;데이터 컨텍스트까지 패키지&lt;/strong&gt;로 제공합니다.&lt;/p&gt;
&lt;h3&gt;상호운용성 (Interoperability)&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;일반 Tool Calling:
OpenAI 툴 스키마 ──→ Anthropic 포맷 변환 코드 직접 작성 필요

MCP:
MCP 서버 ──→ (JSON-RPC 2.0 표준) ──→ 어떤 MCP 클라이언트도 즉시 연동&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;JSON-RPC 2.0을 표준 전송 계층으로 사용하므로, MCP를 지원하는 클라이언트라면&lt;br&gt;모델 종류에 관계없이 &lt;strong&gt;동일한 서버&lt;/strong&gt;를 재사용할 수 있습니다.&lt;/p&gt;
&lt;h3&gt;통신 방식 (Transport) 및 마샬링 (Marshaling)&lt;/h3&gt;
&lt;h4&gt;데이터 규약: JSON-RPC 2.0&lt;/h4&gt;
&lt;p&gt;MCP의 모든 메시지는 &lt;strong&gt;JSON-RPC 2.0&lt;/strong&gt; 표준 형식을 따릅니다.&lt;br&gt;데이터는 &lt;strong&gt;JSON(UTF-8 인코딩)&lt;/strong&gt;으로 직렬화(Marshaling)되어 전송됩니다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-json&quot;&gt;// tool_call 발생 시 에이전트 → MCP 서버로 전달되는 실제 메시지
{
  &amp;quot;jsonrpc&amp;quot;: &amp;quot;2.0&amp;quot;,
  &amp;quot;id&amp;quot;: &amp;quot;123&amp;quot;,
  &amp;quot;method&amp;quot;: &amp;quot;tools/call&amp;quot;,
  &amp;quot;params&amp;quot;: {
    &amp;quot;name&amp;quot;: &amp;quot;adder&amp;quot;,
    &amp;quot;arguments&amp;quot;: {
      &amp;quot;a&amp;quot;: 10,
      &amp;quot;b&amp;quot;: 20
    }
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;에이전트 코드에서 &lt;code&gt;session.call_tool()&lt;/code&gt;을 호출하면, MCP 라이브러리가 내부적으로 위와 같은 JSON-RPC 메시지를 만들어 서버로 전송합니다. &lt;strong&gt;개발자는 직접 JSON-RPC를 다루지 않아도&lt;/strong&gt; 됩니다.&lt;/p&gt;
&lt;h4&gt;전송 계층별 차이&lt;/h4&gt;
&lt;p&gt;두 방식 모두 동일한 JSON-RPC 2.0 메시지를 사용하지만, &lt;strong&gt;메시지를 실어 나르는 통로&lt;/strong&gt;와 &lt;strong&gt;구분 방식(Framing)&lt;/strong&gt;이 다릅니다.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&quot;left&quot;&gt;구분&lt;/th&gt;
&lt;th align=&quot;left&quot;&gt;Stdio 방식&lt;/th&gt;
&lt;th align=&quot;left&quot;&gt;HTTP/SSE 방식&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;위치&lt;/strong&gt;&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;로컬 (같은 컴퓨터 내 프로세스)&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;원격 (네트워크)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;실행 방식&lt;/strong&gt;&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;에이전트가 서버를 자식 프로세스로 직접 실행&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;외부 서버 URL로 접속&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;메시지 구분자&lt;/strong&gt;&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;&lt;code&gt;\n&lt;/code&gt; (Newline) — JSON 한 줄로 직렬화&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;SSE 스펙 (&lt;code&gt;data:&lt;/code&gt; 접두사 등)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;속도&lt;/strong&gt;&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;매우 빠름&lt;/strong&gt; (네트워크 오버헤드 없음)&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;상대적으로 느림 (TCP/HTTP 핸드셰이크)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;주요 용도&lt;/strong&gt;&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;로컬 도구 (파일, 셸, DB 등)&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;원격 서비스, 클라우드 배포&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;pre&gt;&lt;code&gt;# Stdio wire 예시 — 개행(\n)으로 메시지 경계 구분
{&amp;quot;jsonrpc&amp;quot;:&amp;quot;2.0&amp;quot;,&amp;quot;id&amp;quot;:&amp;quot;1&amp;quot;,&amp;quot;method&amp;quot;:&amp;quot;tools/call&amp;quot;,&amp;quot;params&amp;quot;:{&amp;quot;name&amp;quot;:&amp;quot;adder&amp;quot;,&amp;quot;arguments&amp;quot;:{&amp;quot;a&amp;quot;:10,&amp;quot;b&amp;quot;:20}}}\n

# HTTP/SSE wire 예시 — SSE 규격으로 메시지 경계 구분
event: message
data: {&amp;quot;jsonrpc&amp;quot;:&amp;quot;2.0&amp;quot;,&amp;quot;id&amp;quot;:&amp;quot;1&amp;quot;,&amp;quot;method&amp;quot;:&amp;quot;tools/call&amp;quot;,&amp;quot;params&amp;quot;:{&amp;quot;name&amp;quot;:&amp;quot;adder&amp;quot;,&amp;quot;arguments&amp;quot;:{&amp;quot;a&amp;quot;:10,&amp;quot;b&amp;quot;:20}}}&lt;/code&gt;&lt;/pre&gt;&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;p&gt;&lt;strong&gt;요약&lt;/strong&gt;: &amp;quot;마샬링된 JSON-RPC 메시지를 보낸다&amp;quot;는 내용물은 동일합니다.&lt;br&gt;&lt;strong&gt;Stdio&lt;/strong&gt;는 옆 프로세스에 개행 구분 텍스트를 던지는 것이고,&lt;br&gt;&lt;strong&gt;HTTP&lt;/strong&gt;는 원격 서버에 SSE 규격 스트림으로 보내는 것입니다.&lt;br&gt;에이전트 코드 입장에서는 두 방식 모두 같은 &lt;code&gt;session.call_tool()&lt;/code&gt; 인터페이스로 투명하게 사용할 수 있습니다.&lt;/p&gt;
&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;이러한 표준 규격 덕분에 &lt;strong&gt;Python&lt;/strong&gt; 클라이언트와 &lt;strong&gt;Go&lt;/strong&gt; 또는 &lt;strong&gt;TypeScript&lt;/strong&gt;로 작성된 MCP 서버가 아무런 수정 없이 통신할 수 있습니다.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;5. 언제 무엇을 선택할까&lt;/h2&gt;
&lt;h3&gt;일반 Tool Calling이 적합한 경우&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;1~3개&lt;/strong&gt;의 간단한 내부 함수만 필요한 프로토타이핑&lt;/li&gt;
&lt;li&gt;단일 모델(예: OpenAI만)을 고정해서 사용하는 환경&lt;/li&gt;
&lt;li&gt;외부 서버 인프라를 운영하기 어려운 가벼운 스크립트&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;MCP가 적합한 경우&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;기업/팀 환경&lt;/strong&gt;에서 여러 외부 서비스(Slack, GitHub, Jira 등)를 연동할 때&lt;/li&gt;
&lt;li&gt;Claude, GPT, Gemini 등 &lt;strong&gt;여러 모델을 교체·비교&lt;/strong&gt;해야 하는 에이전트 플랫폼&lt;/li&gt;
&lt;li&gt;툴뿐 아니라 &lt;strong&gt;파일이나 DB 데이터&lt;/strong&gt;도 컨텍스트로 주입해야 하는 경우&lt;/li&gt;
&lt;li&gt;보안 경계가 필요한 환경 (툴 실행을 격리된 서버에서 처리)&lt;/li&gt;
&lt;li&gt;다수의 에이전트가 &lt;strong&gt;동일한 MCP 서버를 공유&lt;/strong&gt;해야 하는 마이크로서비스 구조&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;6. 참고 자료&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://modelcontextprotocol.io/specification/2025-11-25&quot;&gt;MCP 공식 스펙 (2025-11-25)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://martinfowler.com/articles/function-call-LLM.html&quot;&gt;Martin Fowler — Function Calls and LLMs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://huggingface.co/learn/mcp-course/en/unit1/architectural-components&quot;&gt;HuggingFace MCP Course — Architectural Components&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://workos.com/blog/how-mcp-servers-work&quot;&gt;WorkOS — How MCP Servers Work&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://mcpcat.io/guides/understanding-json-rpc-protocol-mcp/&quot;&gt;JSON-RPC 2.0 in MCP&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>devops</category>
      <category>Agent</category>
      <category>AI</category>
      <category>devops</category>
      <category>JSON-RPC</category>
      <category>llm</category>
      <category>MCP</category>
      <category>tool-calling</category>
      <author>디클냥</author>
      <guid isPermaLink="true">https://devopslog.tistory.com/222</guid>
      <comments>https://devopslog.tistory.com/222#entry222comment</comments>
      <pubDate>Tue, 10 Mar 2026 15:34:25 +0900</pubDate>
    </item>
    <item>
      <title>AI 에이전트(OpenClaw 등)의 LLM 인터페이스 구현 및 툴 콜링 기술 개요</title>
      <link>https://devopslog.tistory.com/221</link>
      <description>&lt;p&gt;OpenClaw, Claude 데스크톱 앱, 혹은 로컬 기반의 여러 AI 에이전트들은 내부적으로 LLM(대형 언어 모델)과 어떻게 소통하고, 로컬 환경의 도구(Tool)들을 사용할까요? 이 글에서는 에이전트가 LLM과 인터페이스를 맺는 기술적 구현 내용과 핵심 요소들을 살펴봅니다.&lt;/p&gt;
&lt;h2&gt;1. 지침 파일(&lt;code&gt;agent.md&lt;/code&gt; 등) 적용 방법&lt;/h2&gt;
&lt;p&gt;AI 에이전트의 페르소나, 역할, 기본 규칙을 정의하기 위해 주로 &lt;code&gt;.md&lt;/code&gt; 형태의 지침 파일을 사용합니다. (예: &lt;code&gt;agent.md&lt;/code&gt;, &lt;code&gt;system_prompt.txt&lt;/code&gt;, &lt;code&gt;SOUL.md&lt;/code&gt; 등)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;기술적 구현:&lt;/strong&gt;&lt;br&gt;이러한 지침 파일은 LLM에 전달되는 &lt;strong&gt;시스템 프롬프트(System Prompt)&lt;/strong&gt;로 로드됩니다. 에이전트 프로그램이 실행될 때 혹은 세션이 시작될 때 파일 시스템에서 문서를 읽어 LLM의 &lt;code&gt;system&lt;/code&gt; 역할(role) 메시지에 주입합니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;구현 샘플 (Python/가상코드):&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;def load_agent_instructions(filepath=&amp;quot;agent.md&amp;quot;):
    with open(filepath, &amp;quot;r&amp;quot;, encoding=&amp;quot;utf-8&amp;quot;) as f:
         return f.read()

# LLM API 호출 시
system_instruction = load_agent_instructions()
messages = [
    {&amp;quot;role&amp;quot;: &amp;quot;system&amp;quot;, &amp;quot;content&amp;quot;: system_instruction},
    {&amp;quot;role&amp;quot;: &amp;quot;user&amp;quot;, &amp;quot;content&amp;quot;: &amp;quot;오늘의 주요 시스템 로그를 요약해줘.&amp;quot;}
]
response = llm_client.chat.completions.create(
    model=&amp;quot;gpt-4o&amp;quot;,
    messages=messages
)&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;2. 스킬(&lt;code&gt;skills&lt;/code&gt;) 파일 적용 방법&lt;/h2&gt;
&lt;p&gt;단순한 지침을 넘어, 특정 작업(예: &amp;quot;웹 크롤링&amp;quot;, &amp;quot;데이터베이스 조회&amp;quot;)을 수행하기 위한 리소스나 스크립트 모음을 &lt;code&gt;skills&lt;/code&gt; 디렉토리로 구성할 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;기술적 구현:&lt;/strong&gt;&lt;br&gt;스킬 파일들은 로컬 시스템에 저장되어 있으며, 사용자의 요청이 들어올 때 일종의 RAG(Retrieval-Augmented Generation) 방식이나 직접 컨텍스트화되어 동적으로 프롬프트에 삽입됩니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;스킬 메타데이터 인덱싱&lt;/strong&gt;: 에이전트는 사용 가능한 스킬 목록과 설명을 미리 읽어 LLM에게 &amp;quot;너는 현재 이러한 스킬들을 알고 있다&amp;quot;고 프롬프트 상단에 알려줍니다. (프롬프트 주입)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;동적 파일 읽기&lt;/strong&gt;: LLM이 특정 스킬의 세부 내용이 필요하다고 판단하면, 로컬 파일 시스템을 읽는 툴(view_file 등)을 통해 해당 스킬의 &lt;code&gt;.md&lt;/code&gt;나 관련 스크립트 내용을 읽어들여 적용합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;3. 툴 콜링(Tool Calling)의 판단 및 실행 방법&lt;/h2&gt;
&lt;p&gt;에이전트 시스템에서 가장 중요한 부분은 &amp;quot;언제 외부 도구를 부를 것인가&amp;quot; 그리고 &amp;quot;어떻게 실행할 것인가&amp;quot;입니다.&lt;/p&gt;
&lt;h3&gt;3.1 Tool Calling 판단 방법&lt;/h3&gt;
&lt;p&gt;대부분의 현대적인 에이전트는 LLM 자체의 능력(Function Calling 기능)을 활용합니다. 개발자는 LLM API에 &lt;strong&gt;가용한 툴의 명세서(Schema)&lt;/strong&gt;를 JSON 형태로 설명(Description), 파라미터(Parameters) 등과 함께 전달합니다.&lt;br&gt;LLM은 사용자의 요청을 분석하다가 자신의 내부 지식만으로 답변할 수 없는 작업(예: 로컬 파일 검색, 터미널 명령 실행, 웹 크롤링 등)이라 판단하면, 일반 텍스트 답변이 아닌 &lt;strong&gt;Tool Call 객체&lt;/strong&gt;를 반환합니다.&lt;/p&gt;
&lt;h3&gt;3.2 Tool 호출 및 실행 흐름&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Tool 정의 전달&lt;/strong&gt;: 에이전트 시스템이 LLM에 툴 스키마(이름, 설명, 파라미터 타입)를 전달.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;LLM의 판단 (Tool Call 반환)&lt;/strong&gt;: LLM이 툴 호출에 필요한 인자(Arguments)를 채워 &lt;code&gt;tool_calls&lt;/code&gt; 객체로 시스템에 반환.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;도구 실행 (시스템/로컬 환경)&lt;/strong&gt;: 에이전트 시스템이 해당 응답을 파싱하여, 실제 로컬 환경에서 지정된 함수나 쉘 명령어를 단독으로 실행합니다. (이때 사용자의 승인을 받거나, 샌드박스 환경에서 실행하여 보안을 확보합니다.)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;결과 반환&lt;/strong&gt;: 명령어나 함수의 실행 결과(stdout, stderr, 혹은 오류 메시지)를 확보하여 다시 LLM 시스템으로 전달되는 메시지 목록에 추가합니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;최종 응답 생성&lt;/strong&gt;: LLM이 해당 결과를 읽고 분석하여 사용자에게 최종적으로 유의미한 텍스트 결과를 보고합니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;구현 샘플 (툴 실행 주기):&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;import json
import subprocess

# 1. Tool 정의
tools = [
    {
        &amp;quot;type&amp;quot;: &amp;quot;function&amp;quot;,
        &amp;quot;function&amp;quot;: {
            &amp;quot;name&amp;quot;: &amp;quot;run_shell_command&amp;quot;,
            &amp;quot;description&amp;quot;: &amp;quot;운영체제 쉘 명령어를 실행합니다.&amp;quot;,
            &amp;quot;parameters&amp;quot;: {
                &amp;quot;type&amp;quot;: &amp;quot;object&amp;quot;,
                &amp;quot;properties&amp;quot;: {
                    &amp;quot;command&amp;quot;: {
                        &amp;quot;type&amp;quot;: &amp;quot;string&amp;quot;,
                        &amp;quot;description&amp;quot;: &amp;quot;실행할 터미널 커맨드&amp;quot;
                    }
                },
                &amp;quot;required&amp;quot;: [&amp;quot;command&amp;quot;]
            }
        }
    }
]

# 2. LLM 호출 및 판단
response = llm_client.chat.completions.create(
    model=&amp;quot;gpt-4o&amp;quot;,
    messages=messages,
    tools=tools
)

# 3. LLM이 Tool Call을 요구한 경우
if response.choices[0].message.tool_calls:
    for tool_call in response.choices[0].message.tool_calls:
        if tool_call.function.name == &amp;quot;run_shell_command&amp;quot;:
            # 전달받은 파라미터 파싱
            args = json.loads(tool_call.function.arguments)
            cmd = args[&amp;quot;command&amp;quot;]

            # 4. 로컬 도구 실제 실행
            result = subprocess.run(cmd, shell=True, capture_output=True, text=True)
            output = result.stdout if result.returncode == 0 else result.stderr

            # 5. 결과를 다시 메시지 히스토리에 추가하여 LLM 재호출
            messages.append(response.choices[0].message) # 어시스턴트의 Tool Call 기록을 추가
            messages.append({
                &amp;quot;role&amp;quot;: &amp;quot;tool&amp;quot;,
                &amp;quot;tool_call_id&amp;quot;: tool_call.id,
                &amp;quot;content&amp;quot;: output
            })

            final_response = llm_client.chat.completions.create(
                model=&amp;quot;gpt-4o&amp;quot;,
                messages=messages
            )
            print(final_response.choices[0].message.content)&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;마무리&lt;/h2&gt;
&lt;p&gt;OpenClaw나 다양한 코딩 에이전트는 결론적으로 &lt;strong&gt;LLM의 Function Calling 메커니즘&lt;/strong&gt;과 &lt;strong&gt;로컬 시스템 간의 인터페이스 다리(Bridge)&lt;/strong&gt; 역할을 합니다. 단편적인 프롬프팅 기술을 넘어서, &lt;code&gt;agent.md&lt;/code&gt;로 기본 캐릭터와 지침을 설정하고, 구조화된 &lt;code&gt;skills&lt;/code&gt; 파일로 전문 기능 영역을 확장하며, 동적인 툴 콜링(Tool Calling) 방식을 통해 물리적인 시스템 자원을 자유롭고 유연하게 제어하는 것이 최신 독립형 AI 에이전트 아키텍처의 핵심입니다.&lt;/p&gt;</description>
      <category>devops</category>
      <category>Agent</category>
      <category>AI</category>
      <category>devops</category>
      <category>llm</category>
      <category>openclaw</category>
      <category>tool-calling</category>
      <author>디클냥</author>
      <guid isPermaLink="true">https://devopslog.tistory.com/221</guid>
      <comments>https://devopslog.tistory.com/221#entry221comment</comments>
      <pubDate>Tue, 10 Mar 2026 15:34:02 +0900</pubDate>
    </item>
    <item>
      <title>OpenClaw 용어집 및 운영 지침 가이드</title>
      <link>https://devopslog.tistory.com/220</link>
      <description>&lt;p&gt;OpenClaw(ClawdBot 기반)는 개인 AI 에이전트를 메시징 채널과 연결해 운영하는 게이트웨이 중심 프레임워크입니다. 이 문서는 용어를 사람 친화적으로 정리하고, 운영 시 바로 적용할 수 있는 체크리스트와 최신 변경 사항(공식 소스 기준)까지 함께 제공합니다.&lt;/p&gt;
&lt;h2&gt;개요&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;문서 목적: 용어 설명 + 운영 지침 통합 가이드&lt;/li&gt;
&lt;li&gt;최신 정보 범위: 공식 문서와 공식 릴리스만 사용&lt;/li&gt;
&lt;li&gt;최신 반영 기준:&lt;ul&gt;
&lt;li&gt;GitHub Release &lt;code&gt;v2026.2.15&lt;/code&gt; (게시일: &lt;strong&gt;2026-02-16&lt;/strong&gt;)&lt;/li&gt;
&lt;li&gt;docs.openclaw.ai의 공식 업데이트 문서&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;핵심 개념 (단순 설명)&lt;/h2&gt;
&lt;h3&gt;Gateway (게이트웨이)&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;모든 메신저(WhatsApp, Telegram, Discord 등)와 에이전트를 연결해 주는 중앙 서버/데몬.&lt;/li&gt;
&lt;li&gt;기본 포트: &lt;code&gt;18789&lt;/code&gt; (WebSocket).&lt;/li&gt;
&lt;li&gt;한 개의 Gateway로 여러 채널과 여러 에이전트를 동시에 관리 가능.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Agent (에이전트)&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;AI 어시스턴트의 &amp;quot;뇌&amp;quot;에 해당.&lt;/li&gt;
&lt;li&gt;개별 성격, 메모리, 행동 방식을 가짐.&lt;/li&gt;
&lt;li&gt;각 Agent는 격리된 상태(&lt;code&gt;workspace&lt;/code&gt;, &lt;code&gt;auth&lt;/code&gt;, &lt;code&gt;sessions&lt;/code&gt;)를 유지.&lt;/li&gt;
&lt;li&gt;기본 에이전트 이름: &lt;code&gt;main&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Workspace (작업 폴더)&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Agent의 &amp;quot;개인 폴더&amp;quot;로, 기본 경로: &lt;code&gt;~/.openclaw/workspace&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;주요 파일:&lt;ul&gt;
&lt;li&gt;&lt;code&gt;AGENTS.md&lt;/code&gt;: 동작 지시, 규칙, 메모리.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;SOUL.md&lt;/code&gt;: 성격, 말투, 경계.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;USER.md&lt;/code&gt;: 사용자 정보와 호칭.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;TOOLS.md&lt;/code&gt;: 사용 가능한 도구/툴 설명.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;BOOTSTRAP.md&lt;/code&gt;: 최초 실행 설정(한 번 실행 후 삭제).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;memory/YYYY-MM-DD.md&lt;/code&gt;: 일일 메모리 로그.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Agent Directory (&lt;code&gt;agentDir&lt;/code&gt;)&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;에이전트의 기술 설정/인증 정보를 저장.&lt;/li&gt;
&lt;li&gt;기본 경로: &lt;code&gt;~/.openclaw/agents/&amp;lt;agentId&amp;gt;/agent&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;주요 파일:&lt;ul&gt;
&lt;li&gt;&lt;code&gt;auth-profiles.json&lt;/code&gt;: 모델 제공자(Anthropic, OpenAI 등) 인증 정보.&lt;/li&gt;
&lt;li&gt;에이전트별 모델 설정/구조 파일.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;통신 구조&lt;/h2&gt;
&lt;h3&gt;Channel (채널)&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;메신저 연결 단위.&lt;/li&gt;
&lt;li&gt;예: WhatsApp, Telegram, Discord 각각 하나의 관(pipe).&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Account ID (&lt;code&gt;accountId&lt;/code&gt;)&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;같은 채널 내 여러 계정을 구분.&lt;/li&gt;
&lt;li&gt;예: 개인 WhatsApp, 업무용 WhatsApp.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Session Key (&lt;code&gt;sessionKey&lt;/code&gt;)&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;대화 스레드를 구분하는 고유 이름/주소.&lt;/li&gt;
&lt;li&gt;예:&lt;ul&gt;
&lt;li&gt;&lt;code&gt;agent:main:main&lt;/code&gt; (기본 1:1 대화)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;agent:main:telegram:group:123&lt;/code&gt; (그룹 대화)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Session ID (&lt;code&gt;sessionId&lt;/code&gt;)&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;실제 대화 기록 파일 ID.&lt;/li&gt;
&lt;li&gt;경로 예: &lt;code&gt;~/.openclaw/agents/&amp;lt;agentId&amp;gt;/sessions/&amp;lt;sessionId&amp;gt;.jsonl&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;세션 재설정 시 값이 바뀜.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Binding (바인딩)&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;라우팅 규칙.&lt;/li&gt;
&lt;li&gt;어떤 채널/계정/연락처에서 온 메시지를 어떤 Agent로 보낼지 결정.&lt;/li&gt;
&lt;li&gt;가장 구체적인 규칙이 우선 적용.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;세션 관리&lt;/h2&gt;
&lt;h3&gt;Main Session (기본 대화)&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;기본 1:1 대화 세션.&lt;/li&gt;
&lt;li&gt;예: &lt;code&gt;agent:&amp;lt;agentId&amp;gt;:main&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;모든 개인 대화를 한 세션으로 모아 유지할 수 있음.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;DM Scope (&lt;code&gt;dmScope&lt;/code&gt;)&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;DM(1:1) 분리 수준 설정.&lt;ul&gt;
&lt;li&gt;&lt;code&gt;main&lt;/code&gt;: 모든 DM 공유&lt;/li&gt;
&lt;li&gt;&lt;code&gt;per-peer&lt;/code&gt;: 사용자별 분리&lt;/li&gt;
&lt;li&gt;&lt;code&gt;per-channel-peer&lt;/code&gt;: 채널+사용자별 분리&lt;/li&gt;
&lt;li&gt;&lt;code&gt;per-account-channel-peer&lt;/code&gt;: 계정+채널+사용자별 최대 분리&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Session Reset (초기화)&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;새 대화를 시작할 때 &lt;code&gt;sessionId&lt;/code&gt;를 새로 생성.&lt;/li&gt;
&lt;li&gt;방법:&lt;ul&gt;
&lt;li&gt;수동: &lt;code&gt;openclaw new&lt;/code&gt;, &lt;code&gt;openclaw reset&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;자동: 지정 시각(예: 매일 04:00), 비활성 시간 기준 자동 리셋&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Compaction (압축/요약)&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;긴 대화를 요약해 컨텍스트 한도 초과를 방지.&lt;/li&gt;
&lt;li&gt;핵심 맥락은 남기고 오래된 상세를 정리.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Memory Flush (메모리 저장)&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Compaction 전에 중요한 정보를 영구 메모리로 기록.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;memory/YYYY-MM-DD.md&lt;/code&gt;에 저장.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;NO_REPLY&lt;/code&gt; 내부 메시지로 사용자 노출 없이 처리 가능.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;접근 제어 / 보안&lt;/h2&gt;
&lt;h3&gt;Pairing (페어링)&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;새 노드(장치) 연결 시 승인 절차.&lt;/li&gt;
&lt;li&gt;로컬(&lt;code&gt;127.0.0.1&lt;/code&gt;)은 자동 승인 옵션 가능.&lt;/li&gt;
&lt;li&gt;승인 후 토큰 발급으로 접근 허용.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;DM Policy (&lt;code&gt;dmPolicy&lt;/code&gt;)&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;DM 허용 범위 제어.&lt;ul&gt;
&lt;li&gt;&lt;code&gt;open&lt;/code&gt;: 누구나 가능(위험)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;pairing&lt;/code&gt;: 승인 사용자만&lt;/li&gt;
&lt;li&gt;&lt;code&gt;allowlist&lt;/code&gt;: 허용 목록만&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Allow From (&lt;code&gt;allowFrom&lt;/code&gt;)&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;허용 번호/ID 목록.&lt;/li&gt;
&lt;li&gt;예: &lt;code&gt;+15555550123&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Group Policy (&lt;code&gt;groupPolicy&lt;/code&gt;)&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;그룹 참여 범위 제어.&lt;ul&gt;
&lt;li&gt;&lt;code&gt;open&lt;/code&gt;: 모든 그룹(권장하지 않음)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;allowlist&lt;/code&gt;: 허용 그룹만&lt;/li&gt;
&lt;li&gt;&lt;code&gt;denylist&lt;/code&gt;: 차단 목록 제외&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Require Mention&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;그룹에서 &lt;code&gt;@멘션&lt;/code&gt;이 있을 때만 응답.&lt;/li&gt;
&lt;li&gt;불필요 응답/스팸 방지에 유효.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Gateway Token (&lt;code&gt;OPENCLAW_GATEWAY_TOKEN&lt;/code&gt;)&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Gateway 접속용 공유 비밀.&lt;/li&gt;
&lt;li&gt;WebSocket 인증에 사용.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Sandbox (샌드박스)&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;도구 실행 격리(도커 기반).&lt;/li&gt;
&lt;li&gt;모드:&lt;ul&gt;
&lt;li&gt;&lt;code&gt;off&lt;/code&gt;: 비격리(전체 시스템 접근)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;non-main&lt;/code&gt;: 메인 세션만 비격리&lt;/li&gt;
&lt;li&gt;&lt;code&gt;all&lt;/code&gt;: 모든 세션 격리&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;스코프: &lt;code&gt;session&lt;/code&gt;, &lt;code&gt;agent&lt;/code&gt;, &lt;code&gt;shared&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;p&gt;주의&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;bind: 0.0.0.0&lt;/code&gt; + 약한 인증은 외부 노출 위험이 큼.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;dmPolicy: open&lt;/code&gt;, &lt;code&gt;groupPolicy: open&lt;/code&gt;은 운영 초기 기본값으로 쓰지 않는 것을 권장.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;sandbox: off&lt;/code&gt;는 편의성은 높지만, 도구 실행 리스크가 가장 큼.&lt;/li&gt;
&lt;/ul&gt;
&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;h2&gt;노드 / 클라이언트&lt;/h2&gt;
&lt;h3&gt;Node (노드)&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;원격 장치(휴대폰/태블릿/PC)가 Gateway에 연결한 실행 주체.&lt;/li&gt;
&lt;li&gt;연결 역할: &lt;code&gt;role: &amp;quot;node&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;기능 예:&lt;ul&gt;
&lt;li&gt;&lt;code&gt;canvas.*&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;camera.*&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;screen.record&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;location.get&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Client (클라이언트)&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Gateway를 조작/관리하는 앱.&lt;/li&gt;
&lt;li&gt;예: macOS 앱, CLI, 웹 UI.&lt;/li&gt;
&lt;li&gt;메시지 발송, 설정 변경, 세션 점검 가능.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Control UI (제어 UI)&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;접속: &lt;code&gt;http://127.0.0.1:18789/&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;채팅 기록, 구성, 세션, 노드 상태를 확인/수정.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Canvas&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Agent가 인터랙티브 UI를 생성하는 렌더링 영역.&lt;/li&gt;
&lt;li&gt;기본 포트: &lt;code&gt;18793&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;버튼/폼/편집 UI를 클라이언트에 표시.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;툴 / 기능&lt;/h2&gt;
&lt;h3&gt;Tool (툴)&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Agent가 실행 가능한 기능 단위.&lt;/li&gt;
&lt;li&gt;예: &lt;code&gt;exec&lt;/code&gt;, &lt;code&gt;read&lt;/code&gt;, &lt;code&gt;write&lt;/code&gt;, &lt;code&gt;browser&lt;/code&gt;, &lt;code&gt;canvas&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;에이전트별 허용/차단 정책 적용 가능.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Skill (스킬)&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;사용자 정의 스크립트/프로그램.&lt;/li&gt;
&lt;li&gt;경로:&lt;ul&gt;
&lt;li&gt;&lt;code&gt;~/.openclaw/skills/&lt;/code&gt; (공유)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;workspace&amp;gt;/skills/&lt;/code&gt; (에이전트별)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;RPC (Remote Procedure Call)&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Gateway 내부 요소 간 호출 프로토콜.&lt;/li&gt;
&lt;li&gt;도구 실행, 에이전트 호출, 상태 조회에 사용.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Plugin (플러그인)&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;채널/도구/CLI 명령/Gateway 메서드 확장 모듈.&lt;/li&gt;
&lt;li&gt;설치 예: &lt;code&gt;openclaw plugins install @openclaw/plugin-name&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;설정 / 인증&lt;/h2&gt;
&lt;h3&gt;&lt;code&gt;openclaw.json&lt;/code&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Gateway 메인 설정 파일.&lt;/li&gt;
&lt;li&gt;기본 경로: &lt;code&gt;~/.openclaw/openclaw.json&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;CLI/웹 UI에서 수정 가능.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Hot Reload&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;재시작 없이 설정 반영.&lt;ul&gt;
&lt;li&gt;즉시 반영: 대부분 설정&lt;/li&gt;
&lt;li&gt;다음 메시지부터 반영: 세션/라우팅 계열&lt;/li&gt;
&lt;li&gt;재시작 필요: 네트워크 바인딩/구조 변경&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;환경 변수&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;비밀 값(API 키, 토큰) 분리 저장.&lt;/li&gt;
&lt;li&gt;예: &lt;code&gt;TELEGRAM_BOT_TOKEN&lt;/code&gt;, &lt;code&gt;ANTHROPIC_API_KEY&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Auth Profile&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;모델 제공자 인증 정보.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;auth-profiles.json&lt;/code&gt;에 저장.&lt;/li&gt;
&lt;li&gt;API 키/OAuth 사용 가능.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Model Provider / Model Ref&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;models.providers&lt;/code&gt;에 제공자 정의.&lt;/li&gt;
&lt;li&gt;모델 참조 형식: &lt;code&gt;provider/model&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;예: &lt;code&gt;anthropic/claude-sonnet-4-5&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;운영 체크리스트&lt;/h2&gt;
&lt;h3&gt;기본 보안 권장값&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;dmPolicy&lt;/code&gt;: &lt;code&gt;pairing&lt;/code&gt; 또는 &lt;code&gt;allowlist&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;groupPolicy&lt;/code&gt;: &lt;code&gt;allowlist&lt;/code&gt; 우선&lt;/li&gt;
&lt;li&gt;&lt;code&gt;requireMention&lt;/code&gt;: 그룹에서 &lt;code&gt;true&lt;/code&gt; 권장&lt;/li&gt;
&lt;li&gt;&lt;code&gt;OPENCLAW_GATEWAY_TOKEN&lt;/code&gt;: 평문 공유 금지, 정기 교체&lt;/li&gt;
&lt;li&gt;외부 바인딩 필요 시 방화벽/IP ACL 동시 적용&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;세션 운영 시나리오&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;정기 리셋: 하루 1회 또는 업무 단위 종료 시 &lt;code&gt;sessionId&lt;/code&gt; 회전&lt;/li&gt;
&lt;li&gt;Compaction 기준: 토큰 한도 60~70% 접근 시 선제 요약&lt;/li&gt;
&lt;li&gt;Memory Flush: 운영 정책/사용자 선호/중요 결정사항만 저장&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;장애 대응 최소 순서&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;health&lt;/code&gt; 상태 확인(게이트웨이 응답 여부)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;openclaw doctor&lt;/code&gt; 실행(권한/설정/네트워크 점검)&lt;/li&gt;
&lt;li&gt;Gateway 로그 확인(토큰 인증 실패/채널 연결 실패/툴 실행 오류)&lt;/li&gt;
&lt;li&gt;채널별 바인딩 규칙 재검토&lt;/li&gt;
&lt;li&gt;필요 시 마지막 정상 구성으로 롤백&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;최신 변경 요약 (공식 소스 기준)&lt;/h2&gt;
&lt;p&gt;기준 시점: &lt;strong&gt;2026-02-17&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;항목명&lt;/strong&gt;: Release &lt;code&gt;v2026.2.15&lt;/code&gt; (게시일: &lt;strong&gt;2026-02-16&lt;/strong&gt;)&lt;br&gt;&lt;strong&gt;변경 내용&lt;/strong&gt;: RPC semantics 개선, macOS 앱 안정성 강화, hooks/commands 개선, 테스트 회귀 수정&lt;br&gt;&lt;strong&gt;운영 영향&lt;/strong&gt;: 노드/클라이언트 연동 시 예외 케이스 감소, 채널 연결 안정성 향상 기대&lt;br&gt;&lt;strong&gt;적용 시 주의점&lt;/strong&gt;: 커스텀 훅/플러그인 사용 시 이벤트 처리 순서/에러 핸들링 회귀 테스트 필요&lt;br&gt;&lt;strong&gt;출처&lt;/strong&gt;: &lt;a href=&quot;https://github.com/moltbot/moltbot/releases/tag/v2026.2.15&quot;&gt;https://github.com/moltbot/moltbot/releases/tag/v2026.2.15&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;항목명&lt;/strong&gt;: 공식 업데이트 문서(업데이트 작성일: &lt;strong&gt;2026-02-17&lt;/strong&gt;)&lt;br&gt;&lt;strong&gt;변경 내용&lt;/strong&gt;: 상위 경로 변경(&lt;code&gt;~/.claude&lt;/code&gt; -&amp;gt; &lt;code&gt;~/.openclaw&lt;/code&gt;), 명령어 변경(&lt;code&gt;molt&lt;/code&gt; -&amp;gt; &lt;code&gt;openclaw&lt;/code&gt;), 앱 리브랜딩 반영&lt;br&gt;&lt;strong&gt;운영 영향&lt;/strong&gt;: 기존 운영 스크립트/문서/자동화 파이프라인의 경로/명령어 수정 필요&lt;br&gt;&lt;strong&gt;적용 시 주의점&lt;/strong&gt;: 백업/배포 스크립트, systemd/launchd, CI 문서에서 구 경로/구 명령어 잔존 여부 점검&lt;br&gt;&lt;strong&gt;출처&lt;/strong&gt;: &lt;a href=&quot;https://docs.openclaw.ai/updating&quot;&gt;https://docs.openclaw.ai/updating&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;전반 흐름 요약&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;로컬/클라우드에 OpenClaw 설치&lt;/li&gt;
&lt;li&gt;Gateway 데몬 실행&lt;/li&gt;
&lt;li&gt;WhatsApp/Telegram/Discord 등 채널 연결&lt;/li&gt;
&lt;li&gt;사용자 메시지가 Gateway로 유입&lt;/li&gt;
&lt;li&gt;Binding 규칙으로 대상 Agent 라우팅&lt;/li&gt;
&lt;li&gt;Agent가 &lt;code&gt;SOUL.md&lt;/code&gt;, &lt;code&gt;USER.md&lt;/code&gt;, &lt;code&gt;memory/*.md&lt;/code&gt;를 읽고 컨텍스트 구성&lt;/li&gt;
&lt;li&gt;모델 호출 및 필요 시 툴 실행&lt;/li&gt;
&lt;li&gt;결과를 채널로 반환&lt;/li&gt;
&lt;li&gt;히스토리 저장/메모리 업데이트/Compaction 수행&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;참고 링크&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;OpenClaw 공식 문서: &lt;a href=&quot;https://docs.openclaw.ai/&quot;&gt;https://docs.openclaw.ai/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;OpenClaw 업데이트 가이드: &lt;a href=&quot;https://docs.openclaw.ai/updating&quot;&gt;https://docs.openclaw.ai/updating&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;OpenClaw 릴리스 목록: &lt;a href=&quot;https://github.com/moltbot/moltbot/releases&quot;&gt;https://github.com/moltbot/moltbot/releases&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;v2026.2.15&lt;/code&gt; 릴리스: &lt;a href=&quot;https://github.com/moltbot/moltbot/releases/tag/v2026.2.15&quot;&gt;https://github.com/moltbot/moltbot/releases/tag/v2026.2.15&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>devops</category>
      <category>Agent</category>
      <category>Clawdbot</category>
      <category>devops</category>
      <category>Gateway</category>
      <category>openclaw</category>
      <category>Operations</category>
      <category>Security</category>
      <category>용어집</category>
      <category>운영 지침</category>
      <author>디클냥</author>
      <guid isPermaLink="true">https://devopslog.tistory.com/220</guid>
      <comments>https://devopslog.tistory.com/220#entry220comment</comments>
      <pubDate>Tue, 10 Mar 2026 15:33:47 +0900</pubDate>
    </item>
    <item>
      <title>127.0.0.1 vs localhost: 차이와 함정</title>
      <link>https://devopslog.tistory.com/218</link>
      <description>&lt;p&gt;작성일: 2026-02-08&lt;/p&gt;
&lt;p&gt;운영 환경에서 &amp;quot;localhost로 붙었는데 왜 안 되지?&amp;quot; 같은 문제는 자주 발생합니다. 결론부터 말하면 &lt;code&gt;127.0.0.1&lt;/code&gt;과 &lt;code&gt;localhost&lt;/code&gt;는 보통 같은 의미로 쓰이지만, &lt;strong&gt;항상 동일하게 해석되진 않습니다.&lt;/strong&gt; 이 미묘한 차이가 헬스체크 실패, 접근 불가, 보안 정책 충돌로 이어질 수 있습니다.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;1. 루프백(Loopback) 정의&lt;/h2&gt;
&lt;p&gt;루프백은 &lt;strong&gt;자기 자신에게 되돌아오는 네트워크 경로&lt;/strong&gt;입니다. 물리 NIC 없이도 TCP/IP 스택을 테스트하거나 로컬 프로세스 간 통신을 가능하게 합니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;IPv4 루프백 대역: &lt;code&gt;127.0.0.0/8&lt;/code&gt; (대표 주소가 &lt;code&gt;127.0.0.1&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;IPv6 루프백 주소: &lt;code&gt;::1&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;즉, &lt;code&gt;127.0.0.1&lt;/code&gt;은 &lt;strong&gt;항상 이 머신 자신&lt;/strong&gt;을 의미합니다. DNS나 이름 해석 과정과는 무관합니다.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;2. &lt;code&gt;localhost&lt;/code&gt;는 이름이고, &lt;code&gt;127.0.0.1&lt;/code&gt;은 주소다&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;localhost&lt;/code&gt;는 &lt;strong&gt;호스트명&lt;/strong&gt;입니다. 따라서 실제 연결 주소는 &lt;strong&gt;어떻게 resolve되느냐&lt;/strong&gt;에 따라 달라집니다. 일반적으로는 &lt;code&gt;/etc/hosts&lt;/code&gt;나 로컬 DNS에서 다음과 같이 매핑됩니다.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;127.0.0.1   localhost
::1         localhost&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;하지만 이 순서와 우선순위는 OS, 설정, 애플리케이션 스택에 따라 달라질 수 있습니다.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;3. &lt;code&gt;localhost&lt;/code&gt;가 다르게 해석(resolve)될 수 있는 여지&lt;/h2&gt;
&lt;h3&gt;3.1 IPv6 우선 정책&lt;/h3&gt;
&lt;p&gt;많은 시스템은 &lt;code&gt;localhost&lt;/code&gt;를 먼저 &lt;code&gt;::1&lt;/code&gt;로 해석합니다. 이때 애플리케이션이 IPv6로 리슨하지 않으면:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;localhost&lt;/code&gt; 접속 실패&lt;/li&gt;
&lt;li&gt;&lt;code&gt;127.0.0.1&lt;/code&gt;로는 정상 연결&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;즉, &lt;strong&gt;동일한 서비스인데 주소에 따라 실패/성공이 갈릴 수 있습니다.&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;3.2 &lt;code&gt;/etc/hosts&lt;/code&gt; 설정 문제&lt;/h3&gt;
&lt;p&gt;이미지 빌드나 보안 정책 때문에 &lt;code&gt;localhost&lt;/code&gt; 매핑이 누락될 수 있습니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;localhost&lt;/code&gt;가 DNS로 넘어가며 외부로 resolve될 가능성&lt;/li&gt;
&lt;li&gt;특정 환경에서는 &lt;code&gt;localhost&lt;/code&gt;가 전혀 해석되지 않는 케이스도 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;3.3 컨테이너/네임스페이스 격리&lt;/h3&gt;
&lt;p&gt;컨테이너 내부에서 &lt;code&gt;localhost&lt;/code&gt;는 &lt;strong&gt;컨테이너 자신&lt;/strong&gt;입니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;호스트 머신을 가리키지 않음&lt;/li&gt;
&lt;li&gt;같은 호스트라도 컨테이너 간 &lt;code&gt;localhost&lt;/code&gt;는 서로 다름&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;그래서 Docker 환경에서는 호스트 접근을 위해 &lt;code&gt;host.docker.internal&lt;/code&gt; 같은 별도 이름을 사용합니다.&lt;/p&gt;
&lt;h3&gt;3.4 Kubernetes / Pod 단위 격리&lt;/h3&gt;
&lt;p&gt;Kubernetes Pod에서도 &lt;code&gt;localhost&lt;/code&gt;는 &lt;strong&gt;Pod 내부의 네임스페이스를 의미&lt;/strong&gt;합니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Pod 내부 프로세스끼리는 &lt;code&gt;localhost&lt;/code&gt;로 통신 가능&lt;/li&gt;
&lt;li&gt;다른 Pod나 서비스는 &lt;code&gt;localhost&lt;/code&gt;로 접근 불가&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;4. DevOps에서 자주 발생하는 실수&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;헬스체크가 &lt;code&gt;localhost&lt;/code&gt;를 사용하고, 실제 서비스는 IPv6 리슨이 없어 실패&lt;/li&gt;
&lt;li&gt;보안 정책이 IPv4만 허용하는데 &lt;code&gt;localhost&lt;/code&gt;가 IPv6로 resolve되어 차단&lt;/li&gt;
&lt;li&gt;컨테이너/Pod 격리로 인해 &lt;code&gt;localhost&lt;/code&gt;가 잘못된 대상에 연결됨&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;5. 실무 팁&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;IPv4만 쓰는 서비스라면 &lt;strong&gt;&lt;code&gt;127.0.0.1&lt;/code&gt;로 명시&lt;/strong&gt;하는 것이 안전합니다.&lt;/li&gt;
&lt;li&gt;IPv6 지원이 필요하다면 &lt;strong&gt;&lt;code&gt;::1&lt;/code&gt; 리슨을 활성화하거나 듀얼스택을 고려&lt;/strong&gt;합니다.&lt;/li&gt;
&lt;li&gt;컨테이너 환경에서는 &lt;strong&gt;&lt;code&gt;localhost&lt;/code&gt;가 “컨테이너 자신”이라는 전제&lt;/strong&gt;를 팀 내에서 공유합니다.&lt;/li&gt;
&lt;li&gt;배포 이미지에서 &lt;code&gt;/etc/hosts&lt;/code&gt;와 resolve 우선순위를 검증하는 체크리스트를 갖습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;정리&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;127.0.0.1&lt;/code&gt;은 주소이고, &lt;strong&gt;항상 이 머신 자신&lt;/strong&gt;을 뜻합니다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;localhost&lt;/code&gt;는 이름이라서 &lt;strong&gt;환경에 따라 다른 주소로 해석될 수 있습니다.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;DevOps에서는 이 차이가 장애와 직결되므로, 명확한 주소 사용과 환경 검증이 중요합니다.&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>devops</category>
      <category>containers</category>
      <category>devops</category>
      <category>dns</category>
      <category>IPv4</category>
      <category>IPv6</category>
      <category>kubernetes</category>
      <category>localhost</category>
      <category>loopback</category>
      <category>Networking</category>
      <author>디클냥</author>
      <guid isPermaLink="true">https://devopslog.tistory.com/218</guid>
      <comments>https://devopslog.tistory.com/218#entry218comment</comments>
      <pubDate>Tue, 10 Mar 2026 15:33:23 +0900</pubDate>
    </item>
  </channel>
</rss>