From 8098f93810bf9463f1f5be7a3580a9d98222ef30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=ED=83=80=EB=9E=98?= <85001878+meowTarae@users.noreply.github.com> Date: Wed, 9 Jul 2025 21:47:36 +0900 Subject: [PATCH 01/16] =?UTF-8?q?Feat(#17):=20Logo=20Icon=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/icons/logo.svg | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 public/icons/logo.svg diff --git a/public/icons/logo.svg b/public/icons/logo.svg new file mode 100644 index 0000000..94ba2b1 --- /dev/null +++ b/public/icons/logo.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + From 8a06c2db161cdae7d2a66b0e3c4ac80aa6925cdc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=ED=83=80=EB=9E=98?= <85001878+meowTarae@users.noreply.github.com> Date: Wed, 9 Jul 2025 22:15:43 +0900 Subject: [PATCH 02/16] =?UTF-8?q?Feat(#17):=20=EB=A1=9C=EA=B7=B8=EC=9D=B8?= =?UTF-8?q?=20=EC=8B=9C=20=20=EC=82=AC=EC=9A=A9=EB=90=98=EB=8A=94=20social?= =?UTF-8?q?=20icons=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/icons/login/facebook.svg | 3 +++ public/icons/login/google.svg | 9 +++++++++ public/icons/login/kakao.svg | 3 +++ public/icons/login/naver.svg | 3 +++ public/icons/login/phone.svg | 3 +++ 5 files changed, 21 insertions(+) create mode 100644 public/icons/login/facebook.svg create mode 100644 public/icons/login/google.svg create mode 100644 public/icons/login/kakao.svg create mode 100644 public/icons/login/naver.svg create mode 100644 public/icons/login/phone.svg diff --git a/public/icons/login/facebook.svg b/public/icons/login/facebook.svg new file mode 100644 index 0000000..7c45f4c --- /dev/null +++ b/public/icons/login/facebook.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/icons/login/google.svg b/public/icons/login/google.svg new file mode 100644 index 0000000..3ebc98c --- /dev/null +++ b/public/icons/login/google.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/public/icons/login/kakao.svg b/public/icons/login/kakao.svg new file mode 100644 index 0000000..3ba3c72 --- /dev/null +++ b/public/icons/login/kakao.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/icons/login/naver.svg b/public/icons/login/naver.svg new file mode 100644 index 0000000..f3ee1a8 --- /dev/null +++ b/public/icons/login/naver.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/icons/login/phone.svg b/public/icons/login/phone.svg new file mode 100644 index 0000000..56a8273 --- /dev/null +++ b/public/icons/login/phone.svg @@ -0,0 +1,3 @@ + + + From 95b872d8a5255a3e8ae2e67d2459039c2cd5f347 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=ED=83=80=EB=9E=98?= <85001878+meowTarae@users.noreply.github.com> Date: Wed, 9 Jul 2025 22:19:22 +0900 Subject: [PATCH 03/16] =?UTF-8?q?Refactor(#17):=20SignUpButton=20=ED=83=80?= =?UTF-8?q?=EC=9E=85=20=EB=B6=84=EB=A6=AC=20=EB=A6=AC=ED=8C=A9=ED=86=A0?= =?UTF-8?q?=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../feature/SignInPage/SignupButton.tsx | 66 +++++++++++++++++++ .../feature/SignInPage/SignUpButton.ts | 9 +++ 2 files changed, 75 insertions(+) create mode 100644 src/components/feature/SignInPage/SignupButton.tsx create mode 100644 src/types/components/feature/SignInPage/SignUpButton.ts diff --git a/src/components/feature/SignInPage/SignupButton.tsx b/src/components/feature/SignInPage/SignupButton.tsx new file mode 100644 index 0000000..e4e4b1c --- /dev/null +++ b/src/components/feature/SignInPage/SignupButton.tsx @@ -0,0 +1,66 @@ +import { SignupButtonProps } from "@/types/components/feature/SignInPage/SignUpButton"; +import Image from "next/image"; + +export default function SignupButton({ + type, + font = "body-5", + iconSize = 24, +}: SignupButtonProps) { + const buttonTypes = { + kakao: { + icon: "/icons/login/kakao.svg", + text: "text-grey-800", + background: "bg-[#FEE500]", + hover: "hover:bg-[#FCDA00]", + phrase: "카카오로 시작하기", + }, + naver: { + icon: "/icons/login/naver.svg", + text: "text-white", + background: "bg-[#03C75A]", + hover: "hover:bg-[#03C139]", + phrase: "네이버로 시작하기", + }, + facebook: { + icon: "/icons/login/facebook.svg", + text: "text-white", + background: "bg-[#1A77F2]", + hover: "hover:bg-[#006CE0]", + phrase: "페이스북으로 시작하기", + }, + google: { + icon: "/icons/login/google.svg", + text: "text-grey-600", + background: "bg-white", + hover: "hover:bg-background", + phrase: "구글로 시작하기", + }, + phone: { + icon: "/icons/login/phone.svg", + text: "text-white", + background: "bg-primary-400", + hover: "hover:bg-primary-300", + phrase: "전화번호로 시작하기", + }, + }; + + const currentStyle = buttonTypes[type]; + const typeClasses = `${currentStyle.background} ${currentStyle.text} ${currentStyle.hover} ${currentStyle.phrase}`; + + const baseClasses = `flex items-center justify-center rounded-xl gap-2 + w-full h-12 + focus:outline-none disabled:cursor-not-allowed cursor-pointer truncate text-${font}`; + + return ( + + ); +} diff --git a/src/types/components/feature/SignInPage/SignUpButton.ts b/src/types/components/feature/SignInPage/SignUpButton.ts new file mode 100644 index 0000000..fbaeb8c --- /dev/null +++ b/src/types/components/feature/SignInPage/SignUpButton.ts @@ -0,0 +1,9 @@ +import { FontSizeType } from "@/constants/design"; + +export interface SignupButtonProps { + type: ButtonType; + font?: FontSizeType; + iconSize?: number; +} + +export type ButtonType = "kakao" | "naver" | "facebook" | "google" | "phone"; From e93a3ba81499694b6b0be08fb1b917253a5c55f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=ED=83=80=EB=9E=98?= <85001878+meowTarae@users.noreply.github.com> Date: Wed, 9 Jul 2025 22:24:10 +0900 Subject: [PATCH 04/16] =?UTF-8?q?Feat(#17):=20SignUpButton=EC=97=90=20clas?= =?UTF-8?q?sname=20props=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/feature/SignInPage/SignupButton.tsx | 7 +++++-- src/types/components/feature/SignInPage/SignUpButton.ts | 1 + 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/components/feature/SignInPage/SignupButton.tsx b/src/components/feature/SignInPage/SignupButton.tsx index e4e4b1c..8176584 100644 --- a/src/components/feature/SignInPage/SignupButton.tsx +++ b/src/components/feature/SignInPage/SignupButton.tsx @@ -5,6 +5,7 @@ export default function SignupButton({ type, font = "body-5", iconSize = 24, + className, }: SignupButtonProps) { const buttonTypes = { kakao: { @@ -31,7 +32,7 @@ export default function SignupButton({ google: { icon: "/icons/login/google.svg", text: "text-grey-600", - background: "bg-white", + background: "bg-white border border-border", hover: "hover:bg-background", phrase: "구글로 시작하기", }, @@ -51,8 +52,10 @@ export default function SignupButton({ w-full h-12 focus:outline-none disabled:cursor-not-allowed cursor-pointer truncate text-${font}`; + const buttonClasses = `${typeClasses} ${baseClasses} ${className}`; + return ( - + + + ); } From 9ebeb850a726e54e9e3fb82224de810e4a4bcf3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=ED=83=80=EB=9E=98?= <85001878+meowTarae@users.noreply.github.com> Date: Mon, 14 Jul 2025 17:53:13 +0900 Subject: [PATCH 08/16] =?UTF-8?q?Feat(#17):=20Input=20=EC=BB=B4=ED=8F=AC?= =?UTF-8?q?=EB=84=8C=ED=8A=B8=20autoComplete=20=EC=86=8D=EC=84=B1=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/commons/Input/index.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/commons/Input/index.tsx b/src/components/commons/Input/index.tsx index 81f119b..f60e2bf 100644 --- a/src/components/commons/Input/index.tsx +++ b/src/components/commons/Input/index.tsx @@ -71,6 +71,7 @@ export default function Input({ type={ iconType === "password" ? (isVisible ? "text" : "password") : "text" } + autoComplete='off' /> {iconType === "text" ? ( Date: Mon, 14 Jul 2025 17:53:39 +0900 Subject: [PATCH 09/16] =?UTF-8?q?Feat(#17):=20=EB=A1=9C=EA=B7=B8=EC=9D=B8?= =?UTF-8?q?=20=ED=8E=98=EC=9D=B4=EC=A7=80=20ui=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/(auth)/sign-in/phone/page.tsx | 121 +++++++++++++++++++++++++- 1 file changed, 120 insertions(+), 1 deletion(-) diff --git a/src/app/(auth)/sign-in/phone/page.tsx b/src/app/(auth)/sign-in/phone/page.tsx index e08ff3a..d91e068 100644 --- a/src/app/(auth)/sign-in/phone/page.tsx +++ b/src/app/(auth)/sign-in/phone/page.tsx @@ -1,3 +1,122 @@ +"use client"; + +import { useForm } from "react-hook-form"; +import Input from "@/components/commons/Input"; +import { useState } from "react"; + +interface PhoneSignInForm { + phone: string; + password: string; + remember: boolean; +} + export default function PhoneSignInPage() { - return
PhoneSignInPage
; + const { + register, + handleSubmit, + formState: { errors, isSubmitting }, + } = useForm({ + defaultValues: { remember: false }, + mode: "onChange", + }); + const [phone, setPhone] = useState(""); + + const isPhoneError = phone.length > 0 && /\D/.test(phone); + + const onSubmit = (data: PhoneSignInForm) => { + // 로그인 처리 로직 + console.log(data); + }; + + return ( +
+

전화번호로 시작하기

+ + {/* 로그인 부분 */} + { + if (value.length <= 8) setPhone(value); + }} + font='body-5' + /> + {isPhoneError && ( + + 숫자만 입력 가능합니다. + + )} + + {/* 비밀번호 */} +
+ + + {errors.password && ( + + {errors.password.message} + + )} +
+ + {/* ****************************************************** */} + {/* 로그인 유지 */} + {/* ****************************************************** */} +
+ + + 비밀번호 재설정 + +
+ +
+ 계정이 없으신가요?{" "} + + 전화번호로 회원가입 + +
+
+ ); } From 506842d39a67afa44b9b0ae489bca74dee6be7dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=ED=83=80=EB=9E=98?= <85001878+meowTarae@users.noreply.github.com> Date: Mon, 14 Jul 2025 20:36:49 +0900 Subject: [PATCH 10/16] =?UTF-8?q?Feat(#17):=20=EC=9E=85=EB=A0=A5=EB=B0=9B?= =?UTF-8?q?=EC=9D=80=20state=20=EA=B4=80=EB=A6=AC=EB=A5=BC=20useState?= =?UTF-8?q?=EC=97=90=EC=84=9C=20rhf=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/(auth)/sign-in/phone/page.tsx | 35 +++++++++++-------- src/components/commons/Input/index.tsx | 8 ++--- .../commons/Input/inputDeleteIcon.tsx | 4 +-- src/types/components/commons/input/index.ts | 7 ++-- .../commons/input/inputDeleteIcon.ts | 7 ++-- 5 files changed, 37 insertions(+), 24 deletions(-) diff --git a/src/app/(auth)/sign-in/phone/page.tsx b/src/app/(auth)/sign-in/phone/page.tsx index d91e068..b9c6324 100644 --- a/src/app/(auth)/sign-in/phone/page.tsx +++ b/src/app/(auth)/sign-in/phone/page.tsx @@ -2,9 +2,8 @@ import { useForm } from "react-hook-form"; import Input from "@/components/commons/Input"; -import { useState } from "react"; -interface PhoneSignInForm { +export interface PhoneSignInForm { phone: string; password: string; remember: boolean; @@ -15,16 +14,17 @@ export default function PhoneSignInPage() { register, handleSubmit, formState: { errors, isSubmitting }, + watch, + setValue, } = useForm({ - defaultValues: { remember: false }, - mode: "onChange", + defaultValues: { remember: false, phone: "", password: "" }, + mode: "onSubmit", }); - const [phone, setPhone] = useState(""); - const isPhoneError = phone.length > 0 && /\D/.test(phone); + const phoneValue = watch("phone") || ""; + const isPhoneError = phoneValue.length > 0 && /\D/.test(phoneValue); const onSubmit = (data: PhoneSignInForm) => { - // 로그인 처리 로직 console.log(data); }; @@ -35,23 +35,30 @@ export default function PhoneSignInPage() { >

전화번호로 시작하기

- {/* 로그인 부분 */} { - if (value.length <= 8) setPhone(value); - }} font='body-5' + text={phoneValue} + setText={setValue} + register={register("phone", { + required: "전화번호를 입력해주세요.", + pattern: { + value: /^(010|011|016|017|018|019)\d{7,8}$/, + message: "올바른 형식의 전화번호를 입력해 주세요.", + }, + })} /> {isPhoneError && ( - + 숫자만 입력 가능합니다. )} + {errors.phone && !isPhoneError && ( + {errors.phone.message} + )} {/* 비밀번호 */}
diff --git a/src/components/commons/Input/index.tsx b/src/components/commons/Input/index.tsx index f60e2bf..ed8c793 100644 --- a/src/components/commons/Input/index.tsx +++ b/src/components/commons/Input/index.tsx @@ -22,13 +22,14 @@ export default function Input({ id, label, placeholder, - text, - setText, font = "body-5", iconType = "text", iconSize = 18, isRequired = false, className = "", + text, + setText, + register, }: InputProps) { const [isVisible, setIsVisible] = useState(false); @@ -66,12 +67,11 @@ export default function Input({ id={id} className={typeClasses} placeholder={placeholder} - value={text} - onChange={e => setText(e.target.value)} type={ iconType === "password" ? (isVisible ? "text" : "password") : "text" } autoComplete='off' + {...register} /> {iconType === "text" ? ( setText("")} + style={{ display: text?.length === 0 ? "none" : "block" }} + onClick={() => setText && setText("phone", "")} /> ); } diff --git a/src/types/components/commons/input/index.ts b/src/types/components/commons/input/index.ts index 39949c1..ba5397e 100644 --- a/src/types/components/commons/input/index.ts +++ b/src/types/components/commons/input/index.ts @@ -1,15 +1,18 @@ +import { PhoneSignInForm } from "@/app/(auth)/sign-in/phone/page"; import { FontSizeType } from "@/constants/design"; +import { UseFormRegisterReturn, UseFormSetValue } from "react-hook-form"; export interface InputProps { type: "default" | "error"; id: string; label: string; placeholder: string; - text: string; - setText: (text: string) => void; font?: FontSizeType; iconType?: "text" | "password"; iconSize?: number; isRequired?: boolean; className?: string; + text?: string; + setText?: UseFormSetValue; + register?: UseFormRegisterReturn; } diff --git a/src/types/components/commons/input/inputDeleteIcon.ts b/src/types/components/commons/input/inputDeleteIcon.ts index e42f5a4..a1cd030 100644 --- a/src/types/components/commons/input/inputDeleteIcon.ts +++ b/src/types/components/commons/input/inputDeleteIcon.ts @@ -1,5 +1,8 @@ +import { PhoneSignInForm } from "@/app/(auth)/sign-in/phone/page"; +import { UseFormSetValue } from "react-hook-form"; + export interface InputDeleteIconProps { iconSize: number; - text: string; - setText: (text: string) => void; + text: string | undefined; + setText: UseFormSetValue | undefined; } From b7018edba184ea79d6afa3c379903e44bcd7e073 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=ED=83=80=EB=9E=98?= <85001878+meowTarae@users.noreply.github.com> Date: Mon, 14 Jul 2025 20:44:20 +0900 Subject: [PATCH 11/16] =?UTF-8?q?Typo(#17):=20icon=20=EC=98=A4=EA=B8=B0?= =?UTF-8?q?=EC=9E=AC=EB=90=9C=20=EA=B2=BD=EB=A1=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/commons/Input/inputVisibleIcon.tsx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/components/commons/Input/inputVisibleIcon.tsx b/src/components/commons/Input/inputVisibleIcon.tsx index 98b50bb..f66709c 100644 --- a/src/components/commons/Input/inputVisibleIcon.tsx +++ b/src/components/commons/Input/inputVisibleIcon.tsx @@ -6,9 +6,7 @@ export default function InputVisibleIcon({ isVisible, setIsVisible, }: InputVisibleIconProps) { - const iconSrc = isVisible - ? "./icons/eyeCrossLine.svg" - : "./icons/eyeOpen.svg"; + const iconSrc = isVisible ? "/icons/eyeCrossLine.svg" : "/icons/eyeOpen.svg"; return ( Date: Mon, 14 Jul 2025 20:45:14 +0900 Subject: [PATCH 12/16] =?UTF-8?q?Feat(#17):=20rhf=20=EB=A5=BC=20=EC=A0=81?= =?UTF-8?q?=EC=9A=A9=ED=95=9C=20=EB=B9=84=EB=B0=80=EB=B2=88=ED=98=B8=20Inp?= =?UTF-8?q?ut=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/(auth)/sign-in/phone/page.tsx | 51 +++++++++++++-------------- 1 file changed, 24 insertions(+), 27 deletions(-) diff --git a/src/app/(auth)/sign-in/phone/page.tsx b/src/app/(auth)/sign-in/phone/page.tsx index b9c6324..3b6acf3 100644 --- a/src/app/(auth)/sign-in/phone/page.tsx +++ b/src/app/(auth)/sign-in/phone/page.tsx @@ -22,6 +22,7 @@ export default function PhoneSignInPage() { }); const phoneValue = watch("phone") || ""; + const passwordValue = watch("password") || ""; const isPhoneError = phoneValue.length > 0 && /\D/.test(phoneValue); const onSubmit = (data: PhoneSignInForm) => { @@ -35,6 +36,7 @@ export default function PhoneSignInPage() { >

전화번호로 시작하기

+ {/* 전화번호 */} - - - {errors.password && ( - - {errors.password.message} - - )} -
+ + {errors.password && ( + + {errors.password.message} + + )} {/* ****************************************************** */} {/* 로그인 유지 */} From 8d4e9d51eb72d7b5c259819b521838c3b5c42cce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=ED=83=80=EB=9E=98?= <85001878+meowTarae@users.noreply.github.com> Date: Mon, 14 Jul 2025 21:10:58 +0900 Subject: [PATCH 13/16] =?UTF-8?q?Style(#17):=20Card=20=EA=B3=B5=ED=86=B5?= =?UTF-8?q?=20=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=20title=EC=9D=98=20html?= =?UTF-8?q?=20=ED=83=9C=EA=B7=B8=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/commons/Card/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/commons/Card/index.tsx b/src/components/commons/Card/index.tsx index 881f93e..e6affc1 100644 --- a/src/components/commons/Card/index.tsx +++ b/src/components/commons/Card/index.tsx @@ -21,7 +21,7 @@ export default function Card({ onClick={onClick} style={{ width: `${width}px`, height: `${height}px` }} > - {title} +

{title}

{description}

); From c79c9364a04a9fff8e28f22bed005bc6bc299a39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=ED=83=80=EB=9E=98?= <85001878+meowTarae@users.noreply.github.com> Date: Mon, 14 Jul 2025 21:13:13 +0900 Subject: [PATCH 14/16] =?UTF-8?q?Feat(#17):=20=EB=A1=9C=EA=B7=B8=EC=9D=B8?= =?UTF-8?q?=20=EC=9C=A0=EC=A7=80=20&=20=EB=B9=84=EB=B0=80=EB=B2=88?= =?UTF-8?q?=ED=98=B8=20=EC=9E=AC=EC=84=A4=EC=A0=95=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/(auth)/sign-in/phone/page.tsx | 59 ++++++++++++++++++--------- 1 file changed, 39 insertions(+), 20 deletions(-) diff --git a/src/app/(auth)/sign-in/phone/page.tsx b/src/app/(auth)/sign-in/phone/page.tsx index 3b6acf3..85867bc 100644 --- a/src/app/(auth)/sign-in/phone/page.tsx +++ b/src/app/(auth)/sign-in/phone/page.tsx @@ -2,6 +2,11 @@ import { useForm } from "react-hook-form"; import Input from "@/components/commons/Input"; +import Link from "next/link"; +import { useState } from "react"; +import CheckBox from "@/components/commons/CheckBox"; +import UnderlineButton from "@/components/commons/UnderlineButton"; +import Card from "@/components/commons/Card"; export interface PhoneSignInForm { phone: string; @@ -17,22 +22,24 @@ export default function PhoneSignInPage() { watch, setValue, } = useForm({ - defaultValues: { remember: false, phone: "", password: "" }, + defaultValues: { phone: "", password: "" }, mode: "onSubmit", }); + const [isRemember, setIsRemember] = useState(false); const phoneValue = watch("phone") || ""; const passwordValue = watch("password") || ""; const isPhoneError = phoneValue.length > 0 && /\D/.test(phoneValue); const onSubmit = (data: PhoneSignInForm) => { + console.log(isRemember); console.log(data); }; return (

전화번호로 시작하기

@@ -86,25 +93,37 @@ export default function PhoneSignInPage() { )} - {/* ****************************************************** */} - {/* 로그인 유지 */} - {/* ****************************************************** */} -
-