들어가며

패럴랙스 스크롤링 웹 사이트의 세계로 들어갈 준비는 되었나요? 패럴랙스 스크롤을 사용한 사이트는 많습니다. 안타깝게도 일부 사이트에 있는 패럴랙스 스크롤링은 사용자들의 주의를 분산시키거나 보여주고자 했던 콘텐츠가 아닌 다른 곳으로 사용자들의 눈을 돌리지만, 제대로만 사용한다면 훨씬 더 빼어난 웹을 만들 수 있습니다. 패럴랙스는 잘만 사용된다면 사용자들이 더 실감 나는 매력적인 방식으로 콘텐츠를 탐색할 수 있도록 도와줍니다.

최근 우리팀은 콘텐츠 일부에 패럴랙스 스크롤 애니메이션을 사용하기 시작했습니다. 우리는 ADT의 역사라는 페이지에서 약간의 아이디어를 얻고, 유명 드라마인 워킹 데드에 대한 인터랙티브 좀비 인포그래픽을 만들어보기로 했습니다. 오늘은 이 프로젝트의 무대 뒤로 여러분을 데려가 굉장히 유용했던 Skrollr.js라는 자바스크립트 플러그인의 사용법을 보여주려고 합니다.

메인 좀비 이미지

간단히 말해서 Skrollr는 HTML과 CSS를 사용해 정교한 스크롤 기반 애니메이션(패럴랙스 혹은 그 밖의 것)을 만드는 플러그인입니다. Skrollr의 수많은 장점은 공식 문서에서 찾아볼 수 있습니다. 이 글에서 우리는 자바스크립트와 스프라이트 몇 개를 사용해 사용자가 스크롤을 앞뒤로 움직임에 따라 반응하는 보행 애니메이션을 간단하게 만들어보겠습니다. 이 글을 끝까지 따라가면, 패럴랙스 환경에서 걷는 캐릭터가 인간에서 좀비로 변하는 것도 볼 수 있습니다.

먼저 몇 가지 소스 파일을 다운로드 받으세요. 워킹 데드 프로젝트에서 사용했던 이미지 몇 장과 자바스크립트 파일, HTML 뼈대가 있을 것입니다. 이제 이 파일들을 가지고 삽질을 시작해보겠습니다.

1단계 - 패럴랙스 백그라운드

HTML5 data- 속성을 추가한 <div> 몇 개를 추가해서 패럴랙스 백그라운드 레이어 두 장을 만들어 보겠습니다. 또한, 스타일시트에 CSS도 약간 추가하고 우리가 작성한 main.js 파일에서 Skrollr의 .init() 함수도 호출할 것입니다. 다음 코드에서 보듯 패럴랙스 레이어는 id="skrollr-body"가 설정된 엘리먼트의 자식 노드여야 합니다. 지금 보기에는 클래스와 ID가 너무 많다 싶을 수 있지만, 나중에 엘리먼트를 조금 더 추가하게 되면 이유가 있었음을 알게 될 것입니다.

HTML:

<div id="skrollr-body">
	<div id="Scene">
		<div id="bg1" class="parallax-layer"
			data-0="left:0px;"
			data-5000="left:-1000px;">
		</div>
		<div id="bg2" class="parallax-layer"
			data-0="left:0px;"
			data-5000="left:-2500px;">
		</div>
	</div>
</div>

우리가 보게될 마술같은 일은 모두 data- 속성 덕분입니다. Skrollr를 호출하면, Skrollr는 #skrollr-body 안에 있는 모든 엘리먼트를 탐색하며 엘리먼트에 설정된 data- 속성을 사용해 적절한 애니메이션을 구현합니다. data- 뒤에 붙은 숫자는 사용자가 스크롤 한 픽셀의 수이며, 속성의 값은 해당 스크롤 위치에 왔을 때 현재의 요소에 설정할 스타일입니다. #bg1를 예로 들면, 사용자가 페이지 상단(data-0)으로부터 페이지 아래로 5,000 픽셀(data-5000)만큼 스크롤하면 #bg1이 왼쪽으로 1000 픽셀만큼 움직이는 애니메이션이 나타날 것입니다. 설정한 값을 보면 Skollr는 대략 사용자 스크롤 5픽셀마다 왼쪽으로 1픽셀씩 #bg1을 옮길 것입니다. 이 애니메이션은 앞으로도 뒤로도 일어나므로 사용자는 어느쪽으로든 스크롤 할 수 있으며 Skrollr이 적절한 애니메이션을 보여줄 것입니다.

