[PHP] 분산 설정 파일(.htaccess) 사용법


Study/PHP  2019. 9. 24. 00:05

안녕하세요. 명월입니다.


이 글은 PHP에서 분산 설정 파일(.htaccess)에 대한 글입니다.


이전까지 php를 작성하면 index.php나 접속 페이지.php로 접속했습니다. 사실 이 상태로 웹 서비스해도 문제가 되지는 않는데 특정 클래스 파일만 있는 파일이라면 빈 페이지만 보이게 되고 웹 서비스의 디렉토리가 노출이 되기 때문에 보안상 좋은 설정 방법은 아닙니다.

그렇다면 *.php의 의 설정이 아닌 C#의 MVC처럼 디렉토리만으로 php를 접속할 수 있게 하는 설정 파일이 있는데 그것이 분산 설정 파일(.htaccess)입니다.


링크 - https://httpd.apache.org/docs/2.2/ko/howto/htaccess.html


먼저 분산 설정 파일을 사용하기 위해서 .htaccess의 구조에 대해서 알아보겠습니다.

위 파일은 파일명이 없이 확장자만 .htaccess로 생성된 파일이기 때문에 eclipse에는 보이지가 않습니다.

Options -MultiViews
RewriteEngine On
Options -Indexes
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-l
RewriteCond %{REQUEST_URI} !(.js$)
RewriteCond %{REQUEST_URI} !(.css$)
RewriteCond %{REQUEST_URI} !(.ico$)
RewriteRule ^(.*)$ Index.php?htaccess=$1 [QSA,L]


Options -MultiViews

이 구문은 request 요청으로 오는 설정과 관계가 있는데 만약 localhost로 요청이 오면 처음에는 index.php를 찾지만, 없으면 index.html를 찾는 형태입니다.

즉 Options +MultiViews라고 하면 자동으로 찾는 설정이 되지만 Options -MultiViews로 하면 자동으로 찾지 않습니다.


RewriteBase /

RewriteBase의 경우는 서버의 root폴더를 어디에 두는 것인지 설정하는 파일입니다. 즉, localhost가 오면 어떤 폴더부터 시작하는지 알려주는 것입니다.


RewriteEngine On

RewriteEngine On의 경우는 url를 재구성하는 방식으로 예전에는 localhost/index.php?data=test라는 형식을 localhost/index/test라는 식으로 디렉토리 구조처럼 변환시켜 주는 구문입니다.

즉, 이전에 직접 페이지를 탐색하는 거이 아니라 url를 하나의 데이터로 받아드리는 구문입니다.


Options -Indexes

Options -Indexes는 파일의 디렉토리를 활성할 여부를 결정하는 구문입니다.

즉, 위 구문이 없거나 Options +Indexes로 되어 있으면 해당 디렉토리에 index.php의 파일이 없을 경우 디렉토리가 다 보여줍니다.

제가 image 폴더에 no_photo.png 파일 넣어 놓고 브라우져에서 localhost/image라고 치면 아래와 처럼 나오는 결과가 나옵니다.


RewriteCond

RewriteCond는 하단의 RewriteRule의 URL재설정으로 가기 위한 필터의 역할입니다.

즉, .htaccess파일에서 위에서 아래로 처리가 이루어 지는데 RewriteCond의 구문이 True의 결과가 나와야 RewriteRule가 적용이 되고 False가 나오면 재설정이 필요없이 url 그대로 파일을 읽는 것입니다.


만약에 모든 URL은 RewriteRule에 의해 재설정이 되지만 phpinfo.php라는 파일만은 RewriteRule를 재설정을 하지 않고 그대로 localhost/phpinfo.php라고 보여주고 싶으면 아래와 같이 설정하면됩니다.

Options -MultiViews
RewriteEngine On
Options -Indexes
# url에서 정규식이 일치(phpinfo.php로 끝나는 경우)하면 부정(!)마크로 False가 된다.
RewriteCond %{REQUEST_URI} !(phpinfo.php$)
RewriteRule ^(.*)$ index.php?htaccess=$1 [QSA,L]

RewriteCond의 파라미터은 서버 변수, 정규식으로 이루어 집니다.

사용가능한 서버 변수는 아래의 apache 메뉴얼을 보면 꽤 많이 있습니다.

참조 - http://httpd.apache.org/docs/current/mod/mod_rewrite.html#RewriteCond

그러나 저도 그 변수들을 다 사용해 본적은 없고 보통 REQUEST_FILENAME과 REQUEST_URI이 전부입니다.


