macOS 앱의 파일 접근 권한을 재실행 후에도 검증하기

Security ·약 7분 읽기

macOS 앱의 파일 접근 권한을 재실행 후에도 검증하기

원격 Mac에서 개발한 macOS 파일 읽기 기능이 테스트 디렉터리에서는 정상적으로 작동하지만, 사용자에게 전달한 앱에서는 ‘접근 권한이 없음’ 오류가 날 수 있습니다. 테스트 파일이 우연히 앱 자체 컨테이너 안에 있거나, 파일을 선택한 직후만 확인하고 앱 종료 후 다시 열 수 있는지는 검증하지 않은 경우가 흔합니다. 이 기능을 검증하려면 사용자가 직접 선택한 컨테이너 외부 파일을 대상으로 삼고, 앱을 재실행한 뒤에도 읽을 수 있는지 확인해야 합니다.

테스트 범위 먼저 정하기

App Sandbox는 앱이 컨테이너 외부 파일에 접근하는 것을 제한합니다. 사용자가 시스템 파일 선택 창을 통해 접근을 허용했다고 해서, 앱이 원래 경로만으로 해당 파일을 영구적으로 읽을 수 있는 것은 아닙니다. 앱에서 파일을 기억해야 한다면 보안 범위 북마크를 저장하고, 다음 실행 시 북마크를 해석한 뒤 실제로 읽거나 쓰는 동안 접근을 활성화해야 합니다.

내용을 식별할 수 있는 일반 텍스트 파일을 앱 컨테이너 외부에 준비합니다. 별도의 시스템 개인정보 보호 권한이 적용되는 디렉터리는 피해야 이번 테스트에 다른 권한 부여 절차가 섞이지 않습니다. 비교용으로 컨테이너 내부 파일도 준비합니다. 내부 파일을 읽을 수 있다는 사실은 기본 파일 처리 코드가 작동한다는 증거일 뿐, 외부 파일 접근 절차가 올바르다는 증거는 아닙니다.

합격 기준은 ‘파일 선택 창을 닫은 직후 오류가 나지 않는다’가 아닙니다. ‘앱을 재실행한 뒤에도 허용된 범위에서 지정한 파일을 읽고, 권한을 사용할 수 없을 때는 사용자가 복구할 수 있는 방법을 제공한다’입니다.

배포할 앱의 권한 선언 확인하기

프로젝트에서 수정한 권한 파일만 보지 말고 실제로 전달할 .app을 먼저 확인합니다. 빌드 설정이나 서명 과정에 차이가 있으면 최종 산출물의 선언도 달라질 수 있습니다. 아래 APP을 이번 빌드 산출물의 실제 경로로 바꿉니다.

APP="$PWD/build/Reader.app"
codesign --verify --strict --verbose=2 "$APP"
codesign -d --entitlements :- "$APP"

샌드박스 권한이 활성화되어 있는지 확인합니다. 읽기 전용으로 파일을 가져오는 기능이라면 사용자가 선택한 파일의 읽기 권한을 확인하고, 원본 파일을 실제로 수정해야 할 때만 읽기·쓰기 권한을 고려합니다. 앱을 다시 실행한 뒤에도 접근해야 하는 기능이라면 앱 범위 북마크 권한 선언도 확인해야 합니다. 테스트를 통과시키려고 관련 없는 디렉터리까지 접근 권한을 넓히지 마세요.

서명 검사는 ‘무엇을 선언했는가’만 알려줍니다. ‘사용자가 파일을 선택했는가’나 ‘북마크로 접근 권한을 복원할 수 있는가’는 알 수 없습니다. 이 두 가지는 앱을 실행해 검증해야 합니다.

북마크 저장과 접근 시작·종료를 한 쌍으로 관리하기

NSOpenPanel에서 사용자가 선택한 URL을 받으면 보안 범위 북마크를 만들고, 반환된 Data를 앱 자체의 영구 저장소에 저장합니다. url.path만 저장해서는 안 됩니다. 경로에는 파일 위치만 담겨 있고, 접근 권한을 다시 얻는 데 필요한 정보는 없습니다.

파일을 읽을 때는 북마크 해석, 접근 시작, 접근 종료를 같은 함수 안에서 처리해 오류 경로에서도 정리 작업이 빠지지 않도록 합니다.

enum FileAccessError: Error {
    case staleBookmark
    case accessDenied
}

func readSelectedFile(bookmark: Data) throws -> Data {
    var stale = false
    let url = try URL(
        resolvingBookmarkData: bookmark,
        options: .withSecurityScope,
        relativeTo: nil,
        bookmarkDataIsStale: &stale
    )
    guard !stale else { throw FileAccessError.staleBookmark }
    guard url.startAccessingSecurityScopedResource() else {
        throw FileAccessError.accessDenied
    }
    defer { url.stopAccessingSecurityScopedResource() }
    return try Data(contentsOf: url)
}

