공공부하자개발 · 영어 학습 노트
리눅스
웹 서버Tomcat · Nginx 설치와 설정0/8 완료
  • 01Tomcat 설치
  • 02Tomcat server.xml 설정
  • 03Tomcat 인스턴스와 JVM 옵션
  • 04Tomcat 보안과 운영 점검
  • 05nginx 설치
  • 06nginx 리버스 프록시
  • 07nginx HTTPS
  • 08nginx 로드밸런싱과 운영
사이트 소개개인정보처리방침연락처
© 2026 공부하자
홈 › 웹 서버 › 03 / 8

Tomcat 인스턴스와 JVM 옵션

섹션 7진행 0 / 8
1왜 배우는가2핵심 원리3코드 예제4응용 변형 예제5자주 하는 실수 (Tip)6연습 문제7정리‹ 이전다음 ›

3. 코드 예제

예제 1: 인스턴스 폴더 생성과 server.xml 포트 분리 — 01_tomcat_instance_jvm.sh 발췌

bash
make_dirs() {
    inst="$1"
    INST="$ROOT$BASE/tomcat-inst/$inst"
    mkdir -p "$INST"/{conf,temp,webapps,work} "$ROOT$BASE/logs/$inst"
    run ln -sfn "$BASE/logs/$inst" "$INST/logs"
    echo "  $inst: conf temp webapps work 생성, logs 는 $BASE/logs/$inst 로 링크"
}
make_dirs app1
make_dirs app2

make_server_xml() {
    inst="$1"; http="$2"; shutdown="$3"
    XML="$ROOT$BASE/tomcat-inst/$inst/conf/server.xml"
    cat > "$XML" <<EOF
<Server port="$shutdown" shutdown="SHUTDOWN">
  <Service name="Catalina">
    <Connector port="$http" protocol="HTTP/1.1" URIEncoding="UTF-8" />
    ...
  </Service>
</Server>
EOF
    validate "$XML"
}
make_server_xml app1 8080 8005
make_server_xml app2 8180 8105
text
== 1. 인스턴스 폴더 생성 (CATALINA_BASE 분리) ==
  [dry] ln -sfn /app/logs/app1 WORK/app/tomcat-inst/app1/logs
  app1: conf temp webapps work 생성, logs 는 /app/logs/app1 로 링크
  [dry] ln -sfn /app/logs/app2 WORK/app/tomcat-inst/app2/logs
  app2: conf temp webapps work 생성, logs 는 /app/logs/app2 로 링크
== 2. server.xml 포트 분리 ==
  XML 유효성 검사 통과: server.xml
  XML 유효성 검사 통과: server.xml

인스턴스 이름과 포트만 바꿔 함수를 두 번 호출해 app1·app2 를 만들었습니다. 두 server.xml 모두 XML 문법 검증을 통과했습니다.

예제 2: setenv.sh JVM 옵션 — 01_tomcat_instance_jvm.sh 발췌

bash
make_setenv() {
    inst="$1"; xmx="$2"
    SETENV="$ROOT$BASE/tomcat-inst/$inst/bin/setenv.sh"
    mkdir -p "$(dirname "$SETENV")"
    cat > "$SETENV" <<EOF
export JAVA_HOME="$BASE/jdk"
export CATALINA_PID="$BASE/tomcat-inst/$inst/temp/catalina.pid"
JAVA_OPTS="-Xms$xmx -Xmx$xmx -XX:+UseG1GC"
JAVA_OPTS="\$JAVA_OPTS -Duser.timezone=Asia/Seoul -Dfile.encoding=UTF-8"
JAVA_OPTS="\$JAVA_OPTS -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=$BASE/logs/$inst"
export JAVA_OPTS
EOF
    bash -n "$SETENV" && echo "  $inst/setenv.sh 문법 확인: 이상 없음, Xmx=$xmx"
}
make_setenv app1 512m
make_setenv app2 256m
text
== 3. setenv.sh JVM 옵션 ==
  app1/setenv.sh 문법 확인: 이상 없음, Xmx=512m
  app2/setenv.sh 문법 확인: 이상 없음, Xmx=256m

같은 함수로 인스턴스마다 힙 크기(Xmx)만 다르게 줬습니다. bash -n 으로 문법만 검사하고 실제 실행은 하지 않습니다.

예제 3: context.xml JNDI DataSource — 01_tomcat_instance_jvm.sh 발췌

bash
CTX="$ROOT$BASE/tomcat-inst/app1/conf/context.xml"
cat > "$CTX" <<EOF
<Context>
  <Resource name="jdbc/AppDB" auth="Container" type="javax.sql.DataSource"
    driverClassName="org.postgresql.Driver"
    url="jdbc:postgresql://db.internal:5432/app"
    username="app" password="\${db.password}"
    initialSize="5" maxTotal="20" maxIdle="10" />
</Context>
EOF
validate "$CTX"
echo "  드라이버 jar 위치: $BASE/tomcat-inst/app1/lib (인스턴스 전용)"
text
== 4. context.xml JNDI DataSource ==
  XML 유효성 검사 통과: context.xml
  드라이버 jar 위치: /app/tomcat-inst/app1/lib (인스턴스 전용, CATALINA_HOME/lib 과 별도)

password 값은 개념을 보여주는 자리 표시(${db.password})이고, 실제 운영에서는 평문으로 커밋하지 않습니다. 드라이버 jar 는 이 인스턴스의 lib 폴더에만 둡니다.

예제 4: systemd 템플릿 유닛과 기동 확인 — 01_tomcat_instance_jvm.sh 발췌

bash
UNIT="$UNITDIR/[email protected]"
cat > "$UNIT" <<EOF
[Service]
Type=forking
Environment=CATALINA_BASE=$BASE/tomcat-inst/%i
Environment=CATALINA_PID=$BASE/tomcat-inst/%i/temp/catalina.pid
PIDFile=$BASE/tomcat-inst/%i/temp/catalina.pid
ExecStart=$BASE/tomcat/current/bin/startup.sh
ExecStop=$BASE/tomcat/current/bin/shutdown.sh
EOF
run systemctl daemon-reload
run systemctl enable --now tomcat@app1
run systemctl enable --now tomcat@app2
run curl -s -o /dev/null -w '%{http_code}\n' "http://localhost:8080/"
run curl -s -o /dev/null -w '%{http_code}\n' "http://localhost:8180/"
text
== 5. systemd 템플릿 유닛 [email protected] ==
  [email protected] 필수 키 확인: 이상 없음 (%i 는 인스턴스 이름으로 치환)
  [dry] systemctl daemon-reload
== 6. 인스턴스 기동과 확인 ==
  [dry] systemctl enable --now tomcat@app1
  [dry] systemctl enable --now tomcat@app2
  app1 확인:
  [dry] curl -s -o /dev/null -w %{http_code}\n http://localhost:8080/
  app2 확인:
  [dry] curl -s -o /dev/null -w %{http_code}\n http://localhost:8180/
  로그 위치: /app/logs/app1/catalina.out, /app/logs/app2/catalina.out

%i 하나로 app1·app2 를 같은 유닛 정의로 기동합니다. 실제 서버에서는 curl 이 진짜 상태 코드를 돌려줍니다.

예제 직접 실행

아래 폴더의 셸 스크립트를 RHEL 또는 Git Bash 에서 실행합니다. 리눅스 전용 명령은 DRY_RUN=1 을 붙이면 실행하지 않고 명령만 출력합니다.

cd web-src/03_tomcat_instance_jvm
ls *.sh
DRY_RUN=1 bash <스크립트>.sh
코드 예제
  • 예제 1: 인스턴스 폴더 생성과 server.xml 포트 분리 — 01_tomcat_instance_jvm.sh 발췌
  • 예제 2: setenv.sh JVM 옵션 — 01_tomcat_instance_jvm.sh 발췌
  • 예제 3: context.xml JNDI DataSource — 01_tomcat_instance_jvm.sh 발췌
  • 예제 4: systemd 템플릿 유닛과 기동 확인 — 01_tomcat_instance_jvm.sh 발췌
이전 섹션2 핵심 원리3 / 7다음 섹션4 응용 변형 예제