정리하기에 앞서 알아두어야할 점은 Synchronous, Asynchronous 와 Blocking, Non-Blocking 은 서로 비교 가능한 개념들이 아니다. 많이들 기술 먼저 습득하다보니(특히 NodeJS), 개념을 먼저 습득하기보다는, 특징을 먼저 배우는 터라 개념이 혼용되어서 쓰이는 경우가 많을 뿐이다.


동기(Sync) 와 비동기(Async)


<Synchronous I/O Model>


Sync와 Async 를 구분하는 기준은 작업 순서이다.

동기식 모델은 모든 작업들이 일련의 순서를 따르며 그 순서에 맞게 동작한다. 즉, A,B,C 순서대로 작업이 시작되었다면 A,B,C 순서로 작업이 끝나야 한다. 설령 여러 작업이 동시에 처리되고 있다고 해도, 작업이 처리되는 모델의 순서가 보장된다면 이는 동기식 처리 모델이라고 할 수 있다. 

많은 자료들이 동기식 처리 모델을 설명할 때, 작업이 실행되는 동안 다음 처리를 기다리는 것이(Wait) Sync 모델이라고 하지만, 이는 잘 알려진 오해이다. 이 Wait Process 때문에 Blocking 과 개념의 혼동이 생기는 경우가 흔하다. 동기 처리 모델에서 알아두어야할 점은 작업의 순서가 보장된다는 점 뿐이다.

동기식 처리 모델은 우리가 만드는 대부분의 프로세스의 로직이며, 특히 Pipeline 을 준수하는 Working Process 에서 매우 훌륭한 모델이다.


<Asynchronous I/O Model>


반면 비동기식 모델은 작업의 순서가 보장되지 않는다. 말그대로 비동기(Asynchronous) 처리 모델로, A,B,C 순서로 작업이 시작되어도 A,B,C 순서로 작업이 끝난다고 보장할 수 없다.

비동기식 처리 모델이 이득을 보는 경우는 각 작업이 분리될 수 있으며, Latency 가 큰 경우이다. 예를들어 각 클라이언트 또는 작업 별로 Latency 가 발생하는 네트워크 처리나 File I/O 등이 훌륭한 적용 예시이다.



블로킹(Blocking) 과 넌블로킹(Non-Blocking)


Blocking 과 Non-Blocking 을 구분하는 기준은 통지 이다.

Blocking 이란 말그대로 작업의 멈춤, 대기(Wait) 을 말한다. 즉, 작업을 시작하고 작업이 끝날때까지 대기하다가 즉석에서 완료 통지를 받는다.

이 때 작업이 멈추는 동안 다른작업이 끼어들수 있는지 없는지는 다른 얘기이다. 이부분이 중요하면서도 헷갈린데, 많은 Blocking 방식의 사례에서 다른 작업의 Interrupt 를 방지하기 때문에, Blocking 은 곧 "순차처리" 로 생각하는 오류가 생긴다. (이렇게 생각해버리면 Blocking 과 Synchronous 모델은 같은 개념이 된다.)

단순히 생각해서 Blocking 은 그저 작업을 수행하는 데 있어서 대기 시간을 갖는다는 의미일 뿐이다.


Non Blocking 이란 작업의 완료를 나중에 통지받는 개념이다. 작업의 시작 이후 완료시까지 대기하지 않고, 완료시킨다. 

즉, 내부 동작에 무관하게 작업에 대한 완료를 처리받는 걸 말한다.

(작업의 예약 부분이 오히려 비동기 설명과 오해를 불러오는 듯 하여 수정했습니다.)

효과적인 작업 상태의 처리를 위해 Non-blocking 에서는 성공, 실패, 일부 성공(partial success) 라는 3가지 패턴이 존재한다.

한 작업에 대해 대기 Queue 와 무관하게 다른 작업을 처리하는 효율적인 알고리즘 처리 시, 각 작업의 완료들의 순서가 보장되지 않는 경우가 많기 때문에 Async 와 헷갈릴 수 있지만, 이들은 앞서 언급했듯이 비교할 수 없는 다른 개념이다.



오해


많은 종류의 소프트웨어에서 동기 처리 방식이 Blocking 이고, 비동기 처리 방식이 Non-Blocking 인 이유는 익숙한 구조이기 때문이다.

