60 jours sous Live/Snapshot/Cache : trois sauvetages, une trahison, et ce que j'ai changé

개요

기술 블로그는 Live/Snapshot/Cache라는 데이터 저장 규칙을 60일간 적용한 경험을 공유하며, 해당 규칙이 데이터의 일관성을 유지하는 데 기여한 세 번의 사례와 한 번의 실패 사례를 통해 얻은 교훈을 제시한다.

주요 내용

* Live/Snapshot/Cache 규칙: 프로젝트에서 데이터 복제 시 반드시 Live(즉시 읽기), Snapshot(저장 후 불변), Cache(저장 후 갱신 메커니즘 명시) 중 하나로 분류하고, 각 방식에 따른 구현을 강제하는 규칙이 도입되었다.
* 규칙 도입 배경: 과거 montant_total 컬럼에서 발생했던 수치 오류와 같은 문제를 방지하고 데이터 일관성을 확보하기 위해 도입되었다.
* 규칙의 세 가지 성공 사례:
* 첫 번째 (Snapshot): 요금 개편 시 과거 inscriptions.tarif_applique 컬럼을 소급 적용하려는 시도를 Snapshot 규칙에 따라 새로운 이벤트로 처리하여 과거 데이터의 무결성을 보존했다.
* 두 번째 (Cache): 외부 테이블 export 성능 향상을 위해 cours 테이블에 컬럼을 추가하되, 갱신 메커니즘(trigger, GENERATED ALWAYS AS 등)을 명시하지 않은 커밋을 규칙에 따라 반려하여 데이터 불일치를 사전에 방지했다.
* 세 번째 (Live): 재무 분석을 위한 월별 매출 집계 카운터를 저장하는 대신, 성능상 문제가 없어 Live 규칙에 따라 v_cours_recettes_mensuelles 뷰로 처리하여 별도의 갱신 관리 필요성을 제거했다.
* 규칙의 실패 사례 (트레이션): SMS 재등록 토큰 발급 로직(generateTokenForContact 헬퍼)에서 reinscription_tokens 테이블의 used_at 컬럼이 Live 상태임에도 불구하고, Snapshot으로 분류된 다른 컬럼들과 함께 객체 전체를 반환하면서 used_at 상태가 초기화되지 않아 토큰이 이미 사용된 것으로 간주되는 문제가 발생했다.
* 실패로부터의 교훈: 컬럼 단위의 분류 규칙만으로는 객체 단위의 비일관성을 막을 수 없으며, Snapshot과 Live 상태가 혼합된 객체를 다룰 때는 동일 트랜잭션 내에서 Snapshot은 유지하고 Live 상태는 초기화하는 hybrid-snapshot-live-reset 패턴이 필요하다는 것을 인지했다.
* 규칙의 확장 및 적용: hybrid-snapshot-live-reset 패턴을 프로젝트 단위의 확장 규칙으로 도입하여, 기존 R6 규칙이 커버하지 못했던 객체 동적 상태 변화에 대한 처리 방안을 마련했다.

시사점

Live/Snapshot/Cache 규칙은 데이터 일관성 유지에 효과적이었으나, 객체 단위의 상태 변화까지 고려한 hybrid-snapshot-live-reset 확장 규칙의 필요성을 보여주며, 규칙 자체의 성공률보다는 예상치 못한 상황에 대한 유연한 확장 가능성이 중요함을 시사한다.

원문 읽기 →
원문을 불러오는 중...

댓글

GitHub Discussions