개발자의 시간 15분
가벼운 일은 작고 빠르게, 무거운 일은 깊고 신중하게 실행하기
사무실에 회의를 위한 공간이 몇 개 있다. 조직이 많아지고 회의도 많아지니 회의 공간을 예약하고 예약 현황을 공유할 필요가 생겼다. 여러 가지 방법이 있을 텐데 일단 구글 캘린더를 만들어 운영했다. 하지만 이런저런 자잘한 불편함이 해결되지 않았다. 이 문제를 마주한 사람이 개발자라면 어떤 생각을 하게 될까?
그냥 만들까?
필요한 핵심 기능은 어떤 공간을 "누가 언제부터 언제까지 무슨 용도로 사용할 것입니다."라는 내용을 불특정 다수가 쉽게 볼 수 있도록 하는 것이다. 그 외의 기능은 필요 없다. 단지 그것 뿐.
나는 15분의 시간을 쓰기로 했다.
"회의실 예약 보드"를 만들기 위해 필요한 것을 추려본다.
1번은 캘린더의 Day 뷰 형태가 떠오른다. 캘린더 컴포넌트를 사용하면 될 것 같다. 검색... 고민 없이 구글이 알려준 첫 번째 UI 컴포넌트를 사용하기로 했다. http://fullcalendar.io 많이들 사용하는 것 같다. 뭐, 많이 사용하지 않아도 상관없다. 필요한 기능이 잘 동작만 하면 된다.
사내 인프라를 사용해도 되겠으나 그럴 것도 없는 일이라 생각했다. 그렇다고 돈을 써서 할 만한 일도 아니라 결정했으니 무료 호스팅 서비스를 이용하도록 하자. 무료 호스팅은 종류도 많고 형태도 다양하다. 요구사항은 내가 만든 코드를 - nodejs를 사용할 것이다 - 운영할 수 있으면 된다. 무료로. 빠르지 않아도 된다. 만들 앱이 크기가 크지도 않기 때문에 많은 용량이 필요하지도 않다. 설정이 불편해서도 안된다. 시간이 많이 안 쓰기로 했으니까 말이다.
https://www.heroku.com를 사용하기로 결정했다. 익숙하기도 하고 이런 미션을 달성하기에 최적화되어있다. Heroku 계정을 만들고 설정을 위해 Heroku Toolbelt을 설치만 하면 된다.
저장소는 파일이 좋을까? 다루기 까다롭다. 다루기 좋은 DB 형태면 좋겠다. RDB가 좋을까? 이것도 귀찮다. 그냥 JSON 때려 넣을 수 있는 형태면 딱 좋겠다. MongoDB 가 익숙하니 고민 없이 선택한다.
DB를 설치하려 하면 이 또한 수 많은 시간과 비용이 필요해진다. 역시 무료를 알아보자. 구글이 알려준다.
https://www.mongolab.com 의 무료 플랜은 무려 500MB 의 스토리지를 준다. 500Mb면 몇 개의 일정을 저장할 수 있을까? 엄청 많겠지?
5분 만에 필요한 것이 준비됐다. 똑같이 따라 한다면 아마도 회원가입하는데 시간을 가장 많이 쓸 것 같다.
시간이 없다. 터미널을 열자.
$ mkdir fast-board && cd fast-board && git init && npm init
fast-board $ npm install --save express body-parser mongoose
에디터를 열어서 index.js를 만든다. 이 녀석이 서버가 될 것이다.
var express = require('express');
var mongoose = require('mongoose');
var app = express();
var bodyParser = require('body-parser');
var db = mongoose.connection;
mongoose.connect('mongodb://id:pw@xxx.mongolab.com:111111/fastboard');
var eventSchema = mongoose.Schema({
title: String, start: String, end: String, owner: String, password: String
});
var Events = mongoose.model('event', eventSchema);
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(express.static('public'));
// 모든 이벤트 목록 반환
app.get('/events', (req, res, next) => {
Events.find({}, (err, collection) => {
res.send(collection);
});
});
// 이벤트 생성
app.post('/events', (req, res, next) => {
(new Events(req.body)).save( (err, event) => res.send(event));
});
// 서버 실행
app.listen(process.env.PORT || 3000, () => console.log('ready!'));
이제 UI 가 필요하니 HTML을 만들어야 한다. HTML이 위치할 public 디렉터리를 만든다.
fast-board $ mkdir public
편집기로 index.html 파일을 만들고 편집한다. 사용할 컴포넌트들은 설치할 필요는 없다. 요즘 세상에...
<link href='http://fonts.googleapis.com/css?family=Lato:100,400,700' rel='stylesheet' />
<link href='//cdnjs.cloudflare.com/ajax/libs/fullcalendar/2.6.0/fullcalendar.min.css' rel='stylesheet' />
<link href='//cdnjs.cloudflare.com/ajax/libs/fullcalendar/2.6.0/fullcalendar.print.css' rel='stylesheet' media='print' />
<script src='//cdnjs.cloudflare.com/ajax/libs/moment.js/2.9.0/moment.min.js'></script>
<script type='text/javascript' src='//ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js'></script>
<script src='//cdnjs.cloudflare.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js'></script>
<script src='//cdnjs.cloudflare.com/ajax/libs/fullcalendar/2.6.0/fullcalendar.min.js'></script>
HTML 본문을 구성하고...
<h1>Z동 회의실 캘린더</h1>
<div id='calendar'></div>
캘린더 UI를 위한 Javascript 코드를 작성한다.
$(document).ready(function() {
$.get('/events').done(function(data) {
$('#calendar').fullCalendar({
header: { left: 'today prev,next', right: 'agendaDay,agendaWeek,month' },
events: data,
select: function(start, end) { // 이벤트 생성 호출 }
});
});
});
이제 코딩은 끝났다. 서버에 올려보자.
일단 서버를 만들고...
fast-board $ heroku apps:create fast-board
fast-board $ git push heroku master
fast-board $ heroku open
이제 브라우저에서 실행되는 - 위와 같이 한다면 주소는 fast-board.herokuapp.com 이 될 것이다 - 앱을 캘린더 앱을 볼 수 있을 것이다.
스타트업에 있다 보면 시간과 효율이 얼마나 중요한지 매일 매일 느끼게 된다. 일의 범위도 서비스 개발에만 국한되지 않는다. 회사에서 일어나는 모든 종류의 일에 해당된다. 이런 일들의 비효율을 없애는 활동에 많은 부분 소프트웨어적 활용 능력은 시간을 줄이고 효율을 높여줄 수 있다. 소프트웨어적 활용 능력이 이제는 엑셀이나 파워포인트 등을 잘 활용하는 정도에 머물지 않는 시대가 되었다. 간단한 프로그래밍을 할 수 있는 정도로 개념을 확장시킬 수 있다면 많은 비효율을 효과적으로 제거해 나갈 수 있을 것이다.
ps: 위 상황을 따라하기 위해선 git, nodejs 등이 이미 설치되어 있어야한다. 이벤트를 저장하는 코드 등은 생략되어 있다. 그 코드 자체도 간단하기도 하지만 fullcalendarjs의 API 문서에 충분히 설명되어 있기도 해서 생략했다. 따라서 이 글의 내용만 그대로 복붙한다 해서 동작하진 않는다.