리눅스에 깔려있는 아파치 톰캣을 윈도우 PC에서 모니터링해 보는 방법을 알아본다.

1. 톰캣 버전 확인

아파치 톰캣 버전이 9.0대면 이미 JMX remote가 내장되어 있지만, 그 아래 버전이면 홈페이지가서 다운 받아야 한다.

https://tomcat.apache.org/download-80.cgi

 

Apache Tomcat® - Apache Tomcat 8 Software Downloads

Welcome to the Apache Tomcat® 8.x software download page. This page provides download links for obtaining the latest versions of Tomcat 8.x software, as well as links to the archives of older releases. Unsure which version you need? Specification versions

tomcat.apache.org

 

본인컴퓨터에 깔려있는 톰캣 버전을 확인하려면 tomcat/bin 폴더에 가서 아래 명령어를 입력하면 된다.

$./catalina.sh version

참고로 카탈리나 명령어를 통해 start, stop도 할 수 있다.

 

2. catalina.sh 설정

catalina.sh에 바로 jmx remote 설정 문구를 넣는 케이스도 있는데, 그냥 서버 ip와 port만 넣어주는 것으로 한다.

catalina.sh는 tomcat/bin 폴더 에 있다.

 

catalina.sh

serverIP="10.26.10.110"
remotePORT=9090
rmiPORT=9091

여기서 서버IP는 모니터링 프로그램 VMVisual을 실행시키는 서버가 아니라 톰캣이 돌아가고 있는 서버의 IP이다.

 

 

3. setenv.sh

bin폴더 안에 setenv.sh를 만들어서 아래와 같이 써준다.

 

########JMX remote start########


# OOM 발생시 /home/heapdump 에 heapdump 뜨고 GC 로그 남도록 설정
export CATALINA_OPTS="$CATALINA_OPTS -server -Xms1024m -Xmx1024m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/home/heapdump -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:/home/tomcat_8080/logs/gc.log -XX:+UseGCLogFileRotation -XX:GCLogFileSize=2m -XX:NumberOfGCLogFiles=100"

export JMX_OPTS="$JMX_OPTS -Dcom.sun.management.jmxremote 
-Dcom.sun.management.jmxremote.authenticate=false 
-Djava.rmi.server.hostname=${serverIP}
-Dcom.sun.management.jmxremote.port=${remotePORT}
-Dcom.sun.management.jmxremote.rmi.port=${rmiPORT}
-Dcom.sun.management.jmxremote.ssl=false "
CATALINA_OPTS="${JMX_OPTS} ${CATALINA_OPTS}"

#########JMX END###############

setenv.sh는 catalina가 실행될 때 저절로 불러오게끔 코딩되어 있다.

 

4. 톰캣 실행

./catalina.sh start 또는 systemctl start tomcat으로 톰캣을 실행한다.

 

5. 연결

VMvisual을 실행하여 Add remote에 가서 해당 Host와 Port를 써준다.

실제로 연결되는지 확인하려면 Jconsole을 사용해도 무방하다.

 

1. nodemon

코드가 바뀌면 자동으로 재실행해준다. 이와 비슷한 것으로 forever, supervisor, PM2가 있다.

 

 

2. bluebird

프로미스처럼 시간순서대로 실행하게 해준다.

프로미스를 쓰는 것보다 간단하다.

 

3. express

MVC Framework이다.

라우터기능을 쉽게 쓸 수 있다.

 

4. ejs

Template Engine이다.

header, footer 처럼 코드를 분리하고 싶을 때 사용한다.

 

5. mysql

db를 연결시켜준다. async/await을 편하게 사용하려면 promise-mysql을 쓴다.

가독성보다 최적화를 원한다면 mysql을 사용한다. mysql2도 같이 설치한다.

orm을 사용한다면 sequelize를 사용 하는것이 좋다.

 

6. sequelize

db를 연결하여 자바스크립트 문법으로 실행시키는 orm이다.

 

앞 장에서는 포트의 state를 확인하는 법을 배웠다.

 

이번에는 iptables를 이용하여 리눅스방화벽 ufw를 조작하는 법을 말해보겠다.


리눅스에서 아래 명령어를 쳤을 때 No command가 나오면 iptables를 설치해줘야한다.

 

$ iptables -nL

$ apt-get install iptables-persistent  //리눅스 방화벽 ufw를 disable시킨 상태에서 iptables를 설치한다.

$ cp /usr/share/netfilter-persistent/plugins.d/15-ip4tables /etc/init.d/iptables → 해당 파일 init.d에 복사한다.

$ sudo /etc/init.d/iptables start  //iptables를 시작한다.

$ /etc/init.d/iptables flush → iptables를 종료한다. (이것은 왠만하면 실행않는다.)

 

 

제대로 설치되었다면 아래 명령어를 치면 ip들이 쭈루룩 뜰것이다.

$ sudo iptables -nL

 

특정 포트를 외부에서 접속할 수 있게 방화벽을 해제하기

- TCP PORT일 경우

$ iptables -I INPUT -p tcp --dport 5006 -j ACCEPT   //5006 포트를 외부에서 연결할수 있도록 OPEN

- UDP PORT일 경우

$ iptables -I INPUT -p udp --dport 5006 -j ACCEPT   //5006 포트를 외부에서 연결할수 있도록 OPEN

 

 

-I: 새로운 규칙을 추가한다. (알파벳 엘이 아니고 아이다.)

-p: 패킷의 프로토콜을 명시한다.

-j: 규칙에 해당되는 패킷을 어떻게 처리할지를 정한다. 

 

