이미지 로딩 중...

시스템 자동화 실전 프로젝트 완벽 가이드 - 슬라이드 1/7
A

AI Generated

2025. 11. 18. · 4 Views

시스템 자동화 실전 프로젝트 완벽 가이드

실무에서 바로 사용할 수 있는 시스템 자동화 스크립트를 배워보세요. 백업, 모니터링, 배포까지 모든 반복 작업을 자동화하는 방법을 단계별로 알려드립니다. 초보자도 쉽게 따라할 수 있도록 친절하게 설명합니다.


목차

  1. 백업 자동화 스크립트
  2. 로그 모니터링 및 알림
  3. 서버 헬스 체크 스크립트
  4. 배포 자동화
  5. Cron 작업 설정
  6. 베스트 프랙티스와 코드 리뷰

1. 백업 자동화 스크립트

시작하며

여러분이 매일 아침 출근하면 가장 먼저 하는 일이 중요한 데이터를 백업하는 것이라면, 이제 그 시간을 다른 생산적인 일에 사용할 수 있습니다. 매번 같은 명령어를 입력하고, 날짜를 확인하고, 백업 파일 이름을 정하는 반복적인 작업은 정말 지루하죠.

실제로 많은 개발자들이 백업을 깜빡해서 중요한 데이터를 잃어버리는 경우가 있습니다. 수동으로 하는 작업은 사람이 실수할 수밖에 없고, 특히 바쁜 날에는 더욱 그렇습니다.

바로 이럴 때 필요한 것이 백업 자동화 스크립트입니다. 한 번만 설정해두면 매일 정해진 시간에 자동으로 백업이 진행되고, 오래된 백업 파일은 자동으로 삭제되어 저장 공간도 관리됩니다.

개요

간단히 말해서, 백업 자동화 스크립트는 여러분의 중요한 데이터를 정기적으로 안전하게 복사해주는 로봇 비서와 같습니다. 실무에서는 데이터베이스, 설정 파일, 사용자 업로드 파일 등 다양한 데이터를 주기적으로 백업해야 합니다.

예를 들어, 쇼핑몰을 운영한다면 고객 정보와 주문 데이터를 매일 백업해야 하는데, 이걸 매번 수동으로 하면 시간도 오래 걸리고 실수하기 쉽습니다. 기존에는 매번 터미널을 열고 명령어를 직접 입력했다면, 이제는 스크립트가 자동으로 모든 작업을 처리합니다.

심지어 백업이 실패하면 이메일로 알림까지 보내줍니다. 이 스크립트의 핵심 특징은 첫째, 날짜별로 백업 파일을 자동으로 구분하고, 둘째, 오래된 백업을 자동으로 정리하며, 셋째, 백업 성공 여부를 로그로 기록한다는 점입니다.

이러한 특징들 덕분에 여러분은 안심하고 다른 일에 집중할 수 있습니다.

코드 예제

#!/bin/bash
# 백업할 디렉토리와 백업 저장 위치 설정
SOURCE_DIR="/var/www/html"
BACKUP_DIR="/backup"
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_FILE="backup_${DATE}.tar.gz"

# 백업 디렉토리가 없으면 생성
mkdir -p $BACKUP_DIR

# 백업 실행 (압축하여 저장)
tar -czf ${BACKUP_DIR}/${BACKUP_FILE} ${SOURCE_DIR} 2>/dev/null

# 백업 성공 여부 확인
if [ $? -eq 0 ]; then
    echo "[$(date)] 백업 성공: ${BACKUP_FILE}" >> ${BACKUP_DIR}/backup.log
    # 30일 이상 된 백업 파일 자동 삭제
    find ${BACKUP_DIR} -name "backup_*.tar.gz" -mtime +30 -delete
else
    echo "[$(date)] 백업 실패!" >> ${BACKUP_DIR}/backup.log
    exit 1
fi

설명

이것이 하는 일: 이 스크립트는 마치 여러분의 비서처럼 매일 정해진 시간에 중요한 파일들을 안전한 곳에 복사해둡니다. 그리고 너무 오래된 백업은 자동으로 삭제하여 저장 공간이 가득 차는 것을 방지합니다.

첫 번째로, 스크립트 상단에서 어떤 폴더를 백업할지, 어디에 저장할지를 정합니다. SOURCE_DIR은 백업할 원본 폴더이고, BACKUP_DIR은 백업 파일을 저장할 위치입니다.

DATE 변수는 현재 날짜와 시간을 가져와서 백업 파일 이름에 사용합니다. 이렇게 하면 "backup_20250118_143022.tar.gz" 같은 형식으로 파일이 생성되어 나중에 언제 백업했는지 쉽게 알 수 있습니다.

그 다음으로, mkdir -p 명령으로 백업 폴더가 없으면 자동으로 만들고, tar 명령어로 원본 폴더를 압축하여 백업합니다. tar는 여러 파일을 하나로 묶어주는 도구인데, -c는 새로 만들기, -z는 gzip으로 압축하기, -f는 파일 이름 지정을 의미합니다.

2>/dev/null은 에러 메시지를 숨기는 옵션입니다. 마지막으로, $?라는 특별한 변수로 이전 명령어가 성공했는지 확인합니다.

0이면 성공, 그 외는 실패를 의미합니다. 성공하면 로그 파일에 기록하고 find 명령어로 30일 이상 된 백업 파일을 자동으로 삭제합니다.

