GiantStepDEV
article thumbnail

๋ผ์šฐํŒ…์ด๋ž€?

  • ์‚ฌ์šฉ์ž๊ฐ€ ์š”์ฒญํ•œ URL์— ๋”ฐ๋ผ ์•Œ๋งž์€ ํŽ˜์ด์ง€๋ฅผ ๋ณด์—ฌ์ฃผ๋Š” ๊ฒƒ
  • ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋งŒ๋“ค ๋•Œ ํ”„๋กœ์ ํŠธ๋ฅผ ํ•˜๋‚˜์˜ ํŽ˜์ด์ง€๋กœ ๊ตฌ์„ฑํ•  ์ˆ˜๋„ ์žˆ๊ณ , ์—ฌ๋Ÿฌ ํŽ˜์ด์ง€๋กœ ๊ตฌ์„ฑํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์—ฌ๋Ÿฌ ํŽ˜์ด์ง€๋กœ ๊ตฌ์„ฑ๋œ ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋งŒ๋“ค ๋•Œ ํŽ˜์ด์ง€ ๋ณ„๋กœ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ถ„๋ฆฌํ•ด๊ฐ€๋ฉด์„œ ํ”„๋กœ์ ํŠธ๋ฅผ ๊ด€๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด ํ•„์š”ํ•œ ๊ฒƒ์ด ๋ฐ”๋กœ ๋ผ์šฐํŒ… ์‹œ์Šคํ…œ ์ž…๋‹ˆ๋‹ค.

๐Ÿ‘‰ ๋ฆฌ์•กํŠธ ๋ผ์šฐํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์†์‰ฝ๊ฒŒ ๋ฆฌ์•กํŠธ ๋ผ์šฐํ„ฐ๋กœ ์‹ฑ๊ธ€ํŽ˜์ด์ง€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜(SPA)๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.


SPA๋Š” ์ด๋ฆ„ ๊ทธ๋Œ€๋กœ ํŽ˜์ด์ง€ ํ•˜๋‚˜๋กœ ๋Œ์•„๊ฐ€๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด๊ธฐ ๋•Œ๋ฌธ์— ํŽ˜์ด์ง€ ์ด๋™์‹œ ๋ฒ„๋ฒ…์ž„ ์—†์ด ๋ถ€๋“œ๋Ÿฝ๊ฒŒ ์ „ํ™˜๋˜์ง€๋งŒ,

์›น ํŽ˜์ด์ง€ ์ •๋ณด๊ฐ€ ์—†๊ธฐ ๋•Œ๋ฌธ์— SEO์—๋Š” ๋งค์šฐ ์ทจ์•ฝํ•ฉ๋‹ˆ๋‹ค. ํ—ˆ๋‚˜ ์ด๋Š” HTML metaํƒœ๊ทธ์— ์ •๋ณด๋ฅผ ์˜ฌ๋ฆฌ๋ฉด ๋˜์–ด์„œ ํฌ๊ฒŒ ๊ฑฑ์ •ํ•  ์ •๋„๋Š” ์•„๋‹™๋‹ˆ๋‹ค.

์ตœ๊ทผ์—๋Š” ์ด๋Ÿฐ SEO์— ์•ฝํ•˜๋‹ค๋Š” ๋‹จ์ ์„ ๋ณด์™„ํ•˜๊ธฐ ์œ„ํ•ด ์„œ๋ฒ„ ์‚ฌ์ด๋“œ ๋ Œ๋”๋ง์„ ์ด์šฉํ•œ Next.js๊ฐ€ ๋งŽ์ด ์“ฐ์ด๊ณค ํ•ฉ๋‹ˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ , ์ •๋ณด๋ฅผ ํ•œ๋ฒˆ์— ๋‹ค ๋ถˆ๋Ÿฌ์™€์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ฒซ ํŽ˜์ด์ง€ ๋กœ๋”ฉ ์‹œ๊ฐ„์ด ๊ธธ์–ด์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.


ํ”„๋กœ์ ํŠธ ์ƒ์„ฑ ๋ฐ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์„ค์น˜

$ yarn create react-app [ํด๋”๋ช…]

$ cd [ํด๋”๋ช…]

$ yarn add react-router-dom

ํ”„๋กœ์ ํŠธ์— ๋ผ์šฐํ„ฐ ์ ์šฉ

src/index.js

import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
    <App />
);

src/pages/Home.js

๐Ÿ‘‰ src ๋””๋ ‰ํ† ๋ฆฌ์— Pages ํด๋” ๋งŒ๋“ค๊ณ , ํ•˜์œ„ ํŒŒ์ผ ์ƒ์„ฑ

import React from "react";

