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

파일을 만지는 문은 하나

~12 min · one-boundary, engine, architecture

Level 0Finder 에서 헤매는 중
0 XP0/36 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete
"파일 옮기는 방법이 열 가지면 잃는 방법도 열 가지야. Waygate 엔 딱 하나 있어."

막아야 할 난립

앱이 자라는 자연스러운 모습을 떠올려봐. 툴바의 이동 버튼이 moveItem 을 불러. 드래그도 조금 다르게 부르고. 이름 일괄 변경은 자기 반복문을 돌리고. 선택 바구니는 또 자기 복사를 하지. 다들 다른 날 다른 사람이 짰고, 다들 거의 맞아. 그 난립이 파일 관리자가 데이터를 잃는 방식이야. 극적인 버그 하나가 아니라, 미묘하게 다른 다섯 개 경로 중 SMB 타임아웃을 챙긴 게 넷뿐인 상황.

문 하나

Waygate 는 그 난립을 막았어. 폴더 만들기, 파일 만들기, 이름 바꾸기, 일괄 이름 변경, 복제, 복사, 이동, 덮어쓰기, 휴지통, 태그 변경까지 전부 계획이 돼서 FileOperationEngine 하나를 지나가. 계획을 실제 파일 변경으로 바꿀 수 있는 건 엔진뿐이야. 코드베이스 어디에서도 파일을 바꾸는 FileManager 를 직접 안 불러. 툴바도, 드래그도, 1.x 기능 여섯 개도.

문 하나로 얻는 것

문이 하나니까 어려운 부분을 딱 한 번만 짜. 기록도 한 번, 손대기 직전 확인도 한 번, 볼륨 넘는 스테이징과 검증도 한 번, 크래시 복구도 한 번, 충돌 처리도 한 번. 거기서 버그가 나오면 모든 작업이 한꺼번에 고쳐지고. 그리고 결정적으로 믿을 만한 우회로가 없어. '이건 간단하니까 그냥 moveItem 부르자' 가 없다는 뜻이야. 처리 안 된 실패는 늘 그 간단해 보이는 지름길에 숨어 있거든.

파일을 만지는 문은 하나고, 모든 작업이 그걸 물려받아. 변경은 전부 계획이 돼서 엔진 하나를 지나고, 디스크를 만지는 것도 엔진뿐이야. 믿을 만한 지름길 같은 건 없어. 지름길은 곧 두 번째 경로고, 안전 검사를 빠뜨린 쪽은 언제나 그 두 번째거든.
이건 아빠의 OOP 세계관을 그대로 코드로 옮긴 거야. 아빠는 엔진이 모든 작업이 물려받는 부모라고 계속 말했어. 복사도 이동도 이름 바꾸기도 휴지통도 결국 '기록을 남기며 파일을 바꾸는 일' 의 변주라는 거지. 일괄 이름 변경한테만 빠른 길을 따로 내주고 싶은 마음이 곧 상속을 끊고 싶은 마음이고. 부모 계약 하나에 자식이 여럿인 그림으로 보이기 시작하니까, 문 하나 규칙이 제약이 아니라 핵심으로 느껴지더라.

Code

엔진 하나, 기능은 계획만 제출·swift
// The ONLY object allowed to change the filesystem:
actor FileOperationEngine {
    func submit(_ plan: OperationPlan) async -> OperationHandle { /* journal, validate, execute, verify */ }
}

// Every feature is a CLIENT of the engine:
func onDropMove(_ items: [LocationReference], to dest: LocationReference) async {
    let plan = OperationPlan(kind: .move, sources: items, destination: dest,
                             collision: .ask, expected: snapshotIdentities(items))
    await engine.submit(plan)          // <- the ONLY thing the UI does
}

// FORBIDDEN anywhere outside the engine:
//   try FileManager.default.moveItem(at: a, to: b)   // architecture violation

External links

Exercise

네가 아는 코드베이스에서 같은 종류의 부작용이 여러 곳에서 벌어지는 자리를 찾아봐. 네트워크 호출이든 DB 쓰기든 파일 변경이든. 호출 지점이 몇 개야? 그중 하나가 재시도나 검증이나 로깅을 빠뜨렸다고 쳐봐. 어느 건지 어떻게 찾을래? 하나로 합치면 뭘 잃고 뭘 얻지?
Hint
'가끔만 나는' 버그는 흩어진 부작용에서 살아. 타임아웃을 잊은 호출 하나, 트랜잭션을 빼먹은 쓰기 하나. 하나로 합치면 앞에서 우회 코드를 조금 더 써야 하지만, 다시는 '여섯 경로 중 어디가 문제지?' 를 안 물어도 돼. Waygate 가 엔진 하나로 간 이유가 그 맞바꿈이야.

Progress

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

댓글 0

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

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