์ํ ์ง์์ฑ ๋ฐ ์ ๋๋ฉ์ด์ ๋ณต๊ตฌ์ ์ค์ ์ ๋ CSS View Transitions๋ฅผ ํ์ํด ๋ณด์ธ์. ์๋ค๋ก ํ์ํ ๋๋ ๋งค๋๋ฌ์ด ์ฌ์ฉ์ ๊ฒฝํ์ ๋ง๋๋ ๋ฐฉ๋ฒ์ ๋ฐฐ์๋๋ค.
CSS View Transition ์ํ ์ง์์ฑ: ์ ๋๋ฉ์ด์ ์ํ ๋ณต๊ตฌ
CSS View Transitions๋ ๊ฐ๋ฐ์๊ฐ ์น ์ ํ๋ฆฌ์ผ์ด์ ์ ์ฌ๋ฌ ์ํ ๊ฐ์ ๋ถ๋๋ฝ๊ณ ์๊ฐ์ ์ผ๋ก ๋งค๋ ฅ์ ์ธ ์ ํ์ ์์ฑํ ์ ์๊ฒ ํด์ฃผ๋ ๊ฐ๋ ฅํ ์ ๊ธฐ๋ฅ์ ๋๋ค. ์ด๊ธฐ ๊ตฌํ์ ๊ธฐ๋ณธ์ ์ธ ์ ํ์ ์ค์ ์ ๋์์ง๋ง, ์ง์ ์ผ๋ก ์ธ๋ จ๋ ์ฌ์ฉ์ ๊ฒฝํ์ ๋ง๋๋ ๋ฐ ์์ด ์ค์ํ ์ธก๋ฉด์ ํนํ ํ์ด์ง๋ ์น์ ๊ฐ์ ์๋ค๋ก ํ์ํ ๋ ์ํ ์ง์์ฑ๊ณผ ์ ๋๋ฉ์ด์ ๋ณต๊ตฌ๋ฅผ ์ฒ๋ฆฌํ๋ ๊ฒ์ ๋๋ค.
์ํ ์ง์์ฑ์ ํ์์ฑ ์ดํดํ๊ธฐ
์ฌ์ฉ์๊ฐ ์ฌ์ง ๊ฐค๋ฌ๋ฆฌ๋ฅผ ํ์ํ๋ ์ํฉ์ ์์ํด ๋ณด์ธ์. ํด๋ฆญํ ๋๋ง๋ค ๋ฉ์ง ์ ๋๋ฉ์ด์ ๊ณผ ํจ๊ป ๋ค์ ์ด๋ฏธ์ง๋ก ์ ํ๋ฉ๋๋ค. ๊ทธ๋ฌ๋ ์ฌ์ฉ์๊ฐ ๋ธ๋ผ์ฐ์ ์ '๋ค๋ก' ๋ฒํผ์ ํด๋ฆญํ๋ฉด ์ ๋๋ฉ์ด์ ์ด ๋ฐ๋๋ก ์ฌ์๋์ด ์ด์ ์ด๋ฏธ์ง์ ์ํ๋ก ๋์๊ฐ ๊ฒ์ผ๋ก ๊ธฐ๋ํ ์ ์์ต๋๋ค. ์ํ ์ง์์ฑ์ด ์์ผ๋ฉด ๋ธ๋ผ์ฐ์ ๋ ์ ํ ์์ด ์ด์ ํ์ด์ง๋ก ๋ฐ๋ก ์ด๋ํ์ฌ ๊ฑฐ์ฌ๋ฆฌ๊ณ ์ผ๊ด์ฑ ์๋ ๊ฒฝํ์ ์ ๋ฐํ ์ ์์ต๋๋ค.
์ํ ์ง์์ฑ์ ์ ํ๋ฆฌ์ผ์ด์ ์ด UI์ ์ด์ ์ํ๋ฅผ ๊ธฐ์ตํ๊ณ ํด๋น ์ํ๋ก ๋ถ๋๋ฝ๊ฒ ๋ค์ ์ ํํ ์ ์๋๋ก ๋ณด์ฅํฉ๋๋ค. ์ด๋ ์ ์ฒด ํ์ด์ง ์๋ก๊ณ ์นจ ์์ด DOM์ ์กฐ์ํ๋ ๊ฒฝ์ฐ๊ฐ ๋ง์ ๋จ์ผ ํ์ด์ง ์ ํ๋ฆฌ์ผ์ด์ (SPA)์์ ํนํ ์ค์ํฉ๋๋ค.
๊ธฐ๋ณธ์ ์ธ View Transitions: ์์ฝ
์ํ ์ง์์ฑ์ ๋ํด ์์ธํ ์์๋ณด๊ธฐ ์ ์ CSS View Transitions์ ๊ธฐ๋ณธ์ ๋น ๋ฅด๊ฒ ์์ฝํด ๋ณด๊ฒ ์ต๋๋ค. ํต์ฌ ๋ฉ์ปค๋์ฆ์ ์ํ ๋ณ๊ฒฝ ์ฝ๋๋ฅผ document.startViewTransition()
๋ด์ ๋ํํ๋ ๊ฒ์
๋๋ค.
document.startViewTransition(() => {
// DOM์ ์ ์ํ๋ก ์
๋ฐ์ดํธํฉ๋๋ค
updateTheDOM();
});
๊ทธ๋ฌ๋ฉด ๋ธ๋ผ์ฐ์ ๋ ๊ด๋ จ DOM ์์์ ์ด์ ์ํ์ ์ ์ํ๋ฅผ ์๋์ผ๋ก ์บก์ฒํ๊ณ CSS๋ฅผ ์ฌ์ฉํ์ฌ ๋ ์ํ ๊ฐ์ ์ ํ์ ์ ๋๋ฉ์ด์
์ผ๋ก ๋ง๋ญ๋๋ค. transition-behavior: view-transition;
๊ณผ ๊ฐ์ CSS ์์ฑ์ ์ฌ์ฉํ์ฌ ์ ๋๋ฉ์ด์
์ ์ฌ์ฉ์ ์ ์ํ ์ ์์ต๋๋ค.
๊ณผ์ : ๋ค๋ก ๊ฐ๊ธฐ ํ์ ์ ์ ๋๋ฉ์ด์ ์ํ ๋ณด์กด
๊ฐ์ฅ ํฐ ๊ณผ์ ๋ ์ฌ์ฉ์๊ฐ ์ผ๋ฐ์ ์ผ๋ก ๋ธ๋ผ์ฐ์ ์ ๋ค๋ก ๊ฐ๊ธฐ ๋ฒํผ์ ํด๋ฆญํ์ฌ '๋ค๋ก' ํ์ ์ด๋ฒคํธ๋ฅผ ํธ๋ฆฌ๊ฑฐํ ๋ ๋ฐ์ํฉ๋๋ค. ๋ธ๋ผ์ฐ์ ์ ๊ธฐ๋ณธ ๋์์ ์ข ์ข ์บ์์์ ํ์ด์ง๋ฅผ ๋ณต์ํ์ฌ View Transition API๋ฅผ ํจ๊ณผ์ ์ผ๋ก ์ฐํํ๋ ๊ฒ์ ๋๋ค. ์ด๋ก ์ธํด ์์ ์ธ๊ธํ ์ด์ ์ํ๋ก์ ๊ฑฐ์ฌ๋ฆฌ๋ ์ด๋์ด ๋ฐ์ํฉ๋๋ค.
์ ๋๋ฉ์ด์ ์ํ ๋ณต๊ตฌ๋ฅผ ์ํ ํด๊ฒฐ์ฑ
์ด ๊ณผ์ ๋ฅผ ํด๊ฒฐํ๊ณ ๋ถ๋๋ฌ์ด ์ ๋๋ฉ์ด์ ์ํ ๋ณต๊ตฌ๋ฅผ ๋ณด์ฅํ๊ธฐ ์ํด ์ฌ๋ฌ ์ ๋ต์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
1. History API ๋ฐ popstate
์ด๋ฒคํธ ์ฌ์ฉ
History API๋ ๋ธ๋ผ์ฐ์ ์ ํ์คํ ๋ฆฌ ์คํ์ ๋ํ ์ธ๋ฐํ ์ ์ด๋ฅผ ์ ๊ณตํฉ๋๋ค. history.pushState()
๋ก ํ์คํ ๋ฆฌ ์คํ์ ์ ์ํ๋ฅผ ํธ์ํ๊ณ popstate
์ด๋ฒคํธ๋ฅผ ์์ ํจ์ผ๋ก์จ ๋ค๋ก ๊ฐ๊ธฐ ํ์์ ๊ฐ๋ก์ฑ๊ณ ์ญ๋ฐฉํฅ ๋ทฐ ์ ํ์ ํธ๋ฆฌ๊ฑฐํ ์ ์์ต๋๋ค.
์์ :
// ์ ์ํ๋ก ์ด๋ํ๋ ํจ์
function navigateTo(newState) {
document.startViewTransition(() => {
updateTheDOM(newState);
history.pushState(newState, null, newState.url);
});
}
// popstate ์ด๋ฒคํธ ์์
window.addEventListener('popstate', (event) => {
const state = event.state;
if (state) {
document.startViewTransition(() => {
updateTheDOM(state); // ์ด์ ์ํ๋ก ๋๋๋ฆฝ๋๋ค
});
}
});
์ด ์์ ์์ navigateTo()
๋ DOM์ ์
๋ฐ์ดํธํ๊ณ ์ ์ํ๋ฅผ ํ์คํ ๋ฆฌ ์คํ์ ํธ์ํฉ๋๋ค. ๊ทธ๋ฐ ๋ค์ popstate
์ด๋ฒคํธ ๋ฆฌ์ค๋๋ ๋ค๋ก ๊ฐ๊ธฐ ํ์์ ๊ฐ๋ก์ฑ๊ณ ๋ค๋ฅธ ๋ทฐ ์ ํ์ ํธ๋ฆฌ๊ฑฐํ์ฌ ์ด์ ์ํ๋ก ๋๋๋ฆฝ๋๋ค. ์ฌ๊ธฐ์ ํต์ฌ์ `history.pushState`๋ฅผ ํตํด ํธ์๋ state
๊ฐ์ฒด์ ์ถฉ๋ถํ ์ ๋ณด๋ฅผ ์ ์ฅํ์ฌ `updateTheDOM` ํจ์์์ ์ด์ ์ํ์ DOM์ ๋ค์ ์์ฑํ ์ ์๋๋ก ํ๋ ๊ฒ์
๋๋ค. ์ด๋ ์ข
์ข
์ด์ ๋ทฐ๋ฅผ ๋ ๋๋งํ๋ ๋ฐ ์ฌ์ฉ๋ ๊ด๋ จ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ๋ ๊ฒ์ ํฌํจํฉ๋๋ค.
2. Page Visibility API ํ์ฉ
Page Visibility API๋ฅผ ์ฌ์ฉํ๋ฉด ํ์ด์ง๊ฐ ๋ณด์ด๊ฑฐ๋ ์จ๊ฒจ์ง ๋๋ฅผ ๊ฐ์งํ ์ ์์ต๋๋ค. ์ฌ์ฉ์๊ฐ ํ์ด์ง์์ ๋ฒ์ด๋๋ฉด ํ์ด์ง๊ฐ ์จ๊ฒจ์ง๋๋ค. ๋ค์ ๋์์ค๋ฉด ํ์ด์ง๊ฐ ๋ค์ ๋ณด์ด๊ฒ ๋ฉ๋๋ค. ์ด API๋ฅผ ์ฌ์ฉํ์ฌ ํ์ด์ง๊ฐ ์จ๊ฒจ์ง ํ ๋ค์ ๋ณด์ผ ๋ ์ญ๋ฐฉํฅ ๋ทฐ ์ ํ์ ํธ๋ฆฌ๊ฑฐํ ์ ์์ต๋๋ค.
์์ :
document.addEventListener('visibilitychange', () => {
if (document.visibilityState === 'visible') {
document.startViewTransition(() => {
// ์บ์๋ ๋ฐ์ดํฐ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์ด์ ์ํ๋ก ๋๋๋ฆฝ๋๋ค
revertToPreviousState();
});
}
});
์ด ์ ๊ทผ ๋ฐฉ์์ ํ์ด์ง๊ฐ ์จ๊ฒจ์ง๊ธฐ ์ ์ DOM์ ์ด์ ์ํ๋ฅผ ์บ์ฑํ๋ ๋ฐ ์์กดํฉ๋๋ค. ๊ทธ๋ฐ ๋ค์ revertToPreviousState()
ํจ์๋ ์ด ์บ์๋ ๋ฐ์ดํฐ๋ฅผ ์ฌ์ฉํ์ฌ ์ด์ ๋ทฐ๋ฅผ ๋ค์ ๋ง๋ค๊ณ ์ญ๋ฐฉํฅ ์ ํ์ ์์ํฉ๋๋ค. ์ด๋ History API ์ ๊ทผ ๋ฐฉ์๋ณด๋ค ๊ตฌํ์ด ๋ ๊ฐ๋จํ ์ ์์ง๋ง ์บ์๋ ๋ฐ์ดํฐ์ ์ ์คํ ๊ด๋ฆฌ๊ฐ ํ์ํฉ๋๋ค.
3. History API์ Session Storage ๊ฒฐํฉ
๋ ๋ณต์กํ ์๋๋ฆฌ์ค์ ๊ฒฝ์ฐ, ์ ๋๋ฉ์ด์ ๊ด๋ จ ๋ฐ์ดํฐ๋ฅผ ๋ณด์กดํ๊ธฐ ์ํด History API๋ฅผ ์ธ์ ์คํ ๋ฆฌ์ง์ ๊ฒฐํฉํด์ผ ํ ์๋ ์์ต๋๋ค. ์ธ์ ์คํ ๋ฆฌ์ง๋ฅผ ์ฌ์ฉํ๋ฉด ๋์ผํ ๋ธ๋ผ์ฐ์ ํญ ๋ด์์ ํ์ด์ง ํ์ ๊ฐ์ ์ง์๋๋ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ ์ ์์ต๋๋ค. ์ ๋๋ฉ์ด์ ์ํ(์: ํ์ฌ ํ๋ ์ ๋๋ ์งํ๋ฅ )๋ฅผ ์ธ์ ์คํ ๋ฆฌ์ง์ ์ ์ฅํ๊ณ ์ฌ์ฉ์๊ฐ ํ์ด์ง๋ก ๋ค์ ๋์์ฌ ๋ ์ด๋ฅผ ๊ฒ์ํ ์ ์์ต๋๋ค.
์์ :
// ํ์ด์ง๋ฅผ ๋ ๋๊ธฐ ์ :
sessionStorage.setItem('animationState', JSON.stringify(currentAnimationState));
// ํ์ด์ง ๋ก๋ ๋๋ popstate ์ด๋ฒคํธ ์:
const animationState = JSON.parse(sessionStorage.getItem('animationState'));
if (animationState) {
document.startViewTransition(() => {
// ์ ๋๋ฉ์ด์
์ํ๋ฅผ ๋ณต์ํ๊ณ ์ญ๋ฐฉํฅ ์ ํ์ ํธ๋ฆฌ๊ฑฐํฉ๋๋ค
restoreAnimationState(animationState);
});
}
์ด ์์ ๋ ํ์ด์ง๋ฅผ ๋ ๋๊ธฐ ์ ์ currentAnimationState
(์ ๋๋ฉ์ด์
์ ์งํ๋ฅ , ํ์ฌ ํ๋ ์ ๋๋ ๊ธฐํ ๊ด๋ จ ๋ฐ์ดํฐ์ ๋ํ ์ ๋ณด๋ฅผ ํฌํจํ ์ ์์)๋ฅผ ์ธ์
์คํ ๋ฆฌ์ง์ ์ ์ฅํฉ๋๋ค. ํ์ด์ง๊ฐ ๋ก๋๋๊ฑฐ๋ popstate
์ด๋ฒคํธ๊ฐ ํธ๋ฆฌ๊ฑฐ๋๋ฉด ์ธ์
์คํ ๋ฆฌ์ง์์ ์ ๋๋ฉ์ด์
์ํ๋ฅผ ๊ฒ์ํ์ฌ ์ ๋๋ฉ์ด์
์ ์ด์ ์ํ๋ก ๋ณต์ํ๋ ๋ฐ ์ฌ์ฉ๋ฉ๋๋ค.
4. ํ๋ ์์ํฌ ๋๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ฌ์ฉ
๋ง์ ํ๋ ์๋ฐ์คํฌ๋ฆฝํธ ํ๋ ์์ํฌ ๋ฐ ๋ผ์ด๋ธ๋ฌ๋ฆฌ(์: React, Vue.js, Angular)๋ ์ํ ๊ด๋ฆฌ ๋ฐ ํ์์ ์ฒ๋ฆฌํ๊ธฐ ์ํ ๋ด์ฅ ๋ฉ์ปค๋์ฆ์ ์ ๊ณตํฉ๋๋ค. ์ด๋ฌํ ํ๋ ์์ํฌ๋ ์ข ์ข History API์ ๋ณต์ก์ฑ์ ์ถ์ํํ๊ณ ์ํ ๋ฐ ์ ํ ๊ด๋ฆฌ๋ฅผ ์ํ ๊ณ ์์ค API๋ฅผ ์ ๊ณตํฉ๋๋ค. ํ๋ ์์ํฌ๋ฅผ ์ฌ์ฉํ ๋๋ ์ํ ์ง์์ฑ ๋ฐ ์ ๋๋ฉ์ด์ ๋ณต๊ตฌ๋ฅผ ์ํด ๋ด์ฅ๋ ๊ธฐ๋ฅ์ ํ์ฉํ๋ ๊ฒ์ ๊ณ ๋ คํ์ญ์์ค.
์๋ฅผ ๋ค์ด, React์์๋ Redux๋ Zustand์ ๊ฐ์ ์ํ ๊ด๋ฆฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ์ฌ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ํ๋ฅผ ์ ์ฅํ๊ณ ํ์ด์ง ํ์ ๊ฐ์ ์ด๋ฅผ ์ ์งํ ์ ์์ต๋๋ค. ๊ทธ๋ฐ ๋ค์ React Router๋ฅผ ์ฌ์ฉํ์ฌ ํ์์ ๊ด๋ฆฌํ๊ณ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ํ์ ๋ฐ๋ผ ๋ทฐ ์ ํ์ ํธ๋ฆฌ๊ฑฐํ ์ ์์ต๋๋ค.
์ํ ์ง์์ฑ ๊ตฌํ์ ์ํ ๋ชจ๋ฒ ์ฌ๋ก
- ์ ์ฅ๋๋ ๋ฐ์ดํฐ ์ ์ต์ํ: ์ด์ ์ํ๋ฅผ ์ฌํํ๋ ๋ฐ ํ์ํ ํ์ ๋ฐ์ดํฐ๋ง ์ ์ฅํ์ธ์. ๋๋์ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ๋ฉด ์ฑ๋ฅ์ ์ํฅ์ ๋ฏธ์น ์ ์์ต๋๋ค.
- ํจ์จ์ ์ธ ๋ฐ์ดํฐ ์ง๋ ฌํ ์ฌ์ฉ: ์ธ์
์คํ ๋ฆฌ์ง์ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ ๋
JSON.stringify()
์ ๊ฐ์ ํจ์จ์ ์ธ ์ง๋ ฌํ ๋ฐฉ๋ฒ์ ์ฌ์ฉํ์ฌ ์ ์ฅ ๊ณต๊ฐ ํฌ๊ธฐ๋ฅผ ์ต์ํํ์ธ์. - ์ฃ์ง ์ผ์ด์ค ์ฒ๋ฆฌ: ์ฌ์ฉ์๊ฐ ํ์ด์ง๋ฅผ ์ฒ์ ๋ฐฉ๋ฌธํ๋ ๊ฒฝ์ฐ(์ฆ, ์ด์ ์ํ๊ฐ ์๋ ๊ฒฝ์ฐ)์ ๊ฐ์ ์ฃ์ง ์ผ์ด์ค๋ฅผ ๊ณ ๋ คํ์ธ์.
- ์ฒ ์ ํ ํ ์คํธ: ๋ค์ํ ๋ธ๋ผ์ฐ์ ์ ์ฅ์น์์ ์ํ ์ง์์ฑ ๋ฐ ์ ๋๋ฉ์ด์ ๋ณต๊ตฌ ๋ฉ์ปค๋์ฆ์ ํ ์คํธํ์ธ์.
- ์ ๊ทผ์ฑ ๊ณ ๋ ค: ์ ํ์ด ์ฅ์ ๊ฐ ์๋ ์ฌ์ฉ์์๊ฒ ์ ๊ทผ ๊ฐ๋ฅํ์ง ํ์ธํ์ธ์. ์ ํ์ด ๋ฐฉํด๊ฐ ๋ ๊ฒฝ์ฐ ์ ํ๋ฆฌ์ผ์ด์ ์ ํ์ํ ์ ์๋ ๋์ฒด ๋ฐฉ๋ฒ์ ์ ๊ณตํ์ธ์.
์ฝ๋ ์์ : ์ฌ์ธต ๋ถ์
์ด์ ์์ ๋ฅผ ๋ ์์ธํ ์ฝ๋ ์ค๋ํซ์ผ๋ก ํ์ฅํด ๋ณด๊ฒ ์ต๋๋ค.
์์ 1: ์์ธ ์ํ๋ฅผ ํฌํจํ History API
// ์ด๊ธฐ ์ํ
let currentState = {
page: 'home',
data: {},
scrollPosition: 0 // ์์ : ์คํฌ๋กค ์์น ์ ์ฅ
};
function updateTheDOM(newState) {
// newState๋ฅผ ๊ธฐ๋ฐ์ผ๋ก DOM ์
๋ฐ์ดํธ (์ค์ ๋ก์ง์ผ๋ก ๋์ฒด)
console.log('DOM์ ๋ค์์ผ๋ก ์
๋ฐ์ดํธ:', newState);
document.getElementById('content').innerHTML = `ํ์๋ ํ์ด์ง: ${newState.page}
`;
window.scrollTo(0, newState.scrollPosition); // ์คํฌ๋กค ์์น ๋ณต์
}
function navigateTo(page) {
document.startViewTransition(() => {
// 1. DOM ์
๋ฐ์ดํธ
currentState = {
page: page,
data: {},
scrollPosition: 0 // ์คํฌ๋กค ๋ฆฌ์
๋๋ ์ ์ง
};
updateTheDOM(currentState);
// 2. ํ์คํ ๋ฆฌ์ ์ ์ํ ํธ์
history.pushState(currentState, null, '#' + page); // ๊ฐ๋จํ ๋ผ์ฐํ
์ ์ํด ํด์ ์ฌ์ฉ
});
}
window.addEventListener('popstate', (event) => {
document.startViewTransition(() => {
// 1. ์ด์ ์ํ๋ก ๋๋๋ฆฌ๊ธฐ
const state = event.state;
if (state) {
currentState = state;
updateTheDOM(currentState);
} else {
// ์ด๊ธฐ ํ์ด์ง ๋ก๋ ์ฒ๋ฆฌ (์์ง ์ํ ์์)
navigateTo('home'); // ๋๋ ๋ค๋ฅธ ๊ธฐ๋ณธ ์ํ
}
});
});
// ์ด๊ธฐ ๋ก๋: ๋ค๋ก ๊ฐ๊ธฐ ๋ฒํผ ๋ฌธ์ ๋ฐฉ์ง๋ฅผ ์ํด ์ด๊ธฐ ์ํ ๊ต์ฒด
history.replaceState(currentState, null, '#home');
// ์ฌ์ฉ ์์ :
document.getElementById('link-about').addEventListener('click', (e) => {
e.preventDefault();
navigateTo('about');
});
document.getElementById('link-contact').addEventListener('click', (e) => {
e.preventDefault();
navigateTo('contact');
});
์ค๋ช :
currentState
๊ฐ์ฒด๋ ์ด์ ํ์ฌ ํ์ด์ง, ์์์ ๋ฐ์ดํฐ, ์คํฌ๋กค ์์น์ ๊ฐ์ ๋ ๊ตฌ์ฒด์ ์ธ ์ ๋ณด๋ฅผ ๋ด๊ณ ์์ต๋๋ค. ์ด๋ฅผ ํตํด ๋ ์์ ํ ์ํ ๋ณต์์ด ๊ฐ๋ฅํฉ๋๋ค.updateTheDOM
ํจ์๋ DOM ์ ๋ฐ์ดํธ๋ฅผ ์๋ฎฌ๋ ์ด์ ํฉ๋๋ค. ํ๋ ์ด์คํ๋ ๋ก์ง์ ์ค์ DOM ์กฐ์ ์ฝ๋๋ก ๋ฐ๊พธ์ธ์. ์ค์ํ๊ฒ๋, ์คํฌ๋กค ์์น๋ ๋ณต์ํฉ๋๋ค.- ์ด๊ธฐ ๋ก๋ ์
history.replaceState
๋ ๋ค๋ก ๊ฐ๊ธฐ ๋ฒํผ์ด ์ด๊ธฐ ๋ก๋ ์ ๋น ํ์ด์ง๋ก ์ฆ์ ๋์๊ฐ๋ ๊ฒ์ ๋ฐฉ์งํ๋ ๋ฐ ์ค์ํฉ๋๋ค. - ์ด ์์ ๋ ๊ฐ๋จํจ์ ์ํด ํด์ ๊ธฐ๋ฐ ๋ผ์ฐํ ์ ์ฌ์ฉํฉ๋๋ค. ์ค์ ์ ํ๋ฆฌ์ผ์ด์ ์์๋ ๋ ๊ฐ๋ ฅํ ๋ผ์ฐํ ๋ฉ์ปค๋์ฆ์ ์ฌ์ฉํ ๊ฒ์ ๋๋ค.
์์ 2: ์บ์ฑ์ ์ฌ์ฉํ Page Visibility API
let cachedDOM = null;
function captureDOM() {
// DOM์ ๊ด๋ จ ๋ถ๋ถ ๋ณต์
const contentElement = document.getElementById('content');
cachedDOM = contentElement.cloneNode(true); // ๊น์ ๋ณต์
}
function restoreDOM() {
if (cachedDOM) {
const contentElement = document.getElementById('content');
contentElement.parentNode.replaceChild(cachedDOM, contentElement); // ์บ์๋ ๋ฒ์ ์ผ๋ก ๊ต์ฒด
cachedDOM = null; // ์บ์ ๋น์ฐ๊ธฐ
} else {
console.warn('๋ณต์ํ ์บ์๋ DOM์ด ์์ต๋๋ค.');
}
}
document.addEventListener('visibilitychange', () => {
if (document.visibilityState === 'hidden') {
captureDOM(); // ์จ๊ฒจ์ง๊ธฐ ์ ์ DOM ์บก์ฒ
}
if (document.visibilityState === 'visible') {
document.startViewTransition(() => {
restoreDOM(); // ๋ณด์ด๊ฒ ๋ ๋ DOM ๋ณต์
});
}
});
// ์ฌ์ฉ ์์ (ํ์ ์๋ฎฌ๋ ์ด์
)
function navigateAway() {
document.getElementById('content').innerHTML = 'ํ์ด์ง๋ฅผ ๋ ๋๋ ์ค...
';
// ์ง์ฐ ์๋ฎฌ๋ ์ด์
(์: AJAX ์์ฒญ)
setTimeout(() => {
//์ค์ ์ฑ์์๋ ์ฌ๊ธฐ์์ ๋ค๋ฅธ ํ์ด์ง๋ก ์ด๋ํ ์ ์์ต๋๋ค.
console.log("ํ์ด์ง ๋ ๋๊ธฐ ์๋ฎฌ๋ ์ด์
์๋ฃ.");
}, 1000);
}
document.getElementById('navigate').addEventListener('click', navigateAway);
์ค๋ช :
- ์ด ์์ ๋ DOM ๋ณต์ ๋ฐ ๋ณต์์ ์ค์ ์ ๋ก๋๋ค. ์ด๋ ๋จ์ํ๋ ์ ๊ทผ ๋ฐฉ์์ด๋ฉฐ, ํนํ ๋ณต์กํ SPA์ ๊ฐ์ ๋ชจ๋ ์๋๋ฆฌ์ค์ ์ ํฉํ์ง ์์ ์ ์์ต๋๋ค.
captureDOM
ํจ์๋#content
์์๋ฅผ ๋ณต์ ํฉ๋๋ค. ๋ชจ๋ ์์ ์์์ ๊ทธ ์์ฑ์ ์บก์ฒํ๊ธฐ ์ํด ๊น์ ๋ณต์ ๊ฐ ์ค์ํฉ๋๋ค.restoreDOM
ํจ์๋ ํ์ฌ#content
๋ฅผ ์บ์๋ ๋ฒ์ ์ผ๋ก ๊ต์ฒดํฉ๋๋ค.navigateAway
ํจ์๋ ํ์์ ์๋ฎฌ๋ ์ด์ ํฉ๋๋ค (์ผ๋ฐ์ ์ผ๋ก ์ค์ ํ์ ๋ก์ง์ผ๋ก ๋์ฒดํฉ๋๋ค).
๊ณ ๊ธ ๊ณ ๋ ค ์ฌํญ
1. ๊ต์ฐจ ์ถ์ฒ ์ ํ(Cross-Origin Transitions)
View Transitions๋ ์ฃผ๋ก ๋์ผํ ์ถ์ฒ ๋ด์ ์ ํ์ ์ํด ์ค๊ณ๋์์ต๋๋ค. ๊ต์ฐจ ์ถ์ฒ ์ ํ(์: ๋ค๋ฅธ ๋๋ฉ์ธ ๊ฐ์ ์ ํ)์ ์ผ๋ฐ์ ์ผ๋ก ๋ ๋ณต์กํ๋ฉฐ iframe ์ฌ์ฉ์ด๋ ์๋ฒ ์ธก ๋ ๋๋ง๊ณผ ๊ฐ์ ๋ค๋ฅธ ์ ๊ทผ ๋ฐฉ์์ด ํ์ํ ์ ์์ต๋๋ค.
2. ์ฑ๋ฅ ์ต์ ํ
View Transitions๋ ์ ์คํ๊ฒ ๊ตฌํํ์ง ์์ผ๋ฉด ์ฑ๋ฅ์ ์ํฅ์ ๋ฏธ์น ์ ์์ต๋๋ค. ๋ค์์ ํตํด ์ ํ์ ์ต์ ํํ์ธ์:
- ์ ํ๋๋ DOM ์์์ ํฌ๊ธฐ ์ต์ํ: ์์ DOM ์์๋ ๋ ๋น ๋ฅธ ์ ํ์ ์๋ฏธํฉ๋๋ค.
- ํ๋์จ์ด ๊ฐ์ ์ฌ์ฉ: ํ๋์จ์ด ๊ฐ์์ ํธ๋ฆฌ๊ฑฐํ๋ CSS ์์ฑ(์:
transform: translate3d(0, 0, 0);
)์ ์ฌ์ฉํ์ธ์. - ์ ํ ๋๋ฐ์ด์ฑ: ์ฌ์ฉ์๊ฐ ํ์ด์ง ๊ฐ์ ๋น ๋ฅด๊ฒ ํ์ํ ๋ ๊ณผ๋ํ ์ ํ์ ํผํ๊ธฐ ์ํด ์ ํ ํธ๋ฆฌ๊ฑฐ ๋ก์ง์ ๋๋ฐ์ด์คํ์ธ์.
3. ์ ๊ทผ์ฑ
View Transitions๊ฐ ์ฅ์ ๊ฐ ์๋ ์ฌ์ฉ์์๊ฒ ์ ๊ทผ ๊ฐ๋ฅํ์ง ํ์ธํ์ธ์. ์ ํ์ด ๋ฐฉํด๊ฐ ๋ ๊ฒฝ์ฐ ์ ํ๋ฆฌ์ผ์ด์ ์ ํ์ํ ์ ์๋ ๋์ฒด ๋ฐฉ๋ฒ์ ์ ๊ณตํ์ธ์. ์คํฌ๋ฆฐ ๋ฆฌ๋์ ์ถ๊ฐ์ ์ธ ๋ฌธ๋งฅ์ ์ ๊ณตํ๊ธฐ ์ํด ARIA ์์ฑ์ ์ฌ์ฉํ๋ ๊ฒ์ ๊ณ ๋ คํ์ธ์.
์ค์ ์์ ๋ฐ ์ฌ์ฉ ์ฌ๋ก
- ์ ์์๊ฑฐ๋ ์ ํ ๊ฐค๋ฌ๋ฆฌ: ์ ํ ์ด๋ฏธ์ง ๊ฐ์ ๋ถ๋๋ฌ์ด ์ ํ.
- ๋ด์ค ๊ธฐ์ฌ: ๊ธฐ์ฌ์ ๋ค๋ฅธ ์น์ ๊ฐ์ ๋งค๋๋ฌ์ด ํ์.
- ์ธํฐ๋ํฐ๋ธ ๋์๋ณด๋: ๋ค๋ฅธ ๋ฐ์ดํฐ ์๊ฐํ ๊ฐ์ ์ ์ฐํ ์ ํ.
- ์น ์ฑ์ ๋ชจ๋ฐ์ผ ์ฑ๊ณผ ๊ฐ์ ํ์: ๋ธ๋ผ์ฐ์ ๋ด์์ ๋ค์ดํฐ๋ธ ์ฑ ์ ํ ์๋ฎฌ๋ ์ด์ .
๊ฒฐ๋ก
CSS View Transitions๋ ์ํ ์ง์์ฑ ๋ฐ ์ ๋๋ฉ์ด์ ๋ณต๊ตฌ ๊ธฐ์ ๊ณผ ๊ฒฐํฉํ์ฌ ์น ์ ํ๋ฆฌ์ผ์ด์ ์ ์ฌ์ฉ์ ๊ฒฝํ์ ํฅ์์ํค๋ ๊ฐ๋ ฅํ ๋ฐฉ๋ฒ์ ์ ๊ณตํฉ๋๋ค. ๋ธ๋ผ์ฐ์ ์ ํ์คํ ๋ฆฌ๋ฅผ ์ ์คํ๊ฒ ๊ด๋ฆฌํ๊ณ Page Visibility API์ ๊ฐ์ API๋ฅผ ํ์ฉํจ์ผ๋ก์จ ๊ฐ๋ฐ์๋ ์น ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ ๋ฐ์์ ์ด๊ณ ๋งค๋ ฅ์ ์ผ๋ก ๋๋ผ๊ฒ ํ๋ ๋งค๋๋ฝ๊ณ ์๊ฐ์ ์ผ๋ก ๋งค๋ ฅ์ ์ธ ์ ํ์ ๋ง๋ค ์ ์์ต๋๋ค. View Transition API๊ฐ ์ฑ์ํ๊ณ ๋ ๋๋ฆฌ ์ง์๋จ์ ๋ฐ๋ผ ์์ฌํ ์ฌ์ง ์์ด ํ๋ ์น ๊ฐ๋ฐ์ ํ์ ๋๊ตฌ๊ฐ ๋ ๊ฒ์ ๋๋ค.