Java&Web

[Apache] Apache의 Rewrite 모듈 (mod_rewrite)

프로그래민 2021. 8. 20. 18:24
반응형

한 서비스의 새로운 버전 개발을 담당한 경험이 있다. 버전이 바뀌면서 서버도 새로 바뀌고, API도 개선이 되었고, 그에 따라 요청 파라미터도 변경이 생기게 되었다. 신서버의 작업이 완료된 후, 다른 기존 서비스들과의 연동작업을 진행하게 되었는데, 이때 일부 서비스와 연동 중 신서버로 구서버의 요청 파라미터를 가진 요청들이 발생하였다. 따라서 신서버의 웹서버에서 파라미터의 값을 이용하여 각 파라미터에 알맞은 서버로의 Rewrite Rule 적용이 필요하였다. Apache 환경에서 Rewrite Rule에 대해 알아보고 실습을 진행해보았다.

 

mod_rewrite란

mod_rewrite는 조건 및 규칙을 기반으로 URL을 전환 및 재작성할 수 있도록 도와주는 Apache 확장 모듈이다.

mod_rewrite는 조건 및 규칙을 기반으로 URL을 전환 및 재작성할 수 있도록 도와주는 Apache 확장 모듈이다. mod_rewrite는 다양한 상황에서 활용이 가능한데 대표적으로 쿼리 스트링을 PathVariable로 재작성하거나, 기존 URL에서 새로운 URL로의 이동을 하거나, HTTP를 HTTPS로의 전환하는 등의 작업에 활용이 가능하다. 다만, mod_rewrite는 Apache의 기본 지시자인 Alias, AliasMatch, Redirect, RedirectMatch, Location, LocationMatch들과 기능이 중복되기 부분이 있기 때문에 사용전 확인하는 과정이 필요하다.

mod_rewrite의 지시자로써는 대표적으로 다음과 같은 것들이있다.

  • RewriteEngine On|Off : mod_rewrite의 사용여부를 On, Off 옵션을 통해 지정하는 지사자이다.
예시) RewriteEngine On
  • LogLevel alert rewrite:trace1~8 : mod_rewrite 전용로그 지시자인 RewriteLog, RewirteLogLevel이 있지만 현재는 Apache 로그로 통합되어 LogLevel 지사자를 사용한다. trace의 레벨을 1~8까지 옵션으로 줄 수 있는데 숫자가 클수록 자세한 로그 내용이 기록이 되고, trace3 이상은 성능상 디버깅시에만 사용할 것이 권고된다.
예시) LogLevel alert rewrite:trace3
  • RewriteBase URL-path : rewrite를 위한 기본 URL을 설정하는 지시자이다.
예시) RewriteBase "/"
  • RewriteCond TestString CondPattern [flags] : RewriteRule 지시자 앞에 사용되는 rewrite의 조건을 명시해주는 지시자다. TestString이 CondPattern에 해당하는지 확인하고, flags를 옵션으로 줄 수 있는 지시자이다.
    • TestString : TestString의 위치에는 직전 RewrtieRule 지시자에서 일치한 값, 직전 RewriteCond에서 일치한 값, 그리고 서버변수등을 사용할 수 있다. 보통 서버변수를 많이 사용하고 아래와 같은 것이 있다. 자세한 것은 링크에서 확인할 수 있다.
      서서변수
    • CondPattern : TestString을 검증할 정규표현식을 사용한다.
    • flags : flags로는 NC(NoCase로써 대소 문자를 구분하지 않을 때 사용), OR(RewriteCond들 간의 논리적인 or 조건이 필요할 때 사용, 기본적으로 RewriteCond가 여러개 있을시 and 처리), NV(NoVary로써 조건에서 HTTP 헤더가 사용되는 경우, Vary 헤더에 응답이 추가되는것을 방지할 때 사용)등을 사용한다.
예시) RewriteCond "%{HTTP_USER_AGENT}" "(iPhone|Blackberry|Android)"
        RewriteCond "%{REMOTE_HOST}" "^host1" [OR]
        RewriteCond "%{REMOTE_HOST}" "^host2"
  • RewriteRule Pattern Substitution [flags] : rewrite 규칙에 따른 동작을 지정하는 mod_rewrite의 핵심 지시자이다. 선행하는 RewriteCond가 존재하다면 조건을 판별한다음 RewriteRule에서 동작한다. Pattern에 일치시킬 패턴을 정하고, Substitution에 대체할 문자 그리고 flags를 동작의 옵션으로 지정할 수 있는 지시자이다.
    • Pattern : 정규표현식을 사용하여 Input URL에서 치환할 패턴을 지정한다.
    • Substitution : Pattern을 치환할 할 대체 문자을 지정한다.
    • flags : 어떤 동작을 취할지 지정하는 부분으로써 대표적으로 Redirect의 HTTP 코드를 넘겨주는 R, RewriteRule의 끝을 나타내어주는 L등을 자주사용한다. 추가적으로 아래와 같은 flag들이 있고, 자세한 것은 링크1링크2에서 확인할 수 있다.
      RewriteRul의 flags
예시) RewriteRule ^old-url.html$ /new-url.html [R=301,L]
        RewriteRule ^/?([a-z/]+).html$ $1.jsp[R=301,L]
        RewriteRule .+.(gif|jpg|png)$ - [F]

