[아파치]mod_rewrite를 이용한 편리한 가상 도메인 운영방법

지리즈의 이미지

웹호스팅하는 서버를 관리하다 보면...
새로운 입주가 발생할 때 마다...
웹서버 세팅을 바꾸어야 하는데..
매우 귀찮은 일임이 틀림없다.

게다가 아파치의 한계로 인해..
무한히 가상 서버를 등록할 수도 없다.
(정확한 수치는 모르나... 100여개 이내로 보인다.)

아파치에는 rewrite라는 아주 훌륭한 기능이 있다.
"mod_rewrite를 사용할 수 없다면
당신이 아파치에서 사용할 수 있는 것은 없다."

라는 말이 있을 정도다.

이글은 rewrite모듈을 이용하여 보다 편리하게
가상도메인을 관리하고자 하는 이들을 위한 작은 팁을 제공한다.

몇가지 전제 조건:

아파치 버전 : > 1.3.20
서버IP : 192.168.0.1
서버기본 도큐먼트루트* : /var/www/html/ (Redhat 기본)
가상도메인들의 루트* : /var/www/vhost/도메인네임
ex) /var/www/vhost/wiki.domain.com/ /var/www/vhost/domain.com/
등록되지 않은 가상도메인들은 모두 서버기본 도큐먼트루트가 시작된다.
(* 상기의 내용은 충분히 변경 가능하다.)

운영방법
가상도메인의 등록이 필요하면..
ftp나 쉘접속으로 /var/www/vhost에
해당 도메인네임과 동일한 디렉토리를 만들어 주는 것으로 마무리된다.

ex) mkdir /var/www/vhost/new.domain.com

그밖의 기능
자동 리다이렉션.
DNS에 *.domain.com 등으로 등록되어 있고,
/var/www/vhost/www.domain.com이란 디렉토리를 생성했을 때
http://domain.com http://foobar.domain.com 모두
http://www.domian.com 으로 자동 리다이렉트가 된다.
하지만, foobar.domain.com란 디렉토리 역시 있을 경우..
http://foobar.domain.com 은 /var/www/vhost/foobar.domain.com으로
연결되고 그밖에는 모두 http://www.domain.com 으로 리다이렉션이 된다.

만약
/var/www/vhost/domain.com으로 등록되어 있을 경우에는
http://www.domain.com http://foobar.domain.com 모두
http://domian.com 으로 리다이렉트가 된다.
여기서도 마찬가지로 foobar.domain.com란 디렉토리 있을 경우..
http://foobar.domain.com 은 /var/www/vhost/foobar.domain.com으로
연결되고 그밖에는 모두 http://domain.com 으로 리다이렉션이 된다.

디렉토리 이름끝에 자동으로 / 붙여주기.
ex) http://domain.com/somedir -> http://domain.com/somedir/

한계
mod_rewrite가 참으로 유용하긴 하나.. 한계도 있다.
일단 alias나 scriptalias가 반영되지 않는다.
및의 예에는 /cgi-bin/이라는 scriptAlias를
rewriteRule를 사용 강제로 반영시키는 예제다..

   ScriptAlias     /cgi-bin/ "/var/www/cgi-bin/"
   RewriteRule  /cgi-bin(/.*)$                /cgi-bin$1        [L,PT]

또 한가지 자동 리다이렉션은..
http://domain.com http://www.domain.com 이 두유형에 대해서만 지원한다.
물론 변경할 수는 있다.

가상도메인내에 파일에서는
환경변수 DOCUMENT_ROOT값이 무의미하다.. (/var/www/html로 고정..)
그래서 VIRTUAL_DOCUMENT_ROOT라는 새로운 환경변수를 사용한다.
만약 DOCUMENT_ROOT를 스크립트중에 사용한다면.
대신 VIRTUAL_DOCUMENT_ROOT를 이용하면된다.

마무리

아래의 내용을 편집하거나 혹은 자세한 설명이 필요하다면.
아래의 URL을 참조하기 바란다.
http://httpd.apache.org/docs/mod/mod_rewrite.html
http://httpd.apache.org/docs/misc/rewriteguide.html

그리고 디버깅이 필요하면 아래의 두줄에 주석을 풀어주면 된다.

#       RewriteLog      "/var/www/vhost/rewrite.log"
#       RewriteLogLevel 9

경고 상당히 많은 로그가 발생하므로 디버깅 목적이 아니면...
반드시 주석처리를 해놓을 것!!

사용중 문제가 발생하거나, 의문이 생기면.. 이글에 리플을 달아주세요. :)
자세한 동작방식에 대해서는 언급하지 않았는데..
기회가 나면, mod_rewrite의 간략한 문법 소개와 함께 올리도록 하겠습니다.

<VirtualHost 192.168.0.1>
        ServerAdmin     foo@bar.com
        ServerName      *
        DocumentRoot    /var/www/html/


        DirectoryIndex  index.php index.html index.htm
        ScriptAlias     /cgi-bin/ "/var/www/cgi-bin/"

        RewriteEngine   On

