Angular.js는 기본적으로 원페이지 웹사이트를 위한 프레임워크이다. 대부분의 원페이지 웹사이트들의 동작방식이 그렇듯이 Angular.js도 라우팅에 URL의 해쉬를 사용하고 있다. 이는 해쉬뱅과는 모양은 약간 다르지만 뭐 개념자체는 동일하다.
$routeProvider
.when('/about', {templateUrl: 'about.html', controller: AboutCtrl})
.when('/login', {templateUrl: 'login.html', controller: LoginCtrl})
그래서 Angular.js에서는 $routeProvider
를 사용해서 페이지를 변경할 수 있고 여기서 지정한 URL은 실제로는 http://example.com/#/about, http://example.com/#/login과 같은 형태가 된다. 웹브라우저는 해쉬태그가 변경될 경우에는 페이지 요청을 다시 하지 않고 현재 페이지에서 위치만 이동시키므로 이를 이용해서 해쉬값을 URL 형태로 받아서 라우팅처리를 하는 것이다.
보통 웹 어플리케이션을 작성할 때는(내 경우에 문서형 컨텐츠를 직접 만들지 않으므로) 해쉬를 직접적으로 쓸 일이 별로 없어서 신경안쓰고 있었는데 API로 문서를 받아와서 어플리케이션을 구성하다보니 문서내에 <a>
태그로 해쉬를 사용한 경우가 있어서 Angular.js의 라우팅과 충돌이 발생했다. 아무 처리도 안하면 Angular.js가 앵커태그의 해쉬 이동을 라우팅으로 인식하고 페이지를 변경하려고 시도하지만 당연히 그런 라우팅은 존재하지 않는다.
그래서 라우팅이 아닌 해시를 사용하려면 별도로 처리를 해주어야 하고 이를 위한 함수가 $anchorScroll이다.
$location.hash('HASH ID');
$anchorScroll();
$anchorScroll()
는 위와 같이 사용하는데 $location
객체에 hash()
값에 이동할 해시의 아이디를 지정한 뒤에 $anchorScroll()
를 호출하면 해당 위치로 스크롤이 이동하게 된다. 물론 이를 페이지 전체에 쓸 것인지 일부분에서만 사용할 것인지는 알아서 할 수 있다.(직접 처리해야 하는 것이므로) 뭔가 손이 많이 가지만 원페이지 앱으로 구성해서 해쉬를 라우팅으로 쓰고 있다면 어쩔 수 없을듯 하다.
추가적으로 스택오버플로우에 나온대로 Angular.js 라우팅과 함께 해쉬태그를 같이 쓰려면(대표적으로 API 문서처럼 페이지가 별도로 있고 각 부분으로 이동하는 링크도 가지려면) 다음과 같이 작성할 수 있다.
app.run(function($rootScope, $location, $anchorScroll, $routeParams) {
$rootScope.$on('$routeChangeSuccess', function(newRoute, oldRoute) {
$location.hash($routeParams.scrollTo);
$anchorScroll();
});
});
<a href="#/test?scrollTo=foo">Test/Foo</a>
$routeChangeSuccess
로 라우팅이 변경된 것을 감지한 뒤 scrollTo
파라미터로 받은 위치로 스크롤을 이동시킨 것이다.
Comments