Setup
Asleep.setup()은 SDK의 인증 정보를 설정하고, 필요하면 SDK가 탑재된 기기(Product)를 Asleep 서버에 등록하는 API입니다.
앱 실행 후 수면 측정을 시작하기 전에 호출하고,
setupDidComplete()를 받은 뒤 Asleep.initAsleepConfig()를 호출하세요.
Asleep.setup(apiKey:, productInfo:, delegate:) ← 인증정보 · 기기 정보 전달
└ setupDidComplete()
└ Asleep.initAsleepConfig(userId:, delegate:) ← 인증정보 생략 가능 (setup값을 이어받음)
└ userDidJoin(userId:, config:)
└ createSleepTrackingManager → startTrackingsetup 없이 initAsleepConfig(apiKey:)만 호출하는 기존 방식도 그대로 동작합니다.
Product 등록을 사용하려면 setup을 먼저 호출해야 합니다.
Asleep.setup()
let apiKey: String = "YOUR_API_KEY"
let baseUrl: URL?
let callbackUrl: URL?
let service: String?
let productInfo: Asleep.ProductInfo?
let delegate: AsleepSetupDelegate = self
Asleep.setup(apiKey: apiKey,
baseUrl: baseUrl,
callbackUrl: callbackUrl,
service: service,
productInfo: productInfo,
delegate: delegate)| Property Name | Type | Description |
|---|---|---|
apiKey | String | 대시보드에서 발급받은 API Key |
baseUrl | URL? | nil이면 기본 서버를 사용합니다. 프록시 서버를 쓰는 경우 주소를 입력하세요 |
callbackUrl | URL? | 수면 세션 분석 결과를 받을 서버 URL |
service | String? | 앱 이름 |
productInfo | Asleep.ProductInfo? | 기기(Product) 정보. 넘기면 setup 과정에서 기기를 등록합니다. 아래 Product 등록 참고 |
delegate | AsleepSetupDelegate? | setup 결과를 받을 delegate |
Token 방식
API Key 대신 앱 인증 정보(appId · appSecret) 로 인증할 수 있습니다. setup 이후의 모든 API는 인증 방식과 관계없이 똑같이 사용합니다.
Asleep.setup(appId: "YOUR_APP_ID",
appSecret: "YOUR_APP_SECRET",
productInfo: productInfo,
delegate: self)| Property Name | Type | Description |
|---|---|---|
appId | String | 대시보드에서 발급받은 App ID |
appSecret | String | 대시보드에서 발급받은 App Secret |
isTestEnvironment | Bool? | 테스트 환경을 사용할 때만 true |
baseUrl | URL? | nil이면 기본 서버를 사용합니다 |
callbackUrl | URL? | 수면 세션 분석 결과를 받을 서버 URL |
service | String? | 앱 이름 |
productInfo | Asleep.ProductInfo? | 기기(Product) 정보. 아래 Product 등록 참고 |
delegate | AsleepSetupDelegate? | setup 결과를 받을 delegate |
API Key 방식과의 차이
| 항목 | API Key | Token |
|---|---|---|
| 인증 헤더 | x-api-key | Authorization: Bearer |
| 토큰 갱신 | 없음 | SDK가 자동으로 갱신합니다 (만료 5분 전) |
| 인증 실패(401) | 에러 전달 | 자동으로 다시 발급받아 재시도합니다 |
appId또는appSecret가 빈 문자열이면setupDidFail로 즉시 실패합니다.- 두 방식은 같은 재호출 가드를 공유합니다. API Key setup이 진행 중이면 Token setup도 무시됩니다.
- 토큰 관련 실패는 아래
AsleepError케이스로 전달됩니다.
| AsleepError | 상황 |
|---|---|
tokenIssueFailed | 토큰 발급 실패 |
tokenRefreshFailed | 토큰 갱신 실패 |
tokenInvalidCredentials | 잘못된 appId / appSecret |
tokenNetworkError | 토큰 요청 중 네트워크 오류 |
AsleepSetupDelegate
protocol AsleepSetupDelegate {
func setupDidComplete()
func setupDidFail(error: Asleep.AsleepError)
func setupInProgress(progress: Int)
}- setupDidComplete() — setup이 끝났을 때 호출됩니다.
productInfo를 넘겼다면 기기 등록까지 끝난 뒤에만 호출됩니다. - setupDidFail() — setup이 실패했을 때 호출됩니다. 이 경우
setupDidComplete()는 호출되지 않습니다.error: 에러 정보 (Error Codes 참고)
- setupInProgress() — Product 등록 과정에서는 호출되지 않습니다. 빈 구현으로 두어도 됩니다.
호출 규칙
| 상황 | 동작 |
|---|---|
setup이 진행 중일 때 다시 setup 호출 | 무시됩니다 (콜백 없음). setupDidComplete / setupDidFail을 받은 뒤 호출하세요. 콜백 안에서 다시 호출하는 것은 괜찮습니다 |
수면 측정 중 setup 호출 | 무시됩니다 (콜백 없음). 측정을 종료한 뒤 호출하세요 |
apiKey가 빈 문자열 | 즉시 setupDidFail (unknown) |
setup 후 initAsleepConfig에서 apiKey 등을 생략 | setup에 넘긴 값을 이어받습니다. 앱을 다시 실행하면 setup부터 다시 호출하세요 |
Product 등록
Product 등록은 SDK가 탑재된 기기를 Asleep 서버에 등록하는 기능입니다. 등록해두면 서버가 어떤 세션이 어떤 기기에서 측정되었는지 기록합니다.
- 별도 API 없이
setup에productInfo를 넘기면 등록됩니다. - 등록에 성공하면 SDK가 등록 정보를 기기에 저장하고, 이후 세션 생성 · 데이터 업로드 등의 요청에 자동으로 포함합니다. 앱이 따로 다룰 값은 없습니다.
productInfo없이setup을 호출하면 등록 요청을 보내지 않습니다.
Asleep.ProductInfo
let productInfo = Asleep.ProductInfo(
model: "MODEL_NAME",
identifierType: .serial,
identifierValue: "SERIAL_NUMBER"
)public struct ProductInfo: Equatable {
public let model: String
public let identifierType: ProductIdentifierType
public let identifierValue: String
}
public enum ProductIdentifierType: String {
case serial
case macAddress
}| Property Name | Type | Description |
|---|---|---|
model | String | 제품 모델명 (1~100자) |
identifierType | ProductIdentifierType | 기기를 구분하는 값의 종류. .serial(시리얼 번호) 또는 .macAddress(MAC 주소) |
identifierValue | String | 시리얼 번호 또는 MAC 주소 (1~255자) |
꼭 지켜주세요
identifierValue는 기기마다 고유하고 바뀌지 않는 값을 사용하세요.- 항상 같은 형식으로 넘겨주세요. SDK는 대소문자, 구분자(
:/-), 앞뒤 공백을 변환하지 않고, 문자열이 조금이라도 다르면 다른 기기로 보고 다시 등록 요청을 보냅니다.- 빈 값, 공백만 있는 값, 길이를 넘는 값은 서버 요청 없이
setupDidFail(productRegisterRejected)로 실패합니다
동작 방식
productInfo를 넘기면 기기 등록이 setup의 한 단계가 되고, 등록이 끝나야 setupDidComplete()가 호출됩니다.
Asleep.setup(apiKey:, productInfo:, delegate:)
│
├ ① 저장된 등록 정보 확인
│ 같은 API Key · 같은 productInfo로 이미 등록됨 → 등록 요청 없이 바로 완료
│
├ ② 입력값 확인
│ model / identifierValue 조건 위반 → setupDidFail (productRegisterRejected)
│
├ ③ 서버에 등록 요청
│ 네트워크 오류 · 서버 오류 → 2초 · 4초 · 8초 뒤 최대 3번 재시도
│
└ ④ 성공 → setupDidComplete()
실패 → setupDidFail (productRegisterFailed 또는 productRegisterRejected)
| 상황 | 동작 |
|---|---|
| 처음 실행 | 서버에 등록하고 등록 정보를 저장합니다 |
다음 실행부터 (같은 API Key · 같은 productInfo) | 등록 요청 없이 바로 완료됩니다 |
productInfo가 바뀜 (예: 연결된 기기 변경) | 새 productInfo로 다시 등록합니다. 성공하면 이후 생성되는 세션부터 새 기기로 기록됩니다 |
| API Key가 바뀜 | 기존 등록 정보를 지우고 새 API Key로 다시 등록합니다 |
| 앱 삭제 후 재설치 | 저장된 등록 정보도 함께 삭제되므로, 다음 setup에서 다시 등록합니다 |
앱을 실행할 때마다 같은 productInfo로 setup을 호출하세요. 두 번째 실행부터는 등록 요청 없이 바로 완료됩니다.
소요 시간
- 이미 등록된 기기: 등록 요청 없이 바로 완료됩니다.
- 처음 등록: 보통 요청 한 번으로 끝납니다.
- 서버가 응답하지 않아 재시도를 모두 쓰는 경우: API Key 방식은 최대 약 75초, Token 방식은 시도마다 요청이 2건이라 더 오래 걸린 뒤
setupDidFail(productRegisterFailed)이 호출됩니다.
setupDidComplete()를 기다리는 동안에는 로딩 화면을 보여주는 것을 권장합니다.
측정 시작 시점
세션이 어떤 기기에서 측정되었는지는 세션이 생성될 때(startTracking) 결정됩니다.
- 반드시
setupDidComplete()를 받은 뒤 측정을 시작하세요. setupDidFail을 받았다면 측정을 시작하지 마세요. 등록에 실패해도 이전에 저장된 등록 정보는 그대로 남아 있어, 그대로 측정하면 세션이 이전 기기로 기록될 수 있습니다.- 수면 측정 중에는
setup이 무시됩니다. 연결된 기기가 바뀌었다면 측정을 종료한 뒤 새productInfo로setup을 호출하세요.
저장 정보
- 등록 정보는 앱의
UserDefaults중 SDK 전용 영역에 저장됩니다. - 시리얼 번호 · MAC 주소 원문은 저장하지 않습니다. 값이 바뀌었는지 확인하기 위한 해시값만 저장합니다.
에러 코드
등록 실패는 setupDidFail(error:)로 전달되며, 앱이 다르게 대응해야 하는 두 가지 케이스로 구분됩니다.
| AsleepError | 의미 | 앱이 할 일 |
|---|---|---|
productRegisterFailed | 일시적인 실패. 네트워크 오류, 서버 오류(5xx), 요청 과다(429). SDK가 이미 재시도한 뒤의 결과입니다 | 네트워크 상태를 안내하고 잠시 후 setup을 다시 호출 |
productRegisterRejected | 거부. 입력값 오류, 인증 실패, 등록 권한 없음. 다시 시도해도 결과가 같습니다 | productInfo와 API Key 확인 |
unknown | apiKey가 빈 문자열 | API Key 확인 |
에러의 message는 원인 확인(로그)용이며 문구가 바뀔 수 있습니다. 앱 로직은 에러 케이스(productRegisterFailed / productRegisterRejected)로 분기하세요.
사용 예시
import AsleepSDK
final class SleepSDKController: AsleepSetupDelegate, AsleepConfigDelegate {
private let apiKey: String = "YOUR_API_KEY"
private let userId: String? = nil
private var config: Asleep.Config?
func start() {
let productInfo = Asleep.ProductInfo(
model: "MODEL_NAME",
identifierType: .serial,
identifierValue: "SERIAL_NUMBER"
)
Asleep.setup(apiKey: apiKey,
productInfo: productInfo,
delegate: self)
}
// MARK: - AsleepSetupDelegate
func setupDidComplete() {
// 기기 등록이 끝난 뒤에만 호출됩니다.
Asleep.initAsleepConfig(userId: userId, delegate: self)
}
func setupDidFail(error: Asleep.AsleepError) {
switch error {
case .productRegisterFailed:
// 일시적인 실패 — 네트워크 확인 후 잠시 뒤 setup 재호출
break
case .productRegisterRejected:
// 거부 — productInfo / API Key 확인 (다시 시도해도 결과 동일)
break
default:
break
}
}
func setupInProgress(progress: Int) { }
// MARK: - AsleepConfigDelegate
func userDidJoin(userId: String, config: Asleep.Config) {
self.config = config // 이제 측정을 시작할 수 있습니다.
}
func didFailUserJoin(error: Asleep.AsleepError) { }
func userDidDelete(userId: String) { }
}Updated 36 minutes ago
