표종덕
웹 서비스 · 2026. 11. 3. 업데이트완성형 플랫폼

GiftMall

백화점 상품권을 사고, 선물하고, 매입·정산까지 한곳에서 처리하는 상품권 플랫폼

  • next.js
  • react
  • spring

왜 만들었나요

백화점 상품권을 팔고, 제휴업체와 주고받고, 다시 매입하는 사업을 준비하는 곳의 의뢰로 시작했어요.

이런 사업은 보통 주문은 쇼핑몰에서, 선물·매입은 메신저와 엑셀로, 송금은 은행 앱에서 따로 처리해요.
그러다 보면 같은 상품권이 두 번 쓰이거나, PIN이 대화방에 그대로 남거나, 누구에게 얼마를 보냈는지 맞춰 보기 어려워져요.

그래서 구매부터 선물, 매입, 지급 기록까지 한 흐름으로 이어지고,
돈과 PIN이 오가는 순간마다 안전장치가 걸려 있는 플랫폼을 만들었어요.

주요 기능

고객

  • 휴대폰 본인인증·1원 계좌인증으로 가입하고, 가맹점 코드로 소속 업체와 연결
  • 백화점·권종·수량을 골라 주문하고 결제
  • 내 상품권함에서 백화점별로 보관하고, 사용하기를 누르면 처리가 확인된 뒤에 PIN 공개
  • 사용 전 상품권을 제휴업체에 선물하고 진행 상태 확인

제휴업체

  • 선물받은 상품권 확인, 여러 장 한 번에 매각 신청
  • 정산 요약과 지급 내역, 소속 회원 목록 엑셀 다운로드
  • 정산 계좌 등록, 텔레그램으로 선물 도착·계좌 변경 알림

운영자

  • 주문·발급 현황과 결과 확인이 필요한 건 모아 보기
  • 상품·판매가·할인 기간·매입가 관리 (할인 상품은 홈에 자동 노출)
  • 매각 신청 검토·보류·반려, 직접 송금한 뒤 지급 기록
  • 제휴업체 계정·가입 코드 발급, 운영자 2단계 인증(OTP)

기술과 구조

  • 백엔드: Java 21, Spring Boot, MyBatis, MySQL 8.4, Flyway
  • 프론트엔드: Next.js, React, TypeScript (PC·모바일 반응형, 라이트·다크)
  • 배포: Docker Compose, nginx, Let's Encrypt, 매일 암호화 백업

구조에서 가장 신경 쓴 부분은 이렇게 세 가지예요.

  • 상태가 바뀌는 곳은 한 군데만: 상품권·주문·매각 상태는 정해진 서비스만 바꿀 수 있고, 항상 "지금 상태가 이것일 때만 바꾼다"는 조건으로 반영해요. 동시에 눌러도 한 번만 처리돼요.
  • 응답이 불분명하면 다시 보내지 않기: 외부 업체 응답이 끊기면 같은 요청을 또 보내지 않고 '확인 필요'로 둔 뒤, 결과를 조회해서 확정해요.
  • 외부 연동은 갈아 끼울 수 있게: PG·쿠폰사·본인인증은 인터페이스 뒤에 두어서, 업체가 정해지면 구현만 바꾸면 돼요.

자동 테스트는 1,900개가 넘고, 권한·CSRF·민감 정보 노출을 API 목록과 대조해 검사해요.

배운 점

  • "처리 중"이 가장 어렵다: 성공과 실패보다, 응답이 오지 않은 상태를 어떻게 다룰지가 설계의 대부분이었어요. 늦게 온 응답이 새 요청에 섞이지 않게 막는 것까지 챙겨야 했어요.
  • 보안은 기능이 아니라 기본값: 소유자 조건, PIN 암호화, 로그 가리기를 처음부터 규칙으로 정해 두니, 기능이 늘어나도 빠지는 곳이 없었어요.
  • 결제는 기술보다 심사가 먼저: 상품권을 팔고 다시 매입하는 구조는 PG 심사가 까다로워요. 다음에는 개발 전에 PG사 상담부터 받을 거예요.
  • AI와 함께 개발하기: 계획 → 구현 → 검증 → 별도 리뷰 순서를 정해 두고 AI 코딩 도구와 함께 만들었어요. 규칙을 문서로 명확히 적을수록 결과물이 안정적이었어요.

표종덕의 다른 프로젝트