# 서버 환경에서의 데이터 백업 가이드

## 개요
이 가이드는 서버 환경에서 데이터를 효율적으로 백업하고 관리하는 방법을 설명합니다. 특히 Docker와 같은 컨테이너 환경을 운영하는 서버에서 안정적인 백업 시스템을 구축할 수 있도록 다양한 백업 전략과 자동화 스크립트 예제를 제공합니다.

## 목차
1. [백업 전략](#백업-전략)
2. [디렉토리 구조 및 설정](#디렉토리-구조-및-설정)
3. [증분 백업 구현](#증분-백업-구현)
4. [백업 자동화](#백업-자동화)
5. [원격 서버로 백업 전송](#원격-서버로-백업-전송)
6. [백업 로테이션 및 관리](#백업-로테이션-및-관리)
7. [예제 스크립트](#예제-스크립트)

## 백업 전략
서버 환경에서는 다음과 같은 항목들을 백업해야 합니다:

- 애플리케이션 데이터 (웹 애플리케이션 데이터, 사용자 업로드 파일 등)
- 서버 설정 파일 (nginx, apache 설정 등)
- Docker 관련 데이터 (docker-compose.yml, Dockerfile, 볼륨 데이터 등)
- 데이터베이스 백업 파일

백업 주기는 데이터의 중요도와 변경 빈도에 따라 결정해야 합니다:
- 중요 데이터: 일일 백업
- 설정 파일: 변경 시마다 백업
- 전체 시스템: 주간 또는 월간 백업

## 디렉토리 구조 및 설정

효율적인 백업을 위한 디렉토리 구조 예시:

```
/data/
  ├── backup/
  │   ├── source/       # 원본 백업 저장
  │   ├── compress/     # 압축된 백업 파일
  │   └── mirror/       # 미러링 백업 저장 (연도별/월별)
  ├── webapps/          # 웹 애플리케이션 디렉토리
  └── upload/           # 업로드 파일 디렉토리
```

백업 디렉토리 초기 설정:

```bash
#!/bin/bash

BACKUP_DIR="/data/backup"
SOURCE_DIR="/data/webapps"
UPLOAD_DIR="/data/upload"
BACKUP_SOURCE_PATH="${BACKUP_DIR}/source"
BACKUP_COMPRESS_DIR="${BACKUP_DIR}/compress"
BACKUP_MIRROR_DIR="${BACKUP_DIR}/mirror"

# 필요한 디렉토리 생성
mkdir -p "${BACKUP_SOURCE_PATH}"
mkdir -p "${BACKUP_COMPRESS_DIR}"
mkdir -p "${BACKUP_MIRROR_DIR}"
```

## 증분 백업 구현

rsync를 이용한 증분 백업 구현:

```bash
#!/bin/bash

SOURCE_DIR="/data/webapps"
BACKUP_DIR="/data/backup"
BACKUP_SOURCE_PATH="${BACKUP_DIR}/source"
LATEST_LINK="${BACKUP_DIR}/latest"

# rsync를 이용한 증분 백업
rsync -av --delete \
  "${SOURCE_DIR}/" \
  --link-dest "${LATEST_LINK}" \
  --exclude=".cache" \
  "${BACKUP_SOURCE_PATH}"

# 심볼릭 링크 업데이트
rm -rf "${LATEST_LINK}"
ln -s "${BACKUP_SOURCE_PATH}" "${LATEST_LINK}"
```

## 백업 자동화

### Cron을 이용한 자동화
아래와 같이 crontab을 설정하여 백업을 자동화할 수 있습니다:

```
# 매일 오전 3시에 백업 실행
0 3 * * * /path/to/daily_backup_script.sh

# 매주 일요일 오전 2시에 백업 실행
0 2 * * 0 /path/to/weekly_backup_script.sh

# 매월 마지막 날 오전 1시에 백업 실행
0 1 28-31 * * [ "$(date -d '+1 day' +\%d)" -eq "1" ] && /path/to/monthly_backup_script.sh
```

### 월말 체크 스크립트
월의 마지막 날에만 실행할 작업을 위한 스크립트:

```bash
#!/bin/bash

TODAY=$(date +%d)
TOMORROW=$(date -d "1 day" +%d)

# 내일의 날짜가 오늘보다 작으면 월의 마지막 날
if [ $TOMORROW -lt $TODAY ]; then
    # 월말 백업 작업 실행
    /path/to/monthly_backup.sh
    exit 0
fi

exit 1
```

## 원격 서버로 백업 전송

### rsync를 이용한 백업 전송
```bash
rsync -avz --delete /data/backup/compress/ user@remote-server:/remote/backup/directory/
```

### lftp를 이용한 FTP 전송
```bash
lftp -c "open -u username,password ftp-server -p 21; mirror -R /data/backup/mirror /remote/directory"
```

실제 예제(비밀번호 보안 주의):
```bash
lftp -c "open -u admin,password 118.45.160.139 -p 2121; mirror -R /data/backup/mirror /homes/java/203"
```

### 암호화된 백업 전송
민감한 데이터를 안전하게 전송하기 위한 암호화 방법:

```bash
# 백업 파일 암호화
tar -czf - /data/backup/source | gpg -e -r recipient@email.com > backup-$(date +%Y%m%d).tar.gz.gpg

# 암호화된 백업 파일 전송
scp backup-$(date +%Y%m%d).tar.gz.gpg user@remote-server:/remote/backup/directory/
```

## 백업 로테이션 및 관리

### 월별 백업 로테이션 구현
오래된 백업을 자동으로 삭제하고 새 백업을 유지하는 로테이션 시스템:

```bash
#!/bin/bash
set -o errexit
set -o nounset
set -o pipefail

# 백업 디렉토리 설정
BACKUP_DIR="/data/backup"
MIRROR_DIR="/data/backup/mirror/$(date +%Y%m)"
MIRROR_CHECK_DIR="/data/backup/mirror/$(date -d "-6 month" +%Y%m)"

# 필요한 디렉토리 생성
if [ ! -d "${MIRROR_DIR}" ]; then
    mkdir -p "${MIRROR_DIR}"
fi

# 6개월 이상 지난 백업 삭제
if [ -d "${MIRROR_CHECK_DIR}" ]; then
    rm -rf "${MIRROR_CHECK_DIR}"
fi

# 압축 백업 파일을 월별 디렉토리로 복사
cp -R /data/backup/compress/* "${MIRROR_DIR}"
```

### Docker 볼륨 데이터 백업
Docker 볼륨 데이터를 외부에서 백업하는 방법:

```bash
# Docker 볼륨 데이터 위치 (일반적으로 /var/lib/docker/volumes/)
DOCKER_VOLUME_PATH="/var/lib/docker/volumes"
BACKUP_PATH="/data/backup/docker_volumes"

# 백업 디렉토리 생성
mkdir -p "${BACKUP_PATH}"

# Docker 볼륨 데이터 백업
tar -czf "${BACKUP_PATH}/docker_volumes-$(date +%Y%m%d).tar.gz" -C "${DOCKER_VOLUME_PATH}" .
```

## 예제 스크립트

### 소스 코드 및 업로드 파일 백업 스크립트
```bash
#!/bin/bash
set -o errexit
set -o nounset
set -o pipefail

BACKUP_DIR=""
SOURCE_DIR_UPLOAD=""
SOURCE_DIR_WEBAPPS=""
BACKUP_COMPRESS_DIR=""
BACKUP_UPLOAD_PATH=""
BACKUP_WEBAPPS_PATH=""
UPLOAD_TARGET=""
WEBAPPS_TARGET=""
LATEST_UPLOAD_LINK=""
LATEST_WEBAPPS_LINK=""
SOURCE_DIR_UPLOAD="/data/upload"
SOURCE_DIR_WEBAPPS="/data/webapps"
BACKUP_DIR="/data/backup"
BACKUP_UPLOAD_PATH="${BACKUP_DIR}/upload/source"
BACKUP_WEBAPPS_PATH="${BACKUP_DIR}/webapps/source"
BACKUP_COMPRESS_DIR="${BACKUP_DIR}/compress"
UPLOAD_TARGET="${BACKUP_COMPRESS_DIR}/upload.tar.gz"
WEBAPPS_TARGET="${BACKUP_COMPRESS_DIR}/webapps.tar.gz"
LATEST_UPLOAD_LINK="${BACKUP_DIR}/upload/latest"
LATEST_WEBAPPS_LINK="${BACKUP_DIR}/webapps/latest"

# 필요한 디렉토리 생성
if [ ! -d "${BACKUP_DIR}" ]; then mkdir -p "${BACKUP_DIR}"; fi
if [ ! -d "${BACKUP_UPLOAD_PATH}" ]; then mkdir -p "${BACKUP_UPLOAD_PATH}"; fi
if [ ! -d "${BACKUP_WEBAPPS_PATH}" ]; then mkdir -p "${BACKUP_WEBAPPS_PATH}"; fi
if [ ! -d "${BACKUP_COMPRESS_DIR}" ]; then mkdir -p "${BACKUP_COMPRESS_DIR}"; fi

# rsync를 이용한 증분 백업 (업로드 디렉토리)
rsync -av --delete \
  "${SOURCE_DIR_UPLOAD}/" \
  --link-dest "${LATEST_UPLOAD_LINK}" \
  --exclude=".cache" \
  "${BACKUP_UPLOAD_PATH}"

# rsync를 이용한 증분 백업 (웹앱 디렉토리)
rsync -av --delete \
  "${SOURCE_DIR_WEBAPPS}/" \
  --link-dest "${LATEST_WEBAPPS_LINK}" \
  --exclude=".cache" \
  "${BACKUP_WEBAPPS_PATH}"

# 심볼릭 링크 업데이트 및 압축
rm -rf "${LATEST_UPLOAD_LINK}"
rm -rf "${UPLOAD_TARGET}"
rm -rf "${LATEST_WEBAPPS_LINK}"
rm -rf "${WEBAPPS_TARGET}"
ln -s "${BACKUP_UPLOAD_PATH}" "${LATEST_UPLOAD_LINK}"
ln -s "${BACKUP_WEBAPPS_PATH}" "${LATEST_WEBAPPS_LINK}"
tar -cf "${UPLOAD_TARGET}" "${BACKUP_UPLOAD_PATH}"
tar -cf "${WEBAPPS_TARGET}" "${BACKUP_WEBAPPS_PATH}"
```

### 미러링 백업 및 원격 전송 스크립트
```bash
#!/bin/bash
set -o errexit
set -o nounset
set -o pipefail

# 백업 디렉토리 설정
MIRROR_DIR="/data/backup/mirror/$(date +%Y%m)"
MIRROR_CHECK_DIR="/data/backup/mirror/$(date -d "-6 month" +%Y%m)"

# 필요한 디렉토리 생성
if [ ! -d "${MIRROR_DIR}" ]; then
    mkdir -p "${MIRROR_DIR}"
fi

# 6개월 이상 지난 백업 삭제
if [ -d "${MIRROR_CHECK_DIR}" ]; then
    rm -rf "${MIRROR_CHECK_DIR}"
fi

# 압축 백업 파일을 월별 디렉토리로 복사
cp -R /data/backup/compress/* "${MIRROR_DIR}"

# 원격 FTP 서버로 백업 파일 전송
lftp -c "open -u username,password remote-ftp-server -p 2121; mirror -R /data/backup/mirror /remote/directory"
```

### 데이터베이스 백업 스크립트 (MySQL/MariaDB)
```bash
#!/bin/bash
set -o errexit
set -o nounset
set -o pipefail

# 데이터베이스 접속 정보
DB_USER="dbuser"
DB_PASS="dbpassword"
DB_NAME="dbname"
BACKUP_DIR="/data/backup/database"
BACKUP_FILE="${BACKUP_DIR}/mysql-$(date +%Y%m%d).sql.gz"

# 백업 디렉토리 생성
mkdir -p "${BACKUP_DIR}"

# MySQL 데이터베이스 백업
mysqldump -u "${DB_USER}" -p"${DB_PASS}" "${DB_NAME}" | gzip > "${BACKUP_FILE}"

# 30일 이상 지난 백업 파일 삭제
find "${BACKUP_DIR}" -name "mysql-*.sql.gz" -type f -mtime +30 -delete
```

## 결론
서버 환경에서 데이터 백업은 시스템의 안정성과 지속성을 보장하는 중요한 작업입니다. 이 가이드에서 제공하는 방법과 스크립트를 활용하여 체계적인 백업 시스템을 구축하고, 정기적인 테스트를 통해 복원 과정이 원활하게 작동하는지 확인하세요.

효율적인 백업 시스템을 위한 핵심 원칙:
- 자동화된 백업 스크립트 구현
- 주기적인 백업 수행 (일간, 주간, 월간)
- 다중 백업 위치 활용 (로컬 및 원격)
- 백업 로테이션 시스템 도입 (오래된 백업 자동 삭제)
- 데이터 복원 테스트 정기적 수행

중요한 데이터는 항상 여러 위치에 분산 저장하고, 백업 프로세스를 자동화하여 인적 오류를 최소화하는 것을 권장합니다. 