# TIL - 2026.08.05

ssls·2026년 8월 5일

📌 오늘 학습한 주제

  • React Router Dom을 활용한 페이지 라우팅 및 상태 전달 (useNavigate, useLocation)
  • URL 매개변수 파싱 기법 (useSearchParams, useParams)
  • React useState 기반 입력 폼 동기화 및 Axios 비동기 인증 통신 (EventPage.jsx)
  • 웹 브라우저 저장소 (localStorage)를 활용한 사용자 세션 관리

💡 오늘 배운 것 — 나만의 언어로

① 오늘의 목표

  • React Router Dom의 주요 Hook들을 활용하여 로그인 인증 처리 및 상태/쿼리스트링/경로 파라미터를 동반한 페이지 전환(Transition) 흐름 구현하기

② 학습할 내용

  • 상태 관리 및 비동기 로그인 인증 (EventPage.jsx): useState로 이메일과 비밀번호 입력값을 관리하고, 로그인 버튼 클릭 시 Axios로 백엔드 API (/users?email=...&pswd=...) 조회를 수행했다. 인증 성공 시 localStorage에 사용자 정보를 저장하고 useNavigatestate 옵션을 사용하여 성공 페이지로 이동시켰다.
  • 성공 페이지 및 State 수신 (SuccessPage.jsx): 라우터의 useLocation() Hook을 통해 전달받은 state 객체(user, from)와 localStorage에 저장된 사용자명을 조합하여 동적 안내 문구를 출력했다.
  • 실패 페이지 및 QueryString 수신 (ErrorPage.jsx): 로그인 실패 시 useSearchParams() Hook을 사용해 URL 쿼리스트링(?category=react&sort=latest) 파라미터 값을 파싱하고 안내 화면을 구성했다.
  • 경로 파라미터 파싱 (ViewPage.jsx): useParams() Hook을 활용해 URL Path Variable(/read/:id) 형태의 동적 id 값을 추출하는 방법을 학습했다.

💻 오늘 핵심 코드

1. 로그인 인증 및 페이지 전환 처리 (EventPage.jsx)

import Button from 'react-bootstrap/Button';
import 'bootstrap/dist/css/bootstrap.min.css';
import { useEffect, useState } from 'react';
import api from '../../api/axios';
import { useNavigate } from 'react-router-dom';

const EventPage = () => {
    const [email, setEmail] = useState('');
    const [pswd, setPswd] = useState('');
    const moveUrl = useNavigate();

    const signInHandler = async (e, email, pswd) => {
        e.preventDefault();

        await api.get(`/users?email=${email}&pswd=${pswd}`)
            .then(response => {
                const ary = response.data;
                if (ary.length > 0) {
                    const user = ary[0];
                    // 사용자 세션 정보 저장
                    localStorage.setItem('userName', user.name);
                    // State 객체와 함께 성공 페이지로 이동
                    moveUrl('/success', {
                        state: { user, from: '/signIn' }
                    });
                } else {
                    // QueryString을 포함하여 에러 페이지로 이동
                    moveUrl('/error?category=react&sort=latest');
                }
            })
            .catch(err => {
                console.log(`debug >>>> error : `, err);
            });
    }

    return (
        <div className='container'>
            <div className="mb-3 mt-3">
                <label htmlFor="email" className="form-label">Email:</label>
                <input 
                    type="email" 
                    className="form-control" 
                    id="email" 
                    value={email}
                    onChange={(e) => setEmail(e.target.value)} 
                />
            </div>
            <div className="mb-3">
                <label htmlFor="pwd" className="form-label">Password:</label>
                <input 
                    type="password" 
                    className="form-control" 
                    id="pwd" 
                    value={pswd}
                    onChange={(e) => setPswd(e.target.value)} 
                />
            </div>
            <Button variant='primary' onClick={(e) => signInHandler(e, email, pswd)}>SignIn</Button>
        </div>
    );
}

export default EventPage;

2. State 수신 및 성공 화면 출력 (SuccessPage.jsx)

import { Link, useLocation } from "react-router-dom";

const SuccessPage = () => {
    // 1. location.state를 통한 라우터 전달 데이터 수신
    const location = useLocation();
    const { user, from } = location.state || {};

    // 2. localStorage 세션 데이터 수신
    const name = localStorage.getItem('userName');

    return (
        <div>
            <center>{name}-{user?.name}님 로그인 성공</center>
            <Link to="/read/10">상세페이지로...</Link>
            <Link to="/">랜딩페이지로...</Link>
        </div>
    );
}

export default SuccessPage;

3. QueryString 파싱 및 실패 화면 처리 (ErrorPage.jsx)

import { Link, useSearchParams } from "react-router-dom";

const ErrorPage = () => {
    // 쿼리스트링 (?category=react&sort=latest) 파싱
    const [searchParams] = useSearchParams();
    const category = searchParams.get('category');
    const sort = searchParams.get('sort');

    return (
        <div>
            <center>로그인 실패({category} , {sort})</center>
            <Link to="/">랜딩페이지로...</Link>
        </div>
    );
}

export default ErrorPage;

4. Path Variable 파싱 (ViewPage.jsx)

import { useParams } from "react-router-dom";

const ViewPage = () => {
    // URL 경로 파라미터 (/read/:id) 파싱
    const { id } = useParams();
    console.log(`debug >>>> ViewPage useParams : id , ${id}`);

    return (
        <div>
            <h2>상세 보기 페이지 (ID: {id})</h2>
        </div>
    );
}

export default ViewPage;

🛠️ 실습 / 결과물 & 참고 자료

③ 실습 / 결과물

  • 강의 실습코드: EventPage.jsx, SuccessPage.jsx, ErrorPage.jsx, ViewPage.jsx 코드를 연동하여, 로그인 성공/실패 여부에 따라 state, useSearchParams, useParams 방식으로 데이터를 다르게 전달하고 화면에 동적으로 출력하는 라우팅 시스템 구현.

④ 참고 자료


🔍 문제와 해결

  • 막힌 부분: SuccessPage로 이동 시 직접 URL을 입력해 접근하는 경우 location.state 값이 undefined가 되어 렌더링 에러가 발생하는 문제 점검.
  • 해결 방법: const { user, from } = location.state || {}; 및 옵셔널 체이닝(user?.name) 문법을 활용하여 예외 안전성을 확보하고, localStorage에 저장된 데이터를 백업 수단으로 활용함.

🎯 다음에 할 일

  • JSON Web Token(JWT) 기반 인증 방식 및 Axios Interceptor를 활용한 헤더 토큰 자동 주입 구현해보기
  • 로그인 여부에 따른 보호된 라우트(Protected Route) 컴포넌트 설계해보기
profile
성장중

0개의 댓글