게임 실시간 입력처리할 때 rank를 알려주기 위해서 score를 기준으로 user_id를 정렬해서 보내줘야 함

{
  "event": "game:player:realtime",
  "data": {
    "highest_score": "100",
    "average_score": "32.56",
    "ranks": ["uuid-01", "uuid-04", "uuid-03", "uuid-02"] 
  }
}

기존

room:roomId:game:players 내에 각 플레이어들이 Hash로 저장되어 있고, 거기에 메타데이터로 score가 저장되어있는 형태

score 정렬을 위해 매 브로드캐스트마다 모든 키를 가져와 정렬해야 해서 I/O + CPU 비용이 증가

image.png

📍 점수 정렬/조회 빈도가 높으므로 ZSET으로 점수만 분리하도록 결정

메타데이터는 Hash에 남김

📍 Redis ZSet의 기본 구조

Redis에서 ZSet은 각 멤버(Member)마다 Score 라는 실수 값을 연결해둔 집합

📍 점수 정렬은 scores (ZSet 사용)

점수 정렬을 Redis ZSET으로 옮겨서 실시간 랭킹을 따로 정렬 없이 바로 가져오도록 함

flowchart LR
    %% 유저/클라이언트 영역
    subgraph UserSide [Client Side]
        A[User/Client]
    end

    %% 서버 영역
    subgraph ServerSide [Application Layer]
        B[NestJS Server]
    end

    %% 실시간 연산 영역 (Redis)
    subgraph VolatileLayer [Real-time Engine]
        C[(Redis ZSet)]
    end

    %% 영속성 저장 영역 (MySQL)
    subgraph PersistentLayer [Database Layer]
        D[(MySQL)]
    end

    %% 데이터 흐름 정의
    A -- "1. 점수 획득 이벤트" --> B
    B -- "2. zIncrBy (실시간 가산)" --> C
    C -. "3. zRange (O(log N) 조회)" .-> B
    B -- "4. 300ms 주기 랭킹 방송" --> A
    
    B -- "5. 최종 결과 저장 
    (Post-game)" --> D

    %% 스타일링
    style C fill:#f96,stroke:#333,stroke-width:2px
    style D fill:#69f,stroke:#333,stroke-width:2px

<aside>

node-rediszAdd 함수에 객체 배열을 전달할 때, score 필드를 점수로, value 필드를 **멤버(데이터)**로 인식하도록 설계되어 있음

명시적으로 점수순으로 정렬하라고 정해주지 않아도, Redis 엔진 자체가 ZSet에 들어오는 데이터를 항상 Score 기준으로 오름차순 정렬해서 보관하게 됨

</aside>