- 주제: 주문 처리 및 체결 엔진 고도화
- 목표: 다중 종목 + 다중 사용자 환경에서의 처리 성능 확보
- 기술 스택: Spring Boot, MySQL, WebSocket, JPA, HikariCP, Concurrent Collection
- 사용자로부터 주문 요청을 수신
- 가격 유효성, 보유 자산 검증 (Account/Asset 서비스 연동)
- 검증 통과 시 주문 등록
- 종목별로
ConcurrentSkipListMap<Price, ConcurrentSkipListSet<Order>>
사용 - 가격 우선 → 시간 순 우선 체결 방식
- 체결된 주문은
TradeHistory
에 저장
- 주문 체결 시 WebSocket을 통해 클라이언트로 실시간 데이터 전송
@Scheduled
를 활용한 15초 단위 Candle 갱신
- 서버 시작 시 DB에서 거래 내역을 로딩 후 차트 초기화
- 종목별 Lock (
ReentrantReadWriteLock
)을 활용한 병렬 접근 제어
- 종목 수: 20개
- 사용자 수: 1,000명
- 동작 시간: 10분
- 테스트 도구: NGrinder
- 총 요청 수: 약 140,000건
- 기존 TreeMap + PriorityQueue 사용

- Order:
ReentrantLock
- Account: 비관적 락 (Pessimistic Lock)

- Order:
ReentrantLock
- Account: 비관적 락 (Pessimistic Lock)
- 쿼리 튜닝

- Order:
ReentrantLock
- Account: 비관적 락 (Pessimistic Lock)
- 쿼리 튜닝
- 커넥션 풀 튜닝

- Order:
synchronized
- Account: 낙관적 락 (Optimistic Lock)

- Order:
synchronized
- Account: 낙관적 락 (Optimistic Lock)
- 쿼리 튜닝

- Order:
synchronized
- Account: 낙관적 락 (Optimistic Lock)
- 쿼리 튜닝
- 커넥션 풀 튜닝

구분 | TPS | 최고 TPS | 에러 |
---|---|---|---|
Before | 145.5 | 191.0 | 7,677 |
After | 235.7 | 276.0 | 0 |
- Before: TreeMap + PriorityQueue
- After:
ConcurrentSkipListMap
+ConcurrentSkipListSet
+ 쿼리 튜닝 + 커넥션 풀 튜닝 - 결과: 종목 20개, 유저 1000명 기준 → 약 62% 성능 향상
- 해결:
ConcurrentSkipListMap
+ConcurrentSkipListSet
+ Lock 기반 제어
- 해결: HikariCP max pool → 30, MySQL max_connections → 300
- 해결: 조건부 Fetch Join 적용으로 쿼리 수 감소
체결 로직과 Account 동기화를 모두 고려하며 다양한 락 전략 및 구조 조합을 테스트했습니다.
실제 트래픽 환경을 기반으로 성능을 수치화하고, 분산 구조로의 확장을 위한 기반을 완성한 단계였습니다.