본문 바로가기
C.W.K.
Stream
Lesson 03 of 05 · published

임시로 쓰고, 확인하고, 제자리로

~12 min · staging, publish, atomicity

Level 0Finder 에서 헤매는 중
0 XP0/36 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete
"쓰다 만 파일한테 진짜 이름을 내주지 마. 검사 끝날 때까지 가명을 달아두고, 통과하면 그때 한 번에 이름을 줘."

목적지에 곧장 쓰면 생기는 문제

report.pdf 를 목적지 볼륨의 최종 경로에 바로 복사한다고 해보자. 절반쯤 갔을 때 볼륨이 빠져. 이제 정확히 맞는 자리에 report.pdf 라는 파일이 있는데, 잘려 있는 쓰레기야. 디스크만 봐선 완성된 복사본과 구별이 안 돼. 다음에 그걸 여는 사람도, 그걸 동기화하는 도구도 시체를 진짜로 믿게 되지. 목적지 이름에 곧장 쓰는 게 절반짜리를 멀쩡한 파일로 위장시키는 방법이야.

임시 이름은 검사 전의 가명

Waygate 는 목적지 볼륨에 작업 번호가 붙은 임시 이름으로 복사해. 최종 파일이 아닌 게 딱 봐도 보이는 이름으로. 복사하면서 계획이 요구하는 걸 같이 챙겨. 속성, 리소스 포크, 접근 권한, 확장 속성, 날짜까지. 그다음 임시본이 계획과 맞는지 확인하지. 그 확인을 통과하기 전까지 진짜 목적지 이름은 존재조차 안 해. 성공으로 착각할 게 아예 없는 거야.

이름은 한 번에 바뀌어

확인이 끝나야 Waygate 가 임시본을 진짜 목적지 이름으로 옮겨. 가능하면 같은 볼륨 안 이름 바꾸기로. 임시본과 목적지가 같은 볼륨에 있으니 그 이름 바꾸기엔 중간이 없어. 진짜 이름을 가졌거나 안 가졌거나지 절반은 없지. 진짜 이름이 나타나는 순간, 그 뒤의 파일은 이미 완전하고 확인까지 끝나 있어. 그 순간이 복사가 참이 되는 순간이야.

작업 번호가 붙은 임시 이름으로 복사하고, 확인하고, 같은 볼륨 이름 바꾸기로 제자리에 놔. 쓰다 만 파일이 진짜 목적지 이름을 차지하는 일이 없어. 임시 이름이 미완성본을 붙들고, 확인이 통과의 조건이고, 이름 바꾸기 덕에 진짜 이름은 내용이 이미 멀쩡할 때만 나타나.
임시본을 목적지 볼륨에 두는 게 요령이야. 임시본은 최종 목적지와 같은 볼륨에 있어야 해. 그래야 마지막 단계가 또 한 번의 볼륨 넘는 복사가 아니라 값싸고 중간 없는 이름 바꾸기가 되거든. 출발지 볼륨에 임시본을 두고 다시 복사하면, 임시본으로 없애려던 위험을 그대로 다시 들여오는 셈이야.

Code

작업 소유의 이름으로 쓰고, 확인하고, 한 번에 옮기기·swift
func copyThenPublish(_ src: URL, to dest: URL, _ plan: OperationPlan) async throws -> URL {
    // Staging item lives on the DESTINATION volume, named for the operation:
    let staging = dest.deletingLastPathComponent()
        .appendingPathComponent(".waygate-stage-\(plan.id)")

    try await copyPreservingMetadata(src, to: staging)   // forks, ACLs, xattrs, dates
    try await verify(staging, matches: plan.expectedMetadata)
    try await journal.mark(plan.id, .verified)

    // Same-volume rename -> effectively atomic. The real name appears
    // only now, and the file behind it is already complete + verified.
    try FileManager.default.moveItem(at: staging, to: dest)
    return dest
}
// A crash before the rename leaves only `.waygate-stage-<id>` -- an obviously
// incomplete artifact the journal owns, never a fake `report.pdf`.
가명, 그리고 이름을 얻는 순간·text
  during copy:   .waygate-stage-op_7a3f    <- obviously not the real file
  crash here?    only the staging item exists; report.pdf never appeared

  verify passes: bytes confirmed against the plan
  publish:       .waygate-stage-op_7a3f  --(atomic rename)-->  report.pdf

  after publish: report.pdf exists AND is already complete + verified.
                 There is no instant where report.pdf is half-written.

External links

Exercise

중간에 끊겨서 멀쩡해 보이지만 깨져 있던 다운로드를 떠올려봐. 잘린 영상이나 안 열리는 zip 같은 거. 그 다운로드를 임시 이름·확인·제자리 옮기기로 다시 설계해봐. 받는 동안엔 어떤 이름을 쓰고, 뭘 확인하고, 진짜 파일명은 언제 생겨? 왜 이 방식이면 진짜 이름에 깨진 파일이 남을 수 없어?
Hint
받는 동안엔 file.part 같은 이름을 쓰고, 다 받으면 크기나 체크섬을 확인하고, 그때 file 로 이름을 바꿔. 진짜 이름이 확인 뒤 이름 바꾸기로만 생기니까 중간에 끊기면 file.part 만 남아. 딱 봐도 미완성인 물건이고, 진짜 이름을 쓴 깨진 파일은 안 생겨. 그게 Waygate 가 하는 방식이야.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인 — 댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.