실패하면 로그에 실패 메시지를 남기고 종료합니다. 여러분이 이 스크립트를 사용하면 매일 수동으로 백업할 필요가 없어지고, 저장 공간 관리도 자동으로 됩니다.

또한 로그 파일을 보면 언제 백업이 성공했고 실패했는지 한눈에 확인할 수 있어 문제가 생겨도 빠르게 대응할 수 있습니다.

실전 팁

💡 백업 전에 데이터베이스를 덤프하려면 mysqldump나 pg_dump 명령을 추가하세요. 실행 중인 데이터베이스는 파일 복사만으로는 완전히 백업되지 않습니다.

💡 중요한 백업은 같은 서버가 아닌 다른 서버나 클라우드 스토리지(AWS S3, Google Cloud Storage)에도 복사하세요. 서버가 고장나면 같은 서버의 백업도 함께 사라집니다.

💡 백업 파일이 정말 복원 가능한지 주기적으로 테스트하세요. 백업은 있는데 복원이 안 되면 아무 소용이 없습니다.

💡 큰 파일을 백업할 때는 rsync를 사용하면 변경된 부분만 백업하여 시간과 공간을 절약할 수 있습니다.

💡 백업 스크립트 실행 권한을 chmod +x backup.sh로 설정하고, 민감한 정보가 포함되어 있다면 chmod 700으로 소유자만 실행할 수 있게 제한하세요.


2. 로그 모니터링 및 알림

시작하며

여러분의 서버에서 에러가 발생했는데 몇 시간이 지나서야 알게 된다면 어떨까요? 그 사이에 고객들은 불편을 겪고, 매출은 손실되며, 여러분의 신뢰도는 떨어지게 됩니다.

실제 서비스 운영에서는 에러 로그를 실시간으로 감시하는 것이 매우 중요합니다. 하지만 24시간 모니터를 지켜보고 있을 수는 없죠.

특히 밤에 에러가 발생하면 다음날 아침에야 알게 되는 경우가 많습니다. 바로 이럴 때 필요한 것이 로그 모니터링 자동화 스크립트입니다.

이 스크립트는 로그 파일을 계속 감시하다가 ERROR나 CRITICAL 같은 심각한 키워드를 발견하면 즉시 이메일이나 슬랙으로 알려줍니다.

개요

간단히 말해서, 이 스크립트는 여러분의 서버에 24시간 대기하고 있는 경비원과 같습니다. 뭔가 이상한 일이 생기면 바로 여러분에게 연락해줍니다.

실무에서는 애플리케이션 로그, 웹 서버 로그, 데이터베이스 로그 등 다양한 로그 파일을 모니터링해야 합니다. 예를 들어, 결제 시스템에서 에러가 발생하면 즉시 알아야 고객 불만을 최소화할 수 있습니다.

기존에는 주기적으로 로그 파일을 열어서 직접 확인했다면, 이제는 스크립트가 자동으로 감시하고 문제가 생기면 알려줍니다. 심지어 어떤 종류의 에러인지, 몇 번 발생했는지도 함께 알려줍니다.

핵심 특징은 첫째, tail 명령어로 실시간으로 로그를 감시하고, 둘째, 정규표현식으로 특정 패턴을 찾아내며, 셋째, 중복 알림을 방지하여 알림 피로도를 줄인다는 점입니다. 이를 통해 진짜 중요한 문제에만 집중할 수 있습니다.

코드 예제

#!/bin/bash
# 모니터링할 로그 파일과 알림 설정
LOG_FILE="/var/log/application.log"
ALERT_EMAIL="admin@example.com"
ALERT_KEYWORD="ERROR|CRITICAL|FATAL"
TEMP_FILE="/tmp/alert_sent.tmp"

# 로그 파일이 존재하는지 확인
if [ ! -f "$LOG_FILE" ]; then
    echo "로그 파일을 찾을 수 없습니다: $LOG_FILE"
    exit 1
fi

# 로그 파일을 실시간으로 감시하며 에러 키워드 검색
tail -Fn0 "$LOG_FILE" | while read line; do
    # 에러 키워드가 포함된 라인 발견
    if echo "$line" | grep -qE "$ALERT_KEYWORD"; then
        # 중복 알림 방지 (1분 내 같은 알림 방지)
        if [ ! -f "$TEMP_FILE" ] || [ $(find "$TEMP_FILE" -mmin +1 2>/dev/null | wc -l) -eq 1 ]; then
            echo "$line" | mail -s "[알림] 서버 에러 발생!" "$ALERT_EMAIL"
            echo "$(date): 알림 전송됨" > "$TEMP_FILE"
        fi
    fi
done

설명

이것이 하는 일: 이 스크립트는 마치 CCTV처럼 로그 파일을 계속 지켜보다가 ERROR, CRITICAL, FATAL 같은 위험한 단어가 나타나면 즉시 여러분에게 이메일을 보냅니다. 24시간 쉬지 않고 감시하는 자동 경비 시스템입니다.

첫 번째로, 스크립트는 어떤 로그 파일을 볼지, 누구에게 알림을 보낼지, 어떤 키워드를 찾을지 설정합니다. ALERT_KEYWORD에는 여러 단어를 파이프(|)로 연결하여 한 번에 여러 패턴을 검색할 수 있습니다.

