Apache HTTP Server Version 2.1

Apache > HTTP Server > Documentation > Version 2.1 > 가상호스트

# 가상호스트 예

가능한 언어: en | ko

이 문서는 자주 문의되는 가상호스트 질문에 답을 하려고 쓰여졌다. 상황은 이름기반이나 IP기반 가상호스트를 통해 한 서버에서 여러 웹사이트를 서비스하려는 경우이다. 한 프록시 서버 뒤에서 여러 서버를 사용하여 사이트를 운영하는 경우를 다룬 문서도 곧 나올 것이다.

## IP 주소 한개에 여러 이름기반 웹사이트 운영하기.

서버에 IP 주소가 한개 있고, DNS에서 여러 주소(CNAMES)가 이 컴퓨터를 가리킨다. 이 컴퓨터에서 `www.example1.com`과 `www.example2.org`의 웹서버를 실행하고 싶다.

### Note

아파치 서버에 가상호스트 설정을 한다고 그 호스트명에 대한 DNS 항목이 자동이로 생성되지 않는다. 반드시 DNS에 IP 주소를 가리키는 이름이 있어야 한다. 안그러면 아무도 웹사이트를 볼 수 없다. 검사해보기 위해 `hosts` 파일에 항목을 추가할 수 있지만, 이는 hosts 항목을 가진 컴퓨터에만 반영된다.

### 서버 설정

`# 아파치가 포트 80을 기다린다
Listen 80
# 모든 IP 주소에서 가상호스트 요청을 기다린다
NameVirtualHost *
<VirtualHost *>
DocumentRoot /www/example1
ServerName www.example1.com
# 다른 지시어들도 있다
</VirtualHost>
<VirtualHost *>
DocumentRoot /www/example2
ServerName www.example2.org
# 다른 지시어들도 있다
</VirtualHost>`

별표는 모든 주소를 가리키므로, 주서버는 어떤 요청도 서비스하지 않는다. `www.example1.com`이 설정파일에 처음으로 나오므로 가장 높은 우선순위를 가지며, 기본혹은 초기 서버가 된다. 어떤 `ServerName` 지시어에도 해당되지않는 요청은 첫번째 `VirtualHost`가 서비스한다.

### 주의

원한다면 `*` 대신 시스템의 실제 IP 주소를 사용할 수 있다. 이 경우 `VirtualHost`의 아규먼트는 `NameVirtualHost`의 아규먼트와 일치해야 한다:

`NameVirtualHost 172.20.30.40
<VirtualHost 172.20.30.40>
# 생략 ...`

그러나 ISP에서 동적으로 IP 주소를 가져오는 등 IP 주소를 모르는 경우에는 `*`를 사용하는 것이 유용하다. `*`는 모든 IP 주소에 해당하므로, IP 주소가 변경되어도 설정을 변경할 필요가 없다.

거의 대부분의 이름기반 가상호스트 설정은 위와 같다. 예외는 다른 IP 주소나 포트로 다른 내용을 서비스하려는 경우이다.

## 여러 IP 주소에서 이름기반 호스트.

### 주의

여기서 설명한 방법은 IP 주소가 몇개라도 적용가능하다.

서버는 IP 주소가 두개있다. 하나에서 (`172.20.30.40`) "주" 서버 `server.domain.com`을 서비스하고, 다른 하나에서 (`172.20.30.50`) 여러 가상호스트를 서비스할 것이다.

### 서버 설정

`Listen 80
# 172.20.30.40에서 실행하는 "주"서버이다
ServerName server.domain.com
DocumentRoot /www/mainserver
# 다른 주소다
NameVirtualHost 172.20.30.50
<VirtualHost 172.20.30.50>
DocumentRoot /www/example1
ServerName www.example1.com
# 다른 지시어들도 있다 ...
</VirtualHost>
<VirtualHost 172.20.30.50>
DocumentRoot /www/example2
ServerName www.example2.org
# 다른 지시어들도 있다 ...
</VirtualHost>`

`172.20.30.50`이 아닌 주소에 대한 요청은 주서버가 서비스한다. 호스트명 없이, 즉 `Host:` 헤더없이 `172.20.30.50`로 요청하면 `www.example1.com`이 서비스한다.

## (내부와 외부 주소와 같이) 다른 IP 주소로 같은 내용을 서비스하기.

서버 컴퓨터에 IP 주소가 두개 (`192.168.1.1`과 `172.20.30.40`) 있다. 컴퓨터는 내부 (인트라넷) 네트웍과 외부 (인터넷) 네트웍 사이에 위치한다. 네트웍 밖에서 `server.example.com`은 외부 주소를 (`172.20.30.40`) 의미하고, 네트웍 내부에서 같은 이름을 내부 주소로 (`192.168.1.1`) 사용한다.

서버는 `VirtualHost` 섹션 한개로 내부와 외부 응답에 같은 내용을 서비스할 수 있다.

### 서버 설정

`NameVirtualHost 192.168.1.1
NameVirtualHost 172.20.30.40
<VirtualHost 192.168.1.1 172.20.30.40>
DocumentRoot /www/server1
ServerName server.example.com
ServerAlias server
</VirtualHost>`

