[DevOps] Apache rewrite rule 정리

[DevOps] Apache rewrite rule 정리

안녕하세요 정리하는 개발자 워니즈입니다. 이번시간에는 아파치 config 중에 rewrite 룰에 대해서 정리를 해보려고 합니다. 필자가 속한 프로젝트에서는 Apache를 웹서버로 사용하고 있습니다. 그러다보니, apache에 들어가있는 configuration에 대해서 알아야 되는데요. 그중에서도 rewrite rule이 있습니다.

Apache의 rewrite Module은 아파치 모듈주의 한종류로 서버 Request를 정해진 Rule에 의해서 다른 URL or File로 보내는 모듈입니다.

rewrite_1

1. Rewrite 모듈 지시자

  • RewriteEngine

Rewriting 엔진을 사용할지 여부를 설정합니다. 기본설정은 Off로 되어 있으며 RewriteEngine On으로 설정하면 Rewriting 엔진이 활성화 됩니다.

  • RewirteLog File-Path

RewriteLog 지시자는 Rewrite 엔진의 로그를 그록할 파일을 지정합니다.
RewriteLog 파일을 항상 남기기 보다 잘못된 Rewrite 규칙들을 디버킹할 때 사용하기를 권장합니다. 아파치와 마찬가지로 RewriteLog 파일도 방문자 수가 많은 사이트에서는 많은 로그파일이 쌓이기 때문에 해당 파티션의 여유공간이 많이 없는 시스템에서는 장래를 유발 할수도 있으므로 로그를 잘 관리 해야 합니다.

  • RewriteLogLevel Level

RewriteLogLevel 지시자는 RewriteLog 지시자로 설정한 로그파일에 기록할 로그들에 대해 얼마나 자세한 내용을 로그로 남길것인가에 대해 설정하는 지시자입니다.
기록할 로그 Level 은 0 ~ 9까지 사용할 수 있으며 0은 로그를 기록하지 않겠다는 의미입니다.

2. Rewrite Flag

RewriteRule 문법중 마지막에 패턴이 일치할 경우 어떤 동작을 취할지 지정하는 부분이며, 이를 플래그라고도 합니다. 지정할 수 있는 플래그중 자주 사용되는 것들은 다음과 같은 항목이 있습니다. 플래그는 전체 단어를 써도 되지만 축약어로 써도 됩니다.

필자의 프로젝트에 적용된 것을 위주로 정리를 해보겠습니다.

  • Last : L

Last 플래그는 더이상 mod_rewrite 룰 처리를 하지 않겠다는 의미이다. 프로그래밍 언어에서 break 와 비슷한 용도로 사용되며 여러 개의 RewriteRule 룰을 연결해서 사용하는 경우 더 이상의 처리를 하지 않아도 될 때 유용하게 사용할 수 있다.

  • Nocase : NC

Nocase 는 패턴 매칭할 경우 대소문자 구분을 하지 않겠다는 의미이다.

  • Noescape: NE

    기본적으로 & 및 ?와 같은 특수 문자는 16진수 등가로 변환된다. [NE] 플래그를 사용하면 그런 일이 발생하지 않는다.

RewriteRule “^/anchor/(.+)” “/bigpage.html#$1” [NE,R]
위의 예는 /anchor/xyz를 /bigpage로 리디렉션한다.html#xyz. [NE]를 생략하면 #가 16진수 등가 %23로 변환되어 404 Not Found 오류 상태가 된다.

  • Redirect:R

리다이렉트 플래그는 규칙에 일치할 경우 HTTP 302 Redirect 응답을 클라이언트에게 전송한다. 만약 HTTP 301 Moved Permanently 응답을 전송해야 한다면 R=301 로 적어주면 된다.

  • Passthru:PT

RewriteRule 의 target_url 이 http 나 https 로 시작하지 않으면 mod_rewrite 는 target_url 을 로컬 파일의 경로로 인식한다. / 로 시작할 경우 절대 경로로 / 가 아닐 경우 상대 경로로 처리하게 된다. 파일 경로로 처리할 경우 스크립트 파일의 경우 파일의 내용이 그대로 노출될 우려가 있다.

  • qsappend: QSA

mod_rewrite 는 기본적으로 클라이언트가 GET 으로 전송한 변수를 무시한다. 이 변수 값은 QUERY_STRING 이라는 변수명에 저장된다. QSA(Query String Append) 플래그를 사용하면 QUERY_STRING 을 무시하지 않고 유지시키므로 URL 전환시에도 문제가 없다.

3. RewriteCond