이 외에도 mod_rewrite의 지시자로써 Map을 사용하는 RewriteMap과 Rewrite에 대한 옵션을 지정해줄 수 있는 RewriteOptions가 있다.

 

 

Rewrite Rule 적용 예시

프로젝트의 개선이 이루어지면서 구서버는 요청 파라미터로 service, 신서버는 요청 파라미터로 svc를 가진다고 가정하자. 만일 신서버로 service라는 파라미터를 가지고 요청이 들어온다면 이것을 구서버로 rewrite해주는 작업이 필요하게 된다. 따라서 신서버의 QueryString에서 구서버의 요청 파라미터인 service가 발견이 된다면 이것을 구서버로 rewrite를 적용해주보았다. 아래는 신서버에 적용된 Rewrite Rule 예시이다.

1
2
3
4
5
6
7
8
9
LoadModule rewrite_module modules/mod_rewrite.so
 
<IfModule rewrite_module>
        RewriteEngine On
        RewriteCond %{REQUEST_URI} ^/api?$
        RewriteCond %{QUERY_STRING} ^(.*)service=(.*)
        RewriteRule (.*) https://old.server.com/api [L,R=300]
        LogLevel alert rewrite:trace1
</IfModule>
cs

신서버의 Apache conf에 적용된 형태이다. RewriteCond 지시자를 이용하여 /api로의 요청 중 구서버의 파라미터인 name을 가지는 QueryString에 대해 rewrite 조건을 제한해주었다. 그리고 LogLevel 지시자를 통해 로깅을 해주었다.

위의 RewriteRule을 테스트해보기 위해 rewrite 조건에 해당하는 item을 포함한 "https://new.server.com/api?service=100" 요청을 보내주었다. 즉, 신서버로 구서버의 파라미터형식을 요청하였다. Apache의 access 로그에서 다음과 같이 요청을 확인하였다.

신서버의 Apache Access 로그

그 후 해당 요청에 대해 rewrite가 적용된 로그를 아래와 같이 확인 할 수 있었다.

신서버의 Apache Rewrite 로그

신서버에서 구서버의 파라미터형식인 service에 대해 RewriteCond를 제한해주었기에 신서버에서 구서버(old.server.com)로 명시된 300 HTTP 상태코드와 함께 redirect를 확인 할 수 있었다.

 

 

mod_rewrite 지시자의 flags 실습

추가적으로 RewriteCond 및 RewriteRule에 사용되는 다양한 flag들에 대해서 간단한 조건에서 실습을 진행해보았다.

  • NC(NoCase) : RewriteCond의 TestString에 대하여 case-insensitive하게 해주는 flag 이다. TestString에 대문자를 포함시킨다음 NC flag를 적용할 때, 적용하지 않을 때의 차이를 확인해보았다.
    • NC 미적용
    • NC 적용
    • 결과 : 대문자 TestString에 대해 NC 미적용 시에는 rewrite하지 않고 통과하고, NC 적용 시에는 rewrite하는 것을 확인할 수 있었다.

 

  • F(Forbidden) : 일정 조건에 해당하는 요청에 대해 Forbidden을 반환하는 flag 이다. URI에 특정 조건을 제한하고 테스트해보았다.
    • F 적용
    • 결과 : RewriteCond에 해당하는 요청에 대해 403 HTTP 상태코드로 Forbidden하는 것을 확인할 수 있었다.

 

  • QSA(QueryString Append) : 요청에 포함된 QueryString을 rewrite시에 그대로 포함시키는 flag 이다. QueryString을 포함한 요청을 QSA 적용, QSA 미적용에서 차이를 테스트해보았다.
    • QSA 미적용
    • QSA 적용
    • 결과 : QSA를 적용했을 때와 미적용 때 모두 쿼리스트링을 그대로 rewrite해주는 것을 확인할 수 있었다.

 

  • QSD(QueryString Discard) : 요청에 포함된 QueryString을 rewrtie시에 제거 시키는 flag 이다. QSA가 기본적으로 동작하기 때문에 QueryString을 제거하기 위해 QSD를 적용후 테스트해보았다.
    • QSD 적용
    • QSA, QSD 동시 적용
    • 결과 : QSD가 적용되면 QSA 존재여부와 상관없이 QueryString을 제거해주는 것을 확인 할 수 있었다.

 

  • OR : RewriteCond의 flag로써 조건을 or로 처리되도록 설정해주는 flag 이다. RewriteCond는 기본적으로 and 방식으로 동작하기에 RewriteCond에 OR를 미적용, 적용에 대해 테스트해봤다.
    • OR 미적용
    • 첫 번재 조건에 OR 적용
    • 결과 : OR 미적용시 RewriteCond를 모두 만족해야지 RewriteRule이 실행되는 것을 확인할 수 있었고, 첫번째 RewriteCond에 OR 적용시 첫번째 조건에 or가 적용되어 RewrtieRule이 실행되는 것을 알 수 있었다.

 

 

출처
https://httpd.apache.org/docs/current/mod/mod_rewrite.html
https://runebook.dev/ko/docs/apache_http_server/mod/mod_rewrite
https://www.lesstif.com/1stb/mod_rewrite-url-18219493.html
https://zetawiki.com/wiki/아파치_mod_rewrite_지시자
반응형