본문으로 건너뛰기

© 2026 Molayo

Dev.to헤드라인2026. 05. 26. 13:19

터미널 AI 에이전트 구축 (v46)

요약

로컬 LLM을 활용하여 터미널에서 직접 작동하는 AI 에이전트를 구축하는 실전 가이드입니다. Ollama를 이용한 API 설정부터 Python을 활용한 기본적인 CLI 에이전트 구현 방법까지 단계별로 설명합니다.

핵심 포인트

  • Aider, Continue.dev 등 주요 CLI AI 도구 비교
  • Ollama를 활용한 로컬 LLM API 서버 구축 방법
  • Python을 이용한 커스텀 CLI 에이전트 구현 실습

터미널 AI 에이전트 구축 (v46)

터미널에서 직접 작동하는 AI 에이전트를 구축해보는 실전 가이드입니다. 이 가이드는 로컬에서 작동하는 LLM을 활용한 개발자용 AI 에이전트를 구축하고 최적화하는 방법을 실습 중심으로 설명합니다.

1. CLI AI 에이전트 생태계

현재 CLI AI 에이전트 시장은 다음과 같은 주요 도구들로 구성되어 있습니다:

주요 도구 비교:

# Aider - 최신 인기 도구
# pip install aider
# aider --help

# Continue.dev - VSCode 확장이지만 CLI 지원
# npm install -g @continue-dev/cli

# OpenCode - 코드 생성 전용
# pip install opencode

현실적인 선택지: 로컬에서 작동하는 자체 에이전트가 가장 안정적입니다. 특히 회사 내부에서 사용할 경우.

2. 로컬 LLM API 엔드포인트 설정

로컬 LLM을 CLI에서 사용하기 위해 API 서버를 설정합니다:

# Ollama 설치 (가장 쉬운 방법)
curl -fsSL https://ollama.com/install.sh | sh

# 모델 다운로드
ollama pull llama3
ollama pull codellama:7b

# API 서버 시작
ollama serve
# 기본 포트: 11434

# 테스트
curl http://localhost:11434/api/generate -d '{
  "model": "llama3",
  "prompt": "Hello, how are you?",
  "stream": false
}'

3. 간단한 Python CLI 에이전트 구축

기본적인 CLI 에이전트를 만들어보겠습니다:

# agent.py
import json
import requests
import sys
from typing import Dict, List

class LocalAI:
    def __init__(self, base_url="http://localhost:11434"):
        self.base_url = base_url

    def chat(self, messages: List[Dict], model="llama3", temperature=0.7):
        """기본 채팅 API 호출"""
        payload = {
            "model": model,
            "messages": messages,
            "temperature": temperature,
            "stream": False
        }

        response = requests.post(
            f"{self.base_url}/api/chat",
            json=payload,
            timeout=30
        )

        if response.status_code == 200:
            return response.json()['message']['content']
        else:
            raise Exception(f"API Error: {response.text}")

def main():
    if len(sys.argv) < 2:
        print("사용법: python agent.py <질문>")
        return

    question = " ".join(sys.argv[1:])

    ai = LocalAI()
    messages = [
        {"role": "system", "content": "You are a helpful coding assistant. Respond in concise markdown."},
        {"role": "user", "content": question}
    ]

    try:
        response = ai.chat(messages)
        print(response)
    except Exception as e:
        print(f"에러 발생: {e}")

if __name__ == "__main__":
    main()

실행 방법:

python agent.py "Python으로 factorial 함수를 작성해주세요"

4. tmux와 통합

터미널을 분할해서 사용할 수 있도록 tmux 통합:

# tmux_agent.py
import subprocess
import os
import time
import json

class TmuxAgent:
    def __init__(self, session_name="ai_session"):
        self.session_name = session_name
        self._setup_session()

    def _setup_session(self):
        """tmux 세션 생성"""
        subprocess.run([
            "tmux", "new-session", "-d", "-s", self.session_name
        ], check=True)

    def create_window(self, name):
        """새 창 생성"""
        subprocess.run([
            "tmux", "new-window", "-t", f"{self.session_name}:{name}"
        ], check=True)

    def send_command(self, window, command):
        """명령어 전송"""
        subprocess.run([
            "tmux", "send-keys", "-t", f"{self.session_name}:{window}",
            command, "Enter"
        ], check=True)

    def get_window_output(self, window):
        """창의 출력 가져오기"""
        result = subprocess.run([
            "tmux", "capture-pane", "-p", "-t", f"{self.session_name}:{window}"
        ], capture_output=True, text=True)
        return result.stdout