const Home = () => {
    return (
        <div>
            <h1>์—ฌ๊ธฐ๊ฐ€ ํ™ˆ ์ž…๋‹ˆ๋‹ค.</h1>
            <p>๊ฐ€์žฅ ๋จผ์ € ๋ณด์—ฌ์ง€๋Š” ํŽ˜์ด์ง€ ์ž…๋‹ˆ๋‹ค.</p>
        </div>
    )
}
export default Home;

src/pages/About.js

import React from "react";

const About = () => {
    return (
        <div>
            <h1>์†Œ๊ฐœ</h1>
            <p>๋ฆฌ์•กํŠธ ๋ผ์šฐํ„ฐ๋ฅผ ์‚ฌ์šฉํ•ด ๋ณด๋Š” ํ”„๋กœ์ ํŠธ ์ž…๋‹ˆ๋‹ค.</p>
        </div>
    )
}
export default About;

Route ์ปดํฌ๋„ŒํŠธ๋กœ ํŠน์ • ๊ฒฝ๋กœ์— ์›ํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ ๋ณด์—ฌ์ฃผ๊ธฐ

<Route path="์ฃผ์†Œ ๊ทœ์น™" element={๋ณด์—ฌ์ค„ ์ปดํฌ๋„ŒํŠธ JSX} />

โฌ‡๏ธ

import './App.css';
import About from './pages/About';
import Home from './pages/Home';
import { BrowserRouter as Router, Route, Routes} from "react-router-dom";

function App() {
  return (
    <Router>
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/About" element={<About />} />
      </Routes>
    </Router>
  );
}

export default App;

Link ์ปดํฌ๋„ŒํŠธ ์‚ฌ์šฉ

์›น ํŽ˜์ด์ง€์—์„œ๋Š” ์›๋ž˜ ๋งํฌ๋ฅผ ๋ณด์—ฌ์ค„ ๋•Œ a ํƒœ๊ทธ๋ฅผ ์‚ฌ์šฉํ•˜๋Š”๋ฐ, ๋ฆฌ์•กํŠธ ๋ผ์šฐํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ํ”„๋กœ์ ํŠธ์—์„œ๋Š” a ํƒœ๊ทธ๋ฅผ ๋ฐ”๋กœ ์‚ฌ์šฉํ•˜๋ฉด ์•ˆ๋ฉ๋‹ˆ๋‹ค. (a ํƒœ๊ทธ๋ฅผ ํด๋ฆญํ•˜๋ฉด ๋ธŒ๋ผ์šฐ์ €์—์„œ๋Š” ํŽ˜์ด์ง€๋ฅผ ์ƒˆ๋กœ ๋ถˆ๋Ÿฌ ์˜ค๊ธฐ ๋•Œ๋ฌธ์—..)

 

Link ์ปดํฌ๋„ŒํŠธ ์—ญ์‹œ a ํƒœ๊ทธ๋ฅผ ์‚ฌ์šฉํ•˜๊ธด ํ•˜์ง€๋งŒ ํŽ˜์ด์ง€๋ฅผ ์ƒˆ๋กœ ๋ถˆ๋Ÿฌ์˜ค๋Š” ๊ฒƒ์„ ๋ง‰๊ณ , History API๋ฅผ ํ†ตํ•ด ๋ธŒ๋ผ์šฐ์ € ์ฃผ์†Œ์˜ ๊ฒฝ๋กœ๋งŒ ๋ฐ”๊พธ๋Š” ๊ธฐ๋Šฅ์ด ๋‚ด์žฅ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

src/pages/Home.js

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

const Home = () => {
    return (
        <div>
            <h1>์—ฌ๊ธฐ๊ฐ€ ํ™ˆ ์ž…๋‹ˆ๋‹ค.</h1>
            <p>๊ฐ€์žฅ ๋จผ์ € ๋ณด์—ฌ์ง€๋Š” ํŽ˜์ด์ง€ ์ž…๋‹ˆ๋‹ค.</p>
            <Link to="/about">์†Œ๊ฐœ</Link>
        </div>
    )
}
export default Home;

