Proxy AJP + mod_rewrite를 이용하여 Apache 2.2 + Tomcat 완벽 연동하기

블로그 글에 자꾸 반말/존칭이 섞여가는거 같아 껄끄럽긴 하지만 이번에는 존댓말로 써봅니다;;

여러분의 JAVA/JSP는 어떤 WAS에서 돌리고 계신가요? 톰캣을 쓰신다고요?

그럼 웹서버는 아파치를 사용하시겠군요. 연동을 위해 톰캣 사이트에서 받을 수 있는 mod_jk를 많이들 쓰실것입니다.

하지만 아파치 2.2.x에서 제공하는 Proxy AJP를 사용하면 매우 깔끔하게 연동을 할 수 있습니다.

톰캣은 설치가 되어 정상적으로 동작하고 있는 상황이라 가정하고 아파치 설정만을 적어보겠습니다.

[이곳]에서 가장 최신의 아파치 2.2 버젼을 다운받습니다. 압축을 풀고 컴파일을 합니다.

설정(쓰레드 방식)
[code][root@Theeye src]$ CC=”gcc” CFLAGS=”-O2″ ./configure –prefix=/usr/local/httpd –enable-so –enable-proxy-ajp –enable-cgi –enable-rewrite –enable-speling –enable-usertrack –enable-deflate –enable-ssl –enable-cache –enable-disk-cache –enable-expires –enable-file-cache –enable-headers –enable-mem-cache –enable-mime-magic –enable-proxy –enable-mods-shared=all –with-mpm=worker[/code]
설정(프로세스 방식)
[code][root@Theeye src]$ CC=”gcc” CFLAGS=”-O2″ ./configure –prefix=/usr/local/httpd –enable-so –enable-proxy-ajp –enable-cgi –enable-rewrite –enable-speling –enable-usertrack –enable-deflate –enable-ssl –enable-cache –enable-disk-cache –enable-expires –enable-file-cache –enable-headers –enable-mem-cache –enable-mime-magic –enable-proxy –enable-mods-shared=all –with-mpm=prefork[/code]
컴파일
[code][root@Theeye src]$ make
[root@Theeye src]$ make install
[/code]

아파치가 설치된 디렉토리의 conf/httpd.conf 파일을 열어 다음의 두가지가 정상적으로 존재하는지 확인합니다.
[code]LoadModule proxy_ajp_module modules/mod_proxy_ajp.so
LoadModule rewrite_module modules/mod_rewrite.so[/code]

그리고 마지막쯤에 있는 가상호스팅 관련 설정을 인클루드 하도록 설정합니다.
[code]Include conf/extra/httpd-vhosts.conf[/code]

아파치 설치 디렉토리의 conf/extra/httpd-vhost.conf 파일을 열어 가상호스트를 추가합니다.
[code]<VirtualHost *:80>
    ServerAdmin your@emailhere
    DocumentRoot /var/www/html
    ServerName theeye.pe.kr
    ErrorLog logs/theeye.pe.kr-error_log
    CustomLog logs/theeye.pe.kr-access_log common


    RewriteEngine On
    RewriteCond %{REQUEST_FILENAME} \.(htm|html|xhtml|js|css|jpg|gif|png|swf)$
    RewriteRule (.*) – [L]
    RewriteRule (.*) ajp://localhost:8009$1 [P]
</VirtualHost>[/code]
위와같은 rewrite를 통한 설정은 htm, html, xhtml, js, css, jpg, gif, png, swf 확장자를 가진 요청은 아파치가 처리하도록 하고 나머지는 톰캣이 처리하도록 합니다. 원하시는 확장자를 마음껏 추가하셔도 됩니다.

톰캣이 설치된 디렉토리의 conf/server.xml의 설정을 변경합니다. Connector설정을 확인합니다.
[code]<Connector port=”8009″ protocol=”AJP/1.3″ maxThreads=”150″ minSpareThreads=”25″
    maxSpareThreads=”75″ enableLookups=”false” redirectPort=”8443″ acceptCount=”100″
    debug=”0″ connectionTimeout=”20000″ disableUploadTimeout=”true” URIEncoding=”UTF-8″ />[/code]

아파치 가상호스트에 지정한것과 동일한 호스트를 설정합니다.
[code]<Host name=”theeye.pe.kr” debug=”0″ appBase=”/var/www/html” unpackWARs=”true” autoDeploy=”true” xmlValidation=”false” xmlNamespaceAware=”false”>
<Context path=”” docBase=”/var/www/html” debug=”0″ reloadable=”false” crossContext=”true” />
</Host>[/code]

