처리중입니다. 잠시만 기다려주세요.
TTJ 코딩클래스
정규반 단과 자료실 테크 뉴스 코딩 퀴즈
테크 뉴스
Hacker News 2026.04.27 23

Sloppy Copies: 파일 복사가 끝나도 끝난 게 아니라고요?

Hacker News 원문 보기
Sloppy Copies: 파일 복사가 끝나도 끝난 게 아니라고요?

복사 끝났다고 안심하면 안 되는 이유

터미널에서 cp 명령어로 큰 파일을 복사한 적 있으시죠? 명령어가 프롬프트로 돌아오면 우리는 자연스럽게 "아, 복사 끝났구나" 하고 다음 작업으로 넘어가요. 그런데 사실 이게 그렇게 단순한 이야기가 아니에요. 디스크에 진짜로 데이터가 안전하게 쓰였는지는 또 다른 문제거든요. 이번에 Mark Round라는 시스템 엔지니어가 자기 블로그에서 이 문제를 정리한 글을 올렸는데, 읽다 보면 "어, 진짜 그렇네" 하고 무릎을 치게 돼요.

현대 운영체제는 파일 입출력 성능을 높이기 위해 페이지 캐시(page cache)라는 걸 적극적으로 활용해요. 이게 뭐냐면, 디스크에 직접 쓰는 대신 일단 메모리(RAM)에 데이터를 모아두고, 나중에 적당한 타이밍에 한꺼번에 디스크에 기록하는 방식이에요. 그래야 디스크 헤드 움직임이나 SSD의 쓰기 횟수를 줄일 수 있고, 사용자가 보기에는 모든 작업이 빠르게 끝난 것처럼 느껴지거든요.

진짜 문제는 여기서 시작돼요

문제는 cp 명령이 "복사 끝났습니다" 하고 종료되는 시점이, 실제로 디스크에 모든 데이터가 안전하게 쓰인 시점이 아니라는 거예요. 정확히는 "커널의 페이지 캐시에 데이터를 다 넘겨줬습니다" 시점에서 끝나요. 그 다음에 페이지 캐시에서 디스크로 실제로 내려가는(flush) 작업은 백그라운드에서 천천히 진행되는 거죠.

평소에는 이게 별로 문제가 안 돼요. 잠시 후에 알아서 디스크에 다 써지니까요. 그런데 만약 그 짧은 사이에 정전이 일어나거나, 외장 디스크를 뽑거나, 시스템이 충돌하면 어떻게 될까요? 메모리에만 있던 데이터는 그대로 사라져요. 디스크에는 "파일은 만들어졌지만 내용은 비어있거나 일부만 쓰인 상태"로 남게 되는 거예요. 이게 바로 글 제목인 "Sloppy Copies(엉성한 복사)"의 뜻이에요.

글쓴이는 자기가 직접 겪은 사례를 소개해요. 외장 SSD에 큰 데이터셋을 백업하고 나서, cp 명령이 끝나자마자 SSD를 뽑았더니 며칠 뒤에 일부 파일이 깨져있는 걸 발견했다는 거죠. 분명히 복사는 끝났는데, 사실은 절반만 끝나있었던 거예요.

그럼 어떻게 해야 안전하게 복사할 수 있나

해결책은 의외로 단순해요. 복사 후에 명시적으로 sync 명령을 실행하거나, cp 대신 dd 명령에 conv=fsync 옵션을 붙이거나, rsync를 쓸 때 --fsync 옵션을 명시하는 거예요. fsync라는 시스템 콜이 "메모리에 있는 데이터를 지금 당장 디스크에 강제로 써주세요"라고 커널에 요청하는 함수거든요. 이게 끝나야 비로소 "진짜로 복사가 끝났다"고 말할 수 있어요.