$ iptables -L -v  | grep 5006 // 방금 추가한 설정을 조회

-L: 규칙을 출력

-v: 자세히 

 

$ service iptables save //변경 사항 저장

$ /etc/init.d/iptables restart  //재시작

추가한 규칙을 삭제하고 싶을 때

 

a) 규칙번호로 삭제

$ iptables -D INPUT 1 // 1번규칙 삭제

 

b) 추가한 규칙 그대로 삭제. (-D는 delete)

$ iptables -D INPUT -p tcp --dport 5006 -j ACCEPT

$ iptables -D INPUT -p udp --dport 5006 -j ACCEPT

방화벽 활성화 & 비활성화

1. 켜기

$ /etc/init.d/iptables start

 

2. 끄기

$ /etc/init.d/iptables flush

 

 

우분투의 경우는 ufw 명령어도 사용할 수 있다.

 

$ sudo ufw enable  //ufw 켜기

$ sudo ufw disable  //ufw 끄기

 

$ sudo ufw allow 5006/tcp  //tcp 5006 port 허용

$ sudo ufw allow 5006/udp  //udp 5006 port 허용

 

$ sudo ufw deny 5006/tcp  //tcp 5006 port 거부

$ sudo ufw deny 5006/udp  //udp 5006 port 거부

 

ufw 상태보기

$ sudo ufw status

$ sudo ufw status verbose


--------------------------

 

참고로 TCP는 송신자와 수신자가 상호작용을 하며 응용계층으로부터 데이터를 받아 TCP 헤더를 추가한 후에 이를 IP로 보낸다.

하지만 UDP는 수신자가 데이터를 받는지 마는지 관심이없다. 즉, UDP는 신뢰성을 보장해주지 않지만 간단하고 속도가 빠르다.

 

 

TCP(Transfer Control Protocol)                                           UDP(User Datagram Protocol)

연결이 성공해야 통신 가능(연결형 프로토콜) 비연결형 프로토콜(연결 없이 통신이 가능)
데이터의 경계를 구분하지 않음(Byte-Stream Service) 데이터의 경계를 구분함(Datagram Service)
신뢰성 있는 데이터 전송(데이터의 재전송 존재) 비신뢰성 있는 데이터 전송(데이터의 재전송 없음)
일 대 일(Unicast) 통신 일 대 일, 일 대 다(Broadcast), 다 대 다(Multicast) 통신

 

 

 

리눅스 자체 방화벽에서 포트를 열고 닫는데 이때 다른 컴퓨터나 VM에서 접속하려고 하면 안되는 경우가 있다.

 

포트가 닫혀있는지 확인하는 법은

 

cmd에서는 ping이나 tcping을 사용하면 된다.

 

아래처럼 나오면 연결이 안된다는 뜻

아래처럼 나오면 연결이 잘 동작한다는 뜻이다.

 

하지만 특정 포트에 알아보고 싶으면 tcping을 쓰면 된다.

 

설치방법은 C:\Windows\System32 경로에 아래 파일을 복사하면된다.

tcping.exe
0.25MB

 

그리고 cmd창에 tcping이라고 입력하면 쭈루룩 무언가가 뜨는데, 이러면 설치 성공이다.

 

5009포트에 대해서 tcping 테스트를 해보면 아래와 같이나온다.

 

No response라고 뜨는데, 이는 5009 포트가 닫혀있다는 것을 의미한다.

 

5006 포트는 열려있기에 아래와 같이 정상적으로 작동한다.

 

 

만약 내가 리눅스OS에서 5006 포트를 열었는데 타PC에서 접속할때 No response가 뜬다면 리눅스 방화벽이 원인이고 이는 여러 방법으로 해결할 수 있다.

 

netstat을 이용한 port 스캔

 

$ netstat -tnlp       // 현재 가동 중인 포트 들을 보여준다.

이와 더불어 netstat -nap도 열려있는 모든 포트를 보여준다. grep을 사용하여 포트번호를 검색할 수 도 있다.

 

$ netstat 

namp을 이용한 포트 확인

 

nmap을 이용한 port 스캔

리눅스 상에 아래 명령어를 치면 Usage: Nmap으로 나오면 nmap이 이미 설치되어 있는 것.

$ nmap

 

Command 'nmap' not found가 나온다면 설치를 해줘야 한다.

아래 명령어로 namp을 설치 한다.

 

$ sudo apt install nmap

 

그리고 아래 명령어를 실행 해본다.

 

$ nmap -sT 172.26.12.120      // 172.26.12.120에서 열린 port들을 보여준다.

$ nmap -sT 172.26.12.120 -p 5006     // 172.26.12.120의 5006포트가 열렸는지 닫혔는지 보여준다.

$ nmap -Pn 172.26.12.120 -p 5006     // 172.26.12.120의 5006포트가 열렸는지 닫혔는지 보여준다.

 

-sT 또는 -Pn을 주로 쓴다.

