🌐
유저가 프로덕트를 인지하고, 인증으로 자격을 얻고, 구독을 결제해 사용을 시작하는 모든 동선이 지나가는 웹입니다. 새 기능보다 이 동선이 어느 단계에서도 막히지 않는 것이 먼저였습니다.
결론
로그인을 전역 모달로, 접근 판정을 멤버십·역할 2축으로 나눠 유저가 막힌 자리에서 결제까지 이어지게 설계했습니다. 175개 경로는 명세와 하나씩 대조하고 에러 계약을 테스트로 고정해, 백엔드가 바뀌면 화면이 아니라 테스트가 먼저 깨지게 했습니다.
담당 범위
- 직접 구현: 인증·구독 결제·멤버십·에이전트 생성·다국어 화면, 계약 테스트 216건, e2e 24케이스, 결제 킬스위치, 오류 응답 매핑
- 전체 구조 이해·조율: v2 명세 175경로 인벤토리 작성, CORS 부재(OPTIONS 405)와 OAuth 전건 실패를 실측해 백엔드에 원인과 대안 전달, 결제 재개 조건 조율
- 다른 담당: 결제 트랜잭션·멱등 처리·환불 이벤트(백엔드), 어드민 콘솔 화면 다수(동료)
- 하지 않은 것·설계안(미구현): 장애 감지 채널 부재가 남은 1번 과제입니다. 결제 실패율·중복 승인 알림은 미구현입니다.
배경
voidx.ai는 AI 에이전트 SaaS의 마케팅 사이트이자 회원 콘솔입니다. 회원가입·로그인부터 데모 체험, 멤버십 구독 결제, 에이전트 캐스팅·배치, 위젯 설치까지 서비스가 실제로 팔리는 동선 전체가 이 웹을 지나갑니다. 기존 구현을 Next.js 16 / React 19로 이관하는 작업부터 시작해 정식 운영(LIVE)까지 맡고 있습니다. 담당 영역은 인증 · 구독 결제(조회·해지·재개) · 멤버십 · API v2 이관 주도 · SEO/GEO · AI 에이전트 생성·배치 · 다국어(ko/en)입니다.
한 일
- 진입 동선 전체를 기획까지 맡아 구현: 로그인을 페이지가 아니라 전역 모달로 설계해, 어디서 막히든 그 자리에서 인증하고
next파라미터로 원래 목적지에 복귀합니다(내부 경로만 허용). 가입 진입점 8곳이 모달 하나로 수렴합니다. 가입·인증 → 결제·멤버십 → 캐스팅 → 위젯 키 발급 → 설치 3단 스테퍼를 하나의 동선으로 이었고, 라우트 54개 중 53개를 직접 작성했습니다. 인증은 NextAuth 기반으로 이메일·소셜 로그인, 탈퇴, 프로필 조회·수정을 붙였고, 미들웨어에서 JWT 오류를 자동 처리해 어긋난 세션이 화면 오류로 이어지지 않게 했습니다. - 접근 판정을 두 축으로 분리하고 메뉴 게이팅을 2단으로: 멤버십이 없는 계정으로 들어오면 화면이 403을 받고 나갈 길이 없어지는 문제가 있었습니다. 결제로 해소되는 것(멤버십)에만 구독을 유도하고, 결제로 해소되지 않는 것(협업 역할 부족)에는 구독 유도를 금지하도록 판정을 단일 훅으로 모았습니다. 멤버십이 필요한 메뉴는 숨기지 않고 잠금 아이콘으로 노출해 결제하면 열리는 기능을 보여주고, 몰 연동이 필요한 메뉴만 숨깁니다. 에이전트 생성 입구는 일부러 잠그지 않고 결과 확정·토큰 발급 단계에만 잠금을 걸었습니다. 잠긴 기능을 누르면 이동 대신 안내 모달을 띄우고, 요금제로 넘어갈 때 유입 출처(from)를 체크아웃까지 승계해 어떤 게이트에서 결제로 이어졌는지 추적할 수 있게 했습니다.
- 구독 결제 UX: 해지는 즉시 차단이 아니라 기간 만료형입니다. 남은 기간 접근을 유지하고 빌링키를 보존해, 재개 시 카드 재등록 없이 구독이 복원됩니다. 결제 실행의 전역 킬스위치는 환경 플래그화하되 기본값을 잠금으로 두었습니다.
- API v2 이관: 175개 경로를 계약 테스트 기반으로 전수 대조: 운영 중인 서비스의 백엔드 API가 전면 개편됐고, 화면 전체가 의존하는 175개 경로를 사용자에게 끊김 없이 옮겨야 했습니다. 명세와 실제 응답이 다른데 화면에서는 동작하는 것처럼 보이는 상태가 가장 위험해, 경로 하나씩 대조하는 전수 이관을 택하고 API 응답과 에러 체계를 테스트로 고정할 수 있는 계약으로 만들었습니다. 도메인별 에러 코드 체계(problem+json)를 클라이언트 계약 테스트로 명문화해 결제·캐스팅·카페24 연동 등 도메인마다 단위 테스트를 두어, 백엔드가 바뀌면 테스트가 먼저 깨지게 했습니다. 연동 진척도 코드로 다시 셌습니다. 백엔드가 게이트웨이 접속 로그를 근거로 공유한 연동률과 화면 코드의 호출 지점을 전수 대조한 결과가 크게 달랐고(로그에 남지 않는 경로 때문), 이 대조를 기준으로 남은 작업량을 다시 잡아 전량 이관을 정식 운영에 올렸습니다.
- 운영 어드민을 만들어 팀에 공유: 대시보드·회원·멤버십·결제·페르소나·안전·감사까지 13화면 규모입니다. 초기 콘솔은 단독 구축했고 v2 재구축은 동료와 분담했습니다. 어드민에는 MSW 계약 테스트 체계를 세워 정의되지 않은 API 호출은 즉시 실패(
onUnhandledRequest: 'error')하도록 했고, 이 덕분에 백엔드 구현이 끝나기 전에 프론트가 목(mock) 기준으로 먼저 개발할 수 있었습니다. 실서버 읽기 스모크를 별도로 돌려 목과 실서버가 어긋난 지점을 잡아냈습니다. - 검증 인프라를 함께 깔음: Playwright 여정 e2e 24케이스를 setup·journeys·locale 3프로젝트로 분리해, 백엔드 없이도 도는 locale 검증과 실서버가 필요한 여정 검증이 서로 막지 않게 했습니다. 탈퇴·결제처럼 파괴적인 시나리오는 기존 dev 서버 재사용을 금지(
reuseExistingServer: false)해 프로덕션 API를 바라보는 서버에서 실행되는 사고를 차단하고, 백엔드 rate limit을 공유하는 시나리오는 직렬로 실행합니다. 단위/계약 테스트 216건과 실카드 결제·환불 15건을 통과 기준으로 삼았고, Storybook에는 접근성 애드온을 붙였습니다. - 내 초기 구조를 스스로 되돌린 것이 두 건: 캐스팅 완료 후 외부 관리 사이트로 이탈하던 경로를 없애 본 사이트 프로필 영역으로 통합했고, 하드코딩해 둔 회원 콘솔 전반의 한국어를 한/영 다국어로 일괄 전환했습니다. 네임스페이스 23개, 키 약 2,500개 규모입니다.
- 해킹 시도를 계기로 보안 정비: HSTS·CSP·X-Frame-Options 등 보안 헤더를 정비하고 시크릿을 환경변수로 옮겼습니다. dangerouslySetInnerHTML 구간에 DOMPurify를 적용하고, Server Actions 입력 검증(지식베이스 파일 타입·10MB 제한)을 붙였습니다.
- 실사용자 결제 장애 대응을 주도: 장애를 알린 것은 모니터링이 아니라 사용자의 문의 메일이었습니다. 당일 사과·전액 환불과 전역 결제 차단으로 피해 확산을 끊고, 프론트 사각지대 3종 실증·수정, 오류 응답 전수 매핑, 테스트 확충을 진행했습니다. 상세는 별도 케이스 "실결제 장애 대응"에 정리했습니다.
결과
- 175개 경로: API v2 전량 이관, 정식 운영(LIVE)
- e2e 24케이스 · 단위/계약 테스트 216건 · 실카드 결제·환불 15건: 통과 기준
- 가입 진입점 8곳 → 전역 인증 모달 하나: next 파라미터로 목적지 복귀
- 라우트 54개 중 53개: 직접 작성, 가입 → 체험 → 결제 풀사이클 운영 중
- 23개 네임스페이스: 한/영 다국어 전환, 키 약 2,500개
- 어드민 13화면: 초기 콘솔 단독 구축 (v2 재구축은 동료와 분담)
- 보안 헤더·CSP 정비 + DOMPurify + Server Actions 입력 검증
정리
이 웹에서 가장 중요한 일은 새 화면을 늘리는 것보다 인지 → 인증 → 결제 → 사용의 동선이 어디서도 막히지 않게 유지하는 것이었습니다. 눈으로 확인하는 대신 API 계약을 테스트로 고정해 두었기에 175개 경로를 끊김 없이 옮길 수 있었고, 결제 장애 때는 감지 채널의 부재 자체를 재발 방지 과제로 삼았습니다.