전에 블로그 글 주제를 요청받기로 하고 올라온 이슈 중에 Ajax를 사용할 때 "뒤로 가기"에 대한 요청이 있었다. 난이도가 아주 높은 건 아니므로 재밌겠다는 생각이 들었다. 일단 최근에는 Ajax를 쓸 때 페이지 뒤로 가기를 직접 구현해 본 적이 없다. 나는 "문서로서의 웹"이라는 기본 개념을 중시하기 때문에 Ajax를 본문 중심으로 헤비하게 쓰지 않는 편이고 SPA(Single Page Application)을 많이 선호하진 않지만, SPA를 하더라도 Angular.js나 React, Backbone 같은 프레임워크에서 제공하는 라우팅을 썼기 때문에 직접 구현해 본 적은 없다. 이 글은 내가 아는 지식 선에서 Ajax를 사용할 때의 "뒤로 가기"에 대해서 정리한 글이지만 그사이에 뭔가 새로운 방법이나 접근이 있을 수도 있는데 그런 경우 알려주면 좋겠다. 글 목록을 보여주는 방식해당 이슈를 보면 "'페이스북'처럼 목록이 로딩된 상태 (페이징 처리X) 에서 뒤로 가기 처리하는 방법"이라고 나와 있는데 내 지식 범위에서 목록에 대한 관리는 2가지로 나뉜다. 그래서 이해를 도우려면 이 2가지를 먼저 구분하고 설명하는 게 더 좋겠다. 전통적인 방식의 게시판 같은 것을 생각해 보자. 게시판의 글 목록이 화면에 나오고 다음 페이지로 이동하면 글 목록만 Ajax로 불러오게 된다. 이 경우 URL 등으로 정해진 각 페이지 번호에 따라 보여야 하는 글의 목록이 정해져 있다. 물론 새로운 글이 올라오면 목록이 달라지겠지만, 프로그램 관점에서는 불러와야 하는 글의 목록이 정해져 있다. 대신 페이스북이나 트위터 같은 경우의 목록을 생각하면 무한스크롤이다. 페이지별로 나오는 글 목록이 정해져 있는 것이 아니라 URL이 달라지지 않은 상태에서 무한 스크롤을 하게 된다. 그래서 목록의 URL을 복사해서 다른 사람에게 공유한다고 해서 같은 화면을 보지 않는다.(위에서 설명한 상황에서는 같은 주소는 같은 글 목록을 본다.) 이런건 웹사이트의 요구사항에 따라 달라지지만 보통은 URL에 따라서 보여주는 글의 목록을 정하지 않겠다는 의도이다. 그래서 페이스북이든 트위터든 글 목록에서 무한스크롤로 계속 로딩해서 보다가 특정 글을 클릭해서 이동했다가 뒤로 가기로 돌아오면 글 목록을 처음부터 다시 로딩한다. 후자의 경우는 기술적인 문제라기 보다는 서비스의 특성에 관한 것이다. 이어서 설명한 방법을 이용해서 이전에 어디까지 무한스크롤을 했는지 기억했다가 페이지를 로딩하고 사용자를 이 위치에 스크롤 시켜놓는 것은 가능하지만 나는 이 방식은 무한 스크롤과는 좀 맞지 않는다고 생각한다. 이런 상황이 있다면 구현하기 보다는 실제로 무한 스크롤이 정말 필요한가를 고민해 볼 필요가 있다고 생각한다. 그래도 요구하면 할수 없기는 하지만 여기서는 무한스크롤로 보여지는 목록이 아닌 페이징 처리가 된 상태에서 뒤로가기를 구현하는 방식에 대해서 설명하도록 하겠다. 이슈를 올려주신 분이 무한스크롤쪽을 원하는 것 같기도 한데 그렇다면 이슈를 새로 올려주시거나 추가 설명을 해주시면 좋겠다. 그리고 기술적으로 방식은 동일하기 때문에 무한스크롤에서 뒤로가기를 구현하더라도 이글에서 설명하는 방식을 먼저 이해해야 한다. 링크를 이용한 방식위 방식을 보자. Ajax 등을 쓰지 않고 링크로 목록을 보여주고 페이지관리를 하는 방식이다. 이 방식이 웹의 기본 방식이고 특별한 이유가 없으면 링크로 모든 페이지를 연결하면 된다. 이렇게 하면 모든 페이지에 고유 URL이 있으므로 SEO나 소셜을 대응하는데도 아무런 문제가 없다. "다음"을 클릭하면 다음 10개의 목록을 가져오고 개별 URL을 가지므로 상세 목록에 들어갔다가 뒤로 가기를 해도 이전에 보던 페이지로 잘 돌아간다. 동작하는 예제는 여기에서 볼 수 있다. 여기서는 주소에 그래서
Ajax를 이용한 방식앞의 방식에서는 링크로 연결되어 있으므로 클릭할 때마다 항상 전체 페이지를 새로 로딩하게 된다. 이 데모 페이지는 목록 외에 스타일이나 다른 문서가 없으므로 문제가 될게 거의 없지만 복잡한 페이지의 경우 페이지마다 헤더나 사이드바, 푸터를 로딩하는 건 속도 저하의 영향을 준다. 그래서 등장한 게 Ajax(Asynchronous JavaScript and XML)다. Ajax는 이미 보편화한 기술이지만 약간 설명하지만 제시 제임스 가렛(Jesse James Garrett)이 만든 용어로 Ajax를 이용하면 웹 페이지에서 일부만 로딩해서 갈아치우는 것이 가능해졌고 이후 웹사이트 작성에 큰 영향을 주었다. 이 예제의 동작을 확인하려면 여기서 볼 수 있다. 이 주소는
앞의 HTML과 크게 다른 점은 뒤에도 그렇지만 여기의 예제는 데모용으로 최적화된 코드이다. 코드의 품질보다는 동작 방식을 봐주길 바란다. 마지막 두 라인을 보면 위의 다음 버튼
이 방식은
앞의 링크방식과 큰 차이점이 있다. 일단 페이지의 URL이 앵커를 이용한 방식앞에서 설명한 대로 Ajax를 이용하면 전체 페이지를 매번 로딩할 필요 없이 웹페이지의 핵심 콘텐츠 부분만 가져와서 로딩할 수 있다. 그래서 속도가 빠르고 사용자 편의성도 증가하지만 웹 브라우저 입장에서는 페이지의 URL은 바뀌지 않았다. 그래서 "다음" 버튼을 눌러서 새로운 목록을 보더라도 "뒤로 가기"를 누르면 사용자의 기대와
다르게 이전 목록이 나오는 게 아니라 이전 페이지 여기서는 그래서 이를 해결하는 방법으로 이용한 것이 앵커다. 예를 들어 babel 프로젝트의 README를 보자. 상단에 목차가 있는데 README 의 주소는 https://github.com/babel/babel/blob/7.0/README.md이지만 각 목차를 누르면
https://github.com/babel/babel/blob/7.0/README.md#faq, https://github.com/babel/babel/blob/7.0/README.md#team같은 식으로 뒤에 동작하는 예제는 여기서 볼 수 있고 이 페이지에 접속하면 다음과 같은 HTML을 내려주게 된다.
이전에 본 ajax와 거의 비슷하다. 서버가 목록을 내려주는 게 아니라 페이지가 로딩된 후 자바스크립트에서 서버에 목록을 받아와서 화면에 보여준다. 가장 크게 다른 점은 여기서 주의할 점은 앵커는 서버에 전달되는 값이 아니라는 것이다.
동작 원리는 같지만 좀 더 주소처럼 보이려고 만든 것이 해시뱅이다. 해시뱅의 차이점은 pushState를 이용한 방식
하지만 이 예제의 동작을 확인하려면 여기서 볼 수 있다. 이 페이지는 서버에서 다음과 같은 HTML을 내려준다.
HTML을 자세히 보면 처음에 본 링크방식과 유사하게
마지막에 앵커를 바꿔주는 대신 그리고 추가로 앞의 예제와 크게 다른 점 중 하나가 해당 페이지의 주소가 그러므로 서버는 주소에 따라 해당 목록을 HTML로 내려줄 수 있어야 한다. 이는 서버에서 렌더링하는 방식과 브라우저에서 Ajax로 하는 방식이 섞여 있는 것이므로 서버에서 요청의 Node.js에서 express와 jade를 이용해서 간단하게 작성한 예제이지만 전체 소스를 확인하고 싶다면 저장소를 참고하면 된다. |