-sT 일반적인 TCP 포트스캐닝.
-sS 이른바 'half-open' 스캔으로 추적이 어렵다.
-sP ping 을 이용한 일반적인 스캔.
-sU UDP 포트 스캐닝.
-PO 대상 호스트에 대한 ping 응답을 요청하지 않음 .
log 기록과 filtering 을 피할 수 있다.
-PT 일반적이 ICMP ping이 아닌 ACK 패킷으로 ping 을 보내고
RST 패킷으로 응답을 받는다.
-PI 일반적인 ICMP ping 으로 방화벽이나 필터링에 의해 걸러진다.
-PB ping 을 할 때 ICMP ping 과 TCP ping을 동시에 이용한다.
-PS ping 을 할 때 ACK 패킷대신 SYN 패킷을 보내 스캔.
-O 대상 호스트의 OS 판별.
-p 대상 호스트의 특정 포트를 스캔하거나, 스캔할 포트의 범위를 지정.
ex) -p 1-1024
-D Decoy 기능으로 대상 호스트에게 스캔을 실행한 호스트의 주소를 속인다.
-F /etc/services 파일 내에 기술된 포트만 스캔.
-I TCP 프로세서의 identd 정보를 가져온다.
-n IP 주소를 DNS 호스트명으로 바꾸지 않는다. 속도가 빠르다.
-R IP 주소를 DNS 호스트명으로 바꿔서 스캔. 속도가 느리다.
-o 스캔 결과를 택스트 파일로 저장.
-i 스캔 대상 호스트의 정보를 지정한 파일에서 읽어서 스캔.
-h 도움말 보기

 

PORT의 state가 open이면 열렸다는 것, closed면 닫혔거나 존재하지 않는다는 것, filtered면 열렸지만 방화벽으로 가로막혔다는 것을 뜻한다.

 

filtered면 방화벽을 해제함으로써 다른 pc에서 통신할수 있게끔 할수 있다. 다음장에 계속

 

 

 

 

 

리눅스는 대표적으로 우분투, CentOS, KaliLinux 등이 있지만 Ubuntu 기준으로 기술한다.

 

1. 리눅스에서 실행되고 있는 프로세스 확인하기

 

ps 명령어를 사용한다.

 

옵션 설명
-e 모든 프로세스를 출력해 준다.
-f 풀 포맷으로 보여준다. (UIP, PID)
-l 긴 포맷으로 보여준다.
-p 특정 PID의 프로세스를 보여준다.
-u 특정 사용자의 프로세스를 보여준다.

여기서 PID는 프로세스를 구별하는 유일한 요소이며, UID는 프로그램을 실행한 사람의 정보를 나타내는 요소이다.

그리고 PPID는 프로세스를 만든 부모 프로세스의 PID를 나타내는 값이다.

 

옵션으로는 aux, -e 등 많지만 -ef나 -el을 grep과 함께 많이 사용한다.

 

 

$ ps -el | grep "찾을 문자열"
예) $ ps -el | grep ripple

 

2. 파일 찾기

리눅스는 CLI 기반이라서 파일이 어디있는지 찾기 힘든 경우가 많다.

 

단순히 아래 명령어를 치면 폴더가 검색되어 나온다.

$ find | grep "찾을 문자열"

 

아래만 명심하면 된다.

 

* r로 시작하는 폴더만 찾기

$ find -name "r*" -type d

 

* r로 시작하는 파일만 찾기

$ find -name "r*" -type f

 

3. 프로세스 죽이기

sudo kill -9 "PID번호"

ps -el | grep "찾는 문자열"   << 이 명령어로 PID 확인 가능

 

 

4. 로그 파일 열기

tail -f "로그파일명"

-f는 로그파일을 계속 감시한다는 것을 뜻한다.

이때 해당 폴더 안에 있거나 정확한 디렉토리명을 입력해줘야한다.

 

 

 

 

 

WEB이란 네트워크 체계 위에서 동작하는 통신 규약(HTTP) 중의 하나이다.

 

인터넷 안에서 돌아가는 시스템들을 나열해 보면 아래와 같다.

이름 프로토콜 포트 기능
WWW HTTP 80 웹서비스
WWW HTTPS 443 보안인증서 추가된 웹서비스
FTP FTP 21 파일 전송 서비스
DNS DNS 23 네임서비스
NEWS NNTP 119 인터넷 뉴스 서비스

 

 

 

nginx는 요즘 떠오르는 차세대 웹서버 소프트웨어이다. 적은 자원으로 더 많은 일을 할 수 가 있다.

 

APCHE는 요청이 많을 경우 Process를 생성하여 처리하는 방식(preFork)이다. APACHE는 접속마다 프로세스 또는 Thread를 생성하는 구조이다. 동시 접속 요청이 10,000개라면 그 만큼 Thread 생성 비용이 들 것이고 대용량 요청을 처리할 수 있는 웹서버로서의 한계를 드러내게 된다.

 

반면 NGINX는 Event-driven 방식으로 동작한다.

한 개 또는 고정된 프로세스만 생성하고, 그 프로세스 내부에서 비동기방식으로 효율적으로 작업들을 처리한다. 따라서 동시 접속 요청이 많아도 프로세스 또는 쓰레드 생성 비용이 존재하지 않는다.

 

우분투 18.04에서 NGINX 설치 방법

nginx는 Ubuntu의 레파지토리에 default로 있기에 아래와 같이 명령어를 입력한다.

 

$ sudo apt update

$ sudo apt install nginx

 

그렇다면 아래와 같이 nginx가 설치된다.

