토스증권 실시간 시세 적용기 (정리)

토스ㅣSLASH 22 - 토스증권 실시간 시세 적용기

 

  • 토스증권은 인생 첫 주식거래 때 사용했던 어플리케이션이다.
  • 마침 토스 유튜브 채널 Slash22에서 박성우[토스 Server Developer] 님께서 실시간 시세 적용기에 대한 설명을 해주셔서 내용을 정리해보기로 했다.
  • 평소 궁금했던 토스증권 어플리케이션의 원활한 작동을 위한 아키텍쳐와 프로세스에 대해서 이해하려고 노력했다.
  • 모르는 용어는 중간중간 Chat GPT를 활용해 정리해 두었다.

 

실시간 시세

  • 투자자들은 가능한 최신 가격으로 거래하기를 희망한다. (시세와 주문호가 기준)
  • 증권사는 실시간 시세를 제공받아 해당 기능 구현하는데 사용한다.
  • 국내 종목의 경우 모든 증권사에서 무료로 제공되고 있지만 해외 종목의 경우 사정이 다르다.

 

API Polling 방식 ⇒ WebSocket 방식

API Polling 방식
클라이언트 애플리케이션이 서버에서 데이터를 주기적으로 가져오는 방식이다. 클라이언트는 일정한 간격으로 서버에 요청을 보내고, 서버는 데이터를 응답한다.
클라이언트는 이전 요청에서 가져온 데이터의 마지막 수정 시간 등의 정보를 포함하여 요청을 보내고, 서버는 이 정보를 기반으로 업데이트된 데이터를 반환한다.
API Polling은 간단하고 쉽게 구현할 수 있으며, 대부분의 API에서 지원되는 방식. 그러나, 주기적인 요청으로 인해 서버의 부하가 증가할 수 있으며, 실시간성이 중요한 애플리케이션에는 적합하지 않을 수 있다.
이러한 문제를 해결하기 위해서는 WebSockets와 같은 실시간 통신 방식을 사용할 수 있다.
WebSocket
WebSocket은 클라이언트와 서버 간의 양방향 통신을 가능하게 해주는 프로토콜이다. 이를 통해 서버는 클라이언트에게 실시간으로 데이터를 전송할 수 있다.
WebSocket은 HTTP 프로토콜 위에서 동작하며, 서버와 클라이언트 간에 핸드쉐이킹 과정을 거쳐 연결이 수립된다.
이후에는 TCP 연결을 유지하며, 클라이언트나 서버가 언제든지 데이터를 전송할 수 있다.
WebSocket은 일반적으로 실시간으로 업데이트되는 데이터를 처리할 때 유용하다. 예를 들어, 실시간 채팅 애플리케이션, 주식 거래 시스템, 게임 등에서 사용된다.또한, Polling 방식과는 달리, 서버 부하를 줄이고 성능을 향상시킬 수 있다.

 

  • 런칭 전 초기 초창기 토스증권에서는 API Polling 방식을 채택했었다.
  • 하지만 이후 주 타겟층(초보)과 별개로 전체 사용자 경험을 위해 실시간 시세를 제공해야 한다는 의견이 나왔다.
  • 많은 팀원들이 동의하였고, 따라서 Polling 대신 WebSocket 기능을 선택하게 되었다.
  • 원래 SSE(Server Side Event) 방식도 후보에 있었지만, 양방향 통신 기능의 니즈가 있을 것으로 예상해 WebSocket 채택했다.
SSE 방식
Server-Sent Event (SSE)는 웹 애플리케이션에서 서버로부터 실시간 이벤트를 받기 위한 기술. 이 기술은 단방향 통신으로, 서버에서 클라이언트로만 데이터를 보낼 수 있다.
SSE는 HTTP와 함께 사용된다. 웹 브라우저는 HTTP 연결을 열고, 서버는 이 연결을 통해 실시간 이벤트를 전송한다.
  •  

  • SSE 방식이 더 방화벽 친화적이다. WebSocket의 경우 방화벽 관련 이슈 다소 발생했다.
  • WebSocket 기능에 문제가 생기면 기존에 구축해놓은 Polling 방식이 Fallback 기능으로써 작동한다.
  • WebSocket 시스템을 활용해 같은 종목을 보고 있는 사용자 수를 알려주는 기능을 구현했었지만, 최종적으로 고객의 매매 전환으로는 이어지지 않는다는 A/B Test 결과로 인해 페이드아웃 되었다.
