에러 번호와 측정 상태(v3.3.2)

3.3.1에서 3.3.2로 올릴 때 대부분 바꿔야 하는 코드는 없습니다. 앱이 받는 에러 케이스는 그대로이고, 새 기능은 필요할 때만 쓰면 됩니다. 아래 5. 에러 케이스가 바뀌는 곳과 6. 동작이 바뀌는 곳만 확인해 주세요.

1. 측정이 끊기지 않도록 개선

상황3.3.13.3.2
측정 중 AirPods 등 블루투스 기기를 연결·해제했는데 오디오 엔진 재시작이 실패didFail(error: .audioInitializationFailed) 로 측정 종료didInterrupt() → 자동 재개 → didResume(). 다른 앱이 오디오를 쓰고 있으면 30초마다 다시 확인하고, 끝내 재개하지 못하면 interruptionRecoveryFailed
음악 재생 중 Siri가 알림을 읽어 준 뒤녹음이 다시 시작되지 않는 경우가 있음알림 읽기가 끝나면 재개를 시도
알람 중 재개 재시도가 예약된 상태에서 알람이 꺼짐didResume() 이 2번 올 수 있음이미 재개됐으면 재시도를 건너뜀

측정 중이 아닐 때 오디오 엔진이 실패하면 예전처럼 audioInitializationFailed 입니다.

2. 5자리 에러 코드(베타) 정리

3.2.0부터 베타로 제공하는 5자리 에러 코드(error.errorCode)의 번호를 원인별로 정리하고, 번호 이름으로 분기할 수 있게 했습니다. 케이스 정리와 정식 전환은 v4.0.0에 예정되어 있습니다.

번호 이름으로 분기하기

func didFail(error: Asleep.AsleepError) {
    switch error.errorCode {
    case .createConflict:          // 22409 이전 세션이 아직 닫히지 않음
        // ...
    case .commonExpired:           // 11403 플랜 만료 · 요청 과다
        // ...
    case .uploadTrackingTerminated: // 23499 업로드 오류로 측정 종료
        // ...
    default:
        print(error.errorCode.code, error.errorCode.message ?? "")
    }
}
  • 기존처럼 케이스(case .httpStatus, case .startTrackingNetworkFail 등)로 분기하는 코드도 그대로 동작합니다.
  • startTrackingNetworkFail, stopTrackingNetworkFail 에 deprecated 경고가 붙습니다. 경고만 나고 동작은 같으며, v4.0.0 전까지 그대로 전달됩니다.
  • 전체 번호표는 Error Codes 를 참고하세요.

errorCode.message

서버가 보낸 문구가 있으면 그 문구가 들어갑니다. 원인 확인(로그)용이며 문구는 예고 없이 바뀔 수 있으니, 앱 로직은 번호(code) 또는 번호 이름으로 분기하세요.

== 는 번호만 비교합니다

message 가 서버 문구라 매번 다를 수 있어, AsleepErrorCode 의 == 는 code 만 비교합니다.

// 3.3.2: 서버 문구와 관계없이 true
[.audioSilenced, .audioUnsilenced, .uploadFailed].contains(error.errorCode)

3. 바뀐 번호

아래 상황에서는 앱이 받는 에러 번호(errorCode.code)가 3.3.1과 달라집니다. 이 숫자로 분기하거나 통계를 내고 있다면 확인해 주세요.

상황3.3.13.3.2
세션 생성 4002200022400
세션 생성 403 · 429 (플랜 만료 · 요청 과다)2200011403
세션 생성 404 (없는 사용자)2200011404
이미 측정 중인데 startTracking()2200011010
녹음기 시작 실패2200011003
업로드 5xx1150023500
init 서버 5xx1150021500
init 그 밖의 실패 · 인터넷 없음1100021000
토큰 발급 401 · 404 (잘못된 appId / appSecret)1200012002
리포트 조회 400 · 401 · 404 · 5xx · 그 외11xxx32400 · 32401 · 32404 · 32500 · 32000
리포트 목록 400 · 401 · 5xx · 그 외11xxx33400 · 33401 · 33500 · 33000
평균 리포트 400 · 404 · 5xx · 그 외11xxx34400 · 34404 · 34500 · 34000
세션 삭제 401 · 5xx · 그 외11xxx25401 · 25500 · 25000
사용자 삭제 401 · 404 · 5xx · 그 외 · 인터넷 없음11xxx26401 · 11404 · 26500 · 26000 · 26000
분석 요청 400 · 401 · 404 · 5xx · 그 외11xxx31400 · 31401 · 31404 · 31500 · 31000
메타데이터 저장 서버 4002700027400
ODA 모델 파일 손상1000210001