일련의 작업들에 대해 순차적으로 하나씩 처리하고 완료하는 방식은 매 작업의 수행마다 Blocking 하는게 작업의 순서를 보장하기 쉬우며,

여러 작업들이 동시에 일어나는 구조에서는 한 작업을 수행하는 동시에 Non-Blocking으로 다른 작업을 받아와서 처리하는 구조가 효율적이다.

그렇기 때문에 같은 개념으로 혼동하기 쉽지만, 동기/비동기와 블로킹/논블로킹은 서로 양립할 수 있는 개념이란걸 기억하자.



정리한 개념을 통해 System I/O 의 모델들에 대해 이해해보자.


- Synchronous Blocking I/O : Application layer 의 계층이 Block을 일으키는 System Call을 호출하고, 이에 따라 User Layer와 Kernel Layer 간의 Context Switching 이 발생한다. 

이 때, Application 은 CPU 를 사용하지 않고 Kernel 의 응답을 기다리게 된다.


- Synchronous Non-blocking I/O : Nonblock Kernel Systemcall 을 사용하기 때문에 더 향상된 것처럼 보이지만, 

User Layer 가 Synchronous 이므로 응답을 기다리는 동안 Kernel 의 System Call을 Polling 하게 된다. 당연히 Context Switching 빈도수가 늘어나기 때문에 더 I/O에 지연이 발생하게 된다.


- Asynchronous Blocking I/O : User Layer의 I/O 가 Non-blocking 이고 Kernel 에서 알림이 블로킹 방식이다. Select System call 이 이 방식의 대표적이며 여러 I/O 를 한번에 수행할 수 있는 모델이다.


- Asynchronous Non-blocking I/O : Kernel I/O 의 개시와 알림 두 차례만 Context Switching 이 발생하고, Kernel 작업이 Non-block 이므로 select() 와 같은 멀티플렉싱 뿐 아니라 다른 프로세싱 자체가 가능하다. 

Kernel level 에서의 응답은 Signal 이나 Thread 기반 Callback 을 통해 user level 로 마치 이벤트처럼 전달된다.


OS 레벨에서 프로세스들의 동작 처리는 비동기 처리 모델 방식으로 진행된다. 각 프로세스 내에서 처리는 작업의 순서가 보장되는 동기 처리 방식이지만, 커널 레벨의 관점에서는 커널의 리소스를 사용하는 모든 작업들의

순서를 지켜줄 수 없으며, 커널 동작의 관점에서 보면 비동기 처리 모델을 사용한다. 

즉, 시스템 프로그래밍 윗 레벨에서의 대부분의 작업 모델은 동기 처리이지만, 커널 레벨에서 프로세스의 운용은 비동기 처리로 볼 수 있다.

물론 각 프로그램들이 동기 / 비동기 중 어떤 방식으로 내부 로직을 처리하는 가는 별도의 문제이다.



추가로 NodeJS 포스팅에서 언급할 예정이지만, NodeJS 는 Async I/O 처리를 위해 libuv 를 사용하는데, 이 엔진은 default thread를 4개 사용하여 Async I/O 를 구현한다. 결국 Async 라 해도 마법은 아니며, 구현의 레벨로 보자면 Scheduling 과 Loop 의 문제이다.


참조 : https://docs.microsoft.com/en-us/windows/desktop/FileIO/synchronous-and-asynchronous-i-o





서버 인스턴스를 관리하면서 자주 사용하게 되는 몇가지 시스템 모니터링을 위한 유틸리티 들을 정리해보았다



- Top : 시스템의 전반적인 운용상황을 확인할 수 있다. CPU / 메모리 / 부하율 등을 한번에 확인할 수 있다. Top –d 2 와 같이 하면 초단위로 refresh 한다. –q로 하면 실시간으로 반영된다. 윈도우의 작업 관리자와 같은 역할을 수행한다.


- Uptime : 서버의 전체적인 부하율을 확인하고자 할 때 사용한다

그냥 uptime 만 치면 한줄로 출력이 되며 현재시간, 부팅 후 꺼지지않고 운용된 시간, 현재 시스템에 로그인한 사용자 수(/var/run/utmp참조), 1분, 5분, 15분 간 서버 시스템 부하율 을 표기한다.


