Single Page Application
SPA๋ ์๋ฒ๋ก๋ถํฐ ์์ ํ ์๋ก์ด ํ์ด์ง๋ฅผ ๋ถ๋ฌ์ค๋ ๊ฒ์ด ์๋๋ผ,
ํ๋ฉด์ ์
๋ฐ์ดํธํ๊ธฐ ์ํด ํ์ํ ๋ฐ์ดํฐ๋ง ์๋ฒ์์ ์ ๋ฌ๋ฐ์ ๋ธ๋ผ์ฐ์ ์์
ํด๋นํ๋ ๋ถ๋ถ๋ง ์
๋ฐ์ดํธํ๋ ๋ฐฉ์์ผ๋ก ์๋ํ๋ ์น ์ ํ๋ฆฌ์ผ์ด์
์ด๋ ์น ์ฌ์ดํธ๋ฅผ ๋งํ๋ค.
๋น ๋ฅธ ์
๋ฐ์ดํธ์ ๋ ๋๋ง ์๋, ์์ฐ์ค๋ฌ์ด UI
DOM์ ์ง์ ์์ ํ๋ ๊ฒ์ด ์๋๋ผ ์
๋ฐ์ดํธํด์ผ ํ ์ต์ํ์ ๋ถ๋ถ๋ง ์ฐพ์์ ๋ณ๊ฒฝํ๊ธฐ ๋๋ฌธ์ ๋น ๋ฅธ ์
๋ฐ์ดํธ๊ฐ ๊ฐ๋ฅํ๊ณ , ์ ์ฒด ํ์ด์ง๋ฅผ ์
๋ฐ์ดํธ ํ ํ์๊ฐ ์๊ธฐ์ ๊น๋นก์์ด ์๋ค.
์ฌ์ฌ์ฉ์ฑ
๋ฆฌ์กํธ๋ ๋ชจ๋ ํ์ด์ง๊ฐ ์ปดํฌ๋ํธ๋ก ๊ตฌ์ฑ๋์ด์ ธ ์๊ณ , ํ๋์ ์ปดํฌ๋ํธ๋ ๋ค๋ฅธ ์ฌ๋ฌ๊ฐ์ ์ปดํฌ๋ํธ๋ก ๊ตฌ์ฑ๋ ์ ์๋ค. ๋ฐ๋ผ์ ๋ ๊ณ ๋ธ๋ก์ ์กฐ๋ฆฝํ๋ฏ ์ปดํฌ๋ํธ๋ฅผ ์กฐํฉํด์ ์ฌ์ฉํ ์ ์๊ธฐ์ ์ฌ์ฌ์ฉ์ฑ์ด ์ข๋ค.
ํ๋ฐํ ์ง์๊ณต์ ๋ฐ ์ปค๋ฎค๋ํฐ
๋ค์๊ฐ ์ฌ์ฉํ๊ธฐ์ ๋ชจ๋ฅด๋ ๊ฒ์ ๋ฐ๋ก๋ฐ๋ก ์ฐพ์์ ๋ณผ ์ ์๋ค.
React Native
๋ณ๋์ ์ธ์ด๋ฅผ ๋ฐฐ์ ๋ชจ๋ฐ์ผ ์ฑ์ ๊ฐ๋ฐํ์ง ์๊ณ ,
React Native๋ฅผ ํ์ฉํ์ฌ ๋ชจ๋ฐ์ผ ํ๊ฒฝ ๊ฐ๋ฐ์ ํ ์ ์๋ค.
(์๋๋ก์ด๋ ์ฑ๊ณผ IOS ๋์์ ๋ง๋ค ์ ์์)
๋ฌด๊ฑฐ์ด JavScript ํ์ผ
์ฒซ ํ๋ฉด ๋ก๋ฉ ์ ์ฝ์ด๋ค์ธ HTML ํ์ผ์ ๊ฑฐ์ ๋น์ด์๊ณ , ๋๋ถ๋ถ์ ์ฝ๋๋ JavaScript ํ์ผ ์์ ๋ค์ด์๋ค ๋ณด๋ ์์ฐ์ค๋ฝ๊ฒ JavaScript ํ์ผ์ด ๋ฌด๊ฑฐ์์ง๋ค. ์ฆ, JavaScript ํ์ผ์ ๊ธฐ๋ค๋ฆฌ๋ ์๊ฐ์ผ๋ก ์ธํด ์ฒซ ํ๋ฉด ๋ก๋ฉ ์๊ฐ์ด ๊ธธ์ด์ง๋ค๋ ๊ฒ.
๊ฒ์ ์์ง ์ต์ ํ(SEO)์ ๋ถ๋ฆฌ
๊ฒ์ ๋ก๋ด์ ์๋ฃ๋ฅผ ์์งํ ๋์ ์น ํ์ด์ง์ URL์ ๋ฌผ๋ก ์ด๊ณ HTML ๋ฌธ์ ๋ด์ ๊ฐ์ข
ํ๊ทธ๋ ๋งํฌ ๋ฑ์ ๋ถ์ํ๋ค. SPA๋ HTML์ด ๊ฑฐ์ ๋น์ด์๋ค ๋ณด๋ ๊ฒ์ ๋ก๋ด์ด ์ถฉ๋ถํ ์๋ฃ๋ฅผ ์์งํ์ง ๋ชปํ๋ค. (ํ์ง๋ง, SSR๋ก ํด๊ฒฐ ๊ฐ๋ฅํ๋ค.)
๋์ ์ํ๊ด๋ฆฌ ๋ณต์ก๋
React ์์๋ ์ฑ๋ฅ ์ต์ ํ๋ฅผ ํ๊ธฐ ์ํด์๋ State๋ฅผ ์ ๊ด๋ฆฌํ๋ ๊ฒ์ด ์ค์ํ๋ค.
์น์ฌ์ดํธ์ ๊ท๋ชจ๊ฐ ์ปค์ ธ์ ์ปดํฌ๋ํธ์ ๊ฐ์๊ฐ ๋ง์์ง๋ฉด ์ํ๊ด๋ฆฌ์ ๋ณต์ก๋๋ ์ฆ๊ฐํ๊ธฐ์ State๋ฅผ ์ ๊ด๋ฆฌํ๋ ๊ฒ์ด ์ด๋ ต๋ค. ๊ทธ๋์ ๋ณดํต ํฐ ๊ท๋ชจ์ ํ๋ก์ ํธ์ ๊ฒฝ์ฐ Redux, Recoil , Mobx ์ ๊ฐ์ ์ํ๊ด๋ฆฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ค์ ์ฌ์ฉํ๋ค.
์๋ก์ด ๋ฒ์ ์ ๋ํ ํ์ต ์๊ตฌ
์๋กญ๊ฒ ๊ณต๋ถํ ๊ฒ ๋ง๋ค..
dynamic import๋ thenํจ์๋ฅผ
์ฌ์ฉํด ํ์ํ ์ฝ๋๋ง ๊ฐ์ ธ์จ๋ค.
์ด ๋ฐฉ์์ ์ฌ์ฉํ๋ฉด ๋ฒ๋ค๋ง ์ ๋ถํ ๋ ์ฝ๋(์ฒญํฌ)๋ฅผ
์ง์ฐ ๋ก๋ฉ์ํค๊ฑฐ๋ ์์ฒญ ์์ ๋ก๋ฉํ ์ ์๋ค.
์ด๋ ๊ฒ ์ฌ์ฉ์๊ฐ from์ ํตํด ์์์
์ ์ถํ ๊ฒฝ์ฐ์๋ง ๊ฐ์ ธ์ค๋๋ก ํ ์ ์๋ค.
form.addEventListener("submit", e => {
e.preventDefault();
/* ๋์ ๋ถ๋ฌ์ค๊ธฐ๋ ์ด๋ฐ ์์ผ๋ก ์ฝ๋์ ์ค๊ฐ์ ๋ถ๋ฌ์ฌ ์ ์๋ค. */
import('library.moduleA')
.then(module => module.default)
.then(someFunction())
.catch(handleError());
});
const someFunction = () => {
/* moduleA๋ฅผ ์ฌ๊ธฐ์ ์ฌ์ฉํ๋ค. */
}
dynamic import๋ React.lazy ์ ํจ๊ป ์ฌ์ฉํ ์ ์๋ค.
React 18 ๋ฒ์ ์์๋ createRoot API๋ฅผ ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์
๋ ์ด์ ReactDOM.render๋ฅผ ์ง์ํ์ง ์๋๋ค.
/* React 18์ด์ ์ index.js */
const rootElement = document.getElementById("root");
ReactDOM.render(<AppTest />, rootElement);
-------
/* ๋ฐ๋ index.js */
import { createRoot } from "react-dom/client";
const rootElement = document.getElementById("root");
const root = createRoot(rootElement);
root.render(
<App />
);
์ง๊ธ๊น์ง๋ Concurrent Mode๋ผ๊ณ ๋ถ๋ ธ์ง๋ง,
์ด๋ฒ์ Concurrent Feature๋ก ๋ฐ๋๋ฉด์ ํ๋์ ๊ธฐ๋ฅ์ผ๋ก ๋ค์ด์ค๊ฒ ๋์๋ค.
๊ทธ ์ค์๋ Suspense ๊ธฐ๋ฅ์ด ์๋๋ฐ, React 18 ๋ฒ์ ๋ถํฐ๋
์ด Suspense ๊ธฐ๋ฅ์ ์ด์ฉํ์ฌ ๋
๋ฆฝ์ ์ผ๋ก ๋ ๋๋ง์ ํ ์ ์๊ฒ ๋์๋ค.