
사용자가 입력한 정보가 올바른지 확인하는 과정
아주 간단한 방식으로 구현했고, 시간이 더 있었다면 조금 더 세부적인 유효성 검사를 도전해 봐야겠다.🤓
기본적인 회원가입을 먼저 작성한다.
import { useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { loginApi } from '../axios/api';
import styled from 'styled-components';
const SignUpForm = styled.div`
// 스타일 코드 생략
`;
const Signup = () => {
// 닉네임, 아이디, 비밀번호, 비밀번호 확인의 상태를 관리
const [nickname, setNickname] = useState('');
const [id, setId] = useState('');
const [password, setPassword] = useState('');
const [confirmPassword, setConfirmPassword] = useState('');
const navigate = useNavigate();
const handleSignUp = async (e) => {
e.preventDefault(); // 폼 제출 새로고침 방지
// 비밀번호와 비밀번호 확인 내용이 일치하는지 확인
if (password !== confirmPassword) {
alert('비밀번호가 일치하지 않습니다. 다시 확인해주세요.');
return;
}
try {
// 회원가입 API를 호출하여 서버에 데이터를 전송
const response = await loginApi.post('/register', {
id,
password,
nickname,
});
// 회원가입 성공 시 로그인 페이지로 이동
const data = response.data;
if (data.success) {
navigate('/login');
} else {
// 실패 시 사용자에게 알림을 표시
alert('회원가입 실패하였습니다.');
}
} catch (error) {
// 에러가 발생하면 콘솔에 출력
console.error('Signup error:', error);
// 사용자에게 에러 메시지를 표시
alert('회원가입 실패하였습니다.');
}
};
// 회원가입 폼을 렌더링
return (
<SignUpForm>
<h1>
<img src="/logo.png" alt="로고" />
</h1>
<form onSubmit={handleSignUp}>
<label htmlFor="nickname">닉네임</label>
<input
type="text"
value={nickname}
onChange={(e) => setNickname(e.target.value)}
placeholder="닉네임"
/>
<label htmlFor="id">아이디</label>
<input type="text" value={id} onChange={(e) => setId(e.target.value)} placeholder="ID" />
<label htmlFor="password">비밀번호</label>
<input
type="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
placeholder="비밀번호"
/>
<label htmlFor="confirmPassword">비밀번호 확인</label>
<input
type="password"
value={confirmPassword}
onChange={(e) => setConfirmPassword(e.target.value)}
placeholder="비밀번호 확인"
/>
<button type="submit">회원가입</button>
</form>
</SignUpForm>
);
};
export default Signup;
닉네임, 아이디, 비밀번호에 대한 유효성 검사를 추가한다.
// 입력된 폼 데이터를 유효성 검사하는 함수 생성
const validateForm = () => {
const errors = {}; // 오류 메시지를 저장할 객체
// 닉네임이 입력되지 않았을 경우 오류 메시지를 추가
if (!nickname.trim()) {
errors.nickname = '닉네임을 입력해주세요.';
}
// 아이디가 입력되지 않았을 경우 오류 메시지를 추가
if (!id.trim()) {
errors.id = '아이디를 입력해주세요.';
}
// 비밀번호가 입력되지 않았을 경우 오류 메시지를 추가
if (!password.trim()) {
errors.password = '비밀번호를 입력해주세요.';
} else {
// 비밀번호에 최소 두 개의 영문자가 포함되어 있는지 확인
const hasTwoLetters = /[a-zA-Z].*[a-zA-Z]/.test(password);
if (!hasTwoLetters) {
errors.password = '비밀번호에는 최소 두 개의 영문자가 포함되어야 합니다.';
}
// 비밀번호가 최소 6자리 이상인지 확인
if (password.length < 6) {
errors.password = '비밀번호는 최소 6자리여야 합니다.';
}
}
// 비밀번호와 비밀번호 확인이 일치하는지 확인
if (password !== confirmPassword) {
errors.confirmPassword = '비밀번호가 일치하지 않습니다.';
}
return errors; // 오류 메시지를 반환
};
validateForm함수에서 발생한 오류를 처리하고, 오류가 있을 때는 회원가입 요청을 보내지 않도록 한다.
// 회원가입 버튼이 눌렸을 때 실행되는 함수
const handleSignUp = async (e) => {
e.preventDefault();
const validationErrors = validateForm(); // 폼 데이터를 유효성 검사
// 유효성 검사에서 오류가 발견되면 오류 메시지를 상태로 설정하고 함수를 종료함
if (Object.keys(validationErrors).length > 0) {
setErrors(validationErrors);
return;
}
try {
// 서버에 회원가입 요청을 보냄
const response = await loginApi.post('/register', {
id, // 입력된 아이디
password, // 입력된 비밀번호
nickname, // 입력된 닉네임
});
const data = response.data; // 서버로부터의 응답 데이터를 저장
// 회원가입이 성공하면 로그인 페이지로 이동
if (data.success) {
navigate('/login');
} else {
// 회원가입이 실패시 경고 메시지
alert('회원가입 실패하였습니다.');
}
} catch (error) {
// 회원가입 요청 중 오류가 발생하면 콘솔에 오류를 출력하고 경고 메시지 띄움
console.error('Signup error:', error);
alert('회원가입 실패하였습니다.');
}
};
import { useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { loginApi } from '../axios/api';
import styled from 'styled-components';
const SignUpForm = styled.div`
// 스타일 코드 생략
`;
const Signup = () => {
const [nickname, setNickname] = useState(''); // 닉네임 상태
const [id, setId] = useState(''); // 아이디 상태
const [password, setPassword] = useState(''); // 비밀번호 상태
const [confirmPassword, setConfirmPassword] = useState(''); // 비밀번호 확인 상태
const [errors, setErrors] = useState({}); // 유효성 검사 오류 메시지 상태
const navigate = useNavigate(); // 페이지 이동을 위한 네비게이트 훅
// 폼 유효성 검사 함수
const validateForm = () => {
const errors = {}; // 오류 메시지를 담을 객체
// 닉네임이 비어 있는지 확인
if (!nickname.trim()) {
errors.nickname = '닉네임을 입력해주세요.';
}
// 아이디가 비어 있는지 확인
if (!id.trim()) {
errors.id = '아이디를 입력해주세요.';
}
// 비밀번호가 비어 있는지 확인
if (!password.trim()) {
errors.password = '비밀번호를 입력해주세요.';
} else {
// 비밀번호에 최소 두 개의 영문자가 포함되어 있는지 확인
const hasTwoLetters = /[a-zA-Z].*[a-zA-Z]/.test(password);
if (!hasTwoLetters) {
errors.password = '비밀번호에는 최소 두 개의 영문자가 포함되어야 합니다.';
}
// 비밀번호가 최소 6자리 이상인지 확인
if (password.length < 6) {
errors.password = '비밀번호는 최소 6자리여야 합니다.';
}
}
// 비밀번호와 비밀번호 확인이 일치하는지 확인
if (password !== confirmPassword) {
errors.confirmPassword = '비밀번호가 일치하지 않습니다.';
}
return errors; // 오류 메시지 객체 반환
};
// 회원가입 버튼이 눌렸을 때 실행되는 함수
const handleSignUp = async (e) => {
e.preventDefault(); // 폼의 기본 제출 동작을 막음
const validationErrors = validateForm(); // 폼 데이터를 유효성 검사
// 유효성 검사에서 오류가 발견되면 오류 메시지를 상태로 설정하고 함수를 종료
if (Object.keys(validationErrors).length > 0) {
setErrors(validationErrors);
return;
}
try {
// 서버에 회원가입 요청을 보냄
const response = await loginApi.post(
'/register',
{
id, // 입력된 아이디
password, // 입력된 비밀번호
nickname, // 입력된 닉네임
},
{
headers: {
'Content-Type': 'application/json',
},
}
);
const data = response.data; // 서버로부터의 응답 데이터를 저장
// 회원가입이 성공하면 로그인 페이지로 이동
if (data.success) {
navigate('/login');
} else {
// 회원가입이 실패하면 경고 메시지를 띄움
alert('회원가입 실패하였습니다.');
}
} catch (error) {
// 회원가입 요청 중 오류가 발생하면 콘솔에 오류를 출력하고 경고 메시지를 띄움
console.error('Signup error:', error);
alert('회원가입 실패하였습니다.');
}
};
return (
<SignUpForm>
<h1>
<img src="/logo.png" alt="로고" />
</h1>
<form onSubmit={handleSignUp}>
<label htmlFor="nickname">닉네임</label>
<input
type="text"
value={nickname}
onChange={(e) => setNickname(e.target.value)}
placeholder="닉네임"
/>
{errors.nickname && <p className="notice">{errors.nickname}</p>}
<label htmlFor="id">아이디</label>
<input type="text" value={id} onChange={(e) => setId(e.target.value)} placeholder="ID" />
{errors.id && <p className="notice">{errors.id}</p>}
<label htmlFor="password">비밀번호</label>
<input
type="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
placeholder="비밀번호"
/>
{errors.password && <p className="notice">{errors.password}</p>}
<label htmlFor="confirmPassword">비밀번호 확인</label>
<input
type="password"
value={confirmPassword}
onChange={(e) => setConfirmPassword(e.target.value)}
placeholder="비밀번호 확인"
/>
{errors.confirmPassword && <p className="notice">{errors.confirmPassword}</p>}
<button type="submit">회원가입</button>
</form>
</SignUpForm>
);
};
export default Signup;