-
이전 페이지의 URLDev 2023. 3. 27. 13:32
1. previous URL 필요 상황
임의의 페이지에 대하여 접근하는 URI에 따라 다른 처리를 해야하는 경우가 존재할 수 있습니다.
이러한 경우, 이전 페이지의 URL을 가져오는 방법과 동작원리에 대해 작성합니다.
2. 방법
2.1. In JavaScipt
document.referrer을 사용합니다.
document.referrer는 현재 페이지로 이동하기 이전 페이지의 URL 주소를 문자열로 반환하는 JavaScript의 속성입니다.
이전 페이지의 URL 주소가 없는 경우, 빈 문자열('')을 반환합니다.
이전 페이지의 URL은 HTTP 리퍼러 헤더(Referer 또는 Referrer)에 담겨서 현재 페이지로 전송되며,
document.referrer 속성은 이 HTTP 리퍼러 헤더에서 이전 페이지의 URL을 추출하여 반환합니다.
document.referrer 속성은 보안상의 이유로 HTTPS에서 HTTP 페이지로 이동하는 경우나,
다른 도메인으로 이동하는 경우에는 이전 페이지의 URL을 가져올 수 없을 수도 있습니다.
또한, 일부 보안 소프트웨어나 브라우저 확장 프로그램 등에서 이전 페이지의 URL을 가려서 반환할 수도 있습니다.
항상 정확한 값을 반환하는 것은 아니므로, 사용에 주의해야 합니다.
const prevUrl = window.history.length > 1 ? document.referrer : null;다만 React를 통해 구동되는 웹의 경우에는 페이지를 새로고침하지 않고,
React에서 URL에 맞는 컴포넌트를 렌더링하여 document.referrer의 값이 원하는대로 동작하지 않을 수 있습니다.따라서 ReactJS환경에서는 다른 방법을 사용해야 합니다.
2.2. In ReactJS
2.2-1. useRef + useEffect
이동하는(출발) 페이지에서 useRef와 useEffect를 사용해 location객체에 previousPageUrl을 삽입합니다.
import React from "react"; import { useEffect, useRef } from "react"; import { Link, useLocation } from "react-router-dom"; const Home = () => { const location = useLocation(); const previousPageUrlRef = useRef(null); useEffect(() => { previousPageUrlRef.current = location.pathname; }, [location.pathname]); const handleGoBack = () => { const previousPageUrl = previousPageUrlRef.current; location.push(previousPageUrl); }; return ( <React.Fragment> <div>home</div> <Link to="/about" onClick={() => { handleGoBack(); }} > page move </Link> </React.Fragment> ); }; export default Home;이동된(도착) 페이지에서 document.referrer를 통해 이전 페이지의 URL을 읽을 수 있습니다.
const About = () => { console.log(document.referrer); // http://localhost:3000/ return ( <> about </> ); }; export default About;2.2-2. cookie 또는 sessionStorage 사용
서버와의 통신에 이전 페이지의 URL이 사용되는 경우라면, cookie에 저장하는 것도 방법이 될 수 있습니다.
하지만 이전 페이지의 URL을 웹 스토리지에 저장하는 것은 보안상의 문제를 유발할 수 있습니다.
이전 페이지 URL에 사용자 자격 증명 또는 개인 데이터와 같은 정보가 포함되어 있으면 중요한 데이터로 간주될 수 있기 때문입니다.
쿠키와 마찬가지로 sessionStorage에 이전 페이지의 URL을 저장할 수도 있습니다.
limited lifetime, not sent to server, no third-party acces등을 이유로 localStorage나 cookie보다는 안전하다고 해도,
이전 페이지의 URL을 웹 스토리지에 저장하는 것은 역시 보안상의 문제를 유발할 수 있습니다.
import Cookies from 'js-cookie'; import crypto from 'crypto'; const COOKIE_NAME = 'previousUrl'; export const savePreviousUrl = (currentUrl) => { const key = crypto.randomBytes(32); const iv = crypto.randomBytes(16); const cipher = crypto.createCipheriv('aes-256-cbc', key, iv); const encryptedUrl = cipher.update(currentUrl, 'utf8', 'hex') + cipher.final('hex'); const encryptedData = { url: encryptedUrl, iv: iv.toString('hex'), }; const encryptedDataJson = JSON.stringify(encryptedData); Cookies.set(COOKIE_NAME, encryptedDataJson, { expires: 1, secure: true }); }; export const getPreviousUrl = () => { const encryptedDataJson = Cookies.get(COOKIE_NAME); if (encryptedDataJson) { try { const encryptedData = JSON.parse(encryptedDataJson); const key = crypto.randomBytes(32); const iv = Buffer.from(encryptedData.iv, 'hex'); const decipher = crypto.createDecipheriv('aes-256-cbc', key, iv); const decryptedUrl = decipher.update(encryptedData.url, 'hex', 'utf8') + decipher.final('utf8'); return decryptedUrl; } catch (error) { console.error('Error decrypting previous URL:', error); Cookies.remove(COOKIE_NAME); } } return null; };crypto 라이브러리를 통한 암호화나 백엔드에서의 자격 검증을 통해 보안성을 향상시킬 수 있습니다.
import { useNavigate } from 'react-router-dom'; import savePreviousUrl from 'util/previousUrl'; const Home = () => { const navigate = useNavigate(); pageRedirect = () => { savePreviousUrl(navigate.pathname); navigate('/about'); } return ( <button onClick={pageRedirect}>Move Page</button> ); }; export default Home;import { React, useState, useEffect } from "react"; import getPreviousUrl from 'util/previousUrl'; const About = () => { [prevUrl, setPrevUrl] = useState(''); useEffect(()=>{ setPrevUrl(getPreviousUrl()) },[]) return ( <React.Fragment> // ~ </React.Fragment> ); }; export default About;2.3. In NextJS
NextJS의 built-in function인 getInitialProps를 사용합니다.
서버 측 요청 개체에서 이전 페이지 URL을 가져올 수 있습니다.
import { useRouter } from 'next/router'; const About = ({ previousPageUrl }) => { const router = useRouter(); const handleGoBack = () => { router.push(previousPageUrl); }; return ( <button onClick={handleGoBack}>Go back to previous page</button> ); }; PageComponent.getInitialProps = ({ req }) => { const previousPageUrl = req.headers.referer; return { previousPageUrl }; }; export default About;getInitialProps 함수는 Next.js 다른 유형의 구성 요소에서는 사용할 수 없고 페이지 구성 요소에서만 사용할 수 있습니다.
또한 headers.referer가 항상 신뢰할 수 있는 것이 아니라 경우에 따라 사용할 수 없는 경우도 있으므로,
에지 케이스를 적절히 처리하는 코드를 작성해야 할 수도 있습니다.
'Dev' 카테고리의 다른 글
프론트엔드 깃허브 액션 CI 시스템을 이용한 버전관리 (3) 2025.07.17 React hook form과 zod로 form validation 처리 (0) 2025.06.16 tabIndex의 진실 (0) 2024.07.25 json-server 라이브러리 (0) 2022.12.30 SEO와 Next.js (0) 2022.11.15