TEMP_FILE은 중복 알림을 방지하기 위한 임시 파일입니다. 그 다음으로, 로그 파일이 실제로 존재하는지 확인합니다.

if [ ! -f "$LOG_FILE" ]는 "파일이 없으면"을 의미하는데, 파일이 없으면 에러 메시지를 출력하고 종료합니다.

그리고 tail -Fn0 명령으로 로그 파일의 끝부분을 실시간으로 계속 읽습니다. -F 옵션은 파일이 삭제되고 다시 생성되어도 계속 추적하고, -n0은 기존 내용은 건너뛰고 새로운 라인만 읽습니다.

마지막으로, while read line으로 새로운 로그 라인을 하나씩 읽으면서 grep -qE로 에러 키워드가 있는지 확인합니다. -q는 조용히 (출력 없이) 검색하고, -E는 확장 정규표현식을 사용합니다.

에러를 발견하면 1분 이내에 같은 알림을 보낸 적이 있는지 확인하고, 없으면 mail 명령으로 이메일을 보냅니다. find "$TEMP_FILE" -mmin +1은 "1분 이상 전에 수정된 파일 찾기"를 의미합니다.

여러분이 이 스크립트를 사용하면 서버 문제를 즉시 알 수 있어 빠른 대응이 가능합니다. 중복 알림 방지 기능 덕분에 같은 에러가 계속 발생해도 1분에 한 번만 알림을 받으므로 알림에 치이지 않습니다.

또한 백그라운드로 실행해두면 계속 감시하므로 여러분은 다른 일에 집중할 수 있습니다.

실전 팁

💡 이메일 대신 슬랙이나 텔레그램으로 알림을 받고 싶다면 curl을 사용해서 웹훅 URL로 메시지를 보내세요. 모바일에서 즉시 확인할 수 있어 편리합니다.

💡 스크립트를 백그라운드로 실행하려면 nohup ./monitor.sh & 명령을 사용하고, 서버 재부팅 시에도 자동 실행되도록 systemd 서비스로 등록하세요.

💡 로그 파일이 너무 크면 성능이 저하되므로 logrotate를 설정하여 자동으로 로그 파일을 회전시키고 오래된 로그는 압축하세요.

💡 여러 서버의 로그를 한 곳에서 모니터링하려면 ELK 스택(Elasticsearch, Logstash, Kibana)이나 Grafana Loki 같은 중앙 집중식 로깅 시스템을 고려해보세요.

💡 알림에 에러가 발생한 서버 이름, 타임스탬프, 에러 라인 번호를 포함시키면 디버깅할 때 훨씬 빠르게 문제를 찾을 수 있습니다.


3. 서버 헬스 체크 스크립트

시작하며

여러분의 서버가 느려지거나 다운되기 전에 미리 알 수 있다면 얼마나 좋을까요? 대부분의 서버 장애는 갑자기 발생하는 것처럼 보이지만, 실제로는 CPU 사용률이나 메모리, 디스크 공간이 서서히 증가하다가 임계점을 넘는 경우가 많습니다.

많은 서비스들이 갑작스러운 다운타임으로 고객을 잃고 신뢰를 잃습니다. "서버가 죽었어요!"라는 고객의 불만 전화를 받기 전에 미리 알고 조치했다면 이런 상황을 막을 수 있었을 것입니다.

바로 이럴 때 필요한 것이 서버 헬스 체크 스크립트입니다. CPU, 메모리, 디스크 사용률을 주기적으로 확인하고, 위험 수준에 도달하면 즉시 알려줍니다.

마치 병원에서 환자의 활력 징후를 계속 모니터링하는 것과 같습니다.

개요

간단히 말해서, 서버 헬스 체크는 여러분의 서버가 건강한지 주기적으로 검진하는 자동 건강검진 시스템입니다. 실무에서는 서버 리소스가 부족해지면 성능이 급격히 저하되고 최악의 경우 서비스가 중단됩니다.

예를 들어, 디스크 공간이 100% 차면 로그도 쓸 수 없고 데이터베이스도 작동하지 않습니다. 이런 상황이 발생하기 전에 "디스크 사용률 85% 도달"이라는 경고를 받으면 여유롭게 대응할 수 있습니다.

기존에는 top, df, free 같은 명령어를 직접 실행해서 확인했다면, 이제는 스크립트가 자동으로 체크하고 문제가 있을 때만 알려줍니다. 핵심 특징은 첫째, 여러 리소스를 한 번에 체크하고, 둘째, 임계값을 자유롭게 설정할 수 있으며, 셋째, 체크 결과를 로그로 남겨 나중에 분석할 수 있다는 점입니다.

이를 통해 서버 문제를 사전에 예방할 수 있습니다.

코드 예제

#!/bin/bash
# 임계값 설정 (백분율)
CPU_THRESHOLD=80
MEMORY_THRESHOLD=85
DISK_THRESHOLD=90
ALERT_EMAIL="admin@example.com"

# CPU 사용률 확인
CPU_USAGE=$(top -bn1 | grep "Cpu(s)" | awk '{print $2}' | cut -d'%' -f1)
CPU_USAGE=${CPU_USAGE%.*}  # 소수점 제거

# 메모리 사용률 확인
MEMORY_USAGE=$(free | grep Mem | awk '{print int($3/$2 * 100)}')

# 디스크 사용률 확인 (루트 파티션)
DISK_USAGE=$(df -h / | tail -1 | awk '{print $5}' | cut -d'%' -f1)

