Skip to content

[feat] 마이페이지 API 연동 및 누락된 UI 추가#42

Open
dohy-eon wants to merge 14 commits into
devfrom
feat/ALT-234
Open

[feat] 마이페이지 API 연동 및 누락된 UI 추가#42
dohy-eon wants to merge 14 commits into
devfrom
feat/ALT-234

Conversation

@dohy-eon
Copy link
Copy Markdown
Member

@dohy-eon dohy-eon commented May 21, 2026

ID

  • ALT-234

변경 내용

  • 마이페이지의 본인 정보 조회 및 프로필 관리 기능을 실제 API와 연동했습니다.
  • APP/ MANAGER scope에 따라 /app/users/me, /manager/me 계열 API를 분기 호출하도록 확장했습니다.
  • 닉네임, 프로필 이미지, 비밀번호, 이메일, 회원 탈퇴, 소셜 계정 연동/해제 기능 화면과 API 연동을 추가했습니다.

구현 사항

  • features/user/me API 계층을 확장해 본인 정보 조회뿐 아니라 닉네임 변경, 프로필 이미지 수정/삭제, 비밀번호 변경, 이메일 인증/등록/삭제, 회원 탈퇴, 소셜 연동 상태 조회/연동/해제 요청을 처리하도록 구현했습니다.
  • useAuthStore의 현재 scope를 기준으로 USER는 /app/users/me, MANAGER는 /manager/me 및 /manager/me/social 경로를 사용하도록 공통 hook을 구성했습니다.
  • 프로필 수정 화면에서 profileImageUrl을 표시하고, 파일 업로드 API로 USER_PROFILE 이미지를 업로드한 뒤 반환된 fileId로 프로필 이미지 수정 API를 호출하도록 연결했습니다.
  • /my/profile/nickname, /my/profile/password, /my/profile/email, /my/profile/social, /my/withdraw 라우트와 화면을 추가해 각 마이페이지 기능을 실제 사용자 플로우로 사용할 수 있게 했습니다.
  • 이메일 관리는 인증 코드 발송, 코드 검증 후 sessionId 기반 등록/변경, 이메일 삭제까지 한 화면에서 처리하도록 구현했습니다.
    회원 탈퇴는 성공 시 로컬 인증 상태를 정리하고 로그인 화면으로 이동하며, MANAGER scope에서는 운영 중 업장으로 인한 탈퇴 제한 에러를 안내하도록 처리했습니다.
  • 소셜 계정 관리는 카카오/애플 연동 상태 조회, OAuth 기반 연동, provider별 연동 해제를 지원하도록 구현했습니다.

구현 시연 (필요 시)

2026-05-21.9.57.02.mov

참고 사항 (필요 시)

  • 마이페이지
  • PUT /app/users/me/nickname — 닉네임 변경 (페이지 자체 미구현)
  • PUT /app/users/me/profile-image — 프로필 이미지 수정 (handleAvatarUpload()
    {} 빈 함수)
  • DELETE /app/users/me/profile-image — 프로필 이미지 삭제
  • PUT /app/users/me/password — 비밀번호 변경 (페이지 자체 미구현)
  • POST /app/users/me/email/verification/send — 이메일 인증 코드 발송 (로그인
    상태)
  • POST /app/users/me/email/verification — 이메일 인증 코드 검증 (로그인 상태)
  • POST /app/users/me/email — 이메일 등록/변경 (현재 mock 데이터 사용)
  • DELETE /app/users/me/email — 이메일 삭제
  • DELETE /app/users/me — 회원 탈퇴 (버튼만 있고 API 미연동)
  • POST /app/users/social/link — 소셜 계정 연동
  • DELETE /app/users/social/unlink/{provider} — 소셜 연동 해제
  • GET /app/users/social/status — 소셜 연동 상태 조회

매니저 본인 정보 (MANAGER scope)

  • GET /manager/me — 매니저 본인 정보 조회
  • PUT /manager/me/nickname, PUT /manager/me/profile-image, DELETE
    /manager/me/profile-image
  • PUT /manager/me/password, POST /manager/me/email, DELETE /manager/me/email
  • DELETE /manager/me — 매니저 탈퇴
  • POST /manager/me/social/link, DELETE /manager/me/social/unlink/{provider}

