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

Tomcat 보안과 운영 점검

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

2. 핵심 원리

2.1 기본 웹앱이 위험한 이유

설치 직후 webapps 에는 manager·host-manager·docs·examples·ROOT 다섯 개가 들어 있습니다. 앞의 넷은 운영 서비스에 필요 없고 관리 콘솔·문서·예제 코드가 공격 경로가 됩니다.

ROOT 는 지우지 않고 우리 서비스 페이지로 교체합니다. 기본 안내 페이지를 그대로 두면 서버가 아직 설정되지 않았다는 신호가 됩니다.

2.2 ErrorReportValve 와 정보 노출

ErrorReportValve 는 500 같은 오류가 났을 때 보여줄 화면을 담당합니다. 기본값은 스택 트레이스와 Tomcat 버전을 그대로 보여줍니다.

showReport="false", showServerInfo="false" 로 끄면 사용자에게는 간단한 오류만 보이고 내부 정보는 로그에만 남습니다.

2.3 Connector server 속성과 응답 헤더

Tomcat 은 기본적으로 응답 헤더 Server 에 정확한 버전 문자열을 넣습니다. Connector 의 server 속성에 다른 값을 채우면 그 값이 대신 나갑니다.

값을 비워도 되지만, 빈 값보다는 WebServer 처럼 의미 없는 이름을 넣어야 일부 클라이언트가 헤더 누락을 오류로 취급하는 문제를 피할 수 있습니다.

2.4 종료 포트 보호 방식 두 가지

Server 요소의 port·shutdown 속성이 종료 포트와 비밀 명령입니다. 기본값 shutdown="SHUTDOWN" 은 누구나 아는 값이라 그대로 두면 안 됩니다.

방식 설정 종료 방법
비밀 명령으로 보호 shutdown 값을 임의 문자열로 네트워크로 그 문자열을 보내야 종료
포트 자체를 끔 port="-1" kill -TERM 또는 systemctl stop 만 가능

포트를 완전히 끄면 네트워크로는 절대 종료할 수 없어 더 안전하지만, 그만큼 서버 접근 권한이 있어야만 종료할 수 있습니다.

2.5 conf·webapps 쓰기 권한 원칙

conf 폴더는 실행 중 절대 바뀌면 안 되므로 쓰기 권한을 모두 뺍니다(chmod a-w). logs·temp·work 는 실행 계정이 계속 써야 하므로 쓰기 권한을 남깁니다.

webapps 도 실행 계정이 쓸 수 있게 두면, 웹 애플리케이션 취약점으로 파일이 업로드될 때 그대로 war 로 배포될 위험이 생깁니다. 배포는 별도 계정으로만 하고 실행 계정은 읽기만 하게 막습니다.

2.6 실행 계정과 소유권 분리

배포 계정과 실행 계정(tomcat)을 나누면 애플리케이션이 뚫려도 피해가 그 프로세스 권한 안으로 제한됩니다. chown -R tomcat:tomcat 으로 소유권을 tomcat 계정에 주되, 쓰기 권한 자체는 2.5 의 원칙을 따릅니다.

로그인 불가 시스템 계정(레슨 01 의 useradd --system --shell /sbin/nologin)이라는 전제도 그대로 유지합니다.

2.7 세션 타임아웃과 쿠키 보안 속성

web.xml 의 session-config 에서 session-timeout(분 단위)으로 방치된 세션이 오래 살아있지 않게 합니다. cookie-config 의 http-only 는 자바스크립트로 쿠키를 읽지 못하게 막아 XSS 피해를 줄입니다.

secure 는 HTTPS 연결에서만 쿠키를 보내게 합니다. HTTP 로도 서비스한다면 이 값을 켜는 순간 HTTP 쪽 세션이 끊기므로 nginx HTTPS 전환(레슨 07)과 함께 적용해야 합니다.

context.xml 의 Context 요소에 useHttpOnly="true" 를 두면 기본값으로도 적용됩니다. CookieProcessor 의 sameSiteCookies="strict" 는 다른 사이트에서 걸어오는 요청에 쿠키를 안 실어 CSRF 위험을 줄입니다.

2.8 스레드 덤프 읽는 법

스레드 덤프는 그 순간 JVM 안의 모든 스레드가 무엇을 하고 있는지 찍은 사진입니다. 응답이 갑자기 느려졌을 때 jcmd <PID> Thread.print 로 뜬 다음, BLOCKED 상태 스레드가 많은지, 같은 락을 여럿이 기다리는지를 봅니다.

한 번만 뜨면 순간 상태만 보이므로, 느려지는 동안 몇 초 간격으로 두세 번 떠서 비교하면 원인을 좁히기 쉽습니다.

2.9 힙 덤프와 메모리 누수 확인

힙 덤프는 그 순간 힙에 들어있는 객체를 통째로 파일로 남깁니다. jcmd <PID> GC.heap_dump 파일 로 즉시 뜨거나, -XX:+HeapDumpOnOutOfMemoryError 로 OOM 이 날 때 자동으로 남게 미리 설정해 둡니다(레슨 03 의 setenv.sh 참조).

힙 덤프 파일은 수백 MB 에서 수 GB 까지 커질 수 있어 디스크 여유 공간을 먼저 확인하고, 분석 후에는 지워야 합니다.

2.10 점검 체크리스트 항목

배포 직후나 장애 대응 때 매번 같은 항목을 손으로 확인하면 빠뜨리기 쉽습니다. 스크립트로 만들어 한 번에 돌립니다.

항목 확인 방법
포트 ss -ltn 으로 LISTEN 여부
PID PID 파일과 실제 프로세스 존재
디스크 df -h 여유 공간
로그 크기 du -sh 로 급증 여부

2.11 업그레이드는 새 폴더 + 링크 전환

레슨 01 에서 본 것처럼 새 버전은 기존 폴더를 건드리지 않고 별도 폴더에 풀고 current 심볼릭 링크(symbolic link)만 돌립니다. 인스턴스 설정(tomcat-inst)은 버전과 분리돼 있어 그대로 유지됩니다.

전환 직후에는 점검 체크리스트로 포트·PID·응답을 확인해야 문제를 바로 발견합니다.

2.12 롤백은 링크만 되돌리면 끝

문제가 보이면 current 링크를 이전 버전 폴더로 다시 돌리고 재시작하면 됩니다. 파일을 다시 풀거나 설정을 복원할 필요가 없어 배포와 대칭인 절차입니다.

핵심 원리
  • 2.1 기본 웹앱이 위험한 이유
  • 2.2 ErrorReportValve 와 정보 노출
  • 2.3 Connector server 속성과 응답 헤더
  • 2.4 종료 포트 보호 방식 두 가지
  • 2.5 conf·webapps 쓰기 권한 원칙
  • 2.6 실행 계정과 소유권 분리
  • 2.7 세션 타임아웃과 쿠키 보안 속성
  • 2.8 스레드 덤프 읽는 법
  • 2.9 힙 덤프와 메모리 누수 확인
  • 2.10 점검 체크리스트 항목
  • 2.11 업그레이드는 새 폴더 + 링크 전환
  • 2.12 롤백은 링크만 되돌리면 끝
이전 섹션1 왜 배우는가2 / 7다음 섹션3 코드 예제