우분투 16.04 서버 셋팅 시 자주 생기는 FAQ

AWS Tips

EC2 포트 문제

AWS EC2는 Security Group에서 별도로 허용해주지 않으면 포트들이 기본적으로 막혀있다. 따라서 EC2 Dashboard -> Network & security -> Security Groups에서 Inbound 룰을 바꿔줘야 한다.
예를 들면, 80포트 웹서버를 외부에 오픈하기 위해서는 프로토콜 : TCP, 포트 : 80 으로 Source : 0.0.0.0/0 (모든 IP)를 열어줘야 한다. HTTPS 443, MySQL 3306, SSH 22 등 또한 일일히 열어줘야 한다.
자주하는 실수 : 새로운 테스트 서버 열어야 해서 9000과 같은 포트로 설정해놓곤 Security Group에서 열어주는 걸 잊어버리는 것

AWS RDS MySQL 인코딩 문제

AWS RDS(관계형 데이터베이스) 서비스로 MySQL을 시작해보면, 한국어가 제대로 들어가지 않는 것을 확인할 수 있다. 기본값이 latin-1이라서 생기는 문제점인데, 뒤늦게 고치려면 골치가 아프다. 처음 시작할 때부터 제대로 만들자.
RDS Dashboard -> Parameter Groups를 가서 Create DB parameter group 버튼을 클릭한다.
적절히 이름을 넣고 만든 뒤, Edit parameters 버튼을 눌러 수정을 시작한다. Parameters 탭의 항목들을 다음과 같이 변경한다 :

character_set_client : utf8
character_set_connection : utf8
character_set_database : utf8
character_set_filesystem : utf8
character_set_results : utf8
character_set_server : utf8
collation_connection : utf8_general_ci
collation_server : utf8_general_ci

SSH Tips

SSH config

.pem과 같은 키를 이용해 ssh 연결을 하는 경우, 항상 .pem을 arg에 포함시키는 게 귀찮다. 이는 config 파일을 수정해놓으면 편하게 할 수 있다.

cd ~/.ssh
sudo chmod 400 key.pem
vim config

# === config file === #
Host               friendly-name
HostName           long.and.cumbersome.server.name
IdentityFile       ~/.ssh/private_ssh_file
User               username-on-remote-machine
# === end === #

ssh friendly-name

Node.js 설치

  • 설치하는 방법에는 공식링크에 나와있듯, 소스를 받아 컴파일 하는 방법부터 리눅스 바이너리 등 여러가지가 있지만, 개인적으로는 패키지관리자(apt 등)를 이용한 방법을 추천한다. Node.js는 업데이트가 잦고 LTS 버전도 4, 6, 8과 같이 짝수 패턴으로 계속 올라가는데 은근 버전업이 빨리 이루어진다. 패키지 매니저로 설치하는 것이 제거/업그레이드가 매우 용이하다. ("sudo apt remove node")

apt를 이용한 설치 방법

curl -sL https://deb.nodesource.com/setup_8.x | sudo -E bash -
sudo apt-get install -y nodejs
sudo apt-get install -y build-essential

서버 production 레벨로 띄우기 : PM2

"node app.js"와 같은 방식으로 서버를 실행시키면, 쉘을 닫았을 때 서버가 꺼져버린다. 이를 막기 위해서는 PM2와 같은 node 프로세스 관리자를 써야 한다.

sudo npm install -g pm2   # pm2를 쉘 명령어로 사용 가능하게 global 설치(현재 폴더 node_modules가 아님)
sudo pm2 start app.js     # start process
sudo pm2 monit            # monitor process
sudo pm2 list             # list processes
sudo pm2 save             # save current process list
sudo pm2 startup          # reload process list even after rebooting

서버 안죽게 띄우기 : 번외편1(권장하지 않음)

nohup node webchat.js &   # "&"만 쓰고 실행시키면, 앞의 명령어는 백그라운드 프로세스로 실행시켜버리고 다음 명령어 입력을 기다린다.
ps -ef                    # 프로세스 보기
kill [process number]     # 프로세스 종료

서버 안죽게 띄우기 : 번외편2(권장하지 않음)

