๐Ÿš€ Apache Tomcat: ๋„ˆ์™€ ํ•จ๊ป˜ํ•˜๋Š” Java ์›น ์„œ๋ฒ„ ์—ฌํ–‰ ๐Ÿš€

์ฝ˜ํ…์ธ  ๋Œ€ํ‘œ ์ด๋ฏธ์ง€ - ๐Ÿš€ Apache Tomcat: ๋„ˆ์™€ ํ•จ๊ป˜ํ•˜๋Š” Java ์›น ์„œ๋ฒ„ ์—ฌํ–‰ ๐Ÿš€

 

 

2025๋…„ 2์›” ๊ธฐ์ค€ ์ตœ์‹  ์ •๋ณด๋กœ ์•Œ์•„๋ณด๋Š” Tomcat ๊ด€๋ฆฌ์˜ ๋ชจ๋“  ๊ฒƒ!

๐ŸŒŸ ์•ˆ๋…•, ํ†ฐ์บฃ ์นœ๊ตฌ๋“ค! ๐ŸŒŸ

์•ผํ˜ธ! ์˜ค๋Š˜์€ Java ์›น ๊ฐœ๋ฐœ์ž๋ผ๋ฉด ํ•œ ๋ฒˆ์ฏค ๋งŒ๋‚˜๊ฒŒ ๋˜๋Š” Apache Tomcat์— ๋Œ€ํ•ด ํ•จ๊ป˜ ์•Œ์•„๋ณผ ๊ฑฐ์•ผ. ์„œ๋ฒ„ ๊ด€๋ฆฌ๊ฐ€ ์–ด๋ ต๊ฒŒ ๋Š๊ปด์ง„๋‹ค๊ณ ? ๊ฑฑ์ • ๋งˆ! ์ด ๊ธ€์„ ๋‹ค ์ฝ๊ณ  ๋‚˜๋ฉด ํ†ฐ์บฃ์„ ๋‚ด ๋ง˜๋Œ€๋กœ ๋‹ค๋ฃฐ ์ˆ˜ ์žˆ์„ ๊ฑฐ์•ผ. ๐Ÿ˜Ž

์š”์ฆ˜ ์žฌ๋Šฅ๋„ท ๊ฐ™์€ ์›น ํ”Œ๋žซํผ๋“ค์ด ๋Š˜์–ด๋‚˜๋ฉด์„œ ์•ˆ์ •์ ์ธ ์„œ๋ฒ„ ์šด์˜์ด ๋” ์ค‘์š”ํ•ด์กŒ์–ด. ํŠนํžˆ Java ๊ธฐ๋ฐ˜ ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์šด์˜ํ•œ๋‹ค๋ฉด Tomcat์€ ํ•„์ˆ˜ ์ง€์‹์ด์ง€! ๊ทธ๋Ÿผ ์ง€๊ธˆ๋ถ€ํ„ฐ Tomcat์˜ ์„ธ๊ณ„๋กœ ํ•จ๊ป˜ ๋– ๋‚˜๋ณผ๊นŒ? ๐Ÿšข

Apache Tomcat Java ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์„œ๋ฒ„ ์„œ๋ธ”๋ฆฟ JSP

๐Ÿ“š Tomcat์ด ๋ญ๊ธธ๋ž˜? ๊ธฐ๋ณธ ๊ฐœ๋… ์žก๊ธฐ ๐Ÿ“š

Apache Tomcat์€ Java ์„œ๋ธ”๋ฆฟ๊ณผ JSP ๊ธฐ์ˆ ์„ ์ง€์›ํ•˜๋Š” ์˜คํ”ˆ์†Œ์Šค ์›น ์„œ๋ฒ„์ด์ž ์„œ๋ธ”๋ฆฟ ์ปจํ…Œ์ด๋„ˆ์•ผ. 2025๋…„ 2์›” ํ˜„์žฌ Tomcat 10.1.x ๋ฒ„์ „์ด ์•ˆ์ •ํ™” ๋ฒ„์ „์œผ๋กœ ์‚ฌ์šฉ๋˜๊ณ  ์žˆ๊ณ , Tomcat 11๋„ ๊ฐœ๋ฐœ ์ค‘์ด๋ž˜. ๐Ÿ†•

๊ทผ๋ฐ ์„œ๋ธ”๋ฆฟ ์ปจํ…Œ์ด๋„ˆ๊ฐ€ ๋ญ๋ƒ๊ณ ? ๊ฐ„๋‹จํžˆ ๋งํ•˜๋ฉด Java๋กœ ์ž‘์„ฑ๋œ ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•˜๊ณ  ๊ด€๋ฆฌํ•ด์ฃผ๋Š” ํ™˜๊ฒฝ์ด์•ผ. ๋„ค๊ฐ€ ์ž‘์„ฑํ•œ Java ์ฝ”๋“œ๊ฐ€ ์›น์—์„œ ๋™์ž‘ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๋Š” ๋งˆ๋ฒ•์‚ฌ ๊ฐ™์€ ์กด์žฌ์ง€! โœจ

๐Ÿงฉ Tomcat์˜ ์ฃผ์š” ๊ตฌ์„ฑ ์š”์†Œ

  1. Catalina: ์„œ๋ธ”๋ฆฟ ์ปจํ…Œ์ด๋„ˆ ๋ถ€๋ถ„์œผ๋กœ Tomcat์˜ ํ•ต์‹ฌ์ด์•ผ
  2. Coyote: HTTP ์ปค๋„ฅํ„ฐ๋กœ ์›น ์š”์ฒญ์„ ๋ฐ›์•„ ์ฒ˜๋ฆฌํ•ด
  3. Jasper: JSP ์—”์ง„์œผ๋กœ JSP ํŒŒ์ผ์„ ์„œ๋ธ”๋ฆฟ์œผ๋กœ ๋ณ€ํ™˜ํ•ด์ค˜
  4. Cluster: ์—ฌ๋Ÿฌ Tomcat ์ธ์Šคํ„ด์Šค๋ฅผ ํด๋Ÿฌ์Šคํ„ฐ๋งํ•  ๋•Œ ์‚ฌ์šฉํ•ด
  5. 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 7 ์ง€์› ์ข…๋ฃŒ Java EE 6 Tomcat 8.5 ์œ ์ง€๋ณด์ˆ˜ Java EE 7 Tomcat 9 ์•ˆ์ •ํ™” Java EE 8 Tomcat 10 ์ตœ์‹  ์•ˆ์ •ํ™” Jakarta EE 9 Tomcat 11 ๊ฐœ๋ฐœ ์ค‘ Jakarta EE 11 ์‹œ๊ฐ„ ํ๋ฆ„ ๋ฐ ๊ธฐ๋Šฅ ํ–ฅ์ƒ 2025๋…„ 2์›” ๊ธฐ์ค€

โš™๏ธ Tomcat ์„ค์น˜ ๋ฐ ๊ธฐ๋ณธ ์„ค์ • โš™๏ธ

์ด์ œ Tomcat์„ ์„ค์น˜ํ•˜๊ณ  ๊ธฐ๋ณธ ์„ค์ •์„ ํ•ด๋ณผ๊นŒ? ์šด์˜์ฒด์ œ๋ณ„๋กœ ์„ค์น˜ ๋ฐฉ๋ฒ•์ด ์กฐ๊ธˆ์”ฉ ๋‹ค๋ฅด๋‹ˆ ๋„ค๊ฐ€ ์‚ฌ์šฉํ•˜๋Š” ํ™˜๊ฒฝ์— ๋งž๊ฒŒ ๋”ฐ๋ผ์™€! ๐Ÿ› ๏ธ

๐ŸชŸ Windows์— ์„ค์น˜ํ•˜๊ธฐ

  1. Apache Tomcat ๊ณต์‹ ์›น์‚ฌ์ดํŠธ(https://tomcat.apache.org)์—์„œ ์ตœ์‹  ๋ฒ„์ „์˜ Windows ์ธ์Šคํ†จ๋Ÿฌ(.exe) ๋‹ค์šด๋กœ๋“œ
  2. ๋‹ค์šด๋กœ๋“œํ•œ ์ธ์Šคํ†จ๋Ÿฌ ์‹คํ–‰ ํ›„ ์„ค์น˜ ๋งˆ๋ฒ•์‚ฌ ๋”ฐ๋ผ๊ฐ€๊ธฐ
  3. ๊ด€๋ฆฌ์ž ๊ณ„์ • ์„ค์ • ์‹œ username๊ณผ password ๊ธฐ์–ตํ•ด๋‘๊ธฐ
  4. ์„ค์น˜ ์™„๋ฃŒ ํ›„ 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 ์›ฐ์ปด ํŽ˜์ด์ง€๊ฐ€ ๋ณด์ธ๋‹ค๋ฉด ์„ฑ๊ณต์ด์•ผ! ๐ŸŽ‰

๋งŒ์•ฝ ํŽ˜์ด์ง€๊ฐ€ ๋ณด์ด์ง€ ์•Š๋Š”๋‹ค๋ฉด:

  1. Tomcat ์„œ๋น„์Šค๊ฐ€ ์‹คํ–‰ ์ค‘์ธ์ง€ ํ™•์ธ
  2. ๋ฐฉํ™”๋ฒฝ์ด 8080 ํฌํŠธ๋ฅผ ์ฐจ๋‹จํ•˜๊ณ  ์žˆ๋Š”์ง€ ํ™•์ธ
  3. ๋กœ๊ทธ ํŒŒ์ผ(/logs/catalina.out)์„ ํ™•์ธํ•ด์„œ ์˜ค๋ฅ˜ ๋ฉ”์‹œ์ง€ ํ™•์ธ

๐Ÿ“ Tomcat ๋””๋ ‰ํ† ๋ฆฌ ๊ตฌ์กฐ ์ดํ•ดํ•˜๊ธฐ ๐Ÿ“

Tomcat์„ ์ œ๋Œ€๋กœ ๊ด€๋ฆฌํ•˜๋ ค๋ฉด ๋””๋ ‰ํ† ๋ฆฌ ๊ตฌ์กฐ๋ฅผ ์ดํ•ดํ•˜๋Š” ๊ฒŒ ์ค‘์š”ํ•ด! ๊ฐ ํด๋”๊ฐ€ ์–ด๋–ค ์—ญํ• ์„ ํ•˜๋Š”์ง€ ์•Œ์•„๋ณด์ž. ๐Ÿ—‚๏ธ

๐Ÿ“‚ bin

Tomcat์„ ์‹œ์ž‘ํ•˜๊ณ  ์ค‘์ง€ํ•˜๋Š” ์Šคํฌ๋ฆฝํŠธ๊ฐ€ ์žˆ๋Š” ํด๋”์•ผ. startup.sh(bat), shutdown.sh(bat) ๊ฐ™์€ ์‹คํ–‰ ํŒŒ์ผ๋“ค์ด ์—ฌ๊ธฐ ์žˆ์–ด.

Windows์—์„œ๋Š” .bat ํŒŒ์ผ, Linux/macOS์—์„œ๋Š” .sh ํŒŒ์ผ์„ ์‚ฌ์šฉํ•ด!

๐Ÿ“‚ conf

Tomcat์˜ ์„ค์ • ํŒŒ์ผ๋“ค์ด ์žˆ๋Š” ํด๋”์•ผ. ๊ฐ€์žฅ ์ค‘์š”ํ•œ ํŒŒ์ผ์€ server.xml์ด์•ผ. ์ด ํŒŒ์ผ์—์„œ ํฌํŠธ, ์ปค๋„ฅํ„ฐ, ํ˜ธ์ŠคํŠธ ๋“ฑ์„ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์–ด.

์ฃผ์š” ์„ค์ • ํŒŒ์ผ๋“ค:

  1. server.xml: ๋ฉ”์ธ ์„ค์ • ํŒŒ์ผ
  2. web.xml: ๊ธฐ๋ณธ ์„œ๋ธ”๋ฆฟ ์„ค์ •
  3. tomcat-users.xml: ์‚ฌ์šฉ์ž ๊ณ„์ •๊ณผ ์—ญํ•  ์ •์˜
  4. context.xml: ๋ชจ๋“  ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ์ ์šฉ๋˜๋Š” Context ์„ค์ •

๐Ÿ“‚ lib

Tomcat์ด ์‚ฌ์šฉํ•˜๋Š” JAR ํŒŒ์ผ๋“ค์ด ์žˆ๋Š” ํด๋”์•ผ. ๋ชจ๋“  ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ๊ณตํ†ต์œผ๋กœ ์‚ฌ์šฉํ•  ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์—ฌ๊ธฐ์— ๋„ฃ์„ ์ˆ˜ ์žˆ์–ด.

๐Ÿ“‚ logs

Tomcat์˜ ๋กœ๊ทธ ํŒŒ์ผ๋“ค์ด ์ €์žฅ๋˜๋Š” ํด๋”์•ผ. ๋ฌธ์ œ๊ฐ€ ์ƒ๊ฒผ์„ ๋•Œ ๊ฐ€์žฅ ๋จผ์ € ํ™•์ธํ•ด์•ผ ํ•  ๊ณณ์ด์ง€!

์ฃผ์š” ๋กœ๊ทธ ํŒŒ์ผ:

  1. catalina.out: ๋ฉ”์ธ ๋กœ๊ทธ ํŒŒ์ผ
  2. localhost_access_log.YYYY-MM-DD.txt: ์•ก์„ธ์Šค ๋กœ๊ทธ
  3. localhost.YYYY-MM-DD.log: ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋กœ๊ทธ

๐Ÿ“‚ webapps

์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋ฐฐํฌํ•˜๋Š” ๊ธฐ๋ณธ ํด๋”์•ผ. WAR ํŒŒ์ผ์ด๋‚˜ ๋””๋ ‰ํ† ๋ฆฌ๋ฅผ ์ด ํด๋”์— ๋„ฃ์œผ๋ฉด ์ž๋™์œผ๋กœ ๋ฐฐํฌ๋ผ.

๊ธฐ๋ณธ์ ์œผ๋กœ ๋‹ค์Œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜๋“ค์ด ํฌํ•จ๋˜์–ด ์žˆ์–ด:

  1. ROOT: ๊ธฐ๋ณธ ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ (http://localhost:8080/ ๋กœ ์ ‘๊ทผ)
  2. examples: ์˜ˆ์ œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜
  3. manager: ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๊ด€๋ฆฌ ๋„๊ตฌ
  4. host-manager: ๊ฐ€์ƒ ํ˜ธ์ŠคํŠธ ๊ด€๋ฆฌ ๋„๊ตฌ

๐Ÿ“‚ work

Tomcat์ด JSP ํŒŒ์ผ์„ ์„œ๋ธ”๋ฆฟ์œผ๋กœ ๋ณ€ํ™˜ํ•œ ์ฝ”๋“œ๊ฐ€ ์ €์žฅ๋˜๋Š” ํด๋”์•ผ. ์ž„์‹œ ์ž‘์—… ๋””๋ ‰ํ† ๋ฆฌ๋กœ ์ƒ๊ฐํ•˜๋ฉด ๋ผ.

๐Ÿ“‚ temp

Tomcat์ด ์‚ฌ์šฉํ•˜๋Š” ์ž„์‹œ ํŒŒ์ผ๋“ค์ด ์ €์žฅ๋˜๋Š” ํด๋”์•ผ.

์ด ๋””๋ ‰ํ† ๋ฆฌ ๊ตฌ์กฐ๋ฅผ ์ž˜ ์ดํ•ดํ•˜๋ฉด Tomcat ๊ด€๋ฆฌ๊ฐ€ ํ›จ์”ฌ ์‰ฌ์›Œ์งˆ ๊ฑฐ์•ผ! ํŠนํžˆ ๋ฌธ์ œ ํ•ด๊ฒฐํ•  ๋•Œ logs ํด๋”๋ฅผ ์ž์ฃผ ๋“ค์—ฌ๋‹ค๋ณด๊ฒŒ ๋  ๊ฑฐ์•ผ. ๐Ÿ˜‰

TOMCAT_HOME bin conf lib logs webapps work/temp ROOT manager examples host-manager ๋‚ด ์•ฑ 1 ๋‚ด ์•ฑ 2 server.xml web.xml context.xml tomcat-users.xml Tomcat ๋””๋ ‰ํ† ๋ฆฌ ๊ตฌ์กฐ

๐Ÿ”ง 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๋กœ ์‰ฝ๊ฒŒ ๋ฐฐํฌํ•  ์ˆ˜ ์žˆ์–ด:

  1. ๋ธŒ๋ผ์šฐ์ €์—์„œ http://localhost:8080/manager/html ์ ‘์†
  2. ๊ด€๋ฆฌ์ž ๊ณ„์ •์œผ๋กœ ๋กœ๊ทธ์ธ
  3. '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

๋กœ๊ทธ ๋ ˆ๋ฒจ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ˆœ์„œ๋กœ ์ƒ์„ธ๋„๊ฐ€ ๋†’์•„์ ธ:

  1. SEVERE: ์‹ฌ๊ฐํ•œ ์˜ค๋ฅ˜
  2. WARNING: ๊ฒฝ๊ณ 
  3. INFO: ์ •๋ณด์„ฑ ๋ฉ”์‹œ์ง€ (๊ธฐ๋ณธ๊ฐ’)
  4. CONFIG: ์„ค์ • ๊ด€๋ จ ๋ฉ”์‹œ์ง€
  5. FINE: ์ƒ์„ธ ์ •๋ณด
  6. FINER: ๋” ์ƒ์„ธํ•œ ์ •๋ณด
  7. 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์„ ์—ฐ๋™ํ•˜๋Š” ๊ฒƒ์ด ์ผ๋ฐ˜์ ์ด์•ผ:

  1. Prometheus + Grafana: ๋ฉ”ํŠธ๋ฆญ ์ˆ˜์ง‘ ๋ฐ ์‹œ๊ฐํ™”
  2. ELK Stack: ๋กœ๊ทธ ์ˆ˜์ง‘, ๊ฒ€์ƒ‰, ๋ถ„์„
  3. New Relic / Datadog: APM(Application Performance Monitoring)
  4. 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 ์„œ๋ฒ„ JMX ๋ชจ๋‹ˆํ„ฐ๋ง ๋กœ๊ทธ ๋ถ„์„ ์„ฑ๋Šฅ ๋ฉ”ํŠธ๋ฆญ ์•Œ๋ฆผ ์‹œ์Šคํ…œ JConsole VisualVM ELK Stack Prometheus Grafana Slack Email Tomcat ๋ชจ๋‹ˆํ„ฐ๋ง ์—์ฝ”์‹œ์Šคํ…œ

๐Ÿ”’ ๋ณด์•ˆ ๊ฐ•ํ™” ์ „๋žต ๐Ÿ”’

์›น ์„œ๋ฒ„๋Š” ํ•ญ์ƒ ๋ณด์•ˆ ๊ณต๊ฒฉ์˜ ํ‘œ์ ์ด ๋˜๊ธฐ ์‰ฌ์›Œ. ํŠนํžˆ Tomcat์€ ๋„๋ฆฌ ์‚ฌ์šฉ๋˜๋Š” ์„œ๋ฒ„์ด๊ธฐ ๋•Œ๋ฌธ์— ๋” ๋งŽ์€ ๊ณต๊ฒฉ์„ ๋ฐ›์„ ์ˆ˜ ์žˆ์–ด. 2025๋…„ ๊ธฐ์ค€์œผ๋กœ Tomcat์˜ ๋ณด์•ˆ์„ ๊ฐ•ํ™”ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ์•„๋ณด์ž! ๐Ÿ›ก๏ธ

๐Ÿ” ๊ธฐ๋ณธ ๋ณด์•ˆ ์„ค์ •

  1. ์ตœ์‹  ๋ฒ„์ „ ์œ ์ง€: ํ•ญ์ƒ ์ตœ์‹  ๋ณด์•ˆ ํŒจ์น˜๊ฐ€ ์ ์šฉ๋œ Tomcat ๋ฒ„์ „์„ ์‚ฌ์šฉํ•ด
  2. ๋ถˆํ•„์š”ํ•œ ๊ธฐ๋Šฅ ๋น„ํ™œ์„ฑํ™”: ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ๊ธฐ๋Šฅ์€ ๋ชจ๋‘ ๋น„ํ™œ์„ฑํ™”ํ•ด
  3. ๊ธฐ๋ณธ ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ œ๊ฑฐ: ์˜ˆ์ œ, ๋ฌธ์„œ ๋“ฑ ๋ถˆํ•„์š”ํ•œ ์›น ์•ฑ์€ ์ œ๊ฑฐํ•ด
  4. 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 ํด๋Ÿฌ์Šคํ„ฐ๋ง ์•„ํ‚คํ…์ฒ˜๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์•„:

  1. ํด๋ผ์ด์–ธํŠธ: ์›น ๋ธŒ๋ผ์šฐ์ €๋‚˜ ๋ชจ๋ฐ”์ผ ์•ฑ
  2. ๋กœ๋“œ ๋ฐธ๋Ÿฐ์„œ: Nginx, HAProxy, AWS ELB ๋“ฑ
  3. Tomcat ์„œ๋ฒ„ ํด๋Ÿฌ์Šคํ„ฐ: ์—ฌ๋Ÿฌ Tomcat ์ธ์Šคํ„ด์Šค
  4. ๊ณต์œ  ์ €์žฅ์†Œ: ์„ธ์…˜ ๋ฐ์ดํ„ฐ, ํŒŒ์ผ ๋“ฑ์„ ์ €์žฅ
  5. ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค: 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 ์„œ๋ฒ„๊ฐ€ ๊ฐ™์€ ํŒŒ์ผ์— ์ ‘๊ทผํ•ด์•ผ ํ•œ๋‹ค๋ฉด ๊ณต์œ  ํŒŒ์ผ ์‹œ์Šคํ…œ์„ ์„ค์ •ํ•ด์•ผ ํ•ด:

  1. NFS: ๋ฆฌ๋ˆ…์Šค ํ™˜๊ฒฝ์—์„œ ๋„๋ฆฌ ์‚ฌ์šฉ๋˜๋Š” ๋„คํŠธ์›Œํฌ ํŒŒ์ผ ์‹œ์Šคํ…œ
  2. S3/EFS: AWS ํ™˜๊ฒฝ์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ํด๋ผ์šฐ๋“œ ์Šคํ† ๋ฆฌ์ง€
  3. 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
                '''
            }
        }
    }
}

ํด๋Ÿฌ์Šคํ„ฐ๋ง์€ ๊ฐ€์šฉ์„ฑ๊ณผ ํ™•์žฅ์„ฑ์„ ๋†’์ด์ง€๋งŒ, ๋ณต์žก์„ฑ๋„ ์ฆ๊ฐ€ํ•ด. ์ฒ ์ €ํ•œ ํ…Œ์ŠคํŠธ์™€ ๋ชจ๋‹ˆํ„ฐ๋ง์ด ํ•„์ˆ˜์•ผ! ํŠนํžˆ ์žฌ๋Šฅ๋„ท ๊ฐ™์€ ์„œ๋น„์Šค๊ฐ€ ์„ฑ์žฅํ•˜๋ฉด์„œ ํŠธ๋ž˜ํ”ฝ์ด ์ฆ๊ฐ€ํ•œ๋‹ค๋ฉด, ํด๋Ÿฌ์Šคํ„ฐ๋ง์€ ํ•„์ˆ˜์ ์ธ ์„ ํƒ์ด ๋  ๊ฑฐ์•ผ. ๐Ÿš€

ํด๋ผ์ด์–ธํŠธ ๋กœ๋“œ ๋ฐธ๋Ÿฐ์„œ (Nginx/HAProxy) Tomcat ์„œ๋ฒ„ 1 Tomcat ์„œ๋ฒ„ 2 Tomcat ์„œ๋ฒ„ 3 Redis ์„ธ์…˜ ์ €์žฅ์†Œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๊ณต์œ  ํŒŒ์ผ ์‹œ์Šคํ…œ Tomcat ํด๋Ÿฌ์Šคํ„ฐ๋ง ์•„ํ‚คํ…์ฒ˜

๐Ÿ” ๋ฌธ์ œ ํ•ด๊ฒฐ ๋ฐ ๋””๋ฒ„๊น… ๊ฐ€์ด๋“œ ๐Ÿ”

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๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ๊ฒฝ์šฐ: