조용히 무거워지고 있었다

주말 사이 봇이 부풀어 있었다. 3일 11시간 연속 가동한 시점의 수치다.

2026-08-17 · 서버 메모리 실측
봇 RSS 434MB 전체 911MB 의 46.50%
익명 메모리 403MB
스왑 사용 810MB
가용 84MB OOM 직전
--------------------------------------------------
fd 8개 · 스레드 4개 핸들 누수는 아니다
→ 파이썬 객체가 쌓이고 있다

핸들이 새면 파일 디스크립터나 스레드가 같이 늘어난다. 둘 다 정상이었다. 그러면 남는 건 객체다.

창 경계가 매번 밀리고 있었다

범인은 원장 조회 캐시였다. vv_ledger 는 거래소 체결 내역을 45일치 소급해 읽는데, 긴 기간을 한 번에 안 주기 때문에 6일씩 창을 나눠 페이징한다. 그 창의 시작점을 ‘지금부터 45일 전’으로 잡은 것이 문제였다.

창 경계를 어디에 고정하느냐
[ 이전 ] start = now - 45일
5분 뒤 호출하면 경계가 5분 밀린다
캐시 키 매번 신규 · 적중률 0% · 삭제 없음
 
[ VV211 ] start = epoch 6일 배수 격자에 스냅
같은 구간이면 언제 물어봐도 같은 키
키 재사용 9/9 (이전 방식 0/8)
--------------------------------------------------
5분 주기 × 창 8개 × 종목 수 → 3.5일에 40만 키

재현해 보니 계산대로였다. 캐시가 하는 일이 없었고, 지워지지도 않았다. 안전망도 하나 붙였다. 캐시가 500개를 넘으면 오래된 창부터 200개를 정리한다. 캔들 캐시와 일봉 캐시가 이미 쓰던 방식 그대로다.

부수 효과가 하나 더 있었다. 적중률이 0이었으니 대조할 때마다 전량 재조회를 했다. 원장 대조 자체가 느렸던 이유다. 캐시가 살아나면서 그것도 같이 풀렸다.

배포 전 무결성 검사와 게이트21은 통과했다. 총자산 3,228,929원이 거래소 값과 일치했고, 그 시점엔 보유 포지션이 없었다.

손익표 바깥의 계기판

두 달 넘게 진입 게이트와 청산 파라미터만 들여다봤다. 메모리는 한 번도 안 봤다. 손익표에 안 나타나니까.

그런데 OOM 이 나면 파라미터가 아무리 좋아도 그 순간 봇은 없는 것과 같다. 이 버그는 내 수익을 한 푼도 깎지 않았고, 대신 봇을 죽일 뻔했다. 계기판을 손익 쪽에만 달아뒀다는 걸 434MB 를 보고 알았다.

폴 튜더 존스는 트레이딩에서 중요한 건 화려한 공격이 아니라 탄탄한 수비라고 했다. 수비를 진입 게이트 얘기로만 읽고 있었다. 봇이 내일 아침에도 켜져 있는 것, 그것도 수비다.


약어 풀이

* 이 글에 나온 영어 약어를 풀어 둔다.

  • RSS (Resident Set Size): 상주 메모리 크기. 프로세스가 실제로 물리 메모리에 올려두고 쓰는 용량.
  • OOM (Out Of Memory): 메모리 고갈. 남은 메모리가 없어 운영체제가 프로세스를 강제 종료하는 상태.