로그가 장애 원인이 되는 순간

운영 서버에서 로그는 문제를 추적하는 가장 기본적인 자료이지만, 관리 기준이 없으면 장애의 원인이 되기도 합니다. 애플리케이션 오류가 반복되거나 외부 요청이 폭증했을 때 로그 파일이 몇 시간 만에 수십 기가바이트까지 커지고, 루트 파티션이 가득 차면서 데이터베이스, 배포, SSH 접속까지 연쇄적으로 실패할 수 있습니다. 특히 작은 클라우드 인스턴스나 단일 서버 환경에서는 디스크 여유 공간이 넉넉하지 않아 로그 정책을 미뤄 두면 복구보다 예방이 훨씬 중요합니다.

Linux 서버의 로그 관리는 크게 두 축으로 나누어 보는 것이 좋습니다. 하나는 systemd-journald가 수집하는 시스템 저널이고, 다른 하나는 Nginx, 애플리케이션, 배치 프로그램이 직접 남기는 파일 로그입니다. journald는 서비스 표준 출력, 커널 메시지, systemd 단위 로그를 관리하고, 파일 로그는 보통 /var/log 아래 또는 서비스별 디렉터리에 쌓입니다. 두 영역을 같은 방식으로 다루면 누락이나 중복이 생기므로 각각의 역할에 맞는 제한과 회전 정책을 별도로 잡아야 합니다.

먼저 현재 위험도를 확인하기

정책을 바꾸기 전에는 현재 로그가 어느 파티션을 얼마나 차지하는지 확인해야 합니다. 루트 파티션이 80%를 넘으면 새 배포나 패키지 설치 중에도 실패할 가능성이 커지고, 90%를 넘으면 데이터베이스 임시 파일이나 세션 파일 쓰기까지 영향을 받을 수 있습니다. 아래 명령은 디스크 전체 사용량, /var/log 하위 용량, journald 점유량을 빠르게 확인하는 기본 점검 세트입니다.

df -h
sudo du -h --max-depth=1 /var/log | sort -h
journalctl --disk-usage
sudo find /var/log -type f -size +500M -exec ls -lh {} ;

이 결과에서 특정 서비스 로그만 비정상적으로 큰 경우에는 애플리케이션 로깅 레벨, 반복 예외, 접근 로그 형식을 함께 점검해야 합니다. 반대로 journalctl --disk-usage 값이 큰 경우에는 journald 자체 보관 한도를 설정하는 것이 우선입니다. 임시로 파일을 삭제해 공간을 만들 수는 있지만, 원인을 바꾸지 않으면 같은 문제가 다시 발생합니다.

journald 보관 한도 설정

