React Router v6의 새로운 API 중 하나로, 웹 애플리케이션에서 클라이언트 사이드 라우팅을 설정하는 데 사용
기존에는
<BrowserRouter>
<Routes>
<Route path="/home" element={<Home/>}/>
<Route path="/about" element={<About/>}/>
</Routes>
</BrowserRouter>
이런식으로 작성했었다!
하지만, 이제는 createBrowserRouter를 사용해서 라우팅을 설정해보자
const router = createBrowserRouter() 여기서, 라우트 배열을 인자로 받고, 라우터 객체를 반환하게 된다.
라우트 배열 : 배열의 각 항목은 라우터 설정을 나타낸다.
'Path' 속성은 URL 경로를 정의하고, 'element' 속성은 해당 경로에 매핑되는 React 컴포넌트를 정의하게 된다.
const router = createBrowserRouter([
{
path: '/',
element: <Root />,
},
]);
export default router;
먼저 이렇게 정의하게 되면, / url에 Root 컴포넌트가 매핑된다는 것을 의미한다.
그럼, 여기서 /about, /home 을 url로 정의를 어떻게 할까?
--> createBrowserRouter에서는 children 속성을 제공해준다!
createBrowserRouter에서 children 속성을 사용하여 중첩된 라우트를 정의할 수 있다. 이를 통해
/about,/home과 같은 URL 경로를 추가할 수 있다.
--> 기본 경로와 하위 경로가 계층적으로 설정되게 된다.

/) : /경로에 Root컴포넌트를 렌더링한다.Home 컴포넌트를 렌더링한다.About 컴포넌트를 렌더링한다. 이렇게 중첩된 라우트를 사용하려면, 
부모 컴포넌트(Root)에<outlet/> 컴포넌트를 추가해주어야 한다.
<Outlet/>컴포넌트는 자식 라우트의 렌더링 위치를 정의하며, 자식 라우트의 내용을 표시하는 역할을 한다.
<Outlet/> 은 부모 라우트의 렌더링 위치에 자식 라우트의 컴포넌트를 삽입한다. <Outlet/>을 사용함으로써, 자식 라우트의 내용이 부모 컴포넌트의 일부로 렌더링 된다. 
현재는 Header 컴포넌트 밑에 Outlet 컴포넌트가 위치하고 있다. 여기서 화면을 렌더링해보면,

<Outlet/>위치에 Home 컴포넌트가 추가된 것을 확인할 수 있다.
만약, Header 컴포넌트와 Outlet 컴포넌트의 위치가 바뀐다면,

이렇게 변경되는 것을 확인할 수 있다.
<Outlet/> 의 속성을 이용해서, Header, Footer, 사이드 바 등 다양한 속성을 추가할 수 있게 된다!
까먹을 뻔 했다..!

createBrowserRouter 라우터 생성 함수로 생성한 라우터 객체를 애플리케이션에 연결해주는 역할을 한다.
<RouterProvider> 는 애플리케이션에 라우터 컨텍스트를 제공하여, 라우팅 관련된 컴포넌트들이 URL에 따라 올바른 컴포넌트를 렌더링할 수 있도록 해준다.
--> 즉, 애플리케이션의 다른 부분에서 라우터 관련 정보와 기능을 사용할 수 있게 해준다!
라우터 객체 전달: router 속성으로 전달되는 라우터 객체는 라우터의 설정(경로, 컴포넌트 등)을 포함하고 있다. 이 객체는 애플리케이션의 라우팅을 관리한다.
라우터 객체를 React 애플리케이션에 연결하는 역할을 한다고 생각하면 될 것 같다!
이 컴포넌트를 통해 라우터 컨텍스트가 애플리케이션의 모든 하위 컴포넌트에 제공되게 된다.
에러 처리 : 라우팅 중에 에러가 발생했을 때, errorElement에 지정된 컴포넌트가 렌더링된다. 이 컴포넌트는 에러 정보를 표시하거나 사용자에게 에러 상황을 알리는 역할을 하게 된다.
정의된 라우트 내에서 에러 처리 : 각 라우트에 대해 errorElement를 정의함으로써, 특정 라우트에서만 발생할 수 있는 에러를 핸들링할 수 있다.
--> 이를 통해, 애플리케이션의 에러 처리 로직을 보다 세분화하고 구체화할 수 있다.
즉, 만약 Home페이지에서 에러가 발생한다면, Home페이지에 해당하는 errorElement를 설정해 두어, 사용자에게 보여주게 된다. 사용자는 Home페이지에서 에러를 만나도, About페이지로 이동하는 것은 문제가 되지 않는다!
const NotFound = () => {
return (
<>
<h1>404 Not Found</h1>
</>
);
};
export default NotFound;
간단하게 페이지 오류를 만들어보고, 이를 errorElement에 추가해보자!