앞에서 RewriteRule 에 대한 설명을 보고 만약 조건문이 필요할 경우는 어떻게 해야 할지 의문이 생긴 독자들도 있을 것이다. RewriteCond 는 그런 독자들의 의문을 해소해 줄 지시자이다. 여러 가지 상황별로 조건을 확인하고 그 조건이 맞을 경우 처리를 하게 할 수 있다. RewriteCond는 다음과 같은 문법을 갖는다.

RewriteCond TestString Pattern [Flags]

TestString 에는 다음과 같은 값등을 사용할 수 있다.

  • 직전 RewriteRule 에서 일치한 캡처값 – RewriteCond 앞에 RewriteRule 을 사용했고 정규 표현식에서 그룹으로 지정된 값이 있을 경우 TestString 에 사용할 수 있다. 사용할 경우 $N (N 은 0 에서 9사이 값) 형식으로 사용한다.
  • 직전 RewriteCond 에서 일치한 캡처값 – RewriteCond 앞에 RewriteCond를 사용했고 정규 표현식에서 그룹으로 지정된 값이 일치했을 경우 %N(N 은 0 에서 9) 형식으로 사용할 수 있다.

  • 서버 변수 – 웹서버가 갖고 있는 변수값을 사용할 수 있다. 서버의 변수를 사용할 경우 %{변수명} 형식으로 사용한다. 제일 많이 사용하는 변수들은 %{HTTP_HOST}, %{QUERY_STRING} 등이다.

변수명 설명
HTTP 요청 변수
HTTP_HOST URL 에서 호스트 이름 부분이며 클라이언트가 보낸 HTTP 헤더중 Host: 헤더에 있는 값이 된다. 가상 호스트 기반 rewrite 규칙을 설정할 경우에 많이 사용된다.
HTTP_REFERER 사용자가 현재 요청시 어떤 링크를 통해 들어왔는지 알수 있는 변수이다.
REQUEST_METHOD HTTP 요청 메소드로 보통 GET 또는 POST 가 된다.
QUERY_STRING GET 방식으로 URL 을 호출했을 때 넘긴 파라미터가 설정된다. 예로 “http://www.example.com/article/view.jsp?one=two&three=four” 로 호출했을 경우, QUERY_STRING 은 “one=two&three=four” 가 된다.
REQUEST_URI 클라이언트가 요청한 리소스로 보통 URL 에서 호스트 이름과 파라미터를 제외한 부분이 된다. 위 QUERY_STRING 예제에서 REQUEST_URI는 “article/view.jsp” 가 된다.
클라이언트 변수
HTTP_USER_AGENT 사용자 브라우저 정보가 설정
HTTP_ACCEPT 브라우저가 처리할 수 있는 컨텐츠의 목록
REMOTE_ADDR 요청 클라이언트가 사용하는 IP
REMOTE_USER 로그인이 필요한 리소스에 접근할 경우 사용자명
서버 내부 변수
DOCUMENT_ROOT 현재 가상 호스트에 설정한 DocumentRoot 의 경로를 얻을 수 있다.
REQUEST_FILENAME 클라이언트가 요청한 파일이나 스크립트가 현재 서버에 위치하는 절대 경로를 의미한다. 현재 가상호스트의 DocumentRoot 가 “/var/www/vhost1” 이고 클라이언트가 /book.php 를 요청했을 경우 REQUEST_FILENAME 은 /var/www/vhost1/book.php 가 된다.
SERVER_NAME The canonical name of the current virtual host.
SERVER_ADDR The IP address of the current virtual host.
SERVER_PORT The port number from which the current request is being served.
HTTPS SSL 이나 TLS 를 사용할 경우 on 으로 설정되고 HTTP 일 경우 off 이다.

Pattern 에는 정규식으로 일치시킬 문자열의 패턴을 기술하면 된다.

마지막 플래그는 다음과 같은 값을 사용할 수 있다.

  • NoCase:NC – RewriteRule 과 마찬가지로 대소 문자를 구분하지 않을 경우 사용한다.
  • ORNext:OR – OR 플래그는 여러 개의 RewriteCond 를 사용할 경우 논리적인 OR 조건이 필요할 때 사용할 수 있다.(여러 개의 RewriteCond 가 있을 때 기본적으로 AND 로 처리한다.)

4. 실제 사용 사례

