유대선
프로젝트로
·결정·3

App Store 제출을 막던 코드 차단 3개를 정리하다

출시 준비도 감사가 짚은 App Store 하드 차단 3개를 코드로 해소. (1) 네이티브 Apple 로그인 백엔드(app/api/auth/apple, lib/oauth/apple.ts)가 커밋조차 안 돼 있어 프로덕션에서 작동 안 하던 걸 커밋, (2) 계정 생성 앱은 인앱 계정삭제를 제공해야 한다는 가이드라인 5.1.1(v) 위반 — 설정 화면에 이중확인 '계정 삭제' 추가(백엔드 DELETE /api/account 호출), (3) 출시 빌드에 노출되던 '개발용' 로그인 폼을 __DEV__ 뒤로 숨김. tsc --noEmit 통과.

출시 준비도 감사에서 짚은 App Store 하드 차단 셋을 정리했다. 셋 다 코드 작업이라 외부 승인·시크릿 없이 바로 처리할 수 있었다.

1. Apple 로그인 백엔드가 커밋조차 안 돼 있었다

app/api/auth/apple/mobile/route.ts(네이티브 identityToken 검증 → 세션 발급)와 lib/oauth/apple.ts(Apple JWKS로 issuer·audience·exp·RSA 서명 검증)가 git 미추적 상태였다. 즉 어느 브랜치에도 없고 배포된 적이 없어서, 앱은 Apple 버튼을 띄우는데 프로덕션 서버는 그 경로에서 not-found를 반환했다. Apple은 3rd-party 로그인(카카오/구글)을 제공하면 동작하는 Sign in with Apple을 요구한다(4.8) → 거절 사유. 두 파일을 커밋했다. (실제로 라이브에서 동작하려면 배포가 남았다 — 백엔드는 마침 NCP 이전 중이라 그쪽과 함께.)

2. 인앱 계정 삭제가 없었다 (5.1.1(v))

계정 생성을 지원하는 앱은 인앱에서 계정 삭제를 제공해야 한다. 백엔드엔 DELETE /api/account(미디어 실삭제 + FK cascade로 보관함/항목/알림/구독 제거)가 이미 있었는데 모바일이 호출하지 않았다. mobile/src/api.tsdeleteAccount()를 추가하고, 설정 화면 프라이버시 섹션에 이중 확인('되돌릴 수 없어요') '계정 삭제' 버튼을 달았다 — 삭제 성공 시 로컬 세션을 비우고 로그인 화면으로.

3. 개발용 로그인 폼이 출시 빌드에 노출됐다

로그인 화면의 '개발용' 이름/이메일 폼은 /api/auth/dev-login을 호출하는데, 이 라우트는 프로덕션에서 무조건 404다. 출시 빌드에서 보이고 눌리는데 항상 에러로 끝나 완성도(2.1) 문제가 됐다. 폼·구분선·시작하기 버튼을 {__DEV__ ? ... : null} 뒤로 숨겼다. OAuth/Apple 에러 표시는 프로덕션에서도 보이도록 블록 밖으로 빼뒀다.

검증 / 남은 것

cd mobile && npm run typecheck(tsc --noEmit) exit 0. 런타임(시뮬레이터 빌드)은 별도. 아직 남은 출시 차단(이번 작업 범위 밖): Apple 라우트의 실제 배포, EAS 프로젝트 연결·submit 크레덴셜, 스토어 자료(스크린샷·1024 아이콘·개인정보처리방침/지원 URL), 리마인더 네이티브 푸시.