root2@DESKTOP-024G8AA:~$ sudo apt update
Get:4 https://download.docker.com/linux/ubuntu bionic InRelease [64.4 kB]
Hit:1 http://mirror.kakao.com/ubuntu bionic InRelease
Get:2 http://mirror.kakao.com/ubuntu bionic-updates InRelease [88.7 kB]
Get:3 http://mirror.kakao.com/ubuntu bionic-backports InRelease [74.6 kB]
Get:5 https://download.docker.com/linux/ubuntu bionic/stable amd64 Packages [9594 B]
Get:6 http://security.ubuntu.com/ubuntu bionic-security InRelease [88.7 kB]
Get:7 http://mirror.kakao.com/ubuntu bionic-updates/main amd64 Packages [768 kB]
Get:8 http://mirror.kakao.com/ubuntu bionic-updates/main Translation-en [275 kB]
Get:9 http://mirror.kakao.com/ubuntu bionic-updates/restricted amd64 Packages [18.7 kB]
Get:10 http://mirror.kakao.com/ubuntu bionic-updates/restricted Translation-en [5328 B]
Get:11 http://mirror.kakao.com/ubuntu bionic-updates/universe amd64 Packages [1022 kB]
Get:12 http://mirror.kakao.com/ubuntu bionic-updates/universe Translation-en [315 kB]
Get:13 http://mirror.kakao.com/ubuntu bionic-updates/multiverse amd64 Packages [8096 B]
Get:14 http://mirror.kakao.com/ubuntu bionic-updates/multiverse Translation-en [3972 B]
Get:15 http://mirror.kakao.com/ubuntu bionic-backports/main amd64 Packages [2512 B]
Get:16 http://mirror.kakao.com/ubuntu bionic-backports/main Translation-en [1644 B]
Get:17 http://mirror.kakao.com/ubuntu bionic-backports/universe amd64 Packages [4024 B]
Get:18 http://mirror.kakao.com/ubuntu bionic-backports/universe Translation-en [1856 B]
Get:19 http://security.ubuntu.com/ubuntu bionic-security/main amd64 Packages [545 kB]
Get:20 http://security.ubuntu.com/ubuntu bionic-security/main Translation-en [182 kB]
Get:21 http://security.ubuntu.com/ubuntu bionic-security/restricted amd64 Packages [9856 B]
Get:22 http://security.ubuntu.com/ubuntu bionic-security/restricted Translation-en [3480 B]
Get:23 http://security.ubuntu.com/ubuntu bionic-security/universe amd64 Packages [617 kB]
Get:24 http://security.ubuntu.com/ubuntu bionic-security/universe Translation-en [206 kB]
Get:25 http://security.ubuntu.com/ubuntu bionic-security/multiverse amd64 Packages [5476 B]
Get:26 http://security.ubuntu.com/ubuntu bionic-security/multiverse Translation-en [2500 B]
Fetched 4324 kB in 13s (328 kB/s)
Reading package lists... Done
Building dependency tree
Reading state information... Done
291 packages can be upgraded. Run 'apt list --upgradable' to see them.


root2@DESKTOP-024G8AA:~$ sudo apt install nginx
[sudo] password for root2:
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following additional packages will be installed:
  libnginx-mod-http-geoip libnginx-mod-http-image-filter libnginx-mod-http-xslt-filter libnginx-mod-mail
  libnginx-mod-stream nginx-common nginx-core
Suggested packages:
  fcgiwrap nginx-doc ssl-cert
The following NEW packages will be installed:
  libnginx-mod-http-geoip libnginx-mod-http-image-filter libnginx-mod-http-xslt-filter libnginx-mod-mail
  libnginx-mod-stream nginx nginx-common nginx-core