A/B Test
A/B 테스트는 두 가지 이상의 다른 디자인, 콘텐츠, 또는 기능을 가진 웹 페이지나 앱 화면을 랜덤으로 사용자에게 제공하여, 어떤 디자인이나 기능이 더 좋은 사용자 경험을 제공하는지 비교하는 실험적인 방법이다.

 

토스증권의 전체 시세 시스템 아키텍처

원장 시스템
원장 : 참가자들 간에 공유되는 거래 정보를 안전하게 저장하고 관리하는 시스템.
원장 시스템(ledger system)은 여러 참가자 간에 공유되는 분산 원장(distributed ledger) 기술을 기반으로 한 분산 시스템으로, 여러 참가자 간에 공유되는 정보나 자산을 관리하는 데 사용된다.
원장 시스템은 중앙 집중식 시스템과 달리, 모든 참가자 간에 분산된 데이터베이스를 유지하면서, 데이터 변경 시 승인된 노드들에 의해 실시간으로 검증되고 갱신된다. 이를 통해 블록체인 기술의 핵심 기능인 탈중앙화와 보안성이 보장된다.
원장 시스템은 다양한 분야에서 사용되고 있다. 예를 들어, 금융 분야에서는 거래원장(transaction ledger)을 관리하는 데 사용된다.

 

  • Unix C 기반의 원장 시스템과 Kubernetes Java 기반의 MTS Application 영역 ⇒ 다른 기술스택으로 구성되어있다.
  • C 기반 원장 시스템에서 수신받은 시세 정보를 Java 기반 어플을 거쳐 클라이언트단으로 전달하기 위한 매개체로 Kafka 활용
Kafka
Kafka는 대용량의 실시간 메시지 데이터를 안정적으로 처리하고 분산 저장하는 분산 메시징 시스템이다.
이를 통해 데이터를 효율적으로 수집, 전송, 처리할 수 있다.
Kafka는 대용량 데이터를 처리하는 데 매우 효과적이며, 빠른 처리 속도와 높은 확장성, 신뢰성, 내고장성을 제공한다. 또한, 데이터 손실이나 중복을 방지하고, 데이터의 영속성을 보장한다. Kafka는 대규모 분산 시스템의 핵심 기술로 사용되고 있다.

 

인프라 구조

  • WebSocket 서버를 DMZ 영역에 배치하고, N개의 서버가 각각 고유한 호스트 명을 갖도록 했다.
  • WebSocket 서버를 DMZ 영역에 배치했다.
