์ฃผ์ ์์
- spa๋ก ๋ก๊ทธ์ธ ๊ตฌํ โ
2024-09-04
- ๋ก๊ทธ์ธ ํ๋ฉด
- ๋ก๊ทธ์ธ ์๋ฌ์ ์๋ด๋ฌธ๊ตฌ
- ๋ก๊ทธ์ธ ์ฑ๊ณต์ ๋ฉ์ธ์ผ๋ก ์ด๋
- ์๋ฌ ํธ๋ค๋ง โ
2024-09-04
- ๋ก๊ทธ์ธ ์๋ฌ ์ํ๋ณ๋ก ์ฒ๋ฆฌ
throw error๋ฅผ ํตํ ์๋ฌ ์ ํ
ํ์ต ํค์๋
- ํจ์คํฌํธ ๋ชจ๋ โ 2024-09-04
- ๋ก๊ทธ์ธ ๋ก์ง โ 2024-09-04
ํ์ต์ ๋ฆฌ ์ข ํฉ๋ณธ
https://luxurious-share-af6.notion.site/3-1f7fcdb0591241f487bdfa6f74f1200a?pvs=4
๊ณ ๋ฏผ ๋ฐ ํด๊ฒฐ๊ณผ์
๋ก๊ทธ์ธ ํ์ด์ง ํด๋ผ์ด์ธํธ ์ฌ์ด๋ ๋ ๋๋ง ๋ฐฉ์์ผ๋ก ๊ตฌํํ๊ธฐ
๊ธฐ๋ณธ์ ์ธ ๋ ์ด์์ ์์ฒด๋ ์๋ฒ์ฌ์ด๋ ๋ ๋๋ง์ผ๋ก ๊ตฌํ์ ํ์ง๋ง, ๊ฐ๊ฐ์ ์ปดํฌ๋ํธ๋ค์ ํด๋ผ์ด์ธํธ ์ฌ์ด๋ ๋ ๋๋ง์ผ๋ก ๊ตฌํ์ ํ์๋ค.
ํ์ง๋ง ์ด๋ ๊ฒ ํด๋ผ์ด์ธํธ ์ฌ์ด๋ ๋ ๋๋ง์ผ๋ก ๊ตฌํํ๋ ๊ณผ์ ์์ views ํด๋์ index.jsํ์ผ์ ์ํธ๋ฆฌ ํฌ์ธํธ๋ฅผ ๊ฐ๋ฆฌํค๊ณ , app์์ ๊ฐ ํ์ด์ง์ ๋ํด์ ๋ ๋๋ง์ ์ํค๋๋ก ํ์๋๋ฐ ์ด ๊ณผ์ ์์ ๋ง์ฝ ๋ก๊ทธ์ธ์ด ์ถ๊ฐ๋ ๊ฒฝ์ฐ ๊ฒฝ๋ก๋ฅผ ์
๋ ฅํ ์ ์๋ express.render์ ํน์ฑ์ ์๋ฒ์ฌ์ด๋ ๋ ๋๋ง ๋ฐฉ์์ผ๋ก ๋ค์๊ธ ๋ค๋ฅธ ํ์ด์ง๋ก ์ด๋์ํค๋ ค๋ฉด index.js์ login.js ํ์ผ ๋ชจ๋๋ฅผ ๋๋ ๋ฐฉ๋ฒ๋ฐ์ ์๊ฐ์ด ๋์ง ์์๋ค.
ํ์ง๋ง ์ด๋ ๊ฒ ํ๊ฒ ๋๋ฉด ๊ธฐ์กด์ ๋๋ ํ ๋ฆฌ ๊ตฌ์กฐ ์์ฒด๊ฐ ๋ฌด์ํด์ง ๋ฟ๋๋ฌ, ๊ธฐ์กด์ ์ฌ์ฉํ๋ Pages ๋๋ ํ ๋ฆฌ๋ ์ ํ ํ์์๋ ๋๋ ํ ๋ฆฌ๊ฐ ๋์ด๋ฒ๋ฆฌ๊ธฐ ๋๋ฌธ์ ์ด๋ฅผ ํ์ฉํ ๋ฐฉ๋ฒ์ ๊ณ ๋ฏผํด๋ณด์๋ค.
์ฃผ์๋ฅผ ๋ฐ์ ๋์ ์ผ๋ก ํ์ด์ง ๋ ๋๋งํ๊ธฐ
// /app/app.js
import navigation from "../shared/utils/navigation.js";
function entryPoint() {
const pathName = window.location.pathname;
console.log(pathName);
navigation.navigate(pathName);
}
window.onpopstate = navigation.onPageChanged;
document.addEventListener("DOMContentLoaded", entryPoint);๊ธฐ์กด์ mainpage๋ง ์๋ ๋๋ ๋ฉ์ธ ํ์ด์ง๋ง์ ๋ ๋๋ง ์ํค๋ ํจ์๋ฅผ ์คํ์ํค๋ ์ ๋๋ก app.js๋ฅผ ์ฌ์ฉํ์ง๋ง, ๋ก๊ทธ์ธ ํ์ด์ง๊ฐ ์ถ๊ฐ๋จ์ ๋ฐ๋ผ ์ด๋ฅผ pathname์ ๋ฐ๋ผ ํ์ํ ํ์ด์ง๋ฅผ ๋ ๋๋ง ์ํค๋๋ก ๋ฐฉ์์ ๋ฐ๊ฟจ๋ค.
app.get("/", isLoggedIn, (req, res, next) => {
res.render("index");
});
app.get("/login", isNotLoggedIn, (req, res, next) => {
res.render("index");
});๋ฐ๋ผ์ ์๋ฒ์์๋ pathname์ ๋ค๋ฅด์ง๋ง, ๋ชจ๋ ํ์ด์ง๋ค์ด entryPoint์์ ์ผ์ด๋๋ ๊ฒ์ ์ ์ ์๋ค. ์ด๋ ๊ฒ spa ๋ฐฉ์์ผ๋ก ๋ง๋ค๋ฉด ์ข์ ์ ์ ์๋ฌด๋๋ index๋ง์ ์ํธ๋ฆฌ ํฌ์ธํธ๋ก ์ก๊ธฐ ๋๋ฌธ์ ๋ค๋ฅธ pathname์ผ๋ก ์ ์ํ์ ๊ฒฝ์ฐ๋ ์ ๋ถ ํด๋ผ์ด์ธํธ ์ฌ์ด๋์์ ์ ์ด๊ฐ ๊ฐ๋ฅํ๋ค๋ ์ ์ด๋ค. ๋ฐ๋ผ์ ์๋ฒ๊ฐ ๋ ๋๋งํ๋ ๊ฒ์ ๊ธฐ์กด index์ ๋ ์ด์์์ ๋ถ๊ณผํ๊ธฐ ๋๋ฌธ์ api๊น์ง ์ฌ์ฉํด์ผ ํ๋ ์๋ฒ์ ์ญํ ์ด ๋ถ๋ด๋๋ ํจ๊ณผ๋ฅผ ๊ฐ์ง๋ค.
๋ค์ app.js๋ก ๋์์์, pathname์ ๋ฐ๋ผ spa๋ฅผ ๊ตฌํํ๊ธฐ ์ํด์๋ navigation ๊ฐ์ฒด๊ฐ ํ์์ ์ด์๋ค. ์๋ํ๋ฉด
- pathname ๊ด๋ฆฌ
- ๊ธฐ์กด ๋ ์ด์์์ ์ฌ์ฌ์ฉํ๋ฉด์ body์ ๋ด์ฉ๋ง ๋ฌ๋ผ์ง๊ฒ ํ๋ ๋ฐฉ์
- ํ์ด์ง ์ด๋์ ๋ฐ๋ฅธ ํ์ด์ง๋ณ ์ด๋ฒคํธ ํธ๋ค๋ฌ ๋ถ์ด๊ธฐ/๋ผ๊ธฐ ๋ฑ์ ์กฐ๊ฑด์ ๊ฐ์ถฐ์ผ ํ๊ธฐ ๋๋ฌธ์ ์ด๋ฅผ navigation ๊ฐ์ฒด๋ฅผ ๋ง๋ค์ด ํ์ด์ง๋ฅผ ์ด๋ํ๋ ๋ก์ง์ ๋ด๋นํ๋๋ก ํ๋ค.
// /shared/utils/navigation.js
import Main from "../../pages/main/index.js";
import Login from "../../pages/login/index.js";
import EventManager from "../../feature/index.js";
export default (function navigation() {
const navigator = {
"/": Main.render,
"/login": Login.render,
};
function navigate(pathname, prev) {
document.body.innerHTML = "";
history.pushState({ pathname: prev }, null, pathname);
navigator[pathname]();
}
function onPageChanged(event) {
document.body.innerHTML = "";
EventManager.detachEvent(event.pathname);
navigator[window.location.pathname]();
}
return {
navigate,
onPageChanged,
};
})();
navigation ๊ฐ์ฒด๋ ์ด๋์๋ ํ์ด์ง ์ด๋์ ์ฐ์ฌ์ผ ๋ก์ง์ด๊ธฐ ๋๋ฌธ์ fsd ๊ณ์ธต ์ค์ shared ๊ณ์ธต์ด ์๋ง์ ์๋ฆฌ์ผ ๊ฒ์ด๋ผ ์๊ฐํด์ ๋ฃ์ด์ฃผ์๋ค ํด๋น navigation๊ฐ์ฒด๋ ๋ฑ๋ก๋ pathname์ ๋ฐ๋ผ
- ๊ธฐ์กด ๋ ์ด์์์์ body๋ฅผ ์ด๊ธฐํ
history.pushState๋ฅผ ํ์ฉํ์ฌ ์ด์ ์ฃผ์๊ฐ์ ๊ฐ์ง๊ณ ๋ค๋ก๊ฐ๊ธฐ๋ฅผ ๋๋ ์ ๊ฒฝ์ฐ ์ด์ ๋ํด์ ๋ค์๊ธ ์ฌ๋ฐ๋ฅธ ํ์ด์ง๋ฅผ ๋ ๋๋ง ํ ์ ์๋๋ก ๋ก์ง ๊ตฌ์ฑ- ํ์ด์ง๋ณ ๋ ๋๋ง ํจ์ ์คํ ์ ๊ณผ์ ์ ๊ฑฐ์น๋ค. onPageChanged๋ ๊ธฐ์กด ํ์ด์ง๊ฐ ๋ค๋ฅธ ํ์ด์ง๋ก ์ด๋ํ ๋๋ง๋ค ์คํ๋ ์ ์๋๋ก window์ ๋ฑ๋กํด๋์ ์ด๋ฒคํธํธ๋ค๋ฌ์ธ๋ฐ, ์ด๋ ํ์ด์ง๊ฐ ๋ฐ๋ ๋๋ง๋ค ๋ค์๊ธ ์ด๊ธฐํ์ํค๊ณ , ํด๋น ํ์ด์ง์ ํด๋นํ๋ ์ด๋ฒคํธ ํธ๋ค๋ฌ๋ค์ ์ข ํฉํด๋์ ๋ชจ๋์ head์์ ๋ผ์ด๋์ผ๋ก์จ ์๋ฌ๊ฐ ๋ฐ์ํ์ง ์๋๋ก ์ค๊ณํ๋ค.
// /feature/index.js
export default (function EventManager() {
const route = {
"/login": "/feature/login/index.js",
"/main": "/feature/main/index.js",
};
function attachEvent(pathname) {
const script = document.createElement("script");
script.src = route[pathname];
script.type = "module";
document.head.appendChild(script);
}
function detachEvent(pathname) {
const script = document.head.querySelector(
`script[src="${route[pathname]}"]`
);
if (script) script.remove();
}
return { attachEvent, detachEvent };
})();
๋ฉ์ธํ์ด์ง์ ์ด๋ฒคํธ๋ฅผ ์ข ํฉํ์ฌ ๋ฑ๋กํ๊ธฐ๋ง ํด์ฃผ๋ feature/index.js๋ ํ์ด์ง๊ฐ ์ถ๊ฐ๋จ์ ๋ฐ๋ผ ํ์ด์ง๋ณ๋ก ๋๋ ํ ๋ฆฌ๋ฅผ ๋ง๋ค์ด depth๋ฅผ ํ๋จ๊ณ ๋๋ฆฌ๋ ๋์ ์, ํ์ด์ง๋ณ๋ก index.js๋ฅผ ๋ฐ๋ก ๋ง๋ค์ด ํด๋น ํ์ด์ง์ ๋ฑ๋ก๋์ด์ผ ํ ์ด๋ฒคํธ ์์๊ณผ ํธ๋ค๋ฌ๋ค์ ์ข ํฉํ์ฌ ๋ฑ๋กํ ์ ์๋๋ก ํด์ฃผ์์ผ๋ฉฐ, ์ด๋ฅผ ์ ๋๊ฒฝ๋ก๋ก ์ค์ ํ์ฌ head์ script๋ก ๋ฃ์ด์ฃผ๋ ๋ฐฉ์์ ์ฌ์ฉํ๋ค.