해당 api들 누락 없이 잘 반영된건지 꼼꼼히 살펴서 리뷰해주세요 @CodeRabbit

Summary by CodeRabbit

  • 새로운 기능
    • 프로필 관리가 세부 페이지로 분리: 닉네임·비밀번호·이메일·소셜 계정·탈퇴 화면 추가
    • 이메일 인증(발송·검증) 및 이메일 등록·변경·삭제 흐름 추가
    • 카카오·Apple 소셜 계정 연동/해제 및 연동 상태 표시/관리 기능 추가
    • 프로필 이미지 업로드·편집·삭제 UI 및 삭제 확인 모달 추가
    • 회원 탈퇴 전용 화면과 확인 절차 추가
    • 인증/권한(scope) 기반으로 사용자 데이터 쿼리 및 라우팅이 적용되도록 개선

Review Change Stack

@dohy-eon dohy-eon requested review from kim3360 and limtjdghks May 21, 2026 00:59
@dohy-eon dohy-eon self-assigned this May 21, 2026
@vercel
Copy link
Copy Markdown

vercel Bot commented May 21, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
alter-client Ready Ready Preview, Comment May 22, 2026 12:26am

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 21, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 90f9fb94-2c76-4cde-ac06-e0863ee6fdcc

📥 Commits

Reviewing files that changed from the base of the PR and between 071900d and 9515f53.

📒 Files selected for processing (1)
  • src/features/user/me/hooks/useWithdrawUserFlow.ts

📝 Walkthrough

Walkthrough

스코프 기반 사용자 API와 공용 파일 업로드 모듈을 도입하고, 닉네임/비밀번호/이메일/소셜/탈퇴 관련 타입·API·뮤테이션 훅·UI 페이지와 라우팅을 추가하여 마이페이지 프로필 관리를 확장합니다.

Changes

사용자 프로필 관리 기능

Layer / File(s) Summary
타입 정의 및 DTO/요청 계약
src/features/user/me/types/user.ts
UserMeDto에 연락처·프로필 이미지 필드 추가, UserMeScope, SocialProvider, SocialPlatformType 및 이메일/비밀번호/프로필/소셜 관련 요청·응답 DTO들을 추가했습니다.
API 기초 및 쿼리 키 확장
src/features/user/me/api/user.ts, src/shared/lib/queryKeys.ts
getUserMe(scope)로 변경, scope 기반 경로 헬퍼 추가 및 queryKeys.user.me(scope)/user.socialStatus(scope) 추가로 쿼리 키에 scope를 포함시켰습니다.
사용자 수정·관리 API
src/features/user/me/api/user.ts
닉네임/프로필 이미지 업데이트·삭제, 비밀번호 업데이트, 이메일(전송/검증/등록/삭제), 탈퇴, 소셜(link/unlink/status) API 래퍼를 추가했습니다.
공유 파일 업로드 모듈 이동
src/shared/api/appFileUpload.ts, src/features/store-register/api/workspaceFileUpload.ts
앱 파일 업로드 구현을 공용 모듈로 이동하고 기존 workspaceFileUpload에서 재export하도록 변경했습니다.
useUserMe 쿼리·뷰모델
src/features/user/me/hooks/useUserMe.ts
auth scope를 반영하도록 queryKey/queryFn/enabled를 변경하고 뷰모델에 email, phone, profileImageUrl을 추가했습니다.
뮤테이션/쿼리 훅 모음
src/features/user/me/hooks/useUserMeMutations.ts
scope 강제(requireUserScope)와 함께 닉네임/프로필 이미지/비밀번호/이메일/탈퇴/소셜 상태·link·unlink 훅들을 추가했습니다. 성공 시 적절한 쿼리 키를 invalidate합니다.
프로필 이미지 편집 훅
src/features/user/me/hooks/useProfileImageEditor.ts
파일 input ref, uploadAppFile 호출, update/delete 뮤테이션 연동, 삭제 모달 제어와 에러 상태를 제공하는 훅을 추가했습니다.
닉네임 변경 흐름
src/features/user/me/hooks/useChangeNickname.ts, src/pages/my/profile/nickname/index.tsx
닉네임 입력 검증(1~64자, 기존값 대비 변경) 및 비동기 제출 후 리다이렉트 구현입니다.
비밀번호 변경 흐름
src/features/user/me/hooks/usePasswordUpdateFeature.ts, src/pages/my/profile/password/index.tsx
비밀번호 형식(8~16자, 영문/숫자/특수 포함) 검증과 제출·네비게이션 흐름을 훅과 페이지로 분리했습니다.
이메일 인증 흐름
src/features/user/me/hooks/useEmailVerificationFlow.ts, src/pages/my/profile/email/index.tsx
이메일 발송/코드 검증(sessionId)/등록·삭제 흐름을 훅으로 관리하고 EmailEditPage에서 UI를 연결합니다.
소셜 연동 흐름
src/features/user/me/hooks/useSocialAccountLinking.ts, src/pages/my/profile/social/index.tsx
카카오/애플별 연동·해제 로직과 상태 조회를 훅으로 구현하고 UI에서 provider별 버튼·상태를 렌더링합니다.
회원 탈퇴 흐름
src/features/user/me/hooks/useWithdrawUserFlow.ts, src/pages/my/withdraw/index.tsx
체크박스·window.confirm 확인 후 탈퇴 요청을 수행하고 성공 시 로그아웃 및 로그인 페이지로 리다이렉트합니다.
ProfileEditPage 및 Modal 통합
src/pages/my/profile/index.tsx
이미지 업로드/삭제(숨김 input, 모달, ESC 및 overflow cleanup)와 메뉴 라우팅을 ROUTES 상수로 전환했습니다.
MyPage 통합 및 라우팅 등록
src/pages/my/index.tsx, src/app/App.tsx, src/shared/constants/routes.ts
MyPage에서 avatarUrl 전달과 탈퇴 라우팅 상수 사용을 반영하고, App.tsx에 PROFILE_NICKNAME/PASSWORD/EMAIL/SOCIAL/WITHDRAW 경로를 등록했습니다.
배럴(export) 확장
src/features/user/me/index.ts
API, 훅, 기능 훅, 타입 재export 목록을 확장했습니다.

