티스토리 뷰
실전 운영에서 터진 것들 — 리스크 관리와 리팩토링
코드를 짜는 건 쉬웠다. 진짜 어려운 건 그 코드를 실전에서 돌리는 것이었다. 봇을 2개월 운영하면서 터진 것들, 그리고 그걸 수습하면서 배운 것들을 정리한다.
사건 1: 새벽 3시 폭락
어느 날 새벽, BTC가 10분 만에 7% 빠졌다. 봇은 손절 라인(-3.5%)을 찍고 매도했는데, 문제는 그 다음이었다. 가격이 잠깐 반등하자 봇이 다시 매수했고, 또 떨어져서 또 손절. 이걸 3번 반복했다. 하룻밤에 -8%.
이 사건 이후 비상 손절 시스템을 만들었다.
class EmergencyStop:
def check(self, daily_loss_pct):
# 일일 손실이 -5%를 넘으면 당일 매매 전면 중단
if daily_loss_pct < -5.0:
scheduler.pause()
notifier.send("🚨 일일 손실 -5% 초과. 봇 자동 정지.")
return True
# 연속 3회 손절 시 1시간 쿨다운
if self.consecutive_losses >= 3:
self.cooldown_until = now() + timedelta(hours=1)
notifier.send("⚠️ 연속 손절 3회. 1시간 쿨다운.")
return True
return False
일일 손실 한도, 연속 손절 쿨다운, 최대 포지션 크기 제한. 이 세 가지가 리스크 관리의 기본이었다.
사건 2: 메모리 누수
봇을 3일 연속 돌리면 메모리 사용량이 2GB를 넘어갔다. tracemalloc으로 추적해보니 범인은 두 가지였다.
market_snapshots를 메모리에 전부 들고 있었다. 쿼리 결과를 리스트로 받아서 슬라이싱하는 대신, SQL에서LIMIT을 걸어야 했다.- WebSocket 연결이 끊어져도 이벤트 리스너가 해제되지 않았다. 클래식한 메모리 누수.
3일에 한 번 봇을 재시작하는 건 해결책이 아니다. 원인을 잡고 나서는 일주일을 돌려도 메모리가 300MB 이하로 유지됐다.
에러 핸들링 + 알림
운영에서 가장 중요한 건 "뭔가 잘못됐을 때 바로 아는 것"이다. Telegram 봇을 연동해서 알림 시스템을 구축했다.
- 매매 체결 시 알림 (코인, 수량, 가격, 수익률)
- 에러 발생 시 알림 (API 타임아웃, 잔고 부족 등)
- 일일 정산 리포트 (총 자산, 수익률, 매매 횟수)
- 봇 상태 변경 알림 (시작, 정지, 비상 정지)
업비트 API 에러 핸들링도 체계화했다. 429(Rate Limit)는 지수 백오프로 재시도, 5xx는 3회 재시도 후 알림, 인증 에러는 즉시 봇 정지. 에러별로 대응 전략을 명확히 정의하니까 새벽에 장애가 나도 봇이 알아서 처리하고, 내가 못 처리하는 건 알림으로 깨워줬다.
리팩토링: 클린 아키텍처
기능이 계속 붙으면서 코드가 스파게티가 되어갔다. main.py가 800줄을 넘어가는 걸 보고 리팩토링을 결심했다.
src/cryptobot/
├── core/ # 도메인 로직 (전략, 지표, 리스크 관리)
├── infra/ # 외부 연동 (업비트 API, DB, Telegram)
├── api/ # FastAPI 서버
├── services/ # 유스케이스 (매매 실행, 데이터 수집, 정산)
└── config/ # 설정 관리
핵심은 의존성 방향을 안쪽으로 통일한 것이다. core는 infra를 모른다. 전략 로직이 업비트 API를 직접 호출하지 않고, 인터페이스를 통해 데이터를 받는다. 이렇게 하니까 백테스팅할 때도 같은 전략 코드를 쓸 수 있었다.
CI/CD
GitHub Actions로 CI를 구성했다. PR마다 pytest 실행, ruff 포매팅 체크, 타입 체크. 메인 브랜치에 머지되면 서버에 자동 배포. 배포 스크립트는 봇을 graceful shutdown 하고, 코드 업데이트 후 재시작한다.
# .github/workflows/ci.yml
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: pip install -e ".[dev]"
- run: ruff check .
- run: pytest --cov=cryptobot
시리즈를 마치며
한 달 정도 봇을 돌리면서 단순한 운영 이상의 경험을 얻었다. 실시간 시스템 운영, 장애 대응, AI를 실용적으로 활용하는 감각, 백테스팅으로 가설을 검증하는 습관 — 수익보다 큰 가치였다.
그런데 이 모든 안전장치를 다 갖췄다고 생각한 시점에, Phase 2를 실전에 올리자마자 하루 만에 hotfix 6개를 쏟아내는 사건이 터졌다. 다음 편에서 그 12시간을 풀어본다.
👉 다음 글 보러가기
'CryptoBot' 카테고리의 다른 글
| 봇이 알아서 돌게 만들기 — 스케줄러, 안전장치, 그리고 웹 사이트 제작 (0) | 2026.04.16 |
|---|---|
| 실전 투입하자마자 터진 버그 6개 — 테스트에서 못 잡는 것들 (0) | 2026.04.13 |
| FastAPI + React로 봇 관리 대시보드 만들기 (0) | 2026.04.10 |
| 승률 22%에서 배운 것 — 멀티코인 + 전략 진화 (0) | 2026.04.09 |
| Claude Haiku가 월 640원에 매매를 도와준다 — AI 자동매매의 시작 (0) | 2026.04.05 |
- Total
- Today
- Yesterday
- CryptoBot
- kafka connect
- Kafka
- Haiku4096토큰
- jdbc
- SlidingWindowTTL
- DataFramebool
- CDC
- LLM동적호출
- LLM비용오차
- LLM비활성결정
- 코드자체감사
- P0P4우선순위
- BOJ #JS
- 일일주간월간스케줄러
- Telegram알림
- 수수료슬리피지
- 일경계처리
- AnthropicCaching
- 데이터엔지니어링
- 메이저화이트리스트
- 코인별전략배정
- 5중검증
- 트레일링스탑버그
- 데모모드
- 한달운영진단
- 비용80%절감
- 코인별손익분석
- LLM파라미터머지
- Page_DownPage_DownPage_Down
| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | |||||
| 3 | 4 | 5 | 6 | 7 | 8 | 9 |
| 10 | 11 | 12 | 13 | 14 | 15 | 16 |
| 17 | 18 | 19 | 20 | 21 | 22 | 23 |
| 24 | 25 | 26 | 27 | 28 | 29 | 30 |
| 31 |