포인트 시스템으로 배우는 SQL 로드맵: 적립·차감·만료를 끝까지 완성하는 20단계 계획

SQL을 “문법”으로만 배우면, 실제 서비스에 붙일 때 어디서부터 막히는 경우가 많습니다. 반대로 작은 기능을 끝까지 완성해 보면 SELECT 하나를 배우더라도 “왜 이 쿼리가 필요한지”가 분명해집니다. 이 연재는 포인트(적립/사용/만료/취소) 시스템을 목표로, SQL 기초를 실전 감각으로 쌓아가는 로드맵입니다.

왜 하필 ‘포인트 시스템’인가

포인트는 단순히 숫자 하나를 더하고 빼는 문제가 아닙니다. 운영에서 반드시 부딪히는 이슈가 다 들어 있습니다.

  • 중복 적립을 어떻게 막을까?
  • 동시에 여러 요청이 들어오면 잔액이 꼬이지 않을까?
  • 만료(Expire)는 언제/어떤 기준으로 처리할까?
  • 사용 취소환불이 생기면 어떻게 되돌릴까?
  • 데이터가 쌓이면 조회 성능은 어떻게 유지할까?

결국 이 주제 하나로 테이블 설계, 쿼리 작성, 인덱스, 트랜잭션, 운영 검증까지 자연스럽게 연결됩니다.

이번 연재에서 만들 결과물

연재가 끝나면 아래를 스스로 설명하고 구현할 수 있는 상태가 목표입니다.

  • 포인트 히스토리 기반으로 잔액과 내역을 정확하게 조회한다
  • 중복/오류를 막는 제약조건과 키 설계를 적용한다
  • 동시성에서 안전하게 적립/차감을 처리한다(트랜잭션/잠금)
  • 만료 배치 쿼리를 만들고 운영 점검 쿼리로 검증한다
  • 성능을 위해 인덱스와 조회 패턴을 설계한다

포인트 시스템 최소 모델(처음엔 이것만으로 충분)

포인트는 “현재 잔액”보다 왜 그렇게 되었는지(내역)가 더 중요합니다. 그래서 기본은 ‘히스토리(원장)’ 테이블입니다.

-- 예시: point_history (가장 단순한 형태) -- DBMS에 따라 타입/문법은 조금씩 다를 수 있습니다. CREATE TABLE point_history ( id BIGINT PRIMARY KEY AUTO_INCREMENT, uid CHAR(36) NOT NULL, -- 사용자 식별자(UUID 가정) point_type ENUM('PAID','FREE') NOT NULL, -- 유료/무료 구분 action_type ENUM('CHARGE','USE','REFUND','USE_CANCEL','EXPIRE','ADJUST') NOT NULL, amount INT NOT NULL, -- +적립, -차감 등 정책에 따라 ref_id VARCHAR(64) NULL, -- 주문번호/이벤트ID 등 “중복방지” 근거 created_at DATETIME NOT NULL, INDEX idx_uid_created (uid, created_at), INDEX idx_ref (ref_id) );

위 설계는 “정답”이라기보다 학습을 위한 최소 출발점입니다. 연재를 진행하면서 중복 방지, 만료 처리, 사용 우선순위(FIFO 등), 잔액 테이블 분리 여부를 단계적으로 확장합니다.

20단계 로드맵이 어떻게 진행되는가

글이 길어지지 않도록 각 글은 “하나의 문제를 해결하고 산출물을 남기는 방식”으로 구성합니다. 아래는 큰 흐름입니다.

구간 핵심 학습 산출물
1~6 테이블/타입/키/제약조건의 감각 최소 스키마 + 중복 방지 기준 정리
7~13 조회(SELECT)와 집계, JOIN, 서브쿼리 잔액/기간별 리포트/이상거래 점검 쿼리
14~16 트랜잭션/잠금/동시성 + 잔액관리 전략 안전한 적립/차감 처리 패턴 2가지
17~20 만료/취소/환불 + 운영 검증/성능 만료 배치 + 테스트/점검/튜닝 체크리스트

처음부터 흔히 하는 실수 5가지(이 연재가 피하려는 것)

  1. 잔액만 저장하고 내역을 안 남겨서 정산/분쟁 시 추적이 불가능해짐
  2. 중복 적립 방지 기준(ref_id 같은 근거)이 없어 동일 요청이 두 번 들어오면 사고가 남
  3. 동시성을 고려하지 않아 “잔액이 마이너스”가 되는 순간이 생김
  4. 만료를 “그때그때” 처리하다가 누락되어 부채 포인트가 쌓임
  5. 인덱스 없이 로그가 쌓여 조회가 느려지고 결국 기능이 꺼짐

다음 글 예고: “포인트 시스템에 필요한 최소 테이블 목록”부터 잡는다

다음 글에서는 포인트 시스템을 구성하는 테이블을 최소 단위로 쪼개고, “어떤 컬럼이 왜 필요한지”를 예시 데이터로 확인합니다. SQL을 배우는 과정에서 가장 중요한 건, 문법 자체보다 데이터가 어떤 형태로 쌓이고 어떤 질문을 받는지를 이해하는 것입니다.

연재를 따라오면서 그대로 DB에 실행해 볼 수 있도록, 각 글마다 예시 데이터(INSERT)검증 쿼리를 함께 제공합니다.

댓글

이 블로그의 인기 게시물

SELECT 기초로 “내 포인트 잔액/내역” 조회하기: 문법보다 ‘질문’을 먼저 만든다

포인트 시스템에 필요한 최소 테이블 목록 설계: “나중에 고치기 어려운 것”부터 잡는다