잊지 않겠습니다.

nodejs (express) + mongodb in Heroku

전부터 알고 있던 cloud base 개발 환경인 heroku를 한번 사용해보기로 했습니다. 일단 nodejs로 만들어진 application 이고, express와 mongodb를 사용하고 있는데. 이와 같은 환경을 무료로 제공해주는 곳 중에서 가장 유명하고, 한번 써보고자 하는 욕구가 강한 서비스여서 접근해보기로 했습니다.

먼저, 배포할 application의 구성입니다.

  • nodejs
  • express
  • mongodb
  • google OAuth 이용

nodejs + mongodb application deploy

Heroku service 가입

email을 등록시켜주면, 가입신청 확인 mail이 날라옵니다. 클릭후, password 설정만 하면 완료됩니다.
완료 후, https://dashboard-next.heroku.com/ 에서 Management Account -> Billing에서 신용카드 정보를 넣어두는 것이 좋습니다. 추후 설치할 addon에서 신용카드 정보가 없으면 진행할 수 없습니다.

Heroku toolbelt 설치

https://toolbelt.heroku.com/ 에서 환경에 맞는 toolbelt를 설치합니다. 저는 지금 linux를 설치하고 있기 때문에, linux 용 toolbelt를 설치한 기준으로 아래 글을 계속 이어가도록 하겠습니다.

설치후, heroku cmd를 사용할 수 있습니다.

Heroku toolbelt 인증 정보 + ssh public key 전송

heroku toolbelt를 설치하면 heroku cmd를 사용해서 인증정보를 입력합니다. heroku service에 가입한 email과 password를 넣어주면 됩니다. 그리고 ssh public key를 heroku에 등록시켜 이제는 heroku email/password가 아닌 ssh key인증을 이용해서 heroku cmd를 사용할 수 있습니다.

$> heroku login
Enter your Heroku credentials.
Email: 
Password:
Could not find an existing public key.
Would you like to generate one? [Yn]
Generating new SSH public key.
Uploading ssh public key /Users/adam/.ssh/id_rsa.pub

Application의 준비

기본적으로 heroku toolbelt를 이용한 application의 배포는 git를 이용합니다. local 또는 http://github.com 에서 제공되는 git repository에 project가 등록되어 있어야지 됩니다.

java의 pom.xml이나 build.gradle과 같은 기능을 하는 것이 package.json 입니다. 여기에 모든 dependency가 기록되어있어야지 됩니다.

그리고, scripts 항목의 start에 반드시 application의 실행 node command를 넣어줘야지 됩니다. 다음은 scripts 항목의 예시입니다.

  "scripts": {
    "start": "node app.js",
    "test": "grunt jasmine"
  }

개인적으로 이부분에서 실수를 한것이, 제 개발환경이 express가 global로 설치가 되어있습니다. 그래서 express가 package.json에 등록되어있지 않았습니다. 이렇게 되는 경우, dependency 문제로 인하여 application이 정상적으로 동작하지 않습니다. 반드시 package.json 정보만으로 application이 구동될 수 있어야지 됩니다.

git repository와 heroku repository 간의 연결

git repository directory안에서 다음 command를 실행합니다.

$>  heroku create --http-git
Creating sharp-rain-871... done, stack is cedar-14
http://sharp-rain-871.herokuapp.com/ | https://git.heroku.com/sharp-rain-871.git
Git remote heroku added

위 command의 결과, git는 remote repository를 하나 더 만들게 됩니다. 이 remote repository에 우리가 appliation을 배포하면 heroku에서 running되는 application을 구성하게 되는 것입니다.

위 console 창의 결과는 sharp-rain-871이라는 application의 이름을 갖게 됩니다. 이 이름은 unique 한 결과이며, 변경을 원하는 원하는 경우, heroku apps:rename 명령어를 통해 변경할 수 있습니다. 모든 action은 위 git repository directory 안에서 실행되어야지 됩니다.

git repository에서 heroku repository로 deploy

git repository directory안에서 다음 command를 실행합니다.

$> git push heroku master
Counting objects: 7, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 386 bytes | 0 bytes/s, done.
Total 3 (delta 2), reused 0 (delta 0)
remote: Compressing source files... done.
remote: Building source:
remote: 
remote: -----> Node.js app detected
remote: -----> Requested node range:  0.10.33
remote: -----> Resolved node version: 0.10.33
remote: -----> Downloading and installing node
remote: -----> Restoring node_modules directory from cache
remote: -----> Pruning cached dependencies not specified in package.json
remote: -----> Exporting config vars to environment
remote: -----> Installing dependencies
remote:        
remote:        > sadari-app@1.0.0 postinstall /tmp/build_efb71b073a7c6b8520ad4613bd4ca2a3

