@@ -1,7 +1,128 @@
+import { useNavigate } from 'react-router-dom';
+import { useState } from 'react';
 import './Login.scss';
 
 function Login() {
-  return <></>;
+  // const [idState, setIdState] = useState('');
+  // const [passwordValue, setPasswordValue] = useState('');
+  // const [disabled, setDisabled] = useState(true);
+  // const [style, setStyle] = useState({ opacity: 0.5, cursor: 'default' });
+
+  const navigate = useNavigate();
+  const [loginValues, setLoginValues] = useState({
+    id: '',
+    password: '',
+  });
+
+  const handleInputValue = e => {
+    const { name, value } = e.target;
+    setLoginValues({ ...loginValues, [name]: value });
+  };
+
+  // const { type, value } = event.target;
+
+  // function handleLogin(event) {
+  //   if (type === 'text') {
+  //     setIdState(value);
+  //   } else if (type === 'password') {
+  //     setPasswordValue(value);
+  //   }
+  //   handleButton();
+  // }
+
+  // const checkId = idValue => {
+  //   return idValue.includes('@') ? true : false;
+  // };
+
+  // const checkPw = pwValue => {
+  //   return pwValue.length >= 5 ? true : false;
+  // };
+
+  // const handleButton = () => {
+  //   const isValidId = checkId(state);
+  //   const isValidPw = checkPw(passwordValue);
+
+  //   if (isValidId && isValidPw) {
+  //     buttonColor(true);
+  //   } else {
+  //     buttonColor(false);
+  //   }
+  // };
+
+  // const buttonColor = btnValid => {
+  //   setDisabled(!btnValid);
+  //   setStyle({
+  //     opacity: btnValid ? 1 : 0.5,
+  //     cursor: btnValid ? 'pointer' : 'default',
+  //   });
+  // };
+
+  const goToMain = () => {
+    fetch('http://10.58.4.238:8000/users/login', {
+      method: 'POST',
+      body: JSON.stringify({
+        email: loginValues.id,
+        password: loginValues.password,
+        // name: '래영',
+        // phone_number: '010-1111-111',
+      }),
+    })
+      .then(response => response.json())
+      .then(result => {
+        // console.log(result);
+        if (result.token) {
+          //localStorage.setItem('token', result.token);
+          alert('환영합니다!');
+          navigate('/main-han');
+        } else if (result.message === 'INVALID_USER') {
+          alert('ID와 PW를 확인해주세요.');
+        }
+      });
+  };
+
+  const isInputValid =
+    loginValues.id.includes('@') &&
+    loginValues.id.length >= 6 &&
+    loginValues.password.length >= 6;
+  // console.log(loginValues.id.includes('@') && loginValues.id.length >= 6);
+  // console.log(loginValues.password.length >= 6);
+  // console.log(isInputValid);
+
+  return (
+    <div className="login">
+      <form className="loginBox">
+        <h1>Westagram</h1>
+        <input
+          id="id"
+          name="id"
+          className="userId"
+          type="text"
+          placeholder="전화번호, 사용자 이름 또는 이메일"
+          onChange={handleInputValue}
+        />
+        <input
+          id="password"
+          name="password"
+          className="userPassword"
+          type="password"
+          placeholder="비밀번호"
+          onChange={handleInputValue}
+        />
+        <button
+          type="button"
+          className={`loginButton ${isInputValid ? 'loginBtnLive' : ''}`}
+          onClick={goToMain}
+          disabled={!isInputValid}
+          //style={style}
+        >
+          로그인
+        </button>
+        <div className="findPassword">
+          <a href="#">비밀번호를 잊으셨나요?</a>
+        </div>
+      </form>
+    </div>
+  );
 }
 
 export default Login;

리뷰: disabled, style 등은 state로 만들 필요 없음.
[리액트로 사고하기](https://ko.reactjs.org/docs/thinking-in-react.html) 참고
1. 부모로부터 props를 통해 전달됩니까? 그러면 확실히 state가 아닙니다.
2. 시간이 지나도 변하지 않나요? 그러면 확실히 state가 아닙니다.
3. 컴포넌트 안의 다른 state나 props를 가지고 계산 가능한가요? 그렇다면 state가 아닙니다.