- Vmstat : 현재 리눅스 자원사용률 모니터링 도구로, 이름은 Virtual Memory Statistics 이지만 가상 메모리 이외에 실행 대기 중인 프로세스 수(r), 가상 메모리 사용량(swpd), 입출력 IO, 유휴 메모리(free), 버퍼 메모리(buff), 캐시 메모리(cache), 초당 인터럽트 수(in), 초당 컨텍스트 스위칭 수(cs), 유휴시간(id), 커널모드 소비 시간(sy), 입출력대기시간(wa) 등 다양한 내용 조회 가능하다.


- Iostat : 부팅 이후 Block IO 상태를 나타낸다.


- Free : 메인 메모리 사용량을 보여준다.


- Strace : System call tracer. 리눅스 최강의 디버깅 도구. 리눅스 시스템콜 추적 도구. 프로세스 대상을 선택하면 대상에 대한 시스템콜을 추적할 수 있고 프로세스가 받는 Signal에 대한 정보도 얻을 수 있다. 

간단하게 strace ./helloWorld 와 같이 사용하면 helloWorld 프로그램을 추적하게 되고 –o trace.log 와 같이 매개변수를 넘겨주면 trace.log 파일에 추적 로그가 남게 된다. 또한 –c 옵션을 이용해 통계도 낼 수 있다. –p 옵션을 사용하면 실행중인 프로세스에 대한 추적 또한 가능하다. 


- Tcpdump : 커맨드라인 네트워크 트래픽 모니터링 툴이자 패킷 분석 툴. 

Tcpdump –I eth0 과 같이 사용하면 지정된 eth0이더넷에 대해 패킷을 뜨게 되고 –w test.log 와 같이 test.log 에 로그를 기록할 수 있다. 확인은 –r test.log 와 같은 방식으로 해야 한다. 혹은 당연히 tcpdump –I eth0 > testout.log 와 같이 리다이렉트해줘도 된다.


- Netstat : 시스템의 네트워크 연결 목록(tcp, u에, 소켓)을 보여준다. 

Tcp (t), udp(u), DNS 질의끄기(n), Listen(l), 프로세스 명 표시(p), 라우팅정보(r) 과 같은 파라미터를 –뒤에 붙여 사용한다. 

(ex) netstat -nltp


- lsb_release -a : 리눅스의 버전을 확인하는 명령어. 특히 Dependency 관리를 위해 알아볼 때 종종 사용한다.

cat /etc/issue : 리눅스의 버전을 확인하는 명령어. 몇몇 버전의 경우 /etc/issue 에 버전 정보가 포함되어 있다.

- stat : 파일 또는 파일 시스템 상태를 조회한다. 파일크기, Inode 번호, 링크 갯수, Permission, UID, GID, 접근/수정/변경 일시 확인 가능하다.

(예시)

> stat xxx.log
File: ‘xxx.log’
Size: 11008296 Blocks: 21512 IO Block: 4096 regular file
Device: -----/----- Inode: 269769074 Links: 1
Access: (0644/-rw-r--r--) Uid: ( 500/ user) Gid: ( 500/ user)
Access: 2018-10-04 00:00:03.158986433 +0900
Modify: 2018-10-04 15:02:18.999757886 +0900
Change: 2018-10-04 15:02:18.999757886 +0900
Birth: -

> stat -f xxx.log

File: ‘xxx.log’
ID: -----------        Namelen: 255 Type: xfs
Block size: 4096 Fundamental block size: 4096
Blocks: Total: 25677313 Free: 23658809 Available: 23658809
Inodes: Total: 102759424 Free: 102490423


- du(disk usage) : directory 용량 확인. 현재 폴더 내 파일들의 용량을 확인할 수 있다.

- df : 리눅스 파일시스템 사용량 확인. 디스크 사용량 / 용량 포함.


- find : 파일 이름으로 시스템을 검색하는 명령어

 (1) find -name "파일이름"     > 파일이름에 해당하는 파일 검색

 (2) find -name "*.txt"     > 파일 확장자가 txt인 모든 파일 검색

 (3) find / -name "*.txt"     > 루트에서부터 txt 확장자를 가진 모든 파일 탐색

 (4) find / -name "code" -type d  > 디렉터리 이름이 code 인 모든 디렉토리 검색






리눅스에서 사용되는 Alias란 긴 명령어나 복잡한 명령어 등을 사용자가 알맞게 정의하여 사용할 수 있도록 저장해놓고 불러올 수 있게 하는 별칭을 정하는 기능이다.


 예를 들어 관리해야할 여러 서버가 있고, 우리는 Linux 쉘에서 login 명령어를 통해 각 서버에 접속할 수 있다고 가정해보자.

