๐ Apache Tomcat: ๋์ ํจ๊ปํ๋ Java ์น ์๋ฒ ์ฌํ ๐

2025๋ 2์ ๊ธฐ์ค ์ต์ ์ ๋ณด๋ก ์์๋ณด๋ Tomcat ๊ด๋ฆฌ์ ๋ชจ๋ ๊ฒ!
๐ ์๋ , ํฐ์บฃ ์น๊ตฌ๋ค! ๐
์ผํธ! ์ค๋์ Java ์น ๊ฐ๋ฐ์๋ผ๋ฉด ํ ๋ฒ์ฏค ๋ง๋๊ฒ ๋๋ Apache Tomcat์ ๋ํด ํจ๊ป ์์๋ณผ ๊ฑฐ์ผ. ์๋ฒ ๊ด๋ฆฌ๊ฐ ์ด๋ ต๊ฒ ๋๊ปด์ง๋ค๊ณ ? ๊ฑฑ์ ๋ง! ์ด ๊ธ์ ๋ค ์ฝ๊ณ ๋๋ฉด ํฐ์บฃ์ ๋ด ๋ง๋๋ก ๋ค๋ฃฐ ์ ์์ ๊ฑฐ์ผ. ๐
์์ฆ ์ฌ๋ฅ๋ท ๊ฐ์ ์น ํ๋ซํผ๋ค์ด ๋์ด๋๋ฉด์ ์์ ์ ์ธ ์๋ฒ ์ด์์ด ๋ ์ค์ํด์ก์ด. ํนํ Java ๊ธฐ๋ฐ ์น ์ ํ๋ฆฌ์ผ์ด์ ์ ์ด์ํ๋ค๋ฉด Tomcat์ ํ์ ์ง์์ด์ง! ๊ทธ๋ผ ์ง๊ธ๋ถํฐ Tomcat์ ์ธ๊ณ๋ก ํจ๊ป ๋ ๋๋ณผ๊น? ๐ข
๐ Tomcat์ด ๋ญ๊ธธ๋? ๊ธฐ๋ณธ ๊ฐ๋ ์ก๊ธฐ ๐
Apache Tomcat์ Java ์๋ธ๋ฆฟ๊ณผ JSP ๊ธฐ์ ์ ์ง์ํ๋ ์คํ์์ค ์น ์๋ฒ์ด์ ์๋ธ๋ฆฟ ์ปจํ ์ด๋์ผ. 2025๋ 2์ ํ์ฌ Tomcat 10.1.x ๋ฒ์ ์ด ์์ ํ ๋ฒ์ ์ผ๋ก ์ฌ์ฉ๋๊ณ ์๊ณ , Tomcat 11๋ ๊ฐ๋ฐ ์ค์ด๋. ๐
๊ทผ๋ฐ ์๋ธ๋ฆฟ ์ปจํ ์ด๋๊ฐ ๋ญ๋๊ณ ? ๊ฐ๋จํ ๋งํ๋ฉด Java๋ก ์์ฑ๋ ์น ์ ํ๋ฆฌ์ผ์ด์ ์ฝ๋๋ฅผ ์คํํ๊ณ ๊ด๋ฆฌํด์ฃผ๋ ํ๊ฒฝ์ด์ผ. ๋ค๊ฐ ์์ฑํ Java ์ฝ๋๊ฐ ์น์์ ๋์ํ ์ ์๊ฒ ํด์ฃผ๋ ๋ง๋ฒ์ฌ ๊ฐ์ ์กด์ฌ์ง! โจ
๐งฉ Tomcat์ ์ฃผ์ ๊ตฌ์ฑ ์์
- Catalina: ์๋ธ๋ฆฟ ์ปจํ ์ด๋ ๋ถ๋ถ์ผ๋ก Tomcat์ ํต์ฌ์ด์ผ
- Coyote: HTTP ์ปค๋ฅํฐ๋ก ์น ์์ฒญ์ ๋ฐ์ ์ฒ๋ฆฌํด
- Jasper: JSP ์์ง์ผ๋ก JSP ํ์ผ์ ์๋ธ๋ฆฟ์ผ๋ก ๋ณํํด์ค
- Cluster: ์ฌ๋ฌ Tomcat ์ธ์คํด์ค๋ฅผ ํด๋ฌ์คํฐ๋งํ ๋ ์ฌ์ฉํด
- High Availability: ๊ณ ๊ฐ์ฉ์ฑ์ ์ํ ๊ธฐ๋ฅ์ ์ ๊ณตํด
Tomcat์ Apache ๋ผ์ด์ ์ค 2.0์ ๋ฐ๋ฅด๋ ์์ ์ํํธ์จ์ด์ผ. ๊ทธ๋์ ์์ ์ ์ผ๋ก๋ ์์ ๋กญ๊ฒ ์ฌ์ฉํ ์ ์์ด์ ์คํํธ์ ๋ถํฐ ๋๊ธฐ์ ๊น์ง ๋๋ฆฌ ์ฌ์ฉ๋๊ณ ์์ง. ์ฌ๋ฅ๋ท ๊ฐ์ ํ๋ซํผ๋ Java ๊ธฐ๋ฐ์ด๋ผ๋ฉด Tomcat์ ์ฌ์ฉํ๊ณ ์์ ๊ฐ๋ฅ์ฑ์ด ๋์! ๐ข
๐ Tomcat ๋ฒ์ ๋ณ ํน์ง๊ณผ ์ ํ ๊ฐ์ด๋ ๐
2025๋ ํ์ฌ ์ฌ๋ฌ ๋ฒ์ ์ Tomcat์ด ์ฌ์ฉ๋๊ณ ์์ด. ์ด๋ค ๋ฒ์ ์ ์ ํํด์ผ ํ ์ง ๊ณ ๋ฏผ๋๋ค๋ฉด ์ด ๊ฐ์ด๋๋ฅผ ์ฐธ๊ณ ํด๋ด! ๐ง
๐น Tomcat 10.1.x (์ต์ ์์ ํ ๋ฒ์ )
โข Jakarta EE 10 ์ง์
โข Java 11 ์ด์ ํ์
โข ํจํค์ง ๋ค์์คํ์ด์ค๊ฐ javax.* ์์ jakarta.* ๋ก ๋ณ๊ฒฝ
โข HTTP/2 ํ๋กํ ์ฝ ๊ธฐ๋ณธ ์ง์
โข ํฅ์๋ ๋ณด์ ๊ธฐ๋ฅ
๐น Tomcat 9.x
โข Java EE 8 ์ง์
โข Java 8 ์ด์์์ ์๋
โข HTTP/2 ์ง์
โข ๋ง์ ๊ธฐ์
์์ ์์ง ๋๋ฆฌ ์ฌ์ฉ ์ค
๐น Tomcat 8.5.x
โข Java EE 7 ์ง์
โข Java 7 ์ด์์์ ์๋
โข ๋ ๊ฑฐ์ ์์คํ
์์ ์ฌ์ ํ ์ฌ์ฉ ์ค
2025๋ ๊ธฐ์ค์ผ๋ก ์ ํ๋ก์ ํธ๋ผ๋ฉด Tomcat 10.1.x๋ฅผ ์ ํํ๋ ๊ฒ์ด ์ข์! ํ์ง๋ง ๊ธฐ์กด ํ๋ก์ ํธ๋ฅผ ๋ง์ด๊ทธ๋ ์ด์ ํ ๋๋ javax์์ jakarta๋ก์ ๋ค์์คํ์ด์ค ๋ณ๊ฒฝ์ ๊ณ ๋ คํด์ผ ํด. ์ด ๋ณ๊ฒฝ์ผ๋ก ์ธํด ์ฝ๋ ์์ ์ด ํ์ํ ์ ์์ด. ๐
์ฐธ๊ณ ๋ก Tomcat 7.x์ 8.0.x๋ ์ด์ ๊ณต์ ์ง์์ด ์ข ๋ฃ๋์์ผ๋ ๋ณด์์ ์ํด ์ ๊ทธ๋ ์ด๋ํ๋ ๊ฒ์ ๊ฐ๋ ฅํ ์ถ์ฒํด! ๐ก๏ธ
โ๏ธ Tomcat ์ค์น ๋ฐ ๊ธฐ๋ณธ ์ค์ โ๏ธ
์ด์ Tomcat์ ์ค์นํ๊ณ ๊ธฐ๋ณธ ์ค์ ์ ํด๋ณผ๊น? ์ด์์ฒด์ ๋ณ๋ก ์ค์น ๋ฐฉ๋ฒ์ด ์กฐ๊ธ์ฉ ๋ค๋ฅด๋ ๋ค๊ฐ ์ฌ์ฉํ๋ ํ๊ฒฝ์ ๋ง๊ฒ ๋ฐ๋ผ์! ๐ ๏ธ
๐ช Windows์ ์ค์นํ๊ธฐ
- Apache Tomcat ๊ณต์ ์น์ฌ์ดํธ(https://tomcat.apache.org)์์ ์ต์ ๋ฒ์ ์ Windows ์ธ์คํจ๋ฌ(.exe) ๋ค์ด๋ก๋
- ๋ค์ด๋ก๋ํ ์ธ์คํจ๋ฌ ์คํ ํ ์ค์น ๋ง๋ฒ์ฌ ๋ฐ๋ผ๊ฐ๊ธฐ
- ๊ด๋ฆฌ์ ๊ณ์ ์ค์ ์ username๊ณผ password ๊ธฐ์ตํด๋๊ธฐ
- ์ค์น ์๋ฃ ํ Windows ์๋น์ค์์ Tomcat ์๋น์ค ํ์ธ
๐ง Linux์ ์ค์นํ๊ธฐ
Ubuntu๋ Debian ๊ณ์ด์ด๋ผ๋ฉด:
sudo apt update sudo apt install tomcat9 tomcat9-admin
CentOS๋ RHEL ๊ณ์ด์ด๋ผ๋ฉด:
sudo yum install tomcat
๋๋ ์๋์ผ๋ก ์ค์นํ๋ ๋ฐฉ๋ฒ๋ ์์ด:
# JDK๊ฐ ์ค์น๋์ด ์์ด์ผ ํด wget https://downloads.apache.org/tomcat/tomcat-10/v10.1.16/bin/apache-tomcat-10.1.16.tar.gz tar -xzvf apache-tomcat-10.1.16.tar.gz sudo mv apache-tomcat-10.1.16 /opt/tomcat sudo /opt/tomcat/bin/startup.sh
๐ macOS์ ์ค์นํ๊ธฐ
Homebrew๋ฅผ ์ฌ์ฉํ๋ค๋ฉด:
brew install tomcat
๋๋ ์๋์ผ๋ก ์ค์น:
curl -O https://downloads.apache.org/tomcat/tomcat-10/v10.1.16/bin/apache-tomcat-10.1.16.tar.gz tar -xzvf apache-tomcat-10.1.16.tar.gz mv apache-tomcat-10.1.16 ~/tomcat ~/tomcat/bin/startup.sh
๐ ์ค์น ํ์ธํ๊ธฐ
์ค์น๊ฐ ์๋ฃ๋์๋ค๋ฉด ๋ธ๋ผ์ฐ์ ์์ http://localhost:8080์ ์ ์ํด๋ด. Tomcat ์ฐ์ปด ํ์ด์ง๊ฐ ๋ณด์ธ๋ค๋ฉด ์ฑ๊ณต์ด์ผ! ๐
๋ง์ฝ ํ์ด์ง๊ฐ ๋ณด์ด์ง ์๋๋ค๋ฉด:
- Tomcat ์๋น์ค๊ฐ ์คํ ์ค์ธ์ง ํ์ธ
- ๋ฐฉํ๋ฒฝ์ด 8080 ํฌํธ๋ฅผ ์ฐจ๋จํ๊ณ ์๋์ง ํ์ธ
- ๋ก๊ทธ ํ์ผ(/logs/catalina.out)์ ํ์ธํด์ ์ค๋ฅ ๋ฉ์์ง ํ์ธ
๐ Tomcat ๋๋ ํ ๋ฆฌ ๊ตฌ์กฐ ์ดํดํ๊ธฐ ๐
Tomcat์ ์ ๋๋ก ๊ด๋ฆฌํ๋ ค๋ฉด ๋๋ ํ ๋ฆฌ ๊ตฌ์กฐ๋ฅผ ์ดํดํ๋ ๊ฒ ์ค์ํด! ๊ฐ ํด๋๊ฐ ์ด๋ค ์ญํ ์ ํ๋์ง ์์๋ณด์. ๐๏ธ
๐ bin
Tomcat์ ์์ํ๊ณ ์ค์งํ๋ ์คํฌ๋ฆฝํธ๊ฐ ์๋ ํด๋์ผ. startup.sh(bat), shutdown.sh(bat) ๊ฐ์ ์คํ ํ์ผ๋ค์ด ์ฌ๊ธฐ ์์ด.
Windows์์๋ .bat ํ์ผ, Linux/macOS์์๋ .sh ํ์ผ์ ์ฌ์ฉํด!
๐ conf
Tomcat์ ์ค์ ํ์ผ๋ค์ด ์๋ ํด๋์ผ. ๊ฐ์ฅ ์ค์ํ ํ์ผ์ server.xml์ด์ผ. ์ด ํ์ผ์์ ํฌํธ, ์ปค๋ฅํฐ, ํธ์คํธ ๋ฑ์ ์ค์ ํ ์ ์์ด.
์ฃผ์ ์ค์ ํ์ผ๋ค:
- server.xml: ๋ฉ์ธ ์ค์ ํ์ผ
- web.xml: ๊ธฐ๋ณธ ์๋ธ๋ฆฟ ์ค์
- tomcat-users.xml: ์ฌ์ฉ์ ๊ณ์ ๊ณผ ์ญํ ์ ์
- context.xml: ๋ชจ๋ ์น ์ ํ๋ฆฌ์ผ์ด์ ์ ์ ์ฉ๋๋ Context ์ค์
๐ lib
Tomcat์ด ์ฌ์ฉํ๋ JAR ํ์ผ๋ค์ด ์๋ ํด๋์ผ. ๋ชจ๋ ์น ์ ํ๋ฆฌ์ผ์ด์ ์์ ๊ณตํต์ผ๋ก ์ฌ์ฉํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ๊ธฐ์ ๋ฃ์ ์ ์์ด.
๐ logs
Tomcat์ ๋ก๊ทธ ํ์ผ๋ค์ด ์ ์ฅ๋๋ ํด๋์ผ. ๋ฌธ์ ๊ฐ ์๊ฒผ์ ๋ ๊ฐ์ฅ ๋จผ์ ํ์ธํด์ผ ํ ๊ณณ์ด์ง!
์ฃผ์ ๋ก๊ทธ ํ์ผ:
- catalina.out: ๋ฉ์ธ ๋ก๊ทธ ํ์ผ
- localhost_access_log.YYYY-MM-DD.txt: ์ก์ธ์ค ๋ก๊ทธ
- localhost.YYYY-MM-DD.log: ์ ํ๋ฆฌ์ผ์ด์ ๋ก๊ทธ
๐ webapps
์น ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ฐฐํฌํ๋ ๊ธฐ๋ณธ ํด๋์ผ. WAR ํ์ผ์ด๋ ๋๋ ํ ๋ฆฌ๋ฅผ ์ด ํด๋์ ๋ฃ์ผ๋ฉด ์๋์ผ๋ก ๋ฐฐํฌ๋ผ.
๊ธฐ๋ณธ์ ์ผ๋ก ๋ค์ ์ ํ๋ฆฌ์ผ์ด์ ๋ค์ด ํฌํจ๋์ด ์์ด:
- ROOT: ๊ธฐ๋ณธ ์น ์ ํ๋ฆฌ์ผ์ด์ (http://localhost:8080/ ๋ก ์ ๊ทผ)
- examples: ์์ ์ ํ๋ฆฌ์ผ์ด์
- manager: ์น ์ ํ๋ฆฌ์ผ์ด์ ๊ด๋ฆฌ ๋๊ตฌ
- host-manager: ๊ฐ์ ํธ์คํธ ๊ด๋ฆฌ ๋๊ตฌ
๐ work
Tomcat์ด JSP ํ์ผ์ ์๋ธ๋ฆฟ์ผ๋ก ๋ณํํ ์ฝ๋๊ฐ ์ ์ฅ๋๋ ํด๋์ผ. ์์ ์์ ๋๋ ํ ๋ฆฌ๋ก ์๊ฐํ๋ฉด ๋ผ.
๐ temp
Tomcat์ด ์ฌ์ฉํ๋ ์์ ํ์ผ๋ค์ด ์ ์ฅ๋๋ ํด๋์ผ.
์ด ๋๋ ํ ๋ฆฌ ๊ตฌ์กฐ๋ฅผ ์ ์ดํดํ๋ฉด Tomcat ๊ด๋ฆฌ๊ฐ ํจ์ฌ ์ฌ์์ง ๊ฑฐ์ผ! ํนํ ๋ฌธ์ ํด๊ฒฐํ ๋ logs ํด๋๋ฅผ ์์ฃผ ๋ค์ฌ๋ค๋ณด๊ฒ ๋ ๊ฑฐ์ผ. ๐
๐ง Tomcat ๊ธฐ๋ณธ ์ค์ ์ต์ ํํ๊ธฐ ๐ง
Tomcat์ ์ค์นํ๋ค๋ฉด ์ด์ ์ฑ๋ฅ๊ณผ ๋ณด์์ ์ํ ๊ธฐ๋ณธ ์ค์ ์ ์ต์ ํํด๋ณด์! 2025๋ ๊ธฐ์ค์ผ๋ก ๊ถ์ฅ๋๋ ์ค์ ๋ค์ ์๋ ค์ค๊ฒ. ๐ ๏ธ
๐ ๋ณด์ ๊ฐํํ๊ธฐ
1. ๊ธฐ๋ณธ ์น ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ฑฐํ๊ธฐ
์ด์ ํ๊ฒฝ์์๋ ๋ถํ์ํ ์์ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ ๊ฑฐํ๋ ๊ฒ์ด ์ข์:
# webapps ํด๋์์ ๋ถํ์ํ ์ ํ๋ฆฌ์ผ์ด์ ์ญ์ rm -rf $TOMCAT_HOME/webapps/examples rm -rf $TOMCAT_HOME/webapps/docs
2. ๊ด๋ฆฌ์ ๊ณ์ ์ค์ ํ๊ธฐ
tomcat-users.xml ํ์ผ์ ์์ ํด์ ์์ ํ ๊ด๋ฆฌ์ ๊ณ์ ์ ์ค์ ํด:
<tomcat-users> <role rolename="manager-gui"/> <role rolename="admin-gui"/> <user username="admin" password="๋ณต์กํ_๋น๋ฐ๋ฒํธ" roles="manager-gui,admin-gui"/> </tomcat-users>
์ ๋๋ก ๊ธฐ๋ณธ ๋น๋ฐ๋ฒํธ๋ฅผ ์ฌ์ฉํ์ง ๋ง! ํญ์ ๊ฐ๋ ฅํ ๋น๋ฐ๋ฒํธ๋ฅผ ์ฌ์ฉํด์ผ ํด. ๐
3. ์๊ฒฉ ๊ด๋ฆฌ ์ ๊ทผ ์ ํํ๊ธฐ
manager์ host-manager ์ฑ์ META-INF/context.xml ํ์ผ์ ์์ ํด์ ํน์ IP์์๋ง ์ ๊ทผ ๊ฐ๋ฅํ๋๋ก ์ค์ :
<Context antiResourceLocking="false" privileged="true" > <Valve className="org.apache.catalina.valves.RemoteAddrValve" allow="127\.0\.0\.1|192\.168\.1\.\d+"/> </Context>
โก ์ฑ๋ฅ ์ต์ ํํ๊ธฐ
1. JVM ๋ฉ๋ชจ๋ฆฌ ์ค์
bin ํด๋์ catalina.sh(bat) ํ์ผ์ด๋ setenv.sh(bat) ํ์ผ์ ๋ง๋ค์ด JVM ๋ฉ๋ชจ๋ฆฌ ์ค์ ์ ์กฐ์ ํด:
# Linux/macOS (setenv.sh) JAVA_OPTS="$JAVA_OPTS -Xms512m -Xmx1024m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=256m" # Windows (setenv.bat) set JAVA_OPTS=%JAVA_OPTS% -Xms512m -Xmx1024m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=256m
2. ์ปค๋ฅ์ ํ ์ค์
server.xml ํ์ผ์์ HTTP ์ปค๋ฅํฐ ์ค์ ์ ์ต์ ํํด:
<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" maxThreads="400" minSpareThreads="25" maxConnections="10000" acceptCount="100" enableLookups="false" />
3. ์์ถ ํ์ฑํ
๋คํธ์ํฌ ๋์ญํญ์ ์ ์ฝํ๊ธฐ ์ํด ์๋ต ์์ถ์ ํ์ฑํํด:
<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" compression="on" compressionMinSize="2048" noCompressionUserAgents="gozilla, traviata" compressibleMimeType="text/html,text/xml,text/plain,text/css,text/javascript,application/javascript,application/json" />
๐ ์ธ์ ๊ด๋ฆฌ ์ค์
context.xml ํ์ผ์์ ์ธ์ ๊ด๋ฆฌ ์ค์ ์ ์กฐ์ ํด:
<Context> <Manager pathname="" /> <Session maxInactiveInterval="1800" sessionCookieName="JSESSIONID" sessionCookiePath="/" sessionCookieHttpOnly="true" sessionCookieSecure="true" /> </Context>
์ด๋ฐ ๊ธฐ๋ณธ ์ค์ ๋ง ์ ํด์ค๋ Tomcat์ ์ฑ๋ฅ๊ณผ ๋ณด์์ด ํฌ๊ฒ ํฅ์๋ผ! ํนํ ์ฌ๋ฅ๋ท ๊ฐ์ ์น ์๋น์ค๋ฅผ ์ด์ํ๋ค๋ฉด ์ด๋ฐ ์ต์ ํ๋ ํ์์ผ. ์ฌ์ฉ์๊ฐ ๋ง์์ง์๋ก ์ด๋ฐ ์ค์ ์ ์ค์์ฑ์ ๋ ์ปค์ง๊ฑฐ๋ . ๐
๐ฆ ์น ์ ํ๋ฆฌ์ผ์ด์ ๋ฐฐํฌํ๊ธฐ ๐ฆ
์, ์ด์ ๋ค๊ฐ ๋ง๋ Java ์น ์ ํ๋ฆฌ์ผ์ด์ ์ Tomcat์ ๋ฐฐํฌํ๋ ๋ฐฉ๋ฒ์ ์์๋ณผ๊น? ์ฌ๋ฌ ๊ฐ์ง ๋ฐฉ๋ฒ์ด ์์ผ๋ ์ํฉ์ ๋ง๊ฒ ์ ํํ๋ฉด ๋ผ! ๐
๐ ์๋ ๋ฐฐํฌ ๋ฐฉ๋ฒ
1. WAR ํ์ผ ๋ฐฐํฌ
๊ฐ์ฅ ์ผ๋ฐ์ ์ธ ๋ฐฉ๋ฒ์ WAR(Web ARchive) ํ์ผ์ webapps ๋๋ ํ ๋ฆฌ์ ๋ณต์ฌํ๋ ๊ฑฐ์ผ:
# WAR ํ์ผ์ webapps ๋๋ ํ ๋ฆฌ๋ก ๋ณต์ฌ cp myapp.war $TOMCAT_HOME/webapps/ # Tomcat์ด ์๋์ผ๋ก WAR ํ์ผ์ ๊ฐ์งํ๊ณ ๋ฐฐํฌํด์ค
2. ๋๋ ํ ๋ฆฌ ๋ฐฐํฌ
WAR ํ์ผ์ ํ์ด์ ๋๋ ํ ๋ฆฌ ํํ๋ก ๋ฐฐํฌํ ์๋ ์์ด:
# ๋๋ ํ ๋ฆฌ ์์ฑ mkdir $TOMCAT_HOME/webapps/myapp # ์ ํ๋ฆฌ์ผ์ด์ ํ์ผ ๋ณต์ฌ cp -r myapp/* $TOMCAT_HOME/webapps/myapp/
๐ Tomcat Manager๋ฅผ ์ด์ฉํ ๋ฐฐํฌ
Tomcat Manager ์น ์ธํฐํ์ด์ค๋ฅผ ์ฌ์ฉํ๋ฉด GUI๋ก ์ฝ๊ฒ ๋ฐฐํฌํ ์ ์์ด:
- ๋ธ๋ผ์ฐ์ ์์ http://localhost:8080/manager/html ์ ์
- ๊ด๋ฆฌ์ ๊ณ์ ์ผ๋ก ๋ก๊ทธ์ธ
- 'WAR file to deploy' ์น์ ์์ WAR ํ์ผ ์ ํ ํ 'Deploy' ๋ฒํผ ํด๋ฆญ
Tomcat Manager๋ ๋ฐฐํฌ๋ฟ๋ง ์๋๋ผ ์ ํ๋ฆฌ์ผ์ด์ ์์/์ค์ง/์ฌ์์๋ ํ ์ ์์ด์ ํธ๋ฆฌํด! ๐ฎ
๐ Context ์ค์ ์ ํตํ ๋ฐฐํฌ
Context ์ค์ ํ์ผ์ ์ฌ์ฉํด ๋ ์ธ๋ฐํ ๋ฐฐํฌ ์ค์ ์ ํ ์ ์์ด:
1. conf/Catalina/localhost ๋๋ ํ ๋ฆฌ์ XML ํ์ผ ์์ฑ:
# myapp.xml ํ์ผ ์์ฑ <Context docBase="/path/to/myapp" path="/myapp" reloadable="true"> <!-- ์ถ๊ฐ ์ค์ --> </Context>
2. docBase๋ ์ ํ๋ฆฌ์ผ์ด์ ์ค์ ๊ฒฝ๋ก, path๋ URL ๊ฒฝ๋ก๋ฅผ ์๋ฏธํด
3. reloadable="true"๋ก ์ค์ ํ๋ฉด WEB-INF/classes๋ WEB-INF/lib ๋ณ๊ฒฝ ์ ์๋์ผ๋ก ์ฌ๋ก๋ฉํด
๐ ๏ธ ๋น๋ ๋๊ตฌ๋ฅผ ์ด์ฉํ ์๋ ๋ฐฐํฌ
Maven์ด๋ Gradle ๊ฐ์ ๋น๋ ๋๊ตฌ๋ฅผ ์ฌ์ฉํ๋ฉด ๋ฐฐํฌ ๊ณผ์ ์ ์๋ํํ ์ ์์ด:
Maven์ ๊ฒฝ์ฐ tomcat7-maven-plugin์ ์ฌ์ฉ:
<plugin> <groupId>org.apache.tomcat.maven</groupId> <artifactId>tomcat7-maven-plugin</artifactId> <version>2.2</version> <configuration> <url>http://localhost:8080/manager/text</url> <server>TomcatServer</server> <path>/myapp</path> </configuration> </plugin>
๋ฐฐํฌ ๋ช ๋ น:
mvn tomcat7:deploy # ์ฒ์ ๋ฐฐํฌํ ๋ mvn tomcat7:redeploy # ์ด๋ฏธ ๋ฐฐํฌ๋ ์ฑ์ ๋ค์ ๋ฐฐํฌํ ๋
๐ณ Docker๋ฅผ ์ด์ฉํ ๋ฐฐํฌ
2025๋ ์๋ Docker๋ฅผ ์ด์ฉํ ๋ฐฐํฌ๊ฐ ๋ ์ผ๋ฐ์ ์ด์ผ. Dockerfile ์์:
FROM tomcat:10.1-jdk17 # ๊ธฐ๋ณธ ์น์ฑ ์ ๊ฑฐ RUN rm -rf /usr/local/tomcat/webapps/* # WAR ํ์ผ ๋ณต์ฌ COPY target/myapp.war /usr/local/tomcat/webapps/ROOT.war # ํฌํธ ์ค์ EXPOSE 8080 CMD ["catalina.sh", "run"]
Docker ๋น๋ ๋ฐ ์คํ:
docker build -t myapp . docker run -p 8080:8080 myapp
Docker๋ฅผ ์ฌ์ฉํ๋ฉด ํ๊ฒฝ์ ์๊ด์์ด ์ผ๊ด๋ ๋ฐฐํฌ๊ฐ ๊ฐ๋ฅํด์ "๋ด ์ปดํจํฐ์์๋ ์ ๋๋๋ฐ..." ๊ฐ์ ๋ฌธ์ ๋ฅผ ํผํ ์ ์์ด! ๐ณ
์ด๋ค ๋ฐฐํฌ ๋ฐฉ๋ฒ์ ์ ํํ๋ , ๋ฐฐํฌ ํ์๋ ๊ผญ ์ ํ๋ฆฌ์ผ์ด์ ์ด ์ ๋๋ก ๋์ํ๋์ง ํ์ธํด๋ด์ผ ํด. ๋ก๊ทธ ํ์ผ์ ํ์ธํ๊ณ ์ฃผ์ ๊ธฐ๋ฅ๋ค์ ํ ์คํธํด๋ณด๋ ๊ฒ์ ์์ง ๋ง! ๐
๐ ๋ชจ๋ํฐ๋ง ๋ฐ ๋ก๊น ์ค์ ๐
Tomcat ์๋ฒ๋ฅผ ์ด์ํ๋ค ๋ณด๋ฉด ๋ชจ๋ํฐ๋ง๊ณผ ๋ก๊น ์ ์ ๋ง ์ค์ํด! ๋ฌธ์ ๊ฐ ์๊ฒผ์ ๋ ๋น ๋ฅด๊ฒ ์์ธ์ ํ์ ํ๊ณ ํด๊ฒฐํ ์ ์๊ฑฐ๋ . ์ด๋ป๊ฒ ์ค์ ํ๋์ง ์์๋ณผ๊น? ๐
๐ JMX๋ฅผ ์ด์ฉํ ๋ชจ๋ํฐ๋ง
JMX(Java Management Extensions)๋ฅผ ํ์ฑํํ๋ฉด Tomcat์ ๋ค์ํ ์งํ๋ฅผ ๋ชจ๋ํฐ๋งํ ์ ์์ด:
# setenv.sh ๋๋ catalina.sh์ ์ถ๊ฐ JAVA_OPTS="$JAVA_OPTS -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=9999 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false -Djava.rmi.server.hostname=YOUR_SERVER_IP"
JMX๋ฅผ ํ์ฑํํ๋ฉด JConsole์ด๋ VisualVM ๊ฐ์ ๋๊ตฌ๋ก Tomcat์ ์ฑ๋ฅ์ ๋ชจ๋ํฐ๋งํ ์ ์์ด.
๐ ๋ก๊น ์ค์ ์ต์ ํ
Tomcat์ ๋ก๊น ์ค์ ์ conf/logging.properties ํ์ผ์์ ๊ด๋ฆฌํด. ์ฃผ์ ์ค์ ์ ์ดํด๋ณด์:
# ๋ฃจํธ ๋ก๊ฑฐ ๋ ๋ฒจ ์ค์ .handlers = 1catalina.org.apache.juli.AsyncFileHandler, java.util.logging.ConsoleHandler .level = INFO # ์ฝ์ ํธ๋ค๋ฌ ์ค์ java.util.logging.ConsoleHandler.level = FINE java.util.logging.ConsoleHandler.formatter = org.apache.juli.OneLineFormatter # ํ์ผ ํธ๋ค๋ฌ ์ค์ 1catalina.org.apache.juli.AsyncFileHandler.level = FINE 1catalina.org.apache.juli.AsyncFileHandler.directory = ${catalina.base}/logs 1catalina.org.apache.juli.AsyncFileHandler.prefix = catalina. 1catalina.org.apache.juli.AsyncFileHandler.maxDays = 90 1catalina.org.apache.juli.AsyncFileHandler.encoding = UTF-8
๋ก๊ทธ ๋ ๋ฒจ์ ๋ค์๊ณผ ๊ฐ์ ์์๋ก ์์ธ๋๊ฐ ๋์์ ธ:
- SEVERE: ์ฌ๊ฐํ ์ค๋ฅ
- WARNING: ๊ฒฝ๊ณ
- INFO: ์ ๋ณด์ฑ ๋ฉ์์ง (๊ธฐ๋ณธ๊ฐ)
- CONFIG: ์ค์ ๊ด๋ จ ๋ฉ์์ง
- FINE: ์์ธ ์ ๋ณด
- FINER: ๋ ์์ธํ ์ ๋ณด
- FINEST: ๊ฐ์ฅ ์์ธํ ์ ๋ณด
์ด์ ํ๊ฒฝ์์๋ INFO๋ WARNING ๋ ๋ฒจ์ ์ฌ์ฉํ๊ณ , ๋ฌธ์ ํด๊ฒฐ์ด ํ์ํ ๋๋ง FINE ์ดํ๋ก ๋ฎ์ถ๋ ๊ฒ์ด ์ข์! ๋ก๊ทธ ํ์ผ์ด ๋๋ฌด ์ปค์ง ์ ์๊ฑฐ๋ . ๐
๐ ๋ก๊ทธ ๋กํ ์ด์ ์ค์
๋ก๊ทธ ํ์ผ์ด ๋ฌดํ์ ์ปค์ง์ง ์๋๋ก ๋ก๊ทธ ๋กํ ์ด์ ์ ์ค์ ํ๋ ๊ฒ์ด ์ค์ํด:
# logging.properties์์ ์ค์ 1catalina.org.apache.juli.AsyncFileHandler.rotatable = true 1catalina.org.apache.juli.AsyncFileHandler.suffix = .yyyy-MM-dd 1catalina.org.apache.juli.AsyncFileHandler.maxDays = 90
์ด๋ ๊ฒ ์ค์ ํ๋ฉด ๋ก๊ทธ ํ์ผ์ด ๋ ์ง๋ณ๋ก ์์ฑ๋๊ณ , 90์ผ์ด ์ง๋ ๋ก๊ทธ๋ ์๋์ผ๋ก ์ญ์ ๋ผ.
๐ ์ธ๋ถ ๋ชจ๋ํฐ๋ง ๋๊ตฌ ์ฐ๋
2025๋ ์๋ ๋ค์๊ณผ ๊ฐ์ ์ธ๋ถ ๋ชจ๋ํฐ๋ง ๋๊ตฌ์ Tomcat์ ์ฐ๋ํ๋ ๊ฒ์ด ์ผ๋ฐ์ ์ด์ผ:
- Prometheus + Grafana: ๋ฉํธ๋ฆญ ์์ง ๋ฐ ์๊ฐํ
- ELK Stack: ๋ก๊ทธ ์์ง, ๊ฒ์, ๋ถ์
- New Relic / Datadog: APM(Application Performance Monitoring)
- Spring Boot Actuator: Spring Boot ์ ํ๋ฆฌ์ผ์ด์ ๋ชจ๋ํฐ๋ง
Prometheus์ ์ฐ๋ํ๋ ค๋ฉด JMX Exporter๋ฅผ ์ค์ ํด:
# JMX Exporter JAR ํ์ผ ๋ค์ด๋ก๋ wget https://repo1.maven.org/maven2/io/prometheus/jmx/jmx_prometheus_javaagent/0.17.2/jmx_prometheus_javaagent-0.17.2.jar -O /opt/jmx_exporter.jar # ์ค์ ํ์ผ ์์ฑ cat > /opt/jmx_exporter_config.yaml << EOF --- startDelaySeconds: 0 ssl: false lowercaseOutputName: false lowercaseOutputLabelNames: false EOF # Tomcat ์์ ์คํฌ๋ฆฝํธ์ JMX Exporter ์ถ๊ฐ JAVA_OPTS="$JAVA_OPTS -javaagent:/opt/jmx_exporter.jar=8080:/opt/jmx_exporter_config.yaml"
๋ชจ๋ํฐ๋ง ๋๊ตฌ๋ฅผ ์ ํ์ฉํ๋ฉด ๋ฌธ์ ๊ฐ ๋ฐ์ํ๊ธฐ ์ ์ ๋ฏธ๋ฆฌ ๊ฐ์งํ๊ณ ๋์ํ ์ ์์ด! ํนํ ์ฌ๋ฅ๋ท ๊ฐ์ ์๋น์ค๋ฅผ ์ด์ํ๋ค๋ฉด, ์ฌ์ฉ์ ๊ฒฝํ์ ์ง์ ์ ์ธ ์ํฅ์ ๋ฏธ์น๋ ์ฑ๋ฅ ๋ฌธ์ ๋ฅผ ๋น ๋ฅด๊ฒ ํ์ ํ๋ ๊ฒ์ด ์ค์ํ์ง. ๐จ
๐ ๋ณด์ ๊ฐํ ์ ๋ต ๐
์น ์๋ฒ๋ ํญ์ ๋ณด์ ๊ณต๊ฒฉ์ ํ์ ์ด ๋๊ธฐ ์ฌ์. ํนํ Tomcat์ ๋๋ฆฌ ์ฌ์ฉ๋๋ ์๋ฒ์ด๊ธฐ ๋๋ฌธ์ ๋ ๋ง์ ๊ณต๊ฒฉ์ ๋ฐ์ ์ ์์ด. 2025๋ ๊ธฐ์ค์ผ๋ก Tomcat์ ๋ณด์์ ๊ฐํํ๋ ๋ฐฉ๋ฒ์ ์์๋ณด์! ๐ก๏ธ
๐ ๊ธฐ๋ณธ ๋ณด์ ์ค์
- ์ต์ ๋ฒ์ ์ ์ง: ํญ์ ์ต์ ๋ณด์ ํจ์น๊ฐ ์ ์ฉ๋ Tomcat ๋ฒ์ ์ ์ฌ์ฉํด
- ๋ถํ์ํ ๊ธฐ๋ฅ ๋นํ์ฑํ: ์ฌ์ฉํ์ง ์๋ ๊ธฐ๋ฅ์ ๋ชจ๋ ๋นํ์ฑํํด
- ๊ธฐ๋ณธ ์น ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ฑฐ: ์์ , ๋ฌธ์ ๋ฑ ๋ถํ์ํ ์น ์ฑ์ ์ ๊ฑฐํด
- Server ์ ๋ณด ์จ๊ธฐ๊ธฐ: ๋ฒ์ ์ ๋ณด ๋ฑ์ ๋ ธ์ถํ์ง ์๋๋ก ์ค์ ํด
server.xml์์ Server ์ ๋ณด ์จ๊ธฐ๊ธฐ:
<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" server="Server" />
๐ ์ธ์ฆ ๋ฐ ๊ถํ ์ค์
1. ๊ด๋ฆฌ์ ์ธํฐํ์ด์ค ๋ณดํธ
tomcat-users.xml ํ์ผ์์ ๊ฐ๋ ฅํ ๋น๋ฐ๋ฒํธ๋ฅผ ์ค์ ํ๊ณ , ํน์ IP์์๋ง ์ ๊ทผ ๊ฐ๋ฅํ๋๋ก ์ ํํด:
# webapps/manager/META-INF/context.xml <Context antiResourceLocking="false" privileged="true" > <Valve className="org.apache.catalina.valves.RemoteAddrValve" allow="127\.0\.0\.1|192\.168\.1\.\d+" /> </Context>
2. HTTPS ์ค์
2025๋ ์๋ ๋ชจ๋ ์น ์๋น์ค๊ฐ HTTPS๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด ํ์ค์ด์ผ! server.xml์ SSL ์ปค๋ฅํฐ๋ฅผ ์ค์ ํด:
<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol" maxThreads="150" SSLEnabled="true" scheme="https" secure="true" keystoreFile="${user.home}/.keystore" keystorePass="changeit" clientAuth="false" sslProtocol="TLS" sslEnabledProtocols="TLSv1.2,TLSv1.3" />
3. HTTP ์๋ต ํค๋ ๋ณด์ ์ค์
web.xml์ ๋ณด์ ๊ด๋ จ HTTP ํค๋๋ฅผ ์ถ๊ฐํด:
<filter> <filter-name>httpHeaderSecurity</filter-name> <filter-class>org.apache.catalina.filters.HttpHeaderSecurityFilter</filter-class> <init-param> <param-name>hstsEnabled</param-name> <param-value>true</param-value> </init-param> <init-param> <param-name>hstsMaxAgeSeconds</param-name> <param-value>31536000</param-value> </init-param> <init-param> <param-name>hstsIncludeSubDomains</param-name> <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>httpHeaderSecurity</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
๐ก๏ธ ๊ณ ๊ธ ๋ณด์ ์ค์
1. ์ธ์ ๋ณด์ ๊ฐํ
context.xml์ ์ธ์ ์ฟ ํค ๋ณด์ ์ค์ ์ ์ถ๊ฐํด:
<Context> <CookieProcessor className="org.apache.tomcat.util.http.Rfc6265CookieProcessor" sameSiteCookies="strict" /> <Manager pathname="" /> <Session cookieHttpOnly="true" cookieSecure="true" /> </Context>
2. ์น ์ ํ๋ฆฌ์ผ์ด์ ๋ณด์ ์ค์
web.xml์ ๋ณด์ ์ ์ฝ ์กฐ๊ฑด์ ์ถ๊ฐํด:
<security-constraint> <web-resource-collection> <web-resource-name>Entire Application</web-resource-name> <url-pattern>/*</url-pattern> </web-resource-collection> <user-data-constraint> <transport-guarantee>CONFIDENTIAL</transport-guarantee> </user-data-constraint> </security-constraint>
3. WAF(Web Application Firewall) ์ค์
ModSecurity ๊ฐ์ WAF๋ฅผ Tomcat ์์ ๋ฐฐ์นํด SQL ์ธ์ ์ , XSS ๋ฑ์ ๊ณต๊ฒฉ์ ๋ฐฉ์ดํ ์ ์์ด.
๐ ๋ณด์ ๋ชจ๋ํฐ๋ง ๋ฐ ๊ฐ์ฌ
1. ์ ๊ทผ ๋ก๊ทธ ํ์ฑํ
server.xml์ AccessLogValve๋ฅผ ์ค์ ํด:
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" prefix="localhost_access_log" suffix=".txt" pattern="%h %l %u %t "%r" %s %b "%{Referer}i" "%{User-Agent}i"" resolveHosts="false" />
2. ๋ณด์ ์ค์บ๋ ๋๊ตฌ ์ฌ์ฉ
OWASP ZAP, Nessus ๊ฐ์ ๋๊ตฌ๋ก ์ ๊ธฐ์ ์ธ ๋ณด์ ์ทจ์ฝ์ ์ค์บ๋์ ์ํํด.
3. ์นจ์ ํ์ง ์์คํ (IDS) ์ฐ๋
Fail2ban ๊ฐ์ ๋๊ตฌ๋ฅผ ์ฌ์ฉํด ๋น์ ์์ ์ธ ์ ๊ทผ ์๋๋ฅผ ์ฐจ๋จํด:
# Fail2ban ์ค์ ์์ (jail.local) [tomcat] enabled = true port = http,https filter = tomcat-auth logpath = /path/to/tomcat/logs/catalina.out maxretry = 3 bantime = 3600
๋ณด์์ ์ผํ์ฑ ์์ ์ด ์๋๋ผ ์ง์์ ์ธ ๊ณผ์ ์ด์ผ. ์ ๊ธฐ์ ์ธ ์ ๋ฐ์ดํธ์ ๋ชจ๋ํฐ๋ง์ด ํ์! ํนํ ์ฌ๋ฅ๋ท๊ณผ ๊ฐ์ ์ฌ์ฉ์ ๋ฐ์ดํฐ๋ฅผ ๋ค๋ฃจ๋ ์๋น์ค๋ผ๋ฉด ๋ณด์์ ๋ ์ ๊ฒฝ ์จ์ผ ํด. ๐
โก ์ฑ๋ฅ ํ๋ ๋ฐ ์ต์ ํ โก
Tomcat์ ์ฑ๋ฅ์ ๊ทน๋ํํ๊ณ ์ถ๋ค๋ฉด? ๋ค์ํ ํ๋ ์ต์ ์ ์์๋ณด์! ํนํ ํธ๋ํฝ์ด ๋ง์ ์ฌ๋ฅ๋ท ๊ฐ์ ์๋น์ค๋ผ๋ฉด ์ด๋ฐ ์ต์ ํ๊ฐ ํฐ ์ฐจ์ด๋ฅผ ๋ง๋ค ์ ์์ด. ๐
๐ง JVM ํ๋
1. ๋ฉ๋ชจ๋ฆฌ ์ค์
setenv.sh(bat) ํ์ผ์ JVM ๋ฉ๋ชจ๋ฆฌ ์ค์ ์ ์ต์ ํํด:
# 8GB RAM ์๋ฒ ๊ธฐ์ค ์ค์ ์์ JAVA_OPTS="$JAVA_OPTS -Xms2048m -Xmx4096m -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=512m" # GC ๋ก๊น ํ์ฑํ JAVA_OPTS="$JAVA_OPTS -Xlog:gc*:file=$CATALINA_HOME/logs/gc.log:time,uptime:filecount=10,filesize=100M"
2. ๊ฐ๋น์ง ์ปฌ๋ ํฐ ์ ํ
Java 17 ์ด์์์๋ G1 GC๊ฐ ๊ธฐ๋ณธ์ด์ง๋ง, ์ํฉ์ ๋ฐ๋ผ ๋ค๋ฅธ GC๋ฅผ ์ ํํ ์ ์์ด:
# G1 GC (๊ธฐ๋ณธ๊ฐ, ๋๋ถ๋ถ์ ๊ฒฝ์ฐ ์ ํฉ) JAVA_OPTS="$JAVA_OPTS -XX:+UseG1GC" # ZGC (์ด์ ์ง์ฐ ์ ํ๋ฆฌ์ผ์ด์ ์ฉ, Java 17 ์ด์์์ ์์ ํ) JAVA_OPTS="$JAVA_OPTS -XX:+UseZGC"
๐ ์ปค๋ฅ์ ํ ์ต์ ํ
server.xml์ Connector ์ค์ ์ ์ต์ ํํด:
<Connector port="8080" protocol="org.apache.coyote.http11.Http11Nio2Protocol" connectionTimeout="20000" redirectPort="8443" maxThreads="400" minSpareThreads="50" maxConnections="10000" acceptCount="500" maxKeepAliveRequests="100" keepAliveTimeout="60000" socketBuffer="65536" processorCache="400" tcpNoDelay="true" enableLookups="false" />
2025๋ ๊ธฐ์ค์ผ๋ก HTTP/2 ํ๋กํ ์ฝ์ ์ฌ์ฉํ๋ ๊ฒ์ด ์ฑ๋ฅ ํฅ์์ ๋์์ด ๋ผ! HTTP/2 ์ค์ :
<Connector port="8443" protocol="org.apache.coyote.http11.Http11Nio2Protocol" SSLEnabled="true" maxThreads="400" scheme="https" secure="true" keystoreFile="conf/keystore.jks" keystorePass="changeit" clientAuth="false" sslProtocol="TLS" sslEnabledProtocols="TLSv1.2,TLSv1.3" ciphers="TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384" maxHttpHeaderSize="8192" http2="true" />
๐ฆ ์ ์ ์ฝํ ์ธ ์ต์ ํ
1. ์ ์ ํ์ผ ์บ์ฑ
web.xml์ ์ ์ ๋ฆฌ์์ค ์บ์ฑ ์ค์ ์ ์ถ๊ฐํด:
<filter> <filter-name>ExpiresFilter</filter-name> <filter-class>org.apache.catalina.filters.ExpiresFilter</filter-class> <init-param> <param-name>ExpiresByType image</param-name> <param-value>access plus 1 week</param-value> </init-param> <init-param> <param-name>ExpiresByType text/css</param-name> <param-value>access plus 1 day</param-value> </init-param> <init-param> <param-name>ExpiresByType application/javascript</param-name> <param-value>access plus 1 day</param-value> </init-param> </filter> <filter-mapping> <filter-name>ExpiresFilter</filter-name> <url-pattern>/*</url-pattern> <dispatcher>REQUEST</dispatcher> </filter-mapping>
2. ์์ถ ํ์ฑํ
server.xml์ Connector์ ์์ถ ์ค์ ์ ์ถ๊ฐํด:
<Connector ... compression="on" compressionMinSize="2048" noCompressionUserAgents="gozilla, traviata" compressibleMimeType="text/html,text/xml,text/plain,text/css,text/javascript,application/javascript,application/json,application/xml" />
๐ ์ ํ๋ฆฌ์ผ์ด์ ๋ ๋ฒจ ์ต์ ํ
1. JSP ์ฌ์ ์ปดํ์ผ
JSP ํ์ผ์ ๋ฏธ๋ฆฌ ์ปดํ์ผํด์ ์ฒซ ์์ฒญ ์ ์ง์ฐ์ ์ค์ผ ์ ์์ด:
# Maven์ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ mvn org.apache.jasper.jspc:jspc-maven-plugin:compile
2. ์ธ์ ํด๋ฌ์คํฐ๋ง ์ต์ ํ
์ฌ๋ฌ Tomcat ์ธ์คํด์ค๋ฅผ ์ด์ํ ๋ ์ธ์ ๋ณต์ ๋ฐฉ์์ ์ต์ ํํด:
<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster" channelSendOptions="8"> <Manager className="org.apache.catalina.ha.session.DeltaManager" expireSessionsOnShutdown="false" notifyListenersOnReplication="true"/> <Channel className="org.apache.catalina.tribes.group.GroupChannel"> <Membership className="org.apache.catalina.tribes.membership.McastService" address="228.0.0.4" port="45564" frequency="500" dropTime="3000"/> <Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver" address="auto" port="4000" autoBind="100" selectorTimeout="5000" maxThreads="6"/> <Sender className="org.apache.catalina.tribes.transport.ReplicationTransmitter"> <Transport className="org.apache.catalina.tribes.transport.nio.PooledParallelSender"/> </Sender> <Interceptor className="org.apache.catalina.tribes.group.interceptors.TcpFailureDetector"/> <Interceptor className="org.apache.catalina.tribes.group.interceptors.MessageDispatchInterceptor"/> </Channel> <Valve className="org.apache.catalina.ha.tcp.ReplicationValve" filter=""/> <Valve className="org.apache.catalina.ha.session.JvmRouteBinderValve"/> <Deployer className="org.apache.catalina.ha.deploy.FarmWarDeployer" tempDir="/tmp/war-temp/" deployDir="/tmp/war-deploy/" watchDir="/tmp/war-listen/" watchEnabled="false"/> <ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener"/> </Cluster>
3. ์ธ๋ถ ์ธ์ ์ ์ฅ์ ์ฌ์ฉ
Redis๋ Memcached ๊ฐ์ ์ธ๋ถ ์ธ์ ์ ์ฅ์๋ฅผ ์ฌ์ฉํ๋ฉด ํด๋ฌ์คํฐ๋ง ํ๊ฒฝ์์ ๋ ํจ์จ์ ์ด์ผ:
# Redis ์ธ์ ๊ด๋ฆฌ์ ์ค์ (context.xml) <Manager className="com.orangefunction.tomcat.redissessions.RedisSessionManager" host="localhost" port="6379" database="0" maxInactiveInterval="60" />
์ฑ๋ฅ ํ๋์ ํญ์ ์ธก์ ๊ณผ ํจ๊ป ์งํํด์ผ ํด! ๋ณ๊ฒฝ ์ ํ์ ์ฑ๋ฅ์ ๋น๊ตํ๊ณ , ์ค์ ๋ก ๊ฐ์ ๋์๋์ง ํ์ธํ๋ ๊ฒ์ด ์ค์ํด. ๋ฌด์์ ์ค์ ๊ฐ์ ๋์ด๋ ๊ฒ์ ์คํ๋ ค ์ฑ๋ฅ์ ์ ํ์ํฌ ์ ์์ด. ๐
๐ ํด๋ฌ์คํฐ๋ง ๋ฐ ๋ก๋ ๋ฐธ๋ฐ์ฑ ๐
ํธ๋ํฝ์ด ๋ง์ ์น ์๋น์ค๋ผ๋ฉด ๋จ์ผ Tomcat ์ธ์คํด์ค๋ก๋ ๋ถ์กฑํ ์ ์์ด. ์ฌ๋ฌ Tomcat ์๋ฒ๋ฅผ ํด๋ฌ์คํฐ๋งํ๊ณ ๋ก๋ ๋ฐธ๋ฐ์ฑํ๋ ๋ฐฉ๋ฒ์ ์์๋ณด์! ๐
๐ ๋ก๋ ๋ฐธ๋ฐ์ฑ ์ํคํ ์ฒ
2025๋ ๊ธฐ์ค์ผ๋ก ์ผ๋ฐ์ ์ธ Tomcat ํด๋ฌ์คํฐ๋ง ์ํคํ ์ฒ๋ ๋ค์๊ณผ ๊ฐ์:
- ํด๋ผ์ด์ธํธ: ์น ๋ธ๋ผ์ฐ์ ๋ ๋ชจ๋ฐ์ผ ์ฑ
- ๋ก๋ ๋ฐธ๋ฐ์: Nginx, HAProxy, AWS ELB ๋ฑ
- Tomcat ์๋ฒ ํด๋ฌ์คํฐ: ์ฌ๋ฌ Tomcat ์ธ์คํด์ค
- ๊ณต์ ์ ์ฅ์: ์ธ์ ๋ฐ์ดํฐ, ํ์ผ ๋ฑ์ ์ ์ฅ
- ๋ฐ์ดํฐ๋ฒ ์ด์ค: MySQL, PostgreSQL ๋ฑ
โ๏ธ ๋ก๋ ๋ฐธ๋ฐ์ ์ค์
Nginx๋ฅผ ๋ก๋ ๋ฐธ๋ฐ์๋ก ์ฌ์ฉํ๋ ์์:
# /etc/nginx/conf.d/tomcat.conf upstream tomcat_cluster { # ๋ผ์ด๋ ๋ก๋น ๋ฐฉ์ (๊ธฐ๋ณธ๊ฐ) server tomcat1.example.com:8080; server tomcat2.example.com:8080; server tomcat3.example.com:8080; # ๋๋ IP ํด์ ๋ฐฉ์ (๊ฐ์ IP๋ ๊ฐ์ ์๋ฒ๋ก) # ip_hash; # ๋๋ ์ต์ ์ฐ๊ฒฐ ๋ฐฉ์ (์ฐ๊ฒฐ์ด ์ ์ ์๋ฒ๋ก) # least_conn; # ์๋ฒ ๊ฐ์ค์น ์ค์ # server tomcat1.example.com:8080 weight=3; # server tomcat2.example.com:8080 weight=1; } server { listen 80; server_name example.com; location / { proxy_pass http://tomcat_cluster; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; # ์ธ์ ๊ณ ์ (sticky session) # proxy_cookie_path / "/; SameSite=None; Secure; HttpOnly; Path=/"; # ํ์์์ ์ค์ proxy_connect_timeout 300s; proxy_send_timeout 300s; proxy_read_timeout 300s; } }
๐ ์ธ์ ๊ด๋ฆฌ ์ ๋ต
ํด๋ฌ์คํฐ ํ๊ฒฝ์์ ์ธ์ ์ ๊ด๋ฆฌํ๋ ๋ฐฉ๋ฒ์ ํฌ๊ฒ ์ธ ๊ฐ์ง์ผ:
1. ์ธ์ ๋ณต์ (Session Replication)
Tomcat ๋ด์ฅ ๊ธฐ๋ฅ์ ์ฌ์ฉํ ์ธ์ ๋ณต์ ์ค์ :
# server.xml <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster" channelSendOptions="8"> <Manager className="org.apache.catalina.ha.session.DeltaManager" expireSessionsOnShutdown="false" notifyListenersOnReplication="true"/> <!-- ๊ธฐํ ์ค์ ์๋ต --> </Cluster> # web.xml์ ๋ถ์ฐ ์ค์ ์ถ๊ฐ <distributable/>
2. ๊ณ ์ ์ธ์ (Sticky Session)
๋ก๋ ๋ฐธ๋ฐ์์์ ๊ฐ์ ์ฌ์ฉ์๋ฅผ ํญ์ ๊ฐ์ ์๋ฒ๋ก ๋ณด๋ด๋ ๋ฐฉ์์ด์ผ. Nginx ์ค์ :
# Nginx ์ค์ upstream tomcat_cluster { ip_hash; # ๊ฐ์ IP๋ ๊ฐ์ ์๋ฒ๋ก server tomcat1.example.com:8080; server tomcat2.example.com:8080; }
3. ์ค์ ์ง์ค์ ์ธ์ ์ ์ฅ์
2025๋ ์๋ Redis๋ Memcached ๊ฐ์ ์ธ๋ถ ์ธ์ ์ ์ฅ์๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด ๊ฐ์ฅ ๊ถ์ฅ๋๋ ๋ฐฉ์์ด์ผ! Redis ์ธ์ ๊ด๋ฆฌ์ ์ค์ :
# pom.xml์ ์์กด์ฑ ์ถ๊ฐ <dependency> <groupId>com.orangefunction</groupId> <artifactId>tomcat-redis-session-manager</artifactId> <version>2.0.0</version> </dependency> # context.xml ์ค์ <Valve className="com.orangefunction.tomcat.redissessions.RedisSessionHandlerValve" /> <Manager className="com.orangefunction.tomcat.redissessions.RedisSessionManager" host="redis.example.com" port="6379" database="0" password="your_redis_password" maxInactiveInterval="60" />
๐ ๊ณต์ ํ์ผ ์์คํ
์ฌ๋ฌ Tomcat ์๋ฒ๊ฐ ๊ฐ์ ํ์ผ์ ์ ๊ทผํด์ผ ํ๋ค๋ฉด ๊ณต์ ํ์ผ ์์คํ ์ ์ค์ ํด์ผ ํด:
- NFS: ๋ฆฌ๋ ์ค ํ๊ฒฝ์์ ๋๋ฆฌ ์ฌ์ฉ๋๋ ๋คํธ์ํฌ ํ์ผ ์์คํ
- S3/EFS: AWS ํ๊ฒฝ์์ ์ฌ์ฉํ ์ ์๋ ํด๋ผ์ฐ๋ ์คํ ๋ฆฌ์ง
- GlusterFS/Ceph: ๋ถ์ฐ ํ์ผ ์์คํ
NFS ๋ง์ดํธ ์์:
# NFS ์๋ฒ ์ค์ sudo apt install nfs-kernel-server echo "/shared/tomcat *(rw,sync,no_subtree_check)" >> /etc/exports sudo exportfs -a sudo systemctl restart nfs-kernel-server # NFS ํด๋ผ์ด์ธํธ ์ค์ sudo apt install nfs-common sudo mkdir -p /mnt/shared sudo mount nfs-server:/shared/tomcat /mnt/shared
๐ ์๋ ๋ฐฐํฌ ์ค์
ํด๋ฌ์คํฐ ํ๊ฒฝ์์ ๋ชจ๋ ์๋ฒ์ ๋์์ ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ฐฐํฌํ๋ ๋ฐฉ๋ฒ:
1. Tomcat์ FarmWarDeployer ์ฌ์ฉ:
<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"> <!-- ๊ธฐํ ์ค์ ์๋ต --> <Deployer className="org.apache.catalina.ha.deploy.FarmWarDeployer" tempDir="/tmp/war-temp/" deployDir="/tmp/war-deploy/" watchDir="/tmp/war-listen/" watchEnabled="true"/> </Cluster>
2. CI/CD ํ์ดํ๋ผ์ธ ์ฌ์ฉ (Jenkins, GitHub Actions ๋ฑ)
Jenkins ํ์ดํ๋ผ์ธ ์์:
pipeline { agent any stages { stage('Build') { steps { sh 'mvn clean package' } } stage('Deploy') { steps { sh ''' for server in tomcat1 tomcat2 tomcat3; do scp target/myapp.war user@$server:/opt/tomcat/webapps/ ssh user@$server "sudo systemctl restart tomcat" done ''' } } } }
ํด๋ฌ์คํฐ๋ง์ ๊ฐ์ฉ์ฑ๊ณผ ํ์ฅ์ฑ์ ๋์ด์ง๋ง, ๋ณต์ก์ฑ๋ ์ฆ๊ฐํด. ์ฒ ์ ํ ํ ์คํธ์ ๋ชจ๋ํฐ๋ง์ด ํ์์ผ! ํนํ ์ฌ๋ฅ๋ท ๊ฐ์ ์๋น์ค๊ฐ ์ฑ์ฅํ๋ฉด์ ํธ๋ํฝ์ด ์ฆ๊ฐํ๋ค๋ฉด, ํด๋ฌ์คํฐ๋ง์ ํ์์ ์ธ ์ ํ์ด ๋ ๊ฑฐ์ผ. ๐
๐ ๋ฌธ์ ํด๊ฒฐ ๋ฐ ๋๋ฒ๊น ๊ฐ์ด๋ ๐
Tomcat์ ์ด์ํ๋ค ๋ณด๋ฉด ๋ค์ํ ๋ฌธ์ ๊ฐ ๋ฐ์ํ ์ ์์ด. 2025๋ ๊ธฐ์ค์ผ๋ก ๊ฐ์ฅ ํํ ๋ฌธ์ ๋ค๊ณผ ํด๊ฒฐ ๋ฐฉ๋ฒ์ ์์๋ณด์! ๐ ๏ธ
๐ซ ์์ ์คํจ ๋ฌธ์
1. ํฌํธ ์ถฉ๋
Tomcat์ด ์์๋์ง ์๋ ๊ฐ์ฅ ํํ ์์ธ ์ค ํ๋๋ ํฌํธ ์ถฉ๋์ด์ผ:
# ํฌํธ ์ฌ์ฉ ํ์ธ (Linux/macOS) sudo lsof -i :8080 # ํฌํธ ์ฌ์ฉ ํ์ธ (Windows) netstat -ano | findstr :8080 # server.xml์์ ํฌํธ ๋ณ๊ฒฝ <Connector port="8081" protocol="HTTP/1.1" ... />
2. ๋ฉ๋ชจ๋ฆฌ ๋ถ์กฑ
OutOfMemoryError๊ฐ ๋ฐ์ํ๋ ๊ฒฝ์ฐ:
- ์ง์์ธ์ ์ฒ - ์ง์ ์ฌ์ฐ๊ถ ๋ณดํธ ๊ณ ์ง
์ง์ ์ฌ์ฐ๊ถ ๋ณดํธ ๊ณ ์ง
- ์ ์๊ถ ๋ฐ ์์ ๊ถ: ๋ณธ ์ปจํ ์ธ ๋ ์ฌ๋ฅ๋ท์ ๋ ์ AI ๊ธฐ์ ๋ก ์์ฑ๋์์ผ๋ฉฐ, ๋ํ๋ฏผ๊ตญ ์ ์๊ถ๋ฒ ๋ฐ ๊ตญ์ ์ ์๊ถ ํ์ฝ์ ์ํด ๋ณดํธ๋ฉ๋๋ค.
- AI ์์ฑ ์ปจํ ์ธ ์ ๋ฒ์ ์ง์: ๋ณธ AI ์์ฑ ์ปจํ ์ธ ๋ ์ฌ๋ฅ๋ท์ ์ง์ ์ฐฝ์๋ฌผ๋ก ์ธ์ ๋๋ฉฐ, ๊ด๋ จ ๋ฒ๊ท์ ๋ฐ๋ผ ์ ์๊ถ ๋ณดํธ๋ฅผ ๋ฐ์ต๋๋ค.
- ์ฌ์ฉ ์ ํ: ์ฌ๋ฅ๋ท์ ๋ช ์์ ์๋ฉด ๋์ ์์ด ๋ณธ ์ปจํ ์ธ ๋ฅผ ๋ณต์ , ์์ , ๋ฐฐํฌ, ๋๋ ์์ ์ ์ผ๋ก ํ์ฉํ๋ ํ์๋ ์๊ฒฉํ ๊ธ์ง๋ฉ๋๋ค.
- ๋ฐ์ดํฐ ์์ง ๊ธ์ง: ๋ณธ ์ปจํ ์ธ ์ ๋ํ ๋ฌด๋จ ์คํฌ๋ํ, ํฌ๋กค๋ง, ๋ฐ ์๋ํ๋ ๋ฐ์ดํฐ ์์ง์ ๋ฒ์ ์ ์ฌ์ ๋์์ด ๋ฉ๋๋ค.
- AI ํ์ต ์ ํ: ์ฌ๋ฅ๋ท์ AI ์์ฑ ์ปจํ ์ธ ๋ฅผ ํ AI ๋ชจ๋ธ ํ์ต์ ๋ฌด๋จ ์ฌ์ฉํ๋ ํ์๋ ๊ธ์ง๋๋ฉฐ, ์ด๋ ์ง์ ์ฌ์ฐ๊ถ ์นจํด๋ก ๊ฐ์ฃผ๋ฉ๋๋ค.
์ฌ๋ฅ๋ท์ ์ต์ AI ๊ธฐ์ ๊ณผ ๋ฒ๋ฅ ์ ๊ธฐ๋ฐํ์ฌ ์์ฌ์ ์ง์ ์ฌ์ฐ๊ถ์ ์ ๊ทน์ ์ผ๋ก ๋ณดํธํ๋ฉฐ,
๋ฌด๋จ ์ฌ์ฉ ๋ฐ ์นจํด ํ์์ ๋ํด ๋ฒ์ ๋์์ ํ ๊ถ๋ฆฌ๋ฅผ ๋ณด์ ํฉ๋๋ค.
ยฉ 2025 ์ฌ๋ฅ๋ท | All rights reserved.
๋๊ธ 0๊ฐ