Node.js를 처음 쓰기 시작했을 때 만든 개인 실험 서버다. 이름은 midnight, 패키지명은 gizrak_midnight으로 시작했다가 나중에 gizrak-lab으로 저장소 이름을 바꿨다. 2013년 첫 커밋을 시작으로 2020년까지 산발적으로 손을 댔다.
HTML5 신기능이나 Node.js 기능을 하나씩 실험해보는 공간이었다. 별도 서비스로 분리할 만큼 커지면 떼어내고, 그 전까지는 여기서 프로토타입을 돌려보는 방식이었다.
기술 스택
Express 3.x 기반 서버에 EJS 템플릿 엔진, MongoDB를 저장소로 쓰고, Socket.io로 실시간 기능을 붙였다. 배포는 Heroku에 Procfile로 올렸고, 운영 DB는 mongolab(지금의 MongoDB Atlas)을 사용했다.
{
"dependencies": {
"express": "~3.1.2",
"ejs": "~2.3.4",
"ejs-locals": "~1.0.2",
"socket.io": "~1.3.7",
"mongodb": "~2.0.45",
"textile-js": "~1.0.2",
"log4js": "~0.6.27",
"colors": "~1.1.2",
"jstoxml": "~0.2.3",
"ua-parser-js": "~0.7.9"
}
}기능들
실시간 채팅
Socket.io로 만든 채팅이다. 룸 개념을 넣어서 join/leave를 구현했다. 서버 쪽은 namespace /chat/conn으로 소켓을 분리했고, 클라이언트는 룸을 선택해서 들어가면 해당 룸에만 broadcast가 된다.
io.of('/chat/conn').on('connection', function(socket) {
socket.on('join', function(data) {
socket.join(data);
});
socket.on('message', function(data) {
socket.emit('message', data);
socket.join(data.room);
socket.broadcast.to(data.room).emit('broadcast', data);
});
});자기 메시지는 emit으로 직접 돌려주고, 같은 룸의 다른 사람들한테는 broadcast.to(room)으로 보내는 구조다.
Textile 위키
MongoDB에 페이지를 저장하고, Textile 마크업으로 작성하는 위키다. REST API로 CRUD를 구현했다.
| 메서드 | 경로 | 동작 |
|---|---|---|
| GET | /wiki/:title |
페이지 조회 |
| PUT | /wiki/:title |
페이지 저장 |
| DELETE | /wiki/:title |
페이지 삭제 |
| POST | /wiki/:title/preview |
미리보기 |
/wiki에 접근하면 /wiki/main으로 리다이렉트하고, main 페이지가 없으면 기본 내용으로 자동 생성한다. 저장할 때는 MongoDB의 save()를 써서 upsert로 처리했다.
API 엔드포인트
base64 인코딩/디코딩과 해시 함수 API를 만들어뒀다. 해시는 MD5, SHA1, SHA256, SHA512를 각각 직접 구현한 라이브러리를 붙였다.
GET /api/base64?value=hello
GET /api/hash?seed=hello
GET /api/test.json
GET /api/test.xml/api/test는 포맷 파라미터(.json, .xml, .text)에 따라 같은 데이터를 다른 형식으로 반환하는 테스트 엔드포인트다. jstoxml 라이브러리로 JSON을 XML로 변환했다.
인터셉터 미들웨어
모든 요청 앞에 interceptor.prehandle을 걸었다. 세 가지 일을 한다.
ua-parser-js로 User-Agent를 파싱해서 브라우저 이름과 버전을 로그로 남긴다- CORS 헤더(
Access-Control-Allow-Origin: *)를 응답에 추가한다 - OPTIONS 요청은 200으로 바로 응답한다 (preflight 처리)
IE 9 이하 차단 로직도 있었는데, 주석 처리해두고 결국 쓰지 않았다.
HTML5 실험 도구
/public/tools/ 아래에 HTML5 API를 하나씩 실험해본 파일들이 있다.
html5_canvas.html— Canvas 2D 드로잉html5_geolocation.html— Geolocation APIhtml5_worker.html/html5_shared_worker.html— Web Worker, Shared Workerhtml5_message_api.html/html5_channel_message.html— postMessage, Channel Messaging APIhtml5_elements.html— 시맨틱 요소들
Songbook
/public/songbook/에 기타 코드북 앱이 있다. RequireJS로 모듈 구조를 잡고, jQuery Mobile로 모바일 UI를 구성했다. 나중에 별도 프로젝트로 분리했다.
로거
log4js를 쓰면서도 직접 Logger 클래스를 만들어서 같이 두었다. log4js가 없으면 직접 만든 걸로 폴백하는 구조인데, 실제로는 항상 log4js가 있으니 의미는 없다. colors 라이브러리로 레벨별로 콘솔 색깔을 달리했다.
if (typeof(log4js) !== 'undefined') {
module.exports = log4js;
} else {
exports.getLogger = function(name) { return new Logger(name); };
}내 생각
초기 Node.js 생태계 분위기가 그대로 담겨 있다. Express 3, Socket.io 1.x, MongoDB 드라이버 2.x, Heroku 배포. 지금 기준으로는 구식인 것들이 많지만, 당시에는 이걸로 실시간 채팅이 되고 MongoDB에 데이터가 저장되는 게 신기했다.
기능을 실험하고 분리하는 방식은 지금도 유효하다. 당시 songbook이나 badook 같은 앱이 여기서 프로토타입을 거쳤다. 랩이라는 이름이 잘 어울리는 저장소였다.