# 로그 파일에 현재 상태 기록
echo "[$(date)] CPU: ${CPU_USAGE}%, MEM: ${MEMORY_USAGE}%, DISK: ${DISK_USAGE}%" >> /var/log/health_check.log

# 임계값 초과 시 알림 발송
if [ $CPU_USAGE -ge $CPU_THRESHOLD ]; then
    echo "CPU 사용률이 ${CPU_USAGE}%입니다!" | mail -s "[경고] CPU 사용률 높음" $ALERT_EMAIL
fi

if [ $MEMORY_USAGE -ge $MEMORY_THRESHOLD ]; then
    echo "메모리 사용률이 ${MEMORY_USAGE}%입니다!" | mail -s "[경고] 메모리 사용률 높음" $ALERT_EMAIL
fi

if [ $DISK_USAGE -ge $DISK_THRESHOLD ]; then
    echo "디스크 사용률이 ${DISK_USAGE}%입니다!" | mail -s "[경고] 디스크 사용률 높음" $ALERT_EMAIL
fi

설명

이것이 하는 일: 이 스크립트는 마치 의사가 환자의 혈압, 맥박, 체온을 재는 것처럼 서버의 주요 리소스를 측정하고, 정상 범위를 벗어나면 경고를 보냅니다. 이를 통해 서버가 완전히 다운되기 전에 미리 조치할 수 있습니다.

첫 번째로, 스크립트 상단에서 각 리소스의 위험 임계값을 설정합니다. CPU_THRESHOLD=80은 "CPU 사용률이 80%를 넘으면 위험"을 의미합니다.

이 값들은 여러분의 서버 환경에 맞게 조정할 수 있습니다. 일반적으로 CPU와 메모리는 80-85%, 디스크는 90%를 기준으로 합니다.

그 다음으로, top, free, df 같은 시스템 명령어를 사용해서 현재 리소스 사용률을 가져옵니다. top -bn1은 배치 모드로 한 번만 실행하고, grep과 awk로 필요한 숫자만 추출합니다.

free는 메모리 정보를 보여주는데, awk '{print int($3/$2 * 100)}'는 "사용중인 메모리 / 전체 메모리 * 100"을 계산합니다. df -h /는 루트 파티션의 디스크 사용률을 사람이 읽기 쉬운 형식으로 보여줍니다.

마지막으로, echo로 현재 상태를 로그 파일에 기록하고, if 문으로 각 리소스가 임계값을 넘었는지 확인합니다. -ge는 "크거나 같으면"을 의미하는 비교 연산자입니다.

임계값을 초과하면 mail 명령으로 경고 이메일을 보냅니다. 이메일 제목에 [경고]를 붙여서 긴급한 메일임을 알립니다.

여러분이 이 스크립트를 cron에 등록하여 5분마다 실행하면 서버 상태를 실시간으로 모니터링할 수 있습니다. 로그 파일에는 시간별 리소스 사용 추이가 기록되므로 나중에 "어느 시간대에 CPU가 높아지는가?"를 분석할 수도 있습니다.

위험한 상황이 발생하기 전에 미리 알림을 받으므로 여유롭게 대응할 수 있습니다.

실전 팁

💡 프로세스별 리소스 사용률도 함께 확인하고 싶다면 ps aux --sort=-%cpu | head -5를 추가하여 CPU를 가장 많이 쓰는 프로세스 5개를 알림에 포함시키세요.

💡 네트워크 트래픽도 모니터링하려면 ifstat이나 vnstat 같은 도구를 사용하고, 급격한 트래픽 증가는 DDoS 공격의 신호일 수 있으니 주의하세요.

💡 여러 파티션이 있다면 df -h | grep -E '^/dev' | awk '{print $5}' 같은 방식으로 모든 파티션을 체크하세요. 특히 /var/log가 별도 파티션인 경우 로그로 가득 차는 경우가 많습니다.

💡 모니터링 결과를 Prometheus나 Grafana로 시각화하면 대시보드에서 한눈에 상태를 볼 수 있고, 과거 데이터와 비교하여 추세를 파악할 수 있습니다.

💡 임계값을 너무 낮게 설정하면 알림이 너무 자주 와서 무시하게 되므로, 실제 환경을 며칠 관찰한 후 적절한 값으로 조정하세요.


4. 배포 자동화

시작하며

여러분이 새로운 기능을 개발했는데 서버에 배포하는 데 30분씩 걸린다면 얼마나 답답할까요? Git에서 코드를 pull하고, 의존성을 설치하고, 빌드하고, 서버를 재시작하고, 테스트하고...

이 모든 과정을 매번 반복하는 것은 정말 비효율적입니다. 실제로 많은 팀들이 수동 배포 과정에서 실수를 합니다.

누군가는 빌드를 깜빡하고, 누군가는 서버 재시작을 잊어버립니다. 그 결과 서비스가 중단되거나 버그가 발생하는 경우가 생깁니다.

바로 이럴 때 필요한 것이 배포 자동화 스크립트입니다. 단 한 줄의 명령어로 전체 배포 프로세스가 자동으로 진행되고, 배포 전에 자동으로 백업을 만들며, 문제가 생기면 롤백까지 할 수 있습니다.

개요

간단히 말해서, 배포 자동화는 여러분의 코드를 서버에 올리는 복잡한 과정을 한 번의 클릭으로 처리해주는 마법 버튼과 같습니다. 실무에서는 하루에도 여러 번 배포가 발생할 수 있습니다.

