Nginx 를 이용하여 이름기반 가상 호스트(Name based virtual host)를 구성해보려고 합니다. 엄밀히 말하면 서버 블록(server block)이 맞는 표현일 것입니다. 가상 호스트는 Apache에서 사용하는 용어이기 때문입니다. 하지만 많은 분들에겐 가상 호스트라는 표현이 익숙하므로 제목을 저리 적어보았습니다. 가상 호스트나 이름기반 가상 호스트와 같은 단어의 의미에 대한 설명은 생략하겠습니다. 여기서 전 nginx가 80번 포트로 들어온 두 개의 요청을 받아다가 호스트 네임을 기준으로 판별하여 서로 다른 처리를 하게끔 할 것입니다.

실행환경은 다음과 같습니다.

Nginx 1.10.2
CentOS 7.0

아래의 순서에 따라 진행하겠습니다. 엄밀히 말하면 (1)번과 (2)번은 하나로 합칠 수도 있지만, 좀더 명확하게 가상호스트를 구분해서 이해해보고자 나누었습니다.

(1) 가상 호스트용 설정 파일을 두 개 만든다.
(2) nginx.conf 파일에 위에서 만든 두 개 파일을 include한다.
(3) 출력용 html 파일을 두 개 만든다
(4) hosts 파일을 수정한다

일단 Nginx 가상 호스트(virtual host)를 실행하기 위해선 먼저 기존에 실행되고 있는 apache를 종료해주어야 합니다. 물론 서로 다른 포트 번호를 사용하면 문제가 없지만, 보통은 80번을 공유하고 있는 경우가 많아서, 포트가 겹친다는 사실을 깜빡하고 nginx를 실행하려고 하면, server start부터 되지 않는 현상이 발생합니다. CentOS 7 기준으로 systemctl stop httpd 명령어를 사용해서 실행되고 있던 apache서버를 종료할 수 있습니다.

(1) 가상 호스트용 설정 파일을 두 개 만든다.

Nginx의 설정 파일이 있는 폴더로 가주세요. 저는 /etc/nginx/ 폴더에 설정 파일이 모여있습니다. 임의로 conf.d 폴더 안에 vh_example.conf 란 파일을 만듭니다. 그렇다면 파일의 경로는 /etc/nginx/conf.d/vh_example.conf 가 될 것입니다. 내용물은 다음과 같이 씁니다.


Server {
 listen 80;

 server_name vh_example.com;
 root /var/www/html;
 index index.html
}

먼저 listen 디렉티브를 설명하자면, Nginx로 들어오는 요청(request) 중 포트번호 80번으로 들어오는 요청이 있다면 해당 서버 블록의 내용에 따라 처리를 하겠다는 것입니다. 저 80이라고 써진 부분은, 포트 번호 말고도 ip주소를 써도 됩니다. 또는 호스트 명을 그대로 지정해버리는 것도 가능합니다. 예로 들면 listen 123.4.5.6:80;listen localhost:80;와 같이 써도 된다는 것이겠죠.

문법에 관련된 포스트가 아니므로 이정도만 설명하고 넘어가겠습니다. 그리고 server_name 디렉티브는 호스트명을 지정하는 부분입니다. 외부에서 request가 들어오면 listen 디렉티브가 일차적으로 일치하는지 확인한 뒤, request의 header가 server_name 디렉티브에서 지정한 호스트명과 일치하는지 이차 확인을 거칩니다. 즉 server_name 디렉티브까지 일치할 경우에만, 해당 server 블록의 설정에 따라 실행한다는 겁니다. 엄밀히 말하면 실행하는 게 아니라, 유저가 웹 브라우저 따위에서 볼 수 있게 request가 요청한 파일을 response에 담아 돌려준다는 것이겠죠. 어떤 파일을 돌려주느냐? 그것은 바로 root와 index 디렉티브로 설정이 가능합니다. root는 말그대로 기본경로, 그리고 index.html은 확장자에서부터 알 수 있듯이 파일명입니다. 즉 한 마디로 정리하면 80번 포트로 들어오는 request중 header의 내용물이 vh_example.com인 것이 있다면, /var/www/html/index.html 파일을 response로 돌려주겠다는 의미가 됩니다.

그리고 거의 같은 내용의 파일을 또 하나 만듧니다. 설명은 생략합니다. server_name 디렉티브와 index 디렉티브에 숫자 2를 추가했습니다.

server {
 listen 80;

 server_name vh_example2.com;
 root /var/www/html;
 index index2.html;
}

(2) nginx.conf 파일에 위에서 만든 두 개 파일을 include한다.

그리고 nginx의 기본 설정 파일인 nginx.conf 파일의 http 블록 안에 include 디렉티브를 추가합니다. 다른 서버 블록 안에 추가하지 않도록 조심합니다. Include 디렉티브를 사용함으로써 위에서 만든 두 개의 설정 파일을 http 블록 안에 불러와서 사용하는 셈이 됩니다.