forever라는 애드온도 존재한다. 그런데 개인적으론 pm2보다 불안정한 느낌이 있다.

sudo npm install –g forever
forever start app.js
forever list
forever stop

노드 포트(port) 문제

보안 등 문제로 인해 노드는 sudo로 실행시키는 것을 권장하지 않는다. 그런데 sudo로 하지 않으면 80포트를 쓰지 못하는데, 그러면 웹서버인데도 브라우져에서 접속할 때 포트 번호를 직접 써줘야 하는 문제가 발생한다.
그렇기 때문에 포트 외에도 성능 등 문제를 개선하기 위해 node 앞에 nginx 등의 프론트 웹엔진을 두는 것이 좋다.
하지만 그게 여의치 않다면, 모든 80 포트로 들어오는 통신을 8000 포트로 redirect 해서 미봉책으로 해결하는 방법도 존재한다.

# Port routing
sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-ports 8000

iptables 재부팅 후 자동 초기화 막는법

iptables는 재부팅시 모두 날아간다. 위에서 말했듯, nginx 설정하는 건 매우 쉬우므로 iptables hack(미봉책)을 사용하지 않는 걸 추천하지만, 굳이 해야겠다면 재부팅 후에도 지속되도록 툴을 써줘야 한다.

# iptables-persistent 설치
sudo apt-get install iptables-persistent

# Ubuntu 16.04 미만
sudo /etc/init.d/iptables-persistent save     # 현재 iptables 상태 저장
sudo /etc/init.d/iptables-persistent reload   # 저장된 것 불러오기(재부팅시에는 자동으로 불러옴)

# Ubuntu 16.04 이상
sudo netfilter-persistent save                # 현재 iptables 상태 저장
sudo netfilter-persistent reload              # 저장된 것 불러오기(재부팅시에는 자동으로 불러옴)

iptables 항목 삭제

sudo iptables -t nat -L --line-numbers
sudo iptables -t nat -D $chainname $linenumber

MySQL Tips

인코딩 변경
만약 이미 DB를 생성한 상태인데 인코딩 때문에 골치가 아프다면, 다음과 같이 쿼리문으로 수정 가능하다.

SHOW VARIABLES LIKE 'c%';
use dbname;
SET ~~~~~(whatever entry that came out above without quotes) = 'utf8';

Node.js Tips

Router 사용법

노드의 가장 흔한 웹어플리케이션 프레임워크 Express.js는 4.x 버전부터 Router 클래스가 새로 추가되었다. 이를 통해 node의 메인 앱(index.js, app.js와 같은)에서 모두 routes를 관리할 필요가 없어졌다.
예를 들면, 다음과 같은 기초 예제 코드가 있다.

// app.js
const http = require('http');
const express = require('express');
const app = express();


app.get('/', function(req, res, next) {
    res.send("Hello World!");
});

app.get('/bye', function(req, res, next) {
    res.send("Bye World!");
});


const server = http.createServer(app);
server.listen(9000);

이 정도 크기에서는 문제가 많지 않지만, 실제로 Production으로 올릴 경우에는 복잡도가 기하급수적으로 증가한다. 따라서 Model-View-Controller 패턴을 따를 필요가 있다.
View는 ejs, jade 등의 뷰엔진을 쓰면 되는데, Controller는 Express의 Router 클래스를 활용하면 된다. Router를 이용한 프로젝트 구조는 다음과 같다.

models/
views/
    index.ejs
    bye.ejs
controllers/
    index.js
    bye.js
app.js
package.json

이 때, app.js는 index.js만 불러오면 된다.
index.js는 bye.js 및 앞으로 계속 추가될 모든 route들을 관리해준다.

// app.js
const http = require('http');
const express = require('express');
const app = express();

const index = require('./controllers/index');
app.use('/', index);

const server = http.createServer(app);
server.listen(9000);
// index.js
const express = require('express');
const router = express.Router();

const bye = require('./bye');

router.get('/', function(req, res, next) {
    res.render('index');
});

router.use('/bye', bye);

module.exports = router;
// bye.js
const express = require('express');
const router = express.Router();

router.get('/', function(req, res, next)) {
    res.render('bye');
}

module.exports = router;


  Comments,     Trackbacks