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

경로는 신분증이 아냐

~13 min · identity, bookmarks, revalidation

Level 0Finder 에서 헤매는 중
0 XP0/36 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete
"/Users/you/report.pdf 는 주소지 사람이 아냐. 주소는 다른 사람한테 넘어가."

같은 경로, 다른 파일

순진한 파일 관리자를 잡아먹는 버그가 이거야. 파일 한 줄을 화면에 그려. 사용자가 잠깐 딴 데를 봐. 그사이 다른 프로그램이 그 파일을 지우고, 아무 상관 없는 새 파일을 똑같은 자리에 똑같은 이름으로 써. 사용자가 그 줄에서 '휴지통으로' 를 눌러. 앱이 경로 문자열로 대상을 찾았다면, 사용자가 본 적도 없는 파일을 방금 버린 거야. 경로는 같았지만 파일은 달랐지.

신분증은 북마크와 리소스 ID 야

macOS 는 경로보다 나은 손잡이를 줘. 북마크는 이름이 바뀌거나 파일이 옮겨져도 따라갈 수 있는 참조야. 리소스 식별자는 이름이 아니라 파일 자체에 붙고. Waygate 는 둘을 LocationReference 로 묶어 신분증으로 써. 경로 문자열은 사람 눈에 보여줄 힌트, 그리고 정말 다른 수가 없을 때의 마지막 수단으로만 남겨두고.

손대기 직전에 다시 대조해

좋은 신분증을 들고 있는 건 절반이야. 나머지 절반은 이거야. 파일을 바꾸기 직전에 Waygate 는 다시 대조해. 참조를 지금 파일시스템에 풀어보고, 볼륨이 그 볼륨인지, 파일이 그 파일인지, 전제가 아직 맞는지 확인하지. 그러고 나서야 작업이 진행돼. 같은 파일로 안 풀리는 경로는 실행되지 않고 표시만 남아.

경로 문자열만으로는 아무것도 못 바꿔. Waygate 는 북마크와 리소스 식별자를 신분증으로 들고, 실행 직전에 살아 있는 URL 과 볼륨과 전제를 다시 확인해. 줄에 보이는 이름은 사람 보라고 있는 거지 엔진이 잡는 손잡이가 아니야.
재활용된 경로에 떨어지는 삭제. 파일 도구에서 제일 고약한 데이터 손실은 화면에 보여준 것과 다른 파일을 가리키게 된 경로에 손을 대는 거야. SMB 나 외장 볼륨이면 더 심해. 공유가 다시 붙을 때 신분이 흔들리거든. 다시 대조하지 않는 작업은 운 나쁜 타이밍 하나만 만나면 엉뚱한 파일을 버려.

Code

LocationReference: 경로 말고 신분·swift
struct LocationReference {
    let bookmarkData: Data          // survives rename / move where possible
    let resourceID: String?         // ties to the file object, not the name
    let volumeID: String?           // which volume this identity belongs to
    let displayPath: String         // for humans + last-resort fallback ONLY
}

// Before a mutation, resolve and confirm identity still holds:
func revalidate(_ ref: LocationReference) throws -> URL {
    var stale = false
    let url = try URL(resolvingBookmarkData: ref.bookmarkData,
                      options: [], relativeTo: nil,
                      bookmarkDataIsStale: &stale)
    let values = try url.resourceValues(forKeys: [.fileResourceIdentifierKey,
                                                  .volumeIdentifierKey])
    guard matches(values, ref) else { throw OpError.identityChanged }
    return url   // safe to act on THIS url, now
}
경로만 믿으면 벌어지는 일·text
  t0: row shows  report.pdf   (file A, the one the user sees)
  t1: another process deletes A, writes B to the SAME path
  t2: user clicks 'Move to Trash' on the row

  PATH-BASED app:  trashes whatever is at the path now  -> trashes B (wrong!)
  WAYGATE:         revalidates identity, sees A is gone  -> stops, flags it

  Same string. Different file. Only identity tells them apart.

External links

Exercise

재활용된 경로 때문에 파일을 잃는 과정을 네 말로 적어봐. 파일을 화면에 보여줬고, 그 자리가 다른 파일로 채워졌고, 사용자가 눌렀다. 그다음 이걸 막는 검사 하나를 말해봐. 왜 '이 경로에 파일 있어?' 로는 못 막아? 대신 뭘 비교해야 해?
Hint
'파일 있어?' 는 엉뚱한 파일한테도 있다고 답해. 그게 함정 전체야. 던져야 할 질문은 '여기 있는 게 내가 보여준 그 파일 맞아?' 고, 그러려면 존재 여부가 아니라 신분을 비교해야 해. 있는 것과 같은 것은 다른 얘기니까.

Progress

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

댓글 0

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

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