하루 하나씩 작성하는 TIL #35
이번 til에선 로그인 기능 코드를 뜯어서 설명하겠다.
import { useState } from 'react';
import { Link, useNavigate } from 'react-router-dom';
import SignInBtn from '../components/SignInBtn';
import { supabase } from '../supabaseClient';
function LogIn() {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [error, setError] = useState('');
const navigate = useNavigate();
const handleSignIn = async (e) => {
e.preventDefault();
const { error } = await supabase.auth.signInWithPassword({
email,
password,
});
if (error) {
setError('이메일 또는 비밀번호가 올바르지 않습니다.');
} else {
setError('');
alert('로그인되었습니다.');
setEmail('');
setPassword('');
navigate('/'); // 로그인 성공 시 홈페이지로 이동
}
};
return (
<div className="relative min-h-screen bg-gray-100">
<main className="flex flex-col items-center justify-center min-h-screen pt-20">
<div className="bg-white p-10 rounded shadow-md w-full max-w-md mt-8">
<h1 className="text-5xl font-bold mb-6 text-center">L O G I N</h1>
<form onSubmit={handleSignIn} className="space-y-6">
<div>
<label className="block text-lg text-gray-700">이메일 :</label>
<input
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
placeholder="이메일을 입력하세요"
required
className="w-full px-4 py-3 border rounded text-lg"
/>
</div>
<div>
<label className="block text-lg text-gray-700">비밀번호 :</label>
<input
type="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
placeholder="비밀번호를 입력하세요"
required
className="w-full px-4 py-3 border rounded text-lg"
/>
</div>
<button type="submit" className="w-full bg-blue-500 text-white py-3 rounded text-lg hover:bg-blue-600">
로그인
</button>
</form>
<p className="mt-6 text-center text-lg">
아직 회원이 아니라면?{' '}
<Link to="/sign_up" className="text-blue-500 hover:underline">
가입하러 가기
</Link>
</p>
<div className="mt-6 flex justify-center w-full">
<SignInBtn />
</div>
{error && <p className="mt-6 text-red-500 text-center text-lg">{error}</p>}
</div>
</main>
</div>
);
}
export default LogIn;
이 코드를 하나하나 뜯어서 설명해보고자한다. 일단 출력 결과는
위와 같다.
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [error, setError] = useState('');
const navigate = useNavigate();
useState훅을 사용하여 이메일과 패스워드를 받아 로그인+ 오류 저장을 하고 초기 값은 빈 문자열로 설정해준다.
useNavigate 훅을 사용하여 네비게이션을 관리한다. 이 훅은 사용자를 다른 경로로 리디렉션하거나 이동시킬 때 사용되는데, 본 프로젝트에서는 로그인 후 홈페이지로 이동하기 위해 사용됐다.
const handleSignIn = async (e) => {
e.preventDefault();
const { error } = await supabase.auth.signInWithPassword({
email,
password,
});
로그인 폼이 제출될 때 새로고침되는 기본 동작을 막아준다.
async키워드는 함수가 비동기적으로 동작함을 나타낸다. 이 키워드가 함수 앞에 붙으면, 그 함수는 Promise를 반환하게 된다.
ex) 네트워크 요청을 보내거나 파일을 읽어올 때는 결과가 즉시 사용 가능하지 않은데, 이때 에이싱크 키워드를 사용하여 비동기 작업을 실행할 수 있다.
handleSignIn 함수에서 async 키워드를 사용하는 이유는 supabase.auth.signInWithPassword() 메서드가 비동기 함수이기 때문이다. 이 메서드는 Supabase 서버에 로그인 요청을 보내고, 그 결과를 반환하기 위해 시간이 필요하기 때문에 async 키워드를 사용하여 이 함수를 비동기적으로 호출하고, 그 결과를 기다리는 것.
위 코드는 수퍼베이스 Docs에서 찾아볼 수있다.
if (error) {
setError('이메일 또는 비밀번호가 올바르지 않습니다.');
} else {
setError('');
alert('로그인되었습니다.');
setEmail('');
setPassword('');
navigate('/'); // 로그인 성공 시 홈페이지로 이동
}
};
navigate 함수를 사용하여 사용자를 홈페이지로 리디렉션한다. 이는 로그인 성공 후 사용자를 메인 페이지로 이동시키는 역할을 한다.
<input
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
placeholder="이메일을 입력하세요"
required
className="w-full px-4 py-3 border rounded text-lg"
/>
기타 버튼 및 회원가입 페이지는 다음 til에서 작성하겠다.