앱 설정 정보 조회 API (v2)
앱 설정 정보 조회 API는 모바일 앱 초기화 시 필요한 통합 시스템 설정 정보(시스템 설정·기능 플래그·활성 약관·앱 버전 정책·인증 방식·공지·디바이스 요구사항 등)를 한 번에 조회합니다. v2는 v1의 모든 필드에 더해 **온보딩 콘텐츠(onboarding)**를 추가로 제공하여, 앱 초기화 1콜로 온보딩 영상까지 함께 받을 수 있습니다.
v2 경로의 의미
- v2는 v1 전용 핸들러와 분리된 별도 핸들러(
getAppSettingsV2)이며, 응답 스키마는 v1을 확장한MobileAppSettingsV2ResponseDto입니다 — v1 공통 필드 +onboarding추가. - DE(EU) 클라이언트의 비로그인 약관 표시 대체 경로로 사용됩니다. 응답의
agreements에서 활성 약관 본문을 얻습니다. onboarding.video는GET /v2/learning/onboarding/intro-video와 동일한 인트로 비디오 데이터를 임베드한 것입니다. 온보딩 조회 실패 시 응답을 막지 않고onboarding.video: null로 반환합니다(resilient).
인증 — 가드 없음(비로그인 호출 가능)
- 이 endpoint에는
@UseGuards가 없습니다.@ApiBearerAuth('app-token')은 Swagger 표기상의 보안 스킴일 뿐 실제 토큰 검증을 하지 않으며, 401 응답이 없습니다. - 따라서 App Token 없이도 호출 가능합니다(비로그인 약관 노출 경로). 이 endpoint는 userId를 읽지 않으므로, JWT를 함께 보내더라도
agreements[]에 사용자 동의 상태(agreed/timestamp)는 절대 포함되지 않습니다. 동의 상태는 별도/users/agreements에서 조회합니다.
GET /v2/mobile/app-settings ⭐
모바일 앱 초기화 시 필요한 통합 시스템 설정 정보를 조회합니다.
- Path:
GET /v2/mobile/app-settings - 인증: 가드 없음 (App Token 미검증 — 비로그인 호출 가능)
- Rate Limit: 전역 throttle 60 req / 60s / IP
- 🔗 라이브 명세 (Swagger UI): dev —
Mobile Settings태그
Request
| Header | Type | Required | Description |
|---|---|---|---|
Accept-Language | string | No | 언어 태그 ko-KR | en-US | de-DE (미지정 시 de-DE) |
User-Agent | string | No | {product}/{version} ({platform}; {os}; {device}; {channel}; locale/{locale}) 형식. 파싱 실패 시 400 |
Query Parameter / Request Body 없음.
Response 200 OK — MobileAppSettingsV2ResponseDto
200 OK 예시 (약관에 사용자 동의 상태 미포함 — 이 endpoint의 유일한 응답 형태)
{
"id": "hashcode",
"version": 15,
"systemSettings": {
"globalConfig": {
"sessionTimeoutMinutes": 30,
"maxUploadSizeMB": 10
}
},
"featureFlags": [
{ "name": "enableNewSleepTracking", "isEnabled": true, "description": "New sleep tracking functionality" }
],
"agreements": [
{
"agreementId": "b1f...uuid",
"versionId": "c2e...uuid",
"version": "1.0.0",
"type": "TERMS",
"title": "서비스 이용약관",
"text": "...",
"detailsUrl": "https://www.weltcorp.com/terms",
"orderIndex": 0,
"required": true
}
],
"announcementSummaries": [
{ "id": "announce-123", "title": "새로운 기능이 추가되었습니다", "createdAt": 1747126800000, "isNew": true, "importance": "high" }
],
"appVersion": {
"updateRequired": true,
"forceBlocked": false,
"minimumVersion": "1.6.0",
"latestVersion": "1.8.0",
"deprecatedAt": 1747557000
},
"authenticationMethods": [
{ "type": "email", "isEnabled": true, "displayName": "이메일" }
],
"device": { "minFreeSpaceMB": 500 },
"lastUpdatedAt": 1747557000,
"cacheExpiresAt": 1747600200,
"latestBundleIds": { "relaxation": "a1b2c3d4-e5f6-7890-abcd-ef1234567890" },
"onboarding": {
"video": {
"title": "Lektion 1. Grundlagen",
"media": {
"type": "video",
"description": "BigBuckBunny.",
"urlString": "https://storage.googleapis.com/dta-wide/prod/lesson/1.0.0/de-DE/lesson_01/videos/1.1.mp4"
}
}
}
}
응답 필드
| 필드 | 타입 | 필수 | 설명 |
|---|---|---|---|
id | string | Yes | 현재 AppSettings 버전의 고유 식별자(해시코드) |
version | number | Yes | AppSettings 버전 번호 |
systemSettings | object | No | 시스템 전역 설정 |
systemSettings.globalConfig.sessionTimeoutMinutes | number | No | 세션 타임아웃(분) |
systemSettings.globalConfig.maxUploadSizeMB | number | No | 최대 업로드 크기(MB) |
featureFlags[] | array | No | 기능 플래그 목록 (name, isEnabled, description) |
agreements[] | array | No | 활성 약관 목록 (본문 포함). 아래 표 참조 |
announcementSummaries[] | array | No | 공지 요약 (id, title, createdAt, isNew, importance) |
appVersion | object | No | 앱 버전 호환성 정보. 아래 표 참조 |
mobile | object | No | (deprecated) appVersion으로 대체된 구버전 버전 정보 |
authenticationMethods[] | array | No | 지원 인증 방식 (type, isEnabled, displayName) |
device.minFreeSpaceMB | number | No | 최소 여유 공간(MB) |
lastUpdatedAt | number | No | 마지막 업데이트 시각 (Unix timestamp) |
cacheExpiresAt | number | No | 클라이언트 캐시 만료 시각 (Unix timestamp) |
latestBundleIds.relaxation | string | No | 최신 활성 이완요법 번들 ID (번들 없으면 생략) |
onboarding | object | Yes | (v2 신규) 온보딩 콘텐츠. 아래 표 참조 |
onboarding 필드 (v2 신규)
| 필드 | 타입 | 설명 |
|---|---|---|
onboarding.video | object | null | 활성화 전 "시작 전 영상". 첫 레슨(label=1) 영상. 영상이 없거나 온보딩 조회 실패 시 null |
onboarding.video.title | string | 첫 레슨 제목 (예: Lektion 1. Grundlagen) |
onboarding.video.media | object | null | 영상 미디어. 영상이 없으면 null |
onboarding.video.media.type | string | 미디어 타입 (예: video) |
onboarding.video.media.description | string | 영상 설명 |
onboarding.video.media.urlString | string | GCS 직링크 영상 URL (클라이언트가 직접 재생) |
agreements[] 필드
| 필드 | 타입 | 설명 |
|---|---|---|
agreementId | string | 약관 고유 식별자(UUID) |
versionId | string | 약관 버전 고유 식별자(UUID) |
version | string | 약관 버전 표시 문자열(semver 등, 데이터 없으면 "0") |
type | string | 약관 타입 (TERMS, PRIVACY_POLICY, CONSENT) |
title | string | 약관 제목 |
text | string | 약관 요약 텍스트 |
detailsUrl | string | 약관 상세 URL (선택, DB에 없으면 미포함) |
orderIndex | number | UI 표시 순서(0부터) |
required | boolean | 필수 동의 여부 |
이 endpoint는 비로그인 약관 노출 전용이라
agreements[]에 사용자별 동의 상태(agreed/timestamp)는 포함되지 않습니다. 동의 상태가 필요하면 별도/users/agreements를 사용하세요.
appVersion 필드
| 필드 | 타입 | 설명 |
|---|---|---|
updateRequired | boolean | 업데이트 권장 여부(선택 알림, 사용자가 무시 가능) |
forceBlocked | boolean | 강제 차단 여부(deprecatedAt 이후 필수 업데이트) |
minimumVersion | string | 최소 지원 버전 |
latestVersion | string | 최신 릴리스 버전(정보용) |
deprecatedAt | number | null | 강제 차단 시작 시점(Unix timestamp, null이면 즉시 차단) |
Errors
이 endpoint는 가드가 없어 401 응답이 없습니다.
| HTTP | code | message | 발생 조건 |
|---|---|---|---|
| 400 | 8005 | INVALID_USER_AGENT | User-Agent 헤더가 있으나 파싱 실패(InvalidUserAgentError). HTML 포함 UA(웹뷰)는 예외적으로 통과 |
| 429 | 1000 | ThrottlerException: Too Many Requests | 전역 throttle 초과(60 req / 60s / IP) |
| 500 | 8091 | APP_SETTINGS_ERROR | 활성 AppSettings 없음(AppSettingsError) |
| 500 | 8000 | SERVER_ERROR | 예상치 못한 서버 오류(ServerError 래핑) |
다음 단계
- v2 인증 흐름: eID 로그인 · Native 2FA 로그인 → 서비스 활성화.
- 약관 동의/철회 처리는 별도 agreements API를 통해 수행합니다.
onboarding.video와 동일한 인트로 비디오는 단독 endpointGET /v2/learning/onboarding/intro-video(Learning태그)로도 조회할 수 있습니다. 단독 endpoint는 액세스 토큰이 필요하지만, v2 app-settings에 임베드된 값은 비로그인으로도 조회됩니다.