diff --git a/client/package-lock.json b/client/package-lock.json
index 2b0b49b..8f84442 100644
--- a/client/package-lock.json
+++ b/client/package-lock.json
@@ -10,6 +10,7 @@
"dependencies": {
"@emotion/react": "^11.11.1",
"@emotion/styled": "^11.11.0",
+ "@mui/icons-material": "^5.14.15",
"@mui/material": "^5.14.15",
"framer-motion": "^10.16.4",
"next": "14.0.0",
@@ -3646,6 +3647,31 @@
"url": "https://opencollective.com/mui"
}
},
+ "node_modules/@mui/icons-material": {
+ "version": "5.14.16",
+ "resolved": "https://registry.npmjs.org/@mui/icons-material/-/icons-material-5.14.16.tgz",
+ "integrity": "sha512-wmOgslMEGvbHZjFLru8uH5E+pif/ciXAvKNw16q6joK6EWVWU5rDYWFknDaZhCvz8ZE/K8ZnJQ+lMG6GgHzXbg==",
+ "dependencies": {
+ "@babel/runtime": "^7.23.2"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/mui"
+ },
+ "peerDependencies": {
+ "@mui/material": "^5.0.0",
+ "@types/react": "^17.0.0 || ^18.0.0",
+ "react": "^17.0.0 || ^18.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
"node_modules/@mui/material": {
"version": "5.14.16",
"resolved": "https://registry.npmjs.org/@mui/material/-/material-5.14.16.tgz",
diff --git a/client/package.json b/client/package.json
index 982f308..5d7a2da 100644
--- a/client/package.json
+++ b/client/package.json
@@ -16,6 +16,7 @@
"@emotion/react": "^11.11.1",
"@emotion/styled": "^11.11.0",
"@mui/material": "^5.14.15",
+ "@mui/icons-material": "^5.14.15",
"framer-motion": "^10.16.4",
"next": "14.0.0",
"react": "^18",
diff --git a/client/src/app/auth/login/page.tsx b/client/src/app/auth/login/page.tsx
new file mode 100644
index 0000000..0cd2b73
--- /dev/null
+++ b/client/src/app/auth/login/page.tsx
@@ -0,0 +1,65 @@
+import { Avatar, Box, Grid, Paper, Typography } from "@mui/material";
+import SigninForm from "@/components/user/signin/SigninForm";
+import Link from "next/link";
+import { SIGNUP, FORGOTPASSWORD } from "@/const/clientPath";
+import { Metadata } from "next";
+import { nameOfApp } from "@/const/brand";
+import { LockOutlined as LockOutlinedIcon } from "@mui/icons-material";
+
+export const metadata: Metadata = {
+ title: `${nameOfApp} | 로그인`,
+};
+
+const LoginPage = () => {
+ return (
+
+
+
+
+ {/* heading */}
+
+
+
+
+ Sign in
+
+ {/* form */}
+
+
+
+
+ Forgot password?
+
+
+
+
+ 계정이 없으신가요? 회원가입
+
+
+
+
+
+
+ );
+};
+
+export default LoginPage;
diff --git a/client/src/app/hi/page.tsx b/client/src/app/hi/page.tsx
deleted file mode 100644
index eb5dd3d..0000000
--- a/client/src/app/hi/page.tsx
+++ /dev/null
@@ -1,12 +0,0 @@
-import { Button } from "@mui/material";
-import React from "react";
-
-type Props = {};
-
-const HiPage = (props: Props) => {
- return (
-
- );
-};
-
-export default HiPage;
diff --git a/client/src/components/user/signin/SigninForm.tsx b/client/src/components/user/signin/SigninForm.tsx
new file mode 100644
index 0000000..9a0c2d7
--- /dev/null
+++ b/client/src/components/user/signin/SigninForm.tsx
@@ -0,0 +1,62 @@
+"use client";
+import useLogin from "@/hooks/useLogin";
+import {
+ Box,
+ Button,
+ Checkbox,
+ FormControlLabel,
+ TextField,
+} from "@mui/material";
+
+import { useState } from "react";
+
+const SigninForm = () => {
+ const [email, setEmail] = useState("");
+ const [password, setPassword] = useState("");
+ const handleSubmit = useLogin();
+
+ return (
+ {
+ event.preventDefault();
+ handleSubmit({ email, password });
+ }}
+ sx={{ mt: 1 }}
+ >
+ setEmail(target.value)}
+ margin="normal"
+ required
+ fullWidth
+ id="email"
+ label="Email Address"
+ name="email"
+ autoComplete="email"
+ autoFocus
+ />
+ setPassword(target.value)}
+ margin="normal"
+ required
+ fullWidth
+ name="password"
+ label="Password"
+ type="password"
+ id="password"
+ autoComplete="current-password"
+ />
+ }
+ label="Remember me"
+ />
+
+
+ );
+};
+
+export default SigninForm;
diff --git a/client/src/hooks/useLogin.ts b/client/src/hooks/useLogin.ts
new file mode 100644
index 0000000..f4873e9
--- /dev/null
+++ b/client/src/hooks/useLogin.ts
@@ -0,0 +1,13 @@
+import { SigninRequirement } from "@/types/auth/signin"
+
+/**
+ * 로그인 관련 로직들이 모여있는 Hook
+ * @returns login Handler
+ */
+export default function useLogin () {
+ const loginHandler = (props:SigninRequirement)=>{
+ const {email,password} = props
+ console.log(`email : ${email}, password : ${password}`)
+ }
+ return loginHandler
+}
diff --git a/client/src/stories/Components/Auth/LoginForm.stories.tsx b/client/src/stories/Components/Auth/LoginForm.stories.tsx
new file mode 100644
index 0000000..abb5f4d
--- /dev/null
+++ b/client/src/stories/Components/Auth/LoginForm.stories.tsx
@@ -0,0 +1,35 @@
+import SigninForm from "@/components/user/signin/SigninForm";
+import { Box, Paper } from "@mui/material";
+import { Meta, StoryObj } from "@storybook/react";
+
+const meta = {
+ title: "Components/Auth/LoginForm",
+ component: SigninForm,
+ tags: ["autodocs"],
+ decorators: [
+ (Story) => {
+ return (
+
+
+
+
+
+ );
+ },
+ ],
+} satisfies Meta;
+
+export default meta;
+type Story = StoryObj;
+
+export const LoginForm: Story = {
+ args: {},
+};
diff --git a/client/src/types/auth/signin.ts b/client/src/types/auth/signin.ts
new file mode 100644
index 0000000..0a8dcd0
--- /dev/null
+++ b/client/src/types/auth/signin.ts
@@ -0,0 +1,4 @@
+export interface SigninRequirement {
+ email: string;
+ password: string;
+}