여러 서비스가 공유하는 캐시에서 설정 데이터를 주기적으로 조회하는 구조가 있다. 전량 갱신 방식에서는 데이터 변경 여부와 관계없이 매 주기마다 전체 데이터를 전송한다. 변경이 드문 데이터일수록 낭비가 크다.

변경분만 갱신하면 네트워크 전송량을 데이터 변경 빈도에 비례하도록 줄일 수 있다.

전량 갱신

전량 갱신은 구현이 단순하다. 주기마다 전체 데이터를 가져와서 로컬 상태를 교체하면 된다. 변경 감지 로직이 필요 없다.

그런데 이 방식의 네트워크 전송량은 데이터 크기 × 소비자 수 × 갱신 빈도로 결정된다. 데이터가 실제로 변경되었는지와 무관하다. 소비자 수가 늘거나 데이터 크기가 커지면 전송량이 선형으로 증가한다.

CPU와 메모리는 여유로운데 네트워크 전송량만 한계에 도달하는 상황이 생길 수 있다. 이 경우 인스턴스를 스케일 업해야 하는데, CPU와 메모리는 필요 없는 스케일 업이다.

데이터 분리

변경분 갱신을 적용하려면 먼저 데이터를 갱신 빈도별로 분리해야 한다.

설정 데이터. 엔티티의 메타 정보, 조건, 규칙 같은 데이터는 관리자가 수정할 때만 변경된다. 갱신 빈도가 낮다.

실시간 데이터. 카운터, 소진 현황 같은 데이터는 요청마다 갱신된다. 항상 최신 상태를 유지해야 한다. 변경분 갱신 대상이 아니다.

설정 데이터만 변경분 갱신을 적용하고, 실시간 데이터는 기존대로 매 주기 갱신한다.

중복 제거

하나의 엔티티에 여러 하위 엔티티가 포함되어 있고, 하위 엔티티가 다른 상위 엔티티에서도 참조되는 구조라면 중복이 발생할 수 있다. 하위 엔티티를 별도로 관리하면 저장 공간과 전송량 모두 줄어든다.

변경 감지 전략

데이터 비교

배치가 원본(DB)에서 데이터를 가져온 뒤 캐시에 저장된 데이터와 직접 비교한다. 내용이 다른 항목만 캐시에 쓴다.

장점은 정확하다는 것이다. 원본과 캐시의 불일치를 놓치지 않는다. 단점은 비교를 위해 캐시에서 기존 데이터를 읽어야 하므로 읽기 비용이 추가된다.

Timestamp 기반

각 항목의 변경 시점을 기록해둔다. Sorted Set의 score로 timestamp를 저장하면, 특정 시점 이후 변경된 항목만 범위 조회로 가져올 수 있다.

flowchart LR
    subgraph Write ["쓰기"]
        BATCH["배치"] --> UPD["변경된 항목 캐시 갱신"]
        UPD --> TS["Sorted Set에
timestamp 기록"] end subgraph Read ["읽기"] SVC["서비스"] --> RANGE["마지막 갱신 이후
timestamp 범위 조회"] RANGE --> CHANGED["변경된 항목 ID 목록"] CHANGED --> GET["해당 항목만 조회"] end

읽는 쪽에서 마지막으로 조회한 시점을 기억하고 있으면, 그 이후에 변경된 항목만 가져올 수 있다. 전량 조회가 범위 조회로 바뀌므로 전송량이 변경 건수에 비례한다.

두 전략을 함께 쓸 수도 있다. 쓰기 경로에서 데이터 비교로 변경 여부를 판단하고, timestamp를 기록한다. 읽기 경로에서 timestamp 범위 조회로 변경분만 가져온다.

Write Path / Read Path

변경분 갱신에서는 쓰기 경로와 읽기 경로를 명확히 분리하는 것이 중요하다.

쓰기 경로는 배치가 담당한다. 원본에서 데이터를 가져오고, 캐시와 비교하고, 변경분만 쓴다. 변경 시점을 기록한다.

읽기 경로는 서비스가 담당한다. 마지막 갱신 이후 변경된 항목만 조회하고, 로컬 상태를 부분 갱신한다. 변경이 없으면 로컬 데이터를 그대로 유지한다.

소비자마다 필요한 데이터 범위가 다를 수 있다. 설정만 필요한 서비스, 설정과 콘텐츠가 모두 필요한 서비스, 실시간 데이터까지 필요한 서비스. 읽기 인터페이스를 소비자별로 분리하면 각 서비스가 필요한 데이터만 조회할 수 있다.

적용 사례

이 패턴은 공유 캐시에서 설정 데이터를 주기적으로 조회하는 구조에서 자주 적용된다.

광고 캠페인 설정. 캠페인 메타 정보, 타겟팅 조건은 변경이 드물지만 여러 서버가 동시에 조회한다. 전량 갱신에서 변경분 갱신으로 전환하면 네트워크 전송량이 크게 줄어든다.

상품 카탈로그. 상품 정보는 등록/수정 시에만 변경된다. 수천 개의 상품을 매 주기 전송하는 대신, 변경된 상품만 갱신하면 효율적이다.

사용자 권한/설정. 권한 변경은 빈도가 낮지만 여러 서비스에서 참조한다. 변경분 갱신이 적합한 구조다.

트레이드오프

변경분 갱신은 전량 갱신 대비 복잡도를 추가한다.

변경 감지 로직, timestamp 관리, 로컬 상태의 부분 갱신 로직이 필요하다. 캐시와 원본의 불일치가 발생했을 때 전량 동기화로 복구하는 메커니즘도 고려해야 한다.

데이터가 작거나 변경이 빈번한 경우에는 전량 갱신이 더 단순하고 충분하다. 네트워크 비용이 실제 병목이 된 시점에서 변경분 갱신으로 전환하는 것이 적절하다.