Joyuno's Dev Blog

2026-04-21 (화) 개발일지

dev-blog

오늘의 개발 일지: 서버 복구부터 AI 트레이딩 전략까지

오늘은 정말 다양한 프로젝트를 오가면서 작업한 하루였습니다. 아침에는 갑자기 죽은 서버부터 복구하고, 오후에는 사주 어플의 채팅 기능을 구현하다가 저녁에는 트레이딩 봇의 전략을 완전히 갈아엎는 작업까지… 정말 알차게 보낸 하루네요.

서버가 갑자기 죽어버렸을 때

아침에 출근해서 aiiv.site에 접속하려는데 연결이 안 되더라고요. 당황했죠. “어제까지 잘 되던 사이트가…”

먼저 DNS를 확인해봤습니다. nslookup 결과로는 IP가 정상으로 보이는데, 실제 접속은 안 되더라고요. 서버 문제라는 걸 직감했습니다.

GCP 콘솔에서 VM 상태를 확인해보니 RUNNING 상태였지만, SSH 접속조차 거부당하더라고요. 이건 뭔가 심각한 문제라는 신호였습니다. IAP 터널로 접속을 시도해봤지만 여전히 실패. 시리얼 콘솔로 들어가보니 systemd-logind가 실패하고 있었습니다.

결국 원인은 메모리 부족 + swap 미적용 문제였어요. 기존 e2-small(2GB RAM) 인스턴스에서 메모리가 터져버린 거죠.

해결책은 단호했습니다. VM을 완전히 삭제하고 e2-medium(4GB RAM)으로 새로 만들기로 했습니다. startup-script에 모든 설정을 넣어서 처음부터 다시 구성했죠. 이 과정에서 HTTPS 설정도 한번에 처리했습니다.

배운 점: 서버가 갑자기 죽으면 메모리 문제를 의심해보자. 그리고 startup-script로 초기 설정을 자동화해두면 재생성할 때 큰 도움이 된다.

사주 어플 채팅 기능의 숨은 버그

사주 어플에서 상호 좋아요를 누른 사용자들끼리 채팅할 수 있는 기능을 구현하고 있었습니다. 백엔드 WebSocket 서버는 이미 다 만들어놨다고 생각했는데, 프론트엔드에서 테스트해보니 계속 에러가 나더라고요.

문제를 추적해보니 세 가지 이슈가 있었습니다:

  1. 백엔드 엔드포인트 불일치: 프론트엔드의 getOrCreateChatRoom() 메서드가 호출하는 POST /chat/rooms 엔드포인트가 백엔드에 없었어요.
  2. 메서드 누락: matching_screen.dart에 _openChat() 메서드가 정의되어 있지 않았습니다.
  3. 모델 필드명 불일치: ChatRoom 모델의 필드명이 백엔드 응답과 맞지 않았죠.

가장 웃긴 건 이미 구현은 거의 다 되어 있었다는 점이었어요. 이전에 작업하던 에이전트가 리밋에 걸려서 중간에 멈춘 상태였는데, 거의 90%는 완성되어 있었습니다. 남은 10%의 연결고리만 잇는 작업이었죠.

수정은 비교적 간단했습니다:

  • 백엔드에 누락된 엔드포인트 추가
  • 프론트엔드에 _openChat() 메서드 구현
  • 모델 필드명 매핑 수정

배운 점: 협업할 때(심지어 과거의 나와도) 작업 상태를 명확히 기록해두자. “거의 다 했는데…” 상태가 가장 위험하다.

서울 구(區) 기반 매칭 로직

사주 어플에서 지역 기반 매칭을 구현하려고 했습니다. 사용자가 사는 구를 기준으로 동일 구나 인접 구의 사람들을 추천해주는 기능이었죠.

문제는 서울의 25개 구와 각 구의 인접 관계 데이터가 필요했다는 점입니다. “동대문구는 중랑구, 성북구, 성동구, 광진구와 인접한다” 같은 데이터를 일일이 수집해야 했어요.

결국 Python 딕셔너리로 모든 구의 인접 관계를 정의한 seoul_districts.py 모듈을 만들었습니다. 재미있었던 건 2-hop 이웃(인접구의 인접구)까지 계산하는 로직을 BFS로 구현한 부분이었어요.

def get_neighbors(district, hops=1):
    """구의 인접 구들을 반환 (hops=1: 직접 인접, hops=2: 2-hop 이웃)"""

배운 점: 지리적 데이터는 생각보다 복잡하다. 특히 경계가 불규칙한 도시의 경우 정확한 인접 관계 데이터를 만드는 게 중요하다.

트레이딩 봇 전략의 대격변

bit-scalp 프로젝트에서 가장 큰 변화가 있었습니다. 기존의 여러 전략들을 버리고 @TRADING_ALGORITHM.md에 정의된 새로운 전략 체계로 완전히 갈아엎었죠.

기존에는 smart_scalp, trend_follow_scalp 같은 전략들이 있었는데, 백테스트 결과가 좋지 않았어요. 특히 smart_scalp는 8건 전패라는 충격적인 결과를 보여주더라고요.

새로 구현한 전략들은:

  • 전략A (엔딩 다이아고날): 고점 쐐기 붕괴 시 숏, 저점 쐐기 돌파 시 롱
  • 전략B (삼각수렴 돌파): 삼각형 패턴 돌파 시 추세 방향 진입
  • 전략C (RSI 추세 매매): RSI 과매수/과매도 구간에서의 추세 매매 (새로 추가)

가장 중요한 변화는 포지션 사이징을 90%로 올린 점이었습니다. 기존에는 보수적으로 50%만 사용했는데, 새 전략들의 신뢰도가 높아져서 과감하게 올렸죠.

배운 점: 트레이딩에서 전략은 고정된 게 아니라 계속 발전시켜야 한다. 성과가 나쁜 전략은 과감하게 버리고, 데이터에 기반한 새로운 접근법을 시도해야 한다.

CLI 생산성 향상

사소하지만 실용적인 개선도 있었습니다. Claude CLI 명령어들을 짧은 alias로 설정한 거죠.

alias cc='claude'
alias ccs='claude --dangerously-skip-permissions'
alias cct='claude --telegram@plugin-official'
alias ccst='claude --dangerously-skip-permissions --telegram@plugin-official'

이렇게 하니 터미널에서 Claude를 부를 때마다 긴 명령어를 치지 않아도 되어 정말 편해졌어요. 특히 ccst처럼 여러 옵션을 조합한 alias는 자주 사용하는 작업 흐름을 크게 단축시켜주더라고요.

배운 점: 반복적인 CLI 명령어는 alias로 만들어두자. 작은 시간 절약이 모여 하루 생산성을 크게 높여준다.

오늘의 한줄

서버 복구부터 AI 트레이딩 전략 갈아엎기까지, 문제 해결의 본질은 결국 ‘원인 파악 → 과감한 결정 → 체계적 구현’이라는 사이클을 반복하는 것임을 다시 한번 깨달은 하루였다.