프로젝트를 위해 JS - SPA에 대해 공부했다.
기존에는 페이지를 여러개 만들어서 링크로 이동하는 식이었다면,
SPA는, 하나의 페이지에서 원하는 변경 부분만 데이터를 바꿔끼우는 식이다.
MPA보다 빠릿빠릿해보이고, 엄청 부드러워 보이는 효과가 있다.
하지만, 한 번에 모든 파일을 서버로부터 받아오기 때문에 초기에 데이터를 다운받는 시간이 있다.
요즘 인터넷이 워낙 빨라서 그걸 느낄 사람은 몇 없을 것 같지만..
SPA
아래에 나올 사진들은 SPA를 이해하기 위해 만들어 본 페이지다.
로그인 버튼과 로그아웃 버튼을 눌렀을 때, 왼쪽 부분만 바뀌도록 만들었다.
위 사진은 로그인을 하지 않았을 경우, '로그인을 하세요!'와 로그인 버튼이 보인다.
위 사진은 로그인을 했을 경우, '로그인 됐을 때 페이지!'와 로그아웃 버튼이 보인다.
로그아웃 버튼을 누르면 중간, 오른쪽 부분은 그대로 있고 왼쪽 부분만 바뀐다.
저 부분만 바뀐다고 생각할 수도 있지만, 사실 전체 페이지를 밀어버린(?) 후,
미리 서버로부터 받은 페이지들의 div태그속 text를 가지고 다시 뿌려준 것이다.
요약하자면,
첫째, 브라우저가 index 파일을 로드한다. (앞으로 브라우저는 index 파일만 로드한다)
둘째, 바꿔 넣고 싶은 부분의 데이터(ex. div태그의 text)를 index페이지의 정해진 태그에 삽입한다.
셋째, 브라우저가 바뀐 index 파일을 다시 로드한다.
로그인 버튼과 로그아웃 버튼을 누르면 해시url이 바뀌는데,
해시url이 바뀌면 감지하는 이벤트 리스너를 통해 화면에 뿌려주는 함수를 실행하게 된다.
아래의 코드가 위 설명에 해당하는 코드다.
const handleLocation = async () => {
let path = window.location.hash.replace("#", ""); //#about -> about
const mainpage = await fetch("/pages/home.html").then((data) => data.text());
const logoutpage = await fetch("/pages/logoutpage.html").then((data) =>
data.text()
);
const loginpage = await fetch("/pages/loginpage.html").then((data) =>
data.text()
);
const newspage = await fetch("/pages/newspage.html").then((data) =>
data.text()
);
if (path == "login") {
document.getElementById("my-page").innerHTML = loginpage;
document.getElementById("main-page").innerHTML = mainpage;
document.getElementById("news-page").innerHTML = newspage;
} else {
document.getElementById("my-page").innerHTML = logoutpage;
document.getElementById("main-page").innerHTML = mainpage;
document.getElementById("news-page").innerHTML = newspage;
}
};
// hash url 변경 시 처리
window.addEventListener("hashchange", handleLocation);
// 첫 랜딩 또는 새로고침 시 처리
document.addEventListener("DOMContentLoaded", handleLocation);
맨 아래에 이벤트 리스너들이 있다.
두 리스너들 모두 handleLocation이라는 함수를 실행시킨다.
그 함수는 async가 붙고, 안에 있는 메서드에는 await가 붙는다. 순서를 보장 받기 위한 조치다.
비동기방식은 데이터를 받아오는 동안 다른 동작을 할 수 있기 때문에 예상과 다른 딴 짓을 할 수 있기 때문이다.
fetch의 괄호속에는 데이터를 가져올 경로를 적어주고, 그 데이터는 then의 괄호 속 data에 담기고 text()로 바꿔서 가져온다.
조건문의 path(해시url)와 login이 같다면 loginpage.html을 my-page라는 아이디를 가진 태그에 넣고,
그게 아니라면 logoutpage.html을 넣어서 페이지를 로드한다.
만약 버튼을 눌러서 url을 바꾸거나, 다른 행위로 url이 바뀐다면 이벤트리스너가 감지하여 위 함수를 다시 실행시킬 것이고, 조건에 맞는 데이터를 가져와서 페이지를 보여줄 것이다.