#bg2data-* 속성에 설정된 값을 살펴보면 사용자 스크롤 2픽셀마다 #bg2가 1픽셀씩, 다시 말해 #bg1보다 훨씬 빨리 움직이는 것을 알 수 있습니다. 이 덕분에 3D 공간 같은 느낌이 날 것입니다. 그러나 이 코드를 실행하기 전에 이미지를 추가한 후 액자처럼 감싸는 CSS를 추가해야 합니다. 그 후에는 Skrollr의 초기화 함수도 호출해야 하고요.

CSS:

화면은 700px 높이의 프레임에 수직 중간 정렬되게 합니다.

#Scene{
	position: fixed;
	width: 100%;
	height: 700px;
	margin-top: -350px;
	top: 50%;
	}
.parallax-layer{
	position: absolute;
	height: 700px;
	background-repeat: no-repeat;
	}
#bg1{
	background: url(../images/bg-1.jpg);
	width: 3528px;
	}
#bg2{
	background: url(../images/bg-2.png) left bottom;
	/* 이미지가 꽤 크지만... 사용할만한 가치가 있습니다 */
	width: 4368px;
	}


JavaScript:

skrollr.init();

잠시 후에는 여기에 다른 작업을 더 추가할 것이므로 여기까지 작업한 내용을 별도 파일로 저장했습니다. 하지만, 여러분은 굳이 그렇게 하지 않아도 됩니다.

이것 보세요! 패럴랙스가 만들어졌네요!

2단계 - 전경 엘리먼트

다음으로는 전경에 몇 가지 요소를 추가해보겠습니다. 구름, 해, 학교를 추가한 후 캐릭터도 추가할 것입니다. 이 중 학교는 캐릭터가 인간에서 좀비로 변신할 때 잠시 캐릭터를 숨기는 용도로 사용합니다.

먼저 두 번째 구름 레이어를 추가해봅시다. 이 구름 레이어는 #bg2와 같은 속도로 화면을 가로질러 이동할 것이므로, #bg2 안에 구름 레이어를 추가하여 (절대 위치에 기반한) 동일한 애니메이션이 적용되도록 합니다. 이처럼 내부에 있는 div는 부모의 CSS 위치 속성을 그대로 사용하는 경우가 많습니다.

HTML:

<div id="bg2" class="parallax-layer"
	data-0="left:0px;"
	data-5000="left:-2500px;">
	<div id="cloud"></div>
</div>

CSS:

#cloud{
	position:absolute;
	background:url(../images/clouds.png);
	width:2059px;
	height:347px;
	}

이제 학교와 아직 좀비가 되기 전인 캐릭터를 추가해보겠습니다. 학교는 #bg2보다 살짝 더 빠르게 움직이게 할 것입니다. 또한, 학교를 그릴 때 뒤쪽과 앞쪽 레이어를 나누고 그 사이에 좀비 캐릭터를 두어서 마치 캐릭터가 문을 통과해서 지나가는 것처럼 보이게 할 것입니다.

HTML:

<div class="parallax-layer">
	<div id="schoolunder" class="school"
		data-0="left:2000px;"
		data-5000="left:-1500px;">
	</div>
	<div id="zombie"></div>
	<div id="schoolover" class="school"
		data-0="left:2000px;"
		data-5000="left:-1500px;">
	</div>
</div>

CSS:

캐릭터는 화면 왼쪽에서 300px만큼 떨어진 곳에 그대로 있되 배경이 화면 좌우로 움직이도록 하여 마치 예전에 보던 횡 스크롤 게임 느낌이 나도록 했습니다.

#zombie{
	position:absolute;
	background-image:url(../images/zombify.png);
	width:250px;
	height:190px;
	top:340px;
	left:300px;
	}
.school{
	position:absolute;
	width:600px;
	height:523px;
	top:100px;
	}
#schoolunder{
	background:url(../images/school_under.png);
	}
#schoolover{
	background:url(../images/school_over.png);
	}

이제 이 캐릭터는 마치 스케이트를 타듯 미끄러지며 화면을 이동하는 것처럼 보일 텐데, 여기에 보행 애니메이션과 짤막한 좀비 변신 애니메이션을 추가해보겠습니다. 그전에 해 이미지부터 추가하고 넘어가죠. 우리는 5개의 data 속성을 사용하여 해가 뜨고 지는 애니메이션을 표현했습니다. 이 엘리먼트는 #bg1#bg2 사이에 둘 것이므로 하늘 배경보다는 앞에 보이지만 전경 엘리먼트 뒤쪽을 이동하게 될 것입니다.

HTML:

<div id="bg1" class="parallax-layer"
	data-0="left:0px;"
	data-5000="left:-1000px;">
</div>
<div id="sun"
	data-0="top:200px;"
	data-2000="top:25px;"
	data-3000="top:0px;"
	data-4000="top:25px;"
	data-5000="top:50px;">
</div>
<div id="bg2" class="parallax-layer"
	data-0="left:0px;"
	data-5000="left:-2500px;">
</div>

CSS:

#sun {
	position:absolute;
	background:url(../images/sun.png);
	width:194px;
	height:194px;
	left:180px;
	}

우리가 지금까지 한 내용을 확인해보세요. 꽤 괜찮지만, 아직 다듬어야 할 부분이 남아 있습니다.

3단계 - 계속 걷게 하기 (& 좀비로 변신하기)

이제 캐릭터에 생명력을 불어넣을 때입니다. 캐릭터의 보행 및 변신 애니메이션에 필요한 이미지 프레임은 다운로드 받은 .png 스프라이트 파일 안에 있습니다. 처음에는 인간이었다가 나중에 좀비로 변할 것입니다. 이 프레임들을 배경 이미지로 보여주고 사용자의 스크롤에 따라 주기적으로 반복시키는 자바스크립트를 작성해보겠습니다. 스크롤을 어느 쪽으로 하든 동작하게 만들어서 정말 게임 같은 느낌을 내보겠습니다.


좀비화를 표현하는 스프라이트

data-* 속성을 사용하여 Skrollr가 배경 이미지를 애니메이션으로 만들게 할 수도 있지만, 이 방법은 속성을 꽤 많이 작성해야 하므로 직접 함수를 작성하기로 합니다. 직접 작성한 덕분에 약간의 유연함도 얻을 수 있으며 코드의 유지보수도 확실히 더 편해졌습니다. 우리는 skrollr.init()를 호출할 때 우리가 작성한 함수를 인수로 전달할 것입니다. 조금 더 자세히 말하자면 beforerender 리스너 함수로 할당하여 Skrollr가 애니메이션의 각 프레임을 그리기 직전에 자동으로 호출되게 할 것입니다(beforerender를 비롯한 Skrollr의 다른 옵션은 문서를 참고하세요). beforerender에는 curTop이라는 프로퍼티를 가진 객체가 인수로 전달됩니다. curTop은 현재 스크롤이 상단으로부터 얼마나 떨어졌는가를 알려주는, 다시 말해 페이지 상단으로부터 사용자가 스크롤 한 픽셀의 양을 알려주는 숫자입니다. 우리는 이 값을 사용하여 배경 이미지로 사용한 스프라이트를 앞으로 움직일 것인지 뒤로 움직일 것인지 또는 인간을 좀비로 바꿔야 할 때인지 정하겠습니다.