0 upgraded, 8 newly installed, 0 to remove and 291 not upgraded.
1 not fully installed or removed.
Need to get 598 kB of archives.
After this operation, 2120 kB of additional disk space will be used.
Do you want to continue? [Y/n] Y
Get:1 http://mirror.kakao.com/ubuntu bionic-updates/main amd64 nginx-common all 1.14.0-0ubuntu1.6 [37.3 kB]
Get:2 http://mirror.kakao.com/ubuntu bionic-updates/main amd64 libnginx-mod-http-geoip amd64 1.14.0-0ubuntu1.6 [11.2 kB]
Get:3 http://mirror.kakao.com/ubuntu bionic-updates/main amd64 libnginx-mod-http-image-filter amd64 1.14.0-0ubuntu1.6 [1
4.5 kB]
Get:4 http://mirror.kakao.com/ubuntu bionic-updates/main amd64 libnginx-mod-http-xslt-filter amd64 1.14.0-0ubuntu1.6 [12
.9 kB]
Get:5 http://mirror.kakao.com/ubuntu bionic-updates/main amd64 libnginx-mod-mail amd64 1.14.0-0ubuntu1.6 [41.7 kB]
Get:6 http://mirror.kakao.com/ubuntu bionic-updates/main amd64 libnginx-mod-stream amd64 1.14.0-0ubuntu1.6 [63.6 kB]
Get:7 http://mirror.kakao.com/ubuntu bionic-updates/main amd64 nginx-core amd64 1.14.0-0ubuntu1.6 [413 kB]
Get:8 http://mirror.kakao.com/ubuntu bionic-updates/main amd64 nginx all 1.14.0-0ubuntu1.6 [3596 B]
Fetched 598 kB in 1s (1183 kB/s)
Preconfiguring packages ...
Selecting previously unselected package nginx-common.
(Reading database ... 46509 files and directories currently installed.)
Preparing to unpack .../0-nginx-common_1.14.0-0ubuntu1.6_all.deb ...
Unpacking nginx-common (1.14.0-0ubuntu1.6) ...
Selecting previously unselected package libnginx-mod-http-geoip.
Preparing to unpack .../1-libnginx-mod-http-geoip_1.14.0-0ubuntu1.6_amd64.deb ...
Unpacking libnginx-mod-http-geoip (1.14.0-0ubuntu1.6) ...
Selecting previously unselected package libnginx-mod-http-image-filter.
Preparing to unpack .../2-libnginx-mod-http-image-filter_1.14.0-0ubuntu1.6_amd64.deb ...
Unpacking libnginx-mod-http-image-filter (1.14.0-0ubuntu1.6) ...
Selecting previously unselected package libnginx-mod-http-xslt-filter.
Preparing to unpack .../3-libnginx-mod-http-xslt-filter_1.14.0-0ubuntu1.6_amd64.deb ...
Unpacking libnginx-mod-http-xslt-filter (1.14.0-0ubuntu1.6) ...
Selecting previously unselected package libnginx-mod-mail.
Preparing to unpack .../4-libnginx-mod-mail_1.14.0-0ubuntu1.6_amd64.deb ...
Unpacking libnginx-mod-mail (1.14.0-0ubuntu1.6) ...
Selecting previously unselected package libnginx-mod-stream.
Preparing to unpack .../5-libnginx-mod-stream_1.14.0-0ubuntu1.6_amd64.deb ...
Unpacking libnginx-mod-stream (1.14.0-0ubuntu1.6) ...
Selecting previously unselected package nginx-core.
Preparing to unpack .../6-nginx-core_1.14.0-0ubuntu1.6_amd64.deb ...
Unpacking nginx-core (1.14.0-0ubuntu1.6) ...
Selecting previously unselected package nginx.
Preparing to unpack .../7-nginx_1.14.0-0ubuntu1.6_all.deb ...
Unpacking nginx (1.14.0-0ubuntu1.6) ...
Processing triggers for ufw (0.35-5) ...
Setting up docker.io (18.09.2-0ubuntu1~18.04.1) ...
invoke-rc.d: could not determine current runlevel
Processing triggers for ureadahead (0.100.0-20) ...
Setting up nginx-common (1.14.0-0ubuntu1.6) ...
Created symlink /etc/systemd/system/multi-user.target.wants/nginx.service → /lib/systemd/system/nginx.service.
Setting up libnginx-mod-http-image-filter (1.14.0-0ubuntu1.6) ...
Processing triggers for systemd (237-3ubuntu10.3) ...
Setting up libnginx-mod-mail (1.14.0-0ubuntu1.6) ...
Processing triggers for man-db (2.8.3-2) ...
Setting up libnginx-mod-http-xslt-filter (1.14.0-0ubuntu1.6) ...
Setting up libnginx-mod-http-geoip (1.14.0-0ubuntu1.6) ...
Setting up libnginx-mod-stream (1.14.0-0ubuntu1.6) ...
Setting up nginx-core (1.14.0-0ubuntu1.6) ...
Cannot open netlink socket: Protocol not supported
invoke-rc.d: could not determine current runlevel
Setting up nginx (1.14.0-0ubuntu1.6) ...
Processing triggers for ureadahead (0.100.0-20) ...
Processing triggers for ufw (0.35-5) ...
W: APT had planned for dpkg to do more than it reported back (40 vs 44).
   Affected packages: docker.io:amd64

 

방화벽설치

 

NGINX를 테스트하기전에 ufw라는 방화벽을 설치한다.

root2@DESKTOP-024G8AA:~$ sudo ufw app list
Available applications:
  Nginx Full
  Nginx HTTP
  Nginx HTTPS
  OpenSSH

 

아직 서버에 SSL을 구성하지 않았으므로 포트 80의 트래픽만 허용하면 된다.

 

다음을 입력하여 활성화 할 수 있다.

 

$ sudo ufw allow 'nginx HTTP'

 

----------

윈도우 우분투는 iptables를 사용할 수 없다고 나온다.

 

nginx의 상세 설정은 conf파일을 통해 이루어지며 자세한 것은 아래 링크에 있다.

 

https://sarc.io/index.php/nginx/61-nginx-nginx-conf

 

Nginx 주요 설정 (nginx.conf)

Technical Note 정보 appsroot 님이 작성하신 글입니다. 카테고리: [ Nginx ] 게시됨: 23 February 2014 작성됨: 19 February 2014 최종 변경: 09 February 2018 조회수: 68502 1. 개요 지난 번 포스팅을 통해 OS X에서 Nginx 1.4.4를 설치하여 보았습니다. 강철지그님께서는 계속 작업을 해주고 계십니다. 한편 왜 Nginx를 써야 하는지도 언급된 적이 있지요. 이번에는 설정 파일인

sarc.io

systemctl start nginx

systemctl stop nginx

systemctl restart nginx

 

리눅스에서는 위 명령어로 nginx를 쉽게 조작할 수 있다.

 

 

시퀄라이즈는 ORM(Object-relational Mapping)으로 분류가 된다.

ORM은 자바스크립트 객체와 데이터베이스의 릴레이션을 매핑해주는 도구이다.

 

1. express를 이용해서 새 프로젝트 생성

$ express sequlize_ex --view=pug

 

위에 나온대로 디렉토리를 바꿔준뒤 npm i를 해준다.

$ cd sequelize_ex
$ npm i

 

방금 만든 프로젝트에 sequelize와 mysql2 패키지를 설치한다. 그 후 sequelize 커맨드를 사용하기 위해 sequelize-cli를 전역 설치

$ npm i sequelize mysql2
$ npm i -g sequelize-cli
$ sequelize init

 

그 뒤 파일들을 아래대로 세팅

models/index.js

const path = require('path');
const Sequelize = require('sequelize'); //sequelize 연결

const env = process.env.NODE_ENV || 'development';
const config = require(path.join(__dirname, '..', 'config', 'config.json'))[env];
const db = {};

const sequelize = new Sequelize(config.database, config.username, config.password, config);


db.sequelize = sequelize;
db.Sequelize = Sequelize;

//user와 comment 테이블을 연결시킨다.
db.User = require('./user')(sequelize, Sequelize);
db.Comment = require('./comment')(sequelize, Sequelize); 

