콘텐츠로 이동

대량 파일 전송 가이드 (rsync 활용)

NAS 간에 수백만 개의 파일을 전송해야 할 때, 특히 운영 중인 서버에서 시스템 부하(I/O)를 최소화하면서 안전하게 옮기는 방법을 다룹니다.


1. rsync를 선택하는 이유

cpmv 명령어는 대량 파일 작업 시 네트워크 단절이나 시스템 중단에 취약하며, 현재 진행 상태를 알기 어렵습니다. 반면 rsync는 다음과 같은 장점이 있습니다.

  • 증분 전송: 변경된 부분이나 누락된 파일만 골라서 전송 가능 (중단 후 재시작 시 매우 유리).
  • 부하 조절: 대역폭 제한(--bwlimit) 및 I/O 우선순위 조절 가능.
  • 무결성 검사: 체크섬을 통해 데이터가 정확히 복사되었는지 확인 가능.

2. 실전 전송 시나리오

상황: /A/20260318 폴더를 /B 아래로 복사하여 최종적으로 /B/20260318 구조를 만듦.

2.1 I/O 부하 최소화 핵심 명령어

ionice -c 3 rsync -avh --bwlimit=10000 --info=progress2 /A/20260318 /B/

2.2 주요 옵션 설명

  • ionice -c 3: 이 프로세스의 I/O 우선순위를 'Idle'로 설정합니다. 다른 프로세스가 디스크를 쓰지 않을 때만 작업을 수행하므로 운영 중인 서비스에 미치는 영향을 최소화합니다.
  • -a (archive): 권한, 심볼릭 링크, 수정 시간 등 모든 속성을 유지하며 복사합니다.
  • --bwlimit=10000: 전송 대역폭을 초당 10,000KB(약 10MB/s)로 제한합니다. 네트워크 및 디스크 I/O가 폭주하는 것을 방지합니다.
  • --info=progress2: 개별 파일 목록 대신 전체 진행률, 전송 속도, 예상 소요 시간을 한 줄로 요약해서 보여줍니다. 대량 파일 작업 시 로그가 지저분해지는 것을 방지합니다.
  • /A/20260318 vs /A/20260318/:
    • 끝에 슬래시(/)가 없으면: 20260318 폴더 자체를 복사합니다. (결과: /B/20260318/...)
    • 끝에 슬래시(/)가 있으면: 폴더 내부의 내용물만 복사합니다. (결과: /B/...)

3. 실전 전송 스크립트 (run.sh)

100만 개 이상의 대량 파일을 안전하게 옮기기 위한 쉘 스크립트입니다. 스크립트 내부에서 nohup을 쓰지 않고, 실행 시 nohup으로 감싸서 돌리는 것이 프로세스 관리에 더 유리합니다.

#!/bin/bash

# [설정] 원본 및 대상 경로 (끝에 슬래시 제외)
SOURCE="/A/20260318"
DEST="/B"
LOG_FILE="rsync_transfer.log"

# 1. 원본 디렉토리 존재 확인
if [ ! -d "$SOURCE" ]; then
    echo "ERROR: Source directory $SOURCE does not exist."
    exit 1
fi

echo "Transfer started at: $(date)"
echo "Source: $SOURCE"
echo "Destination: $DEST"

# 2. rsync 실행
# ionice -c 3: I/O 우선순위 최하위(Idle)
# nice -n 19: CPU 우선순위 최하위
# --info=progress2: 전체 진행률 요약 출력
# --append-verify: 중단된 지점부터 데이터 이어받기
ionice -c 3 nice -n 19 rsync -ah \
    --partial \
    --append-verify \
    --inplace \
    --info=progress2 \
    --bwlimit=20000 \
    "$SOURCE" "$DEST"

echo "Transfer finished at: $(date)"

3.1 실행 방법 (Background)

스크립트에 실행 권한을 준 뒤, nohup을 사용하여 백그라운드에서 실행합니다.

# 1. 실행 권한 부여
chmod +x run.sh

# 2. 백그라운드 실행
nohup ./run.sh > rsync_transfer.log 2>&1 &

# 3. 진행 상황 확인
tail -f rsync_transfer.log

4. 작업 상황 및 무결성 확인

4.1 실시간 진행 상황 확인

백그라운드에서 실행 중인 경우 다음 명령어로 현재 진행률을 확인할 수 있습니다.

tail -f rsync_transfer.log

4.2 결과 검증

전송이 끝난 후 원본과 대상의 파일 개수가 일치하는지 확인합니다.

# 파일 개수 비교
find /A/20260318 -type f | wc -l
find /B/20260318 -type f | wc -l

# 용량 비교
du -sh /A/20260318
du -sh /B/20260318


5. 작업 중단 및 재개 (Resume)

대량 전송 중 네트워크 문제나 수동 취소로 작업이 중단되어도 rsync는 위 스크립트를 다시 실행하는 것만으로 중단된 지점부터 다시 시작할 수 있습니다. 이미 완료된 파일은 자동으로 건너뛰며, 전송 중이던 파일은 --append-verify 옵션 덕분에 데이터 조각 단위로 이어서 전송됩니다.


6. 성능 최적화 튜닝 (Performance Tuning)