(생략)
http {
… (생략)

Include /etc/nginx/conf.d/*.conf;

… (생략)
}

이 한 줄이 없으면, 위에서 만든 두 설정 파일이 적용되지 않습니다. 엄밀히 말하면 굳이 파일을 두 개 만들어서 include라는 과정을 거칠 것도 없이 nginx.conf 안에 서버 블록을 두개 만드는 방식으로 처리해도 됩니다. 하지만 파일을 나누는 편이 나중에 관리도 편할 뿐더러 육안으로도 구분되기에 가상호스트가 돌아가는 방식을 이해하기도 쉽다고 생각했습니다. 이로써 nginx 쪽 설정은 끝났습니다.

(3) 출력용 html 파일을 두 개 만든다

그럼 이제 여러분이 하실 것은 /var/www/html/ 경로 안에 index.html 파일과 index2.html 파일을 만드는 것입니다. 그 부분은 여러분이 재량껏 내용물을 써서 만들어주심 될 것입니다. 혹 리눅스의 접근 권한 등에 의해 문제가 생길 수도 있으니 chmod 등을 사용해서 폴더나 파일 접근 권한 등을 조절할 필요가 있을 수도 있습니다.

(4) hosts 파일을 수정한다

마지막으로 하실 준비 작업은 etc/hosts 파일을 수정하는 것입니다. 왜냐하면 이제 여러분은 주소입력창에 vh_example.com 또는 vh_example2.com를 입력해서, 제대로 해당 파일이 각각 잘 열리나 시도를 해볼 것인데, 애초에 주소입력창에 위 도메인(호스트명)을 입력하고 엔터를 치면, DNS 요청을 해버리므로 “페이지를 찾을 수 없습니다”라는 에러가 뜨고 말 것입니다. 왜냐하면 위 주소들은 실제로 호스팅이 된 주소가 아니기 때문이죠. 즉 DNS 요청을 보내도 해당 호스트명을 적절한 IP로 바꿔줄 수가 없습니다. 이 부분을 해결하기 위해 여러분은 etc/hosts 파일을 수정해야 합니다. 이 파일은 DNS 요청을 보내기 전에 먼저 탐색되는데, 이는 즉슨 request로 들어온 호스트명(주소입력창에 입력한 도메인명)이 이 곳에 들어있다면, 따로 DNS 요청을 보내지 않고 이 hosts 파일에 적힌 ip와 매핑을 시켜줍니다. 예로 들어 여러분이 해당 파일에 127.0.0.1 vh_example.com이라고 적어놓고, 아무 웹브라우저나 켜서 주소입력창에 vh_example.com을 입력한다면, 서버는 일단 hosts 파일에 적힌 내용에 따라 vh_example.com이란 호스트명을 127.0.0.1로 바꿔서 처리를 해준다는 것입니다. 이렇게 함으로써 여러분도 여러분의 로컬 컴퓨터에서 가상 호스트를 실험해볼 수 있게 되는 것이죠. 이 부분이 잘 이해가 안가셨다면 dns 와 도메인에 대한 개념을 찾아 익혀보시길 권합니다.

일단 CentOS 7.0의 경우 /etc/ 폴더 안에 hosts 파일이 있는데, 이 파일을 수정하시면 됩니다. 기존에 127.0.0.1 이라고 적힌 부분이 있다면, 해당 줄 맨 뒤에 한 칸 띄고 vh_example.com vh_example2.com 을 차례대로 적어주심 됩니다. 아니면 아예 새로 개행을 해서,

127.0.0.1 vh_example.com vh_example2.com

이라고 적어주신 뒤 저장을 하셔도 좋습니다. 이 과정이 없으면 여러분이 아무리 url 입력란에 vh_example.com 또는 vh_example2.com를 입력하더라도 해당 페이지를 찾을 수 없다는 메시지만 받게 될 것입니다.

설정을 마친 후에는, 현재 실행되고 있는 nginx에게 수정된 설정 파일을 덮어씌워야 합니다. ‘systemctl reload nginx.service’ 또는 ‘service nginx reload’라는 명령어로 실행 가능합니다. Reload 명령어는 Restart와는 다르게 서버를 재기동하지 않고 설정파일만 덮어씌워주는 편리한 명령어입니다. 아직 nginx를 실행하고 있지 않았다면 그대로 실행해주심 됩니다. 그리고 systemctl status nginx.service 등의 명령어를 통해 확실히 nginx가 잘 실행되고 있는지 확인하시길 바랍니다.

그 다음에 웹브라우저로 가서 vh_example.com 또는 vh_example2.com라는 도메인을 입력하여, 해당 html 파일이 각각 잘 출력되는지 확인해봅니다.

본 게시글은 2017.02.11 마지막 수정되었습니다