[질문] 검색엔진 친화적 URL을 그누보드에 적용하기 > 그누3질답

그누3질답

[질문] 검색엔진 친화적 URL을 그누보드에 적용하기 정보

그누보드 [질문] 검색엔진 친화적 URL을 그누보드에 적용하기

본문

안녕하세요.
밑에서도 약간(?)은 논란이 되었던 검색엔지 친화적 URL에 대해서, 갑자기 엄청난 궁금증이 유발되어 잠이 안오더군요.(-.-)
그리하여, phpschool를 뒤적거린결과, "류광"이란 분께서 올리신 글을 발견하여,
그누보드에 적용시켜 볼려고, 며칠 밤낮을 끙끙거렸는데, 도저히 모르겠더군요.
3번까지는 됐는데, 4번은 뭔말인지 도저히 모르겠습니다.(ㅜ.ㅜ)
많은 고수님들께서 보시고, 그누보드에 어떻게 적용시키면 되는지, 어떤 파일을 건드려야 되는지,
예제로 풀어서 설명좀 해주세요.
며칠밤을 샜더니 정신이 하나도 없네요.ㅡㅡ;;
그럼 부탁드립니다.

========================================================================================

**삼형제라는 분이 부탁을 하셔서 허접한 내용이나마 글을 씁니다..

이전에 한 번 올라왔었던 '야후스타일 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번까지는 제가 실제로 시험해 본 것이지만, 마지막에서 이야기한 제로보드 또는 기
타 게시판 시스템과의 통합을 실제로 구현해 보지 못했다는 점이 아쉬운데요. 아마 세부적인
부분에서 몇 가지 문제점들이 있을 지도 모르겠습니다. 다른 분들의 성공담을 듣고 싶습니다.

댓글 전체

전체 9,564
그누3질답 내용 검색

회원로그인

(주)에스아이알소프트 / 대표:홍석명 / (06211) 서울특별시 강남구 역삼동 707-34 한신인터밸리24 서관 1402호 / E-Mail: admin@sir.kr
사업자등록번호: 217-81-36347 / 통신판매업신고번호:2014-서울강남-02098호 / 개인정보보호책임자:김민섭(minsup@sir.kr)
© SIRSOFT