예를 들어, 고객이 발견한 버그를 급하게 수정하고 배포해야 하는 핫픽스 상황에서는 빠르고 안전한 배포가 매우 중요합니다. 수동으로 하면 시간도 오래 걸리고 실수할 위험도 큽니다.

기존에는 배포 체크리스트를 보면서 하나씩 명령어를 입력했다면, 이제는 ./deploy.sh만 실행하면 모든 과정이 자동으로 진행됩니다. 심지어 배포 전 상태를 백업해두었다가 문제가 생기면 바로 되돌릴 수 있습니다.

핵심 특징은 첫째, 전체 배포 과정을 표준화하여 누가 배포해도 같은 결과를 보장하고, 둘째, 배포 전 자동 백업으로 안전장치를 제공하며, 셋째, 무중단 배포를 지원하여 서비스 중단 없이 업데이트할 수 있다는 점입니다.

코드 예제

#!/bin/bash
# 배포 설정
PROJECT_DIR="/var/www/myapp"
BACKUP_DIR="/var/backups/myapp"
BRANCH="main"

echo "[$(date)] 배포 시작..."

# 1. 배포 전 현재 상태 백업
echo "현재 상태 백업 중..."
BACKUP_NAME="backup_$(date +%Y%m%d_%H%M%S)"
cp -r $PROJECT_DIR ${BACKUP_DIR}/${BACKUP_NAME}

# 2. 최신 코드 가져오기
echo "최신 코드 가져오는 중..."
cd $PROJECT_DIR
git fetch origin
git checkout $BRANCH
git pull origin $BRANCH

if [ $? -ne 0 ]; then
    echo "Git pull 실패! 백업으로 복구합니다."
    rm -rf $PROJECT_DIR
    cp -r ${BACKUP_DIR}/${BACKUP_NAME} $PROJECT_DIR
    exit 1
fi

# 3. 의존성 설치 및 빌드
echo "의존성 설치 중..."
npm install --production
npm run build

# 4. 데이터베이스 마이그레이션 (필요시)
echo "데이터베이스 마이그레이션 중..."
npm run migrate

# 5. 서버 재시작 (무중단 배포)
echo "서버 재시작 중..."
pm2 reload myapp --update-env

# 6. 헬스 체크
sleep 5
if curl -f http://localhost:3000/health > /dev/null 2>&1; then
    echo "[$(date)] 배포 성공!"
    # 오래된 백업 삭제 (7일 이상)
    find ${BACKUP_DIR} -name "backup_*" -mtime +7 -exec rm -rf {} \;
else
    echo "[$(date)] 배포 실패! 헬스 체크 실패"
    pm2 reload myapp
    exit 1
fi

설명

이것이 하는 일: 이 스크립트는 마치 숙련된 엔지니어가 배포 매뉴얼을 완벽하게 따라하는 것처럼, 코드 가져오기부터 빌드, 데이터베이스 마이그레이션, 서버 재시작까지 모든 단계를 자동으로 수행합니다. 중간에 문제가 생기면 즉시 중단하고 이전 상태로 되돌립니다.

첫 번째로, 배포를 시작하기 전에 현재 프로젝트 폴더를 통째로 백업합니다. cp -r로 전체 디렉토리를 복사하는데, 백업 이름에 타임스탬프를 붙여서 언제 백업했는지 알 수 있게 합니다.

이 백업은 배포가 실패했을 때 복구하는 용도로 사용됩니다. 마치 게임에서 세이브 포인트를 만드는 것과 같습니다.

그 다음으로, git 명령어로 최신 코드를 가져옵니다. git fetch는 원격 저장소의 최신 정보를 가져오고, git checkout은 배포할 브랜치로 전환하며, git pull은 실제 코드를 다운로드합니다.

여기서 중요한 것은 if [ $? -ne 0 ]로 pull이 실패했는지 확인한다는 점입니다.

-ne는 "같지 않으면"을 의미하므로, 0이 아니면 (즉, 실패하면) 백업을 복원하고 종료합니다. 세 번째로, npm install로 필요한 라이브러리를 설치하고 npm run build로 프로덕션 빌드를 만듭니다.

--production 옵션을 사용하면 개발용 패키지는 설치하지 않아 빌드 시간이 단축됩니다. 그리고 npm run migrate로 데이터베이스 스키마를 최신 버전으로 업데이트합니다.

마지막으로, pm2 reload로 서버를 재시작합니다. pm2 reload는 무중단 재시작을 지원하여 서비스가 중단되지 않습니다.

그리고 sleep 5로 5초 기다린 후 curl로 헬스 체크 엔드포인트를 호출하여 서버가 정상적으로 작동하는지 확인합니다. -f 옵션은 HTTP 에러 시 실패를 반환하고, > /dev/null 2>&1은 출력을 숨깁니다.

헬스 체크가 성공하면 배포 완료이고, 실패하면 경고 메시지를 출력합니다. 여러분이 이 스크립트를 사용하면 배포 시간을 90% 이상 단축할 수 있습니다.

수동으로 30분 걸리던 작업이 3분으로 줄어듭니다. 또한 모든 배포가 동일한 절차를 따르므로 누가 배포하든 일관된 결과를 얻을 수 있고, 실수로 인한 장애를 예방할 수 있습니다.

