요즘 구독 테이블 설계를 하고 있다.
이미 만들어져있는 구독 서비스를 유지보수 해본 적은 있지만 구독 테이블을 직접 설계하는건 처음이다.
이 과정에서 동료와 의견 차이가 있어서 그 과정을 기록하고자 한다.
총 2가지 논제가 있었다.
주제 1) 구독 테이블 설계 - 한 줄로 관리할 것인가, 매 월 새로운 행을 추가할 것인가?
구독 시스템을 설계하는 과정에서 동료 개발자와 구독 테이블 관리 방식에 대해 의견 차이가 있었다.
📌 나의 주장 - 한 개의 row 를 유지하며 갱신하는 방식

- 유저가 특정 플랜을 구독하면 subscription 테이블에 한 개의 row 가 INSERT 됨
- 매달 결제가 이루어질 때 currentPeriodStart, currentPeriodEnd 를 업데이트하여 현재 구독 기간을 관리
- 결제 내역 테이블 (paymentHistory) 을 subscription 과 1:N 관계로 두어, 매달 결제가 이루어질 때 새로운 결제 내역을 INSERT 함
📌 동료의 주장 - 매월 새로운 row 를 INSERT 하는 방식
- 매월 구독이 갱신될 때마다 새로운 row 를 INSERT 하며 각 row 는 특정 월의 구독을 나타냄
나는 동료의 주장이 "데이터 중복" 의 특성을 가지고 있기 때문에 반대했다.
동일한 구독 정보가 매월 새로운 row 로 삽입되므로 데이터가 불필요하게 많아질 수 있으며
데이터 조회 패턴의 빈도 측면에서 보자면 사용자가 "구독 이력" 을 보는 화면은 존재하지 않고
"현재 활성화된 구독 정보 (ex. Premium 이용 중입니다)" 를 조회하는 화면만 있기 때문에 나의 주장이 맞다고 판단했다.
구독 이력을 보고 싶은 케이스가 생긴다면 결제 내역 테이블이 존재하므로 충분히 쿼리를 통해 뽑아낼 수 있다고 판단했다.
그래서 나의 주장을 채택하기로 했다.
주제 2 ) 구독 플랜에 대한 무료체험 정보는 어디에 기록해야 할까?
보통 요금제가 있는 서비스들을 보면 구독 플랜에 7일 무료체험이 존재한다.
나는 이 무료체험 정보를 subscription 테이블에 넣어야한다고 판단했다.
📌 나의 주장: subscription 테이블에 trialStart, trialEnd 컬럼 추가

나는 무료체험 정보를 구독 테이블에 직접 추가해야 한다고 판단했다.
기존 구독 정보와 무료 체험 기간을 같은 row 에서 관리할 수 있어 조회가 용이하기 때문이다.
📌 동료의 주장: 무료체험 정보를 별도 테이블로 분리해야 한다

동료는 무료체험 정보가 subscription 테이블에 포함되는 것이 낭비라고 주장했다.
무료체험을 제공하지 않는 플랜의 경우, trialStart, trialEnd 컬럼이 의미 없이 NULL 이 되어 공간 낭비가 발생할 수 있고
nullable 필드가 생기면 로직에서 매번 타입을 체크 해야 하므로 코드 복잡성이 증가하기 때문이다.
결론적으로 동료의 방식을 채택하기로 했다.
조회 패턴을 고려했을 때, 유저의 무료체험 여부를 빠르게 조회해야 할 일이 많다.
내가 주장했던 subscription 테이블에 직접 저장하는 방식과 trialHistory 테이블로 분리하는 방식 모두 조회 속도에는 큰 차이가 없었다.
따라서, 코드 복잡성을 그나마 줄일 수 있는 trialHistory 테이블을 별도로 두는 방식이 더 적합하다고 판단했다.