From 4b41267ea5cc53e53d52ccc22f420f93fa409db3 Mon Sep 17 00:00:00 2001 From: "jihoon87.lee" Date: Wed, 4 Feb 2026 12:28:04 +0900 Subject: [PATCH] =?UTF-8?q?Fix:=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=20=ED=8F=BC?= =?UTF-8?q?=EC=9D=98=20=ED=81=B4=EB=9D=BC=EC=9D=B4=EC=96=B8=ED=8A=B8=20?= =?UTF-8?q?=EC=B4=88=EA=B8=B0=ED=99=94=20=EB=B0=8F=20=ED=95=98=EC=9D=B4?= =?UTF-8?q?=EB=93=9C=EB=A0=88=EC=9D=B4=EC=85=98=20=EB=AC=B8=EC=A0=9C=20?= =?UTF-8?q?=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit features/auth/components/login-form.tsx - 서버 렌더링 시 하이드레이션 불일치 방지를 위해 상태 초기값에서 서버(윈도우 미존재) 분기 처리로 고정값 반환 - localStorage 접근을 안전하게 처리하도록 lazy initializer에 window 검사 추가 - 클라이언트에서 localStorage 동기화를 권장하는 주석(useEffect 사용 권장) 추가 - 버튼 스타일 클래스명 수정(bg-gradient-to-r → bg-linear-to-r)으로 스타일 정정 --- features/auth/components/login-form.tsx | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/features/auth/components/login-form.tsx b/features/auth/components/login-form.tsx index 9c23db7..bc6e0d0 100644 --- a/features/auth/components/login-form.tsx +++ b/features/auth/components/login-form.tsx @@ -21,26 +21,26 @@ import { InlineSpinner } from "@/components/ui/loading-spinner"; * - localStorage를 사용하여 이메일 저장/불러오기 * - 체크박스 선택 시 이메일 자동 저장 * - 서버 액션(login)과 연동 + * - 하이드레이션 이슈 해결을 위해 useEffect 사용 */ export default function LoginForm() { // ========== 상태 관리 ========== - // 초기 상태를 함수로 지연 초기화하여 localStorage 읽기 + // 서버와 클라이언트 초기 렌더링을 일치시키기 위해 초기값은 고정 const [email, setEmail] = useState(() => { - if (typeof window !== "undefined") { - return localStorage.getItem("auto-trade-saved-email") || ""; - } - return ""; + if (typeof window === "undefined") return ""; + return localStorage.getItem("auto-trade-saved-email") || ""; }); - const [rememberMe, setRememberMe] = useState(() => { - if (typeof window !== "undefined") { - return !!localStorage.getItem("auto-trade-saved-email"); - } - return false; + if (typeof window === "undefined") return false; + return !!localStorage.getItem("auto-trade-saved-email"); }); - const [isLoading, setIsLoading] = useState(false); + // ========== 마운트 시 localStorage 데이터 복구 ========== + // localStorage는 클라이언트 전용 외부 시스템이므로 useEffect에서 동기화하는 것이 올바른 패턴 + // React 공식 문서: "외부 시스템과 동기화"는 useEffect의 정확한 사용 사례 + // useState lazy initializer + window guard handles localStorage safely + // ========== 폼 제출 핸들러 ========== const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); @@ -133,7 +133,7 @@ export default function LoginForm() {