[JavaScript] SPA

윤지·2024년 11월 8일

JavaScript

목록 보기
29/30
post-thumbnail

자바스크립트로 구현하는 싱글 페이지 애플리케이션(SPA)

1. SPA

SPA(Single Page Application): 초기 로딩 후 페이지 전체를 새로고침하지 않고 동적으로 콘텐츠를 갱신하는 웹 애플리케이션

장점: 빠른 응답성과 효율적인 네트워크 사용으로 매끄러운 사용자 경험 제공

SPA는 필요한 데이터만 받아와 화면을 갱신하며, 주로 자바스크립트와 history API를 활용하여 구현

2. 자바스크립트를 사용한 SPA 구현 방법

SPA 구현 시 자바스크립트의 history API를 활용하여 브라우저 히스토리 제어 가능

history.pushState()popstate 이벤트는 사용자의 페이지 이동 시 URL 동적 변경 및 뒤로 가기, 앞으로 가기 기능 구현에 중요한 역할을 함

History API

  • History API는 브라우저 히스토리 제어를 위한 자바스크립트 기능 제공
  • history.pushState() 메서드로 SPA에서 URL과 상태를 동적 변경. 주소 표시줄은 변경되지만 페이지는 새로고침되지 않아 동적 콘텐츠 갱신과 URL 업데이트를 동시에 처리 가능

history.pushState(state, title, url) 메서드의 주요 매개변수

  • state: 새로 저장할 히스토리 상태를 나타내는 객체. 페이지 전환 시 필요한 데이터 포함 가능
  • title: 새 히스토리 항목의 제목. 브라우저에서 무시되어 빈 문자열(””)로 처리됨
  • url: 새로운 히스토리 항목의 URL 지정. 상대 경로나 절대 경로를 사용하여 현재 페이지의 URL 변경 가능

History API를 이용한 SPA 상태 관리

history.pushState()를 이용해 SPA에서 상태 추가 및 URL 변경 예시:

// 새 상태를 히스토리에 추가
window.history.pushState({page: 2}, "", "/page2");

Popstate 이벤트를 통한 상태 복원

window.addEventListener('popstate', function(event) {
  const page = event.state?.page || 'home';
  updateContent(page);
});

function updateContent(page) {
  document.getElementById('content').innerHTML = pages[page];
}

사용자의 뒤로가기 클릭 시, popstate 이벤트 핸들러에서 event.state를 통해 객체 접근 가능

event.state

// 뒤로가기, 앞으로 가기 이벤트 처리
window.addEventListener('popstate', function(event) {
  console.dir(event.state) //{page: 2}
});

console.dir(event)popstate 이벤트 객체의 상세 정보 확인 가능

객체 내 state 속성은 pushState() 또는 replaceState() 메서드로 전달된 상태 객체임

상태 객체 활용으로 페이지 전환 시 필요 데이터 저장 및 복원 가능, SPA에서 더 풍부한 네비게이션 경험 제공 가능함

3. 예제: 자바스크립트로 SPA 구현하기

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>SPA Example</title>
</head>
<body>
    <ul>
        <li><a href="/" data-url="home">Home</a></li>
        <li><a href="/about" data-url="about">About</a></li>
        <li><a href="/contact" data-url="contact">Contact</a></li>
    </ul>
    <div id="page">Home 페이지입니다.</div>
    <script>
        // SPA 페이지 콘텐츠 정의
        const pages = {
            home: "Home 페이지입니다.",
            about: "About 페이지입니다.",
            contact: "Contact 페이지입니다. <input text='text' placeholder='연락처 입력 하세요' />",
        };

        // 각 링크에 이벤트 핸들러 추가
        const aEls = document.querySelectorAll("a");
        aEls.forEach((aEl) =>
            aEl.addEventListener("click", function (e) {
                e.preventDefault(); // 링크의 기본 동작 방지
                const page = e.currentTarget.dataset.url; 
                // 클릭한 링크의 페이지 정보 가져오기
                history.pushState({ page: page }, "", `/${page}`);
                // URL과 상태를 히스토리에 추가
                document.getElementById("page").innerHTML = pages[page];
                // 페이지 콘텐츠 업데이트
            })
        );

        // 뒤로가기, 앞으로 가기 이벤트 처리
        window.addEventListener("popstate", function (event) {
            const page = event.state?.page || "home"; 
            // 상태가 없으면 기본 페이지로 설정(예외처리)
            document.getElementById("page").innerHTML = pages[page];
            // 이전 상태에 맞는 콘텐츠 렌더링
        });
    </script>
</body>
</html>

코드 설명

  1. 페이지 콘텐츠 설정: pages 객체에 페이지별로 표시할 콘텐츠 정의. 각 페이지에 맞는 텍스트나 HTML을 미리 설정하여 링크 클릭 시 innerHTML을 이용해 해당 내용 표시 가능
  2. 링크 이벤트 핸들러 설정: 모든 링크에 click 이벤트 핸들러 추가하여 클릭 시 다음 작업 수행
    • e.preventDefault(): 페이지 이동을 막고 자바스크립트로 전환 처리
    • e.currentTarget.dataset.url: 클릭한 링크의 data-url 속성에서 페이지 정보 가져옴
    • history.pushState(): URL 변경 및 새로운 상태를 브라우저의 히스토리에 저장
    • document.getElementById("page").innerHTML: pages 객체를 이용해 page div의 콘텐츠 업데이트
  3. 뒤로가기, 앞으로 가기 이벤트 처리: popstate 이벤트는 사용자가 브라우저의 뒤로가기나 앞으로가기를 누를 때 발생
    • event.state: pushState를 통해 저장된 상태 가져옴. 페이지 이동 시 state 객체에 저장된 정보를 활용하여 콘텐츠 복원 가능
    • document.getElementById("page").innerHTML: 가져온 state에 따라 page div의 콘텐츠 업데이트

4. History API 메서드

  • history.back(): 현재 URL에서 한 단계 뒤로 이동
  • history.forward(): 현재 URL에서 한 단계 앞으로 이동
  • history.go(n): n이 양수면 앞으로, 음수면 뒤로 이동. 예: history.go(-2)는 두 단계 뒤로 이동

출처: 수코딩

profile
프론트엔드 공부 기록 아카이빙🍁

0개의 댓글