systemd-journald는 기본값만으로도 오래된 저널을 정리할 수 있지만, 서버 용량과 운영 정책에 맞춰 명시적인 상한을 두는 편이 안전합니다. /etc/systemd/journald.conf 또는 /etc/systemd/journald.conf.d/*.conf에 설정을 추가하면 전체 사용량, 파일 하나의 최대 크기, 보관 기간을 제한할 수 있습니다. 작은 웹 서버라면 전체 저널을 1~2GB 이하로 제한하고, 장애 분석에 필요한 기간만 남기는 식으로 시작하면 됩니다.

sudo mkdir -p /etc/systemd/journald.conf.d
sudo tee /etc/systemd/journald.conf.d/10-size-limit.conf >/dev/null <<'EOF'
[Journal]
Storage=persistent
SystemMaxUse=1G
SystemKeepFree=2G
SystemMaxFileSize=128M
MaxRetentionSec=14day
Compress=yes
EOF

sudo systemctl restart systemd-journald
journalctl --disk-usage

SystemMaxUse는 저널이 사용할 수 있는 최대 용량이고, SystemKeepFree는 파일시스템에 반드시 남겨 둘 여유 공간입니다. 둘을 함께 지정하면 로그가 예상을 넘어 커져도 루트 파티션을 끝까지 채우는 상황을 줄일 수 있습니다. MaxRetentionSec는 보관 기간 기준 정리이며, 보안 감사나 장애 분석 요구가 있는 서비스라면 내부 정책에 맞게 더 길게 잡되 별도 백업 저장소와 함께 설계해야 합니다.

파일 로그는 logrotate로 분리 관리

애플리케이션이 /var/log/myapp/app.log처럼 직접 파일에 기록한다면 logrotate 정책이 필요합니다. 단순히 매일 파일명을 바꾸는 수준이 아니라, 압축 여부, 보관 개수, 파일 권한, 서비스 재열기 명령까지 포함해야 합니다. 특히 Node.js, Java, Python 서비스가 파일 핸들을 계속 잡고 있으면 로그 파일을 회전해도 기존 파일에 계속 쓰는 문제가 생길 수 있습니다. 이때는 서비스가 SIGHUP으로 로그를 다시 열 수 있는지 확인하거나, copytruncate를 제한적으로 사용합니다.

sudo tee /etc/logrotate.d/myapp >/dev/null <<'EOF'
/var/log/myapp/*.log {
    daily
    rotate 14
    size 100M
    missingok
    notifempty
    compress
    delaycompress
    create 0640 myapp adm
    sharedscripts
    postrotate
        systemctl kill -s HUP myapp.service 2>/dev/null || true
    endscript
}
EOF

sudo logrotate -d /etc/logrotate.d/myapp
sudo logrotate -f /etc/logrotate.d/myapp

daily와 size를 함께 쓰면 하루가 지나거나 파일이 지정 크기를 넘었을 때 회전 대상이 됩니다. rotate 14는 최근 14개 묶음을 보관한다는 뜻입니다. compress와 delaycompress를 같이 쓰면 바로 이전 로그는 압축하지 않아 최근 장애 분석이 편하고, 더 오래된 로그는 압축해 공간을 줄일 수 있습니다. postrotate에서는 서비스가 새 로그 파일을 열도록 신호를 보냅니다. 서비스가 HUP을 지원하지 않는다면 애플리케이션 로그 라이브러리의 회전 기능을 쓰거나 표준 출력으로 보내 journald에서 관리하는 구조도 검토해야 합니다.

Nginx 접근 로그와 애플리케이션 로그를 구분하기

웹 서버에서는 접근 로그가 가장 빠르게 증가하는 경우가 많습니다. 모든 요청의 User-Agent, Referer, 쿼리 문자열을 길게 남기면 분석에는 유용하지만 저장 비용이 커집니다. 운영 환경에서는 보안 분석과 장애 추적에 필요한 필드만 남기고, 개인정보나 토큰이 URL에 섞이지 않도록 애플리케이션 라우팅도 함께 점검해야 합니다. Nginx 로그는 기본 패키지가 logrotate 파일을 제공하는 경우가 많지만, 트래픽이 많은 서버라면 size 기준을 추가해 하루 중에도 여러 번 회전되도록 조정할 수 있습니다.

  • 접근 로그는 보관 기간과 압축 정책을 명확히 정합니다.
  • 오류 로그는 접근 로그보다 더 오래 보관하되 폭주 알림을 함께 둡니다.
  • 개인정보, 인증 토큰, 결제 관련 원문 데이터는 로그에 남기지 않습니다.
  • 컨테이너 환경에서는 파일 로그보다 표준 출력 수집 방식을 우선 검토합니다.

운영 알림 기준 만들기

로그 정책은 설정 파일만으로 끝나지 않습니다. 디스크 사용량이 일정 기준을 넘었을 때 알림이 와야 하고, 어떤 로그가 늘어났는지 바로 확인할 수 있어야 합니다. 최소한 루트 파티션 80%, 90%, inode 사용량 80% 기준의 알림을 두는 것이 좋습니다. 파일 개수가 지나치게 많아 inode가 고갈되면 df -h에는 여유가 있어 보여도 새 파일 생성이 실패할 수 있으므로 df -ih도 함께 봐야 합니다.

df -h /
df -ih /
sudo journalctl -p warning --since '24 hours ago' --no-pager | tail -100
sudo find /var/log -type f -mtime -1 -printf '%s %p
' | sort -nr | head -20

장애 대응 문서에는 공간 확보용 임시 명령도 적어 둘 수 있지만, 운영자가 실수로 중요한 로그를 지우지 않도록 순서를 정해야 합니다. 먼저 불필요한 압축 로그와 오래된 로그를 확인하고, 그 다음 journald vacuum 명령으로 정책 범위 안에서 정리합니다. 실행 전에 현재 장애 분석에 필요한 기간의 로그가 있는지 확인하는 절차도 필요합니다.

sudo journalctl --vacuum-time=7d
sudo journalctl --vacuum-size=800M
sudo logrotate -f /etc/logrotate.conf

배포 전 점검 체크리스트

새 서버를 만들거나 서비스를 추가할 때는 로그 경로와 보관 정책을 배포 체크리스트에 포함해야 합니다. 로그가 표준 출력으로 가는지 파일로 가는지, 파일이라면 logrotate가 등록되어 있는지, 권한은 서비스 계정과 운영자 그룹에 맞는지 확인합니다. 또한 오류 로그가 실제로 관측 도구나 알림으로 이어지는지도 테스트해야 합니다. 로그를 많이 남기는 것보다 중요한 것은 장애 원인을 찾을 수 있을 만큼 남기되 서버를 멈추지 않게 제한하는 것입니다.

  • journald에는 SystemMaxUse, SystemKeepFree, MaxRetentionSec를 명시합니다.
  • 파일 로그에는 logrotate의 size, rotate, compress, create, postrotate를 지정합니다.
  • 서비스가 로그 회전 후 새 파일을 여는지 강제 회전으로 검증합니다.
  • 디스크 사용량과 inode 사용량 알림을 함께 설정합니다.
  • 개인정보와 인증 정보가 로그에 남지 않도록 애플리케이션 로그 포맷을 점검합니다.

로그 운영의 목표는 모든 기록을 무제한 저장하는 것이 아니라, 장애 분석에 필요한 신호를 안정적으로 남기는 것입니다. journald 한도, logrotate 정책, 디스크 알림, 개인정보 제외 기준을 함께 적용하면 작은 서버에서도 로그 폭주로 인한 장애 가능성을 크게 줄일 수 있습니다.