//테이블 간의 관계를 정의해줌
db.User.hasMany(db.Comment, {foreignKey: 'commenter', sourceKey: 'id'});
db.Comment.belongsTo(db.User, {foreignKey: 'commenter', targetKey: 'id'});

module.exports = db; //db라는 객체에 user와 comment 모델을 담는다.

 

시퀄라이즈를 통해 익스프레스 앱과 MYSQL을 연결한다. app.js에서 추가해준다.

app.js

var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');

var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');
var commentsRouter = require('./routes/comments');

//추가
var sequelize = require('./models').sequelize;

var app = express();

//추가
sequelize.sync();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');

app.use(logger('dev'));
app.use(express.static(path.join(__dirname, 'public')));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());

app.use('/', indexRouter);
app.use('/users', usersRouter);
app.use('/comments', commentsRouter);

// catch 404 and forward to error handler
app.use(function(req, res, next) {
  next(createError(404));
});

// error handler
app.use(function(err, req, res, next) {
  // set locals, only providing error in development
  res.locals.message = err.message;
  res.locals.error = req.app.get('env') === 'development' ? err : {};

  // render the error page
  res.status(err.status || 500);
  res.render('error');
});

module.exports = app;

 

번거롭지만 MYSQL에서 정의한 테이블을 시퀄라이즈에서도 정의해야 한다.

기본적으로 모델 이름은 단수형으로 테이블 이름은 복수형으로 사용한다.

 

models/user.js

module.exports = (sequelize, DataTypes) => {
    return sequelize.define('user', {
        name: {
            type: DataTypes.STRING(20),
            allowNull: false,
            unique: true,
        },
        age: {
            type: DataTypes.INTEGER.UNSIGNED,
            allowNull: false,
        },
        married: {
            type: DataTypes.BOOLEAN,
            allowNull: false,
        },
        comment: {
            type: DataTypes.TEXT,
            allowNull: true,
        },
        created_at: {
            type: DataTypes.DATE,
            allowNull: false,
            defaultValue: DataTypes.NOW,
        },
    }, {
        timestamps: false,
    });
};

 알아서 id를 기본 키로 연결하므로 id 컬럼은 적어줄 필요가 없다.

그리고 알아둘 것이 timestamps가 true면 시퀄라이즈는 createdAt과 updatedAt 컬럼을 추가하며 행이 생성 될때와 수정될 때의 시간을 자동으로 입력한다.

 

하지만 여기서는 created_at 컬럼을 직접만들었으므로 timestamps는 false로 하였다.

참고로 paranoid: true 도 많이 사용하는데 이러면 deletedAt이라는 컬럼이 추가되어 행이 삭제 되었을 때 제거하는 대신 deletedAt에 제거된 날짜를 입력한다.

 

실무에서는 데이터베이스 복원을 위하여 데이터 삭제는 왠만해선 하지 않는다. 사이트에서 회원탈퇴해도 같은 아이디로는 재가입할 수 없는 것도 이러한 이치.

 

이 외에도 underscored 옵션을 사용하여 캐멀형식이 아닌 _를 중간에 써주어 created_at 처럼 표기시킬 수도 있다.

 

comment 모델도 만들어 보자.

models/comment.js

module.exports = (sequelize, DataTypes) => {
    return sequelize.define('comment', {
        comment: {
            type: DataTypes.STRING(100),
            allowNull: false,
        },
        created_at: {
            type: DataTypes.DATE,
            allowNull: true,
            defaultValue: DataTypes.NOW,
        },
    }, {
        timestamps: false,
    });
};

 

아까 위에서 index.js에서 보듯이 db라는 객체에 user와 comment 모델을 담아두었다.

models/index.js

const path = require('path');
const Sequelize = require('sequelize'); //sequelize 연결

const env = process.env.NODE_ENV || 'development';
const config = require(path.join(__dirname, '..', 'config', 'config.json'))[env];
const db = {};

const sequelize = new Sequelize(config.database, config.username, config.password, config);


db.sequelize = sequelize;
db.Sequelize = Sequelize;

//user와 comment 테이블을 연결시킨다.
db.User = require('./user')(sequelize, Sequelize);
db.Comment = require('./comment')(sequelize, Sequelize); 

//테이블 간의 관계를 정의해줌
db.User.hasMany(db.Comment, {foreignKey: 'commenter', sourceKey: 'id'});
db.Comment.belongsTo(db.User, {foreignKey: 'commenter', targetKey: 'id'});

module.exports = db; //db라는 객체에 user와 comment 모델을 담는다.

db객체를 require하여 User와 Comment 모델에 접근할 수 있다.

 

마지막으로 config.json을 수정하여 mysql 비밀번호를 입력하여 연결시켜준다.

본인은 비밀번호는 12351235로 하였다. 

config/config.json

{
  "development": {
    "username": "root",
    "password": "12351235",
    "database": "nodejs",
    "host": "127.0.0.1",
    "dialect": "mysql",
    "operatorsAliases": false
  },
  "test": {
    "username": "root",
    "password": null,
    "database": "database_test",
    "host": "127.0.0.1",
    "dialect": "mysql",
    "operatorsAliases": false
  },
  "production": {
    "username": "root",
    "password": null,
    "database": "database_production",
    "host": "127.0.0.1",
    "dialect": "mysql",
    "operatorsAliases": false
  }
}

 

그리고 나머지 html 코딩파일은 아래의 파일을 다운로드 받아서 덮어쓰기 한다.

 

 

learn-sequelize.zip
6.28MB

 

 