REQUEST_URI의 경우는 요청 된 URI의 경로 구성 요소 (예 : "/index.html")인테 GET방식의 Query string은 제외됩니다.

즉, localhsot/test.php?data=123으로 요청이 오면 /test.php의 값이 표시가 됩니다.


REQUEST_FILENAME의 경우는 요청과 일치하는 파일 또는 스크립트의 전체 로컬 파일 시스템 경로입니다.

REQUEST_FILENAME의 경우는 검사 식은 정규식이 아닌 -d, -f, -l로 나타내는데 -d는 디렉토리, -f는 파일을 뜻합니다.

위 예제에서 REQUEST_URI를 통해 phpinfo.php를 걸러 내었지만 RewriteCond %{REQUEST_FILENAME} !-f이라고 옵션을 추가하면 phpinfo.php파일이 존재할 경우 false가 되는 것입니다.

이 경우는 phpinfo.php파일 뿐아니라 다른 .php파일이 존재하게 되면 RewriteRule를 따르지 않게 되므로 실제 이렇게 작성하면 안되겠네요.

RewriteRule ^(.*)$ Index.php?htaccess=$1 [QSA,L]

지금까지의 구문은 이 RewriteRule를 위한 구문입니다.

예를 들면 localhost/test?data=123라는 요청이 오면 localhost/Index.php?htaccress=test&data=123으로 처리됩니다.

즉, url이 어떤 요청이 오든간에 Index.php를 요청하도록 룰을 변경하는 것입니다.


뒤의 QSA는 파라미터는 파라미터 그대로 변경하는 것으로 ?data=123를 htaccress=test&data=123이런 식으로 변경하는 것입니다.


다시 소스로 돌아와서 실제 서버에 적용하겠습니다. 먼저 .htaccess를 적용하기 위해서는 apache 설정을 조금 수정해야 합니다.

LoadModule rewrite_module modules/mod_rewrite.so의 주석(#)을 해제합니다.

AllowOverride부분을 None에서 All로 수정합니다.

먼저 root 폴더의 .htaccess의 파일을 아래와 같이 작성했습니다.

Options -MultiViews
RewriteEngine On
Options -Indexes
RewriteCond %{REQUEST_URI} !(.js$)
RewriteCond %{REQUEST_URI} !(.css$)
RewriteCond %{REQUEST_URI} !(.ico$)
RewriteRule ^(.*)$ index.php?htaccess=$1 [QSA,L]

그리고 image 폴더의 .htaccess파일을 아래와 같이 작성했습니다.

Options -MultiViews
Options -Indexes
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f

.htaccess파일은 폴더별로 설정이 가능한데 root에 .htaccess파일이 있어도 위처럼 image폴더에 .htaccess를 넣게 되면 localhost/image/...에서는 분산설정이 새로 적용됩니다.

즉, 자바스크립트(js)나 스타일 시트(css), 이미지등은 디렉토리를 생성해서 .htaccess를 따로 만들어서 설정해야 html안에서 설정되는 link를 문제없이 사용할 수 있습니다.

그리고 Index.php도 수정합니다.

<?php
?>
<!DOCTYPE html>
<html>
<head>
<title>title</title>
</head>
<body>
  parameter = <?=$_GET["htaccess"]?>
  <img src="/image/no_photo.png">
</body>
</html>

이제 아파치를 기동하고 브라우저에서 확인합니다.

위 예제를 보면 제가 localhost/helloworld라고 쳤습니다. 그랬더니 내부적으로는 GET형식의 Index.php?htaccess=helloworld라고 호출이 되는 것입니다.

그리고 img의 /image/no_photo.png 경우는 제가 RewriteRule로 적용이 되서 Index.php?htaccess=image로 호출하고 싶지 않았기 때문에 image폴더 안에 .htaccess를 새로 적용한 것입니다.


여기까지 작성이 되었으면 php의 웹 프로그래밍도 /*.php의 형식이 아닌 /~의 형태로 작성이 가능하게 바꾸었습니다.

제가 localhost/data.php로 접속을 하니 data.php가 parameter 형식으로 데이터를 받아오는 걸 볼 수 있네요.


이제 PHP도 MVC를 위한 초기 설정이 완료된 것입니다.


참조 - https://httpd.apache.org/docs/2.2/ko/howto/htaccess.html

참조 - http://webskills.kr/archives/473

참조 - https://stackoverflow.com/questions/15850845/


여기까지 PHP에서 분산 설정 파일(.htaccess)에 관한 설명이었습니다.


궁금한 점이나 잘못된 점이 있으면 댓글 부탁드립니다.