errorElement에 설정된 컴포넌트는 라우터가 요청한 URL에 대해 유효한 경로를 찾지 못할 때(예를 들어, 잘못된 URL을 입력했을 때) 사용자에게 표시하게 된다.
errorElement에 추가한 오류 메시지를 보여주게 된다.
errorElement는 개별 라우트에서도 설정할 수 있으며, 이를 통해 각 라우트에 대해 별도의 에러 페이지를 정의할 수 있다.

아무것도 없는 배열을 만들고, 그 배열에서 0번째 name을 출력하려고 하면 오류가 발생하게 된다.
이렇게 <ErrorComponent/> 오류 메시지를 설정해두고,
errorElement에 추가하게 되면,
내가 설정한 오류가 제대로 뜨게 된다!
errorElement를 사용하여 오류 메시지를 출력하는 경우, 특정 라우트에서 에러가 발생해도 다른 사이트로의 이동에는 방해되지 않는다. 이는 errorElement가 각 라우트의 오류 처리를 독립적으로 관리하기 때문이다.
예를 들면, 로그인 성공 후 해당 페이지로 이동할 경우, 버튼을 눌렀을 때 해당 페이지로 이동할 경우 등등이 있다

useNavigate의 사용 방법
훅 호출: useNavigate 훅을 호출하여 navigate 함수를 얻는다.
--> 이 함수는 페이지를 프로그래밍적으로 탐색하는 데 사용된다.
페이지 이동: navigate 함수에 이동할 경로를 문자열로 전달하여, 해당 경로로 페이지를 이동할 수 있다. 예를 들어, navigate('/about') 는 현재 페이지에서 /about 페이지로 이동하도록 한다.
이로써 버튼을 눌렀을 때, onClick 함수가 실행되면서, navigate('/about')로 이동하게 된다!

URL 파라미터 추출 : URL의 동적 세그먼트(예: /users/:userId에서 :userId) 값을 추출하여 컴포넌트 내에서 사용할 수 있다.
export const users = [
{
id: 1,
name: '서연',
},
{
id: 2,
name: '니꼬',
},
];
간단하게, users라는 데이터를 만들어서 Home 컴포넌트에서 불러서 사용해보자
const Home = () => {
return (
<>
<div>
<h1>Users</h1>
<ul>
{users.map((user) => (
<li key={user.id}>{user.name}</li>
))}
</ul>
</div>
</>
);
};
export default Home;
정말 간단하게, user.name을 출력해 보았다.