🎯 4 (Complex) | ⏱️ ~45 minutes

Suggested Reviewers

  • kim3360
  • limtjdghks
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 1.92% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed PR 제목이 마이페이지 API 연동과 UI 추가라는 변경의 핵심을 명확히 요약하고 있어 충분히 구체적이고 명확합니다.
Description check ✅ Passed PR 설명이 저장소 템플릿의 필수 섹션(ID, 변경 내용, 구현 사항, 참고 사항)을 모두 포함하고 있으며, 상세한 구현 내용과 엔드포인트 목록이 잘 정리되어 있습니다.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/ALT-234

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/features/user/me/hooks/useUserMeMutations.ts`:
- Around line 24-26: The current useCurrentUserScope() forcibly falls back to
'USER', risking wrong endpoints while scope is unresolved; change
useCurrentUserScope (and any callers of it) to NOT default to 'USER'—either
return undefined/null when useAuthStore(state => state.scope) is missing or
throw a clear error from useCurrentUserScope() so mutations (e.g., user-me
mutation hooks) are blocked until scope is resolved; update callers to check the
returned value and prevent or abort the mutation rather than sending requests to
the wrong endpoint.

In `@src/pages/my/profile/email/index.tsx`:
- Around line 20-105: The page currently owns the entire email verification
state machine (sessionId, email, code, message, successMessage) and the action
handlers (handleSend, handleVerify, handleUpdate, handleDelete) which breaks
layering; extract this workflow into a feature hook (e.g. useEmailVerification
or useEmailEmailFlow) that imports the existing mutations
(useSendEmailVerificationMutation, useVerifyEmailCodeMutation,
useUpdateEmailMutation, useDeleteEmailMutation) and encapsulates all state
(email, code, sessionId, message, successMessage), derived booleans (isPending,
canSend, canVerify, canUpdate, canDelete, trimmedEmail) and the methods
clearMessages/send/verify/update/delete; have the hook return the state,
booleans, and action functions so the page component only composes UI and calls
those returned functions (replace uses of sessionId, handleSend, handleVerify,
handleUpdate, handleDelete, clearMessages, message, successMessage, isPending,
canSend, canVerify, canUpdate, canDelete in the page).

In `@src/pages/my/profile/index.tsx`:
- Around line 100-161: ProfileEditPage contains file upload/delete business
logic (handlers handleAvatarUpload, handleAvatarFileChange,
handleOpenDeleteModal, handleDeleteAvatar), mutation usage
(useUpdateProfileImageMutation, useDeleteProfileImageMutation), uploadAppFile
calls and error state (imageError, deleteModalOpen) that should be moved to a
feature hook; extract this into a new hook (e.g., useProfileImageEditor in
src/features/user/me) that encapsulates state (imageError, isImagePending,
deleteModalOpen), side effects (calling uploadAppFile, mutateAsync on
update/delete mutations), and handlers (triggerFileInput, onFileChange,
openDeleteModal, confirmDelete) and returns those values/handlers; then simplify
ProfileEditPage to only call useProfileImageEditor and wire returned handlers to
UI, removing direct API/error logic from the page.

In `@src/pages/my/profile/nickname/index.tsx`:
- Around line 11-41: Extract the nickname-change business flow from the page
into a feature hook (e.g., useChangeNickname or useUpdateNicknameUseCase): move
validation (trim/length/duplicate check against user.nickname), the call to
useUpdateNicknameMutation (mutateAsync), and error mapping
(getAxiosErrorMessage) into that hook and expose a simple API like { nickname,
setNickname, message, canSubmit, submit } for the page to consume; update the
page to only import useUserMe for initial value and the new hook, render
inputs/button/messages, call submit() and on success let the hook return a
success flag or throw so the page can call navigate(ROUTES.MY.PROFILE, {
replace: true }) — keep references to useUpdateNicknameMutation,
trimmedNickname/canSubmit logic, handleSubmit behavior, and getAxiosErrorMessage
inside the new feature hook.

In `@src/pages/my/profile/password/index.tsx`:
- Around line 10-54: Move the password policy and submission orchestration out
of PasswordEditPage into a new feature hook (e.g., usePasswordUpdateFeature)
that encapsulates isPasswordFormatValid, the submit flow that calls
useUpdatePasswordMutation.mutateAsync, error handling via getAxiosErrorMessage,
and navigation to ROUTES.MY.PROFILE; then have PasswordEditPage only manage
local form state (currentPassword, newPassword, confirmPassword) and call the
hook's handlers (validate, handleSubmit, and canSubmit) instead of containing
isPasswordFormatValid, handleSubmit, and canSubmit logic directly so policy and
mutation orchestration live in the feature layer and the page only composes the
form.

In `@src/pages/my/profile/social/index.tsx`:
- Around line 51-107: Extract the social linking/unlinking logic from the page
into a feature hook (e.g., create useSocialAccountLinking) that encapsulates
state and actions: move handleLink and handleUnlink implementations, state
setters (setMessage, setPendingProvider), and all provider-specific flows
(requestFreshKakaoAuthorizationCode, getKakaoOAuthRedirectUri, loginWithApple)
plus the mutations (linkSocialAccountMutation, unlinkSocialAccountMutation) and
error handling (getAxiosErrorMessage) into that hook; have the hook expose:
pendingProvider, message, link(provider: SocialProvider) and unlink(provider:
SocialProvider) so the page keeps only rendering PROVIDERS and wiring onClick to
link/unlink, and remove any business logic from
src/pages/my/profile/social/index.tsx.

In `@src/pages/my/withdraw/index.tsx`:
- Around line 18-39: Move the entire withdrawal flow out of the page component
into a new hook (e.g., useWithdrawUser) so the page only binds UI state and
calls an action; the hook should accept dependencies (withdrawUserMutation,
logout, navigate, scope) or internally import them, expose a performWithdraw()
async function and any loading/error state, and encapsulate confirmation,
mutateAsync call, logout, navigation to ROUTES.AUTH.LOGIN, and error fallback
via getAxiosErrorMessage. Replace handleWithdraw in the page with a simple call
to performWithdraw() and keep checked/setMessage only for UI state; ensure the
hook returns errors/messages so the page can display setMessage without
containing business logic.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 9f863a58-cd2b-42d3-b7b0-44e1f2c05d84

📥 Commits

Reviewing files that changed from the base of the PR and between 15f63bc and b2bb695.

📒 Files selected for processing (15)
  • src/app/App.tsx
  • src/features/user/me/api/user.ts
  • src/features/user/me/hooks/useUserMe.ts
  • src/features/user/me/hooks/useUserMeMutations.ts
  • src/features/user/me/index.ts
  • src/features/user/me/types/user.ts
  • src/pages/my/index.tsx
  • src/pages/my/profile/email/index.tsx
  • src/pages/my/profile/index.tsx
  • src/pages/my/profile/nickname/index.tsx
  • src/pages/my/profile/password/index.tsx
  • src/pages/my/profile/social/index.tsx
  • src/pages/my/withdraw/index.tsx
  • src/shared/constants/routes.ts
  • src/shared/lib/queryKeys.ts

Comment thread src/features/user/me/hooks/useUserMeMutations.ts Outdated
Comment thread src/pages/my/profile/email/index.tsx Outdated
Comment thread src/pages/my/profile/index.tsx Outdated
Comment thread src/pages/my/profile/nickname/index.tsx
Comment thread src/pages/my/profile/password/index.tsx Outdated
Comment thread src/pages/my/profile/social/index.tsx Outdated
Comment thread src/pages/my/withdraw/index.tsx
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/features/user/me/hooks/useEmailVerificationFlow.ts`:
- Line 20: The local email state (const [email, setEmailState] =
useState(currentEmail)) isn't synced when currentEmail updates; add an effect in
useEmailVerificationFlow.ts that watches currentEmail and calls
setEmailState(currentEmail) when it changes (ensure you guard against
undefined/null if needed) so the controlled input represented by email stays in
sync with updates to currentEmail.

