결제대행사 약관 동의 추가
목차
결제대행사 약관 동의는 단순한 체크박스 하나를 붙이는 작업처럼 보이지만, 실제론 꽤 여러 레이어를 건드린다. 서비스 이용약관과 외부 PG 약관을 동시에 처리하면서 동의 이력을 DB에 남겨야 하고, 재가입 제한 정책까지 회원가입 흐름 안에 녹여야 했다. 작업 규모 자체는 크지 않았는데 체크포인트가 생각보다 많았던 케이스.
왜 이게 필요했나
이커머스 플랫폼에서 결제 기능을 붙일 때 PG사는 자사 약관 동의를 별도로 요구한다. 서비스 약관만 받으면 되는 게 아니라, "PG사 이용약관에도 동의했음"을 기록해야 하는 거다. 이게 법적 요건이기도 하고, 나중에 결제 관련 분쟁이 생겼을 때 "동의 안 했다"는 주장을 차단하는 수단이기도 하다.
동의 이력을 단순히 플래그 하나(agreed = Y)로 관리하는 시스템이 종종 있는데, 그건 운영에서 문제가 생겼을 때 쓸모가 없다. 언제, 어떤 버전의 약관에, 어떤 경로로 동의했는지가 필요하다. 그래서 이번에 동의 이력 테이블에 약관 종류, 동의 일시, 가입 요청 IP를 포함해 저장하도록 처리했다.
재가입 제한 기간은 별개 정책이긴 하지만 가입 흐름에서 같은 지점에 걸린다. 탈퇴 후 일정 기간 동안 동일 계정으로 재가입을 막는 이 정책은 플랫폼 어뷰징 방지 목적인데, 기간을 코드에 하드코딩하면 정책이 바뀔 때마다 배포가 필요해진다. 관리자 시스템 설정으로 빼서 운영 중에 바꿀 수 있게 한 것도 이번 작업에 포함됐다.
처리 흐름과 구현 맥락
가입 요청이 들어왔을 때의 흐름은 이렇다.
회원가입 요청
→ 재가입 제한 기간 체크
→ 약관 동의 확인 (서비스 약관 + PG 약관)
→ 회원 생성
→ 동의 이력 저장
Spring MVC + MyBatis 구조라 내부 클래스는 요청 처리와 화면 제어를 담당하고, 쿼리는 SQL XML에서 관리한다. JSP가 뷰 레이어다. 이 스택에서 신경 쓴 지점은 크게 세 가지였다.
트랜잭션 범위. 회원 생성과 동의 이력 저장은 하나의 트랜잭션 안에 묶여야 한다. 회원은 만들어졌는데 동의 이력이 롤백되거나, 반대로 이력만 남고 회원 생성이 실패하는 상황이 생기면 데이터 정합성이 망가진다. @Transactional 범위를 Service 레이어에 명확히 설정하고, 동의 이력 Insert 실패 시 전체가 롤백되도록 했다.
예외 처리 전략. RuntimeException을 그냥 전파할지, 잡아서 응답 포맷으로 변환할지는 항상 고민이 된다. 여기서는 도메인 예외(DuplicateJoinRestrictionException 같은 것)는 잡아서 사용자 메시지로 변환하고, 예상치 못한 인프라 오류는 전파해서 글로벌 핸들러가 처리하도록 구분했다. 두 케이스를 같은 catch 블록에 뭉개면 운영에서 디버깅이 힘들어진다.
로그. 가입 요청 들어올 때 계정 식별자, 약관 동의 항목, 재가입 제한 체크 결과를 INFO로 남겼다. 운영 환경에서 특정 유저의 가입 실패 이슈가 들어왔을 때 로그만 봐도 어느 단계에서 걸렸는지 바로 파악할 수 있어야 한다.
관리자 설정과 0 값 처리
재가입 제한 기간을 시스템 설정으로 뺐을 때 주의할 부분이 있다. 0을 어떻게 해석할 거냐는 거다.
| 설정값 | 동작 |
|---|---|
null 또는 미설정 |
기본값 적용 (또는 무제한으로 처리) |
0 |
제한 없음, 즉시 재가입 가능 |
N (양수) |
탈퇴 후 N일 동안 재가입 불가 |
null과 0을 같은 의미로 처리하면 나중에 운영 측에서 "제한 없음으로 바꿨는데 왜 안 되냐"는 문의가 들어올 수 있다. 명시적으로 0 = 제한 없음으로 정의하고, 쿼리도 그에 맞게 분기했다. 관리자 화면에서 값을 변경하면 캐시 없이 즉시 적용되는 구조라 배포 없이 정책 전환이 가능하다.
챙긴 것들 요약
- 트랜잭션: 회원 생성 + 동의 이력 저장을 단일 트랜잭션으로 묶음
- 예외 분리: 도메인 예외는 응답 변환, 인프라 예외는 전파
- 로그: 가입 흐름 주요 입출력값 INFO 수준으로 기록
- 설정값 의미 명확화:
0 = 제한 없음을 코드와 UI 양쪽에서 일치시킴 - 코드 리뷰: 기존 가입 흐름에 영향이 없는지 추적
작업 후 로컬 기동 확인 → 개발 DB 반영 → 배포 순서로 처리했다. 이 순서가 기본이지만, 특히 DB 스키마 변경이 포함될 때는 마이그레이션 스크립트 순서를 배포보다 먼저 맞추는 게 중요하다. 이번엔 테이블 추가가 있었기 때문에 그 부분을 먼저 처리하고 코드를 올렸다.
작은 수정처럼 보이는 작업일수록 흐름의 어디에 끼어드는지 명확히 해두는 게 낫다. 나중에 다른 사람이 가입 흐름을 건드릴 때 "약관 동의 이력 저장이 여기서 되고 있구나"를 바로 알 수 있도록.
댓글 0
첫 댓글 달아줘.