또 하나의 방법은 외장 장치를 뺄 때 반드시 "안전하게 제거"를 거치는 거예요. 리눅스에서는 umount 명령으로 마운트를 해제하면 자동으로 모든 펜딩(pending) 쓰기가 처리되거든요. 맥OS의 "디스크 꺼내기"나 윈도우의 "하드웨어 안전하게 제거"도 같은 일을 하는 거예요. 우리가 귀찮아서 그냥 뽑는 그 행동이 사실은 데이터를 위태롭게 만드는 거였어요.

글쓴이는 더 깊이 들어가서, 파일 시스템에 따라 동작 방식도 다르다는 점을 짚어요. ext4는 기본적으로 data=ordered 모드라서 메타데이터와 실제 데이터의 쓰기 순서를 어느 정도 보장하지만, 그래도 fsync 없이는 완전한 보장이 안 돼요. ZFS나 btrfs 같은 카피 온 라이트(copy-on-write) 파일 시스템은 좀 더 안전하지만, 역시 fsync는 필요해요.

업계 맥락에서 보면

이 문제는 사실 데이터베이스 엔지니어들 사이에서는 오래된 고민이에요. PostgreSQL이 fsync 동작 방식 때문에 "fsyncgate"라는 큰 사건을 겪은 적도 있거든요. 2018년에 PostgreSQL 개발자들이 "리눅스의 fsync가 실패해도 우리는 그걸 제대로 감지할 수 없다"는 사실을 발견하고 패닉에 빠졌던 일이에요. DB 엔진들은 이런 문제 때문에 WAL(Write-Ahead Log)이나 체크섬 같은 방어 장치를 잔뜩 두고 있어요.

반면에 일반 사용자가 쓰는 cpmv 같은 도구는 이런 보장을 해주지 않아요. "빠른 게 우선"이라는 철학으로 만들어졌으니까요. 그래서 백업 도구를 만들 때는 반드시 fsync를 명시적으로 호출하는 게 상식이에요. borgbackup이나 restic 같은 도구들이 그래서 신뢰받는 거고요.

한국 개발자에게 주는 시사점

실무에서 백업 스크립트를 만드는 분들이라면, 단순히 cp -r 한 줄로 끝내지 마시고 마지막에 sync를 꼭 추가해주세요. 한 줄 추가하는 게 별 거 아닌 것 같아도, 정전이나 USB 분리 사고 한 번에 며칠치 데이터를 잃을 수 있거든요. 특히 외장 디스크에 백업하는 워크플로우가 있다면 더더욱이요.

서버 환경에서도 마찬가지예요. CI/CD에서 빌드 산출물을 다른 디렉터리로 옮길 때, 그 사이에 컨테이너가 종료되면 산출물이 깨질 수 있어요. "빌드는 성공했는데 배포된 파일이 이상하다"는 미스터리한 버그가 알고 보면 이런 문제일 수도 있는 거죠.

마무리

핵심 한 줄: cp가 끝나도 디스크에 다 쓰인 건 아니다. 진짜 안전하려면 fsyncsync를 명시적으로 호출해야 한다.

여러분은 외장 디스크를 뽑을 때 "안전하게 제거"를 꼬박꼬박 누르시나요, 아니면 그냥 뽑으시나요? 데이터 날려본 경험이 있다면 어떤 상황이었는지 댓글로 공유해주세요!


🔗 출처: Hacker News

이 뉴스가 유용했나요?

TTJ 코딩클래스 정규반

월급 외 수입,
코딩으로 만들 수 있습니다

17가지 수익 모델을 직접 실습하고, 1,300만원 상당의 자동화 도구와 소스코드를 받아가세요.

144+실전 강의
17개수익 모델
4.9수강생 평점
정규반 자세히 보기

"비전공 직장인인데 반년 만에 수익 파이프라인을 여러 개 만들었습니다"

실제 수강생 후기
  • 비전공자도 6개월이면 첫 수익
  • 20년 경력 개발자 직강
  • 자동화 프로그램 + 소스코드 제공

매일 AI·개발 뉴스를 받아보세요

주요 테크 뉴스를 매일 아침 이메일로 전해드립니다.

스팸 없이, 언제든 구독 취소 가능합니다.