URL ํŒŒ๋ผ๋ฏธํ„ฐ

  1. URL ํŒŒ๋ผ๋ฏธํ„ฐ๋Š” ๋ฆฌ์•กํŠธ ๋ผ์šฐํ„ฐ์—์„œ URL ํŒŒ๋ผ๋ฏธํ„ฐ ๊ฐ’์„ ๊ฐ€์ ธ์˜ค๊ธฐ ์œ„ํ•œ ํ›…(Hook) ์ž…๋‹ˆ๋‹ค.
  2. URL ํŒŒ๋ผ๋ฏธํ„ฐ๋Š” useParams๋ผ๋Š” Hook์„ ์‚ฌ์šฉํ•˜์—ฌ ๊ฐ์ฒด ํ˜•ํƒœ๋กœ ์กฐํšŒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  3. URL ํŒŒ๋ผ๋ฏธํ„ฐ์˜ ์ด๋ฆ„์€ ๋ผ์šฐํŠธ ์„ค์ •ํ•  ๋•Œ Route ์ปดํฌ๋„ŒํŠธ์˜ path props๋ฅผ ํ†ตํ•ด ์„ค์ • ํ•ฉ๋‹ˆ๋‹ค.
  4. :username ๋ถ€๋ถ„์€ ํ˜ธ์ถœํ•˜๋Š” ํŽ˜์ด์ง€์—์„œ ์ง€์ •ํ•œ ์œ ๋™์ ์ธ ๊ฐ’(aka ๋งค๊ฐœ๋ณ€์ˆ˜)์œผ๋กœ ๋Œ€์ฒด๋˜์–ด ์ปดํฌ๋„ŒํŠธ์— ์ „๋‹ฌ๋ฉ๋‹ˆ๋‹ค.

Profile.js

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

const data = {
	frontend: {
		name: "๊ณฐ๋Œ์ด์‚ฌ์œก์‚ฌ",
		description: "๋ฆฌ์•กํŠธ๋ฅผ ์ข‹์•„ํ•˜๋Š” ๊ฐœ๋ฐœ์ž",
	},
	backend: {
		name: "๋‹ฌ๋น›์‚ฌ๋ƒฅ๊พผ",
		description: "์Šคํ”„๋ง ๋ถ€ํŠธ๋ฅผ ์ข‹์•„ํ•˜๋Š” ๊ฐœ๋ฐœ์ž"
	},
};

const Profile = () => {
	const params = useParams();
	const profile = data[params.username];

	return(
		<div>
            <h1>์‚ฌ์šฉ์ž ํ”„๋กœํ•„</h1>
            {profile ? (<div>
                <h2>{profile.name}</h2>
                <p>{profile.description}</p>
                </div>
                ) : (<p>์กด์žฌํ•˜์ง€ ์•Š๋Š” ํ”„๋กœํ•„ ์ž…๋‹ˆ๋‹ค.</p>)
            }
		</div>
	);
};

export default Profile;

App.js

import './App.css';
import About from './pages/About';
import Home from './pages/Home';
import { BrowserRouter as Router, Route, Routes} from "react-router-dom";

function App() {
  return (
    <Router>
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/About" element={<About />} />
        <Route path="/profiles/:username" element={<Profile />} />
      </Routes>
    </Router>
  );
}

export default App;

Home.js

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

const Home = () => {
    return (
        <div>
            <h1>์—ฌ๊ธฐ๊ฐ€ ํ™ˆ ์ž…๋‹ˆ๋‹ค.</h1>
            <p>๊ฐ€์žฅ ๋จผ์ € ๋ณด์—ฌ์ง€๋Š” ํŽ˜์ด์ง€ ์ž…๋‹ˆ๋‹ค.</p>
            <Link to="/about">์†Œ๊ฐœ</Link>
						<ul>
                <li>
                    <Link to="/profiles/frontend">Frontend ํ”„๋กœํ•„</Link>
                </li>
                <li>
                    <Link to="/profiles/backend">Backend ํ”„๋กœํ•„</Link>
                </li>

            </ul>
        </div>
    )
}
export default Home;

useNavigate

useNavigate๋Š” Link ์ปดํฌ๋„ŒํŠธ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ , ๋‹ค๋ฅธ ํŽ˜์ด์ง€๋กœ ์ด๋™ํ•ด์•ผ ํ•˜๋Š” ์ƒํ™ฉ์— ์‚ฌ์šฉํ•˜๋Š” Hook ์ž…๋‹ˆ๋‹ค.

useNavigate๋Š” ๋ฆฌ์•กํŠธ ๋ฌธ๋ฒ•์ด๋ผ ๋‹ค ์ ์šฉ๋˜์–ด ๋งŽ์ด ์“ฐ์ž…๋‹ˆ๋‹ค.
๋‚ด๋ถ€์ ์œผ๋กœ stack ๊ตฌ์กฐ(LIFO)์ด๊ธฐ ๋•Œ๋ฌธ์— -1 ํ•˜๋ฉด ์ด์ „ ํŽ˜์ด์ง€๋กœ ์ด๋™ํ•ฉ๋‹ˆ๋‹ค.
Link ์ปดํฌ๋„ŒํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๋‹ค๊ฐ€ ๋ฌธ์ œ๊ฐ€ ์ƒ๊ธฐ๋Š” ๊ฒฝ์šฐ๊ฐ€ ์žˆ์Œ.
์ด๋Ÿด ๋•Œ๋Š” useNavigate๋ฅผ ์‚ฌ์šฉ..

 

