🧭 시스템 아키텍처 개요
VivaSport 플랫폼은 Cloudflare의 Serverless 인프라(Workers)와 Edge DB(D1)를 척추로 삼아, 다중 프론트엔드 환경을 유기적으로 결합했습니다.
📱
소비자 React 앱
Vite + React + TS (app.vivaura.tech) 대회 탐색 및 신청, 마이페이지
🌐
퍼블릭 이벤트 허브
이벤트 및 뉴스 공유 허브 (event.vivaura.tech) Q&A 커뮤니티
🏢
어드민 콘솔 웹
테넌트 정산, 감사 로그 및 배너 관리, Q&A Abuse 차단 제어
⚙️
Serverless Workers API
Hono 프레임워크 기반 API 라우팅 및 비즈니스 미들웨어 검증
🗄️
D1 SQL Database
Cloudflare SQLite 기반 글로벌 데이터베이스 분산 쿼리
🔄 데이터 상호작용 및 보안 레이어 흐름
- 클라이언트 인증: Firebase Auth 토큰이 발급되면 모든 프론트엔드가 Hono API 호출 시
Authorization: Bearer [JWT]헤더를 첨부하여 보안 미들웨어 검증을 통과합니다. - 어드민 권한 제어: 어드민 콘솔은 전용 인증 토큰(JWT)과 역할(Role - Owner, Admin, Support) 테이블 매핑을 통해 리소스 접근 범위를 차단 및 통제합니다.
- 스팸(봇) 방지 (Cloudflare Turnstile): 대회 참가 신청, Q&A 의견 등록 및 신고 제출 시 봇 API 트래픽 공격을 완벽 차단하기 위해 Turnstile 사이트 키 검증이 선행됩니다.
🔑 인증 및 보안 처리
VivaSport API는 강력한 보안을 위해 Hono 미들웨어로 보호되며, 호출 유형에 따라 세 가지 인증 메커니즘을 사용합니다.
Firebase JWT Bearer Auth
일반 유저용 API(대회 참가, 내 정보 수정, 단체 개설 등) 호출 시, Firebase Auth에서 발행한 ID 토큰을 전송합니다.
Authorization: Bearer <Firebase_ID_Token>
Admin Console Auth Token
어드민용 API(정산 처리, 감사 로그 조회, 사용자 정지 등) 호출 시, 테넌트 검증이 완료된 Admin 전용 토큰을 전송합니다.
Authorization: Bearer <Admin_Access_Token>
⚡ API 엔드포인트 명세
| 유형 | 엔드포인트 | 설명 및 권한 수준 | 봇 방지 |
|---|---|---|---|
| GET | /api/events |
전체 대회 목록 조회 (비회원/소비자용) | - |
| POST | /api/events |
새로운 대회 개설 (요금제 구독 한도 필터 미들웨어 작동) | - |
| POST | /api/events/:id/feedbacks |
대회 Q&A 댓글/의견 신규 등록 (JWT optional) | Turnstile |
| POST | /api/reports |
댓글, 루트, 주최자 등 불편/스팸 신고 접수 | Turnstile |
| POST | /api/groups |
단체 개설 (소비자앱 또는 이벤트 허브에서 단체 생성) | - |
| GET | /api/groups/:code/members |
특정 단체 가입 신청 멤버 조회 (비밀번호 혹은 단체장 권한) | - |
| PATCH | /api/groups/:code/members/:id |
단체 신청 단체원 수락/반려 (단체장 검증 필수) | - |
| GET | /api/admin/reports |
접수된 신고 및 1:1 고객지원 목록 조회 (어드민 전용) | - |
| GET | /api/admin/feedbacks/:id |
신고 대상이 된 Q&A 피드백 댓글 원본 단건 상세 조회 | - |
| DELETE | /api/admin/feedbacks/:id |
신고된 스팸성 Q&A 댓글 영구 삭제 및 감사로그 기록 | - |
| PATCH | /api/admin/users/:id/status |
Abuse 악성 유저 차단(Blocked) 조치 (임시 provider 컬럼 매핑) | - |
📱 소비자 React 앱 기능 리스트
| 기능 명칭 | 상세 내용 | 상태 |
|---|---|---|
| 홈 (대회 카드 목록) | 대회 리스트 카드 및 실시간 진행률 애니메이션 바 적용 | ✓ 개발완료 |
| 대회 찾기 및 카테고리 필터 | 대회명 검색, 종목별 카테고리, 난이도 및 정렬 기능 연계 | ✓ 개발완료 |
| 이벤트 상세 정보 및 신청 | 상세 안내 정보 및 Firebase Auth 기반 다단계 참가 신청서 작성 | ✓ 개발완료 |
| 단체/팀 관리 (MyGroups) | 개설 단체 실시간 조회, 단체 코드 개설 및 단체원 승인/반려 (API 연계) | ✓ 개발완료 |
| 마이페이지 API 연동 | 신청 상태 실시간 동기화 및 마일리지 적립 조회 기능 | ✓ 개발완료 |
| GNB 모바일 안전 마진 | 노치가 없는 일반 화면에서도 GNB 레이블 텍스트 잘림 해결 | ✓ 개발완료 |
| 홈 타이틀 중복 수정 | 상단 네비게이션 헤더와 본문 타이틀의 'VivaSport' 이중 표시 교정 | ⚡ 개발대기 |
| 대회 생성 위자드 (4단계) | 대회 정보, Race 코스, 결제 방식, 포스터 업로드 4단계 마크업/API 연계 | ⚡ 개발대기 |
| 주최자 정산 관리 대시보드 | 대회 주최 기업/단체 대시보드 및 정산 이력 통계 연동 | ⚡ 개발대기 |
🌐 퍼블릭 이벤트 허브 기능 리스트
| 기능 명칭 | 상세 내용 | 상태 |
|---|---|---|
| 대회 소식 뉴스 카드 | 수집 봇이 물어온 공식 마라톤/대회 소식 리스트 카드화 | ✓ 개발완료 |
| 지도 앱 연동 & 주소 복사 | 개최지 정보의 클립보드 원클릭 복사 및 네이버/카카오 지도 연계 | ✓ 개발완료 |
| 모집율 실시간 카운터 | 모집율 정원 대비 비율 인디케이터 프로그레스 바 렌더링 | ✓ 개발완료 |
| 온오프믹스식 단체 참가 신청 | 대회 단체 가입 다이얼로그 검색, 단체 코드 클립보드 복사 모달 연동 | ✓ 개발완료 |
| Q&A 댓글/피드백 스팸 신고 | 댓글 옆 신고 버튼으로 팝업 다이얼로그 활성화 및 API 접수 연계 | ✓ 개발완료 |
| Turnstile 봇 방지 보호 | Q&A 댓글 작성과 신고 접수 시 악성 자동 도배 방지 캡차 위젯 탑재 | ✓ 개발완료 |
| 다국어 i18n 완전 지원 | 한국어, 영어 듀얼 렌더링 확장 리소스 추가 | ✓ 개발완료 |
🏢 어드민 콘솔 웹 기능 리스트
| 기능 명칭 | 상세 내용 | 상태 |
|---|---|---|
| 로그인 락 스크린 & 우회 | 수동 토큰 입력란에 전용 키 주입을 통해 Mock 데이터 모드 완벽 진입 | ✓ 개발완료 |
| 정산 대장 목록 및 이력 | 참가비 총액, 수수료, 세금 및 주최자 실 수령액 정산 승인 프로세스 | ✓ 개발완료 |
| 감사 로그 (Audit Logs) | 관리자 행위에 따른 IP, 일시, 행위 내역 조회 및 탐색 대시보드 | ✓ 개발완료 |
| 배너 광고 슬롯 관리 | 홈 화면 메인 및 사이드 광고 배너 캠페인 생성, 승인, 기간 통제 | ✓ 개발완료 |
| 신고 관리 (Support / Abuse) | 일반 접수된 불편사항 및 문의 내역 승인, 기각 상태 조치 | ✓ 개발완료 |
| Q&A 원본 fetch & 삭제 조치 | 신고 내역 중 댓글/피드백 원본 조회 후 즉각 삭제 및 해당 신고 완료 처리 | ✓ 개발완료 |
| 작성자 계정 차단 (Block) | 신고 상세 창에서 작성자 계정을 즉시 정지 조치 연계 | ✓ 개발완료 |
| 라이트 모드 가독성 패치 | 인라인 white 색상으로 라이트 테마 전환 시 텍스트 묻히는 가독성 소실 해결 | ✓ 개발완료 |
| 가입 테넌트 타입 정리 | 회원가입 항목 내 부적절한 '개인' 타입을 배제하고 법인, 공공기관 등으로 통일 | ✓ 개발완료 |
| 정산 자동 이체 API (PG) | 정산 승인 시 실시간 계좌이체 자동 연동 API 개발 | ⚡ 개발대기 |
⚙️ Cloudflare Workers & DB 기능 리스트
| 기능 명칭 | 상세 내용 | 상태 |
|---|---|---|
| 요금제 구독 게이팅 미들웨어 | 무료 요금제 유저의 유료 대회 생성 차단, 등급별 월간 유료대회 개설 개수 제한 | ✓ 개발완료 |
| 단체/참가 신청 D1 테이블 스키마 | 단체명, 단체장 정보 및 신청자 정보를 D1 DB 영구 테이블로 런타임 자동 생성 | ✓ 개발완료 |
| 단체 및 가입신청 API 6종 | 내 단체 조회, 참가 신청, 가입자 승인/반려 등 Workers API 구축 | ✓ 개발완료 |
| Turnstile 검증 유연화 | 비회원 상태의 Q&A 피드백 작성 및 신고를 위한 Turnstile 봇 보호 API 추가 | ✓ 개발완료 |
| Google Auth CORS 우회 | Google API 연동 시 X-Viva-Bypass 헤더 중복 전입 방지 우회 조치 | ✓ 개발완료 |
| 스포츠 ODF 표준 코드 매핑 | 러닝->ATH, 사이클->CYC 등의 종목 코드를 저장 시 백엔드 단에서 자동 ODF 매핑 | ✓ 개발완료 |
| 유지보수 중 analytics 캡처 우회 | 점검 상태에서도 익명 분석 로그 수집 Endpoint(/api/analytics/collect) 정상 동작 | ✓ 개발완료 |
| 대규모 트래픽용 KV 캐싱 | D1 데이터베이스 쿼리 부하 분산을 위한 Workers KV 캐싱 캐시 레이어 도입 | ⚡ 개발대기 |
💡 도움말 & 문제해결
Q. 어드민 콘솔 웹에서 테스트를 위해 로그인 잠금(Lock Screen)을 푸는 방법은 무엇인가요?
+
어드민 콘솔 웹 우측 상단 로그인 영역에서 "수동 토큰 (Manual Token)" 탭을 클릭한 뒤, 입력창에 아래 토큰 키를 주입하면 잠금이 해제되고 로컬 Mock 데이터를 연동해 테스트할 수 있습니다.
viva-mock-2026
Q. 무료 요금제 사용자의 유료대회 개설 제한 정책은 어떻게 작동하나요?
+
유저의 등급이
등급별 월간 한도(Basic: 1건, Coach: 5건, Organizer: 무제한) 역시 백엔드 트랜잭션 수량 검증을 통해 엄격하게 차단됩니다.
plan-free인 경우, React 앱 대회 개설 폼에서 참가비 입력 칸이 비활성화되며 무조건 0원으로 고정됩니다. 강제로 API를 조작하여 0원 초과의 결제 금액을 보내더라도 Workers 백엔드 미들웨어 단에서 403 Forbidden을 반환하여 차단합니다.
등급별 월간 한도(Basic: 1건, Coach: 5건, Organizer: 무제한) 역시 백엔드 트랜잭션 수량 검증을 통해 엄격하게 차단됩니다.
Q. 이번에 새로 반영된 Q&A 스팸 제어 및 단체 승인 관리 프로세스는 무엇인가요?
+
Q&A 영역에 악성 도배글이나 욕설 등이 등록되는 것을 방지하기 위해 Cloudflare Turnstile을 연동하여 봇 방지를 수행합니다.
만약 우회해 스팸이 등록된 경우, 일반 유저의 🚨신고 버튼을 통해 어드민 Support 탭에 전달되며, 어드민은 신고 정보에서 원본 댓글을 비동기로 당겨와 직접 삭제하거나 작성자를 즉각 차단(Block)할 수 있습니다.
Q. 이번에 마이그레이션된 모바일 앱(React Native / Expo) 빌드 및 테스트 방법은 무엇인가요?
+
VivaSport 모바일 프로젝트는 Expo Router 파일 기반 내비게이션 구조로 설계되어 있습니다.
로컬 빌드를 위해 자바 JDK 17을 설치하고 환경변수(
JAVA_HOME)를 설정한 상태에서 cd android && ./gradlew assembleDebug 명령을 실행하면 즉각 app-debug.apk 파일이 생성되어 실제 폰이나 에뮬레이터에서 즉시 테스트할 수 있습니다.
Q. 홈페이지 문의하기(Contact Form) 접수 시 메일 발송이 실패하거나 지연되어도 데이터가 유실되지 않나요?
+
문의하기 접수 시 백엔드 Workers API는 이메일 전송에 앞서 D1 데이터베이스(inquiries 테이블)에 문의 데이터를 우선 영구 기록합니다.
이후 연동된 Resend API를 통해 실시간 알림 메일을 전송하며, 만약 Resend API 도메인 인증 상태 등의 문제로 메일 발송이 예외 에러를 발생시키더라도, 내부 Exception 처리로 안전하게 우회 차단되어 사용자 화면에는 "접수 완료" 알림이 정상적으로 노출되며 데이터 유실이 일절 발생하지 않습니다.