수면 기록 수정 API
개요
수면 기록 수정 API는 사용자의 기존 수면 데이터를 수정하고 업데이트하는 기능을 제공합니다. 수면 기록 수정은 수면 여부(DNS), 잠자리에 든 시각, 일어난 시각, 수면의 질, 영향 요인 등의 정보를 변경할 수 있으며, 수정된 데이터는 수면 패턴 분석과 rTIB(Recommended Time In Bed) 재계산에 반영됩니다.
수정 가능한 항목
수면 기록 수정 시 다음과 같은 항목들을 변경할 수 있습니다:
- DNS (Did Not Sleep) 상태 변경: false ↔ true 전환 가능
- 수면 시간 정보:
lot,aet,solMinutes,wasoMinutes - 수면 평가:
sleepQuality - 영향 요인:
positiveFactorIds,negativeFactorIds, 커스텀 요인들 - 기타 정보:
pill,napMinutes
DNS 상태 변경 시 동작
- DNS false → true: 수면 관련 모든 데이터 초기화 (
lot,aet는 epoch time으로,tst,se,sol,waso,sleepQuality는 null로,positiveFactorIds,positiveCustomFactors는 빈 배열로 초기화) - DNS true → false: 필수 수면 데이터 입력 필요
lot,aet필수sleepQuality필수positiveFactorIds또는positiveCustomFactors중 하나 이상 필요negativeFactorIds또는negativeCustomFactors중 하나 이상 필요
수면 지표 재계산
시스템은 수면 기록 수정 시 다음 지표를 자동으로 재계산합니다:
- TST (Total Sleep Time): 총 수면 시간 = TIB - SOL - WASO (분 단위)
- SE (Sleep Efficiency): 수면 효율 = TST / TIB (0~1 사이의 값)
제약사항
- 수면 기록 수정은 당일 일차(현재 진행 중인 dayIndex)에만 가능
- 치료 활동이 일시 정지된 상태에서는 수정 불가
- LOT(잠자리에 든 시각)는 전날 18:00 이후여야 함 (어제 자정부터 1080분 이후)
- LOT, AET는 현재 시간 이전이어야 함 (어제 자정부터 현재까지의 경과 분 범위 내)
- 사용자 지정 요인에서 빈 문자열("")은 없는 값으로 취급
수면 기록 수정
기존 수면 기록의 데이터를 수정합니다.
- HTTP Method:
PATCH - Path:
/v1/sleep/logs/day-index/{dayIndex} - 인증: 액세스 토큰 (
accessToken) 필요
Headers
| Header | Type | Description | Required |
|---|---|---|---|
Content-Type | application/json | 요청 본문 형식을 지정합니다. | Yes |
Authorization | Bearer {accessToken} | 사용자 인증을 통해 발급받은 액세스 토큰입니다. | Yes |
Accept-Language | de-DE, en-US, ko-KR | 오류 메시지의 언어를 지정합니다. 지역 코드를 포함한 형식(예: de-DE, en-US, ko-KR)만 지원합니다. | No |
Path Parameters
| Parameter | Type | Description | Required |
|---|---|---|---|
dayIndex | number | 수정할 수면 기록의 치료 주기 일차 (Kotlin: Int, Swift: Int) | Yes |
Request Body
DNS를 false로 변경하는 경우 예시:
{
"dns": false,
"lot": 1380,
"aet": 1920,
"sleepQuality": 4,
"solMinutes": 30,
"wasoMinutes": 15,
"positiveFactorIds": [1, 3, 5],
"tstMinutes": 450
}
일부 필드만 수정하는 경우 예시:
{
"sleepQuality": 3,
"positiveFactorIds": [1, 2],
"negativeCustomFactors": ["스마트폰 사용", "늦은 저녁 식사"]
}
DNS를 true로 변경하는 경우 예시:
{
"dns": true,
"negativeFactorIds": [2, 4],
"pill": false
}
| 필드 | 타입 | 설명 | DNS=false | DNS=true |
|---|---|---|---|---|
dns | boolean | Did Not Sleep 여부 (전혀 잠을 자지 못했는지) | Optional | Optional |
lot | number | 잠자리에 든 시각 (어제 자정부터의 경과 분, 전날 18:00 이후) | Optional | No |
aet | number | 일어난 시각 (어제 자정부터의 경과 분, LOT보다 이후, 현재 시간 이전) | Optional | No |
sleepQuality | number | 수면의 질 (1점: 매우 나쁨 ~ 5점: 매우 좋음) | Optional | No |
solMinutes | number | 잠들기까지 걸린 시간 (분, 기본값: 0) | Optional | No |
wasoMinutes | number | 수면 중 깬 시간 총합 (분, 기본값: 0) | Optional | No |
positiveFactorIds | number[] | 긍정적 영향 요인 ID 목록 (사전 정의된 요인) | Optional | No |
negativeFactorIds | number[] | 부정적 영향 요인 ID 목록 (사전 정의된 요인) | Optional | Optional |
pill | boolean | 수면제 복용 여부 | Optional | Optional |
napMinutes | number | 낮잠 시간 (분, 기본값: 0) | Optional | Optional |
positiveCustomFactors | string[] | 사용자 지정 긍정적 요인 (최대 10개, 각 100자 이내) | Optional | No |
negativeCustomFactors | string[] | 사용자 지정 부정적 요인 (최대 10개, 각 100자 이내) | Optional | Optional |
tstMinutes | number | 총 수면 시간 (분, 선택사항, 제공 시 계산값과 일치해야 함) | Optional | No |
긍정적 영향 요인 (Positive Factors)
⚠️ 참고: 아래 요인 목록은 임시 데이터이며, 최종 확정된 사항이 아닙니다.
| ID | 독일어 | 한국어 |
|---|---|---|
| 1 | Keine | 없음 |
| 2 | Bewegung an der frischen Luft | 야외에서의 운동 |
| 3 | Gute Stimmung | 좋은 기분 |
| 4 | Sonnenlicht am Tag | 낮 동안의 햇빛 |
| 5 | Entspannungsübung | 이완 운동 |
| 6 | Entspannte Abendroutine | 편안한 저녁 루틴 |
부정적 영향 요인 (Negative Factors)
⚠️ 참고: 아래 요인 목록은 임시 데이터이며, 최종 확정된 사항이 아닙니다.
| ID | 독일어 | 한국어 |
|---|---|---|
| 1 | Keine | 없음 |
| 2 | Stress oder Sorgen | 스트레스나 걱정 |
| 3 | Spätes Arbeiten/Aktivität | 늦은 시간 업무/활동 |
| 4 | Koffein/Alkohol am Abend | 저녁에 카페인/알코올 섭취 |
| 5 | Schmerz oder Unwohlsein | 통증이나 불편함 |
| 6 | Unruhige Schlafumgebung (Licht, Lärm, Hitze) | 불안한 수면 환경 (빛, 소음, 열) |
Responses
| HTTP Status Code | 설명 | Error Code(s) |
|---|---|---|
200 OK | 성공 | - |
400 Bad Request | 잘못된 요청 (필수 필드 누락, 시간 유효성 검증 실패, TST 불일치, 수면 데이터 오류) | 10001, 10009, 10014, 10015, 10017 |
403 Forbidden | 권한 없음 (치료 활동 일시 정지, 날짜 제약 위반) | 10011, 10012 |
404 Not Found | 리소스 없음 (존재하지 않는 수면 기록) | 10040 |
500 Internal Server Error | 서버 내부 오류 | 10000 |
200 OK - 성공
수면 기록 수정 성공 (수면 목표 달성 정보 재계산 포함):
{
"sleepLog": {
"id": "sl_12345",
"dayIndex": 10,
"dns": false,
"lot": 1380,
"aet": 1920,
"tstMinutes": 450,
"sleepEfficiency": 0.9,
"solMinutes": 30,
"wasoMinutes": 15,
"sleepQuality": 4,
"positiveFactorIds": [3, 5],
"negativeFactorIds": [2],
"pill": false,
"napMinutes": 20,
"positiveCustomFactors": ["좋은 베개"],
"negativeCustomFactors": ["옆방 소음"],
"isTemporary": false,
"createdAt": 1715311800000,
"updatedAt": 1715315400000
},
"goalAdherence": {
"id": "adh_12345",
"targetDayIndex": 8,
"sleepGoalId": "sg_12345",
"lotSuccess": true,
"aetSuccess": false,
"createdAt": 1715315400000,
"updatedAt": 1715315400000
}
}
수면 기록 수정 성공 (시간 정보 변경 없음, 목표 달성 정보 재계산 없음):
{
"sleepLog": {
"id": "80117adb-d727-462c-8e84-f60b5180e398",
"dayIndex": 9,
"dns": true,
"lot": null,
"aet": null,
"tstMinutes": null,
"sleepEfficiency": null,
"solMinutes": null,
"wasoMinutes": null,
"sleepQuality": null,
"positiveFactorIds": [],
"negativeFactorIds": [],
"pill": false,
"napMinutes": 30,
"positiveCustomFactors": [],
"negativeCustomFactors": [],
"isTemporary": false,
"createdAt": 1750754142818,
"updatedAt": 1750755467951
},
"goalAdherence": null
}
| 필드 | 타입 | 설명 | 필수 |
|---|---|---|---|
sleepLog | object | 수정된 수면 기록 정보 | Yes |
sleepLog.id | string | 수면 기록 고유 ID | Yes |
sleepLog.dayIndex | number | 치료 주기 일차 | Yes |
sleepLog.dns | boolean | Did Not Sleep 여부 | Yes |
sleepLog.lot | number | 잠자리에 든 시각 (어제 자정부터의 경과 분, DNS=false인 경우에만) | No |
sleepLog.aet | number | 일어난 시각 (어제 자정부터의 경과 분, DNS=false인 경우에만) | No |
sleepLog.tstMinutes | number | 총 수면 시간 (분, 시스템 계산값) | No |
sleepLog.sleepEfficiency | number | 수면 효율 (0~1, 시스템 계산값) | No |
sleepLog.solMinutes | number | 잠들기까지 걸린 시간 (분) | No |
sleepLog.wasoMinutes | number | 수면 중 깬 시간 총합 (분) | No |
sleepLog.sleepQuality | number | 수면의 질 (1점: 매우 나쁨 ~ 5점: 매우 좋음) | No |
sleepLog.positiveFactorIds | array | 긍정적 영향 요인 ID 목록 | No |
sleepLog.negativeFactorIds | array | 부정적 영향 요인 ID 목록 | No |
sleepLog.pill | boolean | 수면제 복용 여부 | Yes |
sleepLog.napMinutes | number | 낮잠 시간 (분) | Yes |
sleepLog.positiveCustomFactors | array | 사용자 지정 긍정적 요인 | No |
sleepLog.negativeCustomFactors | array | 사용자 지정 부정적 요인 | No |
sleepLog.isTemporary | boolean | 임시 기록 여부 (항상 false) | Yes |
sleepLog.createdAt | number | 생성 시각 (Unix timestamp in milliseconds, Kotlin: Long, Swift: Int64) | Yes |
sleepLog.updatedAt | number | 수정 시각 (Unix timestamp in milliseconds, Kotlin: Long, Swift: Int64) | Yes |
goalAdherence | object | 수면 목표 달성 정보 (DNS 상태 변경 또는 시간 정보 변경 시에만 포함) | No |
goalAdherence.id | string | 목표 달성 기록 고유 ID | No |
goalAdherence.targetDayIndex | number | 치료 주기 일차 | No |
goalAdherence.sleepGoalId | string | 수면 목표 ID | No |
goalAdherence.lotSuccess | boolean | 목표 취침 시각 달성 여부 (±30분 이내) | No |
goalAdherence.aetSuccess | boolean | 목표 기상 시각 달성 여부 (±30분 이내) | No |
goalAdherence.createdAt | number | 생성 시각 (Unix timestamp in milliseconds, Kotlin: Long, Swift: Int64) | No |
goalAdherence.updatedAt | number | 수정 시각 (Unix timestamp in milliseconds, Kotlin: Long, Swift: Int64) | No |
400 Bad Request - 잘못된 요청
예시: DNS=false일 때 필수 필드 누락 (MISSING_REQUIRED_FIELDS - 10001)
{
"code": 10001,
"message": "MISSING_REQUIRED_FIELDS",
"detail": "DNS가 false일 때 lot(잠자리에 든 시각)과 aet(일어난 시각)는 필수입니다.",
"metadata": {
"fields": ["lot", "aet"],
"context": "DNS=false일 때 필수 항목"
}
}
예시: DNS=false일 때 sleepQuality 누락 (MISSING_REQUIRED_FIELDS - 10001)
{
"code": 10001,
"message": "MISSING_REQUIRED_FIELDS",
"detail": "DNS가 false일 때 sleepQuality(수면의 질)는 필수입니다.",
"metadata": {
"fields": ["sleepQuality"]
}
}
예시: DNS=false일 때 긍정적 영향 요인 누락 (MISSING_REQUIRED_FIELDS - 10001)
{
"code": 10001,
"message": "MISSING_REQUIRED_FIELDS",
"detail": "DNS가 false일 때 긍정적 영향 요인(positiveFactorIds 또는 positiveCustomFactors) 중 하나 이상이 필요합니다.",
"metadata": {
"fields": ["positiveFactorIds", "positiveCustomFactors"]
}
}
예시: DNS=false일 때 부정적 영향 요인 누락 (MISSING_REQUIRED_FIELDS - 10001)
{
"code": 10001,
"message": "MISSING_REQUIRED_FIELDS",
"detail": "DNS가 false일 때 부정적 영향 요인(negativeFactorIds 또는 negativeCustomFactors) 중 하나 이상이 필요합니다.",
"metadata": {
"fields": ["negativeFactorIds", "negativeCustomFactors"]
}
}
예시: 시간 유효성 검증 실패 (SLEEP_TIME_VALIDATION_FAILED - 10009)
{
"code": 10009,
"message": "SLEEP_TIME_VALIDATION_FAILED",
"detail": "잠자리에 든 시각은 어제 18:00 이후여야 합니다 (사용자 시간대 기준)",
"metadata": {
"lot": 480,
"reason": "잠자리에 든 시각은 어제 18:00 이후여야 합니다 (사용자 시간대 기준)"
}
}
예시: TST 불일치 (INVALID_TST - 10014)
{
"code": 10014,
"message": "INVALID_TST",
"detail": "계산된 총 수면 시간(450분)과 제공된 값(480분)이 일치하지 않습니다",
"metadata": {
"calculated": 450,
"provided": 480
}
}
예시: DNS=true일 때 수면 데이터 포함 (UNEXPECTED_SLEEP_DATA - 10015)
{
"code": 10015,
"message": "UNEXPECTED_SLEEP_DATA",
"detail": "DNS=true인 경우 수면 관련 데이터를 입력할 수 없습니다.",
"metadata": {
"unexpectedFields": ["lot", "aet", "sleepQuality"]
}
}
예시: "없음" 선택 시 사용자 지정 요인 입력 (INVALID_CUSTOM_FACTORS - 10017)
{
"code": 10017,
"message": "INVALID_CUSTOM_FACTORS",
"detail": "긍정적 영향 요인에 '없음'이 선택된 경우 사용자 지정 긍정적 요인을 입력할 수 없습니다.",
"metadata": {
"factorType": "positive",
"selectedFactorIds": [1],
"invalidCustomFactors": ["좋은 베개", "편안한 음악"]
}
}
{
"code": 10017,
"message": "INVALID_CUSTOM_FACTORS",
"detail": "부정적 영향 요인에 '없음'이 선택된 경우 사용자 지정 부정적 요인을 입력할 수 없습니다.",
"metadata": {
"factorType": "negative",
"selectedFactorIds": [1],
"invalidCustomFactors": ["스트레스"]
}
}
403 Forbidden - 권한 없음
예시: 날짜 제약 위반 (INVALID_DAY_INDEX - 10012)
{
"code": 10012,
"message": "INVALID_DAY_INDEX",
"detail": "예상 일차는 10이지만 8을 받았습니다",
"metadata": {
"userId": "user_12345",
"date": 1715299700000,
"expected": 10,
"received": 8,
"message": "예상 일차는 10이지만 8을 받았습니다"
}
}
예시: 치료 활동 일시 정지 (TREATMENT_SUSPENDED - 10011)
{
"code": 10011,
"message": "TREATMENT_SUSPENDED",
"detail": "현재 이 사용자의 치료가 중단된 상태입니다"
}
404 Not Found - 리소스 없음
예시: 수면 기록 없음 (SLEEP_LOG_NOT_FOUND - 10040)
{
"code": 10040,
"message": "SLEEP_LOG_NOT_FOUND",
"detail": "해당 일차의 수면 기록을 찾을 수 없습니다"
}
500 Internal Server Error - 서버 내부 오류
예시: 일반 서버 오류 (SERVER_ERROR - 10000)
{
"code": 10000,
"message": "SERVER_ERROR",
"detail": "서버 내부 오류가 발생했습니다."
}
설명
- 이 API는 사용자가 이미 작성한 수면 기록을 수정할 수 있는 기능을 제공합니다.
- 당일 일차의 수면 기록만 수정 가능하며, 과거 기록은 수정할 수 없습니다.
- DNS 상태 변경 시 관련 필드들이 자동으로 초기화되거나 검증됩니다.
- 데이터 활용:
- 수정된 수면 기록은 rTIB(권장 침대 시간) 재계산에 반영됩니다.
- DNS 상태 변경 또는 시간 정보(lot, aet) 변경 시에만 수면 목표 달성 여부가 자동으로 재계산됩니다.
- 캐시된 데이터도 함께 업데이트되어 실시간 반영됩니다.