자, 이제 아파치와 톰캣의 설정이 모두 끝났습니다. 위와 같이 사용하시면 아파치에서 처리할 파일과 톰캣이 처리할 파일들을 따로 분리할 필요도 없으며 확장자에 따라 정확히 아파치와 톰캣이 분산 처리를 하게 됩니다.

정적인 파일들을 톰캣이 처리할 필요는 없으니깐요^^

추가로 특정 호스트에게만 오픈하는 관리자 페이지거나 개발서버일 경우 다음과 같이 접근 가능 아이피를 지정할 수 있습니다.

[code]<VirtualHost *:80>
    ServerAdmin your@emailhere
    DocumentRoot /var/www/html
    ServerName theeye.pe.kr
    ErrorLog logs/theeye.pe.kr-error_log
    CustomLog logs/theeye.pe.kr-access_log common


    RewriteEngine On
    RewriteCond !%{REMOTE_ADDR} ^127\.0\.0\.1$
    RewriteRule ^.*$ – [F]
    RewriteCond %{REQUEST_FILENAME} \.(htm|html|xhtml|js|css|jpg|gif|png|swf)$
    RewriteRule (.*) – [L]
    RewriteRule (.*) ajp://localhost:8009$1 [P]
</VirtualHost>[/code]

127.0.0.1 아이피를 가진 호스트가 아니라면 아파치에서 바로 에러페이지를 출력하게 됩니다.

위의 방법을 사용할 경우 보안 문제가 있으니 [ProxyAJP를 이용한 Apache2 + Tomcat 연동시 중대한 보안 문제]을 참고하세요

  • 홍재호`

    알려주신 데로 했는뎅.. ㅜㅜ
    왜 저는 jsp파일을 다운로드 할까요?
    제가 실수라도..ㅜㅜ

    그리고 쓰래도 방식과 프로세스 방식의 차이는 무엇인가요

    • 김규현

      *.jsp 파일은 js 를 포함하고 있기 때문에 apache에서 처리해 버리는군요.
      그래서 소스가 그냥 노출되어 버리네요.

      RewriteCond %{REQUEST_FILENAME} .(htm|html|xhtml|js|css|jpg|gif|png|swf)

      을 아래와 같이 수정

      RewriteCond %{REQUEST_FILENAME} .(htm|html|xhtml|css|jpg|gif|png|swf|js$)

      $는 문자의 끝을 의미하니깐,
      js$는 확장자가 js(문장끝)을 의미하는것 같군요.

      *.js 는 apache가 처리하고
      *.jsp 는 tomcat이 처리하는 군요

      저도 정규식을 잘 몰라 삽질하다 처리했네요..
      더 좋은 방법있음… 부탁요.~~

  • 안녕하세요..
    글 보고 연동을 했는데 안되는 부분이 있어 문의를 드립니다.
    기본적인 연동을 잘 됐구요.
    정상적으로 jsp를 호출하는것도 확인했습니다.
    그런데 문제가 tomcat root에서 제일 밖에 있는 파일들(index.jsp등..)은 잘 호출이 되는데 디렉토리 안에 있는 jsp 파일들은 호출할때 문제가 발생합니다.

    < %@ include file="/include/commonPath.jsp" %>

    이런식으로 공통 jsp 파일을 include하는데 이 파일을 못찾습니다.

    예를들어 /sample/daum/aa.jsp 란 파일이 있으면 그냥은 호출이 되는데 안에 include 하는부분에서 /include/commonPath.jsp 이 경로를 찾지 못합니다.

    org.apache.jasper.JasperException: /daum/index.jsp(10,0) File “/include/commonPath.jsp” not found

    이렇게 메시지를 보여주고 상대경로로 해볼려고

    < %@ include file="../../include/commonPath.jsp" %>

    이렇게 해봤지만 아래와 같이 비슷한 에러를 보여주네요..

    org.apache.jasper.JasperException: /daum/index.jsp(10,0) File “/daum/../../include/commonPath.jsp” not found

    아무래도 context 문제인거 같은데요..

    sample 이란 디렉토리를 context로 인식하는듯 합니다..

    기존에 tomcat만 돌릴때는 문제 없었거든요..

    좋은 해결 방법이 없을까요?

    • 아..죄송합니다.

      제가 tomcat/server.xml에 appBase와 docBase를 잘못 셋팅했네요..

      appBase와 docBase를 같은 경로로 잡아줘서 그랬습니다.

    • 아이

      아, 지금 글을 봤네요, 잘 해결되셨다니 다행입니다!
      날도 더운데 건강 유의하시고요! 즐거운 하루 되시길!

  • 아 정리 잘되어있어서 혼자 끙끙되던걸 한번에 처리했네요.

    도움 많이 됐습니다. 감사합니다~