일상생활/코딩코딩

Bootstrap-Calendar (부트스트랩 캘린더) 설치 및 DB 연결 방법


Bootstrap-Calendar는 그 이름에서 알 수 있듯이, Bootstrap을 이용한 캘린더 모듈(아님 프레임워크, 아직도 이 둘을 구분을 못한다)이다. 몇몇 css 파일과 js 파일을 적절한 위치에 넣고, 캘린더를 호출하면, 그 자리에 뙇하고 캘린더가 나타나기 때문에 웹에서 캘린더를 올려놓고, 일정 공유를 할 필요가 있을 때 상당히 유용한 녀석이다. 하지만, 실제 사용에서는 약간의 문제가 있다. 깃허브에 올라온 도큐멘트와 예세 소스들 중에 하나도 제대로 된 게 없고, bower로 Bootstrap-Calendar를 설치하면 된다고 "나와있음에도 불구하고" bower를 이용하면 제대로 캘린더를 사용할 수가 없다. 기능이 상당히 많은 관계로 소스 코드가 상당히 복잡한데, 약간의 기능 수정이나 경로 변경을 하려고 하면, 거의 모든 캘린더 모듈과 관련된 css와 js파일들을 들쑤셔야하기 때문에 쉽게 문제가 해결 되지도 않는다. 필자도 1~2 시간 동안 bower로 bootstrap, bootstrap-calendar, jQuery, underscore.js 설치하다 경로 관련으로 엄청나게 삽질을 하였고, 현재 실력으로는  해결 할 수 없는 문제들이라는 걸 깨닫고 github 레포지토리를 클론하였다. 하지만 이렇게 클론을 했음에도 불구하고, 캘린더의 몇몇 기능들을 설명하는 소스코드를 참고를 해서는 개발을 할 수 없다. 예제 소스에 오류가 있고 도큐멘테이션이 제대로 되지 않았기 때문인데, sql 쿼리를 던져 일정을 json 객체로 던지는 php 예제 코드가 제대로 작동을 안하는 게 대표적이다. 처음에는 코드가 잘못 된 줄 모른채 mysql이 잘못 붙은 줄 알고 장대한 삽질을 하였는데, 설마하고 .css와 .js 소스코드를 분석하면서 예제가 잘못 됬음을 알게되었다. 단도직입적으로 도큐멘테이션도 예제도 못 믿겠으니 .css 파일과 .js 파일을 하나하나씩 뜯어가면서 작동 로직을 확인하고, 로직에 맞게 코드를 다 짜야한다. 부트스트랩은 분명 아무 생각 없이 도큐멘트와 예제 코드만 보고 웹 개발하라고 있는 녀석인데, 이건 좀 아닌거 같았고, 결국 이 글을 쓰게 되었다.


Github 주소 : https://github.com/Serhioromano/bootstrap-calendar

캘린더 데모 : http://bootstrap-calendar.azurewebsites.net/


설치를 위해 git를 이용하자. 설치를 원하는 폴더로 이동하고, git clone을 이용하여 받으면 된다. bower를 써도 된다고 하지만, 적극적으로 비추한다. ( 윈도 환경에서 쓰겠다고 한다면, github에 가서 download .zip을 이용하여 zip파일로 받고 압축 해제를 하면 된다. 또한 리눅스 터미널을 모른다면, zip 파일을 받자)

 git clone https://github.com/Serhioromano/bootstrap-calendar 

index.html를 열어보면 이쁘장한 캘린더가 나올 것이다. 이제 여기에 일정을 넣는 방법을 찾아야한다. 일단, 녀석은 js 폴더 아래에 있는 app.js를 불러오면서 calendar를 그린다. app.js를 보면 알겠지만, 이것도 예제 코드고 개발자는 귀찮았는지 바로 적용해서 바로 쓸 수 있게 만들어놓지를 않았다.

	var options = {
		events_source: 'events.json.php',
		view: 'month',
		tmpl_path: 'tmpls/',
		tmpl_cache: false,
		day: '2013-03-12',
		onAfterEventsLoad: function(events) {
			if(!events) {
				return;
			}
			var list = $('#eventlist');
			list.html('');

			$.each(events, function(key, val) {
				$(document.createElement('li'))
					.html('' + val.title + '')
					.appendTo(list);
			});
		},
		onAfterViewLoad: function(view) {
			$('.page-header h3').text(this.getTitle());
			$('.btn-group button').removeClass('active');
			$('button[data-calendar-view="' + view + '"]').addClass('active');
		},
		classes: {
			months: {
				general: 'label'
			}
		}
	};

보면 알 수 있지만, day 가 고정되어있다. index.html을 열면 매일 달력 날짜가 2013년 3월 12일에 고정되어있는 것이 그 이유이다.

	var today = new Date();
	var dd = today.getDate();
	var mm = today.getMonth()+1; //January is 0!
	var yyyy = today.getFullYear();

	if(dd<10) {
		dd='0'+dd
	} 

	if(mm<10) {
		mm='0'+mm
	} 
	var todayis = yyyy+'-'+mm+'-'+dd;

