영화 검색 사이트의 검색페이지와 상세페이지를 SPA로 구현했다. 그 과정에서 알게된 것들을 기록했다.
검색해보니 위의 방법이 있다는 것을 알게 됐고, 이 중 pjax로 SPA를 구현해보았다.
export const handlePushstate = (element, path) => {
element.addEventListener('click', (e) => {
e.preventDefault();
window.history.pushState('', '', path);
const urlChange = new CustomEvent('urlchange', {
detail: { href: path },
});
document.dispatchEvent(urlChange);
});
};
요소에 클릭 이벤트리스너를 등록한다. 이벤트리스너 함수 내에 주소창의 URL을 변경하고 URL을 history entry로 추가하지만 서버로 HTTP 요청을 하지는 않는 pushState
를 추가한다. URL 주소가 변경되는 것을 알리고 감지할 수 있는 커스텀 이벤트를 만들고, 생성한 커스텀 이벤트를 dispatch() 메서드를 통해 document 객체에 발송한다.
<header role="navigation">
<h1 class="logo">
<a href="/">Moovie</a>
</h1>
</header>
const logoEl = document.querySelector('.logo');
handlePushstate(logoEl, '/');
헤더의 로고 클릭시 검색할 수 있는 홈화면으로 이동해야 한다. handlePushstate
함수로 url 을 변경한다.
movieLiEl.innerHTML = `
<a class='info' href="/detail/${movie.imdbID}" movieId=${movie.imdbID}>
<p>${movieTitleEl}</p>
<p>${movieYearEl}</p>
</a>
`;
const movieIdEl = document.querySelector('.info').getAttribute('movieId');
handlePushstate(movieLiEl, `/detail/?id=${movieIdEl}`);
영화검색결과 하나의 영화 리스트 요소 클릭시, 영화 상세페이지로 이동해야한다. handlePushstate
함수로 url 을 변경한다.
import search from '/src/pages/Search/index';
import detail from '/src/pages/Detail/index';
search();
const render = async () => {
let url = window.location.href;
let path = new URL(url).pathname;
const searchParams = new URL(url).searchParams;
const queryString = searchParams.get('id');
switch (path) {
case '/':
search();
break;
case '/detail/':
await detail(queryString);
break;
default:
}
};
document.addEventListener('urlchange', () => {
render();
});
window.addEventListener('popstate', () => {
render();
});
search()
함수로 검색페이지를 렌더링한다.render()
함수를 실행한다.render()
함수에서는 url 정보를 바탕으로 그에 맞는 페이지를 렌더링한다.popstate 이벤트
를 추가하여, 세션기록변경에 따라 페이지가 조건에 맞게 렌더링되도록 한다.영화검색사이트 프로젝트에서 제일 어려웠던 부분이었다. 그래도 혼자 열심히 찾아보고 고민해낸 끝에, 구현해낸 것이 너무 뿌듯하다! 전체 코드는 깃허브 레포지토리에서 볼 수 있다.