보행 애니메이션부터 작업한 후 인간에서 좀비로 변신하는 과정을 추가하겠습니다.

JavaScript:

var zombie = $('#zombie'),
	pLocs = [0, -250, -500, -750, -1000, -1250, -1500]
	curFrm = 0,
	lastStep=0;

skrollr.init({
	beforerender: function(o){
		// 마지막에 백그라운드 이미지를 움직인 후에
		// 사용자가 50픽셀 아래로 스크롤하면
		// 앞으로 이동해야 하므로 스프라이트에 있는
		// 다음 프레임으로 옮긴다.
		if(o.curTop > lastStep + 50) {
			if (curFrm>=6){ curFrm=-1; }
			zombie.css('background-position', pLocs[curFrm++] + 'px 0px');
			lastStep = o.curTop;
		// 사용자가 50픽셀 위로 스크롤하면
		// 뒤로 이동해야 하므로 이전 프레임으로 옮긴다.
		} else if(o.curTop < lastStep - 50) {
			if (curFrm<=0){ curFrm=7; }
			zombie.css('background-position', pLocs[curFrm--] + 'px 0px');
			lastStep = o.curTop;
		}
	}
});
  • zombie — 캐릭터를 표현하는 div에 대한 참조
  • pLocs — 스프라이트의 각 프레임이 왼쪽 끝으로부터 떨어진 픽셀 위치를 담은 배열
  • curFrm — pLoc에 있는 보행 애니메이션 프레임 중 현재 사용 중인 프레임의 인덱스
  • lastStep — 가장 최근에 배경 이미지를 움직였던 스크롤 위치. 프레임을 앞/뒤 어느 쪽으로 이동할 것인지 계산할 때 사용

멋지네요! 어려운 부분이 끝났습니다. 우리의 좀비는 걷기 시작할 테고요. 이제 남은 단계는 좀비로 변신!밖에 없습니다.

어쩌면 워킹 데드 드라마와 약간 다를지도 모르는데, 이 프로젝트에서는 캐릭터의 좀비 변신이 학교(zombie school)로 표현되었습니다. 덕분에 이 과정은 상대적으로 편했습니다. 인간이 걷는 장면의 프레임과 좀비가 걷는 장면의 프레임은 같은 이미지에 있었고 인간이 걷는 장면 바로 뒤에 좀비가 걷는 장면이 있었으므로 사용자가 캐릭터가 학교를 지나가는 장면이 나오는 곳을 스크롤 할 때 #zombie 레이어 배경 이미지의 위치만 적당히 바꿔주면 됐습니다. 인간이 걷는 장면은 7프레임인데 반해 좀비가 걷는 장면은 4프레임 밖에 안 들어서 애니메이션이 조금 더 유연하게 동작하도록 코드를 살짝 손봐야 했습니다. 수정된 부분은 아래에 굵은 글씨로 표시해두었습니다.

JavaScript:

var zombie = $('#zombie'),
	pLocs = [0, -250, -500, -750, -1000, -1250, -1500],
	curFrm = 0,
	lastStep=0,
	// We need just a couple extra variables
	animationCycle, backPosY;

skrollr.init({
	beforerender: function(o){
		// 사용자가 2800픽셀 이하로 스크롤하면
		// 캐릭터를 그대로 인간인 상태로 두고
		// 그 이상 스크롤하면 좀비로 바꾼다.
		if(o.curTop < 2800) {
			animationCycle=7;
			backPosY= '0px';
		} else {
			animationCycle=4;
			backPosY= '-190px';
		}
		if(o.curTop > lastStep + 50) {
			if (curFrm>=animationCycle-1){ curFrm=-1; }
			zombie.css('background-position', pLocs[++curFrm] + 'px ' + backPosY);
			lastStep=o.curTop;
		} else if(o.curTop < lastStep - 50) {
			if (curFrm<=0){ curFrm=animationCycle; }
			zombie.css('background-position', pLocs[--curFrm] + 'px ' + backPosY);
			lastStep = o.curTop;
		}
	}
});

