
KOA 파티 신청 플랫폼 - koa.asia
KOA라는 기업을 소개하고, 파티를 신청할 수 있는 'KOA'의 웹서비스 개발 프로젝트를 소개합니다.
목차
- 프로젝트 소개
- 트러블슈팅
- 성과
프로젝트 소개
KOA는 한국과 일본 사용자를 연결하는 소셜 파티 매칭 서비스입니다. 디자인 및 개발을 단독으로 진행했습니다.
사용자는 다양한 파티 이벤트에 신청하고, 온라인 결제를 통해 참가할 수 있습니다. 주식회사코아에서 진행한 파티(25.12.13, Osaka Namba Club GALA) 인원모집에 활용되었습니다.
핵심 기능
- PortOne과 PayPal을 활용한 해외 결제 지원, PortOne Webhook을 활용한 결제 안정성 강화
- 한국/일본 사용자들을 위한 다국어 지원 및 소셜 로그인 지원 (Kakao, LINE)
- Solid Queue, Google Sheets API를 활용한 백업 기능 구현 - 사업 초기환경에 적합한 경량 백업 시스템
- GitHub Action & Kamal을 활용한 무중단 배포 구현
- 관리자 대시보드 - 파티 게시물 생성/수정, 참가자 정보 확인, 참가 수락 및 거절
기술 스택
- Backend: Ruby on Rails 8.0.2, SQLite3
- Background Jobs: Solid Queue
- CI/CD: Kamal + GitHub Actions
- 결제: PortOne, PayPal
- 백업: Google Sheets API
구현과정
1. 다국어(I18n) 시스템
한국과 일본 사용자 모두를 대상으로 하기 때문에, URL 기반 로케일 라우팅을 구현했습니다.
# config/routes.rb
scope ":locale", locale: /ko|ja/ do
get "/party", to: "pages#party_home", as: :party_home
# 모든 라우트를 로케일 스코프 내에 정의
end모든 사용자 대면 텍스트는 ko.yml, ja.yml 파일로 관리하고, 데이터베이스 레벨에서도 title_ko, title_ja처럼 다국어 필드를 지원합니다.
2. 결제 시스템
업태의 한계(만남주선)로 PG사 도입이 불가했습니다. 따라서 한국의 경우 계좌이체 항목을 추가하고 실제 입금이 확인되면 관리자가 수동으로 참여 승인을 할 수 있도록 기능을 구현했습니다. 해외의 경우엔 Paypal의 경우 업태의 제한이 없어 이를 적용하여 구현했고, 일본의 특성을 고려하여 현장 결제를 전재로한 신청 기능을 추가했습니다. 단, Paypal 결제 진행이 우선순위가 높도록 기준을 세워 관리했습니다.
3. 웹훅 기반 비동기 결제 처리
기존 동기 방식에서는 결제 성공 페이지에서 2-3초를 대기해야 했습니다. 이를 웹훅 기반 비동기 처리로 전환하여 응답 속도를 1초 미만으로 개선했습니다.
# app/controllers/webhooks_controller.rb
class WebhooksController < ApplicationController
def portone
# HMAC-SHA256 서명 검증
WebhookService.new.verify_portone_webhook!(...)
# 이벤트 처리 (멱등성 보장)
WebhookService.new.process_portone_webhook(event)
render json: { success: true }, status: :ok
rescue WebhookService::WebhookError => e
# 에러 시 PortOne 자동 재시도 활용
render json: { error: e.message }, status: :bad_request
end
end4. Google Sheets 자동 백업 시스템
Solid Queue를 활용해 10분마다 자동으로 백업이 실행됩니다.
Solid Queue (10분마다)
↓
SheetsBackupJob
↓
GoogleSheetsService (Google Sheets API)
↓
Google Sheets
- party-application (신청자 정보)
- user (회원 정보)
- record (백업 실행 로그)Self-Healing 패턴을 적용하여 한 번에 100개씩 백업하고, 남은 데이터가 있으면 1분 후 자동으로 재실행됩니다.
자세한 구현 과정은 Google Sheets 백업 시스템 구축기에서 확인할 수 있습니다.
5. 소셜 로그인
국가별로 가장 많이 사용하는 소셜 로그인을 지원합니다.
- Kakao: 한국 사용자
- LINE: 일본 사용자
- 이메일: 범용
트러블슈팅
1. 결제 과정 중 발생한 Race Condition 해결
문제 상황
PortOne 웹훅이 사용자 리다이렉트보다 먼저 도착하는 현상이 발생했습니다. 웹훅 도착 시점에 Payment 레코드가 아직 생성되지 않아 결제 상태 업데이트가 실패했습니다.
사용자 결제 완료
├── PortOne 웹훅 발송 (즉시)
└── 브라우저 리다이렉트 (거의 동시)
↓
[서버] 웹훅 도착 → Payment 조회 → 없음! (트랜잭션 커밋 전)
[서버] 리다이렉트 도착 → Payment 생성 → 커밋해결 방법
PortOne의 자동 재시도 메커니즘을 활용했습니다. Payment를 찾지 못하면 400 에러를 반환하여 5분 후 재시도되도록 설계했습니다.
자세한 구현 과정은 PortOne 웹훅 구현에서 확인할 수 있습니다.
2. 데이터 유실 사고와 백업의 중요성
문제 상황
Solid Queue 자동 삭제 스크립트 버그로 소셜 로그인 사용자 데이터가 유실되었습니다. 이메일 미인증 사용자 삭제 로직이 소셜 로그인 사용자까지 삭제해버린 것입니다.
해결 과정
Google Sheets 백업 시스템 덕분에 7분 만에 실 결제 고객 4명의 정보를 복구할 수 있었습니다. 브라우저에서 즉시 조회 가능했던 점이 빠른 대응의 핵심이었습니다.
깨달은 점
백업은 "만약"을 대비하는 것입니다. 99%의 시간 동안 사용하지 않지만, 1%의 위기에서 서비스를 살립니다. 비개발자도 접근 가능한 백업의 접근성이 중요합니다.
성과
개인적 성과
개발자로서 모든 시스템을 설계하고 실제 서비스를 운영해본 경험은 매우 소중한 경험이었습니다.
결제 시스템, 백업 시스템 등을 직접 구현해본 경험과 발생한 Race Condition 이슈 및 데이터 유실 사고 복구 경험, 실제 서비스 운영을 위한 국내/해외 미팅까지 전반적으로 너무 소중한 경험이었습니다.
비즈니스 성과
- 주식회사코아 첫 파티(25.12.13, Osaka Namba Club GALA) 인원모집에 성공적으로 활용
마치며
1인 개발로 기획부터 디자인, 개발, 운영까지 전체 과정을 경험했습니다. 특히 결제 시스템의 Race Condition 해결과 데이터 유실 사고 복구 경험은 실제 운영 환경에서만 배울 수 있는 귀중한 경험이었습니다.
서비스는 현재 koa.asia에서 운영 중입니다.