Skip to content

feat: dev/staging 환경 미승인 사용자 404 처리 (세션 쿠키 기반 게이트) #334

Description

@iOdiO89

구현할 기능

dev(dev.piki.day)/staging(staging.piki.day) 웹에 어드민 세션이 없는 사용자가 접속하면 404 페이지를 보여준다.
승인된 사용자(디스코드 /piki-admin dev 링크로 세션 등록)만 접속 가능하게 하고, 실서비스(piki.day)는 영향 없음.

배경 / 조사 결과

  • 디스코드 봇 링크로 등록 페이지에 접속하면 백엔드가 세션 쿠키(JSESSIONID) 를 심어줌 (59분 세션)
    • "IP 세션"처럼 보이지만 실제 판별 기준은 쿠키 — 같은 기기여도 쿠키 없이(curl, 시크릿 창) 호출하면 404 확인됨
  • 백엔드에 세션 확인용 엔드포인트가 이미 있음: GET /admin/session/ttl
    • 세션 있음 → 200 {"remainingSeconds":3600} + 호출 시 세션 자동 연장
    • 세션 없음 → 404 (빈 바디)
    • 세션 있음/없음 판단을 이 엔드포인트 하나로 해결 가능. 신규 API 불필요
  • Vercel 무료 플랜이라 Password Protection / Trusted IPs 등 플랫폼 기능은 사용 불가 → 앱 레벨(proxy.ts)에서 처리
  • 환경 구분은 NEXT_PUBLIC_STAGE=dev|staging|production env로 이미 가능

동작 흐름

dev.piki.day 접속
    ↓
proxy.ts: NEXT_PUBLIC_STAGE === 'production'? → 게이트 skip (기존 흐름 그대로)
    ↓ dev/staging이면
통과 쿠키(짧은 TTL, 서명됨) 있으면 → 통과 (백엔드 호출 생략)
    ↓ 없으면
접속자의 쿠키를 그대로 실어 GET {API_URL}/admin/session/ttl 호출
    ↓
200 → 통과 쿠키 심고 통과
404 → not-found 페이지로 rewrite (404 상태코드)
  • 통과 쿠키(약 5분)로 매 요청마다 백엔드를 호출하지 않도록 캐싱 — 세션 만료자도 최대 5분 내 차단됨
  • ttl 엔드포인트가 호출마다 세션을 연장하므로, 사이트를 쓰는 동안은 세션이 안 끊김 (개발 UX상 장점)

🙏 백엔드 선행 작업 (1건)

현재 JSESSIONID 쿠키의 Domain이 dev.api.piki.day(host-only)라서 웹(dev.piki.day) 요청에는 쿠키가 실리지 않음.
쿠키가 웹까지 딸려 오도록 아래 중 하나 필요:

  1. 세션 쿠키 Domain을 .piki.day로 확장 — Spring 기준 설정 한 줄
    server.servlet.session.cookie.domain: .piki.day
  2. (1이 께름칙하면) 등록 시점에 게이트 전용 쿠키를 Domain=.piki.day로 하나 더 발급

※ 웹 미들웨어는 서버에서 요청 헤더를 읽으므로 HttpOnly 쿠키 그대로 사용 가능 (변경 불필요)

작업 상세 내용

  • (백엔드) 세션 쿠키 Domain .piki.day로 확장 (위 참고)
  • proxy.ts 최상단에 환경 게이트 추가 (NEXT_PUBLIC_STAGE !== 'production'일 때만 동작)
  • 세션 확인 결과 캐싱용 통과 쿠키 (서명, TTL 약 5분)
  • 미승인 사용자 → not-found 페이지 rewrite (404 상태코드)
  • dev/staging 응답에 X-Robots-Tag: noindex 헤더 추가 (검색 노출 방지)
  • 검증: 시크릿 창 404 / 등록 후 정상 접속 / production 영향 없음

참고 / 추후 고민

  • 앱(WebView)으로 dev 접속 시: 웹뷰 쿠키 저장소에 세션 쿠키가 있어야 함 → 등록 링크를 앱 안에서 열어야 함. 404 페이지에 등록 안내를 넣는 방안 등 게이트 적용 후 별도 논의

Metadata

Metadata

Assignees

Labels

WEBfeatureNew feature or request

Type

Fields

No fields configured for Task.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions