클라우드 Mac에서 iOS App Intents 매개변수와 단축어 검증하기

AI 자동화 ·약 9분 읽기

클라우드 Mac에서 iOS App Intents 매개변수와 단축어 검증하기

개발용 Mac에서는 ‘독서 기록’ 단축어를 찾을 수 있는데, 원격 빌드에 사용하는 시뮬레이터에서는 보이지 않을 수 있습니다. 이때 비즈니스 로직부터 수정하지 마세요. 매개변수가 유효한지, Intent가 실행되는지, 시스템이 동작을 발견했는지는 서로 다른 검사 항목입니다. 클라우드 Mac은 앞의 두 항목을 테스트할 환경을 고정하는 데 적합합니다. 마지막 항목은 앱이 설치된 시뮬레이터에서 확인해야 합니다.

자동 테스트의 범위부터 정하기

이 글에서는 디스크에 기록하지 않는 예제 동작으로 검증 절차를 살펴봅니다. 책 ID를 입력받아 앞뒤 공백을 제거한 뒤 정규화된 ID를 반환합니다. 이렇게 하면 우선 저장소 권한과 네트워크 변동을 변수에서 제외할 수 있습니다. 나중에 데이터베이스를 연결한다면 쓰기 작업과 반복 실행 정책을 별도로 테스트하세요. ‘성공을 반환했다’는 사실을 ‘데이터가 저장됐다’는 뜻으로 받아들여서는 안 됩니다.

검증은 세 단계로 나눕니다. 순수 Swift 규칙으로 빈 값과 허용되지 않는 문자를 검사하고, XCTest에서 perform()을 호출해 반환값과 오류를 확인한 다음, 시뮬레이터에서 사람이 직접 동작의 표시 여부와 매개변수 입력·결과 확인 가능 여부를 살핍니다. 앞의 두 단계가 실패하면 병합을 막아야 합니다. 세 번째 단계는 시스템 인덱싱의 영향을 받으므로, 고정된 대기 시간을 넣은 테스트보다는 버전 출시 전 점검 항목으로 두는 편이 적절합니다.

단축어가 나타나기를 기다리려고 자동 테스트에서 앱을 계속 삭제하고 다시 설치하지 마세요. 먼저 코드의 계약이 올바른지 입증한 뒤 앱 설치, 최초 실행, 시스템의 동작 발견 과정을 점검하세요.

입력 규칙을 직접 테스트할 수 있는 타입으로 분리하기

아래 규칙은 1–32자의 ASCII 영문자, 숫자, 밑줄, 하이픈을 허용합니다. 공백은 입력의 앞뒤에만 허용하며, 그 밖의 문자가 들어오면 명확한 오류를 반환합니다. 예제의 perform()은 ID만 반환하고 데이터를 영구 저장하지 않습니다.

import AppIntents
import Foundation

enum ReadingIDError: LocalizedError {
    case invalid

    var errorDescription: String? {
        "编号须为 1–32 位字母、数字、下划线或连字符"
    }
}

enum ReadingID {
    static func normalize(_ raw: String) throws -> String {
        let value = raw.trimmingCharacters(in: .whitespacesAndNewlines)
        let pattern = #"^[A-Za-z0-9_-]{1,32}$"#
        guard value.range(of: pattern, options: .regularExpression) != nil else {
            throw ReadingIDError.invalid
        }
        return value
    }
}

struct CheckReadingIDIntent: AppIntent {
    static var title: LocalizedStringResource = "检查书籍编号"
    static var openAppWhenRun = false

    @Parameter(title: "书籍编号")
    var bookID: String

    func perform() async throws -> some IntentResult & ReturnsValue<String> {
        let normalized = try ReadingID.normalize(bookID)
        return .result(value: normalized)
    }
}

매개변수 제목, 동작 제목, 오류 메시지는 프로젝트의 현지화 리소스에 포함하세요. 코드에 들어 있는 중국어는 예시 문구일 뿐이며, 다국어 앱에서 모든 언어에 그대로 제공해서는 안 됩니다. 규칙 자체는 ASCII ID만 허용합니다. 서비스에서 한자나 다른 문자를 허용한다면 먼저 허용할 문자 집합을 정의한 뒤 정규식과 테스트 사례를 수정하세요.

정상 입력뿐 아니라 경계 조건도 테스트하기

최소한 " book_7 "이 "book_7"을 반환하는지, 빈 문자열·내부 공백이 있는 문자열·32자를 초과하는 ID가 거부되는지 확인하세요. 오류 경로에서는 단순히 ‘어떤 오류가 발생했다’고만 검사하지 말고 오류 타입을 단언해야 합니다. 그렇지 않으면 하위 의존성에서 뜻밖의 오류가 발생해도 테스트가 통과할 수 있습니다. perform()을 테스트할 때는 반환값이 정규화 규칙과 일치하는지도 확인하세요. 순수 규칙 테스트와 Intent 호출 테스트를 분리해야 실패 원인이 입력 규칙인지 시스템 인터페이스를 감싼 계층인지 구별할 수 있습니다.

등록 진입점을 마련하고 시뮬레이터에서 확인하기

시스템에 추천 동작을 표시하려면 앱 타깃에 AppShortcutsProvider를 추가할 수 있습니다. 문구에는 앱 이름 자리표시자를 남겨 두어 시스템이 동작을 현재 앱과 연결하도록 합니다. 이 문구는 셸 문자열이 아닙니다.