DMZ 영역
DMZ(Demilitarized Zone) 영역은 인터넷과 내부 네트워크 사이에 위치한 보안 영역을 이야기한다. DMZ를 사용하면 외부에서 내부 네트워크로 직접적인 접근을 막을 수 있으며, 외부와 내부 간 데이터 전송을 안전하게 처리할 수 있다. DMZ는 기업 등에서 많이 사용되며, 보안성과 효율성을 동시에 보장하는 중요한 보안 체계이다.
WebSocket 서버를 DMZ(Demilitarized Zone) 영역에 배치한다는 것은, 인터넷과 내부 네트워크 사이에 위치한 보안 영역인 DMZ에서 WebSocket 서버를 운영한다는 것을 의미한다. 이렇게 함으로써, 인터넷으로부터 들어오는 악성 공격에 대해 WebSocket 서버가 보호될 수 있다.
로드밸런싱(Load Balancing)
로드 밸런싱(Load Balancing)은 서버나 네트워크 등에서 발생하는 트래픽을 여러 대의 서버에 분산시켜 처리하는 기술이다. 이를 통해 서버의 부하를 분산시켜 서버의 처리 능력을 향상시키고, 서버 다운 시에도 대처할 수 있는 확장성을 갖출 수 있다. 이를 통해 웹 사이트나 애플리케이션의 성능 향상과 안정적인 운영을 보장할 수 있다. 따라서 로드 밸런싱은 대규모 서비스나 트래픽이 많은 서비스에서 매우 중요한 기술이다.
라우팅 서버
클라이언트 요청에 대한 적절한 서버로 요청을 전달하는 역할을 수행하는 서버이다. 라우팅 서버는 일반적으로 메시지 큐와 같은 중간 매개체를 사용하여 요청을 전달한다. 클라이언트가 라우팅 서버의 주소를 가지고 요청을 보내면, 라우팅 서버는 해당 요청을 적절한 서버로 전달한다.
Redis
Redis(Remote Dictionary Server)는 인메모리 데이터 저장소이다. Redis는 다양한 데이터 구조를 지원하며, 분산 캐시, 세션 저장, 푸시 알림, 메시지 큐 등 다양한 용도로 사용된다. 데이터를 디스크에 저장하기 때문에 시스템 장애 시에도 데이터를 유지할 수 있다. Redis는 분산 캐시와 세션 저장 등에 많이 사용된다. Redis는 PUB/SUB 메커니즘을 사용하여 메시지 큐 등의 용도로도 사용된다.
메시지 큐
메시지 큐(Message Queue)는 비동기적으로 메시지를 처리하는 시스템이다. 메시지 큐는 메시지를 보내는 측(Producer)과 메시지를 받는 측(Consumer)이 분리되어 있기 때문에, 서로 독립적으로 동작할 수 있다.
PUB/SUB 메커니즘
PUB/SUB(Publish/Subscribe) 메커니즘은 메시지를 발행하고, 이를 구독하는 시스템 간의 통신 방식이다. 이 방식은 메시지 브로커(Message Broker)를 사용하여 구현할 수 있다. PUB/SUB 메커니즘은 발행자(Publisher)와 구독자(Subscriber)가 분리되어 있다. 발행자는 메시지를 발행하여 브로커에 전달하며, 이를 구독자는 브로커에서 메시지를 수신하여 처리한다.
메시지 브로커
메시지 브로커(Message Broker)는 메시지를 생성한 시스템과 해당 메시지를 소비하는 시스템 간의 중개자 역할을 수행하는 소프트웨어이다. 메시지 브로커는 발행-구독(Publish-Subscribe) 메커니즘, 큐(Queue) 메커니즘 등의 방식을 사용하여 메시지를 관리하고 전달한다. 주요한 메시지 브로커로는 RabbitMQ, Apache Kafka, ActiveMQ 등이 있다.

 

  • 이러한 인프라 구조를 채택한 이유 두 가지
    1. 전자금융감독 규정의 망분리 요건을 준수하기 위함
      • 클라이언트가 증권사 내부 서버에 직접 접속하지 말아야 한다.
      • DMZ 구간에 웹 서버를 경유하도록 권장.
    2. WebSocket 서버 상단의 네트워크 홉을 줄이기 위함
네트워크 홉
네트워크 홉(Network Hop)은 데이터가 한 지점에서 다른 지점으로 이동할 때 거쳐가는 네트워크 장비 수를 의미한다. 네트워크 홉의 수는 대개 네트워크 성능에 영향을 미치게 된다. 이는 데이터 전송 속도, 지연 시간 등과 관련이 있으며, 대개 네트워크 홉 수가 적을수록 더 빠른 데이터 전송이 가능하다. 따라서 네트워크 홉 수를 최소화하고 데이터가 최적의 경로를 따라 이동할 수 있도록 하는 것이 중요하다.

 

  • Stomp는 별도의 프로토콜 없이 빠르게 PUB/SUB 기능을 구현하기에 가장 좋은 선택지
  • 토스증권에서 사용되는 Topic은 크게 두 가지가 있다.
    1. 목적지가 종목 코드
      • 종목의 현재가, 호가, 시장정보등의 정보 전달
    2. 목적지가 사용자
      • 개인자산 갱신 용도

 

