[Web] SPA (Single Page Application)

Peter·2022년 3월 10일
0

web

목록 보기
2/3
post-thumbnail

SPA

  • 단일 페이지 어플리케이션으로 CSR 형태를 띄고, 그렇기 때문에 페이지 이동간 다시 새로고침되지 않아 네이티브 앱과 같은 경험 제공

  • CSR 형태이기 때문에 SEO 이슈 발생

  • React의 경우 Next.js 와 같은 SEO 이슈를 해결할 방법을 가지고 있음

라우팅

  • 원래 URL의 변경에 따른 요청으로 서버로부터 원하는 페이지를 받아와야하지만
  • SPA 같은 경우 모든 리소스를 클라이언트 서버단에 가지고 있으므로 자체적으로 렌더링이 가능함
  • 하지만 history관리를 위해 각 페이지가 URL 같은 무언가를 가지고 있어야함

Ajax를 사용해서

<a href="/service">Service</a>
const routes = [
  { path: '/', component: Home },
  { path: '/service', component: Service },
  { path: '/about', component: About },
];

navigation.onclick = e => {
  if (!e.target.matches('#navigation > li > a')) return;
  e.preventDefault();
  const path = e.target.getAttribute('href');
  render(path);
};
  • 위와 같이 a 링크를 통해 정해진 path를 받아와 컴포넌트를 실행할 수 있다.
  • 이 경우 이미 만들어진 정적메소드를 이용하기 때문에 CSR 형태를 가진다
  • 하지만 내부적으로는 '/'를 사용한 라우팅을 하지만 URL주소창에는 변경사항이 없으므로 모든 렌더링이 홈화면에서 이루어진다
  • 따라서 history관리가 불가능하다

Hash방식

<a href="#service">Service</a>
const routes = [
  { path: '', component: Home },
  { path: 'service', component: Service },
  { path: 'about', component: About },
];

const render = async () => {
  try {
    // url의 hash를 취득
    const hash = window.location.hash.replace('#', '');
    const component = routes.find(route => route.path === hash)?.component || NotFound;
    root.replaceChildren(await component());
  } catch (err) {
    console.error(err);
  }
};

window.addEventListener('hashchange', render);

window.addEventListener('DOMContentLoaded', render);
  • addEventListener의 hashchange를 활용한 라우팅 방법으로 주소에 해시를 넣어 동작하게 된다
  • 주소창엔 해시를 포함한 주소로 URL이 변경되지만 새로고침이 되는것이 아니라 ajax방식과 동일하게 렌더링이 일어난다
  • 다만 어쨌든 URL에 등록이 되고 이는 history관리를 가능하게 해준다.
  • 하지만 주소자체에 '#(해시)'가 포함되어 있으므로 검색 크롤링 엔진이 수집 단계에서 수집을 거절할 수 있을 가능성이 높다

pjax방식 (pushState + ajax)

<a href="#service">Service</a>
navigation.addEventListener('click', e => {
  if (!e.target.matches('#navigation > li > a')) return;

  e.preventDefault();

  const path = e.target.getAttribute('href');

  window.history.pushState({}, null, path);

  render(path);
});


window.addEventListener('popstate', () => {
  console.log('[popstate]', window.location.pathname);
  render(window.location.pathname);
});

render(window.location.pathname);
  • ajax 방식과 비슷하지만 a링크가 클릭됐을때 새로고침이 방지되고
  • path가 history에 올라가는 동시에 path에 해당하는 컴포넌트가 렌더링되는 형태이다.
  • 이 경우 해시로 인한 크롤링 거절 현상을 방지할 수 있다.

https://poiemaweb.com/js-spa
https://miracleground.tistory.com/165

profile
컴퓨터가 좋아

0개의 댓글