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

지키거나, 시끄럽게 실패하거나

~12 min · metadata, preservation, fail-loud

Level 0Finder 에서 헤매는 중
0 XP0/36 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete
"태그와 권한과 만든 날짜를 조용히 흘린 복사는 파일을 복사한 게 아니야. 내용만 옮기고 나머지를 잃은 거지."

파일은 내용만이 아니야

파일을 복사한다고 하면 보통 데이터를 떠올려. 그런데 macOS 파일은 꽤 많은 걸 달고 다녀. 만든 날짜와 고친 날짜, 접근 권한과 세부 권한 목록, 확장 속성, Finder 태그와 색 라벨, 리소스 포크, 격리 표시. 데이터만 옮기고 이걸 다 흘린 '복사' 는 파일을 조용히 망가뜨린 거야. 정리에 쓰던 태그가 사라지고, 지켜주던 권한이 어긋나고, 만든 날짜가 오늘이 되지. 그런데 아무도 안 알려줘.

지키고, 지켰는지 시험하고

Waygate 는 이걸 통째로 챙기는 방식으로 복사하고, 실제로 지켜졌는지 시험까지 해둬. 복사된 파일의 권한 목록과 확장 속성, 태그, 리소스 포크, 날짜가 살아남았는지 확인하는 시험 말이야. 그냥 그러려니 하는 게 아니라 시험 파일 묶음에 대고 확인해. 그래야 확장 속성을 흘리기 시작한 변화가, 몇 주 뒤 사용자가 태그 사라진 걸 발견하는 게 아니라 실패한 시험으로 잡히거든.

못 지킬 땐 그렇다고 말해

목적지가 전부를 담을 수 없을 때도 있어. 확장 속성이나 리소스 포크를 지원 안 하는 파일시스템으로 복사할 때처럼. 그럼 규칙은 하나야. 지원 안 되는 건 눈에 보이는 경고나 실패로 알리지, 조용히 흘리지 않는다. Waygate 는 태그를 버린 복사를 말없이 끝내느니 '이 목적지는 Finder 태그를 못 지켜' 라고 말하고 멈춰. 조용한 손실은 믿을 만한 파일 관리자가 절대 내놓으면 안 되는 결과야. 자잘한 경우도 제대로 다뤄. 대소문자만 바꾸는 이름 변경은 대소문자를 구분 안 하는 볼륨에선 기록을 남기며 임시 이름을 한 번 거치고, 장치 노드 같은 특수 파일은 다룰 방법을 정하기 전엔 거절해.

속성은 시험까지 붙여서 지키고, 못 지키는 건 시끄럽게 실패해. 조용히 흘리지 않아. 권한 목록, 확장 속성, Finder 태그, 리소스 포크, 날짜가 시험 대상이야. 목적지가 뭔가 못 담으면 Waygate 는 조용히 버리는 대신 눈에 보이는 경고나 실패로 알려.
트랙 클리어. 부하 속에서도 살아 있고 정확해. 메인 스레드 밖 I/O, 서로 맞춘 접근, 조심하는 순회, 실수로 안 받는 클라우드, 그리고 지키거나 시끄럽게 실패하는 속성. 이 트랙이 있어서 Waygate 는 패키지와 심링크와 클라우드 파일이 뒤섞인 느린 SMB 공유에서도 쓸 만해. 다른 파일 관리자들이 얼어붙거나 조용히 망가뜨리는 바로 그 조건에서. 다음은 네트워크와 비밀번호가 어디 있어야 하는지.

Code

통째로 복사하고, 살아남았는지 확인하기·swift
import Darwin

func copyPreservingMetadata(_ src: URL, to dst: URL) throws {
    // copyfile with COPYFILE_ALL preserves data + metadata + xattrs + ACLs:
    let state = copyfile_state_alloc()
    defer { copyfile_state_free(state) }
    let flags = copyfile_flags_t(COPYFILE_ALL | COPYFILE_NOFOLLOW)
    guard copyfile(src.path, dst.path, state, flags) == 0 else {
        throw OpError.copyFailed(errno: errno)
    }
    // Then VERIFY the metadata actually landed (a preservation test):
    let srcVals = try src.resourceValues(forKeys: [.creationDateKey, .tagNamesKey])
    let dstVals = try dst.resourceValues(forKeys: [.creationDateKey, .tagNamesKey])
    guard srcVals.creationDate == dstVals.creationDate,
          srcVals.tagNames == dstVals.tagNames else {
        throw OpError.metadataNotPreserved   // fail LOUD, don't ship silent loss
    }
}

External links

Exercise

Finder 에서 파일에 색과 키워드로 태그를 달고 만든 날짜도 손본 다음, 간단한 도구로 복사해서 사본을 들여다봐. 뭐가 살아남았고 뭐가 사라졌어? 이제 '시끄럽게 실패' 를 설계해봐. 복사가 태그를 못 지킬 때 앱이 정확히 뭘 보여줘야 하고, 왜 조용한 성공보다 경고가 훨씬 나은지 말해봐.
Hint
간단한 복사는 도구와 목적지에 따라 날짜와 권한은 지켜도 Finder 태그나 리소스 포크는 흘리는 경우가 많아. 조용한 성공은 실은 정리 체계를 망가뜨린 복사를 믿게 만들어. 몇 주 뒤 태그 검색이 비어 나올 때 알게 되지. 경고는 '이 목적지는 태그를 못 지켜' 라고 지금 말해줘서, 뭘 잃는지 기억하고 있을 때 고르게 해. 데이터가 걸린 일은 늘 시끄러운 쪽이 나아.

Progress

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

댓글 0

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

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