ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Vanilla Javascript로 SPA 만들어보기
    Javascript 2023. 6. 23. 00:47

     

    🔔 서론

    어느덧 프로그래머스 데브코스 교육 4주차가 지나가고 있다. 생각했던것보다 깊은 내용과 어렵고 생소한 내용에 허덕이고 있지만, 잘 헤쳐나가는 것이 중요하다.

    이번 포스팅은 데브코스의 내용중 history api의 사용 방법과 이를 활용해 프레임워크 없이 Vanilla Javascript로만 SPA(Single Page Application)를 만들어 보는 것에 대한 포스팅이다. 과거 어느 한 블로그의 글에서 "신입 개발자나 인턴에게 프레임워크 없이 Vanilla Js로만 SPA를 만들어 보라고 과제를 주면 어떻게 해야하는지 모르는 사람들이 간혹 있어 아쉬웠다" 라는 포스팅을 본 적이 있다. 그 글에는 왜 Vanilla Js로 SPA를 만들어 볼 줄 알아야 하는지에 대한 이유는 서술되어 있지 않았고, 해당 이유를 검색을 해보아도 딱히 별다른 내용들이 나오지 않아 그냥 '프레임워크로 만든 SPA의 동작방식을 이해하기 위해서 먼저 Vanilla Js로 만들어 봐야 하나보다' 하고 혼자 넘겨짚었었다. 해당 포스팅의 글쓴이가 생각하는 바가 사실인지 아닌지를 떠나서 근본적인 궁금증을 해소하지 못하고 넘어간 것에 대해 굉장히 아쉬웠던 경험이었다.

    결국 또 다시 '꼭 Vanilla Js로 SPA를 만들어봐야 하는 이유가 따로 있을까?' 라는 궁금증을 직면하게 됐고, 검색을 해보았지만 원하는 대답을 얻을 수 없었기에 이번에는 chatGPT에게 물어보았다.

    요약하자면, 프레임워크 없이 바닐라 JavaScript로 SPA를 개발하는 경험은 기본 원리 이해, 유연성과 커스터마이징, 프레임워크 종속성 회피, 다양한 스킬셋 확보, 작은 규모 프로젝트에 적합성 등의 이점을 제공하여 개발자로서의 역량을 향상시킬 수 있기에 필요하다 라는 chatGPT 선생님의 입장이었다.

    뭔가 가볍게 접근하려고 했는데 되게 중요한 내용이 되야할 것 같아져 버렸는데,

    그래도 가볍게 쓸 예정이니 아무튼 시작해보자.

     

    📌 history api

     

    우선 브라우저에서 페이지 로딩을 하면, 세션 히스토리라는 것을 갖게된다.

    세션 히스토리는 페이지를 이동할 때마다 쌓이게 되며, 이를 통해 뒤로가기 시 이전 페이지로 가거나 뒤로 간 후 다시 앞으로 가는 등의 이동이 가능하다.

    history api에는 여러가지 메서드 들이 있지만 이번 포스팅에서 세션 히스토리에 접근하기위해 집중적으로 볼 메서드는 다음 두 가지다.

    1. pushState
    2. replaceState

    SPA을 만들어야 하므로 메인페이지에서 상품리스트 페이지와 게시글목록 페이지를 오갈 수 있는 간단한 html 코드로 하나씩 살펴 보도록 하자

     

    📌 history.pushState

    history.pushState는 브라우저의 세션 히스토리에 새 url state를 쌓는다.

    구문은 다음과 같다.

    history.pushState(state, title[, url])

    첫 번째 인자로 들어가는 state는 세로운 세션 히스토리 항목에 연결할 state 객체다. 새로운 state로 이동할 때마다 popstate 이벤트가 발생하는데 이 때 이벤트 객체의 state 속성에 해당 state의 복제본이 담겨있다.

    두 번째 인자로 들어가는 title은 현재의 대부분의 브라우저가 사용하지 않는 인자다. 빈 문자열이나 null 값을 두기도 한다.

    세 번째 인자로 들어가는 url은 변경할 url주소값을 넣으면 된다.

     

    브라우저의 콘솔에서 history를 치면 다음과 같이 나온다

    현재 세션 히스토리의 길이가 2라고 나와있고, 이제 다시 콘솔에 history.statePush를 해보자

    세션 히스토리의 길이가 하나 증가된걸 확인 할 수 있다.

    '/test' url은 실존하는 url이 아닌 테스트로 넣은 url이었지만, history.pushState(null, null, '/test') 을 콘솔에 입력하자마자 브라우저가 새로고침은 되지 않고 주소값이 변경한 것을 확인할 수 있었다. 하지만 새로고침을 하고나면 변경된 url의 실제 파일을 찾으려고 하기 때문에 404 에러가 난다.

    새로고침 없이 url만 바뀌고 있다

    또한 세션 히스토리에 이전에 쌓아둔 스택들의 히스토리가 남아 있기 때문에 뒤로가기를 하거나 앞으로 가기를 하더라도 새로 고침없이 url만 변경된다.

     

    이를 이용해서 url이 바뀔때마다 화면에 보여주는 컨텐츠를 다르게 한다면 Single Page Application을 만들 수 있다.

    function route() {
        const { pathname } = location;
        if (pathname === '/') {
          // 홈페이지 렌더링
        } else if (pathname === '/product-list') {
          // 상품 목록 렌더링
        } else if (pathname === '/article-list') {
          // 게시글 목록 렌더링
        }
    }
    
    // 첫화면 렌더링을 위한 라우팅
    route();
    
    window.addEventListener('click', (e) => {
        if (/** 클릭한 e.target이 a태그 요소라면 */) {
          e.preventDefault();
    
          const { href } = e.target;
          const path = href.replace(window.location.origin, '');
    
          history.pushState(null, null, path);
          // url이 변경 됐으니 새로 라우팅
          route();
        }
    })
    
    // 뒤로가기, 앞으로가기 이벤트가 발생시 라우팅
    window.addEventListener('popstate', () => route());

     

     


    📌 history.replaceState

    history.replaceState는 세션 히스토리에 새 url state를 쌓지 않고, 현재 url을 대체한다

    구문은 다음과 같다.

    history.replaceState(state, title[, url])

    입력받는 파라미터가 history.pushState와 같은 것처럼 파라미터가 의미하는 바도 동일하다.

     

    이미 history.pushState로 SPA를 충분히 구현하는데 완성하였는데 replaceState는 어떤 용도일까?

    예를들어 상품의 구매버튼을 눌렀을 때 로그인을 요구해서 로그인 페이지로 이동했다고 가정해보자. 로그인을 하고나면 사이트의 홈페이지로 location이 변경된 경험을 꽤나 자주 해봤을 것이다. 이 때, 뒤로가기 버튼을 누른다면 로그인페이지와 로그인 하기 전 구매 페이지중 어느 페이지로 돌아가는가?

    당연히 구매 페이지로 가야할 것이다.

    그렇다면 로그인 페이지에서 로그인을 하고나면 세션 히스토리에 로그인 페이지 히스토리는 없애고 새로운 페이지로 덮어 씌워야 한다. 이 때 replaceState를 사용하면 덮어씌울 수 있다.

    영상을 보면 pushState를 하면 세션 히스토리의 스택이 증가한걸 확인할 수 있지만, replaceState를 하면 스택이 증가하지 않고 뒤로 가기를 해도 /test 가 아닌 홈으로 이동 하는 것을 확인할 수 있다.

     


    💊 정리

    1. history api를 이용하면 새로 고침을 일으키지 않고도 브라우저의 url을 바꿀 수 있는 Single Page Application을 만들 수 있다.
    2. history api로 url을 변경한 후 새로고침을 하면 변경된 url의 실제 파일을 찾으려고 하기 때문에 해당 url에 해당되는 라우팅이 없을 경우 404 에러가 난다.
    3. 따라서 404 에러가 났을 경우 root의 index.html로 요청을 돌려주거나 다른 처리가 필요하다.
Designed by Tistory.