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

설문 조회 및 응답 흐름

이 문서는 설문 시스템의 진행 흐름과 사용자-백엔드 간 상호작용을 설명합니다. API 엔드포인트에 대한 구체적인 명세는 설문 API 엔드포인트 문서를 참조하세요.

목차

1. 모바일 설문 캐싱 전략

모바일 환경에서는 네트워크 요청을 최소화하기 위해 설문 정보를 효율적으로 캐싱하는 전략이 필요합니다. 특히 설문 회차별로 설문의 내용이 달라지지 않고, 설문 타입은 버전만 동일하다면 계속 동일하므로 캐싱을 통해 API 호출 횟수를 크게 줄일 수 있습니다.

요청 흐름

  1. 앱 실행 시 GET /v1/mobile/app-settings 호출해 앱 설정 정보 및 questionnaireBundle.id (또는 유사한 버전 식별자) 조회
  2. 로컬 캐시에 저장된 questionnaireBundle.id와 비교
  3. 캐시가 없거나 questionnaireBundle.id가 변경된 경우, GET /v1/questionnaires/bundles/{bundleVersion}?includeQuestions=true&includeScoreLevels=true (또는 /v1/questionnaires/active-bundle) API를 호출하여 최신 설문 번들 데이터 전체를 조회하고 로컬 캐시에 저장합니다.
  4. GET /v1/questionnaires/users/me/schedule/next-pending API를 호출하여 현재 사용자가 진행해야 할 설문 회차(roundId) 및 해당 회차 내 설문 목록(questionnaireId 등) 정보를 가져옵니다.
  5. 로컬 캐시에 저장된 설문 번들 데이터와 4번 단계에서 얻은 스케줄 정보를 사용하여 사용자에게 진행할 설문의 UI를 구성하고 보여줍니다.
  6. 사용자가 설문 응답을 완료하면, 해당 응답 데이터만 POST /v1/questionnaires/{questionnaireId}/rounds/{roundId}/responses API를 통해 서버에 제출합니다.

캐싱 구현 전략

  1. 초기 다운로드: 앱 최초 실행 시 모든 활성 설문 정보를 다운로드하여 로컬에 저장
  2. 버전 확인: 앱 실행 시마다 서버의 bundleVersion과 로컬의 bundleVersion을 비교
  3. 선택적 갱신: 버전이 다른 경우에만 새로운 설문 데이터 다운로드
  4. 응답 처리: 설문 UI 구성과 표시는 로컬 데이터 사용, 응답 제출만 API 호출

오프라인 지원

  1. 인터넷 연결이 없는 경우에도 캐싱된 설문 정보로 UI 표시 가능
  2. 응답은 로컬에 임시 저장하고 인터넷 연결 시 서버에 제출
  3. 오프라인 상태에서 설문 완료 시 사용자에게 "인터넷 연결 시 응답이 제출됩니다" 안내

2. 현재 진행 가능한 회차 확인

모바일 앱에서는 사용자에게 설문을 제시하기 위해 먼저 현재 진행 가능한 설문 회차가 있는지 확인해야 합니다.

요청 흐름

  1. 앱 시작 또는 메인 화면 진입 시 사용자의 현재 설문 상태 확인

회차 상태 조회 API 예시

  • HTTP 메서드: GET
  • 경로: /v1/questionnaires/users/me/schedule/next-pending
  • Headers:
    • Content-Type: application/json
    • Authorization: Bearer {accessToken}

응답 (Response)

  • 성공 응답 (200 OK)
{
"userId": "user_123",
"currentDayIndex": 32,
"pendingRounds": [
{
"roundNumber": "SECOND",
"questionnaireIds": ["q_isi123", "q_dbas123", "q_wis123", "q_pss123", "q_gad123", "q_phq123"],
"startDate": 1718323200000, // 29일차
"endDate": 1718928000000, // 35일차
"isSkippable": true
}
],
"completedRounds": [
{
"roundNumber": "FIRST",
"completedAt": 1715616000000
}
],
"skippedRounds": []
}

3. 설문 순차 진행 프로세스

사용자는 설문들을 순차적으로 진행해야 합니다. (이전에 GET /v1/questionnaires/users/me/schedule/next-pending API를 통해 진행할 회차의 roundId와 설문(questionnaireId) 목록을 알고 있다고 가정합니다.) 캐싱된 설문 데이터를 활용하여 UI를 구성하고, 각 설문이 완료된 후에만 서버에 응답을 제출합니다.

요청 흐름

  1. 사용자가 (알고 있는 회차의) 첫 번째 설문 시작 선택
  2. 로컬에 캐싱된 설문 데이터로 첫 번째 설문 UI 구성
  3. 사용자가 모든 문항에 응답 완료
  4. 설문 전체 응답을 한 번에 서버에 제출 (POST /v1/questionnaires/{questionnaireId}/rounds/{roundId}/responses)
  5. 다음 설문으로 자동 이동 (또는 사용자가 다음 설문 시작 선택) 및 2-4 과정 반복

