학습 이력 배치 저장 API
학습 이력 배치 저장 API는 여러 학습 이벤트를 한 번에 배치 처리하는 API입니다. 네트워크 효율성을 위해 클라이언트에서 수집한 이벤트들을 묶어서 전송할 때 사용합니다.
Enum 정의
LearningEventType
학습 이벤트의 유형을 정의합니다. 자세한 내용은 LearningEventType 문서를 참조하세요.
START: 학습 시작PAUSE: 학습 일시정지RESUME: 학습 재개END: 학습 종료 (자동으로 완료 처리됨)
주의사항
- 배치 크기 제한: 최대 100개의 이벤트까지 처리 가능합니다.
- 사용자 권한: JWT 토큰에서 자동으로 사용자 ID를 추출하므로, 본인의 학습 이력만 저장 가능합니다.
- 타임스탬프 형식: Unix timestamp(밀리초) 형식으로 전송해야 합니다.
- 이벤트 순서: 이벤트들은 타임스탬프 순서대로 정렬되어 처리됩니다.
- 실시간 메트릭: 배치 처리 결과와 함께 실시간 학습 메트릭이 계산됩니다.
학습 이력 배치 저장
여러 학습 이벤트를 한 번에 배치 처리하고 학습 메트릭을 계산하여 응답합니다.
- HTTP Method:
POST - Path:
/learning/history/batch - 인증: Access Token 필요 (Authorization: Bearer
{accessToken})
Headers
| Header | Type | Description | Required |
|---|---|---|---|
Authorization | string | Bearer 토큰 형식의 JWT 액세스 토큰이 필요합니다. | Yes |
Content-Type | string | application/json | Yes |
Accept-Language | string | 응답 언어 (de-DE, ko-KR, en-US). 기본값: de-DE | Yes |
Request Body
| 필드 | 타입 | 설명 | 예시 | 필수 (Yes/No) |
|---|---|---|---|---|
lessonId | string | 레슨 ID | lesson_123 | Yes |
sessionId | string | 세션 ID (클라이언트에서 생성한 학습 세션 식별자) | session_20240402_001 | Yes |
events | LearningHistoryEventDto[] | 학습 이벤트 목록 (최대 100개) | 아래 예시 참조 | Yes |
LearningHistoryEventDto
| 필드 | 타입 | 설명 | 예시 | 필수 (Yes/No) |
|---|---|---|---|---|
eventType | LearningEventType | 이벤트 타입 (START, PAUSE, RESUME, END) | START | Yes |
timestamp | number | 이벤트 발생 시각 (Unix timestamp in milliseconds, Kotlin: Long, Swift: Int64) | 1712048400000 | Yes |
Responses
| HTTP Status Code | 설명 | Error Code(s) |
|---|---|---|
201 Created | 배치 처리 성공 (부분 실패 포함) | - |
400 Bad Request | 잘못된 요청 (유효하지 않은 이벤트 타입) | 11080 |
401 Unauthorized | 인증 실패 (유효하지 않은 토큰) | 2051 |
404 Not Found | 사용자 정보를 찾을 수 없음 | 7008 |
500 Internal Server Error | 서버 내부 오류 | 11000 |
201 Created - 부분 실패가 포함된 배치 처리 성공
일부 이벤트가 실패하더라도 성공한 이벤트가 있으면 201 Created로 응답됩니다.
{
"batchId": "batch_1712048701234_abc123def",
"lessonId": "lesson_123",
"sessionId": "session_20240402_001",
"processedCount": 2,
"failedCount": 2,
"results": [
{
"id": "history_batch_1712048701234_abc123def_0",
"eventType": "START",
"timestamp": 1712048400000,
"status": "SUCCESS"
},
{
"id": "history_batch_1712048701234_abc123def_1",
"eventType": "PAUSE",
"timestamp": 1712048460000,
"status": "SUCCESS"
},
{
"id": "history_batch_1712048701234_abc123def_2",
"eventType": "RESUME",
"timestamp": 1712048520000,
"status": "FAILED"
},
{
"id": "history_batch_1712048701234_abc123def_3",
"eventType": "END",
"timestamp": 1712048700000,
"status": "FAILED"
}
],
"metrics": {
"totalLearningTimeMs": 60000,
"activeLearningTimeMs": 60000,
"pausedTimeMs": 0,
"pauseCount": 1
},
"createdAt": 1712048701000
}
부분 실패 시나리오:
- 레슨이 존재하지 않는 경우
- 활성 세션이 없는 상태에서 PAUSE/END 이벤트 처리 시
- 데이터베이스 일시적 오류로 개별 이벤트 저장 실패
복원력 설계:
- 개별 이벤트 실패가 전체 배치를 중단시키지 않음
- 성공한 이벤트는 정상적으로 저장됨
- 클라이언트는 실패한 이벤트만 재시도 가능
응답 데이터 구조
| 필드 | 타입 | 설명 | 예시 | 필수 (Yes/No) |
|---|---|---|---|---|
batchId | string | 배치 ID | batch_1712048701234_abc123def | Yes |
lessonId | string | 레슨 ID | lesson_123 | Yes |
sessionId | string | 세션 ID | session_20240402_001 | Yes |
processedCount | number | 처리된 이벤트 수 | 4 | Yes |
failedCount | number | 실패한 이벤트 수 | 0 | Yes |
results | BatchResultItemDto[] | 처리 결과 목록 | 아래 참조 | Yes |
metrics | LearningMetricsDto | 학습 메트릭 | 아래 참조 | Yes |
createdAt | number | 생성 시간 (Unix timestamp in milliseconds, Kotlin: Long, Swift: Int64) | 1712048701000 | Yes |
BatchResultItemDto
| 필드 | 타입 | 설명 | 예시 | 필수 (Yes/No) |
|---|---|---|---|---|
id | string | 학습 이력 ID | history_456 | Yes |
eventType | string | 이벤트 타입 | START | Yes |
timestamp | number | 타임스탬프 (Unix timestamp in milliseconds, Kotlin: Long, Swift: Int64) | 1712048400000 | Yes |
status | 'SUCCESS' | 'FAILED' | 처리 상태 | SUCCESS | Yes |
LearningMetricsDto
| 필드 | 타입 | 설명 | 예시 | 필수 (Yes/No) |
|---|---|---|---|---|
totalLearningTimeMs | number | 총 학습 시간 (밀리초, Kotlin: Long, Swift: Int64) | 300000 | Yes |
activeLearningTimeMs | number | 활성 학습 시간 (밀리초, Kotlin: Long, Swift: Int64) | 240000 | Yes |
pausedTimeMs | number | 일시정지 시간 (밀리초, Kotlin: Long, Swift: Int64) | 60000 | Yes |
pauseCount | number | 일시정지 횟수 (Kotlin: Int, Swift: Int) | 1 | Yes |
401 Unauthorized - 인증 실패
{
"code": 2051,
"message": "INVALID_TOKEN",
"detail": "유효하지 않은 토큰입니다."
}
유효하지 않은 액세스 토큰이 제공되었거나 토큰이 만료된 경우 반환됩니다.
400 Bad Request - 유효하지 않은 이벤트 타입
{
"code": 11080,
"message": "INVALID_EVENT_TYPE",
"detail": "유효하지 않은 이벤트 타입입니다. 지원되는 타입: START, PAUSE, RESUME, END"
}
지원하지 않는 이벤트 타입이 전송된 경우 반환됩니다. 지원되는 이벤트 타입: START, PAUSE, RESUME, END
404 Not Found - 사용자를 찾을 수 없음
{
"code": 7008,
"message": "USER_STATE_NOT_FOUND",
"detail": "사용자 정보를 찾을 수 없습니다."
}
JWT 토큰의 사용자 ID에 해당하는 사용자가 존재하지 않는 경우 반환됩니다.
500 Internal Server Error - 서버 내부 오류
{
"code": 11000,
"message": "SERVER_ERROR",
"detail": "서버 내부 오류가 발생했습니다."
}
서버 내부 오류나 데이터베이스 처리 중 예기치 않은 문제가 발생했을 때 반환됩니다.
설명
- 이 API는
apps/dta-wide-api/src/app/learning/services/learning-history.service.ts의saveLearningHistoryBatch메서드의 로직을 기반으로 합니다. - 주요 처리 단계 (서비스 로직 내):
- 사용자 상태 조회: JWT 토큰에서 사용자 ID를 추출하여 활성 사이클 ID 조회 (
GetUserStateQuery) - 이벤트 변환: 클라이언트 이벤트를 도메인 이벤트로 변환
- 배치 처리 실행:
SaveLearningHistoryBatchCommand를 통해 배치 처리 - 메트릭 계산: 실시간 학습 메트릭 계산 (총 학습시간, 활성 학습시간, 일시정지 시간 등)
- 응답 변환: 처리 결과를
SaveLearningHistoryBatchResponseDto형태로 변환
- 사용자 상태 조회: JWT 토큰에서 사용자 ID를 추출하여 활성 사이클 ID 조회 (
- 메트릭 계산 로직:
- 총 학습시간: START부터 END까지의 전체 시간
- 활성 학습시간: 일시정지 시간을 제외한 실제 학습 시간
- 일시정지 시간: PAUSE부터 RESUME까지의 시간 합계
- 일시정지 횟수: PAUSE 이벤트의 발생 횟수
- 이벤트 발행: 배치 처리 시 다음 도메인 이벤트들이 발행됩니다:
LearningHistoryBatchProcessedEvent: 배치 처리 완료 이벤트LearningHistoryBatchFailedEvent: 배치 처리 실패 이벤트 (오류 시)
사용 예시
예시 1: 완전한 학습 세션 (START → PAUSE → RESUME → END)
curl -X POST "https://api.example.com/learning/history/batch" \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." \
-H "Content-Type: application/json" \
-H "Accept-Language: ko-KR" \
-d '{
"lessonId": "lesson_123",
"sessionId": "session_20240402_001",
"events": [
{
"eventType": "START",
"timestamp": 1712048400000
},
{
"eventType": "PAUSE",
"timestamp": 1712048460000
},
{
"eventType": "RESUME",
"timestamp": 1712048520000
},
{
"eventType": "END",
"timestamp": 1712048700000
}
]
}'
응답:
{
"batchId": "batch_1712048701234_abc123def",
"lessonId": "lesson_123",
"sessionId": "session_20240402_001",
"processedCount": 4,
"failedCount": 0,
"results": [
{
"id": "history_batch_1712048701234_abc123def_0",
"eventType": "START",
"timestamp": 1712048400000,
"status": "SUCCESS"
},
{
"id": "history_batch_1712048701234_abc123def_1",
"eventType": "PAUSE",
"timestamp": 1712048460000,
"status": "SUCCESS"
},
{
"id": "history_batch_1712048701234_abc123def_2",
"eventType": "RESUME",
"timestamp": 1712048520000,
"status": "SUCCESS"
},
{
"id": "history_batch_1712048701234_abc123def_3",
"eventType": "END",
"timestamp": 1712048700000,
"status": "SUCCESS"
}
],
"metrics": {
"totalLearningTimeMs": 300000,
"activeLearningTimeMs": 240000,
"pausedTimeMs": 60000,
"pauseCount": 1
},
"createdAt": 1712048701000
}
예시 2: 간단한 학습 세션 (START → END)
curl -X POST "https://api.example.com/learning/history/batch" \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." \
-H "Content-Type: application/json" \
-H "Accept-Language: de-DE" \
-d '{
"lessonId": "lesson_456",
"sessionId": "session_20240402_002",
"events": [
{
"eventType": "START",
"timestamp": 1712049000000
},
{
"eventType": "END",
"timestamp": 1712049300000
}
]
}'
응답:
{
"batchId": "batch_1712049301234_def456ghi",
"lessonId": "lesson_456",
"sessionId": "session_20240402_002",
"processedCount": 2,
"failedCount": 0,
"results": [
{
"id": "history_batch_1712049301234_def456ghi_0",
"eventType": "START",
"timestamp": 1712049000000,
"status": "SUCCESS"
},
{
"id": "history_batch_1712049301234_def456ghi_1",
"eventType": "END",
"timestamp": 1712049300000,
"status": "SUCCESS"
}
],
"metrics": {
"totalLearningTimeMs": 300000,
"activeLearningTimeMs": 300000,
"pausedTimeMs": 0,
"pauseCount": 0
},
"createdAt": 1712049301000
}
활용 사례
- 네트워크 효율성: 여러 학습 이벤트를 한 번에 전송하여 네트워크 호출 횟수 감소
- 실시간 학습 분석: 일시정지/재개가 빈번한 학습 세션의 정확한 시간 추적
- 오프라인 학습 동기화: 네트워크 연결이 불안정한 환경에서 이벤트를 로컬에 저장 후 일괄 전송
- 학습 패턴 분석: 사용자의 학습 중단 패턴, 집중 시간 등 상세한 학습 행동 분석
- 성능 최적화: 대량의 학습 이벤트를 효율적으로 처리하여 서버 리소스 최적화
변경 이력
| 버전 | 날짜 | 작성자 | 변경 내용 |
|---|---|---|---|
| 0.1.0 | 2024-07-17 | elizabeth@weltcorp.com | 최초 문서 작성 - 학습 이력 배치 저장 API 문서 생성 |