본문으로 건너뛰기
버전: 개발 버전 (최신)

학습 이력 배치 저장 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

HeaderTypeDescriptionRequired
AuthorizationstringBearer 토큰 형식의 JWT 액세스 토큰이 필요합니다.Yes
Content-Typestringapplication/jsonYes
Accept-Languagestring응답 언어 (de-DE, ko-KR, en-US). 기본값: de-DEYes

Request Body

필드타입설명예시필수 (Yes/No)
lessonIdstring레슨 IDlesson_123Yes
sessionIdstring세션 ID (클라이언트에서 생성한 학습 세션 식별자)session_20240402_001Yes
eventsLearningHistoryEventDto[]학습 이벤트 목록 (최대 100개)아래 예시 참조Yes

LearningHistoryEventDto

필드타입설명예시필수 (Yes/No)
eventTypeLearningEventType이벤트 타입 (START, PAUSE, RESUME, END)STARTYes
timestampnumber이벤트 발생 시각 (Unix timestamp in milliseconds, Kotlin: Long, Swift: Int64)1712048400000Yes

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)
batchIdstring배치 IDbatch_1712048701234_abc123defYes
lessonIdstring레슨 IDlesson_123Yes
sessionIdstring세션 IDsession_20240402_001Yes
processedCountnumber처리된 이벤트 수4Yes
failedCountnumber실패한 이벤트 수0Yes
resultsBatchResultItemDto[]처리 결과 목록아래 참조Yes
metricsLearningMetricsDto학습 메트릭아래 참조Yes
createdAtnumber생성 시간 (Unix timestamp in milliseconds, Kotlin: Long, Swift: Int64)1712048701000Yes

BatchResultItemDto

필드타입설명예시필수 (Yes/No)
idstring학습 이력 IDhistory_456Yes
eventTypestring이벤트 타입STARTYes
timestampnumber타임스탬프 (Unix timestamp in milliseconds, Kotlin: Long, Swift: Int64)1712048400000Yes
status'SUCCESS' | 'FAILED'처리 상태SUCCESSYes

LearningMetricsDto

필드타입설명예시필수 (Yes/No)
totalLearningTimeMsnumber총 학습 시간 (밀리초, Kotlin: Long, Swift: Int64)300000Yes
activeLearningTimeMsnumber활성 학습 시간 (밀리초, Kotlin: Long, Swift: Int64)240000Yes
pausedTimeMsnumber일시정지 시간 (밀리초, Kotlin: Long, Swift: Int64)60000Yes
pauseCountnumber일시정지 횟수 (Kotlin: Int, Swift: Int)1Yes
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.tssaveLearningHistoryBatch 메서드의 로직을 기반으로 합니다.
  • 주요 처리 단계 (서비스 로직 내):
    1. 사용자 상태 조회: JWT 토큰에서 사용자 ID를 추출하여 활성 사이클 ID 조회 (GetUserStateQuery)
    2. 이벤트 변환: 클라이언트 이벤트를 도메인 이벤트로 변환
    3. 배치 처리 실행: SaveLearningHistoryBatchCommand를 통해 배치 처리
    4. 메트릭 계산: 실시간 학습 메트릭 계산 (총 학습시간, 활성 학습시간, 일시정지 시간 등)
    5. 응답 변환: 처리 결과를 SaveLearningHistoryBatchResponseDto 형태로 변환
  • 메트릭 계산 로직:
    • 총 학습시간: 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.02024-07-17elizabeth@weltcorp.com최초 문서 작성 - 학습 이력 배치 저장 API 문서 생성