#		for Debug
#       RewriteLog      "/var/www/vhost/rewrite.log"
#       RewriteLogLevel 9

        RewriteRule     ^/cgi-bin(/.*)$                /cgi-bin$1        [L,PT]

        RewriteRule     ^(.*)           %{HTTP_HOST}$1

        RewriteCond     /var/www/vhost/%{HTTP_HOST}     -d
        RewriteRule     ^(.+)   /var/www/vhost/$1       [s=4,E=VIRTUAL_DOCUMENT_ROOT:/var/www/vhost/%{HTTP_HOST}/]


        RewriteCond     /var/www/vhost/www.%{HTTP_HOST} -d
        RewriteRule     ^(.*)           http://www.$1                           [L,R]

        RewriteCond     %{HTTP_HOST}    !^www\..+$
        RewriteCond     /var/www/vhost/www.$2           -d
        RewriteRule     ^([^.]+.)([^/]+)(.+)$           http://www.$2$3         [L,R]

        RewriteCond     /var/www/vhost/$2               -d
        RewriteRule     ^([^.]+.)([^/]+)(.+)$           http://$2$3             [L,R]


        RewriteRule     ^([^/]+/)(.*)                   %{DOCUMENT_ROOT}$2      [s=1]

        RewriteCond     $1$2            ^.*[^/]$
        RewriteCond     $1$2            -d
        RewriteRule     ^(/var/www/vhost/)(.+[^/])$      http://$2/        [L,R]

        RewriteCond     $1$2            ^.*[^/]$
        RewriteCond     $1$2            -d
        RewriteRule     ^(/var/www/html/)(.+[^/])$       http://%{HTTP_HOST}/$2/        [L,R]

        HostNameLookups off
</VirtualHost>

Forums: 
지리즈의 이미지

mod_rewrite의 개념...

일반 적인 아파치의 기능은
요청된 URL에 적절한 파일을 HTTP에 맞게 전송하는 것이다.

mod_rewrite는 요청된 URL에 대해
관리자가 목적에 맞게 변경하여 요청자에게 응답할 수 있는 기능을 제공한다.

Quote:
예 일반적인 경우
httpd.conf :
DocumentRoot : /some/local/path/

요청 :
http://host/somedir/somefile.html

서버가 응답하는 실제 내용
/some/local/path/somedir/somefile.html

Quote:
예 :Rewrite
httpd.conf :
DocumentRoot : /some/local/path/
RewriteRule ^/somedir/(.*)$ /anotherdir/$1

요청 :
http://host/somedir/somefile.html

서버가 응답하는 실제 내용
/anotherdir/somefile.html

이와 같이 실제 요청자의 웹브라우저에 표시되는 URL을 통해
서버의 예상되는 위치에 존재하는 파일을 읽어 전송하는 것이 아니라,
별도의 위치에서 전송할 수 있도록 해주는 것이다.

이런 기능외에 로드발랜싱이나 프록시와 같은 기능으로 연결하거나,
혹은 다른 URL로 redirect를 시킬 수도 있다.

기본적으로 rewrite엔진에 넘겨지는 것은 경로(path)이다.
경로라 하면... http://host:80/somedir/somefile.html 에서
/somedir/somefile.html 까지를 의미하고, 포트와 호스트네임은 포함되지 않는다.

웹서버는 이 내용을 기준으로 하여 절적한 파일을 읽어 들이게 되는데...
바로 mod_rewrite는 웹서버가 이 경로와 다른 경로를 읽어 들일 수 있도록 하는 기능을 제공하는 것이다.

몇가지 접근하는대 필요한 개념은 아래와 같다.


입력자 : 웹서버
응답대상: 웹서버
입력값 : "(상대) 경로(path)"
출력값 : "(절대)경로 혹은 요청자에게 답변하는 내용."

mod_rewrite라고 했듯이 모듈이기 때문에..
상대자는 오직 웹서버 뿐이다. 즉 입력값을 받는 것도 답변을 하는 것도
웹서버라는 것이다.

그리고... 입력값은 상대 경로이다. (당연하겠지만)즉 서버내 물리적 위치가 아니다.
하지만 응답을 하는 것은 절대경로로 응답해야 한다. 서버가 실제로 읽어 들일
물리적 위치를 지정하는 것이다.

이정도의 주의 사항을 가지고 접근하기 바란다.

There is no spoon. Neo from the Matrix 1999.

지리즈의 이미지

RewriteRule 1

RewriteRule은 입력값을 변경해주는 유일한 키워드이며, mod_rewrite의
핵심이라고 할 수 있다.

#Syntax:
 RewriteRule Pattern Substitution flags

패턴에 따라 넘겨 받은 값을 치환(Substitution)하는 것이다.