그럼 이제 끝났습니다. 지금 막 우리는 게임 스타일의 패럴럭스 스크롤링을 만들었습니다. 축하합니다! 만약 더 다듬어진 버전을 보고 싶다면 우리팀이 작성한 워킹 데드 데모를 확인해보세요.

마무리

여기서 한 것은 Skrollr로 할 수 있는 기능의 겉핥기에 지나지 않습니다. 따라서 가능하다면 다른 많은 기능에 대해서도 꼭 읽어볼 것을 추천합니다. 애니메이션에 이징(easing)을 적용하거나 data 속성과 상수를 조합해서 사용하거나(유지보수에 좋습니다) Skrollr 스타일 시트에 프레임을 추가하는 대신 마크업에 전체 키프레임을 넣는 등 흥미로운 기능이 많습니다.

끝으로 잠깐 몇 마디 덧붙이려고 합니다. 가끔 웹 디자이너인 우리들은 매체의 노예처럼 느껴질 때가 있습니다. 웹에는 제약이 많고 크로스 브라우저와 크로스 디바이스 이슈에서 오는 어려움도 많습니다. 최소한 저는 여러 매체에서 디자인과 개발을 하는 한 사람으로서 간혹 매체의 노예처럼 느껴질 때가 있습니다. 하지만 이러한 브라우저 기반 매체에는 매우 독특한 면이 있는 것도 사실입니다. 예를 들어, 스크롤링 덕분에 사용자와 이런 식으로 인터랙션 할 수 있는 기회가 생겼습니다. 개인적으로 디자이너들은 이런 고유한 특성을 알아두어야 하며, 항상 이러한 특성을 훌륭한 경험으로 창조해 낼 방법을 찾아야 한다고 생각합니다.


이 글은 Elli Bishop이 오페라 개발자 사이트에 게시한 Creating Game-Style Parallax Scrolling: Zombie Edition을 번역한 글입니다.

Posted by 행복한고니 트랙백 0 : 댓글 1

NoSQL은 상당히 오랫동안 뜨거운 화제였다(음, 이제는 단순한 화젯거리 수준이 아니다).
하지만, 진짜로 NoSQL을 사용해야 할 때는 언제일까?

MongoDB의 적절한 사용법

NoSQL 제품(그리고 MongoDB)은 특정한 문제를 해결하기 위해 사용되어야 한다. 만약 다음과 같은 문제를 겪고 있다면 MongoDB를 고려해보는 것이 좋다.

쓰기 부하가 클 것이 예상될 때

MongoDB는 기본적으로 안전한 트랜잭션을 통해 빠른 속도로 데이터를 삽입한다. 개별 데이터의 비즈니스 가치가 낮은 어마어마한 양의 데이터를 읽어들여야 한다면 MongoDB가 적합하다. 단, 100만건이 넘는 트랜잭션 레코드는 삽입하지 않아야 하며, 최소한 다른 안전 장치를 갖춘 후에 삽입하는 것이 좋다.

신뢰할 수 없는 환경(클라우드와 실생활)에서 고가용성(高可用性)이 필요할 때

MongoDB에서는 replicaSet(마스터-슬레이브로 동작하는 서버의 집합)을 쉽고 빠르게 설정할 수 있다. 게다가, 노드(혹은 데이터 센터)에 문제가 생겼을 때 자동으로 데이터를 안전하게 즉시 복구할 수 있다.

빅 데이터를 다루거나 샤딩이 필요할 때

데이터베이스 스케일링은 어렵다(MySQL 테이블은 테이블당 5~10GB 사이가 되면 성능이 저하된다). MongoDB에는 데이터베이스의 파티셔닝 또는 샤딩이 필요할 때 사용할 수 있는 솔루션이 내장되어 있다.

위치 기반 데이터일 때

MongoDB는 특수한 기능을 내장하고 있어서 특정 위치와 관련한 데이터를 빠르고 정확하게 찾을 수 있다.

