파일 입출력 트러블 슈팅(파일 복제)

문인범·2025년 3월 12일

Macro 챌린지

목록 보기
4/6
post-thumbnail

어느 순간부터 저희 앱에서 논문이 열리지 않는다는 얘기가 간헐적으로 들려왔습니다.
저희 앱을 사용하려고 하면 일단 논문으로 들어가야 하는데 그게 되지 않는다니..!!
사실상 앱이 작동하지 않는다고 볼 수 있죠 ㅜㅜ

그래서 어디에 문제가 있을까 찾아 본 결과 파일 입출력 과정에서 문제가 있었음을 발견했습니다.

문제점

저희 앱은 PDF파일을 업로드하면 해당 파일을 샌드박스 내에 저장해서 사용할 수 있도록 구현을 해놓았습니다.
이렇게 구현을 할 경우 동일한 이름을 가진 PDF을 업로드 할 때 에러가 나기 때문에 이름이 중복이 될 경우 os에서 처리하듯이 파일 이름 뒤에 넘버링을 붙여 중복을 피했습니다.

💡 간지나는 논문.pdf → 간지나는 논문(1).pdf

그런데 위의 문제를 해결하기 위해 여러가지를 시도하던 중 논문 뷰 안에서 파일 이름을 수정 후 삭제를 하고
저장을 한 뒤 다음 동일한 논문을 다시 업로드하니 뒤에 넘버링이 붙기 시작했습니다.

기존 논문의 이름이 engPD였는데 삭제후 다시 업로드 해도 넘버링이 붙었습니다.
그 말은 engPD.pdf 라는 파일이 존재한다는 것이고 직접 확인을 해본 결과 그대로 남아있었습니다.

이름 변경은 정상적으로 되는 것을 확인했고 그럼 저장에 문제가 있다고 판단되어 코드를 살펴보았습니다.

public func savePDF(pdfView: PDFView) {
    guard let document = pdfView.document else { return }
    guard let pdfURL = document.documentURL else {
        print("PDF URL을 찾을 수 없습니다.")
        return
    }
    
    // PDF 파일을 지정한 URL에 덮어쓰기 저장
    do {
        let pdfData = document.dataRepresentation()
        try pdfData?.write(to: pdfURL)
        print("PDF 저장이 완료되었습니다.")
    } catch {
        print("PDF 저장 중 오류 발생: \(error.localizedDescription)")
    }
}

해당 코드에서 현재 열려있는 PDFView 객체에서 PDFDocument와 그 Document의 URL을 받아와 저장에 사용합니다.

그런데 만약 논문의 이름을 변경하면 샌드박스에 있는 파일은 이름이 바뀌고 CoreData에 해당 경로가 저장되는데 이 반영사항이 현재 사용하고 있는 PDFView 객체에는 반영이 따로 되지 않습니다.

그래서 PDFView의 URL은 바뀌기 이전의 URL을 갖고 있는 상태에서 저장을 진행해 기존 이름의 파일이 복제가 되었습니다!

해결방안

엔티티의 상태를 공유할 수 있는 싱글톤 객체를 두어 해당 객체로 저장 뿐만 아니라 다양한 뷰에서 상태 변화를 감지할수 있게 하는 방향으로 수정했습니다!

// 파일 이름 변경 메소드
if let _ = try? FileManager.default.moveItem(at: url, to: newUrl) {
    let newBookmarkData = try! newUrl.bookmarkData(options: .minimalBookmark)
    dataToEdit.url = newBookmarkData
    // 상태 공유 싱글톤 객체
    PDFSharedData.shared.paperInfo?.url = newBookmarkData
}

이름 변경 시 싱글톤 객체에 있는 논문 엔티티의 url을 변경합니다.

public func savePDF(pdfView: PDFView) throws {
    var a = false
    // 싱글톤 객체의 url을 받아오도록 수정
    guard let pdfURL = PDFSharedData.shared.paperInfo?.url, let url = try? URL(resolvingBookmarkData: pdfURL, bookmarkDataIsStale: &a) else {
        print("PDF URL을 찾을 수 없습니다.")
        throw HomeViewError.cannotCreateBookmark
    }
    
    // PDF 파일을 지정한 URL에 덮어쓰기 저장
    do {
        let pdfData = document.dataRepresentation()
        try pdfData?.write(to: url)
        print("PDF 저장이 완료되었습니다.")
    } catch {
        print("PDF 저장 중 오류 발생: \(error.localizedDescription)")
    }
}

저장 시 해당 싱글톤의 url으로 저장을 진행해 변경된 url을 반영하도록 수정했습니다.
이렇게 수정한 결과 저장할 때 파일이 복제되지 않고 잘 있네요 ㅜㅜ

소소한 트러블 슈팅으로 문제를 해결했습니다!

앱을 개발하면서 느낀 것이 어찌보면 이건 당연하게 되겠지 하는 것들이 당연하지 않은 것이더군요.
일일이 직접 다 만져줘야 하는 것을 보고 힘들기도 했지만 개발자의 대한 동경심도 생겼습니다.
숨어있는 곳에 있는 디테일들을 놓치지 않고 다 구현할 수 있도록 열심히 공부해야겠어요 ㅎㅎ;;

profile
월클 개발자를 향한 도전일지

0개의 댓글