결제 테이블 누락으로 생긴 스키마와 라이브 DB 불일치 해소
목차
한 줄 요약: 설계 문서(GAME_DESIGN)에는 있지만 schema.sql에는 빠진 purchase 테이블을 추가해 라이브 DB와의 불일치를 메웠다.
갭이 생기는 이유
이 작업은 단순 테이블 추가처럼 보이지만, 실은 설계와 구현이 어떻게 벌어지는지를 보여주는 사례였다. GAME_DESIGN에 purchase 테이블이 명시되어 있었는데, 정작 schema.sql(우리가 새 환경을 셋업할 때 참조하는 원본 스키마)에는 빠져 있었다.
이런 갭이 발생하는 보통의 시나리오:
- 초기 마이그레이션: 레거시 DB에서 테이블이 있는데, 새 버전을 위한 스키마 설정 시 누락
- 후발 개발: 프로덕션 DB에서 직접 테이블을 생성했지만, schema.sql 업데이트를 미루다가 결국 깜빡함
- 문서 선행 설계: GAME_DESIGN에서 테이블을 정의했지만, 개발팀이 구현할 때 별도로 추가하지 않은 케이스
- 다중 팀 개발: 다른 팀원이 추가한 테이블이 메인 리포 스키마에 반영되지 않음
| 상황 | 위험도 | 발견 난이도 |
|---|---|---|
| 라이브엔 있는데 schema.sql엔 없음 | 높음 | 낮음 (운영 중 문제 발생) |
| schema.sql엔 있는데 라이브엔 없음 | 중간 | 높음 (배포 시점까지 모를 수 있음) |
| 칼럼 정의만 미묘하게 다름 | 낮음 (작동하지만) | 매우 높음 (숨어서 버그 원인이 됨) |
왜 이걸 지금 수정했나
purchase 테이블은 결제 플랫폼 도메인에서 핵심 엔티티다. 새로운 팀원이 온보딩될 때, schema.sql을 읽으면 purchase 테이블이 없어 보인다. 그러다가 라이브 쿼리나 마이그레이션 스크립트에서 purchase를 참조하는 코드를 만나면 "어? 이게 어디서 온 거지?"라는 혼란이 생긴다.
또한 DB 복제/복원 작업 시 문제가 될 수 있다:
- schema.sql을 기준으로 새 스테이징 환경을 만들면 purchase가 없음
- 테스트 코드가 purchase 데이터를 기대하면 실패
- 마이그레이션이 손상될 가능성
어떻게 처리했는가
-- GAME_DESIGN에 정의된 purchase 테이블 구조를
-- schema.sql에 정식으로 추가
CREATE TABLE purchase (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
user_id BIGINT NOT NULL,
game_id BIGINT NOT NULL,
purchased_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
amount INT NOT NULL,
-- 다른 칼럼들...
FOREIGN KEY (user_id) REFERENCES users(id),
FOREIGN KEY (game_id) REFERENCES games(id)
);
라이브 DB와 schema.sql을 비교해서 누락된 부분을 찾아내고, GAME_DESIGN과도 대조해 정의를 정확하게 가져왔다. 이 테이블은 이미 프로덕션에서 구동 중이었으므로 마이그레이션은 필요 없고, schema 정의만 코드베이스에 기록하는 작업이었다.
배운 것들
1. 설계 문서와 구현 코드의 간극은 자동화로는 줄일 수 없다
누군가 수동으로라도 주기적으로 점검해야 한다. 우리 팀에선 분기별 schema audit을 추가했다.
2. schema.sql의 '원본성'을 지키는 게 중요하다
schema.sql이 프로덕션 DB의 진실의 원천(source of truth)이 되려면, 라이브 변경 후에도 반드시 여기를 업데이트하는 문화가 필요하다.
3. 온보딩 관점에서 설계 문서와 코드는 일치해야 한다
새로운 팀원이 GAME_DESIGN을 읽었는데 schema.sql에서 그 테이블이 없으면, 신뢰도가 떨어진다.
이런 작은 갭들이 모이면 결국 더 큰 리스크가 된다. 이번 수정은 단순 테이블 추가지만, "설계와 현실을 어떻게 맞춰갈 것인가"라는 더 큰 질문을 던져줬다.
🛒 이 글과 어울리는 추천 상품
*위 링크는 쿠팡파트너스 활동의 일환이며, 일정액의 수수료를 제공받을 수 있습니다.
댓글 0
첫 댓글 달아줘.