Skip to content

redis를 이용한 한국투자 Open API 세션 관리

JIN edited this page Dec 4, 2024 · 2 revisions

🧑🏻 작성자

⚙️ Web BE ⚙️ Web BE
김진 이시은

💣 문제 상황

현재 한국투자 Open API에서 여러 개의 세션을 이용하기 위해 ip hash 기반 로드 밸런서를 이용 중이다.

아래 이미지는 우리 서버에서 여러 명의 유저가 접속했을 때 발생하는 상황이다.

image

image

image

개인 이용자이기 때문에 세션 내에서 최대 41건까지 이벤트가 구독이 가능하다는 단점을 보완하기 위해 로드 밸런서를 도입했지만, 위 그림처럼 여러 세션에서 동일한 종목을 구독하게 되면 우리의 취지와 맞지 않기에 해당 문제를 해결하기로 했다.

✨ 해결 과정

Redis를 이용해 특정 세션에서 특정 종목 코드를 구독하고 있다면, 다른 세션에서는 해당 종목 코드를 구독하지 않도록 하여 한 세션당 사용하는 이벤트를 절약하려고 한다.

첫 구상은 다음과 같다.

image

특정 종목 코드에 대해서 한 서버가 구독을 시작한다면, 해당 종목 코드에 대해 publish한다.

그 이후, 다른 서버가 같은 종목 코드에 대해 요청하면 subscribe를 통해 값을 받아오게 된다. 만약 이미 구독 중인 종목코드가 아닌 다른 코드를 요청하면, 해당 서버에서 publish 할 수 있도록 구상했다.

이 과정에서 subscribe를 했을 때 어떻게 실시간으로 값을 받아올 지에 대한 논의했다.

1번 아이디어

FE - BE 사이의 연결에서 socket을 사용하는 것에서 착안한 아이디어이다.

특정 종목 코드를 pub할 때, 해당 종목에 대한 이벤트도 생성하는 것이다.

socket.emit(stock/${stockCode}) 와 같은 형태로 이벤트를 생성한 후, 다른 서버에서 sub할 때 해당 이벤트를 socket.on(stock/${stockCode}) 코드를 통해 수신하는 방식이다.

그러나 우리는 이미 공유된 Redis를 사용 중이어서 굳이 서버 간의 통신에 WebSocket을 사용해야 하나싶은 부분이 있어서 다른 아이디어를 생각해보기로 했다.

2번 아이디어

redis의 pub/sub을 활용해보기 위해 생각한 아이디어이다.

대략적인 흐름은 다음과 같다.

어떤 종목에 대해 구독 요청이 들어오면, 그 종목을 구독하고 있는 서버를 찾아 해당 서버로 실시간 데이터를 보내달라는 publish 메시지를 보낸다. 실제 구독 중인 서버는 실시간 데이터 요청 publish 메시지를 받고 데이터를 처리한 뒤, 요청 publish를 보낸 서버를 향해 클라이언트로 데이터를 보내라는 publish 메시지를 보낸다. 요청 publish를 보낸 서버는 해당 메시지를 받으면, socket.io로 클라이언트에게 데이터를 전달한다.

그러나, 이러한 흐름은 너무 복잡하고 pub/sub 과정이 빈번하게 일어나 오버헤드가 있을 것으로 우려되어 다른 아이디어를 생각해보기로 했다.

최종 아이디어

1번 아이디어에서 socket 연결을 redis pub/sub으로 변경한 아이디어이다.

서버2에서 이미 구독 중인 종목에 대해 서버1로 구독 요청이 발생하면 아래와 같이 동작하도록 구현하였다.

sequenceDiagram

participant C as Client
participant S1 as Server 1
participant S2 as Server 2 (삼성전자 구독중)
participant R as Redis

note over S2: 체결가 받아서 항상 publish

C ->> S1: 삼성전자 구독 요청
S1 ->> R: 다른 서버에 구독이 되어 있는지 확인
R -->> S1: 다른 서버에 구독 이미 존재
S1 ->> R: 삼성전자 subscribe
R -->> S1: 삼성전자 체결가
S1 -->> C: socket.io로 체결가 전송

Loading

아래는 위 흐름도에 대한 간단한 설명이다.

  1. 서버2는 삼성전자를 실제 구독함과 동시에 삼성전자에 대한 모든 실시간 데이터를 Redis로 publish한다.
  2. 클라이언트가 서버1에 삼성전자에 대한 구독 요청을 보내면 Redis에 저장된 connection 정보를 통해 다른 서버에 삼성전자가 구독되어 있는지 확인한다.
  3. 다른 서버에 구독이 이미 존재한다는 사실을 확인하면, 서버1은 Redis로 삼성전자에 대한 subscribe를 진행한다.
  4. 서버2는 삼성전자의 실시간 데이터를 publish 중이며, 서버1이 삼성전자를 subscribe 중이기 때문에 서버1에서 삼성전자의 실시간 데이터를 받아올 수 있다.

해당 방식을 통해 비교적 간단하고 오버헤드도 적은 코드를 구현할 수 있었다.

👓 참고 자료

📜 개발 일지

⚠️ 트러블 슈팅

❗ 규칙

🗒️ 기록

기획
회의록
데일리스크럼
그룹 멘토링
그룹 회고

😲 개별 멘토링

고동우
김진
서산
이시은
박진명
Clone this wiki locally