요청은 언제든 받고, 계산 서버는 필요할 때 켜기
API, 장중 모의거래, 백테스트의 실행 시간을 나누고 큐로 연결한 이유.
사용자가 매수와 매도 조건을 블록으로 조합하면, 과거 시세로 시험하거나 실시간 시세로 모의거래를 하는 서비스. Idea2Strategy에서 만들려던 기능이다. 팀장으로 Java 백엔드 개발과 시스템 초기 설계를 맡으면서, 이 작업들을 같은 방식으로 실행해도 되는지부터 살폈다.
요청을 받아야 하는 시간과 실제 계산이 필요한 시간이 달랐다. API는 사용자의 요청에 응답해야 하지만, 장중 모의거래와 과거 시세 계산을 모두 하루 종일 실행할 이유는 없었다.
기술 이름보다 실행 조건을 먼저 나눴다
| 작업 | 필요한 실행 조건 |
|---|---|
| API | 사용자의 요청을 상시 접수 |
| 장중 모의거래 | 정해진 시간에 시작하고 종료 |
| 백테스트 | 계산 요청이 있을 때 기동 |
한 서버에 모으면 시작은 단순하다. 하지만 API가 필요하다는 이유로 계산 환경까지 항상 유지하게 된다. 역할별 서버를 모두 켜 두는 방법도 있지만, 계산하지 않는 시간의 자원을 줄이려는 목적에는 충분하지 않았다.
그래서 API, 트레이딩, 백테스트의 실행 자원을 나누고 가동 조건도 따로 두었다. 인프라 담당 팀원과 요청과 데이터의 흐름을 함께 검토하며 초기 설계를 구체화했다.
서버가 꺼져 있어도 요청은 받아야 한다
백테스트 서버를 필요할 때만 켜려면, 꺼져 있는 동안 들어오는 요청을 어디에 둘지 정해야 한다. 요청 접수와 계산을 SQS로 분리한 이유다. API가 요청을 접수하고 큐로 전달하면, 계산 서버는 기동한 뒤 대기 중인 작업을 가져간다.
- API요청 접수
- SQS작업 대기
- 백테스트기동 후 계산
큐 지표 → CloudWatch 알람 → Auto Scaling 기동 정책
SQS 자체가 EC2를 켜는 것은 아니다. 저장소의 기동 설정은 큐의 대기 메시지 수를 CloudWatch로 관찰하고, 알람이 Auto Scaling 정책을 실행하는 구조다. 작업을 보관하는 역할과 서버를 시작하는 역할을 나눠 봐야 요청이 어디에서 기다리는지 설명할 수 있다.
이 방식에는 대기 시간이 생긴다. 서버가 꺼져 있다면 기동을 기다린 뒤 계산하므로, 요청을 받았다는 사실과 계산이 시작됐다는 상태를 같은 것으로 다뤄서는 안 된다.
켜는 조건만큼 끄는 조건도 중요했다
작업 하나를 마쳤다고 바로 종료하면 뒤이어 온 요청이 다시 서버 기동을 기다릴 수 있다. 큐가 순간적으로 비어 있다는 이유만으로도 실행이 끝났다고 볼 수 없다.
현재 구현은 DB와 큐의 유휴 상태를 연속으로 확인한 뒤 백테스트 자원을 종료하도록 구성되어 있다. 새 요청을 처리하면 다시 유휴 여부를 확인한다. 종료 판단 중 오류가 발생했을 때도 이를 정상적인 유휴 상태로 간주하지 않는다.
트레이딩은 요청 기반이 아니라 예약 기반으로 분리했다. 미국 시장에 맞춰 뉴욕 시간대를 기준으로 시작과 종료를 설정했다. 한국 시각을 연중 고정하면 서머타임에 맞지 않을 수 있기 때문이다.
직접 확인한 동작과 코드에서 확인한 범위
프로젝트에서는 AWS에서 예약 시작·종료와 요청에 따른 서버 기동을 확인했다. 역할별 자원 분리는 설계에 그치지 않고 실제 시작 조건을 확인한 경험이다.
이후 포트폴리오를 정리하며 확인한 자동 종료 시험은 별도 범위다. 해당 시험은 AWS 호출을 모의 객체로 대체해 유휴 조건과 종료 요청을 검사했다. 실제 AWS 자동 종료까지 그 시험으로 증명한 것은 아니다. 운영비 절감률과 전체 서비스의 장기 안정성도 따로 측정하지 않았다.
이 설계에서 남기고 싶은 판단은 서버의 개수가 아니다. 사용자 요청을 받는 일과 계산하는 일을 분리하고, 각 작업에 맞는 실행 조건을 정했다는 점이다.
구현 더 보기
위 링크는 설명의 기준이 된 커밋을 가리킨다. 최신 구성과 서비스 화면은 프로젝트 저장소에서 볼 수 있다.
문제와 선택의 이유를 남깁니다.