FrontEnd Develop

<React + Vue.js> 프로젝트 내 로그인 기능 구현 가이드 With Dummy Server

Frisbeen 2025. 1. 12. 02:43

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 토큰을 활용한 인증 시스템으로 보안 강화를 할 수 있습니다.

 

이것은 기본 프로토타입에 불과합니다. 더더욱 발전시켜서 완전한 프로젝트를 만들어보겠습니다.