
ํ๋ก์ ํธ์์ ํผ ์์ฑ ๋์ค ํ์ด์ง๋ฅผ ๋ฒ์ด๋๋ ์ํฉ์ ๋ง๋ ๋ชจ๋ฌ์ ๊ตฌํํด์ผ ํ๋ค.
๋ค๋ก๊ฐ๊ธฐ, ๋ด๋ถ ๋งํฌ ์ด๋, ์๋ก๊ณ ์นจ ๋ฑ
์ฌ์ฉ์๊ฐ ์๋์น ์๊ฒ ํ์ด์ง๋ฅผ ๋ ๋๋ ๊ฒฝ์ฐ๋ฅผ ๊ฐ์งํ๊ณ
ํ์ธ ๋ชจ๋ฌ์ ๋์ ์ดํ ์ฌ๋ถ๋ฅผ ํ์ธํด์ผ ํ๋ค.
์ฒ์์๋ ๋จ์ํ๊ฒ ๋ธ๋ผ์ฐ์ ํ์คํ ๋ฆฌ๋ฅผ ์ฌ์ฉํ๋ฉด ๋ ๊ฒ์ด๋ผ๊ณ ์๊ฐํ๋ค.
ํ์ง๋ง ์ค์ ๋ก ๊ตฌํํด๋ณด๋ ์๋ก๊ณ ์นจ + ๋ค๋ก๊ฐ๊ธฐ ์ผ์ด์ค์์ ๋ง์ ์์ธ ์ํฉ์ด ์กด์ฌํ๋ค.
์ด๋ฒ ๊ธ์ ๊ทธ ๊ณผ์ ์ ๊ฐ๋จํ๊ฒ ์ ๋ฆฌํด๋ณด๋ ค๊ณ ํ๋ค.
1๏ธโฃ ๋ธ๋ผ์ฐ์ ํ์คํ ๋ฆฌ๋ฅผ ๊ฐ๋ก์ฑ๊ธฐ
์ฒ์์๋ ๋จ์ํ๊ฒ ๋ค๋ก๊ฐ๊ธฐ๋ฅผ ๋ง์ผ๋ฉด ๋๋ค๋ ์๊ฐ์ผ๋ก ๊ตฌํ์ ์์ํ๋ค.
ํผ์ ์ง์ ํ ๋ ํ์คํ ๋ฆฌ๋ฅผ ํ๋ ๋ ์์๋๊ณ
๋ค๋ก๊ฐ๊ธฐ ์ด๋ฒคํธ(popstate)๊ฐ ๋ฐ์ํ๋ฉด ๊ฐ๋ก์ฑ์ ํ์ธ ๋ชจ๋ฌ์ ๋์ฐ๋ ๋ฐฉ์์ผ๋ก ๊ตฌํํ๋ค.
const handlePopState = () => {
history.pushState(null, '', location.href);
overlayStore.push(
<Dialog
variant="confirm"
message={
<>
์์ฑ ์ค์ธ ๋ด์ฉ์ด ์ฌ๋ผ์ง๋๋ค.<br />
์ ๋ง ๋ค๋ก ๊ฐ์๊ฒ ์ต๋๊น?
</>
}
onConfirm={() => {
window.removeEventListener('popstate', handlePopState);
history.go(-2);
}}
onCancel={() => overlayStore.pop()}
/>
);
};
// ์ด๊ธฐ ๋ฐฉ์ด์ฉ ์คํ
history.pushState(null, '', location.href);
์ด ๋ฐฉ์์ ๋ค๋ก๊ฐ๊ธฐ ์์ฒด๋ฅผ ๋ง๊ณ ๋ชจ๋ฌ์ ๋์ฐ๋ ๊ฑด ์ ๋์ํ๋ค.
๊ทธ๋ฐ๋ฐ ์๋ก๊ณ ์นจ์ ์๋ ์๊ฐ ๋ฌธ์ ๊ฐ ๋ฐ์ํ๋ค.
๐คฏ ์์๊ณผ ๋ฌ๋๋ ๋์
์๋ก๊ณ ์นจ > ๋ธ๋ผ์ฐ์ ์์ฒด ์๋ก๊ณ ์นจ ์๋ด ๋ชจ๋ฌ >
๋ชจ๋ฌ ์๋ก๊ณ ์นจ ๋ฒํผ ํด๋ฆญ > ํผ ์์ > ๋ค๋ก๊ฐ๊ธฐ > ๋ค๋ก๊ฐ๊ธฐ ์๋ด ๋ชจ๋ฌ... ๊ฐ์ ์ํฉ์์๋
๋ค๋ก๊ฐ๊ธฐ๊ฐ ํ ๋ฒ์ ์ด์ ํ์ด์ง๋ก ์ด๋ํ์ง ์๊ณ
์ค๊ฐ์์ ์ํ๊ฐ ๋ฉ์ถ๊ฑฐ๋ ์์๊ณผ ๋ค๋ฅด๊ฒ ๋์ํ๋ค.
์ฒ์์๋ ๋จ์ํ history.go(-2)๋ก ํด๊ฒฐํ๋ ค ํ์ง๋ง
ํ ์คํธ๋ฅผ ๋ฐ๋ณตํ ์๋ก ํ์คํ ๋ฆฌ ์คํ์ด ํญ์ ๋์ผํ์ง ์๋ค๋ ๊ฑธ ์๊ฒ ๋์๋ค.
2๏ธโฃ ์นด์ดํธ๋ก ๋ณด์ ํ๊ธฐ
๊ทธ๋์ ์๊ฐํ ๋ ๋ฒ์งธ ๋ฐฉ๋ฒ์ด
ํ์คํ ๋ฆฌ ๋ณํ ํ์๋ฅผ ref๋ก ๊ณ์ฐํ๋ ๋ฐฉ์์ด์๋ค.
pushState๊ฐ ์คํ๋ ๋๋ง๋ค ์นด์ดํธ๋ฅผ ์ฆ๊ฐ์ํค๊ณ
๋ค๋ก๊ฐ๊ธฐ ์ ํด๋น ํ์๋งํผ ํ ๋ฒ์ ์ด๋ํ๋๋ก ๊ตฌํํ๋ค.
const pushCount = useRef(0);
const handlePopState = () => {
history.pushState(null, '', location.href);
pushCount.current += 1;
const targetIndex = -(pushCount.current + 1);
history.go(targetIndex);
};
์ด ๋ฐฉ์์ ์ผ๋ถ ์ผ์ด์ค์์๋ ์ํ๋ ๋๋ก ๋์ํ๋ค.
ํ์ง๋ง ๋ ๋ค๋ฅธ ๋ฌธ์ ๊ฐ ๋ฐ์ํ๋ค...๐คฆโ๏ธ

