
<a> 태그 대신 Link 컴포넌트를 사용하는 것이 좋음.단일 HTML 파일: React SPA는 하나의 HTML 파일을 로드하고나서 페이지를 다시 로드하지 않고도 애플리케이션 내에서 자유롭게 화면을 전환할 수 있다.
빠른 페이지 전환: 페이지를 전환할 때 서버로부터 전체 페이지를 다시 로드할 필요가 없으므로 서버 왕복 시간이 없고 빠르게 화면을 업데이트할 수 있다.
클라이언트 측에서 처리: 페이지 이동, 상태 관리, 렌더링은 대부분 클라이언트(브라우저)에서 처리되어 서버는 필요한 데이터만 제공하는 역할을 한다.
React Router: 클라이언트 사이드 라우팅을 처리하기 위해 react-router와 같은 라이브러리가 자주 사용된다. 이를 통해 URL이 변경될 때마다 특정 컴포넌트를 렌더링할 수 있다.
return (
<>
<div>Aaa 페이지 입니다.</div>
{/* 1. 리액트의 이동방식: 현재페이지에서 JS로 태그만 바꿔치기 => SPA */}
<Link to="/bbb">Bbb 페이지로 가는 기능</Link>
{/* 2. 고전HTML 이동방식: html페이지 새로접속함(느림) => MPA */}
<a href="/bbb">Bbb 페이지 이동</a>
</>
);
-------------------------------------
import { createBrowserRouter, RouterProvider } from "react-router-dom";
import Aaa from "./routes/aaa";
import Bbb from "./routes/bbb";
const 철수의페이지목록 = createBrowserRouter([
{
path: "/",
element: <App />,
},
{
path: "/aaa",
element: <Aaa />,
},
{
path: "/bbb",
element: <Bbb />,
},
]);
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<RouterProvider router={철수의페이지목록} />);
Link를 사용하기 위해서는 import { Link } from "react-router-dom"; 을 임폴트 해줘야 한다.
index.js 에서도 import 똑같이 해주고 페이지 목록을 배열형태로 만들어 주기 위해 철수의 페이지 목록 같은 변수형태로 만들어준다.
setState를 호출하면, 리액트는 이전 상태와 새로운 상태를 비교하기 시작
상태가 변경되었는지 확인하기 위해 얕은 비교(shallow comparison)를 수행
예를 들어, 객체의 상태가 변경될 경우 리액트는 객체의 참조(reference)를 비교하여 변경 여부를 판단
상태 변경이 필요하다고 판단되면, 상태를 비동기적으로 업데이트한다.
상태가 즉시 변경되는 것이 아니라, 비동기 큐에 상태 변경 요청이 쌓이게 된다.그러므로 setState를 여러 번 호출하더라도 성능을 최적화하기 위해 한 번에 배치(batch)하여 업데이트한다.
이 과정은 리액트의 내부 스케줄러에 의해 관리된다. 이런 비동기적 특성 때문에 setState를 호출한 직후의 상태 값은 바로 반영되지 않을 수 있다.
상태가 변경된 후, 리액트는 해당 컴포넌트를 다시 렌더링한다.
변경된 상태값을 기반으로 새로운 UI가 만들어진다. 효율적으로 DOM을 업데이트하기 위해 변경된 부분만 렌더링한다.
결론적으로 가상 DOM(Virtual DOM)과 실제 DOM을 비교하여 변경된 부분만 실제 DOM에 적용하는 방식
import React, { useState } from 'react';
export default function StateExample() {
const [counter1, setCounter1] = useState(0); // 기본 상태 업데이트 방식
const [counter2, setCounter2] = useState(0); // 함수형 업데이트 방식
const handleClick = () => {
// 일반 상태 업데이트 방식 (동일한 상태를 참조함)
setCounter1(counter1 + 1);
setCounter1(counter1 + 1);
setCounter1(counter1 + 1);
// 함수형 업데이트 방식 (이전 상태값을 기반으로 업데이트)
setCounter2(prevCounter => prevCounter + 1);
setCounter2(prevCounter => prevCounter + 1);
setCounter2(prevCounter => prevCounter + 1);
};
return (
<div>
<h1>State Example</h1>
<div>
<h2>Counter 1 (기본 업데이트)</h2>
<p>{counter1}</p>
</div>
<div>
<h2>Counter 2 (함수형 업데이트)</h2>
<p>{counter2}</p>
</div>
<button onClick={handleClick}>Update Counters</button>
</div>
);
}