전송 속도가 너무 느리다면 아래 옵션들을 조정하여 성능을 대폭 끌어올릴 수 있습니다.

6.1 제한 옵션 완화

  • I/O 우선순위: ionice -c 3ionice -c 2 -n 7로 변경하세요. (완전 대기 모드에서 '낮은 우선순위 실행' 모드로 전환)
  • 대역폭 제한: --bwlimit 옵션을 제거하여 네트워크 최대 대역폭을 사용하세요.

6.2 전송 방식 최적화

  • -W (--whole-file): 파일의 변경된 블록을 계산하는 로직을 끄고 파일 전체를 복사합니다. 네트워크 속도가 빠를 때(LAN, 전용선 등) CPU 부하를 줄이고 속도를 높이는 핵심 옵션입니다.
  • --inplace: 대량 파일 작업 시 대상지에 임시 파일을 만들지 않고 즉시 덮어써서 파일 시스템 오버헤드를 줄입니다. (이미 적용 중)

6.3 튜닝된 고성능 스크립트 예시

# 성능 위주 설정 (운영 부하보다 속도가 중요할 때)
ionice -c 2 -n 7 nice -n 10 rsync -avhW \
    --partial \
    --inplace \
    --info=progress2 \
    "$SOURCE" "$DEST"

7. 시스템 부하 분석 (System Load Analysis)

대량 파일 전송 시 부하가 발생하는 지점을 이해하면 운영 중인 서비스의 장애를 방지할 수 있습니다.

7.1 명령 실행 서버 (Client)

  • CPU: rsync 프로세스가 파일 목록 스캔 및 메타데이터 비교 연산 수행.
  • Memory: 전송할 파일의 개수에 비례하여 메모리 점유율 증가 (100만 개 이상 시 수백 MB 이상 소모 가능).
  • Network: 실제 데이터가 실행 서버의 네트워크 카드를 거쳐가므로 대역폭 점유 발생.

7.2 스토리지 서버 (NAS)

  • Disk I/O: 수많은 작은 파일을 읽고 쓰는 과정에서 디스크 헤드 부하 및 IOPS 증가.
  • Network: 스토리지 대역폭 소모.

8. 용량 불일치 트러블슈팅 (Troubleshooting Size Discrepancy)

파일 개수는 일치하는데 du -sh 결과가 원본보다 큰 경우, 아래 원인들을 점검하세요.

8.1 주요 원인

  • 블록 사이즈 차이: 스토리지 간 최소 저장 단위(Block Size)가 다르면 작은 파일이 많을수록 용량 차이가 커집니다.
  • 스파스 파일(Sparse File): 내부가 0으로 채워진 파일이 전송 과정에서 실제 데이터로 채워지며 용량이 팽창할 수 있습니다.
  • 하드 링크: -H 옵션 없이 전송할 경우, 하드 링크가 각각의 일반 파일로 복사되어 용량이 늘어납니다.

8.2 정확한 비교 방법

물리적 점유 공간(du) 대신 순수 데이터의 합을 비교하려면 아래 명령어를 사용하세요.

# 원본과 대상에서 각각 실행하여 실제 파일 크기의 합산 비교
find /경로 -type f -printf "%s\n" | awk '{s+=$1} END {print s}'

8.3 해결을 위한 rsync 옵션 보완

위 현상들을 방지하려면 아래 옵션을 추가하여 다시 실행하세요.

  • -S (--sparse): 스파스 파일을 효율적으로 처리하여 용량 팽창 방지.
  • -H (--hard-links): 하드 링크 구조를 그대로 유지.

9. 디렉토리 병합 및 데이터 통합 (Directory Merging)

서로 다른 스토리지에 분산된 동일 날짜의 데이터를 하나로 합쳐야 할 때 rsync를 활용하는 방법입니다.

9.1 기본 병합 메커니즘

rsync는 기본적으로 '덮어쓰기'가 아닌 '동기화'를 수행합니다. 대상 경로에 동일한 이름의 디렉토리가 이미 존재하더라도, 이를 삭제하고 새로 만드는 것이 아니라 내부의 파일들을 비교하여 누락된 파일만 채워 넣는(Merge) 방식으로 동작합니다.

9.2 실전 명령어 (합집합 만들기)

/NAS_A/20260304의 내용을 /NAS_B/20260304로 합칠 때:

# 주의: 목적지 경로 끝에 20260304를 명시하거나, 원본 경로 끝에 /를 붙여야 함
rsync -av --info=progress2 /NAS_A/20260304/ /NAS_B/20260304/
  • 결과: NAS_B의 기존 파일은 유지되면서, NAS_A에만 있던 새로운 파일들이 추가됩니다.
  • 주의: --delete 옵션을 절대 사용하지 마세요. 이 옵션을 넣으면 NAS_A에 없는 파일이 NAS_B에서 삭제되어 데이터가 손실될 수 있습니다.

9.3 경로 지정의 중요성 (Trailing Slash)

  • rsync -av /src/ /dest/: src 내부의 내용물dest 안으로 합칩니다. (병합 시 권장)
  • rsync -av /src /dest: src 폴더 자체dest 아래로 복사합니다. (결과가 /dest/src/... 가 됨)