이 때 개발 서버(dev)는 login 명령어를 통해 바로 접근할 수 있지만 실제 운영 서버(real)는 보안 키워드인 -secure 를 입력해야한다고 가정해보자. 가령


login dev_001                    > 1번 개발서버에 로그인


login -secure real_001          > 1번 운영서버에 로그인


서버가 많아지고 커맨드가 다양해진다면 타이핑은 매우 불편하며 효율적이지도 않다.


이 때 alias 키워드를 쓰면 좀더 단순해질 수 있다.


Alias 키워드를 사용하면 login “SERVER명” 과 같이 긴 명령어도 login_server 와 같은 명령어로 치환할 수 있다.


 Alias 설정을 보기위해서는 alias 커맨드를 입력하면 된다.

Alias 의 추가를 위해서는 ~/.bashrc 파일을 열어서 alias 단축명=’실행할명령어’ 를 입력해주면 된다. 이 후 /.bashrc 파일의 적용을 위해서 source ~/.bashrc 를 명령어로 입력하면 된다.


위의 예시에 적용해보자.



<~/.bashrc>


alias dev_001='login dev_001'


alias real_001='login -secure real_001'



위와 같이 설정하면, 이제 쉘에서는


dev_001                            > 1번 개발 서버에 로그인


real_001                            > 1번 운영 서버에 로그인


과 같은 단순한 키워드로 커맨드 이용이 가능하다. 활용도가 무궁무진하니 자주 쓰는 명령어로 꼭 익혀두자



 Grep 은 워낙 유명한 리눅스의 패키지이며 그만큼 쓸일이 많으므로 다음의 기본 사용법 정도는 꼭 알아두도록 하자.


 Grep 명령어는 파일 전체를 뒤져서 정규표현식에 해당하는 모든 행들을 출력하는 기능을 한다.


(ex) grep nw datafile -> datafile에서 nw를 포함하는 행 검색


grep nw d* -> d로 시작하는 모든 파일에서 nw를 포함하는 행을 검색


grep <keyword> * -> 모든 파일에서 키워드를 검색


grep '^n' datafile -> n으로 시작하는 datafile 내의 모든 행을 출력


grep '4$' datafile -> 4로 끝나는 datafile 내의 모든 행을 출력


grep '[^0-9]' datafile -> datafile 내에서 숫자가 아닌 문자를 하나라도 포함하는 모든 행을 출력


grep '[a-z]{9}' datafile -> datafile 내에서 소문자가 9번 이상 반복되는 문자열을 포함하는 모든 행을 출력한다.



 grep 실행시 다음 옵션을 부여함으로써 유용하게 정보를 가공할 수도 있다.


-r(하위 디렉토리를 모두 검사)

 

-n(행 번호를 함께 출력)


-i(대소문자 미구분)


-l(행 대신 파일명만 출력)


-w(정확히 일치하는 경우만 검색)


-v(포함되지 않은 행을 출력)


주로 사용하는 건 위의 옵션들이다. 더 많은 옵션은 다음 링크를 참조하자. 예제도 아주 잘 정리되어있다.