데이터가 커지거나 (1GB 이상) 스키마가 고정되어 있지 않을 때

RDBMS에 새로운 칼럼을 추가하면 일부 데이터베이스에서는 전체 데이터베이스에 락을 걸고, 그 외의 데이터베이스에서는 심각한 부하와 성능 저하를 일으킨다. 일반적으로 이런 현상은 테이블의 크기가 1GB보다 클 때 발생한다(또한, 아래에서 설명하는 BillRun과 갈이 크기가 수 TB를 넘는 테이블이 여러 개 존재하는 시스템에는 심각한 문제가 되기도 한다). MongoDB는 스키마가 없는 시스템이므로 새 필드를 추가해도 기존에 저장된 로우(혹은 도큐먼트)는 전혀 영향을 받지 않으며 변경이 즉시 이루어진다. 다른 장점으로는 프로그램이 변경되서 스키마를 수정할 때 DBA가 없어도 된다는 것이다.

DBA가 없을 때

DBA도 없고 데이터를 정규화하거나 조인(join)하기도 싫다면 MongoDB를 고려하는 것이 좋다. MongoDB는 객체를 JSON으로 직렬화하여 그대로 MongoDB에 저장하므로 객체를 저장하기에 좋다. 주의: 빅 데이터를 다룰 것이라면 위험 요소를 피하기 위해 다음과 같은 방법을 따라야 한다.

BillRun - Billing on top of MongoDB | MUG IL, Feb 2014 from Ofer Cohen

실제 사례 연구: 결제 시스템

지난 일리노이 모델링 사용자 그룹(Illinois Modeling Users Group, ILMUG)에서 오퍼 코헨은 MongoDB를 데이터 저장소로 사용한 차세대 오픈소스 결제 솔루션인 BillRun에 대해 발표했다. BillRun 시스템은 매월 5억건 이상의 통화 기록을 처리하는 이스라엘에서 가장 빠르게 성장하는 통신망 기업에서 사용되었다. 이 발표에서 오퍼는 이 시스템이 MongoDB를 사용해서 얻은 장점에 대해 설명했다.

  1. 스키마가 없는 설계 덕분에 새로운 통화 기록 유형을 시스템에 빠르게 도입할 수 있었다. 덕분에 BillRun은 데이터 저장소의 보편성을 유지할 수 있었다.
  2. 새 필드 추가를 제한하거나 데이터 증가를 제한하지 않고도 BillRun은 이미 실무에서 테이블당 수 TB에 달하는 데이터를 다루었다.
  3. 빠른 replicaSet으로 인해 다중 데이터 센터의 DRP(재난 복구 프로토콜)과 HA(고가용성) 솔루션 구성할 때 필요한 규약을 쉽게 충족시킬 수 있다.
  4. 샤딩을 통해 예산을 다 쓰지 않고도 선형적, 수적인 증가가 가능했다.
  5. 초당 2천건 이상의 통화 기록을 삽입할 때처럼 MongoDB 아키텍쳐는 삽입 부하가 높은 시스템에 적합하다. findAndModify(속도가 느림)와 2단계 실행(프로그램 적인 방법)을 통해 트랜잭션을 안전하게 만들 수 있다.
  6. 개발자 지향적인 쿼리덕분에 개발자들은 품격있는 쿼리를 작성할 수 있다.
  7. 위치 기반 기능을 활용해 사용자의 사용 패턴을 분석하고 어디에 통신망 인프라를 투자할 것인지 정했다.

요점

MongoDB는 훌륭한 도구지만 이득을 얻으려면 적합한 시나리오에서 사용해야 한다. BillRun은 MongoDB를 사용하기에 좋은 사례였다.



이 글은 Moshe Kaplan이 작성한 When Should I Use MongoDB rather than MySQL (or other RDBMS): The Billing Example을 번역한 글입니다.

Posted by 행복한고니 트랙백 0 : 댓글 0

티스토리 툴바