실제 유저가 시세를 수신 받기까지의 과정

  1. 라우팅 서버를 통해 연결할 WebSocket 서버의 호스트 정보 획득
    • 획득한 WebSocket 서버로 연결 시도
    • 실패시 Polling 방식 API 호출
  2. WebSocket 서버는 갱신된 커넥션 정보를 라우팅 서버까지 전달
  3. 라우팅 서버는 로드밸런싱을 위해 Redis에서 서버별 커넥션 정보를 관리
  4. 클라이언트는 WebSocket을 통해 화면에 노출되는 종목들에 대해 필요한 토픽을 SUB 요청
  5. WebSocket 서버는 거래소→Kafka를 통해 시세 정보를 전달받아 각 종목을 구독하고 있는 클라이언트로 시세정보 전달

 

사용자별 자산 정보를 갱신하는 과정

  • 자산정보 갱신 과정은 시세 수신 과정과는 조금 다르다.
  • 실제 갱신된 자산정보를 WebSocket을 통해 직접 전달하고 있지는 않고 자산 정보의 갱신 신호를 주는 방식으로 활용하고 있다.
  1. 초기 연결 과정은 동일
  2. 이후 핸드쉐이크 과정에서 사용자 ID 획득
  3. ID를 이용하여 사용자별 접속 서버 정보를 Redis에서 관리
  4. 자산정보 변경 발생 시 라우팅서버에 이벤트 전달
  5. 라우팅 서버는 사용자별 접속 정보를 기준으로 실제 사용자가 연결된 WebSocket 서버에 해당 정보 포워딩
  6. WebSocket 서버는 해당 사용자 자산정보 갱신 지시
  7. 사용자는 자산 조회 API를 통해서 최식 갱신된 자산정보 조회 가능

 

Latency 최적화

  • Kafka 활용하면서 latency 최적화가 필요하게 됨
  • latency 개선을 위해 설정값으로 튜닝할 수 있는 요소는
    1. Compression Type : 압축 알고리즘 효율과 데이터 성격이 결정
    2. Acks : 안정적인 데이터 저장 여부와 성능 trade-off
  • 1KB의 메시지로 송수신 테스트하면서확인한 결과
    1. Compression Type : lz4
    2. Acks : 1
  • 이렇게 설정하고 적절히 파티션 수 조절한 결과 거래소 수신 후 WebSocket 서버 송신까지의 평균 latency를 최적화할 수 있었음.

 


 

이렇게 실시간 시세 기능을 구현하여, 토스증권 런칭 시 적용하였다고 한다.

이 뒤에는 런칭 이후에 겪었던 가장 기억에 남는 이슈 4가지를 소개해 주셨는데, 안정적으로 서비스를 제공하는 것의 어려움을 간접적으로나마 체감 할 수 있었다.

사용자가 몰려 엄청난 양의 트래픽이 몰림으로써 발생하는 Connection 지연, Connection Leak 등의 문제를 해결하는 과정과 서비스 지연, Scale Out 어려움 등의 수많은 문제를 해결하는 과정을 생생히 들을 수 있었는데, 역시 모르는 개념이 줄줄이 등장해서 ChatGPT의 힘을 빌릴 수 밖에 없었다. (많이)

내가 손가락으로 편하게 TQQQ/SQQQ 홀짝놀이를 하고 있는 동안 토스증권 서버 개발자 분들은 조금이나마 더 좋은 UX를 제공하기 위해 이런 노력을 기울이고 계셨다니 감사하면서도 금융권 백엔드에 대한 관심이 더욱 커지게 되었다. 역량을 길러 언젠가는 선배님들과 함께 서비스 개선을 위한 프로젝트에 기여하고 싶다.

위의 이슈 4가지에 대한 내용은 시험기간이 지나면 포스팅 해보려고 한다.

'Finance' 카테고리의 다른 글

미래에셋증권 MTS M-STOCK 사용후기  (0) 2023.03.10
미래에셋금융서비스 TAMS 9기 후기  (0) 2023.03.06