자바스크립트로 URL 라우팅을 구현하려고 한다. 바닐라 자바스크립트를 사용중이고 클라이언트 단 라우팅을 지원하는 라이브러리를 사용할 수 없기 때문에 자바스크립트의 Histroy API 를 사용하였다.
로그인 버튼이나 회원가입 버튼, 홈 버튼 등을 클릭할 때 URL를 변경시키고 동시에 UI도 변경시킨다.
이 navigate() 함수는 상태 객체를 인자로 받고, 상태 객체 안에 담겨있는 url 속성을 읽어서 url 에 맞는 UI를 화면에 보여준다. 따라서 이 함수를 호출하면 HTML에서 페이지의 내용이 바뀐다.
/**
* 주어진 상태에 따라 해당 URL에 맞는 뷰를 표시.
* @param {Object} state - 상태 객체.
*/
function navigate(state) {
const { url } = state;
const views = {
chatting: document.querySelector("#chattingView"),
login: document.querySelector("#loginView"),
};
switch (url) {
case ROUTES.HOME:
updateView(views, views.chatting);
break;
case ROUTES.LOGIN:
updateView(views, views.login);
break;
default:
break;
}
}
/**
* 업데이트할 뷰를 표시하고 다른 뷰를 숨긴다.
* @param {Object} views - 모든 뷰를 담고 있는 객체.
* @param {HTMLElement} viewToShow - 표시할 뷰의 DOM 요소.
*/
function updateView(views, viewToShow) {
Object.values(views).forEach((view) => view.classList.add("hidden"));
viewToShow.classList.remove("hidden");
}
이제 헤더 버튼에 클릭 이벤트 핸들러를 설정한다.
사용자가 각 버튼을 클릭하면 브라우저의 주소 표시줄의 URL이 바뀔 수 있도록 history.pushState() 메서드를 호출한다. 첫 번째 인자에는 경로 정보가 담겨있는 상태 객체를 넘기고, 세 번째 인자로는 브라우저의 주소 표시줄에 표시할 경로를 문자열로 넘김니다. 마지막으로 위에서 작성한 navigate() 함수에 동일한 상태 객체를 넘겨서 페이지 내용이 바뀌게한다.
/**
* 주어진 URL로 브라우저의 히스토리 상태를 업데이트 및 해당 상태로 navigate.
* @param {string} url - 새로 업데이트할 대상 URL
*/
export function updateRoute(url) {
const state = { url };
if (url === window.location.pathname) {
history.replaceState(state, "", url);
} else {
history.pushState(state, "", url);
}
navigate(state);
}
// 핸들러 등록
$headerTitle.addEventListener("click", () => updateRoute(ROUTES.HOME));
이 때, 동일한 버튼을 연속적으로 클릭하면 동일한 history가 history stack 에 쌓이기 때문에 이를 방지하기 위해 replaceState() 메서드를 사용한다.
여기까지만 하면 URL 변경에 따라 UI가 적절하게 변경된다. 하지만 ‘뒤로가기’ 또는 ‘앞으로 가기’를 클릭하면 주소표시창에 URL만 변경될 뿐 페이지의 UI는 그대로다.
이 문제를 해결하기 위해 윈도우에서 발생하는 popstate 이벤트를 감지해서 라우팅 처리해준다. 위에서 pushState() 와 replaceState() 메서드의 첫 번째 인자로 상태 객체를 넘겨주었기 때문에, 해당 페이지로 뒤로 가기나 앞으로 가기가 되면, 이벤트 핸들러에 매개 변수로 해당 상태 객체가 넘어오게 된다. 따라서 이 상태 객체를 그대로 navigate() 함수에 인자로 넘겨준다.
/**
* popstate 이벤트가 발생할 때 호출되어, 이벤트 상태를 가지고 navigate 한다.
* @param {PopStateEvent} event - popstate 이벤트 객체.
*/
function popStateHandler(event) {
const { state } = event;
navigate(state);
}
window.addEventListener("popstate", popStateHandler);

해당 코드 깃허브 주소 https://github.com/lee-yun-pyo/Login-Practice