(https://en.wikibooks.org/wiki/Grep)


(ex) grep -v 'ffl' datafile > edit

// datafile에서 ffl이 있는 행만을 추출하여 edit 파일에 씀.


(ex) grep -rl "*print$"

// 현재 폴더를 루트로 하여 서브 디렉토리를 모두 검사하여 print 로 끝나는 행을 가진 파일의 이름을 출력.


 특히 서버에서 로그 분석 작업을 할 때, Grep 은 tail 과 함께 밥먹듯이 사용한다.

어느정도 프로젝트에서 자주 사용하는 정규식 포맷을 메모하여 grep 사용 시 적용시키는게 유용하다.




 실무를 하다보면 프로젝트에 따라 배치 스크립트를 작성할 일이 종종 있다.

그럴 때 듣게 되는 Daemon Process 라는 단어가 있는데, Background Process와 유사하면서도 의미가 조금 달라 헷갈리기 쉽다.


 Daemon Process 와 Background Process 모두 사용자와 상호작용하는 Foreground가 아닌 Background에서 동작하지만 둘 사이에는 차이가 있다. 


 일반적인 데몬은 터미널을 갖지 않는다. (유저와 상호작용하지 않는다.) 정확히는 데몬은 그 자체로 Process Group Leader로 부모가 1번 pid를 갖는 init으로 세팅된다. 즉, 독자적인 Session 을 갖고있으며 Linux System 자체가 아닌 별도의 독립된 Parent process를 갖지 않는다. 리눅스의 cron, smartd 와 같은 스케줄링 & 모니터링 프로세스들은 바로 이 Daemon Process 의 형태를 갖는다.


 백그라운드 프로세스는 이와 다르게 터미널을 통해 상호작용이 가능하다. 별도의 Parent process를 가질 수 있으며 Parent process와 세션이 공유되기 때문에 Parent process가 받는 Signal 의 영향을 받는다. (부모 프로세스가 종료되면 같이 종료된다.)



 Daemon Process의 조건 3가지는 다음과 같다.

(1) Fork로 자식 프로세스 생성 후 부모 프로세스를 종료 – 자식 프로세스의 ppid(소유 프로세스)를 pid 가 1인 init으로 양도


(2) Setsid를 이용하여 새로운 세션을 만들고 생성된 자식의 pid가 세션의 제어권을 가지도록 한다. – 세션이란 프로그램 그룹의 모음인데 세션 생성시 ttv를 부여하지 않게 되면 터미널을 갖지 않는 세션이 생겨나며 세션의 리더가 된다.


(3) 프로세스의 위치를 루트로 옮겨주면 경로 작업 수행에 유리하다(선택)


 * 또한 윈도우에서는 데몬을 서비스라고 부른다.




리눅스에서 서버를 구축 시 별도의 파티션을 마운트 하는 경우가 종종 있다.


특히 운영 중이던 서버에 로그를 위한 파티션이나, Static inhouse 를 위한 독립된 저장소를 구축하는 경우가 있다.


주로 이런 리소스 들을 인프라팀에서 제공해주긴 하지만, 결국 인스턴스에 알맞게 사용하는건 개발팀의 몫이 되는데, 간단히 마운트 하는 방법을 정리해보았다.


1.      Sudo fdisk -l df 명령어를 통해서 파티션 정보를 확인한다. (타겟 /dev/xvdf)


2.      Mkfs -t (파일시스템타입) /dev/xvdf 명령어를 이용해서 마운트하고자 하는 파일 시스템을 생성 포맷한다.


3.      Sudo mount /dev/xvdf /srv : /srv 폴더에 /dev/xvdf 디스크를 마운트한다.


매우 간단하지만 리눅스의 명령어들이 흔히 그렇듯 사용하지 않으면 까먹게 된다.


자주 사용할 일은 없지만 정리해놓고 알아두도록 하자.




개인적인 목적으로 사용할 때에나 개발을 위한 더미 환경을 구축해서 사용할 때나 VirtualBox 는 좋은 도구이다.(무료이기도 하고...)


처음에 환경을 세팅할 때 잘 몰랐던 부분 중 하나인 네트워크 세팅 방법을 정리해두었다.


(1) NAT : 각 가상머신을 별도의 가상 네트워크로 할당하여 호스트를 Gateway로 한 NAT를 구성하는 방식이다. 가상 머신이 호스트와 별도의 네트워크로 묶이기 때문에 가상머신 끼리의 연결은 지원되지 않는다.


(2) Bridged Network : 호스트 네트워크를 이용한 Bridged Network를 구성한다. 호스트와 동일하게 사용할 수도 있고 혹은 별도의 네트워크 설계도 가능하다. 단, IP 구성이 원활하지 않은 경우에 제한적이다.


(3) Host Only Network : Internal network 처럼 호스트와 격리된 네트워크를 구성하지만 호스트와 통신이 지원되고 DHCP를 이용한 IP할당이 가능하다. 가상머신들과 호스트 간의 네트워킹은 가능하나 인터넷이 안되므로 NAT방식과 같이 사용된다.


이 외에도 몇가지 방식들이 더 있으나, 하위호환 되면서 유명한 3가지 방법들만 정리해두었다.


방법들이 다양하지만 관건은 독립된 가상환경의 OS를 같은 망으로 묶을 것인가 아니면 별도의 독립 망으로 연결하고 터널링을 할 것인가에 따라 분류되는 듯 하다.


이 방법들을 활용하면 VM에서 직접 인터넷에 붙이거나 아니면 호스트의 인터넷 연결을 빌려 사용하거나, 또는 설정을 하지않음으로써 Private Subnet 처럼 가상환경을 구성할 수도 있다.


필자의 경우에는 주로 더미 환경 구축에 사용하므로 Private Subnet 으로 격리시키고 이런저런 테스트를 해보는 편이다.




배치 작업을 할때, 이용할 수 있는 도구는 많지만 개인적으로 가장 손꼽는 프로그램은 Linux 에서 기본적으로 제공해주는 크론탭(Crontab) 이라고 생각한다. 사용하기도 쉽고 강력한 스케줄링 기능을 할 수 있다.


다음은 크론탭의 사용방법이다.


- crontab -e : 크론탭 편집기 실행. VI 가 기본으로 실행된다.

- crontab -i : 크론탭의 내용 조회


- 크론탭 작성 방법


*                *                    *                *                *

분(0-59)       시간(0-23)       일(1-31)       월(1-12)       요일(0-7)


- 매분 실행

* * * * * /home/script/test.sh


- 특정 시간 실행

# 매주 월요일 오전 5시에 test.sh 실행

0 5 * * 5 /home/script/test.sh


- 반복 실행

# 매일 매시간 0분, 20분, 40분에 test.sh 실행

0, 20, 40 * * * * /home/script/test.sh


- 범위 실행

# 매일 1시 10분 부터 30분까지 매분 test.sh 실행

10-30 1 * * * /home/script/test.sh


* 크론탭은 한줄에 한 명령어만 작성해야 하며 #을 통해 주석을 달 수 있다.


또한 실행하는 쉘에 Redirection (>) 을 연결함으로써 출력을 리다이렉트할 수 있으며 이를 통해 로깅이 가능하다.


 Linux 서버 관리를 하다가 가장 자주 마주치는 것 중 하나가 서버의 포트 및 방화벽 문제라고 할 수 있는데 삽질하면서 알아낸 바를 적는다.


 : 리눅스에서 열린 포트를 확인 하는 방법

 - netstat -tnlp : 상태를 인 아웃 port 정보를 포함해서 볼 수 있다.


 : CentOS, Fedora 등의 리눅스에서 포트 방화벽을 확인 하는 방법

-    iptables -list

-    iptables -L(리스팅) -v(자세히)


 : Ubuntu 에서 포트 방화벽을 확인하는 방법

-    sudo ufw status


 : Ubuntu 에서 포트 방화벽을 활성화 / 비활성화 하는 방법

-    sudo ufw enable

-    sudo ufw disable


 : CentOS, Fedora 등의 리눅스에서 포트를 추가하는 방법

-    iptables -I INPUT 1 -p tcp -dport 80 -j ACCEPT  (80 Input 포트를 1번으로 추가)

-    iptables -I OUTPUT 2 -p tcp -dport 8080 -j ACCEPT     (8080 Output 포트를 2번으로 추가)


 : Ubuntu 에서 포트를 추가하는 방법

-    sudo ufw allow <port>/<optional: protocol> (sudo ufw allow 443/tcp)


 : CentOS, Fedora 등의 리눅스에서 포트 예외를 제거하는 방법

-    iptables -D INPUT 2   (INPUT 2번째 규칙 제거)


 : Ubuntu 에서 포트를 제거하는 방법

-    sudo ufw deny <port>/<optional: protocol>


 : Iptables 를 이용한 포트포워딩

-    iptables -t nat -A PREROUTING -p tcp -m tcp dport 80 -j REDIRECT to-ports 8080

-    iptables -t filter -A FORWARD -p tcp -m tcp dport 80 -j ACCEPT

 

 * 이 글을 정리할 때를 돌아보자면 클라우드 VM에서 자체 방화벽을 잘못 건드려서 2차 참사를 유발한 케이스였다, 당시 사내 플랫폼은 유일한 게이트웨이에서 리눅스 서버에 접속할 수 있도록 허용되어 있었는데, 이 부분이 기존 사내 플랫폼 방화벽에 WhiteList로 등록되어있지 않은 상태에서 방화벽을 걸어버려서, 인스턴스 하나를 날린 참사가 일어났었다... ㅡㅡ 

방화벽 설정은 각별히 주의하자.




+ Recent posts