그 뒤 npm start를 실행시킨다.

 

localhost:3000으로 들어가면 아래와 같은 페이지가 나타난다.

위에 이름나이를 등록하고 중간에 리스트를 클릭하면 아래에 클릭한 리스트가 나타난다.

 

 

 

 

 

 

 

 

 

 

 

1. Insert 문

SQL문법

INSERT INTO nodejs.users (name, age, married, comment) VALUES ('zero', 24, 0, '자기소개1');

sequelize 문법

const { User } = require('../models')
User.create({
name: 'zero',
age: 24,
married: false,
comment: '자기소개1',
});

 

이하 아래부터는 위는 SQL문 아래는 seq문법이다.

 

 

 

- SELECT * FROM nodejs.users;

- User.findALL({});

 

- SELECT * FROM nodejs.users LIMIT 1;

- User.findOne({});

 

- SELECT name, married FROM nodejs.users;

- User.findALL({

  attributes: ['name', 'married'],

});

 

- SELECT name, age FROM nodejs.users WHERE married =1 AND age > 30;

 

- const { User, Sequelize : {Op}} = require('../models');

User.findAll({

  attributes: ['name', 'age'],

where: {

  married: 1,

age: { [Op.gt]: 30 },

},

});

 

- SELECT id, name FROM users ORDER BY age DESC;

- User.findAll({

  attributes: ['id', 'name'],

order: [[ 'age', 'DESC']],

});

 

- UPDATE nodejs.users SET comment = '바꿀 내용' WHERE id = 2;

- User.update({

  comment: '바꿀 내용',

}, {

  where : { id : 2 },

});

 

- DELETE FROM nodejs.users WHERE id = 2;

- User.destroy({

 where: { id : 2},

});

 

1. mysql installer를 이용하여 mysql connector 설치

 이 때 아이디는 root이며 비밀번호는 우선 12351235로 설정

 

또한 workbench도 같이 설치

 

mysql installer download 링크

https://dev.mysql.com/downloads/file/?id=490394

 

MySQL :: Begin Your Download

The world's most popular open source database

dev.mysql.com

리눅스의 경우 아래를 따른다.

$ sudo apt-get update
$ sudo apt-get install -y mysql-server-5.7
$ mysql_secure_installation

 

 

2. db연결 및 테이블 생성

C:\Program Files\MySQL\MySQL Server 8.0\bin 로 들어가서 mysql 실행

mysql -h localhost -u root -p
Enter password: 12351235
mysql>

 

nodejs 스키마를 생성하고 이 스키마를 사용하겠다는 것을 MySQL에 알림

 

mysql> CREATE SCHEMA nodejs;
Query OK, 1 row affected (0.01 sec)

mysql> use nodejs;
Database changed

 

nodejs 데이터베이스의 users 테이블 생성

아래 코드를 입력한다.

CREATE TABLE nodejs.users(
id INT NOT NULL AUTO_INCREMENT,
name VARCHAR(20) NOT NULL,
age INT UNSIGNED NOT NULL,
married TINYINT NOT NULL,
comment TEXT NULL,
created_at DATETIME NOT NULL DEFAULT now(),
PRIMARY KEY(id),
UNIQUE INDEX name_UNIQUE (name ASC))
COMMENT = '사용자 정보'
DEFAULT CHARSET=utf8
ENGINE=InnoDB;

 

결과

mysql> CREATE TABLE nodejs.users(
    -> id INT NOT NULL AUTO_INCREMENT,
    -> name VARCHAR(20) NOT NULL,
    -> age INT UNSIGNED NOT NULL,
    -> married TINYINT NOT NULL,
    -> comment TEXT NULL,
    -> created_at DATETIME NOT NULL DEFAULT now(),
    -> PRIMARY KEY(id),
    -> UNIQUE INDEX name_UNIQUE (name ASC))
    -> COMMENT = '사용자 정보'
    -> DEFAULT CHARSET=utf8
    -> ENGINE=InnoDB;
Query OK, 0 rows affected, 1 warning (0.07 sec)

 

table 정보 확인

mysql> DESC users;
+------------+------------------+------+-----+-------------------+-------------------+
| Field      | Type             | Null | Key | Default           | Extra             |
+------------+------------------+------+-----+-------------------+-------------------+
| id         | int(11)          | NO   | PRI | NULL              | auto_increment    |
| name       | varchar(20)      | NO   | UNI | NULL              |                   |
| age        | int(10) unsigned | NO   |     | NULL              |                   |
| married    | tinyint(4)       | NO   |     | NULL              |                   |
| comment    | text             | YES  |     | NULL              |                   |
| created_at | datetime         | NO   |     | CURRENT_TIMESTAMP | DEFAULT_GENERATED |
+------------+------------------+------+-----+-------------------+-------------------+
6 rows in set (0.01 sec)

 

그 뒤, 사용자의 댓글을 저장하는 테이블 생성

아래 코드 입력

CREATE TABLE nodejs.comments (
id INT NOT NULL AUTO_INCREMENT,
commenter INT NOT NULL,
comment VARCHAR(100) NOT NULL,
created_at DATETIME NOT NULL DEFAULT now(),
PRIMARY KEY(id),
INDEX commenter_idx (commenter ASC),
CONSTRAINT commenter
FOREIGN KEY (commenter)
REFERENCES nodejs.users (id)
ON DELETE CASCADE
ON UPDATE CASCADE)
COMMENT = '댓글'
DEFAULT CHARSET=utf8
ENGINE=InnoDB;

 

결과