Home.js

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

const Home = () => {
    const navigate = useNavigate();

    return (
        <>
            <h1>์—ฌ๊ธฐ๋Š” ํ™ˆ ์ž…๋‹ˆ๋‹ค.</h1>
            <p>๊ฐ€์žฅ ๋จผ์ € ๋ณด์ด๋Š” ํŽ˜์ด์ง€ ์ž…๋‹ˆ๋‹ค.</p>
            <Link to="/about">์†Œ๊ฐœ</Link>
            <p style={{ textDecoration: 'underline' }} onClick={()=>navigate("/about")}>์†Œ๊ฐœํŽ˜์ด์ง€๋กœ ์ด๋™</p>
        </>
    );
};

export default Home;

About.js

import React from "react";
import { useNavigate  } from "react-router-dom";

const About = () => {
    const navigate = useNavigate();

    return (
        <>
            <h1>์†Œ๊ฐœ ํŽ˜์ด์ง€ ์ž…๋‹ˆ๋‹ค.</h1>
            <p>๋ฆฌ์•กํŠธ ๋ผ์šฐํ„ฐ๋ฅผ ์‚ฌ์šฉํ•ด ๋ณด๋Š” ํ”„๋กœ์ ํŠธ ์ž…๋‹ˆ๋‹ค.</p>
            <button onClick={()=>navigate(-1)}>๋’ค๋กœ ๊ฐ€๊ธฐ</button>
        </>
    );
};

export default About;

Navigate ์ปดํฌ๋„ŒํŠธ (๋ฆฌ๋‹ค์ด๋ ‰์…˜)

Navigate ์ปดํฌ๋„ŒํŠธ๋Š” ํ™”๋ฉด์— ๋ณด์—ฌ์ฃผ๋Š” ์ˆœ๊ฐ„ ๋‹ค๋ฅธ ํŽ˜์ด์ง€๋กœ ์ด๋™์„ ํ•˜๊ณ  ์‹ถ์„ ๋•Œ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

์ฆ‰, ํŽ˜์ด์ง€๋ฅผ ๋ฆฌ๋‹ค์ด๋ ‰์…˜ ํ•˜๊ณ  ์‹ถ์„ ๋•Œ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

์˜ˆ) ๋งˆ์ดํŽ˜์ด์ง€ ๋ˆŒ๋ €์„ ๋•Œ ๋กœ๊ทธ์ธ ์•ˆ๋˜์–ด์žˆ์œผ๋ฉด ๋ฐ”๋กœ ๋กœ๊ทธ์ธ ํŽ˜์ด์ง€๋กœ ์ด๋™(๋ฆฌ๋‹ค์ด๋ ‰์…˜)

  • replace={true} ๋Š” ๋ธŒ๋ผ์šฐ์ €์˜ ์ฃผ์†Œ ํ‘œ์‹œ์ค„์˜ ๋‚ด์šฉ์„ ๋ฐ”๊พธ์ง€ ์•Š๊ณ  ์ด๋™ํ•  ์ˆ˜ ์žˆ๋„๋ก ์„ค์ •ํ•˜๋Š” ์˜ต์…˜
  • ์ด๋Ÿฌํ•œ ๋ฐฉ์‹์œผ๋กœ <Navigate> ์ปดํฌ๋„ŒํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด, ์ผ๋ฐ˜์ ์œผ๋กœ ์‚ฌ์šฉ๋˜๋Š” <a> ํƒœ๊ทธ๋‚˜ window.location ๋“ฑ์˜ ๋‹ค๋ฅธ ๋ฐฉ๋ฒ•๋ณด๋‹ค ๋ผ์šฐํ„ฐ์˜ ์ƒํƒœ๋ฅผ ์œ ์ง€ํ•˜๋ฉด์„œ ํšจ๊ณผ์ ์œผ๋กœ URL์„ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Login.js

const Login = () => {
	return <div>๋กœ๊ทธ์ธ ํŽ˜์ด์ง€</div>;
};

MyPage.js

import { Navigate } from "react-router-dom";
const MyPage = () => {
	const isLogin = false;

	if(!isLogin) {
		return <Navigate to="/login" replace={true} />;
	}
	return <div>๋งˆ์ดํŽ˜์ด์ง€</div>
};
export default MyPage;
profile

GiantStepDEV

@kongmi

ํฌ์ŠคํŒ…์ด ์ข‹์•˜๋‹ค๋ฉด "์ข‹์•„์š”โค๏ธ" ๋˜๋Š” "๊ตฌ๋…๐Ÿ‘๐Ÿป" ํ•ด์ฃผ์„ธ์š”!