🚀 들어가며
프론트엔드 데브코스 강의를 듣는데 history API 파트가 나왔다. 마음이 너무 급했던 탓일까, 빠르게 이해하려고 보니 이해가 되지 않았다. 나에게 SPA는 생소한 개념이었고, SPA를 모르다보니 SPA를 위한 history API도 이해하기 쉽지 않았다. 잠시 급한 마음을 다스리고, SPA부터 차근차근 공부하기 시작했다.
✅ SPA(Single Page Application)
과거에는 웹 페이지를 렌더링할 때 서버에 렌더링에 필요한 리소스를 요청하고, 받아온 리소스를 클라이언트에서 렌더링했다. 즉, 렌더링이 필요한 특정 부분 이외의 불필요한 부분까지 같이 렌더링해야만 했다.
하지만 SPA가 등장하고 나서부터는 특정 부분의 렌더링을 위해 서버에서 필요한 데이터만 전달받고 렌더링할 수 있게 되었다. SPA를 통해 우리는 훨씬 개선된 UX를 제공받게 되었다.
▪︎ SPA의 장단점
추가 예정
✅ History API
SPA 는 웹 페이지에 최초 한 번 페이지 전체를 렌더링하고, 이후 부터는 특정한 부분만 Ajax 를 통해 데이터를 받아서 렌더링을 하는 방식이다. History API 는 이러한 SPA 방식 중 하나로, URL 주소를 인위적으로 바꾸고(이 때, 실제로 이동시키진 않는다.) history.state 에 담아둔 정보로 Ajax 요청을 보내 화면을 갱신한다. 즉, 서버로 페이지 요청을 하지 않고, history.state에 담아둔 정보로 Ajax 요청을 보내서 화면을 갱신하는 방식으로 라우팅을 구현한다.
▪︎ history.pushState(data, title, path)
브라우저 콘솔에 history.pushState(data, title, path) 을 입력하면 URL 주소가 변경되는 것을 볼 수 있다. 이 때, 실제로 페이지가 이동되는 것은 아니다. 이 점을 이용해 SPA 를 구현할 수 있다. URL 주소를 변경시키고, 해당 URL의 pathname 만 알아낸 후, pathname 에 해당하는 페이지를 렌더링하는 코드를 작성하면 된다.
▪︎ history.replaceState(data, title, path)
앞서 설명했던 pushState 메서드는 history에 인수로 받은 path를 활용하여 URL 주소를 변경시키고 history 에 추가하는 메서드이다. 이 때, 이전의 history 와는 무관하다. 스택 자료구조를 생각하면 편하다.
반면, replaceState 메서드는 이전의 history 를 대체시킨다. 즉, 이전의 history 가 사라지고 새로운 history 가 추가되는 것처럼 보이게 된다. 실제로 pushState 메서드를 호출하고 나면 뒤로가기가 가능한 반면에 replaceState 메서드는 이전의 history 에 덮여씌여지는 바람에 뒤로가기가 불가능해진다.
▪︎ window.addEventListener('popstate', () => { route() })
뒤로가기에 대한 이벤트는 이벤트 핸들러로 이후의 함수를 실행시킬 수 있다. 예제 코드에서는 뒤로가기 이벤트 발생 시 다시 라우트 함수를 실행시켜 페이지가 다시 렌더링될 수 있게 만드는 코드이다.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="container"></div>
<a class="LinkItem" href="/product-list">product list</a>
<a class="LinkItem" href="/article-list">article list</a>
<script>
function route() {
const { pathname } = location; // 현재 pathname만 뽑아냄
const $container = document.querySelector('#container');
// 현재 pathname에 따라 innerHTML로 다른 화면 렌더링
if (pathname === '/') {
$container.innerHTML = '<h1>Home</h1>';
} else if (pathname === '/product-list') {
$container.innerHTML = '<h1>상품 목록</h1>';
} else if (pathname === '/article-list') {
$container.innerHTML = '<h1>게시글 목록</h1>';
}
}
route();
// 버튼에 클릭이 발생했을 경우
window.addEventListener('click', e => {
// 그 버튼의 class="LinkItem" 이라면
if (e.target.className === 'LinkItem') {
e.preventDefault();
// href 링크의 path만 뽑는다.
const { href } = e.target;
const path = href.replace(window.location.origin, '');
// 주소만 변경
history.pushState(null, null, path);
// 라우트
route();
}
})
// 뒤로가기 이벤트 발생시에 route()
window.addEventListener('popstate', () => {
route();
})
</script>
</body>
</html>
🛸 마치며
SPA, History API 는 UX 에 영향을 미치고, 프론트엔드 개발에 있어서 이러한 UX 관점의 고민은 프론트엔드 개발 역량에 차별성을 갖게 해주는 중요한 요소라고 생각한다. 앞으로 프로젝트를 진행하면서 렌더링의 효율성이나, 사용자에게 좋은 UX 을 제공하기 위해 계속해서 고민하고, 발전시켜 나아가야겠다.
'프로그래머스 데브코스' 카테고리의 다른 글
[개인 프로젝트 회고] Vanilla JS 로 노션 클로닝하기 (1) | 2023.10.28 |
---|---|
[데브코스] 성장 중.. 과제 수행, 첫 PR, 코드리뷰 후기 (2) | 2023.10.23 |
[JavaScript] 인프런 코어 자바스크립트 수강후기 (0) | 2023.10.15 |
[JavaScript] Map 과 Set (0) | 2023.10.13 |
[JavaScript] JavaScript의 10가지 코드 트릭 (0) | 2023.10.03 |