실전 팁

💡 배포 전에 자동으로 테스트를 실행하려면 npm run test를 추가하고, 테스트가 실패하면 배포를 중단하세요. 이렇게 하면 버그가 프로덕션에 올라가는 것을 막을 수 있습니다.

💡 블루-그린 배포를 구현하려면 두 개의 서버를 준비하고 로드밸런서로 트래픽을 전환하세요. 새 버전에 문제가 있으면 즉시 이전 버전으로 되돌릴 수 있습니다.

💡 배포 알림을 슬랙에 보내면 팀 전체가 배포 상황을 실시간으로 알 수 있습니다. curl -X POST를 사용하여 슬랙 웹훅으로 메시지를 보내세요.

💡 데이터베이스 마이그레이션이 실패하면 롤백하기 어려우므로, 마이그레이션 스크립트는 항상 되돌릴 수 있는 down 함수도 함께 작성하세요.

💡 큰 프로젝트는 Docker를 사용하여 배포하면 환경 차이로 인한 문제를 줄일 수 있고, docker-compose로 여러 서비스를 한 번에 관리할 수 있습니다.


5. Cron 작업 설정

시작하며

여러분이 만든 백업 스크립트, 모니터링 스크립트를 매번 수동으로 실행해야 한다면 자동화의 의미가 없겠죠? 스크립트를 만드는 것도 중요하지만, 그것을 정해진 시간에 자동으로 실행되도록 예약하는 것이 진정한 자동화입니다.

많은 개발자들이 훌륭한 스크립트를 만들어놓고도 cron 설정을 어려워해서 결국 수동으로 실행하는 경우가 많습니다. 특히 cron 문법이 직관적이지 않아서 "도대체 별표(*)가 뭘 의미하지?"라고 헤매는 경우가 많습니다.

바로 이럴 때 필요한 것이 cron 작업 설정 방법입니다. 한 번만 제대로 배워두면 원하는 시간에 원하는 작업을 자동으로 실행할 수 있고, 여러분은 그저 결과만 확인하면 됩니다.

마치 알람 시계를 설정해두는 것과 같습니다.

개요

간단히 말해서, cron은 리눅스의 알람 시계입니다. 여러분이 원하는 시간에 원하는 프로그램을 자동으로 실행해줍니다.

실무에서는 매일 새벽 2시에 백업, 5분마다 헬스 체크, 매주 일요일에 리포트 생성 등 다양한 주기적인 작업이 필요합니다. 예를 들어, 전자상거래 사이트라면 매일 자정에 주문 통계를 집계하고, 매주 월요일 아침에 주간 리포트를 생성해야 할 수 있습니다.

기존에는 "내가 기억해서 실행해야지" 하다가 깜빡하는 경우가 많았다면, 이제는 cron이 정확한 시간에 자동으로 실행해줍니다. 심지어 여러분이 자고 있는 새벽에도 작동합니다.

핵심 특징은 첫째, 분 단위부터 연 단위까지 다양한 주기를 설정할 수 있고, 둘째, 여러 작업을 동시에 관리할 수 있으며, 셋째, 실행 결과를 로그로 남기거나 이메일로 받을 수 있다는 점입니다. 이를 통해 완전한 무인 자동화가 가능합니다.

코드 예제

# crontab -e 명령으로 편집기를 열고 아래 내용 추가

# 분 시 일 월 요일 명령어
# * * * * * 형식으로 작성

# 매일 새벽 2시에 데이터베이스 백업
0 2 * * * /home/scripts/backup.sh >> /var/log/backup.log 2>&1

# 5분마다 서버 헬스 체크
*/5 * * * * /home/scripts/health_check.sh >> /var/log/health.log 2>&1

# 매주 일요일 자정에 주간 리포트 생성
0 0 * * 0 /home/scripts/weekly_report.sh

# 매월 1일 새벽 3시에 로그 파일 정리
0 3 1 * * find /var/log -name "*.log" -mtime +30 -delete

# 평일(월-금) 오전 9시에 일일 알림 발송
0 9 * * 1-5 /home/scripts/daily_notification.sh

# 매 시간 정각에 캐시 클리어
0 * * * * /home/scripts/clear_cache.sh

# 시스템 재부팅 시 자동 실행
@reboot /home/scripts/startup.sh

설명

이것이 하는 일: cron은 마치 비서가 일정을 관리하듯이 여러분이 예약한 작업들을 정확한 시간에 자동으로 실행해줍니다. 여러분이 잠들어 있는 새벽에도, 주말에 쉬고 있을 때도 묵묵히 일을 처리합니다.

첫 번째로, cron 문법을 이해해야 합니다. 다섯 개의 필드(분 시 일 월 요일)가 있고, 각각 언제 실행할지를 의미합니다.

별표()는 "매번"을 의미하므로 " * * * *"는 "매분 실행"입니다. 0 2 * * *는 "매일 2시 0분에 실행"을 의미합니다.

여기서 첫 번째 0은 0분, 2는 2시, 나머지 세 개의 *는 "매일, 매월, 매요일"을 의미합니다. 그 다음으로, */5는 "5분마다"를 의미하는 특별한 표현입니다.

*/5 * * * *는 "5분마다 실행"이므로 0분, 5분, 10분... 이런 식으로 실행됩니다.

