"[260826] 프로덕션 시작 시각을 당겼다가 발견한 순차 실행 문제, 그리고 새 증권사 연동 검증"
시작 시각을 앞당기면서 드러난 순차 실행 버그를 병렬 배칭으로 고치고, 새 증권사 API를 실계좌로 검증했습니다
시작 시각을 당겼다가 드러난 순차 실행 문제
오늘 낮, 운영 파이프라인의 시작 시각을 원래보다 훨씬 이르게 당겼습니다.
이렇게 당겨도 된다고 판단한 근거는 "새 그래픽카드로 종목 100개를 처리하는 데 한 시간이 채 안 걸린다"는 실측치였습니다.
그런데 저녁에 이 근거 자체가 틀렸다는 걸 알게 됐습니다. 그 수치는 여러 조각으로 쪼개 동시에 처리한 실험 결과였는데, 실제 운영 코드는 종목을 하나씩 순서대로 처리하는 구조였습니다.
순서대로 처리하면 100종목에 여덟 시간 가까이 걸립니다. 당겨놓은 시작 시각으로는 장 시작 전 마감 시간 안에 다 끝낼 수가 없는 게 확정적이었습니다.
더 찾아보니 당겨놓은 시작 시각으로 실제 운영이 돈 적이 그날까지 단 한 번도 없었습니다. 그날 새벽에 완료됐다고 남아있던 기록은 이전 스케줄의 잔재였습니다.
대응은 그래픽카드 한 장 안에서 여러 종목을 동시에 처리하는 배칭 방식을 도입하는 것이었습니다. 이미 다른 실험에서 안전성이 확인된 방식을 그대로 재사용했습니다.
배칭으로 바꾸면서 부수 버그도 몇 개 함께 나왔습니다.
가장 중요한 건 진행 상황을 감시하던 장치였습니다. 이 장치는 종목이 하나 끝날 때마다 기록 파일이 갱신된다는 전제로 짜여 있었는데, 배칭 구조에서는 전체 묶음이 다 끝나야 한 번에 갱신됩니다.
그러면 처리하는 몇 시간 내내 감시 장치가 "멈췄나 안 멈췄나"를 판단할 근거가 사라집니다. 부분적으로 끝난 묶음을 중간중간 미리 병합해서 기록을 갱신하는 장치를 새로 만들어 이 사각지대를 메웠습니다.
시작 시각은 결국 다시 원래대로 되돌리기로 했습니다. 애초에 시각을 당긴 이유였던 다른 실험(별도 모델의 완주 경쟁)이 그날 밤 사이에 이미 끝나버려서, 당겨야 할 이유 자체가 사라졌기 때문입니다.
시작 시각에 딸려 함께 움직이던 파생 타이머 몇 개도 이번엔 따라오지 않도록 고정했습니다. 원래 값들은 "당겨진 시작 시각 기준"으로 설계돼 있었는데, 시작 시각만 되돌리고 파생 타이머는 그대로 두면 엉뚱한 시각이 나오기 때문입니다.
되돌린 시각으로 첫 가동을 했더니, 추론 서버가 뜨는 과정에서 한 번 죽었습니다. 상주 서비스가 실행 경로를 못 찾는 사소한 환경 설정 문제였는데, 매일 밤 서버를 새로 띄우는 구조라 고치지 않으면 매일 밤 재발할 버그였습니다.
바로 수동으로 재기동해 정상화했고, 원인이 되는 환경 설정도 함께 고쳤습니다. 그날 밤 100종목 전체가 46분 만에 끝났는데, 낮에 실측했던 예상 소요 시간과 거의 정확히 일치했습니다.
이 과정에서 다른 AI에게 코드 검토를 맡겼는데, 심각한 버그 두 개를 더 찾아냈습니다. 하나는 어제 처리하다 남은 조각이 오늘 것으로 잘못 병합될 수 있는 경로였고, 다른 하나는 서버가 완전히 멈춘 최악의 상황에서 오히려 감시 장치의 판단 근거가 죽어버리는 문제였습니다. 둘 다 바로 고치고 재현 상황을 만들어 검증했습니다.
당연히 실전 검증은 그날 밤이 처음이었기 때문에, 사람이 직접 옆에서 지켜보며 진행했습니다.
새 증권사 연동, 실계좌 왕복까지 검증
지금까지는 증권사 한 곳에만 자동매매를 붙여 왔는데, 오늘부터 다른 증권사 연동 작업을 시작했습니다.
목표는 최종적으로 실거래 주문까지 새 증권사로 옮기는 것입니다. 다만 이 프로젝트에서 지켜온 승격 절차(모의검증을 통과해야 다음 단계로) 그대로 밟기로 했습니다. 주문 실행/안전장치 계층(새 창)에서 다룬 것과 같은 원칙입니다.
공식 개발 문서가 따로 없는 API라, 공개된 뒷단 엔드포인트를 하나씩 직접 뽑아 정리하는 데서 시작했습니다. 기존 증권사 클라이언트와 완전히 동일한 인터페이스로 새 클라이언트를 만들어서, 나중에 갈아끼울 때 상위 코드는 손댈 필요가 없게 했습니다.
모의 계좌로 먼저 스모크 테스트를 했습니다. 이 과정에서 성공/실패 판정 기준 자체에 있던 버그를 발견했습니다. 정상적으로 처리된 응답을 실패로 오판하는 기준이었는데, 판정 근거를 더 신뢰할 수 있는 필드로 바꿔 고쳤습니다.
오후엔 아주 소액 한도 안에서 실계좌 매수→매도→미체결 취소 전 과정을 실제로 검증했습니다. 매수와 매도 모두 즉시 전량 체결됐고, 미체결 취소도 의도대로 동작했습니다.
이 과정에서 버그를 하나 더 잡았습니다. 이 증권사는 주문 취소를 별개의 새 이벤트로 남기는데, 이걸 걸러내지 않으면 방금 취소한 주문이 다시 미체결 주문으로 잘못 잡히는 문제였습니다.
다른 AI에게 코드 검토를 맡겼더니 "지금 상태로는 바로 갈아끼울 수 없다"는 결론이 돌아왔습니다. 배선이 실제로 끊어지는 지점 여러 곳과, 앞서 찾은 취소 이벤트 버그가 체결 내역 조회 쪽엔 아직 반영 안 된 사실도 함께 지적받았습니다.
지적받은 항목을 거의 전부 즉시 고치고 실계좌로 다시 검증했습니다. 체결 내역 응답 형식을 기존 증권사와 완전히 맞추고, 매수 가능 금액을 더 정확한 기준으로 조회하도록 바꾸고, 계좌번호가 로그에 과다 노출되던 부분도 마스킹을 강화했습니다.
아직 실제 운영에 이 새 클라이언트를 배선하지는 않았습니다. 남은 리스크가 하나 있는데, 이 계좌를 자동매매와 사람이 함께 쓰다 보니 사람이 직접 넣은 주문을 시스템이 오작동으로 오인할 위험입니다. 이 부분부터 먼저 풀어야 다음 단계로 넘어갈 수 있습니다.
오늘은 같은 종류의 실수를 두 번 만났습니다. 실험 환경에서 검증된 수치나 동작을, 실제 운영 환경의 조건 차이를 확인하지 않고 그대로 가져다 쓴 게 문제였습니다. 처리 방식(순차냐 동시냐)도, 이벤트 형태(취소가 새 이벤트로 남는지)도 눈으로 직접 확인하고 나서야 진짜 문제가 보였습니다.