이제 두 네트웍에서 들어온 요청을 같은 `VirtualHost`에서 서비스한다.

### 주의:

내부 네트웍에서는 완전한 호스트명 `server.example.com` 대신 이름 `server`도 가능하다.

또한 위의 예에서 IP 주소 대신 `*`을 사용하여 서버가 모든 주소에 동일하게 동작할 수 있다.

## 여러 포트에서 서로 다른 사이트 운영하기.

같은 IP의 여러 포트에서 서로 다른 도메인을 서비스한다고 가정하자. 이는 "NameVirtualHost" 태그에 포트를 정의하면 가능하다. NameVirtualHost name:port없이 <VirtualHost name:port>만 혹은 Listen 지시어만 사용하면 안된다.

### 서버 설정

`Listen 80
Listen 8080
NameVirtualHost 172.20.30.40:80
NameVirtualHost 172.20.30.40:8080
<VirtualHost 172.20.30.40:80>
ServerName www.example1.com
DocumentRoot /www/domain-80
</VirtualHost>
<VirtualHost 172.20.30.40:8080>
ServerName www.example1.com
DocumentRoot /www/domain-8080
</VirtualHost>
<VirtualHost 172.20.30.40:80>
ServerName www.example2.org
DocumentRoot /www/otherdomain-80
</VirtualHost>
<VirtualHost 172.20.30.40:8080>
ServerName www.example2.org
DocumentRoot /www/otherdomain-8080
</VirtualHost>`

## IP기반 가상호스트

서버는 각각 `www.example1.com`과 `www.example2.org`에 해당하는 두 IP 주소를 (`172.20.30.40`과 `172.20.30.50`) 가진다.

### 서버 설정

`Listen 80
<VirtualHost 172.20.30.40>
DocumentRoot /www/example1
ServerName www.example1.com
</VirtualHost>
<VirtualHost 172.20.30.50>
DocumentRoot /www/example2
ServerName www.example2.org
</VirtualHost>`

`<VirtualHost>` 지시어로 지정한 주소에 해당하지않는 주소로 (예를 들어, `localhost`) 요청이 들어오면 주서버가 있는 경우 주서버가 서비스한다.

## 포트기반과 ip기반이 혼합된 가상호스트

서버는 각각 `www.example1.com`과 `www.example2.org`에 해당하는 두 IP 주소를 (`172.20.30.40`과 `172.20.30.50`) 가진다. 각 IP의 80번과 8080번 포트에 가상호스트를 돌린다.

### 서버 설정

`Listen 172.20.30.40:80
Listen 172.20.30.40:8080
Listen 172.20.30.50:80
Listen 172.20.30.50:8080
<VirtualHost 172.20.30.40:80>
DocumentRoot /www/example1-80
ServerName www.example1.com
</VirtualHost>
<VirtualHost 172.20.30.40:8080>
DocumentRoot /www/example1-8080
ServerName www.example1.com
</VirtualHost>
<VirtualHost 172.20.30.50:80>
DocumentRoot /www/example2-80
ServerName www.example1.org
</VirtualHost>
<VirtualHost 172.20.30.50:8080>
DocumentRoot /www/example2-8080
ServerName www.example2.org
</VirtualHost>`

## 이름기반과 IP기반이 혼합된 가상호스트

주소중 몇몇은 이름기반 가상호스트로, 다른 것은 IP기반 가상호스트로 서비스하고 싶다.

### 서버 설정

`Listen 80
NameVirtualHost 172.20.30.40
<VirtualHost 172.20.30.40>
DocumentRoot /www/example1
ServerName www.example1.com
</VirtualHost>
<VirtualHost 172.20.30.40>
DocumentRoot /www/example2
ServerName www.example2.org
</VirtualHost>
<VirtualHost 172.20.30.40>
DocumentRoot /www/example3
ServerName www.example3.net
</VirtualHost>
# IP-기반
<VirtualHost 172.20.30.50>
DocumentRoot /www/example4
ServerName www.example4.edu
</VirtualHost>
<VirtualHost 172.20.30.60>
DocumentRoot /www/example5
ServerName www.example5.gov
</VirtualHost>`

## `_default_` 가상호스트 사용하기

### 모든 포트에 대한 `_default_` 가상호스트

어떤 가상호스트에도 해당하지않은 IP 주소와 포트에 대한 모든 요청을 처리하기.

### 서버 설정

`<VirtualHost _default_:*>
DocumentRoot /www/default
</VirtualHost>`

default(기본) 가상호스트의 포트로 와일드카드를 사용하여 어떤 요청도 주서버로 못가도록 만든다.

default 가상호스트는 절대로 이름기반 가상호스트가 사용하는 주소/포트로의 요청을 서비스하지 않는다. 알 수 없거나 `Host:` 헤더가 생략된 요청은 항상 최초의 이름기반 가상호스트(설정파일에서 주소/포트가 처음으로 나온 가상호스트)가 서비스한다.

