본문 바로가기
IT/HomeLabs

[HomeLab] 돌고 돌아 순정! Python과 Docker로 3분 만에 AI 봇 구축하기 (2부)

by 수누다 2026. 2. 6.

반갑습니다, 수누다입니다.

지난 1부에서 거창한 프레임워크인 OpenClaw를 도입했다가, '로그 분석관'이 튀어나오는 참사를 겪고 컨테이너를 날려버렸다는 이야기 전해드렸죠.

엔지니어 생활 13년 하면서 느낀 불변의 진리가 하나 있습니다.
"튜닝의 끝은 순정이다."

내 마음대로 제어가 안 되는 블랙박스(프레임워크)를 붙들고 씨름할 바엔, 차라리 바닥부터 직접 짜는 게 훨씬 빠르고 속 편할 때가 많습니다. 오늘은 그 '순정 봇'을 만드는 과정을 공유합니다.

준비물은 딱 두 개면 됩니다. Python, 그리고 Docker.
(제 PC엔 파이썬도 안 깔려 있습니다만, 우리에겐 도커가 있으니 상관없습니다.)


1. 아키텍처 다이어트 (Refactoring)

1부의 그 복잡했던 구조도에서 미들웨어를 다 걷어냈습니다.
중간에 에이전트 프레임워크가 낄 자리는 없습니다. 뇌(Ollama)입(Discord)을 직통으로 연결합니다.

  • Host (PC): Ollama (Llama 3.1) 구동 중
  • Docker Container: Python Script (Discord API ↔ Ollama API 중계)
  • Interface: Discord

(▲ 중간 유통 과정을 없애니 이렇게나 깔끔합니다. 직거래가 답이죠.)


2. 코드 구현: 딱 50줄의 미학

거창한 클래스 설계? 디자인 패턴?
토이 프로젝트에 그런 건 사치입니다. discord.pyrequests 라이브러리만 있으면 됩니다.

핵심 로직은 이게 전부입니다.

# mybot.py (핵심 요약)
import discord
import requests

# 여기가 핵심입니다.
# 도커 컨테이너에서 호스트 PC의 Ollama를 찾으려면 localhost를 쓰면 안 됩니다.
OLLAMA_URL = "http://host.docker.internal:11434/api/chat"

@client.event
async def on_message(message):
    if message.author == client.user: return

    # 1. 사용자 메시지 수신
    user_content = message.content

    # 2. Ollama에게 토스 (Request)
    payload = {
        "model": "llama3.1",
        "messages": [
            # 여기서 봇의 성격을 정의합니다.
            {"role": "system", "content": "너는 친절한 AI 비서 '구름'이야."},
            {"role": "user", "content": user_content}
        ],
        "stream": False
    }

    # 3. 답변 받아서 디스코드에 전송 (Response)
    response = requests.post(OLLAMA_URL, json=payload).json()
    bot_reply = response['message']['content']
    await message.channel.send(bot_reply)

복잡한 설정 파일(json) 수십 줄보다, 내가 짠 파이썬 코드 50줄이 훨씬 직관적이고 수정하기도 편하죠.


3. 도커 배포: 내 PC를 더럽히지 말자

파이썬 환경 설정하다가 의존성 꼬여보신 분들 많으시죠?
저는 제 로컬 환경이 지저분해지는 걸 병적으로 싫어합니다. 봇을 위한 깔끔한 독방(Container)을 하나 만들어 줍니다.

# Dockerfile
FROM python:3.9-slim  # 가볍게 갑시다
WORKDIR /app

# 필수 라이브러리 설치
RUN pip install discord.py requests

# 코드 복사
COPY mybot.py .

# 실행
CMD ["python", "mybot.py"]

💡 삽질 방지 팁: host.docker.internal

위 코드에서 OLLAMA_URL을 보시면 localhost 대신 host.docker.internal을 썼습니다.
도커 컨테이너 입장에서 localhost는 컨테이너 자기 자신을 의미합니다. 내 PC(Host)에 떠 있는 Ollama에 접속하려면, 도커가 제공하는 이 매직 도메인을 써야 합니다.
(이거 몰라서 포트 포워딩하고 방화벽 끄고... 삽질하는 주니어들 많이 봤습니다.)


4. 트러블슈팅: 원숭이도 나무에서 떨어진다

자, 빌드하고 실행! ...했는데 에러가 떴습니다.

File "/app/mybot.py", line 10
    OLLAMA_URL = "..."MODEL_NAME = "llama3.1"
                                           ^
SyntaxError: invalid syntax

...아.
블로그에 올릴 코드 정리하다가 복사/붙여넣기 실수로 변수 두 개가 한 줄에 붙어버렸네요.
13년 차 엔지니어도 이런 오타(Human Error) 냅니다. (머쓱)
엔터 한 방 쳐주고 다시 빌드했습니다.


5. 결과: 3분 컷, 그리고 평화

# 1. 빌드
docker build -t gureum-bot .

# 2. 실행 (호스트 연결 옵션 필수!)
docker run -d --name my-gureum --add-host=host.docker.internal:host-gateway gureum-bot

명령어 두 줄로 봇이 살아났습니다.
1부에서 그 고생을 했는데, 이번엔 3분도 안 걸렸네요.

떨리는 마음으로 다시 말을 걸어봅니다.

드디어!
영어 논문을 읊어대던 '분석관'은 사라지고, 제가 원하던 '친구'가 나타났습니다.
Latency(응답 속도)도 1초 미만. 아주 쾌적합니다.


6. 마치며: 하지만 뭔가 부족하다?

이렇게 해서 Python + Docker + Ollama 조합으로 깔끔하게 봇을 구축했습니다.
"역시 심플한 게 최고다"라며 만족하고 있었는데... 며칠 써보니 치명적인 단점이 보이더군요.

Me: 구름아, 오늘 삼성전자 주가 얼마야?
Gureum: 죄송해요. 저는 2023년 데이터까지만 알고 있어서 최신 주가는 몰라요. 😅

그렇습니다. 제 로컬 PC에 갇혀 있는 이 녀석은 세상과 단절된 '방구석 천재'였습니다.
오늘 날씨도, 실시간 뉴스도 모르는 녀석을 진정한 '비서'라고 부르긴 어렵겠죠.

그래서 다음 편(마지막 3부)에서는, 이 녀석에게 인터넷(Web Search)이라는 강력한 무기를 쥐여주는 과정을 다뤄보겠습니다. 돈 드는 API 말고요, 공짜로요.

[Next] 방구석 천재 AI에게 '구글링' 능력 달아주기 (Tool Use 구현)


[수누다의 한 줄 요약]

"남이 만든 거대한 프레임워크보다, 내가 짠 허접한 코드가 때론 더 강력하다."