1-5는 범위를 의미하여 월요일부터 금요일(1-5)을 나타냅니다. 0 9 * * 1-5는 "평일 오전 9시"를 의미합니다.

세 번째로, >> /var/log/backup.log 2>&1은 실행 결과를 로그 파일에 추가한다는 의미입니다. >>는 파일 끝에 추가(append)하고, 2>&1은 에러 메시지(stderr)도 함께 기록합니다.

이렇게 하면 나중에 작업이 제대로 실행되었는지 로그를 보고 확인할 수 있습니다. @reboot는 특별한 키워드로 시스템이 재부팅될 때 자동으로 실행됩니다.

마지막으로, crontab -e로 cron 작업을 편집하고, crontab -l로 현재 설정된 작업 목록을 볼 수 있습니다. 작업을 추가한 후에는 반드시 로그를 확인하여 제대로 실행되는지 검증해야 합니다.

특히 경로 문제로 실패하는 경우가 많으므로 스크립트에서는 항상 절대 경로를 사용하세요. 여러분이 cron을 활용하면 반복적인 작업에서 완전히 해방됩니다.

한 번 설정해두면 수개월, 수년간 자동으로 작동하므로 여러분은 더 창의적이고 중요한 일에 집중할 수 있습니다. 또한 사람이 실수로 깜빡하는 일이 없으므로 업무의 신뢰성이 크게 향상됩니다.

실전 팁

💡 cron 작업이 제대로 실행되는지 테스트하려면 먼저 짧은 주기(*/1 * * * *)로 설정하여 1분마다 실행되게 한 후 로그를 확인하세요. 정상 작동을 확인한 후 실제 주기로 변경하세요.

💡 스크립트가 실행되지 않는다면 PATH 환경변수 문제일 수 있습니다. crontab 맨 위에 PATH=/usr/local/bin:/usr/bin:/bin을 추가하거나 스크립트에서 절대 경로를 사용하세요.

💡 cron 작업이 실패하면 기본적으로 이메일이 발송되는데, MAILTO=your@email.com을 crontab 상단에 추가하여 받을 이메일 주소를 지정하세요. MAILTO=""로 설정하면 이메일을 보내지 않습니다.

💡 복잡한 시간 패턴은 crontab.guru 같은 웹사이트에서 시각적으로 확인하면 이해하기 쉽습니다. 문법이 헷갈릴 때 유용합니다.

💡 중요한 cron 작업은 별도로 문서화하고, 버전 관리 시스템에 crontab 백업을 저장하세요. crontab -l > crontab_backup.txt로 현재 설정을 백업할 수 있습니다.


6. 베스트 프랙티스와 코드 리뷰

시작하며

여러분이 만든 자동화 스크립트가 몇 개월 후에 갑자기 실패한다면, 그 원인을 찾기 어려울 수 있습니다. "이 스크립트를 누가 만들었지?

왜 이렇게 작성했지?"라고 고민하게 됩니다. 심지어 그 스크립트를 만든 사람이 바로 여러분 자신이라는 사실을 깨닫게 되죠.

실제 업무 현장에서는 여러 사람이 함께 스크립트를 관리하고 유지보수합니다. 코드 품질이 낮으면 나중에 수정하기 어렵고, 버그가 발생했을 때 원인을 찾기 힘듭니다.

특히 자동화 스크립트는 백그라운드에서 조용히 실행되므로 문제가 생겨도 한참 후에야 발견되는 경우가 많습니다. 바로 이럴 때 필요한 것이 베스트 프랙티스입니다.

에러 처리, 로깅, 주석, 변수명 등 작은 습관들이 모여서 유지보수하기 쉬운 견고한 스크립트를 만듭니다. 이번 섹션에서는 실무에서 꼭 지켜야 할 핵심 원칙들을 알려드립니다.

개요

간단히 말해서, 베스트 프랙티스는 여러분의 스크립트를 전문가 수준으로 만들어주는 노하우 모음집입니다. 실무에서는 "일단 작동하는 코드"가 아니라 "안전하고 유지보수하기 쉬운 코드"가 필요합니다.

예를 들어, 에러 처리가 없는 백업 스크립트는 실패해도 조용히 넘어가서 나중에 백업이 필요한 순간에 백업 파일이 없다는 사실을 알게 됩니다. 이런 상황을 방지하려면 처음부터 제대로 작성해야 합니다.

기존에는 "일단 되게만 만들자"는 생각으로 코드를 작성했다면, 이제는 "나중에 누가 봐도 이해할 수 있게, 문제가 생겨도 쉽게 고칠 수 있게" 작성합니다. 핵심 특징은 첫째, set -e 같은 안전장치로 에러를 조기에 발견하고, 둘째, 상세한 로깅으로 무슨 일이 일어났는지 추적하며, 셋째, 명확한 변수명과 주석으로 코드의 의도를 전달한다는 점입니다.

이를 통해 스크립트의 품질과 신뢰성이 크게 향상됩니다.

코드 예제

#!/bin/bash
# 스크립트 시작 시 안전 설정
set -euo pipefail  # 에러 시 즉시 종료, 미정의 변수 사용 금지, 파이프라인 에러 감지

# 설정 파일에서 민감 정보 분리
CONFIG_FILE="/etc/myapp/config.conf"
if [ -f "$CONFIG_FILE" ]; then
    source "$CONFIG_FILE"
else
    echo "설정 파일을 찾을 수 없습니다: $CONFIG_FILE" >&2
    exit 1