deploy가 마치면 heroku open command를 통해서 browser를 이용해서 application이 구동되고 있는 것을 확인할 수 있습니다.

heroku는 cloud platform입니다. instance의 갯수를 제어할 수 있습니다. instance를 1개 이상 사용하는 경우, 비용이 발생하기 때문에 주의가 필요합니다.

$> heroku ps:scale web=1

bower를 이용한 javascript module dependency 처리

bower를 이용하는 경우, javascript를 각각의 repository에서 다운 받아 처리하게 됩니다. 따라서 bower components의 경우, repository에 올라가지 않는 것이 원칙입니다. 따라서, heroku에 배포된 application은 bower components가 하나도 없게 됩니다.

개발환경에서 bower install을 통해서 bower components들을 얻어주는 것과 같이 heroku에서도 이와 같은 action이 필요하게 됩니다. heroku의 nodejs 환경에는 아무런 환경이 없다고 생각해야지 됩니다. 이를 해결하기 위해서 bower 자체를 dependency에 추가해야지 됩니다.

npm install bower --save

bower를 추가후, package.json 파일의 scripts 항목에 다음을 추가한 후, heroku에 배포를 다시 진행합니다.

  "scripts": {
    "start": "node app.js",
    "test": "grunt jasmine",
    "postinstall": "bower install"
  },

이제 application을 정상적으로 설치하는 과정이 모두 마쳐졌습니다.

mongodb 설치

제가 만든 application은 mongodb를 사용하고 있습니다. mongodb는 heroku에서 addon 형태로 제공하고 있습니다. 500M 까지는 무료로 사용할 수 있으니, 아주 작은 application의 경우에는 언제나 무료로 사용할 수 있습니다. compose mongoDb에 대한 소개는 다음 URL에서 확인 가능합니다. https://devcenter.heroku.com/articles/mongohq

mongodb addon의 설치는 다음과 같습니다.

$> heroku addons:add mongohq

여기서, billing information이 설정되어 있지 않으면 addon의 설치는 진행되지 않습니다. 주의가 필요합니다.

mongodb 연결

compose mongodb를 설치하면, ENV에서 db connection url을 확인할 수 있습니다. config 값의 확인은 다음과 같습니다.

$> heroku config
=== my-sadari Config Vars
MONGOHQ_URL: mongodb://heroku:Xucs9HmJrBKBr6bPkO6CM044_G6oVv5gV0bN0dxcXS-LYHWmKdWXaPnqcYwa7MQn1iVyOmbrP4BRT8QkdJcxlQ@dogen.mongohq.com:10058/app31973614

이제 이 값을 이용하는 nodejs code는 다음과 같습니다.

db: process.env.MONGOHQ_URL

mondodb data import/export

개발환경에서의 mongodb의 값을 heroku에 옮겨야지 되는 경우는 자주 발생합니다. 기본적인 key값이라던지, 초기값들을 넣어주는 작업들은 반드시 필요한 작업들입니다. 이러한 작업을 application에서 해주는 것도 좋지만, 개발중인 mongodb의 값을 eport 시킨 후, import 시켜주는 것이 보다 더 편합니다.

이를 위해서는 먼저 원 데이터의 export가 필요합니다.
기본적인 export command는 다음과 같습니다.

mongoexport --collection <collection> --out <collection.json>

각 collection 당 json 파일을 만들어야지 되는 것을 까먹으면 안됩니다.
이제 heroku mongodb로 값을 export 시켜야지 됩니다. heroku deshboard로 가면 설치된 addon들을 모두 볼 수 있습니다. (아래의 무료 Plan은 이제 없습니다. 기존에 사용하고 있던 사람들은 계속 사용가능합니다.)

click 하면 Compose MongoDB configuration 화면을 볼 수 있습니다.

여기서 Admin으로 들어가서 새로운 사용자를 하나 만들어줍니다.

이제 만들어진 사용자로, import를 진행할겁니다. 이 관리자 console에서 remote url을 확인 할 수 있습니다.

위 정보를 이용해서 mongodb import는 다음 command를 이용해서 처리가 가능합니다.

mongoimport --host dogen.mongohq.com --port 10058 --username <user> --password <pass> --collection <collection> --db app31973614 --file <file.json>

Summary

heroku에 nodejs를 이용한 appliation 배포에 대해서 알아봤습니다. 제가 속한 팀에서의 점심후의 사다리타기 결과를 모아둔 heroku app을 공개해뒀습니다. ㅋㅋ (http://my-sadari.herokuapp.com) heroku는 300M까지는 무료입니다. 이 점에서 nodejs의 가벼운 code의 강점이 보이는 것 같습니다. 아무리 가벼운 웹이라도 은근히 용량이 되는 경우가 많으니까요.

그럼 모두 Happy Coding!


Posted by Y2K
,