๋ธ๋ผ์ฐ์ ์์ฒด ์๋ก๊ณ ์นจ ๋ชจ๋ฌ์ด ๋จ๊ณ ์ ์ ๊ฐ ์๋ก๊ณ ์นจ์ ๋๋ ์ ๋๋
๋ธ๋ผ์ฐ์ ์ ํ์คํ ๋ฆฌ ์คํ์ด ์ฆ๊ฐํด์ ๋ฌธ์ ์์ด ๋ค๋ก๊ฐ๊ธฐ๊ฐ ๋์ํ์ง๋ง
์ทจ์ ๋ฒํผ์ ๋๋ฅด๋ ์ผ์ด์ค๋ ํผ์ ์๋ฌด๋ฐ ์ ๋ ฅ ์์ด ์๋ก๊ณ ์นจ์ ํ์๋๋
๋ธ๋ผ์ฐ์ ํ์คํ ๋ฆฌ๊ฐ ์์ด์ง ์์์ ์นด์ดํธ ๋ฐฉ์์ผ๋ก ํด๊ฒฐํ ์ ์๋ค๋๊ฑธ ๊นจ๋ฌ์๋ค.
๊ทธ๋์ ํ์คํ ๋ฆฌ๋ฅผ ๊ธฐ์ค์ผ๋ก ๊ณ์ฐํ๋ ๋ฐฉ์์
ํ์คํ ๋ฆฌ๋ฅผ ๋ถ๋ฌ์ค๊ฑฐ๋ ์กฐ์์ ํ ์ ์๊ธฐ ๋๋ฌธ์ ๋ถ์์ ํ๋ค๊ณ ๋๊ผ๊ณ
๋ค๋ฅธ ๋ฐฉ์์ผ๋ก ๋ค์ ํด๊ฒฐํด๋ณด๋ ค๊ณ ํ๋ค.
3๏ธโฃ URL ๊ด๋ฆฌ ๋ฐฉ์์ผ๋ก ์ ํ
ํ์คํ ๋ฆฌ๋ฅผ ๊ธฐ์ค์ผ๋ก ๊ณ์ฐํ๋ ๋์
์ด๋๋ก ์ด๋ํด์ผ ํ๋์ง ๊ฒฝ๋ก๋ฅผ ์ง์ ๊ด๋ฆฌํ๋ ๋ฐฉ์์ผ๋ก ๋ณ๊ฒฝํ๋ค.
์ ์ ๊ฐ ๋ฐฉ๋ฌธํ URL์ Zustand์ ์ ์ฅํด์ ์คํ์ฒ๋ผ ๊ด๋ฆฌํ๊ณ ,
๋ค๋ก๊ฐ๊ธฐ๋ฅผ ํ ๋ ์ด์ URL๋ก ์ง์ ์ด๋์ํค๋ ๋ฐฉ์์ผ๋ก ๊ตฌํํ๋ค.
const targetUrl = getPreviousUrl();
router.push(targetUrl);
์ด๋ ๊ฒ ๋ณ๊ฒฝํ๋๋ ์๋ก๊ณ ์นจ ์ฌ๋ถ๋ ๋ธ๋ผ์ฐ์ ํ์คํ ๋ฆฌ ์คํ์ ์๊ด์์ด
ํญ์ ์ด๋ํ URL์ด ๋ช ํํด์ง๊ณ ์์ธก ๊ฐ๋ฅํ ๋์์ ๋ง๋ค ์ ์์๋ค.
๐คฏ ๋ค ๋๋ฌ๋ ์ค ์์๋๋ฐ..
๊ทธ๋ฐ๋ฐ...URL ๊ธฐ๋ฐ์ผ๋ก ๋ฐ๊พผ ์ดํ์๋ ํ ๊ฐ์ง ๋ฌธ์ ๊ฐ ๋ ๋จ์ ์์๋ค.
์๋ก๊ณ ์นจ์ ์ฌ๋ฌ ๋ฒ ๋ฐ๋ณตํ ๋ค ๋ค๋ก๊ฐ๊ธฐ๋ฅผ ์๋ํ๋ฉด
๋ชจ๋ฌ์ด ๋จ์ง ์๊ฑฐ๋ router.push๊ฐ ๊ฐํ์ ์ผ๋ก ๋์ํ์ง ์๋ ๋ฌธ์ ๊ฐ ์์๋ค.
์์ธ์ ์ฐพ์๋ณด๋ Next.js์์ popstate ์ด๋ฒคํธ๊ฐ ๋ผ์ฐํฐ ์ํ ๋ณต๊ตฌ๋ณด๋ค ๋จผ์ ์คํ๋์ด
ํ์ด๋ฐ ์ด์๋ก ๋์ํ์ง ์์๋ ๊ฒ์ด์๋ค.
setTimeout(() => {
onPrevent('POPSTATE');
}, 0);
๊ทธ๋์ navigation ์ฒ๋ฆฌ๋ฅผ setTimeout๋ก ์ฒ๋ฆฌํ๋๋
ํ์ด๋ฐ ์ด์ ์์ด ์์ ์ ์ผ๋ก ๋์ํ๋ค.
๐ ์ ๋ฆฌ
๋ธ๋ผ์ฐ์ ํ์คํ ๋ฆฌ๋ฅผ ์ง์ ์ ์ดํ๋ ๊ฑด ์ ๋ง ๋ง์ ์์ธ๊ฐ ์กด์ฌํ๋ค.
ํ์ด์ง ์ดํ ๋ก์ง์์๋ ํ์คํ ๋ฆฌ๋ฅผ ์ง์ ์กฐ์ํ๊ธฐ ๋ณด๋ค๋
์ฌ์ฉ์๋ฅผ ์ด๋๋ก ์ด๋์ํฌ์ง๋ฅผ ์๊ฐํ๋๊ฒ ๋ ์์ ์ ์ด๋ผ๋ ๊ฑธ ๋ฐฐ์ ๋ค.
๋ ์ข์ ๋ฐฉ๋ฒ์ ์๊ฒ ๋๋ค๋ฉด ์ถ๊ฐ ํฌ์คํ ์ผ๋ก ๋จ๊ฒจ์ผ๊ฒ ๋ค๐ฅน