설문 응답 제출 API 예시

  • HTTP 메서드: POST
  • 경로: /v1/questionnaires/{questionnaireId}/rounds/{roundId}/responses
  • Headers:
    • Content-Type: application/json
    • Authorization: Bearer {accessToken}

요청 (Request)

{
"roundId": "round_789",
"questionnaireId": "q_isi123",
"answers": [
{
"questionId": "q_123",
"value": "3",
"metadata": {
"responseTimeMs": 4500
}
},
{
"questionId": "q_124",
"value": "2",
"metadata": {
"responseTimeMs": 3200
}
}
// ... 해당 설문의 모든 문항 응답
],
"completionTimeMs": 45000
}

응답 (Response)

  • 성공 응답 (201 Created)
{
"responseId": "resp_456",
"userId": "user_123",
"roundId": "round_789",
"questionnaireId": "q_isi123",
"status": "COMPLETED",
"score": 15,
"scoreLevel": "sl_isi2",
"submittedAt": 1718497000000,
"resultSummary": {
"levelLabel": "약간의 불면증",
"recommendations": "수면 습관 개선을 위한 몇 가지 조치가 필요합니다."
}
}

이 방식으로 API를 구성하면 요구사항에 명시된 대로 "사용자의 설문 응답 데이터는 설문 단위로 저장"할 수 있습니다. 각 설문을 완료한 후에 한 번만 API를 호출하여 모든 문항 응답을 한꺼번에 전송합니다.

4. 설문 회차 스킵 처리

사용자는 설문을 스킵할 수 있습니다. 스킵된 회차는 유효기간 내에 접속할 경우 다시 진행할 수 있습니다.

요청 흐름

  1. 설문 스킵 요청
  2. 스킵된 회차 유효기간 설정
  3. 스킵된 회차 정보 확인

회차 스킵 API 예시

  • HTTP 메서드: POST
  • 경로: /v1/questionnaire-rounds/{roundId}/skip
  • Headers:
    • Content-Type: application/json
    • Authorization: Bearer {accessToken}

요청 (Request)

{
"reason": "나중에 진행하기 위해 스킵"
}

응답 (Response)

  • 성공 응답 (200 OK)
{
"roundId": "round_789",
"userId": "user_123",
"roundNumber": "SECOND",
"status": "SKIPPED",
"skippedAt": 1718496500000,
"validUntil": 1719101300000, // 현재 + 7일
"message": "설문이 성공적으로 스킵되었습니다. 7일 이내에 완료해주세요."
}
  • 오류 응답 (400 Bad Request)
{
"code": 5052,
"message": "ROUND_CANNOT_BE_SKIPPED",
"detail": "현재 회차는 건너뛸 수 없습니다. (1회차 또는 4회차)"
}

5. 회차별 설문 진행 규칙 (참고)

사용자는 앱 사용 기간에 따라 총 4회의 수면건강조사(설문)를 진행하게 됩니다. 각 회차별 설문 진행 규칙은 다음과 같습니다:

순서진행 시점포함 설문 및 순서스킵 가능 여부
1회차회원 가입 시1. ISI
2. DBAS-16
3. WIS
4. PSS
5. GAD-7
6. PHQ-9
불가능
2회차5주차 (29-35일 접속 중 최초 1회)1. ISI
2. DBAS-16
3. WIS
4. PSS
5. GAD-7
6. PHQ-9
가능
3회차9주차 (57-63일 접속 중 최초 1회)1. ISI
2. DBAS-16
3. WIS
4. PSS
5. GAD-7
6. PHQ-9
가능
4회차사용 종료 후 (91일차 이후 접속 중 최초 1회)1. ISI
2. DBAS-16
3. WIS
4. PSS
5. GAD-7
6. PHQ-9
불가능

모든 회차에서 설문 진행은 위 순서를 따르며, 이전 설문을 완료해야만 다음 설문으로 진행할 수 있습니다.

상세 규칙은 다음 문서를 참조하세요:

변경 이력

버전날짜작성자변경 내용
0.1.02025-05-12bok@weltcorp.com최초 작성 (Questionnaire API 문서에서 분리)
0.2.02025-05-13bok@weltcorp.com모바일 설문 캐싱 전략 및 관련 API 흐름 추가
0.3.02025-05-14bok@weltcorp.com문서 구조 재구성: 모바일 캐싱 전략을 선행 설명으로 배치, 불필요한 API 호출 최소화 방안 반영
0.4.02025-05-15bok@weltcorp.comAPI 설계 변경: 요구사항에 맞게 설문 단위 응답 제출 방식으로 수정