4. 겹친 호출 처리 (측정 상태)

측정이 시작되는 중, 진행 중, 끝나는 중에 다른 호출이 겹치면 아래처럼 처리합니다.

호출이때3.3.13.3.2
createSleepTrackingManager측정 시작 중 · 측정 중 · 종료 중새 매니저로 바뀜 (이전 매니저의 녹음이 알림 없이 멈출 수 있음)지금 매니저를 그대로 돌려줌. 새로 넘긴 delegate · config · 녹음 옵션은 쓰지 않음
startTracking()측정 시작 중두 번째 호출도 진행무시 (콜백 없음)
startTracking()종료 중 · init 진행 중새 측정을 시작무시 (콜백 없음)
startTracking()측정 중alreadyTrackingalreadyTracking (같음)
stopTracking()측정 시작 중녹음기만 멈춤시작이 끝나면 바로 정상 종료
initAsleepConfig앞선 init 응답 전둘 다 진행, 콜백 2번무시 (콜백 없음)
initAsleepConfig측정 중녹음이 알림 없이 멈춤세션을 정상 종료해 didClose 를 보낸 뒤 init 진행 (실패하면 didFail)
setup측정 시작 중 · 측정 중 · 종료 중측정 중만 무시셋 다 무시

Asleep.isSleepTrackingAlive()

측정이 진행 중인지 알려 주는 함수가 추가되었습니다.

if Asleep.isSleepTrackingAlive() {
    // 측정 시작 중 · 측정 중 · 종료 중
}
  • startTracking() 뒤 시작 중이거나, 측정 중이거나, stopTracking() 뒤 종료 처리 중이면 true 입니다.
  • 상태는 메모리에만 있습니다. 앱이 종료되었다가 다시 실행되면 false 입니다.

5. 에러 케이스가 바뀌는 곳

3.3.x 는 앱이 받는 에러 케이스를 바꾸지 않는 것이 원칙이지만, 아래는 바뀝니다.

상황3.3.13.3.2
측정 중 블루투스 기기 연결 · 해제로 엔진 재시작 실패audioInitializationFailed (측정 종료)didInterrupt() → didResume(), 재개하지 못하면 interruptionRecoveryFailed
init 때 이전 세션 정리 요청에 응답 없음stopTrackingNetworkFailhttpStatus (errorCode 21000)
토큰 발급 401 · 404tokenIssueFailedtokenInvalidCredentials
ODA setup 이 끝나지 않은 상태에서 측정 시작unableODAsetupIncomplete (신규, 10000)
메타데이터 저장을 서버가 400 으로 거절saveMetadataFailedmetadataValidationFailed (서버 문구 포함)

6. 동작이 바뀌는 곳

  • 분석 완료 알림(didComplete)은 부른 함수로 정해집니다. createSleepTrackingManager(config:delegate:recordingPath:recordingType:) 로 만든 매니저만 분석 완료를 확인하고 didComplete 를 보냅니다. createSleepTrackingManager(config:delegate:) 에 AsleepCompletableTrackingDelegate 를 넘긴 경우, 3.3.1 은 didComplete 를 보냈지만 3.3.2 는 보내지 않습니다. didCreate(sessionId:) 는 두 경우 모두 그대로 호출됩니다.
  • 측정 중 createSleepTrackingManager 는 새 매니저가 아니라 지금 매니저를 돌려줍니다. 화면마다 매니저를 새로 만들어 delegate 를 바꾸던 앱은, 측정 중에는 처음 넘긴 delegate 로 콜백이 갑니다.
  • 측정 종료 직후 마지막 조각 이 세션 종료보다 늦게 도착해 거절되면, 3.3.1 은 uploadTrackingTerminated 를 보냈지만 3.3.2 는 보내지 않습니다. 측정 중인 세션의 거절은 예전과 같습니다.

7. 알아 두면 좋은 것

📘

재난 · 실종 경보 문자를 받으면 앱을 열 때까지 녹음이 멈출 수 있습니다

앱이 백그라운드에 있을 때 재난 · 실종 경보 문자가 오면, 경보음이 오디오를 잠시 가져가면서 녹음이 멈추고 didFail(error: .cannotActivateInBackground) 가 올 수 있습니다. iOS 가 백그라운드에서 오디오를 다시 켜는 것을 막기 때문에 SDK 가 바로 재개할 수 없습니다. 앱이 포그라운드로 돌아오면 SDK 가 자동으로 녹음을 재개합니다. 로컬 알림 등으로 사용자가 앱을 열도록 안내해 주세요.


Did this page help you?