북마크를 만들 때도 보안 범위 옵션을 사용하고 반환된 데이터를 안전하게 저장해야 합니다. 이 예제는 오래된 북마크를 만나면 읽기를 중단합니다. 실제 앱에서는 사용자가 파일을 다시 선택할 수 있게 하고, 새로 권한을 얻은 뒤 북마크를 다시 생성해야 합니다. startAccessingSecurityScopedResource()의 성공 여부를 확인하는 단계를 생략해서는 안 되며, stopAccessingSecurityScopedResource() 호출을 앱 종료 시점까지 미뤄서도 안 됩니다.

그래픽 세션에서 재실행 회귀 테스트하기

클라우드 Mac에서는 명령줄로 서명을 확인할 수 있지만, NSOpenPanel의 상호작용을 검증하려면 사용 가능한 macOS 그래픽 세션이 필요합니다. SSH 작업이 실행된다는 이유로 파일 선택 창도 정상적으로 표시될 것이라고 가정하지 마세요. 자동화 테스트에서도 테스트 프로세스가 그래픽 세션을 사용할 수 있는 환경에서 실행되는지 확인해야 합니다.

같은 테스트 파일로 다음 순서대로 진행하고, 각 단계의 예상 결과와 실제 결과를 기록합니다.

  1. 앱을 처음 실행한 뒤 파일 선택 창을 열지 않고 저장해 둔 경로로 외부 파일을 직접 읽어 봅니다. 앱이 경로만으로 의도한 권한 부여 절차를 우회하지 못하는지 확인합니다.
  2. 창에서 해당 파일을 직접 선택하고 내용을 읽어 확인하면서 북마크를 저장합니다.
  3. 앱을 완전히 종료한 뒤 동일한 배포 산출물을 다시 실행합니다. 북마크를 해석해 파일을 다시 읽고 내용을 확인합니다.
  4. 테스트 파일을 다른 곳으로 옮긴 뒤 다시 시도합니다. 파일이 없다는 문제를 서명 오류로 잘못 보고하는 대신, 이해할 수 있는 오류와 파일을 다시 선택할 수 있는 방법을 제공해야 합니다.
  5. 손상된 북마크 데이터로 오류 처리 경로를 테스트합니다. 앱은 읽기를 중단하고 파일을 다시 선택하도록 요청해야 하며, 창을 반복해서 띄우거나 무한 재시도해서는 안 됩니다.

가장 빠뜨리기 쉬운 단계는 세 번째입니다. 한 번의 프로세스 실행 중에만 파일을 읽으면 북마크가 영구 저장되지 않은 문제를 놓칠 수 있습니다. 파일에 다시 써야 하는 기능이라면 읽기·쓰기 권한으로 이 절차를 별도로 반복해야 합니다. 읽기 전용 테스트로 대신할 수는 없습니다.

실패 원인을 증거에 따라 좁히기

‘선택 직후 실패’한다면 파일 선택 창이 반환한 URL을 올바르게 사용하는지, 권한 선언이 읽기·쓰기 요구 사항에 맞는지 먼저 확인합니다. ‘직후에는 성공하지만 재실행 후 실패’한다면 북마크가 실제로 영구 저장됐는지, 다시 실행한 앱의 식별 정보와 서명 설정이 이전과 같은지 우선 확인합니다. ‘특정 디렉터리에서만 실패’한다면 샌드박스 권한을 바로 넓히지 말고 해당 디렉터리에 별도의 개인정보 보호 권한이 적용되는지 먼저 살펴봅니다.

회귀 테스트 기록에는 최소한 배포 앱 버전, 최종 권한 선언, 테스트 파일이 있는 디렉터리의 유형, 파일 선택 전후 결과, 재실행 후 결과, 오류 유형을 남깁니다. 로그에는 필요한 상태와 오류만 기록하고 북마크 원본 데이터나 파일 내용은 출력하지 않습니다. 그래야 다음 빌드에서 실패했을 때 팀이 권한 선언 변경, 북마크 수명 주기 문제, 테스트 환경의 그래픽 세션 부재 중 무엇이 원인인지 판단할 수 있습니다. ‘내 컴퓨터에서는 열리는데’라는 말에 의존해 처음부터 다시 추측할 필요가 없습니다.

자주 묻는 질문

파일을 선택했는데 북마크를 별도로 저장해야 하나요?

앱을 재실행한 뒤에도 해당 파일을 열어야 한다면 보안 범위 북마크를 저장해야 합니다. 다시 읽을 때 북마크를 해석하고 접근을 시작한 다음 작업이 끝나면 접근을 종료합니다.

SSH 연결만으로 모든 검사를 마칠 수 있나요?

아니요. 서명과 권한 선언은 명령줄에서 확인할 수 있지만 파일 선택 창과 대화형 접근 검사는 사용 가능한 macOS 그래픽 세션이 필요합니다.

클라우드 Mac을 워크플로에 연결하세요

VPSPush는 원격으로 연결할 수 있는 전용 물리 Mac을 제공합니다. 노드와 이용 기간을 선택한 뒤 주문에서 접속 정보와 최종 금액을 확인하세요.

클라우드 Mac 요금제 확인 및 주문