이전에 한 번 올라왔었던 '야후스타일 URL'에 관련된 내용으로, ReWrite 엔진 대신 ForceType과 PATH_INFO를 이용한 방법입니다. 야후스타일 URL은 흔히 검색엔진 친화적 URL이라고 하는데, 이런 이름이 붙은 이유는 검색 엔진들이 ?가 포함된 URL을 싫어하기(했 기) 때문입니다..
목표는, 이런 복잡한 URL을
http://myhost.com/zboard.php?id=main_story&page=1&sn1=&divpage=1 &sn=off&ss=on&sc=on&select_arrange=headnum&desc=asc&no=3959
이렇게 단순화시키는 것입니다.
http://myhost.com/Board/ZeroReaD3959.html
1. ForceType
ForceType은 서버에 있는 파일들 중 특정한 확장자를 특정 MIME 형식으로 강제하는 아파 치 지시자입니다. 예를 들어 확장자가 html이나 htm인 HTML 파일은 기본적으로 text/html 으로 브라우저에 전달되나, ForceType을 이용하면 그 외의 형식으로 전달되게 할 수 있습니 다.
야후 스타일 URL을 위해 ForceType을 쓰는 이유는, 위의 예의 경우 Board가 zboard.php를 대신하게 만들어야 하기 때문입니다. 즉 php 코드가 들어 있는 Board라는 파일이 php 스크립트로써 실행되게 만들어야 하는 것입니다. 이를 위한 ForceType 지시자의 형태는 다 음과 같습니다.
<Files Board> ForceType application/x-httpd-php </Files>
Board라는 파일에 대한 요청을 받았을 때, MIME 형식을 application/x-httpd-php로 해서 처 리하라는 뜻입니다. 이러한 구문은 아파치 서버 자체의 설정(httpd.conf)의 <Directory> 등에 넣어도 되지만, 웹 호스팅 등 서버 설정을 바꿀 수 없는 경우 그리고 설정 변경의 용이성을 생 각한다면 Board가 있는 디렉토리의 .htaccess 에 넣는 것이 더 나은 방법일 것입니다.
2. ForceType 테스트
우선 빈 텍스트 문서를 열고, 위에 나온 <Files Board>.. </Files> 부분을 그대로 입력한 후 .htaccess라는 이름으로 웹 서버의 임의의 디렉토리에 저장합니다. .htaccess가 이미 존재 한다면 추가해 주면 되구요. (여기서는 웹 사이트의 루트 디렉토리를 기준으로 하겠습니다. 그리고 웹 사이트는 http://localhost/라고 가정하겠습니다)
그런 다음 , 아래를 그 디렉토리에 Board라는 이름으로 저장합니다. 확장자 .php를 붙이면 안 됩니다.
<? echo "소스 전체가 보인다면 실패, 이 문장만 보인다면 성공"; ?>
이제 브라우저로 http://localhost/Board 를 열었을 때, 제대로 되지 않았다면 소스 전체가 보이거나 아니면 다운로드 창이 뜰 것입니다. 그렇지 않고 따옴표 안의 문장만 보인다면 성공 입니다.
실패의 원인은 대부분 해당 디렉토리에 대해 서버 설정 오버라이드가 허용되지 않기 때문입 니다. 웹 호스팅이라면 관리자에게 문의를 해야 하구요. 서버 설정을 직접 고칠 수 있다면, httpd.conf 등에서 해당 디렉토리에 대한 <Directory> 항목 중 AllowOverride를 All로 해주면 됩니다. 예를 들면 다음과 같습니다(루트 디렉토리의 경우)
<Directory /> Options Indexes FollowSymLinks AllowOverride All Order allow,deny Allow from all </Directory>
실패의 경우 아마 AllowOverride가 None일 것입니다. 그것을 All로 바꿔주면 ForceType을 비롯한 다른 설정들의 변경이 가능합니다.
3. PATH_INFO
$PATH_INFO는 PHP가 설정해 주는 전역 변수로, URL 중 스크립트 이름 다음부터 물음표 전 까지의 모든 것들을 담고 있습니다.
Board 파일을 다음과 같이 수정해 봅시다.
<html> <body> <pre> <?
echo '$SCRIPT_NAME : ' . $SCRIPT_NAME . "\n"; echo '$PATH_INFO : '. $PATH_INFO . "\n";
?> </pre>
</body> </html>
이제 브라우저로 http://localhost/Board 를 열면
$SCRIPT_NAME : /Board $PATH_INFO :
이제 진짜 테스트로, 원래의 목표였던 http://localhost/Board/ZeroReaD3959.html 를
$SCRIPT_NAME : /Board $PATH_INFO : /ZeroReaD3959.html
중요한 것은, 웹 서버는 ForceType에 의해 Board를 실행할 뿐이며, ZeroReadD3959.html를 파일 이름으로 보는 것이 아니라 Board에 주어지는 정보로만 인식한다는 점입니다. 이것이 ForceType과 PATH_INFO를 결합해서 사용할 때의 핵심입니다. 이것만 이해한다면 나머지 는 상상력을 발휘해서 얼마든지 활용할 수 있을 것입니다.
아파치 버전이나 플랫폼에 따라서는 PATH_INFO를 지원하지 않을 수도 있는데(옛날 이야기 인가요^^), 그럴 때에는 $REQUEST_URI로 대신할 수 있습니다. 단 $REQUEST_URI에는 스 크립트 이름과 ? 이후의 URL 인자들까지 모두 포함되므로... 정보를 걸러내는 과정이 아주 조 금 복잡해 질 수 있습니다. Board에 echo '$REQUEST_URI : ' . $REQUEST_URI . "\n"; 을 추가하고, http://localhost/Board/ZeroReaD3959.html?hello=world 등 복잡한 URL을 시험 해 보세요.
3. PATH_INFO로부터 정보 추출
이 부분은 뭐 정규 표현식으로 끝낼 수 있습니다. 이 예에서, /ZeroReaD3959.html에서 필요 한 정보는 3959 뿐입니다. 이것을 뽑아내는 정규표현식은 ZeroReaD([0-9]+) 가 되겠죠...
테스트를 위해 Board에 다음을 추가...
preg_match("/ZeroReaD([0-9]+)/", $PATH_INFO, $match);
echo "글 번호 : $match[1] \n";
이제 http://localhost/Board/ZeroReaD3959.html를 열면, 결과는:
$SCRIPT_NAME : /Board $PATH_INFO : /ZeroReaD3959.html 글 번호 : 3959
4. 실제 스크립트 호출
이 부분부터는 사실 제가 제로보드를 써 보지 않아서 테스트할 수는 없었습니다. 다만 PHP와 HTTP의 작동 방식을 생각한다면 그리 어렵지 않게 해결할 수 있을 것입니다.
한 가지 방법은, 글 번호로 실제 URL을 만들고, (이런 식으로..)
$url = "http://localhost/zboard.php?id=main_story&page=1&sn1=&divpage=1 &sn=off&ss=on&sc=on&select_arrange=headnum&desc=asc&no={$match[1]}";
그런다음 redirect 헤더를 이용해서 실제 zboard.php를 호출하는 것입니다. 단점은 서버-브 라우저 간의 전송이 두 번 일어난다는 것. 장점은 아래에서 이야기하겠지만 상대 경로의 문제 가 없다는 것...
또 다른 방법은 zboard.php에 전달될 GET 인자들을 직접 설정한 후 Board에서 zboard.php 를 include 하는 것입니다.... 예를 들면
$HTTP_GET_VARS['id'] = 'main_story';
...
$HTTP_GET_VARS['no'] = $match[1];
include "..경로../zboard.php";
이런 식으로요... 가능할 것이라고 생각합니다. (또는 zboard.php 자체를 Board로 바꾸고 제 일 윗부분에 정규 표현식 처리를 집어 넣어도 될 것입니다...)
5. 주의할 점 및 확장
http://localhost/Board/ZeroReaD3959.html 라는 URL을 보시면 Board가 마치 디렉토리 이 름처럼 되어 있습니다. 서버쪽에서는 ForceType을 이용하니 문제가 없는데 브라우저는 Board를 디렉토리로 인식하므로 <a> 등에서 상대 경로를 사용할 때 문제가 생길 수 있습니 다... 이를 해결하기 위해서는 생성되는 html 안에서 항상 절대 경로를 사용하거나, 아니면 <base>를 사용해서 기준 경로를 지정해 줘야 합니다.
한 가지 확장으로, 이 예에서는 글 번호만 취급했는데, http://localshot/Board/main_story/style_simple/3959.html 처럼 Board 밑에 글 번호 이외 의 여러가지 정보를 넣게 할 수도 있을 것입니다. 이 경우 PHP 함수 split()을 이용해서 $PATH_INFO에 담긴 문자열을 '/'의 기준으로 나누면 각 정보를 쉽게 뽑아낼 수 있을 것입니 다.
6. 결론
이상의 방법은 ReWrite 엔진을 사용하는 것보다는 느리겠지만 구현하기가 간단하며 유연성 도 뛰어난 방법이라고 생각합니다. 개인적으로 저는 이 방법을 http://www.gpgstudy.com/gpgiki/ (여기서 gpgiki가 바로 ForceType을 이용한 스크립트 입니다)에서 유용하게 쓰고 있습니다.
그리고, 3번까지는 제가 실제로 시험해 본 것이지만, 마지막에서 이야기한 제로보드 또는 기 타 게시판 시스템과의 통합을 실제로 구현해 보지 못했다는 점이 아쉬운데요. 아마 세부적인 부분에서 몇 가지 |