패턴과 치환에 관한 방식은 펄의 정규화 표현식과 유사하다.
php의 ereg_replace나 혹은 sed, vi의 치환 명령에 익숙하다면
쉽게 접근할 것이다.
이 것에 대한 자세한 내용은 나중에 다루고..
이번엔 이명령의 중요한 개념에 대해서 설명하고자 한다.

문법에서 보여주는 것대로 한다면,
패턴에 맞게 입력값을 나누고, 거기에 맞게 치환하는 것으로 보인다.
근데 여기에 함정이 있다.

아래의 PHP Code를 보자.

<?php


function RewriteRule($pattern, $Substitution, $flags= 0)
{
	//웹서버에서 넘겨 받아 거나 이전의 RewriteRule의 결과값
	global $URL;

	// 정규화 표현식 실행
	$tmp = ereg_replace($pattern,$Substitution,$URL);
               
	// 결과물이 URL과 일치하면.. 즉 패턴에 일치하지 않고
	//아무런 변화가 없으면 함수를 빠져나간다.
	if($tmp == $URL) return ;

	//정규화표현식의 실행값을 반영한다.
	$URL = $tmp;

	//추가적인 기능이 지정되어 있지 않으면, 함수를 종료한다.
	if($flags== 0) return ;

	//추가적인 기능에 L이 있으면 해당 기능을 수행한다.
	if(ereg("L",$flags){
		something about "L"; 
	}

	//추가적인 기능에 P가 있으면 해당 기능을 수행한다.
	if(ereg("P",$flags){
		something about "P"; 
	}

	.
	.
	.
	.
}


?>

좋은 코드는 아니다.
하지만.. RewriteRule의 동작방식을 이해하는 데는 충분하다고 본다.
RewrieRule은 단순히 치환기능만이 있는 것이 아니라
Condition 즉 특정한 패턴의 검출 여부에 따라
동작을 수행 혹은 수행하지 않는
조건문을 함께 포함하고 있는 구조
다.

이 점을 놓치면, rewrite를 이해하는데 매우 고생스럽다.

RewriteRule /cgi-bin(/.*)$ /cgi-bin$1 [L,PT]

먼저 설명이 안됀 플래그 L,PT가 있다..
PT에 대해서는 나중에 설명을 하고..
L에 대해서만 설명하겠다.
L이란 Last Rule의 약자로... 이 RewriteRule 뒤의 라인을 점부 무시하라는 뜻이다.
위의 내용은
요청된 URL중에 /cgi-bin이란 내용이 포함된 내용을 치환하고,
/cgi-bin$1이란 내용을 중심으로 Rewrite를 종료하라는 뜻이다.
그런데.. 요청된 내용에 /cgi-bin이란 내용이 없으면 어떻게 될까?
정답은 해당 RewriteRule은 무시가 된다.
이렇듯 단순한 치환명령이 아니라, 조건이 포함되어 있는 명령이라는 것을 명심하자.

There is no spoon. Neo from the Matrix 1999.

mudori의 이미지

그래도 버철호스트 올인입니다.

i09000의 이미지

저는 어떤 주소로 접속을 하던지 간에... 같은 페이지로 이동을 하고 싶은데요....

예> 사용자ID.도메인.com이렇게 접속을하면

php등을 이용해서 접속경로에 따라서 처리를 다르게 해줄 생각인데요....

어떻게 해야 할지........

영.... 많이 복잡한데요... 어떻게 해야 하죠??

감사합니다.

지리즈의 이미지

<VirtualHost 192.168.0.1>
ServerAdmin foo@bar.com
ServerName *
DocumentRoot /var/www/html/
</VirtualHost>

간단히 위와 같이 ServerName에 *을 사용하면 됩니다.
혹은
ServerName *.foobar.com
이런 식으로 처리하면 됩니다.

<VirtualHost 192.168.0.1>
ServerName *.bar.com
DocumentRoot /var/www/bar
</VirtualHost>

<VirtualHost 192.168.0.1>
ServerName *.foo.com
DocumentRoot /var/www/foo
</VirtualHost>

i09000 wrote:
저는 어떤 주소로 접속을 하던지 간에... 같은 페이지로 이동을 하고 싶은데요....

예> 사용자ID.도메인.com이렇게 접속을하면

php등을 이용해서 접속경로에 따라서 처리를 다르게 해줄 생각인데요....

어떻게 해야 할지........

영.... 많이 복잡한데요... 어떻게 해야 하죠??

There is no spoon. Neo from the Matrix 1999.

익명 사용자의 이미지

i09000 님처럼 리라이렉트모드까지는 필요없는 상황이었고
지정된 id별 2차도메인으로 모두 같은 DocumentRoot로 보내면 되는 상황이기 때문에 리아이렉트 모드는 필요가 없었고,

ServerName *.a.com

위와같이 설정했을땐 동작되지 않았으며

ServerName a.com
ServerAlias *.a.com

위와같이 alias로 설정하니 정상적으로 되네요...

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.