React Router를 활용한 사용자 인증 구현
이 글에서는 React Router와 fetch API를 이용해 사용자 인증 로직을 구현하는 방법을 설명한다. 로그인(login)과 회원가입(signup) 모드를 처리하며, 서버와의 통신, 인증 토큰 저장, 그리고 만료 시간 관리 등 전체적인 인증 흐름을 다룬다.
코드 구성
작성한 코드는 다음 두 가지 주요 부분으로 나뉜다.
- AuthenticationPage 컴포넌트
사용자에게 로그인/회원가입 폼을 제공한다. - action 함수
사용자가 입력한 데이터를 처리하고, 서버와 통신하는 역할을 한다.
AuthenticationPage 컴포넌트
import { redirect } from "react-router-dom";
import AuthForm from "../components/AuthForm";
function AuthenticationPage() {
return <AuthForm />;
}
export default AuthenticationPage;
1. 주요 기능
- React 컴포넌트
AuthenticationPage는 AuthForm 컴포넌트를 렌더링한다. AuthForm은 이메일과 비밀번호 입력 필드를 포함한 폼 UI를 제공하며, 제출된 데이터를 action 함수로 넘겨준다. - 구조적 역할
이 컴포넌트는 실제 데이터 처리가 아닌, UI와 로직의 연결점을 제공한다.
action 함수
action 함수는 인증 로직의 핵심이다. 폼 데이터가 제출되면 서버로 요청을 보내고, 응답을 처리하며 인증 상태를 관리한다.
export async function action({ request }) {
- action 함수는 React Router의 폼 데이터 처리 방식 중 하나다.
- request 객체를 통해 요청 URL, 쿼리 파라미터, 폼 데이터에 접근한다.
1. URL 파라미터 확인 및 모드 설정
const searchParams = new URL(request.url).searchParams;
const mode = searchParams.get("mode") || "login";
- URL의 쿼리 파라미터 처리
searchParams.get("mode")를 통해 요청 URL에서 mode 값을 가져온다.- 예: http://localhost:3000/auth?mode=signup → mode는 "signup"으로 설정된다.
- 기본값 설정
사용자가 mode를 명시하지 않으면 기본값 "login"을 사용한다. 이를 통해 인증 요청이 로그인인지, 회원가입인지 구분한다.
2. 모드 검증
if (mode !== "login" && mode !== "signup") {
throw new Response(JSON.stringify({ message: "Invalid request" }), {
status: 422,
});
}
- 유효성 검사
mode 값이 "login" 또는 "signup"이 아닌 경우 잘못된 요청으로 간주하고 에러를 반환한다. - 422 상태 코드
HTTP 상태 코드 422는 요청 데이터가 잘못되었음을 나타낸다.
3. 폼 데이터 처리
const data = await request.formData();
const authData = {
email: data.get("email"),
password: data.get("password"),
};
- 폼 데이터 추출
request.formData()를 호출하여 사용자 입력 데이터를 가져온다.- data.get("email")은 사용자가 입력한 이메일 값을 가져온다.
- data.get("password")는 비밀번호 값을 가져온다.
- 데이터 구조화
추출한 데이터를 authData 객체로 변환하여 서버로 전송할 준비를 한다.
4. 서버 요청
const response = await fetch(`http://localhost:8080/${mode}`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(authData),
});
- fetch API 사용
서버로 POST 요청을 보낸다.
mode 값에 따라 서버 경로가 다르다.- "login": http://localhost:8080/login
- "signup": http://localhost:8080/signup
- 요청 헤더 설정
Content-Type을 application/json으로 지정하여 요청 본문이 JSON 데이터임을 서버에 알린다. - 요청 본문
authData 객체를 JSON 문자열로 변환하여 서버로 전송한다.
5. 응답 처리
if (response.status === 422 || response.status === 401) {
return response;
}
- 422 상태 코드
데이터가 잘못되었거나 서버에서 요청을 처리할 수 없을 때 반환된다.
예: 비밀번호가 짧거나 이메일 형식이 잘못된 경우. - 401 상태 코드
인증이 실패했을 때 반환된다. 예를 들어, 로그인 시 잘못된 이메일/비밀번호를 입력한 경우.
if (!response.ok) {
throw new Response(JSON.stringify({ message: "Something went wrong" }), {
status: 500,
});
}
- 500 상태 코드
예상치 못한 서버 오류가 발생한 경우 클라이언트에 알려준다.
6. 토큰 저장 및 만료 시간 관리
const resData = await response.json();
const token = resData.token;
localStorage.setItem("token", token);
const expiration = new Date();
expiration.setHours(expiration.getHours() + 1);
localStorage.setItem("expiration", expiration.toISOString());
- JWT 토큰 처리
서버로부터 응답을 받아 JSON 데이터를 파싱하고, token 값을 추출한다.
토큰은 사용자의 인증 상태를 나타내며, 이후 요청에서 권한 확인에 사용된다. - Bearer 토큰
토큰을 사용할 때는 보통 Authorization 헤더에 "Bearer <토큰>" 형식으로 추가된다.- "Bearer"는 인증 타입을 나타내며, 서버는 이 토큰을 사용해 사용자를 인증한다.
- 로컬 저장소 사용
localStorage에 토큰을 저장하여 브라우저를 닫아도 인증 상태를 유지할 수 있다. - 만료 시간 설정
현재 시간 기준 1시간 뒤 만료 시간을 설정하여 토큰 유효 기간을 관리한다.
7. 성공 시 리다이렉트
return redirect("/");
- 홈 경로로 리다이렉트
인증 성공 후 사용자를 루트 경로(/)로 이동시킨다.
위 전체 내용에 대한 자세한 코드 참고 링크
'Web & App > Frontend Study' 카테고리의 다른 글
| React _ Tanstack react Query (0) | 2025.01.13 |
|---|---|
| React _ Tanstack은 무엇일까? (0) | 2025.01.13 |
| React _ loader/라우터 로 에러 핸들링 (1) | 2025.01.09 |
| React _ loader 란? (1) | 2025.01.08 |
| React _ 라우팅 및 페이지 #2 (0) | 2025.01.07 |