작업에 들어가며
이전에 회원가입 컴포넌트를 만들어보았다.
그렇기에 로그인 컴포넌트를 만드는 일은 크게 어렵지 않게 진행될 것 같다.
이번에도 차크라UI를 사용하여 로그인 폼을 만들 것이며, 차크라 UI에 관한 사용법은 바로 아래 링크를 참조해놓겠다.
바로 시작해보자!
🙏 프로젝트 작업일지 : 회원가입 (폼 만들기_React Hook Form)
로그인 폼 구현
1. 이메일, 비밀번호 입력 필드 구현
import { Button, Input, Stack } from "@chakra-ui/react"
import { Field } from "../components/ui/field"
import { useForm } from "react-hook-form"
const AuthLogin = () => {
const {
register,
handleSubmit,
formState: { errors },
} = useForm()
const onSubmit = handleSubmit((data) => console.log(data))
return (
<form onSubmit={onSubmit}>
<Stack gap="4" align="flex-start" maxW="sm">
<Field
label="이메일"
invalid={!!errors.email}
errorText={errors.email?.message}
>
<Input
{...register("email", { required: "이메일은 필수 입력입니다.",
pattern: {
value: /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/,
message: "올바른 이메일 형식으로 입력해주세요.",
},
})}
/>
</Field>
<Field
label="비밀번호"
invalid={!!errors.password}
errorText={errors.password?.message}
>
<PasswordInput
{...register("password", { required: "비밀번호는 필수 입력입니다." })}
/>
</Field>
<Button type="submit">로그인</Button>
</Stack>
</form>
)
}
export default AuthLogin;
2. 이메일 기억하기, 아이디 / 비밀번호 찾기 구현
<Box>
<Checkbox>이메일 기억하기</Checkbox>
<Box>
<FindEmail />
<FindPassword />
</Box>
</Box>
이메일 기억하기 체크박스와 아이디 / 비밀번호 찾기를 한 줄로 놓기 위해 <Box> 태그로 감싸주었다.
3. 로그인 핸들러 작성
const handleLogin = async (data) => {
try {
const response = await axios.post("http://localhost:8080/auth/login", data, {
withCredentials: true,
});
if (response.status === 200) {
alert("로그인 성공");
navigate("/"); // 로그인 성공 후 메인 페이지로 이동
}
} catch (error) {
alert("로그인 실패");
if(error.response) {
console.error('Response Error:', error.response.data); // 서버에서 반환한 에러 메시지
} else {
console.error('Axios Error:', error.message); // 네트워크 오류나 Axios 문제
}
}
};
const onSubmit = handleSubmit((data) => {
handleLogin(data);
});
회원가입 폼과 마찬가지로 React Hook Form은 자체적으로 폼 제출 핸들러인 handleSubmit 함수가 있기 때문에 submit시 작동되도록 해당 코드에 handleRegister 함수를 넣어주면 된다.
4. 완성
디테일한 디자인은 GPT의 도움을 받아 구현하였다.
import { Box, Button, Input, Stack, Link, Text, Image } from "@chakra-ui/react";
import { Field } from "../../components/ui/field";
import { PasswordInput } from "../../components/ui/password-input";
import { Checkbox } from "../../components/ui/checkbox";
import { KakaoLoginButton } from "./KakaoLogin";
import { useForm } from "react-hook-form";
import axios from "axios";
import FindPassword from "./FindPassword";
import FindEmail from "./FindEmail";
import { useNavigate } from "react-router-dom";
const AuthLogin = () => {
const navigate = useNavigate();
const {
register,
handleSubmit,
formState: { errors },
} = useForm();
const handleLogin = async (data) => {
try {
const response = await axios.post("http://localhost:8080/auth/login", data, {
withCredentials: true,
});
if (response.status === 200) {
alert("로그인 성공");
setIsLoggedIn(true); // 로그인 상태 업데이트
navigate("/");
}
} catch (error) {
alert("로그인 실패");
if(error.response) {
console.error('Response Error:', error.response.data); // 서버에서 반환한 에러 메시지
} else {
console.error('Axios Error:', error.message); // 네트워크 오류나 Axios 문제
}
}
};
const onSubmit = handleSubmit((data) => {
handleLogin(data);
});
return (
<form onSubmit={onSubmit}>
<Box display="flex" alignItems="center" justifyContent="center" height="100vh">
<Stack gap="4" align="flex-start" maxW="sm" width="full">
<Link href="/">
<Image
src="https://example.com/logo.png"
alt="로고"
boxSize="45px"
objectFit="contain"
mb="4"
/>
</Link>
<Box display="flex" alignItems="center" justifyContent="space-between" width="full">
<Text fontSize="2xl" fontWeight="bold">
로그인
</Text>
<Link href="/register" color="orange.500" fontWeight="bold">
회원가입
</Link>
</Box>
<Field
label="이메일"
invalid={!!errors.email}
errorText={errors.email?.message}
>
<Input
size="lg"
placeholder="이메일을 입력해주세요."
{...register("email", {
required: "이메일은 필수 입력입니다.",
pattern: {
value: /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/,
message: "올바른 이메일 형식으로 입력해주세요.",
},
})}
/>
</Field>
<Field
label="비밀번호"
invalid={!!errors.password}
errorText={errors.password?.message}
>
<PasswordInput
size="lg"
placeholder="비밀번호를 입력해주세요."
{...register("password", {
required: "비밀번호는 필수 입력입니다.",
})}
/>
</Field>
<Box display="flex" alignItems="center" justifyContent="space-between" width="full">
<Checkbox
colorPalette="orange"
>
이메일 기억하기
</Checkbox>
<Box display="flex" alignItems="center" gap="1" mr="2">
<FindEmail height="40px" />
<FindPassword height="40px" />
</Box>
</Box>
<Stack spacing="2" width="full" mt="1">
<Button type="submit" colorPalette="orange" width="full" size="lg">
로그인
</Button>
</Stack>
</Stack>
</Box>
</form>
);
};
export default AuthLogin;
작업을 마치며
✨ 나의 생각
이전에 회원가입 폼에 비해서는 확실히 무난하게 폼 구현이 진행되었다.
그러나 시큐리티와 이메일 / 비밀번호 찾기를 구현해봐야하는데,
구글링을 통해 많은 레퍼런스 자료들을 찾아봐야겠다.
시큐리티는 이전 프로젝트에서 사용한 코드에 학원에서 배운 코드들로 리팩토링하고,
이메일 / 비밀번호 찾기는 모달로 띄워서 사용자 인증 정보를 입력 후 서버에 요청하여
모달창 내부에 아이디와 비밀번호를 띄우는 방법으로 진행해야 할 것 같다.
쉽지는 않겠지만 열심히 프로젝트를 진행해봐야겠다!
Reference
'Project > Team' 카테고리의 다른 글
프로젝트 작업일지 : 로그인 (아이디 기억하기) (2) | 2024.12.28 |
---|---|
프로젝트 작업일지 : 로그인 (Spring Security - JWT - React) (0) | 2024.12.28 |
프로젝트 작업일지 : 회원가입 (이메일 중복 검사) (0) | 2024.12.27 |
프로젝트 작업일지 : 회원가입 (스프링 - 리액트 회원가입) (0) | 2024.12.24 |
프로젝트 작업일지 : 회원가입 (리액트 다음 주소 찾기 API) (1) | 2024.12.23 |