앞으로 시절이 시절인 만큼, 공공 게시판에서 다양하게 의견을 주고 받을 수 없는 시절이 다가 올 수도 있습니다. 그래서 뜻이 맞는 사람들 (동지? ㅎㅎ) 끼리 모여서 이야기 할 수 있는 동호회 스러운 느낌의 게시판들이 성행할 수도 있습니다. 

포탈은 어떻게든 내용이 새어나갈 수 있지만 , 이런 동호회 기반의 커뮤니티는 그런 염려가 없습니다. 저도 하나 가입해 있어서 어려울 때 심심찮은 위로가 됩니다. 그런데 그런 작은 규모의 게시판일 때는 제로보드가 문제 없이 동작하나 사람들의 접속이 많아지면 많아질 수록 힘들어 하는 것이 느껴집니다. 따라서 다수의 접속을 처리할 수 있도록 최근 뜨겁게 인기를 끌고 있는 event-driven 방식의 웹서비스가 필요하지 않을까 해서 만들어본 기초 프로젝트 입니다. 

당연히 뼈대(skeleton)뿐 입니다. 완성도 있는 게시판들과 비교할 수가 없지만 앞으로 만들어 나갈려고 생각중입니다. 친구들 몇도 가입해서 개발할 준비가 되어 있습니다.

나중에 엄청 게시판이 흥했을 때 갖춰질 미래 예상도 입니다.

 
수평적으로 확장이 가능한 것이 특징이라고 할 수 있겠습니다. 현재는 간단한 글을 생성하고 볼 수 있습니다. (CR 만 가능합니다. UD 는 안됨 ㅎㅎ) 게다가 디자인은 형편 없습니다. 제가 워낙 미적 감각이 떨어지다 보니 게시판 에디터로는 CKEditor 를 붙였습니다.  이미지 업로드 까지 처리해 둔 상태입니다. 

소스는 https://github.com/crazia/nodejs-mongodb 여기에 올려뒀습니다. 

$ git clone git://github.com/crazia/nodejs-mongodb.git
$ cd nodejs-mongodb
$ npm install -d
$ node app.js



하시면 실제로 동작하는 것을 볼 수가 있습니다. node.js 나 npm 설치나, mongodb , redis 관련 설치법은 제 예전 블로그를 뒤져보시면 많이 나옵니다.

이글 참조

What is this? 가 이것은 무엇인가요가 아닌  this 란 무엇인가요? 라는 말 장난을 쳐 둔 포스트의 내용이 있습니다. 



객체지향 프로그래밍 (Object Oriented Programming) 언어에 보면 this 라는 애가 등장합니다. 여기서의 this 는 간단해서 Object 자신을 가르키고 있습니다. 

다만 Javascript 의 this 는 이와 달라서 class 내에 선언된다고 해도 꼭 그 class 객체를 지정하지는 않습니다. 이 알송 달송한 javascript 의 this 를 체계적으로 잘 설명한 글 입니다.


왠만하면 번역을 해서 편하게 설명할 까 했는데 너무 양이 많아서 엄두가 나지 않는군요 ㅎㅎ;; 대신 결론 부분만 조금 언급을 하자면 this 는 실행 범위 (scope) 의 영향을 받는 다는 것입니다. 

1. 새로운 실행범위를 만드는 유일한 길은 function 키워드를 이용해서 입니다. 

2. var 용법은 현재 범위에만 통용되는 변수를 만들게 해줍니다. 만약 local 범위에서 var 를 이용해서 변수를 만든다면 그 변수는 외부에서 선언된 같은 이름의 변수를 덮어버립니다. 

3. this 와 argument 를 제외한 모든 변수들은 lexical 범위를 따릅니다. (이 뜻이 뭔고하니 함수나 파일 안 같은 물리적인 범위를 말합니다)

4. this 와 argument 는 (일반적인 OOP 와는 다르게) 각각의 불려지는 Context 환경에 따라 다릅니다. 얘네들을 클로져 (closure) 안에 포함시키고 싶다면 참조 (reference) 시키는 코드를 작성해야 합니다. 

5. this 의 값은 함수가 어떻게 불려지느냐에 따라 정의됩니다. 이것을 조절하고 싶다면 call 이나 apply 를 이횽해야 합니다. 


만약 OOP 에서 사용되는 this 의 용법을 구현하려고 하면 좀 복잡한 방법을 써야 한다고 합니다. 그런데 그렇게 구현하는 방법을 고심할 바에는 javascript 의 문법에 익숙해지는 것이 낫다는 충고를 줍니다.

자세한 내용은 본문에 예제와 함께 잘 정리되어 있습니다. 

요즘 Node.js 로 프로젝트를 진행중입니다.  엄청나게 빠르고 편하게 개발할 수가 있는 좋은 개발 환경인데 단 하나의 장점이 너무 빠르게 개발해서 기획이나 클라이언트 개발과 페이스를 맞출 수 없는 단점 아닌 단점이 있습니다. 게다가 페어 프로그래밍 방식으로 일하는 친구마저 있으니 속도가 상상을 할 수 없을 만큼 빠릅니다. (최근에는 진짜 어려운 일이 아니면 페어도 그만두었습니다. 여유를 좀 가지고 일하자고 해서 ㅎㅎ )