이 코드를 app.js에 추가하자. todayis가 오늘의 날짜를 나타내게 하는 코드다. day: '2013-03-12'를 day: todayis로 바꿔주기만 하면, day의 값는 오늘의 날짜를 가리키게 되고, 결과적으로 index.html을 열 때 요번달 달력이 나오게 된다. 이렇게, 날짜 관련 문제를 대부분 해결 할 수 있다. 이제 일정을 넣는 방법을 알아보자.

{
    "success": 1,
    "result": [
        {
            "id": 293,
            "title": "Event 1",
            "url": "http://example.com",
            "class": "event-important",
            "start": 12039485678000, // Milliseconds
            "end": 1234576967000 // Milliseconds
        },
        ...
    ]
}

이것이 맨 처음 나온 json 객체 예제이다. 이 소스는 약간만 수정하면 잘만 작동을 한다. 일단, 여기서 눈 여겨봐야할 점은 success : 1 과 result 값들이다. 뭔 의도인지 몰라도 개발자는 success:1 가 맨 처음에 있어야만, 이후의 json 객체들을 다 읽도록 하였다. result 값은 id, title, url, class, start, end 로 구성이 되어있다. id는 일정 구분을 하는 프라이머리키 (로 추정), title은 일정 제목, url은 일정 title을 클릭했을 때 리다이렉트 되는 주소이다. 이 때, http://를 안 붙이면 "현재 위치한 도메인" + "/" + url 값 으로 리다이렉트 된다. "url" : "250" 이고, 캘린더의 주소가 bengi.kr/index.html 이라면, bengi.kr/250으로 이동을 하는 것이다. class는 calendar.css에 정의된 컬러셋을 불러온다. event-important 는 빨간색으로, event-warning은 주황색으로 캘린더에 점이 찍혀져 나온다. (직접 해보면 이해가 쉽다) 뭐 다른 컬러셋 설정도 있으니, calendar.css를 뜯어볼 것을 추천한다. 또한, 당연하게도 css 파일을 수정해서 컬러셋을 추가할 수도 있다. start와 end는 timestamp로 일정 시작 시간과 일정 마감 시간 받아서 저장하는 부분인데, 이것을 손으로 계산하는 일은 엄청나게 귀찮은 일이라는 건 한 눈에 봐도 알 수 있다. Mysql에 붙여서 이 캘린더를 관리하는 이유가 이것 때문이다. Mysql 에서 timestamp 객체를 생성하고, 날짜와 시간을 지정해주면 밀리초 단위로 자동으로 변환시켜주니, 실제로 복잡한 계산을 할 필요는 없다.

<?php
$db    = new PDO('mysql:host=localhost;dbname=testdb;charset=utf8', 'username', 'password');
$start = $_REQUEST['from'] / 1000;
$end   = $_REQUEST['to'] / 1000;
$sql   = sprintf('SELECT * FROM events WHERE `datetime` BETWEEN %s and %s',
    $db--->quote(date('Y-m-d', $start)), $db->quote(date('Y-m-d', $end)));

$out = array();
foreach($db->query($sql) as $row) {
    $out[] = array(
        'id' => $row->id,
        'title' => $row->name,
        'url' => Helper::url($row->id),
        'start' => strtotime($row->datetime) . '000',
        'end' => strtotime($row->datetime_end) .'000'
    );
}

echo json_encode(array('success' => 1, 'result' => $out));
exit;

DB에 캘린더를 연동하는 예제 소스이다. 소스를 보면 알겠지만 ?> 가 존재하지 않는다. 일단 여기부터 낌새를 알아차려야하는데, 앞서 말했듯이 이 소스는 제대로 작동을 안한다. 또한, class 값을 안 긁어오기에 각 일정마다 색을 입히지를 못한다. PDO가 제대로 mysql에 붙지도 않는다. 제대로 mysql을 붙였다고 하더라도 sql 쿼리가 잘못되어 이 달의 모든 일정을 출력하지 못한다. 여러모로 골 때리는 일이 아닐 수 없다. 그래서, mysqli를 이용해서 DB를 붙이고, 코드를 다시 짜는 쪽으로 방향을 잡았다.


일단, app.js에서 어떤 파일을 끌고올지 설정을 하자. 디폴트 설정은 위에서 볼 수 있듯이 event.json.php이다. 그냥 귀찮다면, index.html있는 폴더에 event.json.php 파일을 만들면 된다.

<?php
$my_db = new mysqli("localhost",아이디,비밀번호,테이블이름);
$res =mysqli_query($my_db,"SELECT * FROM Calendar");

$out = array();
while($data = mysqli_fetch_array($res)) {
	$out[] = array(
		'id' => $data['id'],
		'title' => $data['name'],
		'url' => $data['url'],
		'start' => strtotime($data['datetime']).'000',
		'end' => strtotime($data['datetime_end']).'000',
		'class' => $data['class']

);
}
echo json_encode(array('success' => 1, 'result' => $out));
exit;
?>

요로코롬하게 입력을 하면 된다. 보면 알겠지만, Calendar 테이블에, id, name, url, datetime, datetime_end, class를 긁어오는 소스이다. 즉, mysql에 Calendar 테이블에 id, name, url, datetime, datetime_end, class 컬럼이 있어야하는 건 당연한 일 일 것이다. 필자의 경우 이렇게 테이블을 잡았다.



그리고 결과는 이렇다.