In `@src/features/user/me/hooks/usePasswordUpdateFeature.ts`:
- Around line 8-13: The password validation uses trimmed = value.trim() but the
request still sends the original value, causing mismatch for inputs with
surrounding spaces; update usePasswordUpdateFeature to use a single canonical
string for both validation and transmission (e.g., replace uses of raw value
with the trimmed variable when performing the length/regex checks and when
packaging the password to send), and apply the same change to the other
occurrence referenced (lines 47-48) so validation and network submission use the
identical string.

In `@src/features/user/me/hooks/useProfileImageEditor.ts`:
- Line 2: The import of uploadAppFile from
"`@/features/store-register/api/workspaceFileUpload`" inside useProfileImageEditor
(src/features/user/me/hooks/useProfileImageEditor.ts) breaks feature-layer
boundaries; move the upload API into the entities or shared layer (or add a
passthrough module in entities/shared) and update useProfileImageEditor to
import from that new module instead of the store-register feature; ensure the
symbol name uploadAppFile is preserved (or export a renamed facade) and update
any related imports/exports and tests/build configs that reference
workspaceFileUpload so the features layer only imports from entities/shared.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 7ff37cbf-47d0-4d88-a40e-6f7944ed2868

📥 Commits

Reviewing files that changed from the base of the PR and between b2bb695 and 4b1cc78.