그럼 여기서 서연을 눌렀을 때-> users/1로 이동해서 세부 정보를 볼 수 있도록 해볼까?
--> users/:userId가 된다
이렇게
<Link to={`/users/${user.id}`}>{user.name}</Link>
user.name을 눌렀을 때, /ùsers/${user.id} 로 이동하도록 해두었다.
그럼 라우터에서 해당 라우터를 설정해주어 한다
Router.tsx
{
path: 'users/:userId',
element: <User />,
},
여기서 path:'users/:userId' 로 경로를 표시해 두었다.
'users/:userId'로 동적 경로를 지정하여, URL의 :userId 부분이 동적으로 변할 수 있도록 설정해 둔 것이다!
동작 설명:
/users/${user.id} 경로로 이동한다.:을 사용해야 한다는 점이다!)const User = () => {
const { userId } = useParams();
return (
<>
<h1>
User with it {userId} is name : {users[Number(userId) - 1].name}
</h1>
</>
);
};
export default User;
useParams 호출:
const { userId } = useParams() 에서 useParams 훅을 호출하여 URL의 동적 파라미터인 userId를 추출한다.
이 userId는 URL의 /users/:userId에서 :userId 부분의 값을 의미한다.
동작과정
1 . URL 설정:
예를 들어, 사용자가 /users/2 경로로 이동하면, URL의 2 부분이 userId로 인식
2 . useParams 사용:
useParams 훅을 사용하여 userId 값을 추출한다.
--> 이 경우 userId는 문자열 '2'가 된다.
3 . 데이터 조회:
추출한 userId를 숫자로 변환하여, users 배열에서 해당 사용자의 이름을 조회한다.
예제에서는 users[Number(userId) - 1].name을 통해 userId가 2인 사용자의 이름을 조회한다.
4 . 결과 렌더링:
User 컴포넌트는 사용자 ID와 해당 사용자의 이름을 포함하는 <h1> 요소를 렌더링한다.
useParams를 사용하면, URL의 동적 세그먼트를 쉽게 추출하여 컴포넌트 내에서 사용할 수 있다.
<Outlet />위에도 한번 언급했었지만, 간단하게 정리하고 넘어가자
주요 기능
사용법

간단하게 Followers 라는 컴포넌트를 만들고
User 컴포넌트에 자식 컴포넌트로 추가해볼 예정이다.
const User = () => {
const { userId } = useParams();
return (
<>
<div>
<h1>
User with it {userId} is name : {users[Number(userId) - 1].name}
</h1>
<hr />
<Link to={'followers'}>See Followers</Link>
<Outlet />
</div>
</>
);
};
export default User;
<Link to={'followers'}>See Followers</Link> 를 살펴보면, followers로 이동하는 Link를 생성했다.
여기서 /followers로 실행시키면 --> http://localhost:3000/followers로 링크가 실행된다.
슬라이스를 빼고 followers만 실행시키면 --> http://localhost:3000/users/1/followers 현재 머물러 있는 링크에 + followers가 된다!
또한 여기 Link 컴포넌트 아래에 <Outlet/> 컴포넌트가 있다. Outlet 위치에 자식 컴포넌트가 들어온다고 생각하면 된다!
--> 그럼 라우터도 설정해주어야지!
{
path: 'users/:userId',
element: <User />,
children: [
{
path: 'followers',
element: <Followers />,
},
],
},
자식 라우트:
path: 'followers' : followers 경로를 정의한다.element: <Followers /> : followers 경로로 이동할 때 렌더링될 컴포넌트를 지정한다. 이 경로로 이동하면 Followers 컴포넌트가 렌더링된다.이렇게 하고 화면을 렌더링시켜보면,

User 부모 컴포넌트 렌더링 되고, <Outlet/> 위치에 <Followers/>가 렌더링 된 것을 확인할 수 있다!
부모 라우트에서 자식 라우트로 데이터를 전달하는 데 사용. 주로 중첩된 라우트에서, 부모 컴포넌트가 자식 컴포넌트에게 데이터를 제공하고자 할 때 유용하다.
만약, user(부모 컴포넌트)에서 Followers(자식 컴포넌트)에게 데이터를 전달하려고 할 때, 어떻게 해야할까?

<User/>부모 컴포넌트가 <Outlet context={value} /> 형태로 자식 컴포넌트에 데이터를 전달하게 된다. 여기서는 name을 Followers 컴포넌트에게 넘겨주고 있다고 생각하면 될 것 이다.
그럼 이제, 자식 컴포넌트에서는 어떻게 받아서 사용할까?
자식 컴포넌트는 useOutletContext 훅을 사용하여 부모 컴포넌트에서 제공한 데이터를 접근할 수 있다.
부모 컴포넌트로부터 받아온 { nameOfMyUser }를 사용해서 데이터를 화면에 출력해보자!

See Followers를 누르면, http://localhost:3000/users/1/followers로 이동하고, 부모 컴포넌트로 받아온 { nameOfMyUser }를 출력하는 것까지 확인할 수 있다!
부모 : User 컴포넌트는 현재 사용자의 이름을 Outlet 컴포넌트의 context 속성을 통해 전달
자식 : useOutletContext 훅을 사용하여 부모 컴포넌트에서 전달된 nameOfMyUser 데이터를 접근