mysql> CREATE TABLE nodejs.comments (
    -> id INT NOT NULL AUTO_INCREMENT,
    -> commenter INT NOT NULL,
    -> comment VARCHAR(100) NOT NULL,
    -> created_at DATETIME NOT NULL DEFAULT now(),
    -> PRIMARY KEY(id),
    -> INDEX commenter_idx (commenter ASC),
    -> CONSTRAINT commenter
    -> FOREIGN KEY (commenter)
    -> REFERENCES nodejs.users (id)
    -> ON DELETE CASCADE
    -> ON UPDATE CASCADE)
    -> COMMENT = '댓글'
    -> DEFAULT CHARSET=utf8
    -> ENGINE=InnoDB;
Query OK, 0 rows affected, 1 warning (0.06 sec)

테이블명 확인

mysql> SHOW TABLES;
+------------------+
| Tables_in_nodejs |
+------------------+
| comments         |
| users            |
+------------------+
2 rows in set (0.00 sec)

 

워크벤치 GUI를 이용하여 테이블을 만드는 것이 일반적임.

 

3. CRUD 작업하기

CREATE (행 생성)

mysql> INSERT INTO nodejs.users (name, age, married, comment) VALUES ('zero', 24, 0, '자기소개1');
Query OK, 1 row affected (0.02 sec)

mysql> INSERT INTO nodejs.users (name, age, married, comment) VALUES ('nero', 32, 1, '자기소개2');
Query OK, 1 row affected (0.01 sec)
mysql> INSERT INTO nodejs.comments (commenter, comment) VALUES (1, '안녕하세요. zero의 댓글입니다.');
Query OK, 1 row affected (0.01 sec)

 

READ (조회)

mysql> SELECT * FROM nodejs.users;
+----+------+-----+---------+-----------+---------------------+
| id | name | age | married | comment   | created_at          |
+----+------+-----+---------+-----------+---------------------+
|  1 | zero |  24 |       0 | 자기소개1 | 2019-11-03 23:00:10 |
|  2 | nero |  32 |       1 | 자기소개2 | 2019-11-03 23:00:44 |
+----+------+-----+---------+-----------+---------------------+
2 rows in set (0.00 sec)
mysql> SELECT * FROM nodejs.comments;
+----+-----------+--------------------------------+---------------------+
| id | commenter | comment                        | created_at          |
+----+-----------+--------------------------------+---------------------+
|  1 |         1 | 안녕하세요. zero의 댓글입니다. | 2019-11-03 23:03:32 |
+----+-----------+--------------------------------+---------------------+
1 row in set (0.00 sec)

 

UPDATE (수정)

mysql> UPDATE nodejs.users SET comment = '바꿀 내용' WHERE id = 2;
Query OK, 1 row affected (0.01 sec)
Rows matched: 1  Changed: 1  Warnings: 0

 

DELETE (삭제)

mysql> DELETE FROM nodejs.users WHERE id = 2;

 

이더리움 계열의 코인은 대표적으로 이더리움, 이더리움 클래식, 익스팬스 등이 있다.

RPC연결을 하여 월렛을 컨트롤 하기 위해서는 코어에 접근해서 블록을 syncing 해줘야한다.

 

그런 것을 지원해주는 것은 대표적으로 Go-ethereum(geth)과 Parity이다.

 

Geth

Geth는 이더리움 재단(Ethereum Foundation)이 제공하는 공식 클라이언트 소프트웨어로써, Go언어로 개발되었다.

Geth를 처음 시작하면 네트워크 내의 다른 이더리움 클라이언트(노드node라고도 불림)에 연결하는 작업을 먼저 시작하고 블록체인의 전체 사본을 내려받게 된다.

 

Geth는 블록체인의 복사본을 최신 상태로 유지하기 위해 끊임없이 다른 노드와 통신한다. 또한 블록을 채굴하고, 블록체인에 트랜잭션을 추가하고 블록의 트랜잭션을 검증하며 트랜잭션을 실행할 수도 있다. 그리고 RPC를 통해 상호작용할 수 있는 API를 노출하여 서버 역할을 하기도 한다.

 

Parity

패리티(Parity)는 이더리움 프로토콜의 또 다른 구현체이며, 러스트(Rust) 프로그래밍 언어로 개발되었다. 현재 Parity Inc. 라는 기업에서 운영하고 있다.

이더리움 네트워크에 접속할 수 있는 클라이언트 소프트웨어를 개발하는 길은 누구에게나 열려 있으며, C++, 파이썬 및 다른 언어로 작성된 클라이언트도 있다.

 

 

위 2개의 이더리움 프로토콜에 대해서 개발자의 측면에서 설치하고 통신하는 법을 설명해보겠다. (리눅스 기반)

 

코인거래소에서 일해본 개발자라면 알듯이 코인을 상장하려면 아래의 과정을 따라야 한다.

 

1. 해당 코인의 RPC API를 지원하는 소프트웨어를 확인하고 그것을 서버 PC에 설치

2. 그 소프트웨어를 알맞은 명령어를 입력하여 실행하여, 지갑 저장 디렉토리, 체인 db 디렉토리를 설정

 (실행 명령어는 보통 bitcoind, parity, geth 등 simple함.)

3. 블록 syncing이 정상적으로 완료되면, 직접 코딩하거나 RPC 라이브러리를 활용하여 서버 PC의 해당 port에 연결

4. 정상적으로 통신이 되면 Web3j같은 RPC 라이브러리에서 제공하는 명령어를 통하여 입출금, 잔액 조회 등의  행동을 함

 

다음화에서는 Geth에 대해서 설치하고 API연결하는 법을 알아본다.

 

 

+ Recent posts