그러다 보니 딴 짓을 하게 되더군요. 지금 열심히 만들고 있는 게, DB 에 테스트 데이터를 랜덤으로 만들어서 집어넣는 프로그램을 만들었습니다. 아주 쓸만하더군요. (생각보다 괜찮음 ㅋㅋ) 

그중에서 현재 날짜를 가지고 와서 주어진 포맷팅 형식으로 변환하여 String 타입으로 리턴하는 함수를 만들어 봤습니다. (갑자기 친구놈이 디비 스킴을 바꿔서 ..)



예전 제 포스트 에서 언급된 개인용 GIT 을 설치해서 혼자 깨작 깨작 만드는 프로젝트나, 개인 emacs 설정 파일들을 올려두고 사용하고 있었습니다. 

어쩌다 보니, 팀 단위로 작업을 하게 되었고, 개인용 GIT 만으로는 한계가 존재하더군요. (어떤 사람이 올린 소스가 잘못 됐는지 파악이 되야 '마녀 사냥'을 하지요 ㅎㅎ) 따라서 조금 찾아 봤더니

http://gitlabhq.com/

이렇게 훌륭한 오픈 소스가 있더군요. http://github.com 과 사용법이 많이 유사합니다. 팀단위로 개발할 때 꼭 설치해서 관리해 주면 좋을 것 같습니다. 혼자 프로젝트 관리 하실 때도 좋구요. 

설치한 환경은

(Ubuntu 12.10 과 Ubuntu 12.04 LTS )

에 설치했습니다. 전자는 회사, 후자는 집입니다. 두개의 차이는 거의 없었습니다. 다만 Ubuntu 12.04 LTS 의 경우에는 

$ sudo apt-get install ruby1.9.1



이처럼 명시적으로 버젼을 명시해야 최신 루비 버젼으로 설치가 되더군요. (명시해 주지 않으면 1.8.7 인가가 설치됩니다)

설치법 따라하기 

https://github.com/gitlabhq/gitlabhq/blob/master/doc/install/installation.md

귀신이 곡할 노릇이군요. 분명히 어제 위에 있는 문서가 열리고 그것을 보고 설치했는 데 지금 보니까 사러져 버렸습니다. 차이점은 unicorn 을 이용하는 방법의 차이정도라고 할 수있습니다.

유니콘 부분은 

이 부분을 참조하시면 됩니다. 
 
위에 보면 최신 버젼에 맞춰서 현행화가 잘 되어 있습니다. 순서대로 죽죽 따라서 해주기만 하면 됩니다. 
다만 몇가지 안되는 부분에 대한 것은 제가 따로 아래에 달아두겠습니다. 

루비는 위에 나온 설치법에 따르면 소스를 받아서 설치해줘야 하는데 , 그냥 패키지로 설치해도 되더군요. 

$ sudo apt-get install ruby 



Ubuntu 12.10 의 경우는 위처럼 하면 기본으로 1.9.1 이 설치됩니다. 

$ sudo apt-get install ruby1.9.1



이건 Ubuntu 12.04 LTS 입니다. 

루비 -dev 버젼을 설치해줘야 합니다. 중간에 gem install 경우에 에러가 발생하는 것을 막아줍니다. 

$ sudo apt-get install ruby1.9.1-dev


Ubuntu 12.10 버젼에서 이벤트머신이 설치 안되는 경우가 발생했었습니다. 

https://github.com/gitlabhq/gitlabhq/issues/1051

이 부분을 참조해서 해결했습니다. 
 
혹시나 ntop 어플리케이션이 PORT 3000 번을 물고 있어서 gitlab 웹서버가 스타트했다가 죽어버리는 경우가 발생할 수가 있습니다. 

$ sudo /usr/sbin/ntop -A



실행해주면 admin 패스워드가 set 됐다는 말이 뜹니다. 그때 http://localhost:3000 으로 들어가서 admin / '' (패스워드 없이) 로그인 하셔서 PORT 를 4000 으로 바꾸어 주면 해결 됩니다.  
 
 
몇년전에 ROR (Ruby on Rails)이 이슈화 될때의 유명한 ScreenCast 가 생각납니다. '15분만에 블로그' 만들기 였는데, 그 뒤로 새로운 언어나, 새로운 웹프레임워크의 강력함을 설명하기 위해서 항상 블로그를 얼마만큼 빠르게 만들어 낼 수 있는가가 그 척도가 되는 듯 합니다. 

Node.js
도 예외는 아닌듯 싶은데, 실제로도 빠르게 만들어 볼 수가 있으며, 사용하는 사람에게 프로그램을 짜는 즐거움까지 전달합니다. 