📒 Files selected for processing (15)
  • src/features/user/me/hooks/useChangeNickname.ts
  • src/features/user/me/hooks/useEmailVerificationFlow.ts
  • src/features/user/me/hooks/usePasswordUpdateFeature.ts
  • src/features/user/me/hooks/useProfileImageEditor.ts
  • src/features/user/me/hooks/useSocialAccountLinking.ts
  • src/features/user/me/hooks/useUserMe.ts
  • src/features/user/me/hooks/useUserMeMutations.ts
  • src/features/user/me/hooks/useWithdrawUserFlow.ts
  • src/features/user/me/index.ts
  • src/pages/my/profile/email/index.tsx
  • src/pages/my/profile/index.tsx
  • src/pages/my/profile/nickname/index.tsx
  • src/pages/my/profile/password/index.tsx
  • src/pages/my/profile/social/index.tsx
  • src/pages/my/withdraw/index.tsx

Comment thread src/features/user/me/hooks/useEmailVerificationFlow.ts
Comment thread src/features/user/me/hooks/usePasswordUpdateFeature.ts
Comment thread src/features/user/me/hooks/useProfileImageEditor.ts Outdated
@dohy-eon
Copy link
Copy Markdown
Member Author

@CodeRabbit 리뷰 또 해줘

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 21, 2026