필자의 프로젝트에서 사용하는 RewriteRule에 대해서 정리를 해보도록 하겠습니다.

    # 1단계 URL 을 그냥 통과 시킬 리스트 적용
    RewriteCond %{REQUEST_URI} ^/etc/designs(.*) [NC,OR]
    RewriteCond %{REQUEST_URI} ^/etc.clientlibs(.*) [NC,OR]
    RewriteCond %{REQUEST_URI} ^/apps/samsung/login(.*) [NC,OR]
    RewriteCond %{REQUEST_URI} ^/bin(.*) [NC,OR]
    RewriteCond %{REQUEST_URI} ^/aemapi(.*) [NC,OR]
    RewriteCond %{REQUEST_URI} ^/sysapi(.*) [NC,OR]
    RewriteCond %{REQUEST_URI} ^/libs/granite/csrf/token [NC,OR]
    RewriteCond %{REQUEST_URI} ^/samsung(.*) [NC,OR]
    RewriteCond %{REQUEST_URI} ^/content/dam(.*) [NC]
    RewriteRule ^(.*)$ $1 [PT]

위의 예제는 재작성 조건에 대해서 여러개를 연결 시켜 놓은 것입니다. 개발코드로 치면 조건문에서 or조건으로 여러개의 체크 조건을 갖고 있습니다.

  1. 대소문자를 가리지 않는다. [NC]
  2. 조건체크를 or조건으로 한다. [OR]
  3. 최종 나온 path에 대해서 그대로 통과 시킨다. [PT]
# 2단계 /content/samsung 이 붙어 있을 경우 제거
RewriteCond %{REQUEST_URI} ^/content/samsung/(.*)$ [NC]
RewriteRule ^/content/samsung/(.*)$ /$1 [R=302,NE,QSA,L]

위의 조건은 url 요청이 특정 문자열(/content/samsung)을 붙이고 들어올때, 그부분을 제거하는 내용입니다.

  1. /content/samsung을 떼어주되, 특수문자를 그대로 둡니다.[NE]
  2. query string에 대해서 그대로 append 해줍니다.[QSA]
  3. 302 redirectino 처리를 하고 break를 수행합니다.[R=302, L]
# 3단계 /가 없거나 확장자가 없을때 / 붙여줌
RewriteCond %{REQUEST_URI} !.*\..*$
RewriteCond %{REQUEST_URI} !.*/$
RewriteRule ^(.*)$ $1/ [R=302,NE,QSA]

# handle requests to pages ending with .html
# 4단계 .html 로 끝날경우 / 를 붙여줌
RewriteCond %{REQUEST_URI} .*.html$
RewriteRule ^(.*).html$ $1/ [R=302,NE,QSA]

3단계와 4단계는 유사합니다. 모든 request에 대해서 끝에 슬래시를 추가해주는 내용입니다.

  1. 확장자가 없거나 (!...$), 슬래시가 없거나 (!.*/$)의 조건을 찾음.
  2. .html로 끝나는 경우(.*.html$)
  3. 특수문자 처리, query string append, Redirection 처리[R=302,NE,QSA]
# 5단계 앞의 작업이 끝났을경우 인터널로 호출할때 /content/samsung 을 붙여줌  
# 앞에서 빼고 뒤에서 붙이는 이유는 사전 URL 작업을 진행하고 내부로 호출하기 위해서임
RewriteCond %{REQUEST_URI} ^/(.*)$ [NC]
RewriteRule ^/(.*)$ /content/samsung/$1 [NE,QSA]

# 6단계 내부적으로 호출할때 html 을 붙여줌
RewriteCond %{REQUEST_URI} .*/$
RewriteCond %{REQUEST_URI} !^/$
RewriteRule ^(.*)/$ $1.html [PT,NE,L,QSA]

5단계와 6단계를 거치면서 내부의 internal server(was)로 페이지를 요청하기 위해서 다시 /content/samsung과 확장자(.html)을 붙여줍니다.

5. apache debug 방법

아파치 rewriterule을 셋팅하면서 항상 어려웠던 부분이 rewrite rule에 대한 디버깅이였습니다. 서칭을 좀 하다보니, online으로 rewrite rule을 테스팅 해볼 수 있는 사이트가 있었습니다.

online rewrite test tool

아래에 rewrite rule에 대해서 읿력을 하고, 위에 request 되는 url에 대해서 입력을 하면, 아래에 debugging된 내용이 노출이 됩니다. 이것을 통해서 개략적인 rewrite rule에 대해서 확인을 해 볼 수 있습니다.

6. 마치며…

이번시간에는 apache rewrite rule에 대해서 정리를 해 보았습니다. apache의 지극히 일부의 모듈에 대해서 정리를 한것이고, 지난 포스팅과 더불어 nginx, apache의 설정들에 대한 정리는 지속적으로 해볼 예정입니다.

nginx-aapche-was로 이어지는 트래픽 흐름의 중간에 어디 부분에서 오류를 일으키고, 어떤 부분을 고쳐야 되는지 확인하기 위해서 각각의 미들웨어 + 어플리케이션 로그를 확인할줄도 알아야된다는 것을 느꼇습니다.

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다