# 사용 예시
agent = TmuxAgent("coding_session")
agent.create_window("editor")
agent.send_command("editor", "vim main.py")

5. 맞춤형 도구 개발

코드 검색 도구:

# search_tool.py
import subprocess
import os
import re

class CodeSearchTool:
    def __init__(self, project_root="."):
        self.project_root = project_root

    def search_patterns(self, pattern, file_extensions=None):
        """정규식 패턴으로 코드 검색"""
        if file_extensions is None:
            file_extensions = ["*.py", "*.js", "*.ts", "*.java"]

        cmd = ["find", self.project_root]
        cmd.extend(["-name", f"*.{file_extensions[0]}"])

        try:
            result = subprocess.run(
                cmd, capture_output=True, text=True, check=True
            )
            files = result.stdout.strip().split('\n')

            matches = []
            for file in files:
                if file.strip():
                    with open(file, 'r') as f:
                        content = f.read()
                        if re.search(pattern, content):
                            matches.append(file)
            return matches
        except subprocess.CalledProcessError:
            return []

# 사용 예시
searcher = CodeSearchTool()
results = searcher.search_patterns(r"def\s+\w+\s*\(")
print("함수 정의 찾기:", results)

Git 통합 도구:

# git_tool.py
import subprocess
import json

class GitTool:
    def __init__(self, repo_path="."):
        self.repo_path = repo_path

    def get_diff(self, commit_range="HEAD~1..HEAD"):
        """Git diff 가져오기"""
        try:
            result = subprocess.run([
                "git", "-C", self.repo_path, "diff", commit_range
            ], capture_output=True, text=True, check=True)
            return result.stdout
        except subprocess.CalledProcessError:
            return ""

    def get_staged_files(self):
        """스테이징된 파일들 가져오기"""
        try:
            result = subprocess.run([
                "git", "-C", self.repo_path, "diff", "--cached", "--name-only"
            ], capture_output=True, text=True, check=True)
            return result.stdout.strip().split('\n')
        except subprocess.CalledProcessError:
            return []

# 사용 예시
git_tool = GitTool()
diff = git_tool.get_diff()
staged = git_tool.get_staged_files()

6. 컨텍스트 윈도우 관리

대용량 코드베이스에서 컨텍스트 윈도우를 최적화:

# context_manager.py
class ContextManager:
    def __init__(self, max_tokens=4096):
        self.max_tokens = max_tokens
        self.context = []

    def add_message(self, role, content):
        """메시지 추가 (토큰 제한 고려)"""
        message = {"role": role, "content": content}

        # 간단한 토큰 추정 (실제 구현은 tokenizer 사용)
        token_count = len(content.split())

        if token_count > self.max_tokens:
            # 너무 긴 내용은 자르기
            content = " ".join(content.split()[:self.max_tokens])
            message["content"] = content

        self.context.append(message)
        return self._trim_context()

    def _trim_context(self):
        """컨텍스트 트리밍"""
        total_tokens = sum(len(msg["content"].split()) for msg in self.context)

        while total_tokens > self.max_tokens:
            if len(self.context) > 2:  # 최소 2개 유지
                self.context.pop(1)  # 중간 메시지 제거
                total_tokens = sum(len(msg["content"].split()) for msg in self.context)
            else:
                break

        return self.context

# 사용 예시
cm = ContextManager(max_tokens=2048)
cm.add_message("system", "You are a helpful AI assistant")
cm.add_message("user", "Write a function that does something complex with large data structures...")

7. 비용/성능 최적화

로컬 vs API 모델 비교:


python
# optimization.py
import time
from typing import Optional

class ModelOptimizer:
    def __init__(self):
        self.models = {
            "llama3": {"local": True, "speed": "fast", "cost": "free"},
            "codellama": {"local": True, "speed": "fast

---

📥 **Get the full guide on Gumroad**: https://gumroad.com/l/auto ($5)

AI 자동 생성 콘텐츠

본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.

원문 바로가기
0

댓글

0