`AliasMatch`나 `RewriteRule`을 사용하여 어떤 요청을 특정 페이지(혹은 스크립트)로 재작성할(rewrite) 수 있다.

### 여러 포트에 대한 `_default_` 가상호스트

위의 경우와 같지만, 서버는 여러 포트를 기다리고 80번 포트에 대해서 추가로 `_default_` 가상호스트를 사용하고 싶다.

### 서버 설정

`<VirtualHost _default_:80>
DocumentRoot /www/default80
# ...
</VirtualHost>
<VirtualHost _default_:*>
DocumentRoot /www/default
# ...
</VirtualHost>`

80번 포트에 대한 default 가상호스트는 (반드시 와일드카드 포트를 가진 기본 가상호스트 이전에 나와야 한다) 지정하지않은 IP 주소로 보내진 모든 요청을 서비스한다. 주서버는 절대로 요청을 서비스하지 못한다.

### 한 포트에 대한 `_default_` 가상호스트

80번 포트에 대해서만 default 가상호스트를 만들고 싶다.

### 서버 설정

`<VirtualHost _default_:80>
DocumentRoot /www/default
...
</VirtualHost>`

포트 80번에 지정하지않은 주소에 대한 요청은 기본 가상호스트가 서비스하고, 다른 지정하지않은 주소와 포트를 가진 요청은 주 서버가 서비스한다.

## 이름기반 가상호스트를 IP기반 가상호스트로 옮기기

(이름기반의 첫번째 예에서) 호스트명 `www.example2.org`에 대한 이름기반 가상호스트는 자신의 IP 주소를 가져야 한다. 이름기반 가상호스트의 이전 IP 주소를 캐싱하는 네임서버나 프록시와의 문제를 피하기위해 옮기는 동안 둘 모두를 서비스하고 싶다.
방법은 `VirtualHost` 지시어에 새 IP 주소만을 (`172.20.30.50`) 추가하면되므로 쉽다.

### 서버 설정

`Listen 80
ServerName www.example1.com
DocumentRoot /www/example1
NameVirtualHost 172.20.30.40
<VirtualHost 172.20.30.40 172.20.30.50>
DocumentRoot /www/example2
ServerName www.example2.org
# ...
</VirtualHost>
<VirtualHost 172.20.30.40>
DocumentRoot /www/example3
ServerName www.example3.net
ServerAlias *.example3.net
# ...
</VirtualHost>`

이제 (IP기반 가상호스트를 통한) 새로운 주소와 (이름기반 가상호스트를 통한) 이전 주소 모두 가상호스트에 접근할 수 있다.

## `ServerPath` 지시어 사용하기

두 이름기반 가상호스트를 가진 서버가 있다. 올바른 가상호스트를 선택하기위해 클라이언트는 올바른 `Host:` 헤더를 보내야 한다. 오래된 HTTP/1.0 클라이언트가 이 헤더를 보내지 못하면 아파치는 클라이언트가 어떤 가상호스트를 보려고하는지 알 수 없다 (그래서 최초의 가상호스트가 요청을 서비스한다). 오래된 브라우저와 가능한 호환을 유지하기위해 최초의 가상호스트를 만들고, 여기에 이름기반 가상호스트의 URL 접두사를 포함하는 링크 목록 페이지를 둔다.

### 서버 설정

`NameVirtualHost 172.20.30.40
<VirtualHost 172.20.30.40>
# primary vhost
DocumentRoot /www/subdomain
RewriteEngine On
RewriteRule ^/.* /www/subdomain/index.html
# ...
</VirtualHost>
<VirtualHost 172.20.30.40>
DocumentRoot /www/subdomain/sub1
ServerName www.sub1.domain.tld
ServerPath /sub1/
RewriteEngine On
RewriteRule ^(/sub1/.*) /www/subdomain$1
# ...
</VirtualHost>
<VirtualHost 172.20.30.40>
DocumentRoot /www/subdomain/sub2
ServerName www.sub2.domain.tld
ServerPath /sub2/
RewriteEngine On
RewriteRule ^(/sub2/.*) /www/subdomain$1
# ...
</VirtualHost>`

`ServerPath` 지시어때문에 URL `http://www.sub1.domain.tld/sub1/`에 대한 요청은 항상 subl-가상호스트가 서비스한다.
클라이언트가 올바른 `Host:` 헤더를 보낸다면, URL `http://www.sub1.domain.tld/`에 대한 요청은 subl-가상호스트에서만 서비스한다. 만약 `Host:` 헤더를 보내지않으면 클라이언트는 최초의 호스트에 있는 정보페이지를 보게된다.
여기에 문제가 있음을 주의하라: 클라이언트가 `Host:` 헤더를 보내지않으면 `http://www.sub2.domain.tld/sub1/`에 대한 요청도 subl-가상호스트가 서비스한다.
`RewriteRule` 지시어를 사용하여 올바른 `Host:` 헤더를 보내는 클라이언트는 (예를 들어, URL 전치사가 있거나 없는) 두 URL을 모두 사용할 수 있다.

가능한 언어: en | ko