@dohy-eon 네, PR #42 전체를 다시 리뷰할게요! 잠시만 기다려 주세요.

(ˆ•ω•ˆ)

✅ Actions performed

Full review triggered.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
src/app/App.tsx (1)

31-37: ⚡ Quick win

프로필 관련 페이지들을 lazy loading으로 전환하여 초기 번들 크기를 최적화하세요.

현재 MyPage 및 프로필 하위 5개 페이지(EmailEditPage, NicknameEditPage, PasswordEditPage, SocialAccountPage, WithdrawPage)가 모두 직접 import되어 초기 번들에 포함됩니다. 이들은 사용 빈도가 낮아 lazy loading 적용 시 초기 로딩 성능을 개선할 수 있습니다.

♻️ lazy loading 적용 예시

기존 직접 import를 제거하고:

-import { MyPage } from '`@/pages/my`'
-import { ProfileEditPage } from '`@/pages/my/profile`'
-import { EmailEditPage } from '`@/pages/my/profile/email`'
-import { NicknameEditPage } from '`@/pages/my/profile/nickname`'
-import { PasswordEditPage } from '`@/pages/my/profile/password`'
-import { SocialAccountPage } from '`@/pages/my/profile/social`'
-import { WithdrawPage } from '`@/pages/my/withdraw`'

lazy import로 변경:

+const MyPage = lazy(async () => {
+  const m = await import('`@/pages/my`')
+  return { default: m.MyPage }
+})
+
+const ProfileEditPage = lazy(async () => {
+  const m = await import('`@/pages/my/profile`')
+  return { default: m.ProfileEditPage }
+})
+
+const EmailEditPage = lazy(async () => {
+  const m = await import('`@/pages/my/profile/email`')
+  return { default: m.EmailEditPage }
+})
+
+const NicknameEditPage = lazy(async () => {
+  const m = await import('`@/pages/my/profile/nickname`')
+  return { default: m.NicknameEditPage }
+})
+
+const PasswordEditPage = lazy(async () => {
+  const m = await import('`@/pages/my/profile/password`')
+  return { default: m.PasswordEditPage }
+})
+
+const SocialAccountPage = lazy(async () => {
+  const m = await import('`@/pages/my/profile/social`')
+  return { default: m.SocialAccountPage }
+})
+
+const WithdrawPage = lazy(async () => {
+  const m = await import('`@/pages/my/withdraw`')
+  return { default: m.WithdrawPage }
+})

각 라우트에 Suspense 적용:

-          <Route path={ROUTES.MY.ROOT} element={<MyPage />} />
+          <Route
+            path={ROUTES.MY.ROOT}
+            element={
+              <Suspense fallback={null}>
+                <MyPage />
+              </Suspense>
+            }
+          />

나머지 프로필 관련 라우트들도 동일하게 Suspense로 감싸주세요.

Also applies to: 112-125, 186-186

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/app/App.tsx` around lines 31 - 37, Replace the direct imports of MyPage
and its profile subpages (MyPage, ProfileEditPage, EmailEditPage,
NicknameEditPage, PasswordEditPage, SocialAccountPage, WithdrawPage) with
React.lazy dynamic imports and ensure each route using these components is
wrapped with React.Suspense (provide a fallback) so they load only when visited;
update any route definitions or parent components that render ProfileEditPage
and the five subpages to use the lazy-loaded components and Suspense boundaries
(keep existing export/names intact so route references to MyPage,
ProfileEditPage, EmailEditPage, NicknameEditPage, PasswordEditPage,
SocialAccountPage, WithdrawPage continue to work).
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/features/user/me/hooks/useProfileImageEditor.ts`:
- Around line 16-17: The isImagePending flag currently only includes
updateProfileImageMutation.isPending and deleteProfileImageMutation.isPending,
so include the upload pending state from uploadAppFile (or the mutation/wrapper
that performs file uploads) in that boolean to block actions during upload;
update the isImagePending expression in useProfileImageEditor (and any other
similar checks in the same file around lines 24-41) to OR in the upload
mutation's isPending/awaiting state (e.g., uploadAppFileMutation.isPending or
uploadAppFile.isPending) so delete/retry/update actions are disabled while an
upload is in progress.

