본문으로 건너뛰기

Pjax(pushState와 Ajax)

무료2015-09-22#Front-End#JS#pjax#pushState & Ajax#single page app#spa#pjax详解#pjax原理

Pjax란 무엇이며, 어떤 용도이고, 어떻게 사용하며, 왜 사용하는가?

1. Pjax란 무엇인가?

Pjax = history.pushState + Ajax
     = history.pushState + Async JS + XML(xhr?)

BOM 객체인 history가 한층 강화되었습니다. 주로 히스토리 스택 조작에 관한 것인데, 이전에는 replace, go 등 전체 페이지를 이동시키고 새로고침하는 것들뿐이었지만, 이제는 히스토리 스택의 내용을 단순히 수정하면서 부작용(페이지 이동 및 새로고침)이 없는 pushState, replaceState 등 순수하게 스택을 조작하는 메서드들이 생겼습니다.

history 객체에 대한 더 자세한 정보는 MDN History에서 확인할 수 있습니다.

2. Pjax는 어디에 쓰이는가?

1. 초기의 싱글 페이지 애플리케이션(SPA)

페이지 새로고침은 리소스를 낭비할 뿐만 아니라(동급 페이지의 대부분 내용은 동일하므로 중복 내용을 다시 로드할 필요가 없습니다), 사용자 경험에도 영향을 미칩니다(로딩, 로딩, 로딩...). 부분 새로고침은 로딩이 사용자 경험에 미치는 영향을 피할 수 있게 해주며, Ajax 개념이 나오자마자 많은 이들이 이를 시도했습니다. 전체 사이트를 싱글 페이지 애플리케이션(Single Page App, 이하 SPA)으로 만들고 Ajax로 JSON을 요청한 뒤 데이터를 부분적으로 렌더링하는 방식이었는데, 초기의 SPA에는 여러 단점이 있었습니다.

  • 가장 큰 문제: 페이지 내용과 URL의 불일치

이것은 치명적인 단점입니다. 사용자가 보는 내용과 주소창의 URL이 일치하지 않는다는 것은 내용을 공유하거나 전파할 수 없음을 의미하며(공유와 전파는 매우 중요합니다), 브라우저의 앞으로 가기/뒤로 가기 버튼도 사용자의 예상대로 작동하지 않습니다.

  • 둘째: SEO 파괴

순수 Ajax로 구현된 SPA는 SEO에 매우 부정적인 영향을 미칩니다. 페이지의 많은 내용이 Ajax 요청 후 JavaScript에 의해 렌더링되기 때문에 검색 엔진 스파이더가 이를 볼 수 없고, 결과적으로 인덱싱이나 수집이 되지 않습니다.

2. pretty AJAX URL

SEO 문제를 해결하기 위해 Google은 이름만 'pretty AJAX URL'인 아주 못생긴 방법인 #!을 제안했습니다.

Twitter에서 한 달 정도 사용해 보았으나, 사용자들이 너무 못생겼다는 피드백을 주어 나중에 그만두었다고 합니다. 이 못생긴 URL은 확실히 위에서 언급한 두 번째 문제를 해결할 수 있지만, 검색 엔진의 협조가 필요합니다. Google은 이 방식을 인정하여, Google 스파이더가 mydomain.com/index.html#!article1mydomain.com/index.html#!article2를 두 개의 서로 다른 페이지로 취급합니다. 서버에서 이러한 특수 URL 요청에 대응하는 페이지를 반환하면 SEO 문제는 해결됩니다.

하지만 첫 번째 문제는 여전했습니다. 페이지 내용과 URL이 여전히 일치하지 않았죠. 그래서 등장한 것이 다음에 설명할 Pjax입니다.

3. Pjax

W3C는 히스토리 스택에 대한 제어 능력을 강화한 새로운 API를 발표했습니다. 이 API를 통해 주소창의 URL을 직접 수정할 수 있게 되었고, 마침내 페이지 내용과 URL이 일치할 수 있게 되었습니다.

부분 새로고침이 성공할 때마다 history.pushState를 호출하여 주소창의 URL을 동기화(히스토리 스택 유지)합니다. 이 URL들은 직접 접속 가능한 페이지에 대응됩니다. 각 부분 새로고침 동작은 a 태그에 의해 트리거되며, JavaScript가 기본 이동 동작을 가로챈 뒤 Ajax로 데이터를 요청하여 렌더링합니다. 사용자는 부분 새로고침을 통한 매끄러운 경험을 얻고, 스파이더는 평범한 a 태그를 통한 페이지 이동을 보게 됩니다. 페이지에 표시되는 내용은 항상 해당 URL에 직접 접속했을 때와 일치하므로 치명적인 단점도 사라졌습니다.

만약 각 브라우저의 지원 현황이 좋다면 Pjax는 SPA를 완벽하게 지원할 수 있습니다. 브라우저가 새로운 API를 지원하지 않는다면 그냥 스파이더처럼 취급하면 됩니다(현재로서는 마땅한 호환성 해결책이 없으며, jQuery 플러그인으로도 한계가 있습니다). CSS/JS 충돌이나 메모리 누수 등은 SPA 자체의 문제이며, 성숙한 SPA 솔루션을 통해 해결해야 할 부분입니다.

3. Pjax는 어떻게 사용하는가?

핵심은 두 가지 메서드와 한 가지 이벤트입니다.

  • history.pushState(state, title, url);

  • history.replaceState(state, title, url);

  • popstate

여기서 state 매개변수는 사용자 정의 객체이며 history.state를 통해 가져올 수 있습니다. title 매개변수는 사실상 브라우저들이 지원하지 않아 무의미합니다. pushreplace의 차이점은 전자는 지정된 URL을 스택에 추가하고, 후자는 현재 스택의 최상위 요소를 교체한다는 점입니다. 브라우저의 앞으로 가기/뒤로 가기 버튼은 popstate 이벤트를 트리거하며, 여기서 history.state 데이터에 따라 적절한 처리를 할 수 있습니다.

참고할 만한 간결한 데모가 있습니다: ajax와 HTML5 history pushState/replaceState 예제

또한 사용할 수 있는 오픈 소스 라이브러리들도 있습니다.

  • jQuery pjax: 최근(2015-09-22)까지 업데이트됨

  • history.js: 2년 전에 업데이트가 중단되었지만 사용하기 좋다고 알려져 있음

  • welefen/pjax: 주요 JS 라이브러리의 Pjax 사용법

4. 왜 Pjax를 사용하는가?

SEO에 영향을 주지 않으면서 부분 새로고침 + 로컬 캐싱을 통해 전례 없는 빠른 경험을 제공할 수 있다는 것이 Pjax의 절대적인 장점입니다.

Pjax는 순수 모바일용이 아닌 싱글 페이지 애플리케이션에 적합하며, 매끄러운 사용자 경험을 구현할 수 있습니다. 잘 캡슐화된 Pjax 컴포넌트는 캐싱, 로컬 스토리지, 애니메이션 등 추가 기능을 지원하여 사용하기에도 매우 편리합니다.

모바일 페이지는 일반적으로 대규모의 잦은 콘텐츠 업데이트가 발생하지 않으며 SEO를 크게 고려할 필요가 없는 경우가 많으므로 직접 Ajax를 사용해도 무방합니다.

5. Pjax 사례

  • 전체 사이트 Pjax 블로그: porridge

참고 자료

댓글

아직 댓글이 없습니다

댓글 작성