From 9fdcecace84da5aeeb7f9c8bdfc924f52222f08b Mon Sep 17 00:00:00 2001 From: ttipo Date: Sat, 20 Jun 2026 21:22:23 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=EC=9D=B4=EB=A9=94=EC=9D=BC=20=EC=9D=B8?= =?UTF-8?q?=EC=A6=9D=20=EB=A7=81=ED=81=AC=EB=A5=BC=20=EA=B2=B0=EA=B3=BC=20?= =?UTF-8?q?=ED=8E=98=EC=9D=B4=EC=A7=80(=EC=B0=BD=20=EB=8B=AB=EA=B8=B0)?= =?UTF-8?q?=EB=A1=9C=20=EB=B6=84=EB=A6=AC=20+=20=EA=B0=80=EC=9E=85=20?= =?UTF-8?q?=EB=8C=80=EA=B8=B0=20=ED=99=94=EB=A9=B4=EC=97=90=20=EB=A1=9C?= =?UTF-8?q?=EA=B7=B8=EC=9D=B8=20=EB=B2=84=ED=8A=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 인증 링크(verify-email)의 리다이렉트 대상을 /login?verified → /email-verified?ok=1|0 으로 변경 - 신규 EmailVerifiedPage(/email-verified): 인증 완료/실패 표시 후 창 자동 닫기 시도. 브라우저가 사용자가 연 탭의 close 를 막을 수 있어 안내 문구 + 수동 로그인/가입 링크 병행 - SignupPage 인증 대기 화면에 '인증을 완료했어요 · 로그인하러 가기' 기본 버튼 추가 (다른 탭에서 인증을 마친 뒤 기존 화면에서 로그인 진입) 런타임 검증: 유효 토큰→/email-verified?ok=1·무효→ok=0, 인증 후 로그인 200, SPA 라우트 제공. 백엔드 build/lint 0, 프론트 type-check/lint/build 0. Co-Authored-By: Claude Opus 4.8 (1M context) --- backend/src/modules/auth/auth.controller.ts | 7 +- .../src/pages/relay/EmailVerifiedPage.vue | 210 ++++++++++++++++++ frontend/src/pages/relay/SignupPage.vue | 25 +++ frontend/src/router/index.ts | 7 + 4 files changed, 246 insertions(+), 3 deletions(-) create mode 100644 frontend/src/pages/relay/EmailVerifiedPage.vue diff --git a/backend/src/modules/auth/auth.controller.ts b/backend/src/modules/auth/auth.controller.ts index 8cfbb5e..b482b89 100644 --- a/backend/src/modules/auth/auth.controller.ts +++ b/backend/src/modules/auth/auth.controller.ts @@ -139,7 +139,8 @@ export class AuthController { return null; } - // 이메일 인증 링크 — 메일의 버튼에서 직접 GET 진입. 검증 후 프론트로 리다이렉트. + // 이메일 인증 링크 — 메일의 버튼에서 직접 GET 진입(보통 새 탭). + // 검증 후 결과 페이지로 리다이렉트하며, 그 페이지는 완료를 표시하고 창을 닫는다. @Get('verify-email') @SkipTransform() @ApiOperation({ summary: '이메일 인증 (메일 링크)' }) @@ -149,9 +150,9 @@ export class AuthController { ): Promise { try { await this.authService.verifyEmail(token); - res.redirect(`${this.webUrl()}/login?verified=1`); + res.redirect(`${this.webUrl()}/email-verified?ok=1`); } catch { - res.redirect(`${this.webUrl()}/login?verified=0`); + res.redirect(`${this.webUrl()}/email-verified?ok=0`); } } diff --git a/frontend/src/pages/relay/EmailVerifiedPage.vue b/frontend/src/pages/relay/EmailVerifiedPage.vue new file mode 100644 index 0000000..958deac --- /dev/null +++ b/frontend/src/pages/relay/EmailVerifiedPage.vue @@ -0,0 +1,210 @@ + + + + + diff --git a/frontend/src/pages/relay/SignupPage.vue b/frontend/src/pages/relay/SignupPage.vue index fd728e8..32cf44f 100644 --- a/frontend/src/pages/relay/SignupPage.vue +++ b/frontend/src/pages/relay/SignupPage.vue @@ -419,6 +419,12 @@ const points = [ 인증 메일을 다시 보냈습니다.
+