1. 서론
이번 글에서는 React 로그인 기능을 구현하는 방법을 다룹니다. 사용자로부터 이메일과 비밀번호를 입력받아 서버와 통신하여 로그인 요청을 처리하고, 응답을 받아 인증 상태를 관리하는 과정을 단계별로 설명합니다. 이 가이드에서는 비밀번호 유효성 검사, 로딩 상태 관리, 예외 처리 등을 포함하여 완성된 로그인 페이지를 만들어 보겠습니다.
중요한 점은 이 글은 실제 API가 아닌, Dummy API로 Test 용 서버를 가지고 로그인 및 회원가입의 정상적인 흐름을 확인하는 것 뿐이라는 것을 분명히 명시합니다.
2. 주요 기능
• 입력 필드 관리: useState로 입력값 상태를 관리하여 폼 제출 시 데이터를 전송합니다.
• 서버 통신: axios를 사용하여 로그인 요청을 처리합니다.
• 에러 메시지 출력: 잘못된 로그인 시 에러 메시지를 표시합니다.
• 로딩 상태: 요청 중 로딩 상태를 시각적으로 표시합니다.
• 토큰 저장 및 인증: 로그인 성공 시 토큰을 저장하여 사용자 인증 상태를 관리합니다.
3. 로그인 페이지 컴포넌트 단계별 구현
Step 1. 상태 선언 및 입력값 관리
로그인 페이지에서 useState를 사용하여 이메일과 비밀번호를 관리합니다.
코드 예제:
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [error, setError] = useState('');
const [loading, setLoading] = useState(false); // 로딩 상태
• email: 이메일 입력 상태
• password: 비밀번호 입력 상태
• error: 로그인 실패 시 에러 메시지
• loading: 로딩 상태 관리
Step 2. 입력 이벤트 핸들러 작성
입력값이 변경될 때 onChange 이벤트 핸들러로 상태를 업데이트합니다.
코드 예제:
const handleEmailChange = (e) => setEmail(e.target.value);
const handlePasswordChange = (e) => setPassword(e.target.value);
Step 3. 로그인 요청 처리
**axios.post()**를 사용하여 서버에 로그인 요청을 보냅니다.
코드 예제:
const handleLoginSubmit = async (e) => {
e.preventDefault(); // 기본 동작 방지
setLoading(true); // 로딩 상태 활성화
try {
const response = await axios.post('http://localhost:3001/login', {
email,
password,
});
const token = response.data.token; // 서버에서 받은 JWT 토큰
localStorage.setItem('authToken', token); // 토큰 저장
alert('로그인 성공! 환영합니다!');
setError('');
} catch (e) {
setError('아이디 또는 비밀번호가 잘못되었습니다.');
} finally {
setLoading(false); // 로딩 상태 해제
}
};
• axios.post(): 서버에 로그인 정보를 전송합니다.
• localStorage.setItem(): 받은 토큰을 localStorage에 저장하여 인증 상태를 유지합니다.
Step 4. 로그인 페이지 UI 작성
입력 필드를 사용하여 이메일과 비밀번호를 입력받고, 버튼 클릭 시 handleLoginSubmit 함수를 호출합니다.
코드 예제:
<form onSubmit={handleLoginSubmit}>
<input
type="email"
placeholder="이메일"
value={email}
onChange={handleEmailChange}
required
/>
<input
type="password"
placeholder="비밀번호"
value={password}
onChange={handlePasswordChange}
required
/>
{error && <p style={{ color: 'red' }}>{error}</p>}
<button type="submit" disabled={loading}>
{loading ? '로그인 중...' : '로그인'}
</button>
</form>
• value={state}: 입력 필드에 상태를 바인딩합니다.
• onChange 이벤트 핸들러: 입력값이 변경될 때 상태를 업데이트합니다.
• disabled={loading}: 로딩 중에는 버튼을 비활성화하여 중복 요청을 방지합니다.
4. 로그인 후 페이지 이동 (useNavigate)
로그인 성공 시 메인 페이지로 이동하기 위해 **useNavigate**를 사용합니다.
라우터를 활용하는 방식을 선호하기에 만일 Next.js 환경에서 작업하신다면 굳이 필요는 없을수도 있습니다.
import { useNavigate } from 'react-router-dom';
const navigate = useNavigate(); // 페이지 이동 훅
const handleLoginSubmit = async (e) => {
e.preventDefault();
setLoading(true);
try {
const response = await axios.post('http://localhost:3001/login', { email, password });
const token = response.data.token;
localStorage.setItem('authToken', token);
navigate('/home'); // 홈 페이지로 이동
} catch (e) {
setError('로그인 실패! 다시 시도해주세요.');
} finally {
setLoading(false);
}
};
• useNavigate: React Router v6의 페이지 이동 훅입니다.
• 로그인 성공 시 /home 페이지로 이동합니다.
5. 인증 요청 및 보호된 페이지 접근 ( Dummy Server에서는 활용 안할 것임)
서버로 인증이 필요한 요청을 보낼 때, Authorization 헤더에 토큰을 포함합니다.
이 방법은 JWT를 활용한 실제 서버에서 활용하는 방법입니다.
간략한 예시 코드만 작성하겠습니다.
코드 예제:
const handleProtectedRequest = async () => {
const token = localStorage.getItem('authToken');
try {
const response = await axios.get('http://localhost:3001/protected', {
headers: { Authorization: `Bearer ${token}` },
});
console.log('인증 성공:', response.data);
} catch (error) {
console.error('인증 실패:', error);
}
};
6. 로그인 기능 전체 코드
LoginPage.js
import React, { useState } from 'react';
import axios from 'axios';
import { useNavigate } from 'react-router-dom';
const LoginPage = () => {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [error, setError] = useState('');
const [loading, setLoading] = useState(false);
const navigate = useNavigate();
const handleLoginSubmit = async (e) => {
e.preventDefault();
setLoading(true);
try {
const response = await axios.post('http://localhost:3001/login', { email, password });
const token = response.data.token;
localStorage.setItem('authToken', token);
alert('로그인 성공!');
navigate('/home');
} catch (error) {
setError('아이디 또는 비밀번호가 잘못되었습니다.');
} finally {
setLoading(false);
}
};
return (
<form onSubmit={handleLoginSubmit}>
<input
type="email"
placeholder="이메일"
value={email}
onChange={(e) => setEmail(e.target.value)}
required
/>
<input
type="password"
placeholder="비밀번호"
value={password}
onChange={(e) => setPassword(e.target.value)}
required
/>
{error && <p style={{ color: 'red' }}>{error}</p>}
<button type="submit" disabled={loading}>
{loading ? '로그인 중...' : '로그인'}
</button>
</form>
);
};
export default LoginPage;
결론
이제 React 로그인 페이지를 완성했습니다!
로그인 기능 구현 시에는 반드시 서버와의 통신 및 에러 처리를 신경 써야 합니다. 또한, JWT 토큰을 활용한 인증 시스템으로 보안 강화를 할 수 있습니다.
이것은 기본 프로토타입에 불과합니다. 더더욱 발전시켜서 완전한 프로젝트를 만들어보겠습니다.
'FrontEnd Develop' 카테고리의 다른 글
⏿실제 백엔드와 프론트엔드 통신 #1. 인증과 권한부여 <토큰> (0) | 2025.01.24 |
---|---|
Data Fetching : User의 능동성 여부와 useEffect의 올바른 공존 (0) | 2025.01.22 |
🌐 Context로 상태와 함수를 글로벌하게 관리하며 성능 개선하기 (0) | 2025.01.21 |
🚀 프론트엔드 성능 개선 가이드 #1. React DevTools 컴포넌트 & 프로파일러 기능 활용 (1) | 2025.01.15 |
프론트엔드 개발을 위한 더미 서버 구축 <JSON Server Usage> (0) | 2025.01.11 |