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

๐ 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๊ฐ ๋ฐ์ํ๋ ๊ฒฝ์ฐ:
# ๋ฉ๋ชจ๋ฆฌ ์ค์ ์กฐ์ (setenv.sh/bat) JAVA_OPTS="$JAVA_OPTS -Xms512m -Xmx1024m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=256m" # ํ ๋คํ ํ์ฑํ JAVA_OPTS="$JAVA_OPTS -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=$CATALINA_HOME/logs/heapdump.hprof"
3. ๊ถํ ๋ฌธ์
๋ก๊ทธ ํ์ผ์ด๋ ๋๋ ํ ๋ฆฌ์ ๋ํ ๊ถํ์ด ์๋ ๊ฒฝ์ฐ:
# ๊ถํ ํ์ธ ๋ฐ ์์ ls -la $CATALINA_HOME/logs sudo chown -R tomcat:tomcat $CATALINA_HOME sudo chmod -R 755 $CATALINA_HOME
๐ข ์ฑ๋ฅ ์ ํ ๋ฌธ์
1. ๋ฉ๋ชจ๋ฆฌ ๋์
๋ฉ๋ชจ๋ฆฌ ๋์๊ฐ ์์ฌ๋ ๋ ํ์ธํ ์ ์๋ ๋ฐฉ๋ฒ:
# JVM ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋ ๋ชจ๋ํฐ๋ง jstat -gcutil <PID> 1000 # ํ ๋คํ ์์ฑ ๋ฐ ๋ถ์ jmap -dump:format=b,file=heap.bin <PID> # ๊ทธ ํ Eclipse MAT ๊ฐ์ ๋๊ตฌ๋ก ๋ถ์
2. ๋๋ฆฐ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฟผ๋ฆฌ
๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฐ๊ฒฐ ํ ์ค์ ํ์ธ:
# context.xml์ JDBC ์ฐ๊ฒฐ ํ ์ค์
<Resource name="jdbc/myDB" auth="Container" type="javax.sql.DataSource"
maxTotal="100" maxIdle="30" maxWaitMillis="10000"
username="user" password="password" driverClassName="com.mysql.cj.jdbc.Driver"
url="jdbc:mysql://localhost:3306/mydb?useSSL=false&serverTimezone=UTC"/>
3. ์ค๋ ๋ ๋คํ ๋ถ์
์ค๋ ๋๊ฐ ์ด๋์ ๋ธ๋กํน๋๊ณ ์๋์ง ํ์ธ:
# ์ค๋ ๋ ๋คํ ์์ฑ jstack <PID> > thread_dump.txt # ์ฌ๋ฌ ๋ฒ ๋คํ๋ฅผ ์์ฑํด ๋น๊ต ๋ถ์ํ๋ฉด ๋ ํจ๊ณผ์
๐ ๋ก๊ทธ ๋ถ์ ๋ฐฉ๋ฒ
1. ์ฃผ์ ๋ก๊ทธ ํ์ผ
- catalina.out: ๋ฉ์ธ ๋ก๊ทธ ํ์ผ
- localhost.YYYY-MM-DD.log: ์ ํ๋ฆฌ์ผ์ด์ ๋ก๊ทธ
- localhost_access_log.YYYY-MM-DD.txt: ์ก์ธ์ค ๋ก๊ทธ
- host-manager.YYYY-MM-DD.log: ํธ์คํธ ๊ด๋ฆฌ์ ๋ก๊ทธ
- manager.YYYY-MM-DD.log: ์น ์ ํ๋ฆฌ์ผ์ด์ ๊ด๋ฆฌ์ ๋ก๊ทธ
2. ๋ก๊ทธ ๋ถ์ ๋๊ตฌ
๋๋์ ๋ก๊ทธ๋ฅผ ํจ์จ์ ์ผ๋ก ๋ถ์ํ๊ธฐ ์ํ ๋๊ตฌ:
# grep์ ์ฌ์ฉํ ๊ธฐ๋ณธ ๋ถ์ grep "Exception" catalina.out # ๋ก๊ทธ ํจํด ๋ถ์ grep -A 10 -B 2 "OutOfMemoryError" catalina.out # ELK Stack์ ์ฌ์ฉํ ๊ณ ๊ธ ๋ถ์ # Filebeat๋ก ๋ก๊ทธ ์์ง -> Elasticsearch๋ก ์ ์ฅ -> Kibana๋ก ์๊ฐํ
๐ ์ ํ๋ฆฌ์ผ์ด์ ๋ฐฐํฌ ๋ฌธ์
1. ClassNotFoundException
ํด๋์ค ๋ก๋ฉ ๋ฌธ์ ๊ฐ ๋ฐ์ํ ๋:
# ํด๋์คํจ์ค ํ์ธ ls -la $CATALINA_HOME/lib ls -la $CATALINA_HOME/webapps/myapp/WEB-INF/lib ls -la $CATALINA_HOME/webapps/myapp/WEB-INF/classes # ํด๋์ค๋ก๋ ๋๋ฒ๊น ํ์ฑํ JAVA_OPTS="$JAVA_OPTS -verbose:class"
2. ๋ฐฐํฌ ์คํจ
WAR ํ์ผ ๋ฐฐํฌ๊ฐ ์คํจํ ๋:
# WAR ํ์ผ ๋ด์ฉ ํ์ธ jar tvf myapp.war # ์์ ํ์ผ ์ ๋ฆฌ rm -rf $CATALINA_HOME/work/Catalina/localhost/myapp rm -rf $CATALINA_HOME/webapps/myapp rm -f $CATALINA_HOME/webapps/myapp.war
3. ์ปจํ ์คํธ ๋ก๋ฉ ์คํจ
web.xml ๋ฌธ๋ฒ ์ค๋ฅ ๋ฑ์ผ๋ก ์ปจํ ์คํธ ๋ก๋ฉ์ด ์คํจํ ๋:
# web.xml ์ ํจ์ฑ ๊ฒ์ฌ xmllint --noout --schema web-app_4_0.xsd web.xml # ์ปจํ ์คํธ ์ค์ ํ์ธ cat $CATALINA_HOME/conf/Catalina/localhost/myapp.xml
๐ ๋ณด์ ๋ฌธ์
1. ์ทจ์ฝ์ ์ค์บ
์ ๊ธฐ์ ์ธ ๋ณด์ ์ทจ์ฝ์ ์ค์บ์ ์ํํด:
# OWASP ZAP ์ฌ์ฉ ์์ zap-cli quick-scan --self-contained --start-options "-config api.disablekey=true" http://localhost:8080/myapp/
2. ๋ก๊ทธ์ธ ์คํจ ๋ชจ๋ํฐ๋ง
๋ฐ๋ณต์ ์ธ ๋ก๊ทธ์ธ ์คํจ๋ฅผ ๋ชจ๋ํฐ๋งํด ๋ฌด์ฐจ๋ณ ๋์ ๊ณต๊ฒฉ์ ํ์ง:
# ๋ก๊ทธ์ธ ์คํจ ๋ก๊ทธ ๋ถ์
grep "login failure" localhost_access_log.*.txt | awk '{print $1}' | sort | uniq -c | sort -nr
๋ฌธ์ ํด๊ฒฐ์ ํต์ฌ์ ์ฒด๊ณ์ ์ธ ์ ๊ทผ ๋ฐฉ์์ด์ผ. ์ฆ์์ ์ ํํ ํ์ ํ๊ณ , ๋ก๊ทธ๋ฅผ ๋ถ์ํ๊ณ , ๋จ๊ณ๋ณ๋ก ๋ฌธ์ ๋ฅผ ์ขํ๋๊ฐ๋ ๊ฒ์ด ์ค์ํด! ์ฌ๋ฅ๋ท ๊ฐ์ ์๋น์ค๋ฅผ ์ด์ํ๋ค๋ฉด, ๋ฌธ์ ๊ฐ ๋ฐ์ํ์ ๋ ๋น ๋ฅด๊ฒ ๋์ํ ์ ์๋ ๋ฅ๋ ฅ์ด ํ์์ ์ด์ง. ๐
๐ Tomcat์ ๋ฏธ๋์ ์ต์ ํธ๋ ๋ ๐
2025๋ ํ์ฌ Tomcat์ ์ด๋ป๊ฒ ๋ฐ์ ํ๊ณ ์๊ณ , ์์ผ๋ก ์ด๋ค ๋ฐฉํฅ์ผ๋ก ๋์๊ฐ๊น? ์ต์ ํธ๋ ๋์ ํจ๊ป ์์๋ณด์! ๐
๐ ๋ง์ดํฌ๋ก์๋น์ค ์ํคํ ์ฒ ์ง์
Tomcat์ ์ ํต์ ์ธ ๋ชจ๋๋ฆฌ์ ์ ํ๋ฆฌ์ผ์ด์ ๋ฟ๋ง ์๋๋ผ ๋ง์ดํฌ๋ก์๋น์ค ์ํคํ ์ฒ์์๋ ์ค์ํ ์ญํ ์ ํ๊ณ ์์ด:
- ๊ฒฝ๋ํ: Tomcat์ ๋ค๋ฅธ ์๋ธ๋ฆฟ ์ปจํ ์ด๋๋ณด๋ค ๊ฐ๋ณ๊ณ ๋น ๋ฅด๊ฒ ์์๋ผ
- Spring Boot ๋ด์ฅ ์๋ฒ: Spring Boot์ ๊ธฐ๋ณธ ๋ด์ฅ ์๋ฒ๋ก ์ฌ์ฉ๋ผ
- Docker ์ปจํ ์ด๋ํ: ๋ง์ดํฌ๋ก์๋น์ค๋ฅผ ์ํ ์ปจํ ์ด๋ ์ด๋ฏธ์ง์ ๊ธฐ๋ฐ์ผ๋ก ํ์ฉ๋ผ
2025๋ ์๋ Tomcat์ ๊ธฐ๋ฐ์ผ๋ก ํ ๋ง์ดํฌ๋ก์๋น์ค๊ฐ ๋์ฑ ์ผ๋ฐํ๋์์ด. ํนํ Spring Boot์ ํจ๊ป ์ฌ์ฉํ๋ฉด ๊ฐ๋ฐ ์์ฐ์ฑ์ด ํฌ๊ฒ ํฅ์๋ผ! ๐ฑ
โ๏ธ ํด๋ผ์ฐ๋ ๋ค์ดํฐ๋ธ ์ง์
Tomcat์ ํด๋ผ์ฐ๋ ํ๊ฒฝ์ ์ต์ ํ๋๊ณ ์์ด:
- Kubernetes ํตํฉ: K8s ํ๊ฒฝ์์ ์ฝ๊ฒ ๋ฐฐํฌํ๊ณ ๊ด๋ฆฌํ ์ ์์ด
- ์คํ ์ค์ผ์ผ๋ง: ํธ๋ํฝ์ ๋ฐ๋ผ ์๋์ผ๋ก ํ์ฅ/์ถ์ํ ์ ์์ด
- ํด๋ผ์ฐ๋ ์๋น์ค ์ฐ๋: AWS, Azure, GCP ๋ฑ์ ์๋น์ค์ ์ฝ๊ฒ ํตํฉ๋ผ
Kubernetes์์ Tomcat ๋ฐฐํฌ ์์ (deployment.yaml):
apiVersion: apps/v1
kind: Deployment
metadata:
name: tomcat-app
spec:
replicas: 3
selector:
matchLabels:
app: tomcat-app
template:
metadata:
labels:
app: tomcat-app
spec:
containers:
- name: tomcat
image: tomcat:10.1-jdk17
ports:
- containerPort: 8080
resources:
requests:
memory: "512Mi"
cpu: "500m"
limits:
memory: "1Gi"
cpu: "1000m"
readinessProbe:
httpGet:
path: /
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
livenessProbe:
httpGet:
path: /
port: 8080
initialDelaySeconds: 60
periodSeconds: 20
๐ ๋ณด์ ๊ฐํ
2025๋ ์๋ ๋ณด์์ด ๋์ฑ ์ค์ํด์ก์ด. Tomcat์ ๋ณด์ ๊ธฐ๋ฅ๋ ๊ณ์ ๊ฐํ๋๊ณ ์์ด:
- ์ต์ TLS ์ง์: TLS 1.3์ ๊ธฐ๋ณธ์ผ๋ก ์ง์ํด
- CSRF ๋ณดํธ: ๋ด์ฅ CSRF ๋ณดํธ ๊ธฐ๋ฅ์ด ํฅ์๋์์ด
- ์ปจํ ์ด๋ ๋ณด์: ์ปจํ ์ด๋ ํ๊ฒฝ์์์ ๋ณด์ ๊ฐํ
- ์ ๋ก ํธ๋ฌ์คํธ ์ํคํ ์ฒ: ๋ชจ๋ ์์ฒญ์ ๊ฒ์ฆํ๋ ๋ฐฉ์ ์ง์
โก ์ฑ๋ฅ ์ต์ ํ
Tomcat์ ๊ณ์ํด์ ์ฑ๋ฅ์ ๊ฐ์ ํ๊ณ ์์ด:
- HTTP/3 ์ง์: QUIC ํ๋กํ ์ฝ ๊ธฐ๋ฐ์ HTTP/3 ์ง์ ์ถ๊ฐ
- ๋น๋๊ธฐ I/O: ๋น๋๊ธฐ ์ฒ๋ฆฌ ๊ธฐ๋ฅ ๊ฐํ
- ๋ฉ๋ชจ๋ฆฌ ์ต์ ํ: ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋ ๊ฐ์ ๋ฐ GC ์ต์ ํ
- ์๋ฒ๋ฆฌ์ค ์ง์: ์๋ฒ๋ฆฌ์ค ํ๊ฒฝ์์์ ๋น ๋ฅธ ์์ ์๊ฐ ์ง์
2025๋ Tomcat์ HTTP/3๋ฅผ ์ง์ํ๋ฉด์ ์น ์ฑ๋ฅ์ด ํฌ๊ฒ ํฅ์๋์์ด. ํนํ ๋ชจ๋ฐ์ผ ํ๊ฒฝ์์ ๋คํธ์ํฌ ์ง์ฐ์ด ์ค์ด๋ค์์ง! ๐ฑ
๐ Jakarta EE ํตํฉ
Java EE์์ Jakarta EE๋ก์ ์ ํ์ด ์๋ฃ๋์์ด:
- Jakarta EE 10 ์ง์: ์ต์ Jakarta EE ์คํ ์๋ฒฝ ์ง์
- jakarta.* ๋ค์์คํ์ด์ค: javax.* ์์ jakarta.* ๋ก์ ์ ํ ์๋ฃ
- MicroProfile ํตํฉ: ๋ง์ดํฌ๋ก์๋น์ค๋ฅผ ์ํ MicroProfile ์ง์
๐ ๋์ฒด ๊ธฐ์ ๊ณผ์ ๋น๊ต
2025๋ ์๋ Tomcat์ ์ฌ์ ํ ๊ฐ๋ ฅํ์ง๋ง, ๋ค๋ฅธ ๋์๋ค๋ ์์ด:
- Jetty: ๋ ๊ฐ๋ณ๊ณ ์๋ฒ ๋๋ ์ฌ์ฉ์ ์ต์ ํ๋ ์๋ธ๋ฆฟ ์ปจํ ์ด๋
- Undertow: ๊ณ ์ฑ๋ฅ ์น ์๋ฒ๋ก WildFly์ ๊ธฐ๋ณธ ์๋ฒ
- Netty: ๋น๋๊ธฐ ์ด๋ฒคํธ ๊ธฐ๋ฐ ๋คํธ์ํฌ ์ ํ๋ฆฌ์ผ์ด์ ํ๋ ์์ํฌ
- Quarkus: Kubernetes ๋ค์ดํฐ๋ธ Java ์คํ์ผ๋ก ๋น ๋ฅธ ์์ ์๊ฐ ์ ๊ณต
- Spring Native: Spring ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ค์ดํฐ๋ธ ์ด๋ฏธ์ง๋ก ์ปดํ์ผ
๊ทธ๋ผ์๋ Tomcat์ ์์ ์ฑ, ์ปค๋ฎค๋ํฐ ์ง์, ํธํ์ฑ ์ธก๋ฉด์์ ์ฌ์ ํ ๊ฐ์ ์ ๊ฐ์ง๊ณ ์์ด. ํนํ ๊ธฐ์กด Java ์น ์ ํ๋ฆฌ์ผ์ด์ ์ ์ด์ํ๋ ๊ธฐ์ ๋ค์๊ฒ๋ ๊ณ์ํด์ ์ ๋ขฐํ ์ ์๋ ์ ํ์ด์ผ. ๐ข
์ฌ๋ฅ๋ท ๊ฐ์ ํ๋ซํผ์ ์ด์ํ๋ค๋ฉด, ์ด๋ฐ ์ต์ ํธ๋ ๋๋ฅผ ๋ฐ๋ผ๊ฐ๋ฉด์๋ ์์ ์ฑ์ ์ ์งํ๋ ๊ฒ์ด ์ค์ํด. Tomcat์ ๊ทธ ๊ท ํ์ ์ ๋ง์ถ๊ณ ์๋ ์๋ฒ์ผ! ๐
๐ ๋ง๋ฌด๋ฆฌ: Tomcat ๊ด๋ฆฌ์ ํต์ฌ ์์ฝ ๐
์ง๊ธ๊น์ง Apache Tomcat์ ์ค์น๋ถํฐ ๊ณ ๊ธ ๊ด๋ฆฌ ๊ธฐ๋ฒ๊น์ง ํจ๊ป ์์๋ดค์ด! ์ด์ ํต์ฌ ๋ด์ฉ์ ์์ฝํด๋ณผ๊ฒ. ๐ฏ
๐ Tomcat ๊ด๋ฆฌ์ ํต์ฌ ํฌ์ธํธ
- ์ต์ ๋ฒ์ ์ ์ง: ๋ณด์๊ณผ ์ฑ๋ฅ์ ์ํด ํญ์ ์ต์ ๋ฒ์ ์ ์ฌ์ฉํด
- ์ ์ ํ ๋ฉ๋ชจ๋ฆฌ ์ค์ : ์๋ฒ ํ๊ฒฝ์ ๋ง๋ JVM ๋ฉ๋ชจ๋ฆฌ ์ค์ ์ด ์ค์ํด
- ๋ณด์ ๊ฐํ: ๊ธฐ๋ณธ ์ค์ ์ ๋ณ๊ฒฝํ๊ณ , HTTPS๋ฅผ ์ฌ์ฉํ๊ณ , ๋ถํ์ํ ๊ธฐ๋ฅ์ ๋นํ์ฑํํด
- ๋ชจ๋ํฐ๋ง ์ค์ : ๋ฌธ์ ๋ฅผ ๋น ๋ฅด๊ฒ ๊ฐ์งํ๊ณ ํด๊ฒฐํ๊ธฐ ์ํ ๋ชจ๋ํฐ๋ง ์ฒด๊ณ๋ฅผ ๊ตฌ์ถํด
- ๋ก๊ทธ ๊ด๋ฆฌ: ๋ก๊ทธ ๋กํ ์ด์ ๊ณผ ๋ถ์ ์ฒด๊ณ๋ฅผ ๊ฐ์ถ์ด ๋ฌธ์ ํด๊ฒฐ์ ํ์ฉํด
- ์ฑ๋ฅ ์ต์ ํ: ์ปค๋ฅ์ ํ, ์ค๋ ๋ ์ค์ , ์์ถ ๋ฑ์ ํตํด ์ฑ๋ฅ์ ์ต์ ํํด
- ํด๋ฌ์คํฐ๋ง: ๊ณ ๊ฐ์ฉ์ฑ๊ณผ ํ์ฅ์ฑ์ ์ํด ํ์์ ํด๋ฌ์คํฐ๋ง์ ๊ตฌ์ฑํด
Tomcat ๊ด๋ฆฌ๋ ํ ๋ฒ์ ์์ฑ๋๋ ๊ฒ์ด ์๋๋ผ ์ง์์ ์ธ ๊ด์ฌ๊ณผ ๊ฐ์ ์ด ํ์ํ ๊ณผ์ ์ด์ผ! ์๋น์ค๊ฐ ์ฑ์ฅํ๋ฉด์ ์๊ตฌ์ฌํญ๋ ๋ณํ๋, ๊ณ์ํด์ ํ์ตํ๊ณ ์ต์ ํํ๋ ์์ธ๊ฐ ์ค์ํด. ๐ฑ
๐ ๋ ๊ณต๋ถํ๋ฉด ์ข์ ์๋ฃ
- ๊ณต์ ๋ฌธ์: Apache Tomcat ๊ณต์ ๋ฌธ์ (https://tomcat.apache.org/tomcat-10.1-doc/)
- ์ฑ : "Tomcat: The Definitive Guide" (O'Reilly)
- ์ปค๋ฎค๋ํฐ: Stack Overflow์ Tomcat ํ๊ทธ, Apache Tomcat ๋ฉ์ผ๋ง ๋ฆฌ์คํธ
- ๋ธ๋ก๊ทธ: Baeldung, DZone์ Java ์์ญ์์ Tomcat ๊ด๋ จ ๊ธ
Tomcat์ Java ์น ์ ํ๋ฆฌ์ผ์ด์ ์๋ฒ ์ค์์๋ ๊ฐ์ฅ ๋๋ฆฌ ์ฌ์ฉ๋๋ ์๋ฒ์ผ. ๊ทธ๋งํผ ์๋ฃ๋ ํ๋ถํ๊ณ ์ปค๋ฎค๋ํฐ๋ ํ๋ฐํด์ ๋ฌธ์ ๊ฐ ์๊ฒจ๋ ํด๊ฒฐ์ฑ ์ ์ฐพ๊ธฐ ์ฌ์. ํนํ ์ฌ๋ฅ๋ท ๊ฐ์ ํ๋ซํผ์ ์ด์ํ๋ค๋ฉด, ์ด๋ฐ ์์ ์ ์ธ ๊ธฐ์ ์คํ์ ์ ํํ๋ ๊ฒ์ด ์ค์ํ์ง! ๐
๐ ๋ง์ง๋ง์ผ๋ก...
Tomcat ๊ด๋ฆฌ๋ ์ฒ์์๋ ๋ณต์กํด ๋ณด์ผ ์ ์์ง๋ง, ๊ธฐ๋ณธ ๊ฐ๋ ์ ์ดํดํ๊ณ ์ฐจ๊ทผ์ฐจ๊ทผ ์ ๊ทผํ๋ฉด ์ถฉ๋ถํ ๋ง์คํฐํ ์ ์์ด! ์ด ๊ธ์ด ๋ค๊ฐ Tomcat์ ๋ ์ ์ดํดํ๊ณ ๊ด๋ฆฌํ๋ ๋ฐ ๋์์ด ๋์์ผ๋ฉด ์ข๊ฒ ์ด. ๐
ํน์ ๋ ๊ถ๊ธํ ์ ์ด ์๊ฑฐ๋ ํน์ ๋ฌธ์ ์ ๋ถ๋ชํ๋ค๋ฉด, ์ธ์ ๋ ์ง ์ฌ๋ฅ๋ท์ ๊ฐ๋ฐ์ ์ปค๋ฎค๋ํฐ์์ ์ง๋ฌธํด๋ด! ํจ๊ป ์ฑ์ฅํ๋ ๊ฐ๋ฐ์ ์ํ๊ณ๋ฅผ ๋ง๋ค์ด๊ฐ๋ ๊ฒ์ด ์ค์ํ๋๊น. ๐
Tomcat๊ณผ ํจ๊ปํ๋ ์ฆ๊ฑฐ์ด ์น ๊ฐ๋ฐ ์ฌํ์ด ๊ณ์๋๊ธธ ๋ฐ๋๊ฒ! ๋ค์์ ๋ ๋ค๋ฅธ ์ฃผ์ ๋ก ๋ง๋์! ๐
๊ด๋ จ ํค์๋
๋๊ธ ์์ฑ
์ด ๊ธ์ ๋ํ ์ฌ๋ฌ๋ถ์ ์๊ฐ์ ๋ค๋ ค์ฃผ์ธ์
๋ก๊ทธ์ธ์ด ํ์ํฉ๋๋ค
๋๊ธ์ ์์ฑํ๋ ค๋ฉด ๋จผ์ ๋ก๊ทธ์ธํด์ฃผ์ธ์.
๋๊ธ 0
์ง์์ธ์ ์ฒ - ์ง์ ์ฌ์ฐ๊ถ ๋ณดํธ ๊ณ ์ง
์ง์ ์ฌ์ฐ๊ถ ๋ณดํธ ๊ณ ์ง
- ์ ์๊ถ ๋ฐ ์์ ๊ถ: ๋ณธ ์ปจํ ์ธ ๋ ์ฌ๋ฅ๋ท์ ๋ ์ AI ๊ธฐ์ ๋ก ์์ฑ๋์์ผ๋ฉฐ, ๋ํ๋ฏผ๊ตญ ์ ์๊ถ๋ฒ ๋ฐ ๊ตญ์ ์ ์๊ถ ํ์ฝ์ ์ํด ๋ณดํธ๋ฉ๋๋ค.
- AI ์์ฑ ์ปจํ ์ธ ์ ๋ฒ์ ์ง์: ๋ณธ AI ์์ฑ ์ปจํ ์ธ ๋ ์ฌ๋ฅ๋ท์ ์ง์ ์ฐฝ์๋ฌผ๋ก ์ธ์ ๋๋ฉฐ, ๊ด๋ จ ๋ฒ๊ท์ ๋ฐ๋ผ ์ ์๊ถ ๋ณดํธ๋ฅผ ๋ฐ์ต๋๋ค.
- ์ฌ์ฉ ์ ํ: ์ฌ๋ฅ๋ท์ ๋ช ์์ ์๋ฉด ๋์ ์์ด ๋ณธ ์ปจํ ์ธ ๋ฅผ ๋ณต์ , ์์ , ๋ฐฐํฌ, ๋๋ ์์ ์ ์ผ๋ก ํ์ฉํ๋ ํ์๋ ์๊ฒฉํ ๊ธ์ง๋ฉ๋๋ค.
- ๋ฐ์ดํฐ ์์ง ๊ธ์ง: ๋ณธ ์ปจํ ์ธ ์ ๋ํ ๋ฌด๋จ ์คํฌ๋ํ, ํฌ๋กค๋ง, ๋ฐ ์๋ํ๋ ๋ฐ์ดํฐ ์์ง์ ๋ฒ์ ์ ์ฌ์ ๋์์ด ๋ฉ๋๋ค.
- AI ํ์ต ์ ํ: ์ฌ๋ฅ๋ท์ AI ์์ฑ ์ปจํ ์ธ ๋ฅผ ํ AI ๋ชจ๋ธ ํ์ต์ ๋ฌด๋จ ์ฌ์ฉํ๋ ํ์๋ ๊ธ์ง๋๋ฉฐ, ์ด๋ ์ง์ ์ฌ์ฐ๊ถ ์นจํด๋ก ๊ฐ์ฃผ๋ฉ๋๋ค.
์์ง ๋๊ธ์ด ์์ต๋๋ค.