LC-3027 추상화 작업 5 2#2404
Hidden character warning
Conversation
- page.tsx는 server component로 유지해 metadata(noindex)를 노출하고, 본문은 DevPage 클라이언트 컴포넌트로 분리 - useGetUserAdmin으로 admin 여부 확인 후 미로그인/일반 사용자에겐 "관리자 전용 페이지입니다" 안내 노출 - MentorGuard와 동일하게 isInitialized 가드를 둬 새로고침 시 깜빡임 방지 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- SocialLogin: .module.scss 삭제 후 모든 스타일을 Tailwind 인라인 클래스로 이전, 외부/내부 div를 1개로 병합 - SocialLogin: useSearchParams 호출부를 SocialLoginContent로 분리하고 AsyncBoundary로 감싸 Next.js 정적 렌더링 deopt 경고 해소 - PrivacyPolicyModal: dead code인 .module.scss 삭제, classnames(cn) 의존 제거 - PrivacyPolicyModal: block/hidden 토글을 opacity+pointer-events 기반 transition-opacity로 교체하여 fade in/out 추가, role/aria-modal/aria-hidden 접근성 속성 추가 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- 페이지 로직을 domain/auth/{LoginPage, hooks/useLogin}로 분리 (signup 패턴 일치)
- 도메인 로컬 유틸·UI 추출 (hashEmail, sanitizeRedirect, TextLink)
- 자격증명 에러 toast 제거하고 인라인 메시지 + 입력 border 빨강으로 통일
- 재시도 시 직전 에러 즉시 클리어, isPending 동안 버튼 라벨 변경
- 에러 영역 min-height 고정으로 버튼 위치 시프트 제거
- buttonDisabled를 파생값으로 전환(useState/useEffect 동기화 제거)
- onError에서 ApiError 인스턴스 분기 처리로 status 추출 실패 버그 해결
(axios 인터셉터가 응답 에러를 ApiError로 래핑하는데 AxiosError로만 캐스팅해
모든 분기를 건너뛰고 fallback 메시지가 노출되던 문제)
- sanitizeRedirect로 //·/\ 등 Open Redirect 우회 차단
(useLogin·useSignup 두 진입점에 모두 적용)
- 소셜 콜백 진행 중 isLoggedIn effect 의 중복 router.push 가드 추가
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- SocialLogin: 렌더 중 alert 부작용 제거하고 onClick 핸들러로 이동 - challenge dashboard: 부모 useSuspenseQuery와 키가 동일해 트리거되지 않는 내부 AsyncBoundary 제거 - useLogin: 소셜 콜백 result 쿼리의 JSON.parse를 try/catch로 가드 + 실패 시 Sentry 보고 후 조기 종료 - PrivacyPolicyModal: 닫힘 시 invisible 토글로 키보드 포커스 차단 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ient into LC-3027-추상화-작업-5-2 # Conflicts: # apps/web/src/app/(user)/challenge/[applicationId]/[programId]/page.tsx
- ReportCreditDetailPage를 shell/Content로 분리해 useSuspenseQuery + AsyncBoundary 패턴 적용 - 기존 3중 삼항(로딩/에러/없음) 보일러플레이트 제거, credit/CreditDetailPage와 일치 - api/report.ts에 reportPaymentDetailQueryOptions 순수 추가(기존 훅은 보존) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- admin api에서 admin 어디에서도 참조되지 않는 export 61개 제거 (web 복사본에서만 사용) - 삭제로 고아가 된 내부 const/import 동반 정리 - 전부 비어버린 coupon.ts는 파일째 삭제 (import처 0개 확인) - 검증: ESLint 0 errors, 본 변경이 추가한 타입에러 0건(TS2305 전무) (admin 기존 typecheck 에러는 경로 alias 미해결 등 본 작업과 무관) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- CreditList를 shell/Content로 분리해 useSuspenseQuery + AsyncBoundary 패턴 적용 - 기존 isLoading/isError 삼항 보일러플레이트 제거, 헤더는 로딩 중에도 노출 유지 - api/payment.ts에 paymentListQueryOptions 추가, 유일 소비처였던 usePaymentQuery는 제거 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…l 유지) - Profile을 shell + ProfileContent로 분리, useSuspenseQuery(userQueryOptions) 사용 - 수동 isLoading 스켈레톤 → pendingFallback(ProfileSkeleton)으로 이동 - 에러 시 기존 기본값 카드(rejectedFallback)로 graceful 동작 보존 - suspense는 enabled 불가하므로 shell에서 isLoggedIn 가드 → 비로그인 시 요청 없이 기본값 카드 - 성공/에러/비로그인 카드 JSX를 ProfileCard로 통합 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
web 어디서도 import되지 않는 죽은 api 모듈 정리 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
vertical(DDD) 구조에 맞춰 단일 도메인에서만 쓰는 api 클라이언트를 해당 도메인으로 이동: - domain/challenge/api: attendance, attendanceSchema, challengeQuestion, presignedUrl - domain/faq/api: faq - domain/mentor/api: mentor, challengeMentorGuide(+Schema, +test) importer 경로 일괄 갱신. 공유 의존(challengeSchema, userExperienceSchema, mentorSchema)은 api/ 유지. typecheck/lint/prettier 통과, 동작 변경 없음. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Code Review
This pull request performs a major cleanup of unused schemas, types, and queries across various API files, while refactoring and migrating several API modules and hooks into domain-specific folders (such as attendance, challengeQuestion, presignedUrl, and faq) to align with the domain-based folder structure. It also updates components like CreditList and Profile to utilize useSuspenseQuery and AsyncBoundary for improved loading and error state handling. The review feedback recommends further improving domain cohesion and reducing coupling by moving mentorSchema.ts and the useMentorChallengeListQuery hook into the domain/mentor/api/ directory.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| type PatchAttendanceMentorReq, | ||
| PostAdminChallengeMentorReq, | ||
| } from './mentorSchema'; | ||
| } from '@/api/mentor/mentorSchema'; |
There was a problem hiding this comment.
도메인 기반 폴더 구조화 리팩토링의 일환으로 mentor.ts 파일이 domain/mentor/api/로 이동된 것을 확인했습니다. 하지만 의존성인 mentorSchema.ts 파일은 아직 api/ 폴더에 남아있어 domain 폴더와 api 폴더 간의 의존성이 발생하고 있습니다.
스타일 가이드의 도메인 기반 폴더 구조 원칙(572-578행)에 따라, 관련된 파일들은 같은 도메인 내에 위치시켜 응집도를 높이는 것이 좋습니다.
apps/web/src/api/mentor/mentorSchema.ts 파일을 apps/web/src/domain/mentor/api/mentorSchema.ts로 이동하고, import 경로를 상대 경로로 수정하는 것을 제안합니다.
| } from '@/api/mentor/mentorSchema'; | |
| } from './mentorSchema'; |
References
- 도메인 기반 폴더 구조 원칙에 따라 관련된 파일들은 같은 도메인 내에 위치시켜 응집도를 높여야 합니다. 현재 domain/mentor/api/mentor.ts 파일이 api/mentor/mentorSchema.ts에 의존하고 있어 응집도가 저하됩니다. (link)
| import { useMentorGuideListQuery } from '@/domain/mentor/api/challengeMentorGuide'; | ||
| import { useMentorChallengeListQuery } from '@/api/user/user'; | ||
| import type { ChallengeMentorGuideItem } from '@/api/challenge-mentor-guide/challengeMentorGuideSchema'; | ||
| import type { ChallengeMentorGuideItem } from '@/domain/mentor/api/challengeMentorGuideSchema'; |
There was a problem hiding this comment.
이 파일에서 useMentorGuideListQuery와 ChallengeMentorGuideItem의 import 경로가 도메인 기반 구조에 맞게 잘 수정되었습니다. 하지만 바로 아래 useMentorChallengeListQuery 훅은 여전히 api/user/user.ts에서 직접 import하고 있어 구조적 일관성이 부족해 보입니다.
스타일 가이드(59, 66-70행)는 도메인 간 의존성을 최소화하고 응집도를 높이는 것을 강조합니다. useMentorChallengeListQuery 훅은 멘토의 챌린지 목록을 가져오는 기능으로, mentor 도메인과 강하게 연관되어 있습니다.
따라서 이 훅을 apps/web/src/domain/mentor/api/ 폴더로 이동하여 mentor 도메인의 응집도를 높이고, 다른 도메인과의 결합도를 낮추는 것을 권장합니다.
References
- 도메인 간 직접 import는 피해야 하며, 각 도메인은 독립적으로 유지되어야 합니다. domain/mentor 컴포넌트가 api/user에 직접 의존하는 것은 결합도를 높입니다. (link)
연관 작업