In `@src/features/user/me/hooks/useWithdrawUserFlow.ts`:
- Around line 15-24: Add a re-entry guard inside performWithdraw to prevent
duplicate destructive requests by checking the mutation/loading state (e.g.
withdrawUserMutation.isLoading) or a local isPending flag at the very start of
performWithdraw and returning early if already pending; ensure this check runs
before showing the confirmation prompt and/or before calling
withdrawUserMutation.mutateAsync(), so performWithdraw, withdrawUserMutation,
and any new isPending state are used to block concurrent invocations.

---

Nitpick comments:
In `@src/app/App.tsx`:
- Around line 31-37: Replace the direct imports of MyPage and its profile
subpages (MyPage, ProfileEditPage, EmailEditPage, NicknameEditPage,
PasswordEditPage, SocialAccountPage, WithdrawPage) with React.lazy dynamic
imports and ensure each route using these components is wrapped with
React.Suspense (provide a fallback) so they load only when visited; update any
route definitions or parent components that render ProfileEditPage and the five
subpages to use the lazy-loaded components and Suspense boundaries (keep
existing export/names intact so route references to MyPage, ProfileEditPage,
EmailEditPage, NicknameEditPage, PasswordEditPage, SocialAccountPage,
WithdrawPage continue to work).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: abc8fc9c-521f-41d3-9a74-b1c48b1eefbd

📥 Commits

Reviewing files that changed from the base of the PR and between 15f63bc and b41955d.

📒 Files selected for processing (23)
  • src/app/App.tsx
  • src/features/store-register/api/workspaceFileUpload.ts
  • src/features/user/me/api/user.ts
  • src/features/user/me/hooks/useChangeNickname.ts
  • src/features/user/me/hooks/useEmailVerificationFlow.ts
  • src/features/user/me/hooks/usePasswordUpdateFeature.ts
  • src/features/user/me/hooks/useProfileImageEditor.ts
  • src/features/user/me/hooks/useSocialAccountLinking.ts
  • src/features/user/me/hooks/useUserMe.ts
  • src/features/user/me/hooks/useUserMeMutations.ts
  • src/features/user/me/hooks/useWithdrawUserFlow.ts
  • src/features/user/me/index.ts
  • src/features/user/me/types/user.ts
  • src/pages/my/index.tsx
  • src/pages/my/profile/email/index.tsx
  • src/pages/my/profile/index.tsx
  • src/pages/my/profile/nickname/index.tsx
  • src/pages/my/profile/password/index.tsx
  • src/pages/my/profile/social/index.tsx
  • src/pages/my/withdraw/index.tsx
  • src/shared/api/appFileUpload.ts
  • src/shared/constants/routes.ts
  • src/shared/lib/queryKeys.ts

Comment thread src/features/user/me/hooks/useProfileImageEditor.ts Outdated
Comment thread src/features/user/me/hooks/useWithdrawUserFlow.ts
Copy link
Copy Markdown
Member

@limtjdghks limtjdghks left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

코드래빗은 신이야

드디어 마이페이지 기능이 연동이 되엇군여 회원 탈퇴 기능이 생긴 김에 제 인생도 탈퇴하고싶네요 고생하셨습니다

Comment on lines +7 to +14
function isPasswordFormatValid(value: string): boolean {
const trimmed = value.trim()
if (trimmed.length < 8 || trimmed.length > 16) return false
const hasLetter = /[A-Za-z]/.test(trimmed)
const hasNumber = /\d/.test(trimmed)
const hasSpecial = /[!@#$%^&*(),.?":{}|<>]/.test(trimmed)
return hasLetter && hasNumber && hasSpecial
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이거 회원가입 할때도 동일한 규칙 사용할 것 같은데 공용 유틸로 빼서 통일하면 좋을 듯 싶습니다

Comment on lines +28 to +36
const validate = (): string => {
if (!isPasswordFormatValid(newPassword)) {
return '새 비밀번호는 8~16자, 영문·숫자·특수문자를 모두 포함해야 합니다.'
}
if (newPassword !== confirmPassword) {
return '새 비밀번호가 일치하지 않습니다.'
}
return ''
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

얘도 회원가입 페이지에서 사용할 수 있는 것 맞나욧? 얘도 같이 하면 조을 덧

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

하아아아 하루가 너무 짧네요 ...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants