자바 애플리케이션 배포
5. 자주 하는 실수 (Tip)
❌ 실수 1: -Xmx 를 지정하지 않는다
JVM 기본값은 물리 메모리의 1/4 이라 큰 서버에서도 힙이 작습니다. 반대로 작은 서버에서 여러 앱을 띄우면 합계가 RAM 을 넘어 OOM killer 에 죽습니다. ✅ -Xms 와 -Xmx 를 항상 명시하고 같은 값으로 둡니다.
❌ 실수 2: $JAVA_OPTS 를 큰따옴표로 감싼다
java "$JAVA_OPTS" -jar app.jar 는 옵션 전체가 인자 하나가 되어 Unrecognized option 으로 실패합니다. ✅ 변수 확장 시 단어 분리가 필요하므로 따옴표 없이 씁니다. 공백이 든 값이 필요하면 배열을 씁니다.
java $JAVA_OPTS -jar app.jar # 옵션이 각각 분리됨
OPTS=(-Xmx1g "-Dname=with space"); java "${OPTS[@]}" -jar app.jar❌ 실수 3: jar 를 제자리에서 덮어쓴다
cp new.jar /opt/myapp/app.jar 로 덮으면 이전 버전이 사라져 롤백이 불가능합니다. 실행 중인 JVM 이 jar 를 읽는 도중 덮이면 ZipException 도 납니다. ✅ releases/ 에 새 폴더로 넣고 current 링크만 바꿉니다.
❌ 실수 4: pid 파일이 남아 있어 start 가 거부된다
앱이 KILL 로 죽거나 서버가 재부팅되면 pid 파일이 남습니다. 그 번호를 다른 프로세스가 쓰고 있으면 "이미 실행 중" 으로 오판합니다. ✅ kill -0 으로 실제 생존을 확인하고, 죽어 있으면 pid 파일을 지운 뒤 진행합니다. 더 확실히 하려면 ps -p PID -o comm= 이 java 인지 봅니다.
❌ 실수 5: 상대 경로로 스크립트를 짠다
cd 위치에 따라 logs/ 가 엉뚱한 곳에 생깁니다. cron 이나 systemd 는 홈 폴더가 아닌 곳에서 실행합니다. ✅ APP_HOME 절대 경로를 기준으로 모든 경로를 만들고, 스크립트 시작에 cd "$APP_HOME" 을 넣습니다.
❌ 실수 6: stdout 을 /dev/null 로 버린다
시작 실패 원인이 stdout 에만 찍히는 경우가 많습니다. 로그 설정이 로드되기 전의 에러가 그렇습니다. ✅ >> logs/stdout.log 2>&1 로 남기고 05 레슨의 logrotate 로 크기를 관리합니다.
❌ 실수 7: 시간대 옵션을 빼먹는다
서버 시간대가 UTC 이면 JVM 도 UTC 를 써서 화면의 시각이 9시간 어긋납니다. DB 는 KST 라 날짜 경계 계산이 틀립니다. ✅ -Duser.timezone=Asia/Seoul 을 JAVA_OPTS 에 넣거나 서버 timedatectl 을 맞춥니다.
❌ 실수 8: 비밀번호를 jar 나 스크립트에 넣는다
git 에 올라가고, jar 를 풀면 누구나 봅니다. ✅ 서버의 conf/ 파일에 두고 권한 600, 소유자는 앱 계정으로 합니다. 스크립트는 그 파일을 읽기만 합니다.
❌ 실수 9: 배포 후 헬스 체크 없이 끝낸다
프로세스가 살아 있어도 DB 연결 실패로 요청은 전부 500 일 수 있습니다. ✅ curl -sf .../actuator/health 가 200 을 줄 때까지 기다리고, 실패하면 자동으로 rollback 을 부릅니다.
❌ 실수 10: releases/ 를 정리하지 않는다
jar 하나가 50MB 면 100번 배포 뒤 5GB 입니다. 디스크가 차면 로그도 못 쓰고 앱이 멈춥니다. ✅ 배포 때 최근 N 개만 남기고 지웁니다. ls -1dt releases/*/ | tail -n +6 | xargs -r rm -rf 가 그 한 줄입니다.