제가 예전에 정리한 포스트 에서 마지막에 실전 예제라고 소개하는 직접 블로그 만들기에 관한
 예제입니다. 소스가 예전 버젼에 맞춰져 있기 때문에 현행화를 조금 거쳤습니다. 

환경
    

    OSX Mountain Lion 
    Node.js v0.8.14 
    express 3.0.1
    jade 0.27.7


입니다. 그 외 소소한 것은 Default 를 쓴다고 해도 별 무리는 없을 듯 합니다. (OSX 에서 node.js 와 
npm 설치 방법은 여기 참조 하시면 됩니다)

1. express 를 설치해 줍니다.
    
   

 $ sudo npm install -g express 

       
express 를 전역으로 설치해 주라는 명령입니다. 전역은 별 다른 차이가 없다고 보시고 다만 명령행이 존재한다면 그 명령을 command line 상에서 사용할 수 있다는 점이 다르다고 보면 됩니다. 

2. 프로젝트를 만들어 줍니다. blog 라는 이름이 좋아보이는 군요. 

       $ cd ~/work
       $ mkdir blog
       $ cd blog
       $ express -c stylus
       $ npm install -d 


프로젝트를 만들고 연관된 하위 라이브러리들을 전부 설치해 주라는 명령입니다. 

3. nodemon 을 설치해줍니다. 

       $ sudo npm install nodemon


express 로 코딩을 하다보면 뭐 변경될 때마다 Ctrl-c 누르고 '화살표 위'를 누르는 횟수가
 비약적으로 많아집니다. nodemon 은 js 파일이 변경될 때마다 자동으로 파일을 재구동해주는 편리한 툴입니다. 손가락에 병 생기기 전에 미리 미리 깔아줍시다. 

4. 기본 템플릿으로 만들어진 것을 구동시켜 봅니다. 

       $ cd ~/work/blog
       $ nodemon app.js


구동시키면 다음과 같은 에러가 발생합니다. 

`doctype 5` is deprecated, you must now use `doctype html`
(예전하고 변경됐군요.)
       
 ~/work/blog/views/layout.jade 파일을 열어서 에러메시지처럼 변경해줍니다. 

 doctype 5 -> doctype html 


 로 변경해줍니다. 

http://localhost:3000 을 브라우져에 입력하면 아무것도 안했지만 자동으로 만들어진 내용들이 화면에 출력됩니다. 

5. 데이타베이스를 만들어 봅니다. 나중에는 Mongodb 와 연결할 것입니다. 하지만 처음에는 메모리에
 간단한 타입으로 만들어서 테스트 해 볼것입니다. 

       $ cd ~/work/blog
       $ emacs articleprovider-memory.js 



자 수많은 callback 들하고 higher-order function 들이 난무하기 때문에 정신 사납지만 조금만 익숙해지면 쉽게 볼 수가 있을 것입니다. 사실 고백하자면 Synchronous 방식에 익숙해져 있다면 Node.js 의 거의 대부분을 이루고 있는 Asynchronous 방식이 많이 혼동될 수가 있습니다. 언젠가 언급을 하겠지만 미리 소스를 읽기 쉽게 가볍게 설명을 드리면 

- Callback 함수는 소스 볼 때 잊어버리는 것이 편하다. 
  Callback 은 Asynchronous 일 때 함수의 원하는 행동이 끝나고 나서 추가로 동작하는 방식으로 구동됩니다. function A (id , callback ) ; 이라는 함수가 있다면 A 의 내용이 수행되고 그 다음에 차례로 callback 이라는 함수가 실행된다고 보는 것이 편합니다. 

- function A (id, function (err, result) {..}) ; 와 같은 형식으로 선언이 되어 있다면 
  A 를 실행하기 위해서 파라미터로 id 가 필요하고 그 결과가 err 와 result 로 나온다 라고 보시면 편하게 이해되실 수 있습니다. 

드릴 말씀이 많지만 이 부분을 기억하시고 소스를 보시는 것이 마음 편하게 이해되실 듯 합니다. 


6. 5 에서 만들어준 방식과 app.js 와 연동 시켜보는 작업을 해 줍니다. 

       app.js 를 열어서 

       var express = require('express')
          , routes = require('./routes')
 , user = require('./routes/user')
 , http = require('http')
 , path = require('path');


의 아래에 
       

       var ArticleProvider = require('./articleprovider-memory').ArticleProvider;


과 같이 추가해 줍니다. 

       // app.get('/', routes.index);


기존의 소스를 커멘트 처리 해주시고 
       
그 위에다가 
 


을 추가해 줍니다. 

부연 설명을 드리자면 GET 방식으로 들어온 요청 '/' 에 대해서 function (req, res) 을 수행하라는 내용입니다. 그리고 다시 그 안으로 들어가 보면 articleProvider.findAll 을 수행하고 난 뒤에 function (error, docs) 를 수행하라는 뜻입니다. articleProvider.findAll 의 결과는 error, docs 가 되겠지요? 이 부분을 확실하게 이해를 하는 것이 좋을 것입니다. 거의 대부분이 이런 형식으로 이루어져 있습니다. Asynchronous 방식과 higher-orders function (함수를 입력 파라미터로 넘겨 받는 방식) 그리고 Anonymous function 이 섞여있는 Node.js 의 전형적인 방식의 함수 모습입니다. 

app.get 은 URL 로 넘겨온 값을 '매칭' 하는 함수이고 그것을 실행한 결과를 function (req, res) 로
 넘기고, articleProvider.findAll 은 articleprovider-memory.js 에서 선언한 함수입니다. 저장된 데이터를 전부 가져오고 난 뒤에 파라미터로 선언된 Anonymous function 인 function (error, docs) 를 실행하고 그 결과값 - 저장된 데이터 - 가 docs 로 넘겨집니다. 

http://localhost:3000 에 다시 잘 동작하는 지 확인해 봅니다. 

7. 이제 포장 작업을 해줄 차례입니다. 

       $ emacs ~/work/blog/views/index.jade


로 기본 화면 구성을 열어줍니다. 


jade
 라고 불리는 HTML 엔진입니다. 위 처럼 써주면 대응되는 HTML 코드로 바꾸어 줍니다. 자세한 것은 따로 공부를 하시면 됩니다. (저도 뭐 HTML 은 고수가 아니라서..)

extends layout 이라는 것은 layout.jade 로 부터 확장한다는 뜻입니다. 기초적인 설정은 전부 그곳에
 있다고 해도 과언이 아니겠지요? 

       $ emacs ~/work/blog/views/layout.jade 


로 열어줍니다. 



body 부분에 쓰여져 있는 block content 가 index.jade 의 block content 와 대응되리라는 것을 쉽게
 알 수가 있습니다. (응?..)

8.
jade 파일이 준비가 됐다면 app.js 에서 바꾸어 줄 필요가 있습니다. 


여기서 res.send 는 기본적인 내용을 전달하는 것이므로 (그래서 json 기반의 app 서버 작성시 편합니다) 렌더링 해주는 함수로 변경해줘야 합니다. 위 내용을 


index.jade 를 기본으로 삼되, title 에는 'Blog' 값을 넘기고 , articles 에는 docs 를 넘기라는
 내용입니다. 

9. 이쁘장 (?) 하게 바꾸어줄 시간입니다. (It's CSS Time!!)

귀찮으니까 나중에 쓸 내용까지 전부 CSS 로 밀어 넣기로 합니다. 참 이 내용은 stylus 라는
 라이브러리를 이용합니다. 

       $ emacs ~/work/blog/public/stylesheets/style.styl





인덴테이션이 중요합니다. 이 파일을 작성하면 이 파일에서 style.css 를 자동으로 생성하는 것 같습니다. (자세히는 모르겠음..)
        
여기까지 작성이 완료 됐다면 http://localhost:3000 으로 확인 바랍니다. 색.. 색깔이 나올것입니다. 

10. 새로 글 작성하는 기능을 추가해 보겠습니다. MVC 모델에 따라서 , M 은 이미 작성되어 있고
 (articleprovider-memory.js) 로 , V 에 해당하는 부분을 작성해 줍니다. 

$ emacs ~/work/blog/views/blog_new.jade



음.. 암호 같지요? 저한테도 암호 같습니다. 당분간 외워서 하는 수밖에 없을 듯합니다. 

11. 10 에 대응되는 C (controller) 부분을 추가해 줍니다. 2개의 라우팅 부분을 추가해 줍니다. 

$ emacs ~/work/blog/app.js



app.get 은 GET 방식 , app.post 는 POST 방식입니다. app.get 방식으로 '/blog/new' 로 브
라우져에서 접속하면 blog_new.jade 를 렌더링 하고 , 그 렌더링 페이지에서 내용을 입력하고 Send 버튼을 클릭하면 articleProvider.save 함수를 호출하고 res.redirect 함수로 '/' 에 돌아간다는 내용입니다. http://localhost:3000/blog/new 로 이동해서 테스트 해보기 바랍니다. 

12. 이제 mongodb 를 붙일 시간입니다. 지금까지 만들어온 메모리 버젼은 소스 변경하면 (nodemon 이
 알아서 app.js 를 재구동하니..) 작성하고 테스트 한 내용이 날라가버립니다. 그런 귀찮음을 제거하고자 mongodb 를 연동하는 것입니다. 

먼저 mongodb 모듈을 설치해야 합니다. . 

$ emacs ~/work/blog/package.json




에 위와 같이 "mongodb": "*" 를 추가해 주고 

$ cd ~/work/blog
$ npm install -d 


를 실행 합니다. 
 

13. 이제
mongodb 와 연결해서 포스트 관리해 주는 articleprovider-mongodb 를 제작할 시간입니다.

$ cd ~/work/blog
$ emacs articleprovider-mongodb.js 




14. memory 에서 articleprovider-mongodb 로 바꼈기 때문에 연관된 부분을 app.js 에서 수정할 필요가 있습니다. 

$ cd ~/work/blog
$ emacs app.js


아래와 같이 변경 해줍니다. 

var ArticleProvider = require('./articleprovider-mongodb').ArticleProvider;
//var ArticleProvider = require('./articleprovider-memory').ArticleProvider;


 
메모리를 로딩하는 부분을 comment 처리해주고 그 위로 내용을 추가해 줍니다. articleprovider 를 mongodb 기반으로 바꾸어 준다는 내용입니다. 

var articleProvider = new ArticleProvider('192.168.0.87', 27017);
// var articleProvider = new ArticleProvider();


이 내용은 192.168.0.87 서버에 mongodb 가 띄어져 있고 27017 port 로 접속한다는 이야기
 입니다. 제 경우는 머신이 두대 있을 경우에 쓰는 방법이고 대부분 한 서버에서 같이 동작시킬 때는 192.168.0.87 대신 localhost 라고 입력해 주시면 됩니다. 

또 저와같이 다른 머신에 mongodb 데몬을 띄워논 경우에는 그 머신의 mongodb.conf 파일을 열어서 bind_ip 부분을 comment 처리 하거나 

bind_ip = 192.168.0.* 


으로 같은 대역대에 있는 접속을 허용하는 식으로 변경해 주어야 외부에서 접속이 됩니다. 물론 내부는 세팅해 줄 필요가 없습니다. mongodb.conf 파일은 ubuntu 경우에는 /etc/mongodb.conf 존재합니다. 

15. index 페이지에서 개별 개별 포스트를 클릭했을 때 , 내용을 상세하게 보여주는 페이지 부분에 대한 작성 입니다. 

먼저 V (views) 부분에 대한 처리입니다. 

$ emacs ~/work/blog/views/blog_show.jade



jade 는 꼭 시간을 들여서 익히셔야 합니다. (저도..) 웹 개발이 빨라집니다. 

16. index 페이지에서 개별 개별 포스트를 클릭했을 때 , C (controller) 에 해당하는 라우팅 하는
 부분을 app.js 에 추가해줍니다. 

$ emacs ~/work/blog/app.js




http://localhost:3000 으로 화면을 띄우고 개별 Post 를 클릭하셔서 제대로 동작되는 지 확인하시면 됩니다. 

17. 이제 개별 Post 에 댓글 기능을 추가해 보겠습니다. 16 에서 열어둔 파일에 마저 작업을 해
 줍니다. POST 방식으로 댓글을 Post 에 추가하는 로직입니다. 

$ emacs ~/work/blog/app.js



을 추가해 줍니다. View 에 해당하는 것은 언제 추가해 주냐고요? 15 에서 추가해 줬습니다. 자 이제 모든 것이 완성 됐습니다. http://localhost:3000 에서 확인해 주시기 바랍니다. 

원문 은 여기서 확인 가능합니다. 구버젼 node.js 와 express 로 되어 있어서 현행화 이슈가 있었기에 제가 정리하는 김에 현행화를 한 것입니다. 

제가 현행화한 모든 소스는 https://github.com/crazia/nodejs-mongodb 여기에서 다운 받을 수
 있습니다. 

$ cd ~/work
$ git clone git://github.com/crazia/nodejs-mongodb.git 
$ cd nodejs-mongodb
$ npm install -d 
$ node app.js 


하시면 쉽게 완성된 형태를 따라하실 수 있습니다. 

CLisp 이나 C++ 에서는 쉽게 설정하는 함수 인자 기본 값 (Default) 설정하는 방법에 관한 예제입니다. 일단 쉽게 설정하는 방법이 없는 듯 합니다. 

1 user=> (defn bar
2          ([a b]   (bar a b 100))
3          ([a b c] (* a b c)))
4 #'user/bar
5 user=> (bar 5 6)
6 3000
7 user=> (bar 5 6 2)
8 60

이 와 같은 식으로 가장 인자 수가 많은 함수를 내부에서 호출하는 형식으로 꾸며줍니다. 그 외에 다른 방식으로는 :keyword 형식으로 호출하는 등등이 있으나 위에 쓰여지는 방법이 그나마 다른 언어(Language)에 익숙한 방법이라 사료됩니다. 

defn 설명 페이지 


Parallelism Versus Concurrency

Lest our discussion of concurrency and parallelism lead you to think they are the same thing, let’s disentangle the two notions.

Concurrency is the coordination of multiple, usually interleaved threads of execution that are accessing or modifying some shared state.

Parallelism involves state as well, but usually in the inverse. Being an optimization technique used to efficiently utilize all of the available resources (usually computational, but sometimes other resources, like bandwidth) to improve the performance of an operation, approaches to parallelization generally aim to maximize the window of exclusive access to state (or, often, chunks of state) so as to minimize coordination overhead. Rather than involving interleaved threads of execution, the multiple evaluations of a parallelized operation run simultaneously—sometimes on different CPU cores, other times on different physical machines entirely.

-- Clojure Programming 책 중에서 .. 


쉽게 설명하자면 

'동시성' 은 공유되는 자원에 대한 접근이나 변경을 주도하는 쓰레드들을 배치하는 작업에 관한 용어이고 

'병렬성' 은 공유될 수 있는 자원에 대한 최적화된 사용에 관한 용어입니다. 보통 쓰레드 배치나 이런 것은 당연히 적용하지만 잡-스케쥴링 (Job - scheduling) 을 통해서 다중 CPU 일 경우 각각의 CPU 나 코어 에서 작업을 분배시켜서 돌리게 하거나 또는 아예 다른 기계에서 작업을 돌리게 한다던지 와 같은 오히려 작업 분배에 관한 용어로 쓰일 때가 많습니다. 



 

NodeJS 는 예전부터 C/C++ 이 차지하던 위치를 (최근에 Python 이 차지한 것 같은 이야기가  있습니다) 차지한 것 같은 언어 입니다. (C/C++ 에 비하여) 어렵지도 않고 아주 쉽고 편하게 서버 어플리케이션을 만들 수 있는 쉬운 언어 입니다. 그 쉬운 NodeJS 를 살펴볼 일이 있어서 잠깐  살펴보게 됐습니다.

 설치법

여러가지 해줘야 하는 것이 있지만, 우리는 Ubuntu 를 쓰지 않겠습니까? 초 간단하게 설치가 가능합니다. (당연히 Mint 도 동일합니다)
   
    sudo apt-get install python-software-properties
    sudo apt-add-repository ppa:chris-lea/node.js
    sudo apt-get update
    sudo apt-get install nodejs npm   


 구동 테스트

간단하게 파일을 한개 편집해줍니다.

   
$ emacs example.js

그리고 다음과 같은 내용을 써 줍니다.
	
    var http = require('http');

    http.createServer(function (request, response) {
    response.writeHead(200, {'Content-Type': 'text/plain'});
    response.end('Hello World\n');
    }).listen(8124);

    console.log('Server running at http://127.0.0.1:8124/');

이제 다 됐습니다. 바로 확인해 보기로 합니다.

 
   $ node example.js

브라우져에서 http://localhost:8124 를 입력해서 제대로 동작하는지 테스트 합니다.

사실 이 정도 쉽게 해주는 방법은 많이 나왔지만, 이 언어가 각광 받는 이유는 여러가지가 있겠습니다. 일단 가볍고, 문법 자체가 JavaScript 기 때문에 배우기도 쉽고 (이거 될까? 하는게 다 되는게 자바 스크립트 입니다 ㅎㅎ) 그리고 만들어진 결과물 자체의 효율도 좋습니다.



 프로젝트를 만들다 보면 너무나 당연하게 디펜던시를 가지는 프로젝트가 생기게 됩니다. 메이븐은 기본적으로 디펜던시를 가져다가 프로젝트를 만들게 되는데 이를 수동으로 해야할 필요가 생긴다면  어떻게 할 것인가? 하는 문제가 있습니다. 즉 

   

    A : 실행파일이 만들어지는 프로젝트 
    B : A 가 참조하는 프로젝트
    C : B 가 참조하는 프로젝트 

    A - 
      - B -
          - C

    

이런식으로 아마 만들어지는 것이 지금까지의 일반적인 방법일 것입니다. 그러나 메이븐에서 관리를 하게 된다면 조금 다른 식이 됩니다. 

   

P (parent) 가 존재해서 

    P - A
      - B
      - C 



같은 식으로 프로젝트가 존재하게 됩니다. 그리고 각각은 pom.xml 만 수정해서 프로젝트를 관리할 수가 있습니다. 

    그래서 수정해야 할 부분을 따라하기로 만들어 보기로 합니다. 

    1. 부모 (parent) 프로젝트 생성 
 


$ mvn archetype:generate

Choose a number or apply filter (format: [groupId:]artifactId, case sensitive contains): 186: 186
Choose org.apache.maven.archetypes:maven-archetype-quickstart version: 
1: 1.0-alpha-1
2: 1.0-alpha-2
3: 1.0-alpha-3
4: 1.0-alpha-4
5: 1.0
6: 1.1
Choose a number: 6: 6
Define value for property 'groupId': : upper
Define value for property 'artifactId': : top
Define value for property 'version':  1.0-SNAPSHOT: : 1.0.0
Define value for property 'package':  upper: : 
Confirm properties configuration:
groupId: upper
artifactId: top
version: 1.0.0
package: upper
 Y: : Y



186 번을 선택하시고 나머지 것들은 대충 입력해서 만들어 줍니다. 제 경우에는 

     

       groupId: upper
       artifactId: top
       version: 1.0.0


 와 같이 만들어 줬습니다. 

    2. 부모 프로젝트의 pom.xml 변경 
       
       

       <groupId>upper</groupId>
       <artifactId>top</artifactId>
       <version>1.0.0</version>
       <packaging>pom</packaging>


      <packaging> 태그의 내용을 pom 으로 바꿉니다.


    3. 하위 프로젝트 생성 
      1. 에서 생성한 프로젝트의 위치로 이동합니다.

$ cd $PARENT-BASE
$ mvn archetype:generate
 
Choose a number or apply filter (format: [groupId:]artifactId, case sensitive contains): 186: 186
Choose org.apache.maven.archetypes:maven-archetype-quickstart version: 
1: 1.0-alpha-1
2: 1.0-alpha-2
3: 1.0-alpha-3
4: 1.0-alpha-4
5: 1.0
6: 1.1
Choose a number: 6: 6
Define value for property 'groupId': : upper
Define value for property 'artifactId': : project-a
Define value for property 'version':  1.0-SNAPSHOT: : 1.0.0
Define value for property 'package':  upper: : 
Confirm properties configuration:
groupId: upper
artifactId: project-a
version: 1.0.0
package: upper
 Y: : Y

       
다음 프로젝트 생성 

$ mvn archetype:generate

Choose a number or apply filter (format: [groupId:]artifactId, case sensitive contains): 186: 186
Choose org.apache.maven.archetypes:maven-archetype-quickstart version: 
1: 1.0-alpha-1
2: 1.0-alpha-2
3: 1.0-alpha-3
4: 1.0-alpha-4
5: 1.0
6: 1.1
Choose a number: 6: 6
Define value for property 'groupId': : upper
Define value for property 'artifactId': : project-b
Define value for property 'version':  1.0-SNAPSHOT: : 1.0.0
Define value for property 'package':  upper: : 
Confirm properties configuration:
groupId: upper
artifactId: project-b
version: 1.0.0
package: upper
 Y: : Y


그리고 다음 프로젝트도 생성해줍니다. 
       

$ mvn archetype:generate
 
Choose a number or apply filter (format: [groupId:]artifactId, case sensitive contains): 186: 186
Choose org.apache.maven.archetypes:maven-archetype-quickstart version: 
1: 1.0-alpha-1
2: 1.0-alpha-2
3: 1.0-alpha-3
4: 1.0-alpha-4
5: 1.0
6: 1.1
Choose a number: 6: 6
Define value for property 'groupId': : upper
Define value for property 'artifactId': : project-c
Define value for property 'version':  1.0-SNAPSHOT: : 1.0.0
Define value for property 'package':  upper: :   
Confirm properties configuration:
groupId: upper
artifactId: project-c
version: 1.0.0
package: upper
 Y: : Y


각각에 맞춰서 생성해줍니다. 

이렇게 하면 자동으로 부모 프로젝트의 pom.xml 이 변경됩니다. 

 

 <modules>
    <module>project-a</module>
    <module>project-b</module>
    <module>project-c</module>
  </modules>



하단에 위와 같은 내용이 추가 됐습니다. 그리고 project-a 의 pom.xml 을 열어보면 

 

<parent>
    <groupId>upper</groupId>
    <artifactId>top</artifactId>
    <version>1.0.0</version>
  </parent>


와 같은 보통때는 안보이는 내용이 추가 됐습니다. 다시 자세히 설명하자면 부모 프로젝트의 <package> 내용을 pom 으로 바꾸고 <modules> 내용을 추가하고 , 추가되는 프로젝트의 pom.xml 에 <parent> 관련된 부분을 추가 해주면 복합 모듈 프로젝트로 변경되는 것입니다. 

.
├── pom.xml
├── project-a
│   ├── pom.xml
│   └── src
│       ├── main
│       │   └── java
│       │       └── upper
│       │           └── App.java
│       └── test
│           └── java
│               └── upper
│                   └── AppTest.java
├── project-b
│   ├── pom.xml
│   └── src
│       ├── main
│       │   └── java
│       │       └── upper
│       │           └── App.java
│       └── test
│           └── java
│               └── upper
│                   └── AppTest.java
├── project-c
│   ├── pom.xml
│   └── src
│       ├── main
│       │   └── java
│       │       └── upper
│       │           └── App.java
│       └── test
│           └── java
│               └── upper
│                   └── AppTest.java
└── src
    ├── main
    │   └── java
    │       └── upper
    │           └── App.java
    └── test
        └── java
            └── upper
                └── AppTest.java

31 directories, 12 files


프로젝트의 트리 내용입니다. 


   4. 하위 프로젝트 끼리 연결 시키기 

project-b 는 project-c 를 참조하고 project-a 는 project-b 를 참조합니다. 그렇다면 각각의 project-a 와 project-b 의 pom.xml 을 열어서 

project-a 의 pom.xml 에는 
   

   <dependency>
      <groupId>upper</groupId>
      <artifactId>project-b</artifactId>
      <version>1.0.0</version>
    </dependency>


 을 추가해 주고 

 project-b 의 pom.xml 에는 
 

  <dependency>
      <groupId>upper</groupId>
      <artifactId>project-c</artifactId>
      <version>1.0.0</version>
    </dependency>


 만 추가해 주면 됩니다. 물론 이 내용들은 <dependencies> 태그 안에 위치해야 하는 것은 기본입니다. 


결론적으로 말해서 maven 은 초기의 거리낌이 느껴지는 것과는 달리 순수하게 command-line 으로 관리할 수 있는 프로젝트 관리 모듈입니다. 저 같이 이클립스보다는 이맥스(emacs) 가 손에 익은 사람들이 자바 프로젝트를 깔끔하게 관리할 수 있게 많은 기능들을 제공합니다. 
    

힘들게 저번 포스트 에서 정리를 했더니  더 쉬운 방법이 있다고 알려줘서 정리를 해 둡니다. (시작할 때 왜 알려주지 않은건가여.. )

저번과 거의 동일 합니다.

1. 아파치 설치하기 

$ sudo apt-get install apache2


2. 톰캣 설치하기 

$ sudo apt-get install tomcat7 tomcat7-docs tomcat7-admin tomcat7-examples


  설치해두면 언젠가는 쓸모가 있으니 한꺼번에 설치해줍니다. 

3. 제대로 설치됐는지 확인해보기 

   http://localhost  와 http://localhost:8080 

  으로 페이지가 제대로 뜨는지 확인해 줍니다. 만약 페이지가 제대로 뜬다면 apache2 와 tomcat7 은 제대로 설치된 것입니다. 

여기까지는 동일하고 여기서부터 살짝 바뀝니다.

4. 톰캣 에서 커넥터와 연결시키기 

$ sudo emacs /var/lib/tomcat7/conf/server.xml 


   에서 


       <!-- Define an AJP 1.3 Connector on port 8009 -->
       <!--
       <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
       -->


   로 되어 있는 부분에서 주석을 제거해서 

 

     <!-- Define an AJP 1.3 Connector on port 8009 -->
       <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />


   로 변경합니다. 이것은 포트 8009 로 날라오는 프로토콜(protocol)이 AJP/1.3 인 것은 8443 포트로 넘기라는 것입니다.  8443은 톰캣 서버가 처리를 하는 포트라고 보시면 됩니다.   


5.  Proxy_AJP 모듈 활성화 시키기

소개해주신 분의 말씀으로는 아파치와 톰캣을 너무 자주 연결시키다 보니 아파치에 아예 포함되서 나오게 됐다고 합니다.

 $ sudo a2enmod proxy_ajp  



이 부분이 저번 포스트에서 언급했던 커넥터 부분과 동일한 기능을 하는 부분입니다.  

6. 아파치 에서 톰캣 연결시키기 

$ sudo emacs /etc/apache2/sites-available/default 


   이 부분에 대한 언급이 없어서 제일 어려웠던 부분입니다. 위의 파일을 열어서 


  

       DocumentRoot /var/www
   <Directory />
     Options FollowSymLinks
 AllowOverride None
   </Directory>
   <Directory /var/www/>
Options Indexes FollowSymLinks MultiViews
AllowOverride None
Order allow,deny
allow from all
  </Directory>


   인 부분을 찾아서 


DocumentRoot /var/lib/tomcat7/webapps/ROOT
<Directory />
Options FollowSymLinks
AllowOverride None
</Directory>
<Directory /var/lib/tomcat7/webapps/ROOT/>
Options Indexes FollowSymLinks MultiViews
AllowOverride None
Order allow,deny
allow from all
</Directory>

        ProxyPass /servlet/ ajp://localhost:8009/servlet/
        ProxyPassMatch ^/.*\.(jsp|do)$ ajp://localhost:8009/

 로 바꾸어 줍니다. 즉 /var/www 을 /var/lib/tomcat7/webapps/ROOT 로 바꾸어 주는 것입니다. 그리고 아래쪽에 

ProxyPass /servlet/ ajp://localhost:8009/servlet/
ProxyPassMatch ^/.*\.(jsp|do)$ ajp://localhost:8009/

를 추가해줍니다. 부연 설명을 하자면 아파치(apache)가 바라보고 있는 DocumentRoot 와 톰캣이 바라보고 있는 webapps/ROOT 를 같은 곳을 바라보게 해주는 것입니다. 그리고 맨 아래에 추가해 준것은 jsp 와 do 로 끝나는 파일은 ajp 프로토콜로 8009 번 포트로 리다이렉션 해주라는 것입니다. 

 
7. 테스트페이지를 만들어 봅니다. 

$ sudo emacs /var/lib/tomcat7/webapps/ROOT/hello.jsp 


   내용은 

  

<HTML>
   <BODY>
   Hello!  The time is now <%= new java.util.Date() %>
   </BODY>
   </HTML>


  로 채우고 저장합니다. 

8. 톰캣과 아파치 재시작 (Restart)

$ sudo /etc/init.d/tomcat7 restart
  $ sudo /etc/init.d/apache2 restart



9. 브라우저에서 
   
    http://localhost  와 http://localhost/hello.jsp 로 테스트 해봅니다.


 

+ Recent posts