import AppIntents

struct ReadingShortcuts: AppShortcutsProvider {
    static var appShortcuts: [AppShortcut] {
        AppShortcut(
            intent: CheckReadingIDIntent(),
            phrases: ["在 \(.applicationName) 检查书籍编号"],
            shortTitle: "检查书籍编号",
            systemImageName: "book"
        )
    }
}

먼저 이 파일이 테스트 타깃에만 속한 것이 아니라 앱 타깃에도 포함되어 있는지 확인하세요. 빌드한 앱을 설치해 한 번 실행한 뒤, 시뮬레이터의 ‘단축어’를 열어 동작 제목을 검색하고 유효한 ID를 입력해 실행합니다. 이어서 유효하지 않은 ID를 제출해 오류 메시지를 이해할 수 있는지 확인하세요. 동작이 나타나지 않으면 시스템 버전, 앱 빌드 버전, 설치 후 수행한 작업 순서를 기록하세요. ‘화면을 다시 열었더니 우연히 나타났다’를 확실한 해결책으로 적어서는 안 됩니다.

테스트 기기와 결과 디렉터리 고정하기

ZSHMac의 클라우드 Mac에서 먼저 xcrun simctl list devices available로 설치되어 사용 가능한 시뮬레이터를 확인하세요. 사용할 기기의 UDID를 선택해 SIM_UDID를 설정합니다. 아래 명령은 프로젝트에 Reader라는 공유 scheme이 있다고 가정합니다. 실제 실행 시에는 자신의 프로젝트에 맞는 scheme을 사용하세요. 기존 파일 때문에 테스트 명령이 즉시 실패하지 않도록 실행할 때마다 결과 번들에 새 경로를 지정합니다.

mkdir -p artifacts
test -n "${SIM_UDID:-}" || { printf '%s\n' 'SIM_UDID is required' >&2; exit 1; }
result="$PWD/artifacts/app-intents-$(date +%Y%m%d-%H%M%S)-$$.xcresult"
xcodebuild test \
  -scheme Reader \
  -destination "platform=iOS Simulator,id=$SIM_UDID" \
  -resultBundlePath "$result"

CI에서는 명령의 종료 코드와 결과 번들을 보관하세요. 종료 코드는 작업의 통과 여부를 결정하고, 결과 번들은 실패한 테스트 사례를 찾는 데 사용합니다. scheme이 공유되지 않았거나 대상 시뮬레이터를 사용할 수 없다면 실행 환경부터 바로잡으세요. 이를 Intent 로직의 실패로 분류해서는 안 됩니다. 수동 검증 시에는 동작이 나타나는지, 입력 안내가 올바른지, 유효한 매개변수와 유효하지 않은 매개변수에서 각각 실제로 어떻게 동작하는지 기록합니다.

실패한 단계부터 원인 좁히기

증상 먼저 확인할 것 먼저 하지 말 것
순수 규칙 테스트 실패 허용 문자 범위, 길이, 앞뒤 공백 처리 시뮬레이터 재설치
perform() 결과 불일치 전달된 매개변수와 반환값 타입 시스템 인덱싱 기다리기
테스트 명령이 기기를 찾지 못함 사용 가능한 기기 목록과 UDID Swift 규칙 수정
단축어에 동작이 없음 앱 타깃 포함 여부, 설치, 최초 실행 테스트에 고정 지연 추가
동작은 있지만 실행 오류가 남 매개변수 안내, 오류 타입, 대상 시스템 버전 모든 오류 무시

단계별 점검의 목적은 문제 범위를 좁히는 것이지, 설치 직후 시스템 진입점이 반드시 보인다고 보장하는 것이 아닙니다. 코드 테스트가 통과하고 시뮬레이터에서도 유효한 입력과 유효하지 않은 입력으로 동작을 확인해야 이번 검증이 마무리됩니다. 실제 쓰기 기능을 연결한 뒤에는 반복 실행과 데이터의 디스크 저장을 별도로 테스트해야 합니다. 이 예제처럼 ‘ID만 반환한다’는 통과 기준을 그대로 적용할 수는 없습니다.

자주 묻는 질문

XCTest는 통과했는데 단축어에 동작이 보이지 않는 이유는 무엇인가요?

AppShortcutsProvider가 포함된 앱이 설치되고 실행됐는지, 대상 시스템 버전과 타깃 설정이 맞는지 확인하세요. 시스템 색인에는 시간이 걸릴 수 있습니다.

매개변수 유효성 검사는 어디에 두는 것이 좋나요?

재사용 가능한 Swift 타입에 입력 규칙을 두고 perform()에서 호출하세요. 그러면 시스템 색인과 무관하게 규칙을 단위 테스트할 수 있습니다.

화면 없는 CI만으로 단축어 검증을 끝낼 수 있나요?

아니요. CI는 입력과 반환값을 확인하고, 동작 표시 및 입력 화면은 대상 시스템 버전의 시뮬레이터나 기기에서 확인해야 합니다.

클라우드 Mac을 단독으로 사용하고 싶으신가요?

모델, 리전, 과금 기간을 선택하세요. 전용 물리 머신을 제공하며, 실제 사용 가능 여부는 콘솔에서 실시간으로 확인할 수 있습니다.

구성 확인 및 주문