fi

# 로깅 함수 정의
log_info() {
    echo "[INFO][$(date +'%Y-%m-%d %H:%M:%S')] $1" | tee -a /var/log/myapp.log
}

log_error() {
    echo "[ERROR][$(date +'%Y-%m-%d %H:%M:%S')] $1" | tee -a /var/log/myapp.log >&2
}

# 스크립트가 root 권한으로 실행되는지 확인
if [ "$EUID" -ne 0 ]; then
    log_error "이 스크립트는 root 권한이 필요합니다"
    exit 1
fi

# 임시 파일 사용 시 트랩으로 정리 보장
TEMP_FILE=$(mktemp)
trap "rm -f $TEMP_FILE" EXIT

# 명확한 변수명 사용
readonly MAX_RETRY_COUNT=3
readonly TIMEOUT_SECONDS=30

log_info "스크립트 실행 시작"

# 작업 수행
for i in $(seq 1 $MAX_RETRY_COUNT); do
    if perform_task; then
        log_info "작업 성공"
        break
    else
        log_error "작업 실패 (시도 $i/$MAX_RETRY_COUNT)"
        sleep 5
    fi
done

log_info "스크립트 실행 완료"

설명

이것이 하는 일: 이 코드는 실무에서 사용되는 프로덕션 수준의 스크립트 템플릿입니다. 에러가 발생하면 즉시 멈추고, 모든 동작을 로그에 기록하며, 예상치 못한 상황에도 안전하게 대응합니다.

마치 자동차의 에어백처럼 문제가 생겼을 때 피해를 최소화합니다. 첫 번째로, set -euo pipefail은 스크립트 안전성을 위한 세 가지 핵심 설정입니다.

set -e는 명령어가 실패하면 (0이 아닌 값을 반환하면) 즉시 스크립트를 중단합니다. set -u는 정의되지 않은 변수를 사용하면 에러를 발생시킵니다.

set -o pipefail은 파이프라인 중간에 에러가 발생해도 감지합니다. 예를 들어, cat file.txt | grep error에서 cat이 실패해도 grep이 성공하면 전체가 성공으로 처리되는데, pipefail을 설정하면 cat 실패를 감지합니다.

그 다음으로, 설정 파일을 별도로 분리하여 관리합니다. 데이터베이스 비밀번호, API 키 같은 민감 정보를 스크립트에 하드코딩하면 Git에 올라가거나 다른 사람에게 노출될 위험이 있습니다.

별도의 설정 파일로 분리하고 chmod 600으로 권한을 제한하면 보안이 강화됩니다. log_info와 log_error 함수를 정의하여 로그 형식을 통일하고, tee 명령으로 화면과 파일 모두에 기록합니다.

세 번째로, trap "rm -f $TEMP_FILE" EXIT는 스크립트가 어떤 이유로 종료되든 임시 파일을 자동으로 삭제합니다. 에러가 발생하거나 Ctrl+C로 중단해도 임시 파일이 남지 않습니다.

readonly를 사용하여 상수를 정의하면 실수로 값을 변경하는 것을 방지할 수 있습니다. MAX_RETRY_COUNT 같은 명확한 이름을 사용하면 코드를 읽는 사람이 즉시 의미를 이해할 수 있습니다.

마지막으로, 재시도 로직을 구현하여 일시적인 네트워크 오류 같은 문제를 자동으로 복구합니다. for i in $(seq 1 $MAX_RETRY_COUNT)는 최대 3번까지 시도하고, 각 시도 사이에 5초씩 대기합니다.

성공하면 break로 즉시 종료하고, 실패하면 로그를 남기고 다시 시도합니다. 여러분이 이런 베스트 프랙티스를 따르면 스크립트의 안정성이 크게 향상됩니다.

에러가 발생해도 로그를 보고 즉시 원인을 파악할 수 있고, 다른 사람이 코드를 봐도 쉽게 이해하고 수정할 수 있습니다. 초기에 조금 더 시간을 들여 제대로 작성하면 나중에 수십 배의 시간을 절약할 수 있습니다.

실전 팁

💡 ShellCheck 같은 린터를 사용하면 문법 오류와 잠재적 버그를 자동으로 찾아줍니다. VS Code나 vim에 통합하여 코드를 작성하면서 실시간으로 체크하세요.

💡 스크립트에 --help 옵션을 추가하여 사용법을 보여주세요. 몇 개월 후에 자신도 사용법을 까먹을 수 있습니다. getopts를 사용하여 명령행 인자를 파싱하면 더 전문적입니다.

💡 민감한 작업(삭제, 수정)을 하기 전에 --dry-run 옵션을 제공하여 실제로 실행하지 않고 무엇을 할지 미리 보여주세요. rsync의 -n 옵션처럼요.

💡 스크립트가 여러 번 동시에 실행되면 안 되는 경우 락 파일(lock file)을 사용하세요. flock을 사용하면 간단하게 구현할 수 있습니다.

💡 버전 관리와 변경 이력을 스크립트 상단 주석에 남기세요. "v1.2.0 - 2025-01-18 - 재시도 로직 추가" 같은 형식으로 작성하면 나중에 변경 사항을 추적하기 쉽습니다.


#Bash#Automation#Cron#Monitoring#Backup#Linux,Bash,Shell,자동화

댓글 (0)

댓글을 작성하려면 로그인이 필요합니다.