From 8c0a5724c89dbfb8acf1be8a82b6b13d691988ce Mon Sep 17 00:00:00 2001 From: RosieOh Date: Fri, 25 Sep 2026 03:40:37 +0900 Subject: [PATCH] =?UTF-8?q?test:=20=EC=84=9C=EB=B2=84=20OpenAPI=20?= =?UTF-8?q?=EC=8A=A4=ED=8E=99=EA=B3=BC=20=ED=98=B8=EC=B6=9C=20=EA=B2=BD?= =?UTF-8?q?=EB=A1=9C=EB=A5=BC=20=EB=8C=80=EC=A1=B0=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 경로는 문자열이라 타입 검사도 린트도 불일치를 잡지 못한다. 서버에서 지운 경로 (/oauth2/kakao/auth-url)를 계속 불러 메인 화면 카카오 로그인이 무반응이던 일이 있었다. - openapi/openapi.json: 서버가 고정해 둔 스펙의 사본 (원본은 서버 저장소 docs/api/openapi.json) - openapi-contract.test.ts: src/apis/*.ts 의 호출을 스펙과 대조. PR CI 에 포함된다. 경로 변수 자리는 세그먼트 와일드카드로 비교한다 — 프런트의 ${type} 이 경로 변수인지 리터럴 값(privacy-policy)인지 문자열만 보고는 구분할 수 없다. (첫 실행에서 실제로 오탐이 났다) 검사가 무력화되지 않게 "지워진 옛 경로가 스펙에 없다" 도 함께 고정했다. - npm run sync:openapi: 서버 main 에서 사본 갱신. OPENAPI_SRC 로 로컬 파일도 가능. 내용이 스펙 모양이 아니면(404 HTML 등) 실패시킨다. - openapi-drift 워크플로: 매일 서버 main 스펙을 새로 가져와 대조. PR CI 는 사본으로 검사하므로 (결과가 서버 저장소 상태에 흔들리면 안 된다) 사본이 낡는 문제는 이쪽이 잡는다. --- .github/workflows/openapi-drift.yml | 35 + README.md | 21 + openapi/openapi.json | 16212 ++++++++++++++++++ package.json | 3 +- scripts/sync-openapi.mjs | 42 + src/apis/__tests__/openapi-contract.test.ts | 120 + 6 files changed, 16432 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/openapi-drift.yml create mode 100644 openapi/openapi.json create mode 100644 scripts/sync-openapi.mjs create mode 100644 src/apis/__tests__/openapi-contract.test.ts diff --git a/.github/workflows/openapi-drift.yml b/.github/workflows/openapi-drift.yml new file mode 100644 index 0000000..c0f70db --- /dev/null +++ b/.github/workflows/openapi-drift.yml @@ -0,0 +1,35 @@ +# 서버 API 와 어긋났는지 매일 확인한다. +# +# PR CI 는 저장소에 있는 스펙 사본으로 검사한다(결과가 서버 저장소 상태에 따라 흔들리면 안 된다). +# 그래서 사본이 낡으면 어긋남을 못 본다. 이 워크플로가 서버 main 의 스펙을 새로 가져와 대조해, +# 서버가 경로를 바꿨을 때 하루 안에 드러나게 한다. 무관한 PR 을 막지는 않는다. +name: OpenAPI drift + +on: + schedule: + # 매일 09:20 KST (00:20 UTC). 서버 배포가 몰리는 시간대를 지나서 본다. + - cron: '20 0 * * *' + workflow_dispatch: + +jobs: + drift: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-node@v4 + with: + node-version: 24 + cache: npm + + - run: npm ci + + - name: 서버 main 의 스펙 가져오기 + run: npm run sync:openapi + + - name: 가져온 스펙과 대조 + run: npx vitest run src/apis/__tests__/openapi-contract.test.ts + + - name: 사본과 서버 스펙의 차이 보여주기 + if: always() + run: git --no-pager diff --stat -- openapi/openapi.json diff --git a/README.md b/README.md index a971451..7794e0d 100644 --- a/README.md +++ b/README.md @@ -401,6 +401,7 @@ npm run lint # ESLint + Prettier (설정 파일 포함 전체) npm run lint:fix # 자동 수정 npm run typecheck # tsc --noEmit npm test # Vitest +npm run sync:openapi # 서버 API 스펙(openapi/openapi.json) 갱신 ``` `next lint` 는 Next 15.3 에서 deprecated 되어 16 에서 제거되므로 `eslint .` 를 직접 씁니다. @@ -410,6 +411,26 @@ npm test # Vitest 더해 다섯 단계입니다. 계약 테스트가 통과해도 서버 컴포넌트 경계 문제로 빌드가 깨질 수 있어 빌드를 따로 둡니다. +### 서버 API 와 어긋나지 않게 + +경로는 문자열이라 타입 검사도 린트도 불일치를 잡지 못합니다. 실제로 서버에서 지운 경로 +(`/oauth2/kakao/auth-url`)를 계속 불러 **메인 화면 카카오 로그인이 아무 반응 없던** 일이 있었습니다. + +그래서 서버가 저장소에 고정해 둔 OpenAPI 스펙과 `src/apis/*.ts` 의 호출을 대조합니다. + +| | 내용 | +|---|---| +| 스펙 사본 | `openapi/openapi.json` (원본은 서버 저장소 `docs/api/openapi.json`) | +| 대조 테스트 | `src/apis/__tests__/openapi-contract.test.ts` — PR CI 에 포함 | +| 사본 갱신 | `npm run sync:openapi` (서버 main 에서 가져옴, `OPENAPI_SRC` 로 로컬 파일 지정 가능) | +| 사본이 낡는 문제 | 매일 도는 `openapi-drift` 워크플로가 서버 main 스펙을 새로 가져와 대조 | + +사본을 두는 이유는 PR CI 결과가 서버 저장소 상태에 따라 흔들리면 안 되기 때문입니다. +그래서 "사본과 서버가 어긋났는지" 는 매일 도는 워크플로가 따로 봅니다. + +경로 변수 자리(`${facilityId}`)는 한 세그먼트 와일드카드로 비교합니다. 프런트의 `${type}` 이 +경로 변수인지 리터럴 값(`privacy-policy`)인지 문자열만 보고는 구분할 수 없기 때문입니다. + ### 개발 전용 화면 `*.dev.tsx` 확장자를 쓴 페이지는 개발 서버에서만 라우트로 잡히고 프로덕션 번들에서 제외됩니다 diff --git a/openapi/openapi.json b/openapi/openapi.json new file mode 100644 index 0000000..6380429 --- /dev/null +++ b/openapi/openapi.json @@ -0,0 +1,16212 @@ +{ + "components" : { + "schemas" : { + "AdminBookingDetailResponse" : { + "properties" : { + "actualEndTime" : { + "format" : "date-time", + "type" : "string" + }, + "actualStartTime" : { + "format" : "date-time", + "type" : "string" + }, + "bookingType" : { + "type" : "string" + }, + "bookingTypeDisplay" : { + "type" : "string" + }, + "cancellationReason" : { + "type" : "string" + }, + "cancelledAt" : { + "format" : "date-time", + "type" : "string" + }, + "childAge" : { + "format" : "int32", + "type" : "integer" + }, + "childName" : { + "type" : "string" + }, + "createdAt" : { + "format" : "date-time", + "type" : "string" + }, + "endTime" : { + "format" : "date-time", + "type" : "string" + }, + "facilityAddress" : { + "type" : "string" + }, + "facilityId" : { + "format" : "int64", + "type" : "integer" + }, + "facilityName" : { + "type" : "string" + }, + "facilityPhone" : { + "type" : "string" + }, + "id" : { + "format" : "int64", + "type" : "integer" + }, + "notes" : { + "type" : "string" + }, + "parentName" : { + "type" : "string" + }, + "parentPhone" : { + "type" : "string" + }, + "specialRequirements" : { + "type" : "string" + }, + "startTime" : { + "format" : "date-time", + "type" : "string" + }, + "status" : { + "type" : "string" + }, + "statusDisplay" : { + "type" : "string" + }, + "updatedAt" : { + "format" : "date-time", + "type" : "string" + }, + "userEmail" : { + "type" : "string" + }, + "userId" : { + "type" : "string" + }, + "userName" : { + "type" : "string" + } + }, + "type" : "object" + }, + "AdminBookingListResponse" : { + "properties" : { + "bookingType" : { + "type" : "string" + }, + "childName" : { + "type" : "string" + }, + "createdAt" : { + "format" : "date-time", + "type" : "string" + }, + "endTime" : { + "format" : "date-time", + "type" : "string" + }, + "facilityId" : { + "format" : "int64", + "type" : "integer" + }, + "facilityName" : { + "type" : "string" + }, + "id" : { + "format" : "int64", + "type" : "integer" + }, + "startTime" : { + "format" : "date-time", + "type" : "string" + }, + "status" : { + "type" : "string" + }, + "userId" : { + "type" : "string" + }, + "userName" : { + "type" : "string" + } + }, + "type" : "object" + }, + "AdminBookingSearchResponse" : { + "properties" : { + "bookings" : { + "items" : { + "$ref" : "#/components/schemas/AdminBookingListResponse" + }, + "type" : "array" + }, + "currentPage" : { + "format" : "int32", + "type" : "integer" + }, + "hasNext" : { + "type" : "boolean" + }, + "hasPrevious" : { + "type" : "boolean" + }, + "pageSize" : { + "format" : "int32", + "type" : "integer" + }, + "totalElements" : { + "format" : "int64", + "type" : "integer" + }, + "totalPages" : { + "format" : "int32", + "type" : "integer" + } + }, + "type" : "object" + }, + "AdminBookingStatsResponse" : { + "properties" : { + "averageCompletionRate" : { + "format" : "double", + "type" : "number" + }, + "cancelledBookings" : { + "format" : "int64", + "type" : "integer" + }, + "completedBookings" : { + "format" : "int64", + "type" : "integer" + }, + "confirmedBookings" : { + "format" : "int64", + "type" : "integer" + }, + "dailyBookingCounts" : { + "items" : { + "$ref" : "#/components/schemas/DailyBookingCount" + }, + "type" : "array" + }, + "facilityDistribution" : { + "items" : { + "$ref" : "#/components/schemas/FacilityDistribution" + }, + "type" : "array" + }, + "pendingBookings" : { + "format" : "int64", + "type" : "integer" + }, + "statusDistribution" : { + "items" : { + "$ref" : "#/components/schemas/StatusDistribution" + }, + "type" : "array" + }, + "thisMonthBookings" : { + "format" : "int64", + "type" : "integer" + }, + "thisWeekBookings" : { + "format" : "int64", + "type" : "integer" + }, + "todayBookings" : { + "format" : "int64", + "type" : "integer" + }, + "totalBookings" : { + "format" : "int64", + "type" : "integer" + }, + "typeDistribution" : { + "items" : { + "$ref" : "#/components/schemas/TypeDistribution" + }, + "type" : "array" + } + }, + "type" : "object" + }, + "AdminNotificationCreateRequest" : { + "properties" : { + "message" : { + "type" : "string" + }, + "notificationType" : { + "enum" : [ "POLICY", "HEALTH", "COMMUNITY", "FACILITY", "SYSTEM" ], + "type" : "string" + }, + "title" : { + "type" : "string" + }, + "userId" : { + "format" : "int64", + "type" : "integer" + } + }, + "required" : [ "message", "notificationType", "title", "userId" ], + "type" : "object" + }, + "AdminPolicyDetailResponse" : { + "properties" : { + "applicationEndDate" : { + "format" : "date", + "type" : "string" + }, + "applicationStartDate" : { + "format" : "date", + "type" : "string" + }, + "applicationUrl" : { + "type" : "string" + }, + "benefitAmount" : { + "format" : "int32", + "type" : "integer" + }, + "benefitType" : { + "type" : "string" + }, + "contactInfo" : { + "type" : "string" + }, + "createdAt" : { + "format" : "date-time", + "type" : "string" + }, + "description" : { + "type" : "string" + }, + "id" : { + "format" : "int64", + "type" : "integer" + }, + "isActive" : { + "type" : "boolean" + }, + "policyCategoryId" : { + "format" : "int64", + "type" : "integer" + }, + "policyCategoryName" : { + "type" : "string" + }, + "policyCode" : { + "type" : "string" + }, + "policyEndDate" : { + "format" : "date", + "type" : "string" + }, + "policyStartDate" : { + "format" : "date", + "type" : "string" + }, + "policyType" : { + "type" : "string" + }, + "priority" : { + "format" : "int32", + "type" : "integer" + }, + "requiredDocuments" : { + "type" : "string" + }, + "sourceUrl" : { + "type" : "string" + }, + "targetAgeMax" : { + "format" : "int32", + "type" : "integer" + }, + "targetAgeMin" : { + "format" : "int32", + "type" : "integer" + }, + "targetRegion" : { + "type" : "string" + }, + "title" : { + "type" : "string" + }, + "updatedAt" : { + "format" : "date-time", + "type" : "string" + }, + "verifiedAt" : { + "format" : "date-time", + "type" : "string" + }, + "verifiedBy" : { + "type" : "string" + } + }, + "type" : "object" + }, + "AdminPolicyRequest" : { + "properties" : { + "applicationEndDate" : { + "format" : "date", + "type" : "string" + }, + "applicationStartDate" : { + "format" : "date", + "type" : "string" + }, + "applicationUrl" : { + "maxLength" : 500, + "minLength" : 0, + "type" : "string" + }, + "benefitAmount" : { + "format" : "int32", + "type" : "integer" + }, + "benefitType" : { + "maxLength" : 50, + "minLength" : 0, + "type" : "string" + }, + "contactInfo" : { + "maxLength" : 200, + "minLength" : 0, + "type" : "string" + }, + "description" : { + "maxLength" : 2000, + "minLength" : 0, + "type" : "string" + }, + "isActive" : { + "type" : "boolean" + }, + "policyCategoryId" : { + "format" : "int64", + "type" : "integer" + }, + "policyCode" : { + "maxLength" : 50, + "minLength" : 0, + "type" : "string" + }, + "policyEndDate" : { + "format" : "date", + "type" : "string" + }, + "policyStartDate" : { + "format" : "date", + "type" : "string" + }, + "policyType" : { + "maxLength" : 50, + "minLength" : 0, + "type" : "string" + }, + "priority" : { + "format" : "int32", + "type" : "integer" + }, + "requiredDocuments" : { + "maxLength" : 1000, + "minLength" : 0, + "type" : "string" + }, + "targetAgeMax" : { + "format" : "int32", + "type" : "integer" + }, + "targetAgeMin" : { + "format" : "int32", + "type" : "integer" + }, + "targetRegion" : { + "maxLength" : 100, + "minLength" : 0, + "type" : "string" + }, + "title" : { + "maxLength" : 200, + "minLength" : 0, + "type" : "string" + } + }, + "required" : [ "policyCode", "title" ], + "type" : "object" + }, + "AdminStatusUpdateRequest" : { + "properties" : { + "adminNote" : { + "type" : "string" + }, + "reason" : { + "type" : "string" + }, + "status" : { + "type" : "string" + } + }, + "type" : "object" + }, + "AdminUserResponse" : { + "properties" : { + "createdAt" : { + "format" : "date-time", + "type" : "string" + }, + "deletedAt" : { + "format" : "date-time", + "type" : "string" + }, + "email" : { + "type" : "string" + }, + "emailVerified" : { + "type" : "boolean" + }, + "id" : { + "format" : "int64", + "type" : "integer" + }, + "isActive" : { + "type" : "boolean" + }, + "lastLoginAt" : { + "format" : "date-time", + "type" : "string" + }, + "name" : { + "type" : "string" + }, + "phoneNumber" : { + "type" : "string" + }, + "role" : { + "type" : "string" + }, + "userId" : { + "type" : "string" + } + }, + "type" : "object" + }, + "AdminUserUpdateRequest" : { + "properties" : { + "isActive" : { + "type" : "boolean" + }, + "name" : { + "type" : "string" + }, + "phoneNumber" : { + "type" : "string" + }, + "role" : { + "enum" : [ "PARENT", "CAREGIVER", "ADMIN", "GUEST" ], + "type" : "string" + } + }, + "type" : "object" + }, + "AdmissionForecastResponse" : { + "properties" : { + "accuracy" : { + "$ref" : "#/components/schemas/ForecastAccuracyResponse" + }, + "available" : { + "type" : "boolean" + }, + "confidence" : { + "type" : "string" + }, + "facilityId" : { + "format" : "int64", + "type" : "integer" + }, + "facilityName" : { + "type" : "string" + }, + "observationCount" : { + "format" : "int64", + "type" : "integer" + }, + "observationDays" : { + "format" : "int64", + "type" : "integer" + }, + "probability" : { + "format" : "int32", + "type" : "integer" + }, + "reasons" : { + "items" : { + "type" : "string" + }, + "type" : "array" + }, + "targetClass" : { + "type" : "string" + }, + "targetDate" : { + "format" : "date", + "type" : "string" + }, + "unavailableReason" : { + "type" : "string" + } + }, + "type" : "object" + }, + "ApiSuccess" : { + "properties" : { + "message" : { + "type" : "string" + }, + "timestamp" : { + "format" : "date-time", + "type" : "string" + } + }, + "type" : "object" + }, + "AttachmentResponse" : { + "properties" : { + "createdAt" : { + "format" : "date-time", + "type" : "string" + }, + "description" : { + "type" : "string" + }, + "displayOrder" : { + "format" : "int32", + "type" : "integer" + }, + "fileName" : { + "type" : "string" + }, + "fileSize" : { + "format" : "int64", + "type" : "integer" + }, + "fileType" : { + "type" : "string" + }, + "fileUrl" : { + "type" : "string" + }, + "healthRecordId" : { + "format" : "int64", + "type" : "integer" + }, + "id" : { + "format" : "int64", + "type" : "integer" + } + }, + "type" : "object" + }, + "BenefitAmountConsensusResponse" : { + "properties" : { + "agreedCount" : { + "format" : "int64", + "type" : "integer" + }, + "confirmed" : { + "type" : "boolean" + }, + "consensusAmount" : { + "format" : "int32", + "type" : "integer" + }, + "consensusPaymentType" : { + "type" : "string" + }, + "consensusThreshold" : { + "format" : "int32", + "type" : "integer" + }, + "currentAmount" : { + "format" : "int32", + "type" : "integer" + }, + "policyId" : { + "format" : "int64", + "type" : "integer" + }, + "remainingForConsensus" : { + "format" : "int64", + "type" : "integer" + }, + "title" : { + "type" : "string" + }, + "totalReports" : { + "format" : "int64", + "type" : "integer" + } + }, + "type" : "object" + }, + "BenefitAmountReportRequest" : { + "properties" : { + "amount" : { + "format" : "int32", + "maximum" : 100000000, + "minimum" : 0, + "type" : "integer" + }, + "note" : { + "maxLength" : 300, + "minLength" : 0, + "type" : "string" + }, + "paymentType" : { + "pattern" : "MONTHLY|ONE_TIME", + "type" : "string" + }, + "receivedAt" : { + "format" : "date", + "type" : "string" + } + }, + "required" : [ "amount", "paymentType" ], + "type" : "object" + }, + "BodyObject" : { + "properties" : { + "items" : { + "$ref" : "#/components/schemas/ItemsObject" + }, + "numOfRows" : { + "format" : "int32", + "type" : "integer" + }, + "pageNo" : { + "format" : "int32", + "type" : "integer" + }, + "totalCount" : { + "format" : "int32", + "type" : "integer" + } + }, + "type" : "object" + }, + "BookingResponse" : { + "properties" : { + "bookingType" : { + "type" : "string" + }, + "childAge" : { + "format" : "int32", + "type" : "integer" + }, + "childName" : { + "type" : "string" + }, + "createdAt" : { + "format" : "date-time", + "type" : "string" + }, + "endTime" : { + "format" : "date-time", + "type" : "string" + }, + "facilityId" : { + "format" : "int64", + "type" : "integer" + }, + "facilityName" : { + "type" : "string" + }, + "id" : { + "format" : "int64", + "type" : "integer" + }, + "notes" : { + "type" : "string" + }, + "parentName" : { + "type" : "string" + }, + "parentPhone" : { + "type" : "string" + }, + "specialRequirements" : { + "type" : "string" + }, + "startTime" : { + "format" : "date-time", + "type" : "string" + }, + "status" : { + "type" : "string" + }, + "updatedAt" : { + "format" : "date-time", + "type" : "string" + }, + "userId" : { + "type" : "string" + } + }, + "type" : "object" + }, + "Bucket" : { + "properties" : { + "actualRate" : { + "format" : "double", + "type" : "number" + }, + "actualTrue" : { + "format" : "int32", + "type" : "integer" + }, + "from" : { + "format" : "int32", + "type" : "integer" + }, + "samples" : { + "format" : "int32", + "type" : "integer" + }, + "to" : { + "format" : "int32", + "type" : "integer" + } + }, + "type" : "object" + }, + "CareFacilityAdvancedSearchRequest" : { + "description" : "검색 조건", + "properties" : { + "childAge" : { + "format" : "int32", + "type" : "integer" + }, + "facilityType" : { + "enum" : [ "KINDERGARTEN", "DAYCARE", "PLAYGROUP", "NURSERY", "OTHER" ], + "type" : "string" + }, + "isPublic" : { + "type" : "boolean" + }, + "maxTuitionFee" : { + "format" : "int32", + "type" : "integer" + }, + "minAvailableSpots" : { + "format" : "int32", + "type" : "integer" + }, + "minRating" : { + "format" : "double", + "type" : "number" + }, + "sortBy" : { + "type" : "string" + }, + "sortDirection" : { + "type" : "string" + }, + "subsidyAvailable" : { + "type" : "boolean" + } + }, + "type" : "object" + }, + "CareFacilityInfo" : { + "properties" : { + "additionalInfo" : { + "additionalProperties" : { + "type" : "object" + }, + "type" : "object" + }, + "address" : { + "type" : "string" + }, + "amenities" : { + "items" : { + "type" : "string" + }, + "type" : "array" + }, + "createdAt" : { + "format" : "date-time", + "type" : "string" + }, + "description" : { + "type" : "string" + }, + "email" : { + "type" : "string" + }, + "facilityType" : { + "type" : "string" + }, + "id" : { + "format" : "int64", + "type" : "integer" + }, + "imageUrl" : { + "type" : "string" + }, + "isLiked" : { + "type" : "boolean" + }, + "latitude" : { + "format" : "double", + "type" : "number" + }, + "likeCount" : { + "format" : "int64", + "type" : "integer" + }, + "longitude" : { + "format" : "double", + "type" : "number" + }, + "name" : { + "type" : "string" + }, + "operatingHours" : { + "type" : "string" + }, + "phoneNumber" : { + "type" : "string" + }, + "rating" : { + "format" : "double", + "type" : "number" + }, + "reviewCount" : { + "format" : "int64", + "type" : "integer" + }, + "updatedAt" : { + "format" : "date-time", + "type" : "string" + }, + "website" : { + "type" : "string" + } + }, + "type" : "object" + }, + "CareFacilityListResponse" : { + "properties" : { + "currentPage" : { + "format" : "int32", + "type" : "integer" + }, + "facilities" : { + "items" : { + "$ref" : "#/components/schemas/CareFacilityInfo" + }, + "type" : "array" + }, + "hasNext" : { + "type" : "boolean" + }, + "hasPrevious" : { + "type" : "boolean" + }, + "totalCount" : { + "format" : "int64", + "type" : "integer" + }, + "totalPages" : { + "format" : "int32", + "type" : "integer" + } + }, + "type" : "object" + }, + "CareFacilitySearchRequest" : { + "description" : "검색 조건", + "properties" : { + "city" : { + "type" : "string" + }, + "district" : { + "type" : "string" + }, + "facilityType" : { + "type" : "string" + }, + "keyword" : { + "type" : "string" + }, + "latitude" : { + "format" : "double", + "type" : "number" + }, + "longitude" : { + "format" : "double", + "type" : "number" + }, + "page" : { + "format" : "int32", + "type" : "integer" + }, + "radius" : { + "format" : "double", + "type" : "number" + }, + "size" : { + "format" : "int32", + "type" : "integer" + }, + "sortBy" : { + "type" : "string" + }, + "sortDirection" : { + "type" : "string" + } + }, + "type" : "object" + }, + "CareFacilityStatsResponse" : { + "properties" : { + "activeFacilities" : { + "format" : "int64", + "type" : "integer" + }, + "dataUpdatedAt" : { + "format" : "date-time", + "type" : "string" + }, + "thisMonthBookings" : { + "format" : "int64", + "type" : "integer" + }, + "thisWeekBookings" : { + "format" : "int64", + "type" : "integer" + }, + "todayBookings" : { + "format" : "int64", + "type" : "integer" + }, + "totalBookings" : { + "format" : "int64", + "type" : "integer" + }, + "totalFacilities" : { + "format" : "int64", + "type" : "integer" + }, + "typeDistribution" : { + "additionalProperties" : { + "format" : "int64", + "type" : "integer" + }, + "type" : "object" + }, + "typeStats" : { + "items" : { + "$ref" : "#/components/schemas/TypeStats" + }, + "type" : "array" + } + }, + "type" : "object" + }, + "ChatbotChatHistoryDtoResponse" : { + "properties" : { + "confidence" : { + "format" : "double", + "type" : "number" + }, + "createdAt" : { + "format" : "date-time", + "type" : "string" + }, + "intentType" : { + "type" : "string" + }, + "isHelpful" : { + "type" : "boolean" + }, + "message" : { + "type" : "string" + }, + "messageId" : { + "format" : "int64", + "type" : "integer" + }, + "messageType" : { + "type" : "string" + }, + "response" : { + "type" : "string" + }, + "sessionId" : { + "type" : "string" + } + }, + "type" : "object" + }, + "ChatbotFeedbackDtoResponse" : { + "properties" : { + "isHelpful" : { + "type" : "boolean" + }, + "message" : { + "type" : "string" + }, + "messageId" : { + "format" : "int64", + "type" : "integer" + }, + "updatedAt" : { + "format" : "date-time", + "type" : "string" + } + }, + "type" : "object" + }, + "ChatbotMessageRequest" : { + "description" : "챗봇 요청 정보", + "properties" : { + "childAge" : { + "format" : "int32", + "type" : "integer" + }, + "context" : { + "type" : "string" + }, + "message" : { + "type" : "string" + }, + "sessionId" : { + "type" : "string" + }, + "userId" : { + "type" : "string" + } + }, + "type" : "object" + }, + "ChatbotMessageResponse" : { + "properties" : { + "confidence" : { + "format" : "double", + "type" : "number" + }, + "intentType" : { + "type" : "string" + }, + "messageId" : { + "format" : "int64", + "type" : "integer" + }, + "response" : { + "type" : "string" + }, + "sessionId" : { + "type" : "string" + }, + "timestamp" : { + "format" : "date-time", + "type" : "string" + } + }, + "type" : "object" + }, + "ChatbotSessionDtoResponse" : { + "properties" : { + "createdAt" : { + "format" : "date-time", + "type" : "string" + }, + "description" : { + "type" : "string" + }, + "lastActivityAt" : { + "format" : "date-time", + "type" : "string" + }, + "messageCount" : { + "format" : "int32", + "type" : "integer" + }, + "sessionId" : { + "type" : "string" + }, + "status" : { + "type" : "string" + }, + "title" : { + "type" : "string" + } + }, + "type" : "object" + }, + "CheckupScheduleResponse" : { + "properties" : { + "checkupName" : { + "type" : "string" + }, + "completedDate" : { + "type" : "string" + }, + "description" : { + "type" : "string" + }, + "notes" : { + "type" : "string" + }, + "recommendedAge" : { + "format" : "int32", + "type" : "integer" + }, + "scheduledDate" : { + "type" : "string" + }, + "status" : { + "type" : "string" + } + }, + "type" : "object" + }, + "ChildCreateRequest" : { + "properties" : { + "birthDate" : { + "format" : "date", + "type" : "string" + }, + "gender" : { + "maxLength" : 10, + "minLength" : 0, + "type" : "string" + }, + "name" : { + "maxLength" : 100, + "minLength" : 0, + "type" : "string" + }, + "specialNeeds" : { + "maxLength" : 500, + "minLength" : 0, + "type" : "string" + } + }, + "required" : [ "birthDate", "name" ], + "type" : "object" + }, + "ChildInfoResponse" : { + "properties" : { + "birthDate" : { + "type" : "string" + }, + "createdAt" : { + "type" : "string" + }, + "gender" : { + "type" : "string" + }, + "id" : { + "format" : "int64", + "type" : "integer" + }, + "name" : { + "type" : "string" + }, + "specialNeeds" : { + "type" : "string" + }, + "updatedAt" : { + "type" : "string" + }, + "userId" : { + "format" : "int64", + "type" : "integer" + } + }, + "type" : "object" + }, + "ChildSummary" : { + "properties" : { + "ageMonths" : { + "format" : "int32", + "type" : "integer" + }, + "birthDate" : { + "format" : "date", + "type" : "string" + }, + "childId" : { + "format" : "int64", + "type" : "integer" + }, + "classLabel" : { + "type" : "string" + }, + "name" : { + "type" : "string" + }, + "nextVaccination" : { + "type" : "string" + }, + "nextVaccinationDate" : { + "format" : "date", + "type" : "string" + }, + "waitlistCount" : { + "format" : "int64", + "type" : "integer" + } + }, + "type" : "object" + }, + "Cohort" : { + "properties" : { + "day1" : { + "format" : "int32", + "type" : "integer" + }, + "day30" : { + "format" : "int32", + "type" : "integer" + }, + "day7" : { + "format" : "int32", + "type" : "integer" + }, + "signUpDate" : { + "format" : "date", + "type" : "string" + }, + "signedUp" : { + "format" : "int64", + "type" : "integer" + } + }, + "type" : "object" + }, + "CommunityCommentResponse" : { + "properties" : { + "authorId" : { + "type" : "string" + }, + "authorName" : { + "type" : "string" + }, + "commentId" : { + "format" : "int64", + "type" : "integer" + }, + "content" : { + "type" : "string" + }, + "createdAt" : { + "type" : "string" + }, + "isLiked" : { + "type" : "boolean" + }, + "likeCount" : { + "format" : "int32", + "type" : "integer" + }, + "parentCommentId" : { + "format" : "int64", + "type" : "integer" + }, + "replies" : { + "items" : { + "$ref" : "#/components/schemas/CommunityCommentResponse" + }, + "type" : "array" + } + }, + "type" : "object" + }, + "CommunityCreateCommentRequest" : { + "description" : "댓글 정보", + "properties" : { + "content" : { + "maxLength" : 2000, + "minLength" : 0, + "type" : "string" + }, + "isAnonymous" : { + "type" : "boolean" + }, + "parentCommentId" : { + "format" : "int64", + "type" : "integer" + } + }, + "required" : [ "content" ], + "type" : "object" + }, + "CommunityCreatePostRequest" : { + "description" : "게시글 정보", + "properties" : { + "category" : { + "type" : "string" + }, + "content" : { + "maxLength" : 10000, + "minLength" : 0, + "type" : "string" + }, + "isAnonymous" : { + "type" : "boolean" + }, + "tags" : { + "items" : { + "type" : "string" + }, + "type" : "array" + }, + "title" : { + "maxLength" : 200, + "minLength" : 0, + "type" : "string" + } + }, + "required" : [ "content", "title" ], + "type" : "object" + }, + "CommunityPageResponseCommunityPostResponse" : { + "properties" : { + "content" : { + "items" : { + "$ref" : "#/components/schemas/CommunityPostResponse" + }, + "type" : "array" + }, + "first" : { + "type" : "boolean" + }, + "hasNext" : { + "type" : "boolean" + }, + "hasPrevious" : { + "type" : "boolean" + }, + "last" : { + "type" : "boolean" + }, + "page" : { + "format" : "int32", + "type" : "integer" + }, + "size" : { + "format" : "int32", + "type" : "integer" + }, + "totalElements" : { + "format" : "int64", + "type" : "integer" + }, + "totalPages" : { + "format" : "int32", + "type" : "integer" + } + }, + "type" : "object" + }, + "CommunityPostDetailResponse" : { + "properties" : { + "authorId" : { + "type" : "string" + }, + "authorName" : { + "type" : "string" + }, + "category" : { + "type" : "string" + }, + "commentCount" : { + "format" : "int32", + "type" : "integer" + }, + "comments" : { + "items" : { + "$ref" : "#/components/schemas/CommunityCommentResponse" + }, + "type" : "array" + }, + "content" : { + "type" : "string" + }, + "createdAt" : { + "type" : "string" + }, + "isAnonymous" : { + "type" : "boolean" + }, + "isBookmarked" : { + "type" : "boolean" + }, + "isLiked" : { + "type" : "boolean" + }, + "likeCount" : { + "format" : "int32", + "type" : "integer" + }, + "postId" : { + "format" : "int64", + "type" : "integer" + }, + "relatedPosts" : { + "items" : { + "$ref" : "#/components/schemas/CommunityRelatedPostResponse" + }, + "type" : "array" + }, + "tags" : { + "items" : { + "type" : "string" + }, + "type" : "array" + }, + "title" : { + "type" : "string" + }, + "viewCount" : { + "format" : "int32", + "type" : "integer" + } + }, + "type" : "object" + }, + "CommunityPostResponse" : { + "properties" : { + "authorId" : { + "type" : "string" + }, + "authorName" : { + "type" : "string" + }, + "category" : { + "type" : "string" + }, + "commentCount" : { + "format" : "int32", + "type" : "integer" + }, + "content" : { + "type" : "string" + }, + "createdAt" : { + "type" : "string" + }, + "isAnonymous" : { + "type" : "boolean" + }, + "isBookmarked" : { + "type" : "boolean" + }, + "isLiked" : { + "type" : "boolean" + }, + "likeCount" : { + "format" : "int32", + "type" : "integer" + }, + "postId" : { + "format" : "int64", + "type" : "integer" + }, + "tags" : { + "items" : { + "type" : "string" + }, + "type" : "array" + }, + "title" : { + "type" : "string" + }, + "viewCount" : { + "format" : "int32", + "type" : "integer" + } + }, + "type" : "object" + }, + "CommunityRelatedPostResponse" : { + "properties" : { + "category" : { + "type" : "string" + }, + "likeCount" : { + "format" : "int32", + "type" : "integer" + }, + "postId" : { + "format" : "int64", + "type" : "integer" + }, + "title" : { + "type" : "string" + }, + "viewCount" : { + "format" : "int32", + "type" : "integer" + } + }, + "type" : "object" + }, + "CommunityTagResponse" : { + "properties" : { + "createdAt" : { + "type" : "string" + }, + "description" : { + "type" : "string" + }, + "id" : { + "format" : "int64", + "type" : "integer" + }, + "name" : { + "type" : "string" + } + }, + "type" : "object" + }, + "CommunityUpdateCommentRequest" : { + "description" : "수정할 댓글 정보", + "properties" : { + "content" : { + "maxLength" : 2000, + "minLength" : 0, + "type" : "string" + } + }, + "required" : [ "content" ], + "type" : "object" + }, + "CommunityUpdatePostRequest" : { + "description" : "수정할 게시글 정보", + "properties" : { + "category" : { + "type" : "string" + }, + "content" : { + "maxLength" : 10000, + "minLength" : 0, + "type" : "string" + }, + "tags" : { + "items" : { + "type" : "string" + }, + "type" : "array" + }, + "title" : { + "maxLength" : 200, + "minLength" : 0, + "type" : "string" + } + }, + "required" : [ "content", "title" ], + "type" : "object" + }, + "ConsentHistoryItem" : { + "properties" : { + "consentType" : { + "type" : "string" + }, + "createdAt" : { + "format" : "date-time", + "type" : "string" + }, + "displayName" : { + "type" : "string" + }, + "granted" : { + "type" : "boolean" + }, + "policyVersion" : { + "type" : "string" + } + }, + "type" : "object" + }, + "ConsentItem" : { + "properties" : { + "consentType" : { + "type" : "string" + }, + "displayName" : { + "type" : "string" + }, + "granted" : { + "type" : "boolean" + }, + "policyVersion" : { + "type" : "string" + }, + "required" : { + "type" : "boolean" + }, + "updatedAt" : { + "format" : "date-time", + "type" : "string" + } + }, + "type" : "object" + }, + "ConsentStatusResponse" : { + "properties" : { + "consents" : { + "items" : { + "$ref" : "#/components/schemas/ConsentItem" + }, + "type" : "array" + } + }, + "type" : "object" + }, + "ConsentUpdateRequest" : { + "properties" : { + "consentType" : { + "enum" : [ "TERMS_OF_SERVICE", "PRIVACY_POLICY", "CHILD_DATA", "HEALTH_DATA", "MARKETING", "THIRD_PARTY_SHARING" ], + "type" : "string" + }, + "granted" : { + "type" : "boolean" + }, + "policyVersion" : { + "type" : "string" + } + }, + "required" : [ "consentType", "policyVersion" ], + "type" : "object" + }, + "Contribution" : { + "properties" : { + "amount" : { + "format" : "int64", + "type" : "integer" + }, + "paymentType" : { + "type" : "string" + }, + "title" : { + "type" : "string" + } + }, + "type" : "object" + }, + "CreateBookingRequest" : { + "description" : "예약 정보", + "properties" : { + "bookingType" : { + "type" : "string" + }, + "childAge" : { + "format" : "int32", + "type" : "integer" + }, + "childName" : { + "type" : "string" + }, + "endTime" : { + "format" : "date-time", + "type" : "string" + }, + "notes" : { + "type" : "string" + }, + "parentName" : { + "type" : "string" + }, + "parentPhone" : { + "type" : "string" + }, + "specialRequirements" : { + "type" : "string" + }, + "startTime" : { + "format" : "date-time", + "type" : "string" + } + }, + "type" : "object" + }, + "DailyBookingCount" : { + "properties" : { + "count" : { + "format" : "int64", + "type" : "integer" + }, + "date" : { + "type" : "string" + } + }, + "type" : "object" + }, + "FacilityDistribution" : { + "properties" : { + "count" : { + "format" : "int64", + "type" : "integer" + }, + "facilityId" : { + "format" : "int64", + "type" : "integer" + }, + "facilityName" : { + "type" : "string" + }, + "percentage" : { + "format" : "double", + "type" : "number" + } + }, + "type" : "object" + }, + "FacilityPopularityResponse" : { + "properties" : { + "available" : { + "type" : "boolean" + }, + "averageFillRate" : { + "format" : "int32", + "type" : "integer" + }, + "demandLevel" : { + "type" : "string" + }, + "facilityId" : { + "format" : "int64", + "type" : "integer" + }, + "facilityName" : { + "type" : "string" + }, + "fullRatio" : { + "format" : "int32", + "type" : "integer" + }, + "latestFillRate" : { + "format" : "int32", + "type" : "integer" + }, + "observationCount" : { + "format" : "int64", + "type" : "integer" + }, + "reasons" : { + "items" : { + "type" : "string" + }, + "type" : "array" + }, + "sharpDropDates" : { + "items" : { + "format" : "date", + "type" : "string" + }, + "type" : "array" + }, + "trend" : { + "type" : "string" + }, + "unavailableReason" : { + "type" : "string" + } + }, + "type" : "object" + }, + "ForecastAccuracyResponse" : { + "properties" : { + "actualRate" : { + "format" : "double", + "type" : "number" + }, + "baselineBrierScore" : { + "format" : "double", + "type" : "number" + }, + "betterThanBaseline" : { + "type" : "boolean" + }, + "brierScore" : { + "format" : "double", + "type" : "number" + }, + "calibration" : { + "items" : { + "$ref" : "#/components/schemas/Bucket" + }, + "type" : "array" + }, + "facilities" : { + "format" : "int32", + "type" : "integer" + }, + "horizonMonths" : { + "format" : "int32", + "type" : "integer" + }, + "matchedBucket" : { + "$ref" : "#/components/schemas/Bucket" + }, + "measuredAt" : { + "format" : "date", + "type" : "string" + }, + "samples" : { + "format" : "int32", + "type" : "integer" + } + }, + "type" : "object" + }, + "FunnelResponse" : { + "properties" : { + "from" : { + "format" : "date", + "type" : "string" + }, + "steps" : { + "items" : { + "$ref" : "#/components/schemas/Step" + }, + "type" : "array" + }, + "to" : { + "format" : "date", + "type" : "string" + } + }, + "type" : "object" + }, + "GrowthPointResponse" : { + "properties" : { + "ageMonths" : { + "format" : "int32", + "type" : "integer" + }, + "interpretation" : { + "type" : "string" + }, + "medianValue" : { + "format" : "double", + "type" : "number" + }, + "metric" : { + "type" : "string" + }, + "needsAttention" : { + "type" : "boolean" + }, + "percentile" : { + "format" : "double", + "type" : "number" + }, + "recordDate" : { + "format" : "date", + "type" : "string" + }, + "unit" : { + "type" : "string" + }, + "value" : { + "format" : "double", + "type" : "number" + }, + "zScore" : { + "format" : "double", + "type" : "number" + } + }, + "type" : "object" + }, + "Header" : { + "properties" : { + "resultCode" : { + "type" : "string" + }, + "resultMsg" : { + "type" : "string" + } + }, + "type" : "object" + }, + "HealthAlertResponse" : { + "properties" : { + "alertId" : { + "type" : "string" + }, + "alertType" : { + "type" : "string" + }, + "dueDate" : { + "type" : "string" + }, + "isRead" : { + "type" : "boolean" + }, + "message" : { + "type" : "string" + }, + "priority" : { + "type" : "string" + }, + "title" : { + "type" : "string" + } + }, + "type" : "object" + }, + "HealthCreateHealthRecordRequest" : { + "description" : "건강 정보", + "properties" : { + "bloodPressure" : { + "type" : "string" + }, + "childId" : { + "type" : "string" + }, + "description" : { + "type" : "string" + }, + "doctorName" : { + "type" : "string" + }, + "height" : { + "exclusiveMaximum" : false, + "exclusiveMinimum" : true, + "format" : "double", + "maximum" : 250.0, + "minimum" : 0.0, + "type" : "number" + }, + "hospitalName" : { + "type" : "string" + }, + "location" : { + "type" : "string" + }, + "nextDate" : { + "format" : "date-time", + "type" : "string" + }, + "pulseRate" : { + "format" : "int32", + "maximum" : 300, + "minimum" : 0, + "type" : "integer" + }, + "recordDate" : { + "format" : "date-time", + "type" : "string" + }, + "recordType" : { + "type" : "string" + }, + "temperature" : { + "exclusiveMaximum" : false, + "exclusiveMinimum" : false, + "format" : "double", + "maximum" : 45.0, + "minimum" : 30.0, + "type" : "number" + }, + "title" : { + "type" : "string" + }, + "vaccineName" : { + "type" : "string" + }, + "weight" : { + "exclusiveMaximum" : false, + "exclusiveMinimum" : true, + "format" : "double", + "maximum" : 200.0, + "minimum" : 0.0, + "type" : "number" + } + }, + "required" : [ "childId", "recordDate", "recordType", "title" ], + "type" : "object" + }, + "HealthCreateHospitalReviewRequest" : { + "description" : "리뷰 정보", + "properties" : { + "content" : { + "type" : "string" + }, + "hospitalId" : { + "format" : "int64", + "type" : "integer" + }, + "rating" : { + "format" : "int32", + "type" : "integer" + } + }, + "required" : [ "content", "hospitalId", "rating" ], + "type" : "object" + }, + "HealthRecordAttachmentRequest" : { + "properties" : { + "description" : { + "type" : "string" + }, + "displayOrder" : { + "format" : "int32", + "type" : "integer" + }, + "fileName" : { + "type" : "string" + }, + "fileSize" : { + "format" : "int64", + "type" : "integer" + }, + "fileType" : { + "type" : "string" + }, + "fileUrl" : { + "type" : "string" + } + }, + "type" : "object" + }, + "HealthRecordAttachmentResponse" : { + "properties" : { + "attachmentId" : { + "format" : "int64", + "type" : "integer" + }, + "createdAt" : { + "format" : "date-time", + "type" : "string" + }, + "description" : { + "type" : "string" + }, + "displayOrder" : { + "format" : "int32", + "type" : "integer" + }, + "fileName" : { + "type" : "string" + }, + "fileSize" : { + "format" : "int64", + "type" : "integer" + }, + "fileType" : { + "type" : "string" + }, + "fileUrl" : { + "type" : "string" + }, + "recordId" : { + "format" : "int64", + "type" : "integer" + } + }, + "type" : "object" + }, + "HealthRecordResponse" : { + "properties" : { + "bloodPressure" : { + "type" : "string" + }, + "childId" : { + "type" : "string" + }, + "childName" : { + "type" : "string" + }, + "createdAt" : { + "type" : "string" + }, + "description" : { + "type" : "string" + }, + "doctorName" : { + "type" : "string" + }, + "height" : { + "format" : "double", + "type" : "number" + }, + "hospitalName" : { + "type" : "string" + }, + "id" : { + "format" : "int64", + "type" : "integer" + }, + "isCompleted" : { + "type" : "boolean" + }, + "location" : { + "type" : "string" + }, + "nextDate" : { + "type" : "string" + }, + "pulseRate" : { + "format" : "int32", + "type" : "integer" + }, + "recordDate" : { + "type" : "string" + }, + "recordType" : { + "type" : "string" + }, + "temperature" : { + "format" : "double", + "type" : "number" + }, + "title" : { + "type" : "string" + }, + "updatedAt" : { + "type" : "string" + }, + "userId" : { + "type" : "string" + }, + "vaccineName" : { + "type" : "string" + }, + "weight" : { + "format" : "double", + "type" : "number" + } + }, + "type" : "object" + }, + "HealthStatsResponse" : { + "properties" : { + "completedCheckups" : { + "format" : "int32", + "type" : "integer" + }, + "completedVaccines" : { + "format" : "int32", + "type" : "integer" + }, + "pendingCheckups" : { + "format" : "int32", + "type" : "integer" + }, + "pendingVaccines" : { + "format" : "int32", + "type" : "integer" + }, + "recordTypeDistribution" : { + "additionalProperties" : { + "format" : "int32", + "type" : "integer" + }, + "type" : "object" + }, + "totalRecords" : { + "format" : "int32", + "type" : "integer" + }, + "upcomingEvents" : { + "items" : { + "type" : "string" + }, + "type" : "array" + } + }, + "type" : "object" + }, + "HealthUpdateHealthRecordRequest" : { + "description" : "수정할 건강 정보", + "properties" : { + "bloodPressure" : { + "type" : "string" + }, + "description" : { + "type" : "string" + }, + "doctorName" : { + "type" : "string" + }, + "height" : { + "exclusiveMaximum" : false, + "exclusiveMinimum" : true, + "format" : "double", + "maximum" : 250.0, + "minimum" : 0.0, + "type" : "number" + }, + "hospitalName" : { + "type" : "string" + }, + "isCompleted" : { + "type" : "boolean" + }, + "location" : { + "type" : "string" + }, + "nextDate" : { + "format" : "date-time", + "type" : "string" + }, + "pulseRate" : { + "format" : "int32", + "maximum" : 300, + "minimum" : 0, + "type" : "integer" + }, + "recordDate" : { + "format" : "date-time", + "type" : "string" + }, + "temperature" : { + "exclusiveMaximum" : false, + "exclusiveMinimum" : false, + "format" : "double", + "maximum" : 45.0, + "minimum" : 30.0, + "type" : "number" + }, + "title" : { + "type" : "string" + }, + "vaccineName" : { + "type" : "string" + }, + "weight" : { + "exclusiveMaximum" : false, + "exclusiveMinimum" : true, + "format" : "double", + "maximum" : 200.0, + "minimum" : 0.0, + "type" : "number" + } + }, + "required" : [ "recordDate", "title" ], + "type" : "object" + }, + "HealthUpdateHospitalReviewRequest" : { + "description" : "수정할 리뷰 정보", + "properties" : { + "content" : { + "type" : "string" + }, + "rating" : { + "format" : "int32", + "type" : "integer" + } + }, + "required" : [ "content", "rating" ], + "type" : "object" + }, + "HospitalInfoResponse" : { + "properties" : { + "address" : { + "type" : "string" + }, + "createdAt" : { + "type" : "string" + }, + "grade" : { + "type" : "string" + }, + "id" : { + "format" : "int64", + "type" : "integer" + }, + "latitude" : { + "format" : "double", + "type" : "number" + }, + "longitude" : { + "format" : "double", + "type" : "number" + }, + "name" : { + "type" : "string" + }, + "phoneNumber" : { + "type" : "string" + }, + "type" : { + "type" : "string" + }, + "updatedAt" : { + "type" : "string" + } + }, + "type" : "object" + }, + "HospitalLikeStatusResponse" : { + "properties" : { + "hospitalId" : { + "format" : "int64", + "type" : "integer" + }, + "likeCount" : { + "format" : "int64", + "type" : "integer" + }, + "liked" : { + "type" : "boolean" + } + }, + "type" : "object" + }, + "HospitalReviewResponse" : { + "properties" : { + "content" : { + "type" : "string" + }, + "createdAt" : { + "type" : "string" + }, + "hospitalId" : { + "format" : "int64", + "type" : "integer" + }, + "hospitalName" : { + "type" : "string" + }, + "id" : { + "format" : "int64", + "type" : "integer" + }, + "rating" : { + "format" : "int32", + "type" : "integer" + }, + "updatedAt" : { + "type" : "string" + }, + "userId" : { + "format" : "int64", + "type" : "integer" + }, + "userName" : { + "type" : "string" + } + }, + "type" : "object" + }, + "HospitalStatsResponse" : { + "properties" : { + "byType" : { + "additionalProperties" : { + "format" : "int64", + "type" : "integer" + }, + "type" : "object" + }, + "dataUpdatedAt" : { + "format" : "date-time", + "type" : "string" + }, + "totalHospitals" : { + "format" : "int64", + "type" : "integer" + } + }, + "type" : "object" + }, + "ItemsObject" : { + "properties" : { + "item" : { + "items" : { + "type" : "object" + }, + "type" : "array" + } + }, + "type" : "object" + }, + "JsonNode" : { + "type" : "object" + }, + "KakaoRegistrationRequest" : { + "description" : "가입 완료 정보", + "properties" : { + "name" : { + "description" : "사용자 이름", + "example" : "홍길동", + "type" : "string" + }, + "role" : { + "description" : "역할", + "enum" : [ "PARENT", "CAREGIVER", "ADMIN", "GUEST" ], + "example" : "PARENT", + "pattern" : "^(PARENT|CAREGIVER|ADMIN|GUEST)$", + "type" : "string" + } + }, + "required" : [ "name", "role" ], + "type" : "object" + }, + "LoginRequestDto" : { + "description" : "로그인 정보", + "properties" : { + "email" : { + "type" : "string" + }, + "password" : { + "type" : "string" + } + }, + "type" : "object" + }, + "MissedBenefitResponse" : { + "properties" : { + "applicationUrl" : { + "type" : "string" + }, + "benefitAmount" : { + "format" : "int32", + "type" : "integer" + }, + "childName" : { + "type" : "string" + }, + "claimable" : { + "type" : "boolean" + }, + "eligibleFromMonth" : { + "format" : "int32", + "type" : "integer" + }, + "eligibleToMonth" : { + "format" : "int32", + "type" : "integer" + }, + "policyId" : { + "format" : "int64", + "type" : "integer" + }, + "reasons" : { + "items" : { + "type" : "string" + }, + "type" : "array" + }, + "remainingMonths" : { + "format" : "int32", + "type" : "integer" + }, + "title" : { + "type" : "string" + } + }, + "type" : "object" + }, + "MissedBenefitSummaryResponse" : { + "properties" : { + "claimable" : { + "items" : { + "$ref" : "#/components/schemas/MissedBenefitResponse" + }, + "type" : "array" + }, + "claimableAmount" : { + "format" : "int64", + "type" : "integer" + }, + "claimableCount" : { + "format" : "int32", + "type" : "integer" + }, + "expired" : { + "items" : { + "$ref" : "#/components/schemas/MissedBenefitResponse" + }, + "type" : "array" + }, + "expiredCount" : { + "format" : "int32", + "type" : "integer" + }, + "unknownEligibilityCount" : { + "format" : "int32", + "type" : "integer" + } + }, + "type" : "object" + }, + "NotificationChannelStatusResponse" : { + "properties" : { + "available" : { + "type" : "boolean" + }, + "channel" : { + "type" : "string" + }, + "displayName" : { + "type" : "string" + }, + "reasonCode" : { + "type" : "string" + }, + "unavailableReason" : { + "type" : "string" + } + }, + "type" : "object" + }, + "NotificationCreateRequest" : { + "description" : "알림 정보", + "properties" : { + "message" : { + "type" : "string" + }, + "notificationType" : { + "type" : "string" + }, + "priority" : { + "type" : "string" + }, + "scheduledAt" : { + "format" : "date-time", + "type" : "string" + }, + "title" : { + "type" : "string" + }, + "userId" : { + "type" : "string" + } + }, + "required" : [ "message", "notificationType", "title", "userId" ], + "type" : "object" + }, + "NotificationDeliveryStatusResponse" : { + "properties" : { + "deliveredAt" : { + "type" : "string" + }, + "deliveryMethod" : { + "type" : "string" + }, + "deliveryStatus" : { + "type" : "string" + }, + "errorMessage" : { + "type" : "string" + }, + "notificationId" : { + "format" : "int64", + "type" : "integer" + }, + "sentAt" : { + "type" : "string" + } + }, + "type" : "object" + }, + "NotificationInfoResponse" : { + "properties" : { + "createdAt" : { + "format" : "date-time", + "type" : "string" + }, + "deliveryStatus" : { + "type" : "string" + }, + "id" : { + "format" : "int64", + "type" : "integer" + }, + "isRead" : { + "type" : "boolean" + }, + "message" : { + "type" : "string" + }, + "notificationType" : { + "type" : "string" + }, + "priority" : { + "type" : "string" + }, + "readAt" : { + "format" : "date-time", + "type" : "string" + }, + "scheduledAt" : { + "format" : "date-time", + "type" : "string" + }, + "sentAt" : { + "format" : "date-time", + "type" : "string" + }, + "title" : { + "type" : "string" + }, + "userId" : { + "type" : "string" + } + }, + "type" : "object" + }, + "NotificationMarkAsReadRequest" : { + "description" : "읽음 처리 요청", + "properties" : { + "markAllAsRead" : { + "type" : "boolean" + }, + "notificationIds" : { + "items" : { + "format" : "int64", + "type" : "integer" + }, + "type" : "array" + } + }, + "type" : "object" + }, + "NotificationRegisterPushTokenRequest" : { + "description" : "푸시 토큰 등록 요청", + "properties" : { + "appVersion" : { + "type" : "string" + }, + "deviceType" : { + "type" : "string" + }, + "pushToken" : { + "type" : "string" + }, + "userId" : { + "type" : "string" + } + }, + "required" : [ "pushToken", "userId" ], + "type" : "object" + }, + "NotificationSendTestRequest" : { + "description" : "테스트 알림 요청", + "properties" : { + "message" : { + "type" : "string" + }, + "title" : { + "type" : "string" + }, + "type" : { + "type" : "string" + } + }, + "type" : "object" + }, + "NotificationSettingsResponse" : { + "description" : "알림 설정", + "properties" : { + "createdAt" : { + "format" : "date-time", + "type" : "string" + }, + "deviceToken" : { + "type" : "string" + }, + "emailAddress" : { + "type" : "string" + }, + "emailEnabled" : { + "type" : "boolean" + }, + "id" : { + "format" : "int64", + "type" : "integer" + }, + "inAppEnabled" : { + "type" : "boolean" + }, + "notificationType" : { + "type" : "string" + }, + "phoneNumber" : { + "type" : "string" + }, + "pushEnabled" : { + "type" : "boolean" + }, + "smsEnabled" : { + "type" : "boolean" + }, + "updatedAt" : { + "format" : "date-time", + "type" : "string" + }, + "userId" : { + "type" : "string" + } + }, + "type" : "object" + }, + "NotificationStatsResponse" : { + "properties" : { + "dailyNotificationCount" : { + "additionalProperties" : { + "format" : "int32", + "type" : "integer" + }, + "type" : "object" + }, + "priorityDistribution" : { + "additionalProperties" : { + "format" : "int32", + "type" : "integer" + }, + "type" : "object" + }, + "readCount" : { + "format" : "int32", + "type" : "integer" + }, + "totalNotifications" : { + "format" : "int32", + "type" : "integer" + }, + "typeDistribution" : { + "additionalProperties" : { + "format" : "int32", + "type" : "integer" + }, + "type" : "object" + }, + "unreadCount" : { + "format" : "int32", + "type" : "integer" + } + }, + "type" : "object" + }, + "NotificationTemplateResponse" : { + "properties" : { + "description" : { + "type" : "string" + }, + "isActive" : { + "type" : "boolean" + }, + "message" : { + "type" : "string" + }, + "notificationType" : { + "type" : "string" + }, + "templateId" : { + "type" : "string" + }, + "templateName" : { + "type" : "string" + }, + "title" : { + "type" : "string" + } + }, + "type" : "object" + }, + "NotificationUpdateSettingsRequest" : { + "description" : "설정 수정 요청", + "properties" : { + "chatbotNotification" : { + "type" : "boolean" + }, + "communityNotification" : { + "type" : "boolean" + }, + "emailNotification" : { + "type" : "boolean" + }, + "facilityNotification" : { + "type" : "boolean" + }, + "policyNotification" : { + "type" : "boolean" + }, + "pushNotification" : { + "type" : "boolean" + }, + "quietHoursEnd" : { + "type" : "string" + }, + "quietHoursStart" : { + "type" : "string" + }, + "smsNotification" : { + "type" : "boolean" + } + }, + "type" : "object" + }, + "PageAdminPolicyDetailResponse" : { + "properties" : { + "content" : { + "items" : { + "$ref" : "#/components/schemas/AdminPolicyDetailResponse" + }, + "type" : "array" + }, + "empty" : { + "type" : "boolean" + }, + "first" : { + "type" : "boolean" + }, + "last" : { + "type" : "boolean" + }, + "number" : { + "format" : "int32", + "type" : "integer" + }, + "numberOfElements" : { + "format" : "int32", + "type" : "integer" + }, + "pageable" : { + "$ref" : "#/components/schemas/PageableObject" + }, + "size" : { + "format" : "int32", + "type" : "integer" + }, + "sort" : { + "$ref" : "#/components/schemas/SortObject" + }, + "totalElements" : { + "format" : "int64", + "type" : "integer" + }, + "totalPages" : { + "format" : "int32", + "type" : "integer" + } + }, + "type" : "object" + }, + "PageAdminUserResponse" : { + "properties" : { + "content" : { + "items" : { + "$ref" : "#/components/schemas/AdminUserResponse" + }, + "type" : "array" + }, + "empty" : { + "type" : "boolean" + }, + "first" : { + "type" : "boolean" + }, + "last" : { + "type" : "boolean" + }, + "number" : { + "format" : "int32", + "type" : "integer" + }, + "numberOfElements" : { + "format" : "int32", + "type" : "integer" + }, + "pageable" : { + "$ref" : "#/components/schemas/PageableObject" + }, + "size" : { + "format" : "int32", + "type" : "integer" + }, + "sort" : { + "$ref" : "#/components/schemas/SortObject" + }, + "totalElements" : { + "format" : "int64", + "type" : "integer" + }, + "totalPages" : { + "format" : "int32", + "type" : "integer" + } + }, + "type" : "object" + }, + "PageCommunityPostResponse" : { + "properties" : { + "content" : { + "items" : { + "$ref" : "#/components/schemas/CommunityPostResponse" + }, + "type" : "array" + }, + "empty" : { + "type" : "boolean" + }, + "first" : { + "type" : "boolean" + }, + "last" : { + "type" : "boolean" + }, + "number" : { + "format" : "int32", + "type" : "integer" + }, + "numberOfElements" : { + "format" : "int32", + "type" : "integer" + }, + "pageable" : { + "$ref" : "#/components/schemas/PageableObject" + }, + "size" : { + "format" : "int32", + "type" : "integer" + }, + "sort" : { + "$ref" : "#/components/schemas/SortObject" + }, + "totalElements" : { + "format" : "int64", + "type" : "integer" + }, + "totalPages" : { + "format" : "int32", + "type" : "integer" + } + }, + "type" : "object" + }, + "PageHealthRecordResponse" : { + "properties" : { + "content" : { + "items" : { + "$ref" : "#/components/schemas/HealthRecordResponse" + }, + "type" : "array" + }, + "empty" : { + "type" : "boolean" + }, + "first" : { + "type" : "boolean" + }, + "last" : { + "type" : "boolean" + }, + "number" : { + "format" : "int32", + "type" : "integer" + }, + "numberOfElements" : { + "format" : "int32", + "type" : "integer" + }, + "pageable" : { + "$ref" : "#/components/schemas/PageableObject" + }, + "size" : { + "format" : "int32", + "type" : "integer" + }, + "sort" : { + "$ref" : "#/components/schemas/SortObject" + }, + "totalElements" : { + "format" : "int64", + "type" : "integer" + }, + "totalPages" : { + "format" : "int32", + "type" : "integer" + } + }, + "type" : "object" + }, + "PageHospitalInfoResponse" : { + "properties" : { + "content" : { + "items" : { + "$ref" : "#/components/schemas/HospitalInfoResponse" + }, + "type" : "array" + }, + "empty" : { + "type" : "boolean" + }, + "first" : { + "type" : "boolean" + }, + "last" : { + "type" : "boolean" + }, + "number" : { + "format" : "int32", + "type" : "integer" + }, + "numberOfElements" : { + "format" : "int32", + "type" : "integer" + }, + "pageable" : { + "$ref" : "#/components/schemas/PageableObject" + }, + "size" : { + "format" : "int32", + "type" : "integer" + }, + "sort" : { + "$ref" : "#/components/schemas/SortObject" + }, + "totalElements" : { + "format" : "int64", + "type" : "integer" + }, + "totalPages" : { + "format" : "int32", + "type" : "integer" + } + }, + "type" : "object" + }, + "PageNotificationInfoResponse" : { + "properties" : { + "content" : { + "items" : { + "$ref" : "#/components/schemas/NotificationInfoResponse" + }, + "type" : "array" + }, + "empty" : { + "type" : "boolean" + }, + "first" : { + "type" : "boolean" + }, + "last" : { + "type" : "boolean" + }, + "number" : { + "format" : "int32", + "type" : "integer" + }, + "numberOfElements" : { + "format" : "int32", + "type" : "integer" + }, + "pageable" : { + "$ref" : "#/components/schemas/PageableObject" + }, + "size" : { + "format" : "int32", + "type" : "integer" + }, + "sort" : { + "$ref" : "#/components/schemas/SortObject" + }, + "totalElements" : { + "format" : "int64", + "type" : "integer" + }, + "totalPages" : { + "format" : "int32", + "type" : "integer" + } + }, + "type" : "object" + }, + "PageReportResponse" : { + "properties" : { + "content" : { + "items" : { + "$ref" : "#/components/schemas/ReportResponse" + }, + "type" : "array" + }, + "empty" : { + "type" : "boolean" + }, + "first" : { + "type" : "boolean" + }, + "last" : { + "type" : "boolean" + }, + "number" : { + "format" : "int32", + "type" : "integer" + }, + "numberOfElements" : { + "format" : "int32", + "type" : "integer" + }, + "pageable" : { + "$ref" : "#/components/schemas/PageableObject" + }, + "size" : { + "format" : "int32", + "type" : "integer" + }, + "sort" : { + "$ref" : "#/components/schemas/SortObject" + }, + "totalElements" : { + "format" : "int64", + "type" : "integer" + }, + "totalPages" : { + "format" : "int32", + "type" : "integer" + } + }, + "type" : "object" + }, + "Pageable" : { + "properties" : { + "page" : { + "format" : "int32", + "minimum" : 0, + "type" : "integer" + }, + "size" : { + "format" : "int32", + "minimum" : 1, + "type" : "integer" + }, + "sort" : { + "items" : { + "type" : "string" + }, + "type" : "array" + } + }, + "type" : "object" + }, + "PageableObject" : { + "properties" : { + "offset" : { + "format" : "int64", + "type" : "integer" + }, + "pageNumber" : { + "format" : "int32", + "type" : "integer" + }, + "pageSize" : { + "format" : "int32", + "type" : "integer" + }, + "paged" : { + "type" : "boolean" + }, + "sort" : { + "$ref" : "#/components/schemas/SortObject" + }, + "unpaged" : { + "type" : "boolean" + } + }, + "type" : "object" + }, + "PersonalizedPolicyResponse" : { + "properties" : { + "policy" : { + "$ref" : "#/components/schemas/PolicyDto" + }, + "reasons" : { + "items" : { + "type" : "string" + }, + "type" : "array" + }, + "score" : { + "format" : "int32", + "type" : "integer" + } + }, + "type" : "object" + }, + "PolicyBookmarkResponse" : { + "properties" : { + "bookmarkedAt" : { + "format" : "date-time", + "type" : "string" + }, + "category" : { + "type" : "string" + }, + "policyId" : { + "type" : "string" + }, + "title" : { + "type" : "string" + }, + "userId" : { + "type" : "string" + } + }, + "type" : "object" + }, + "PolicyCategoryStatsResponse" : { + "properties" : { + "averageRating" : { + "format" : "double", + "type" : "number" + }, + "category" : { + "type" : "string" + }, + "count" : { + "format" : "int64", + "type" : "integer" + }, + "totalViews" : { + "format" : "int64", + "type" : "integer" + } + }, + "type" : "object" + }, + "PolicyDto" : { + "properties" : { + "applicationMethod" : { + "type" : "string" + }, + "applicationPeriod" : { + "type" : "string" + }, + "category" : { + "type" : "string" + }, + "contactInfo" : { + "type" : "string" + }, + "createdAt" : { + "format" : "date-time", + "type" : "string" + }, + "description" : { + "type" : "string" + }, + "displayOrder" : { + "format" : "int32", + "type" : "integer" + }, + "eligibilityCriteria" : { + "type" : "string" + }, + "id" : { + "format" : "int64", + "type" : "integer" + }, + "isActive" : { + "type" : "boolean" + }, + "location" : { + "type" : "string" + }, + "maxAge" : { + "format" : "int32", + "type" : "integer" + }, + "minAge" : { + "format" : "int32", + "type" : "integer" + }, + "name" : { + "type" : "string" + }, + "requiredDocuments" : { + "type" : "string" + }, + "supportAmount" : { + "format" : "int32", + "type" : "integer" + }, + "title" : { + "type" : "string" + }, + "updatedAt" : { + "format" : "date-time", + "type" : "string" + }, + "viewCount" : { + "format" : "int32", + "type" : "integer" + }, + "websiteUrl" : { + "type" : "string" + } + }, + "type" : "object" + }, + "PolicyListResponse" : { + "properties" : { + "category" : { + "type" : "string" + }, + "city" : { + "type" : "string" + }, + "currentPage" : { + "format" : "int32", + "type" : "integer" + }, + "district" : { + "type" : "string" + }, + "hasNext" : { + "type" : "boolean" + }, + "hasPrevious" : { + "type" : "boolean" + }, + "pageSize" : { + "format" : "int32", + "type" : "integer" + }, + "policies" : { + "items" : { + "$ref" : "#/components/schemas/PolicyDto" + }, + "type" : "array" + }, + "totalCount" : { + "deprecated" : true, + "format" : "int64", + "type" : "integer" + }, + "totalElements" : { + "format" : "int64", + "type" : "integer" + }, + "totalPages" : { + "format" : "int32", + "type" : "integer" + } + }, + "type" : "object" + }, + "PolicySearchRequest" : { + "description" : "검색 조건", + "properties" : { + "category" : { + "type" : "string" + }, + "city" : { + "type" : "string" + }, + "district" : { + "type" : "string" + }, + "endDate" : { + "format" : "date", + "type" : "string" + }, + "incomeLevel" : { + "type" : "string" + }, + "keyword" : { + "type" : "string" + }, + "location" : { + "type" : "string" + }, + "page" : { + "format" : "int32", + "type" : "integer" + }, + "size" : { + "format" : "int32", + "type" : "integer" + }, + "sortBy" : { + "type" : "string" + }, + "sortDirection" : { + "type" : "string" + }, + "startDate" : { + "format" : "date", + "type" : "string" + }, + "targetAge" : { + "type" : "string" + } + }, + "type" : "object" + }, + "PolicyStatsSimpleResponse" : { + "properties" : { + "categoryStats" : { + "items" : { + "$ref" : "#/components/schemas/PolicyCategoryStatsResponse" + }, + "type" : "array" + }, + "totalPolicies" : { + "format" : "int64", + "type" : "integer" + }, + "totalViews" : { + "format" : "int64", + "type" : "integer" + } + }, + "type" : "object" + }, + "ProfileImageResponse" : { + "properties" : { + "profileImageUrl" : { + "type" : "string" + } + }, + "type" : "object" + }, + "PublicDataResponseObject" : { + "properties" : { + "data" : { + "items" : { + "type" : "object" + }, + "type" : "array" + }, + "errorMessage" : { + "type" : "string" + }, + "response" : { + "$ref" : "#/components/schemas/ResponseObject" + }, + "success" : { + "type" : "boolean" + }, + "totalCount" : { + "format" : "int32", + "type" : "integer" + } + }, + "type" : "object" + }, + "RefreshTokenRequest" : { + "description" : "토큰 갱신 정보 (쿠키를 쓰는 경우 생략 가능)", + "properties" : { + "refreshToken" : { + "type" : "string" + } + }, + "type" : "object" + }, + "RegionalBenefitComparisonResponse" : { + "properties" : { + "baseAmount" : { + "format" : "int64", + "type" : "integer" + }, + "baseRegion" : { + "type" : "string" + }, + "childAgeMonths" : { + "format" : "int32", + "type" : "integer" + }, + "childName" : { + "type" : "string" + }, + "dataQuality" : { + "type" : "string" + }, + "disclaimers" : { + "items" : { + "type" : "string" + }, + "type" : "array" + }, + "horizonMonths" : { + "format" : "int32", + "type" : "integer" + }, + "rankings" : { + "items" : { + "$ref" : "#/components/schemas/RegionalBenefitResponse" + }, + "type" : "array" + } + }, + "type" : "object" + }, + "RegionalBenefitResponse" : { + "properties" : { + "cashPolicyCount" : { + "format" : "int32", + "type" : "integer" + }, + "dataQuality" : { + "type" : "string" + }, + "differenceFromBase" : { + "format" : "int64", + "type" : "integer" + }, + "nonCashPolicyCount" : { + "format" : "int32", + "type" : "integer" + }, + "region" : { + "type" : "string" + }, + "topContributors" : { + "items" : { + "$ref" : "#/components/schemas/Contribution" + }, + "type" : "array" + }, + "totalAmount" : { + "format" : "int64", + "type" : "integer" + }, + "unknownAmountCount" : { + "format" : "int32", + "type" : "integer" + }, + "verifiedPolicyCount" : { + "format" : "int32", + "type" : "integer" + } + }, + "type" : "object" + }, + "ReportCreateRequest" : { + "properties" : { + "detail" : { + "maxLength" : 1000, + "minLength" : 0, + "type" : "string" + }, + "reason" : { + "enum" : [ "SPAM", "ABUSE", "SEXUAL", "PRIVACY", "FALSE_INFO", "OTHER" ], + "type" : "string" + }, + "targetId" : { + "format" : "int64", + "type" : "integer" + }, + "targetType" : { + "enum" : [ "POST", "COMMENT" ], + "type" : "string" + } + }, + "required" : [ "reason", "targetId", "targetType" ], + "type" : "object" + }, + "ReportResponse" : { + "properties" : { + "createdAt" : { + "format" : "date-time", + "type" : "string" + }, + "detail" : { + "type" : "string" + }, + "id" : { + "format" : "int64", + "type" : "integer" + }, + "moderatorNote" : { + "type" : "string" + }, + "reason" : { + "type" : "string" + }, + "reasonDisplay" : { + "type" : "string" + }, + "resolvedAt" : { + "format" : "date-time", + "type" : "string" + }, + "status" : { + "type" : "string" + }, + "targetId" : { + "format" : "int64", + "type" : "integer" + }, + "targetType" : { + "type" : "string" + } + }, + "type" : "object" + }, + "ResponseObject" : { + "properties" : { + "body" : { + "$ref" : "#/components/schemas/BodyObject" + }, + "header" : { + "$ref" : "#/components/schemas/Header" + } + }, + "type" : "object" + }, + "RetentionResponse" : { + "properties" : { + "cohorts" : { + "items" : { + "$ref" : "#/components/schemas/Cohort" + }, + "type" : "array" + } + }, + "type" : "object" + }, + "ReviewRequest" : { + "properties" : { + "content" : { + "type" : "string" + }, + "rating" : { + "format" : "int32", + "type" : "integer" + } + }, + "type" : "object" + }, + "ReviewResponse" : { + "properties" : { + "content" : { + "type" : "string" + }, + "createdAt" : { + "format" : "date-time", + "type" : "string" + }, + "facilityId" : { + "format" : "int64", + "type" : "integer" + }, + "rating" : { + "format" : "int32", + "type" : "integer" + }, + "reviewId" : { + "format" : "int64", + "type" : "integer" + }, + "updatedAt" : { + "format" : "date-time", + "type" : "string" + }, + "userId" : { + "type" : "string" + } + }, + "type" : "object" + }, + "SiblingOverviewResponse" : { + "properties" : { + "childCount" : { + "format" : "int32", + "type" : "integer" + }, + "children" : { + "items" : { + "$ref" : "#/components/schemas/ChildSummary" + }, + "type" : "array" + }, + "multiChildBenefits" : { + "items" : { + "type" : "string" + }, + "type" : "array" + }, + "multiChildHousehold" : { + "type" : "boolean" + }, + "notes" : { + "items" : { + "type" : "string" + }, + "type" : "array" + } + }, + "type" : "object" + }, + "SignUpRequest" : { + "description" : "회원가입 정보", + "properties" : { + "address" : { + "maxLength" : 255, + "minLength" : 0, + "type" : "string" + }, + "birthDate" : { + "format" : "date", + "type" : "string" + }, + "email" : { + "maxLength" : 255, + "minLength" : 0, + "type" : "string" + }, + "gender" : { + "pattern" : "^(MALE|FEMALE|OTHER)$", + "type" : "string" + }, + "name" : { + "maxLength" : 50, + "minLength" : 0, + "type" : "string" + }, + "password" : { + "maxLength" : 64, + "minLength" : 8, + "type" : "string" + }, + "phoneNumber" : { + "pattern" : "^[0-9+\\-() ]{0,20}$", + "type" : "string" + } + }, + "required" : [ "email", "name", "password" ], + "type" : "object" + }, + "SortObject" : { + "properties" : { + "empty" : { + "type" : "boolean" + }, + "sorted" : { + "type" : "boolean" + }, + "unsorted" : { + "type" : "boolean" + } + }, + "type" : "object" + }, + "SseEmitter" : { + "properties" : { + "timeout" : { + "format" : "int64", + "type" : "integer" + } + }, + "type" : "object" + }, + "StatusDistribution" : { + "properties" : { + "count" : { + "format" : "int64", + "type" : "integer" + }, + "percentage" : { + "format" : "double", + "type" : "number" + }, + "status" : { + "type" : "string" + }, + "statusDisplay" : { + "type" : "string" + } + }, + "type" : "object" + }, + "Step" : { + "properties" : { + "conversionRate" : { + "format" : "int32", + "type" : "integer" + }, + "event" : { + "type" : "string" + }, + "label" : { + "type" : "string" + }, + "users" : { + "format" : "int64", + "type" : "integer" + } + }, + "type" : "object" + }, + "TokenDto" : { + "properties" : { + "accessToken" : { + "type" : "string" + }, + "email" : { + "type" : "string" + }, + "expiresIn" : { + "format" : "int64", + "type" : "integer" + }, + "isNewUser" : { + "type" : "boolean" + }, + "message" : { + "type" : "string" + }, + "refreshExpiresIn" : { + "format" : "int64", + "type" : "integer" + }, + "refreshToken" : { + "type" : "string" + }, + "role" : { + "type" : "string" + }, + "success" : { + "type" : "boolean" + }, + "tokenType" : { + "type" : "string" + }, + "user" : { + "$ref" : "#/components/schemas/UserDto" + }, + "userId" : { + "type" : "string" + } + }, + "type" : "object" + }, + "TypeDistribution" : { + "properties" : { + "bookingType" : { + "type" : "string" + }, + "bookingTypeDisplay" : { + "type" : "string" + }, + "count" : { + "format" : "int64", + "type" : "integer" + }, + "percentage" : { + "format" : "double", + "type" : "number" + } + }, + "type" : "object" + }, + "TypeStats" : { + "properties" : { + "averageRating" : { + "format" : "double", + "type" : "number" + }, + "count" : { + "format" : "int64", + "type" : "integer" + }, + "facilityType" : { + "enum" : [ "KINDERGARTEN", "DAYCARE", "PLAYGROUP", "NURSERY", "OTHER" ], + "type" : "string" + }, + "totalViews" : { + "format" : "int64", + "type" : "integer" + } + }, + "type" : "object" + }, + "UpdateBookingRequest" : { + "description" : "수정할 예약 정보", + "properties" : { + "bookingType" : { + "type" : "string" + }, + "childAge" : { + "format" : "int32", + "type" : "integer" + }, + "childName" : { + "type" : "string" + }, + "endTime" : { + "format" : "date-time", + "type" : "string" + }, + "notes" : { + "type" : "string" + }, + "parentName" : { + "type" : "string" + }, + "parentPhone" : { + "type" : "string" + }, + "specialRequirements" : { + "type" : "string" + }, + "startTime" : { + "format" : "date-time", + "type" : "string" + } + }, + "type" : "object" + }, + "UserDto" : { + "properties" : { + "address" : { + "type" : "string" + }, + "birthDate" : { + "format" : "date", + "type" : "string" + }, + "createdAt" : { + "format" : "date-time", + "type" : "string" + }, + "deletedAt" : { + "format" : "date-time", + "type" : "string" + }, + "email" : { + "type" : "string" + }, + "emailVerified" : { + "type" : "boolean" + }, + "gender" : { + "type" : "string" + }, + "id" : { + "format" : "int64", + "type" : "integer" + }, + "isActive" : { + "type" : "boolean" + }, + "lastLoginAt" : { + "format" : "date-time", + "type" : "string" + }, + "latitude" : { + "format" : "double", + "type" : "number" + }, + "longitude" : { + "format" : "double", + "type" : "number" + }, + "name" : { + "type" : "string" + }, + "password" : { + "type" : "string", + "writeOnly" : true + }, + "phoneNumber" : { + "type" : "string" + }, + "profileImageUrl" : { + "type" : "string" + }, + "provider" : { + "type" : "string" + }, + "providerId" : { + "type" : "string" + }, + "registrationCompleted" : { + "type" : "boolean" + }, + "role" : { + "type" : "string" + }, + "updatedAt" : { + "format" : "date-time", + "type" : "string" + }, + "userId" : { + "type" : "string" + } + }, + "type" : "object" + }, + "UserProfileCompletionResponse" : { + "properties" : { + "complete" : { + "type" : "boolean" + }, + "completedFields" : { + "format" : "int32", + "type" : "integer" + }, + "completionPercentage" : { + "format" : "int32", + "type" : "integer" + }, + "message" : { + "type" : "string" + }, + "missingFields" : { + "$ref" : "#/components/schemas/UserProfileMissingFields" + }, + "totalFields" : { + "format" : "int32", + "type" : "integer" + } + }, + "type" : "object" + }, + "UserProfileMissingFields" : { + "properties" : { + "needsAddress" : { + "type" : "boolean" + }, + "needsBirthDate" : { + "type" : "boolean" + }, + "needsGender" : { + "type" : "boolean" + }, + "needsPhoneNumber" : { + "type" : "boolean" + }, + "needsRealName" : { + "type" : "boolean" + } + }, + "type" : "object" + }, + "UserStatsResponse" : { + "properties" : { + "activeUsers" : { + "format" : "int64", + "type" : "integer" + }, + "newUsersThisMonth" : { + "format" : "int64", + "type" : "integer" + }, + "newUsersThisWeek" : { + "format" : "int64", + "type" : "integer" + }, + "newUsersToday" : { + "format" : "int64", + "type" : "integer" + }, + "totalUsers" : { + "format" : "int64", + "type" : "integer" + }, + "verifiedUsers" : { + "format" : "int64", + "type" : "integer" + } + }, + "type" : "object" + }, + "UserUpdateRequestDto" : { + "description" : "업데이트할 프로필 정보", + "properties" : { + "address" : { + "maxLength" : 200, + "minLength" : 0, + "type" : "string" + }, + "birthDate" : { + "format" : "date", + "type" : "string" + }, + "gender" : { + "enum" : [ "MALE", "FEMALE", "OTHER" ], + "type" : "string" + }, + "householdSize" : { + "format" : "int32", + "maximum" : 20, + "minimum" : 1, + "type" : "integer" + }, + "incomePercent" : { + "format" : "int32", + "maximum" : 1000, + "minimum" : 0, + "type" : "integer" + }, + "latitude" : { + "format" : "double", + "type" : "number" + }, + "longitude" : { + "format" : "double", + "type" : "number" + }, + "name" : { + "maxLength" : 10, + "minLength" : 2, + "type" : "string" + }, + "phoneNumber" : { + "pattern" : "^$|^01[0-9]-[0-9]{3,4}-[0-9]{4}$", + "type" : "string" + } + }, + "required" : [ "name" ], + "type" : "object" + }, + "VaccinationScheduleResponse" : { + "properties" : { + "childId" : { + "format" : "int64", + "type" : "integer" + }, + "completedDate" : { + "format" : "date", + "type" : "string" + }, + "doseNumber" : { + "format" : "int32", + "type" : "integer" + }, + "dueDate" : { + "format" : "date", + "type" : "string" + }, + "id" : { + "format" : "int64", + "type" : "integer" + }, + "overdue" : { + "type" : "boolean" + }, + "status" : { + "type" : "string" + }, + "totalDoses" : { + "format" : "int32", + "type" : "integer" + }, + "vaccineName" : { + "type" : "string" + }, + "vaccineType" : { + "type" : "string" + } + }, + "type" : "object" + }, + "VaccineScheduleResponse" : { + "properties" : { + "completedDate" : { + "type" : "string" + }, + "description" : { + "type" : "string" + }, + "notes" : { + "type" : "string" + }, + "recommendedAge" : { + "format" : "int32", + "type" : "integer" + }, + "scheduledDate" : { + "type" : "string" + }, + "status" : { + "type" : "string" + }, + "vaccineName" : { + "type" : "string" + } + }, + "type" : "object" + }, + "WaitlistRequest" : { + "properties" : { + "appliedAt" : { + "format" : "date", + "type" : "string" + }, + "childId" : { + "format" : "int64", + "type" : "integer" + }, + "note" : { + "maxLength" : 300, + "minLength" : 0, + "type" : "string" + }, + "waitNumber" : { + "format" : "int32", + "maximum" : 9999, + "minimum" : 1, + "type" : "integer" + } + }, + "type" : "object" + }, + "WaitlistStatsResponse" : { + "properties" : { + "admittedSamples" : { + "format" : "int32", + "type" : "integer" + }, + "available" : { + "type" : "boolean" + }, + "averageWaitDays" : { + "format" : "int32", + "type" : "integer" + }, + "currentlyWaiting" : { + "format" : "int64", + "type" : "integer" + }, + "facilityId" : { + "format" : "int64", + "type" : "integer" + }, + "facilityName" : { + "type" : "string" + }, + "maxWaitDays" : { + "format" : "int32", + "type" : "integer" + }, + "medianWaitDays" : { + "format" : "int32", + "type" : "integer" + }, + "reasons" : { + "items" : { + "type" : "string" + }, + "type" : "array" + }, + "unavailableReason" : { + "type" : "string" + } + }, + "type" : "object" + } + }, + "securitySchemes" : { + "API Key" : { + "description" : "API 키를 입력하세요", + "in" : "header", + "name" : "X-API-Key", + "type" : "apiKey" + }, + "Basic Auth" : { + "description" : "기본 인증 정보를 입력하세요", + "scheme" : "basic", + "type" : "http" + }, + "Bearer Authentication" : { + "bearerFormat" : "JWT", + "description" : "JWT 토큰을 입력하세요. 예: Bearer {token}", + "scheme" : "bearer", + "type" : "http" + } + } + }, + "info" : { + "contact" : { + "email" : "dhxogns920@naver.com", + "name" : "CareCode Team", + "url" : "https://carecode.com" + }, + "description" : "육아 지원 플랫폼 맘편한의 REST API 문서. API 버전은 `X-API-Version` 요청 헤더로 지정합니다. 생략하면 현재 버전(1)이며, 응답의 `X-API-Version` 헤더가 실제로 처리한 버전입니다.", + "license" : { + "name" : "MIT License", + "url" : "https://opensource.org/licenses/MIT" + }, + "title" : "CareCode API", + "version" : "1" + }, + "openapi" : "3.0.1", + "paths" : { + "/api/admin/analytics/events" : { + "get" : { + "description" : "종류별 집계", + "operationId" : "events", + "parameters" : [ { + "in" : "query", + "name" : "from", + "required" : false, + "schema" : { + "format" : "date", + "type" : "string" + } + }, { + "in" : "query", + "name" : "to", + "required" : false, + "schema" : { + "format" : "date", + "type" : "string" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "additionalProperties" : { + "format" : "int64", + "type" : "integer" + }, + "type" : "object" + } + } + }, + "description" : "OK" + } + }, + "summary" : "이벤트 발생 건수", + "tags" : [ "어드민 - 지표" ] + } + }, + "/api/admin/analytics/funnel" : { + "get" : { + "description" : "단계별 도달 사용자 수와 전환율", + "operationId" : "funnel", + "parameters" : [ { + "description" : "시작일 (기본: 30일 전)", + "in" : "query", + "name" : "from", + "required" : false, + "schema" : { + "format" : "date", + "type" : "string" + } + }, { + "description" : "종료일 (기본: 오늘)", + "in" : "query", + "name" : "to", + "required" : false, + "schema" : { + "format" : "date", + "type" : "string" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/FunnelResponse" + } + } + }, + "description" : "OK" + } + }, + "summary" : "온보딩 퍼널 조회", + "tags" : [ "어드민 - 지표" ] + } + }, + "/api/admin/analytics/notification-funnel" : { + "get" : { + "description" : "발송 → 클릭 → 신청 전환율", + "operationId" : "notificationFunnel", + "parameters" : [ { + "in" : "query", + "name" : "from", + "required" : false, + "schema" : { + "format" : "date", + "type" : "string" + } + }, { + "in" : "query", + "name" : "to", + "required" : false, + "schema" : { + "format" : "date", + "type" : "string" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/FunnelResponse" + } + } + }, + "description" : "OK" + } + }, + "summary" : "알림 효과 퍼널", + "tags" : [ "어드민 - 지표" ] + } + }, + "/api/admin/analytics/retention" : { + "get" : { + "description" : "가입일 기준 D1/D7/D30 잔존율", + "operationId" : "retention", + "parameters" : [ { + "in" : "query", + "name" : "from", + "required" : false, + "schema" : { + "format" : "date", + "type" : "string" + } + }, { + "in" : "query", + "name" : "to", + "required" : false, + "schema" : { + "format" : "date", + "type" : "string" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/RetentionResponse" + } + } + }, + "description" : "OK" + } + }, + "summary" : "코호트 리텐션 조회", + "tags" : [ "어드민 - 지표" ] + } + }, + "/api/admin/community/posts" : { + "get" : { + "operationId" : "list_5", + "parameters" : [ { + "in" : "query", + "name" : "pageable", + "required" : true, + "schema" : { + "$ref" : "#/components/schemas/Pageable" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/PageCommunityPostResponse" + } + } + }, + "description" : "OK" + } + }, + "summary" : "게시글 목록 조회", + "tags" : [ "어드민 - 커뮤니티" ] + } + }, + "/api/admin/community/posts/{id}" : { + "delete" : { + "description" : "부적절한 게시글을 관리자 권한으로 삭제", + "operationId" : "delete_5", + "parameters" : [ { + "in" : "path", + "name" : "id", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "description" : "OK" + } + }, + "summary" : "게시글 삭제", + "tags" : [ "어드민 - 커뮤니티" ] + }, + "get" : { + "operationId" : "detail_5", + "parameters" : [ { + "in" : "path", + "name" : "id", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/CommunityPostResponse" + } + } + }, + "description" : "OK" + } + }, + "summary" : "게시글 상세 조회", + "tags" : [ "어드민 - 커뮤니티" ] + } + }, + "/api/admin/dashboard" : { + "get" : { + "description" : "전체 건수, 최근 활동, 가입자 추이 반환", + "operationId" : "dashboard", + "parameters" : [ { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "additionalProperties" : { + "type" : "object" + }, + "type" : "object" + } + } + }, + "description" : "OK" + } + }, + "summary" : "대시보드 요약 조회", + "tags" : [ "어드민 - 대시보드" ] + } + }, + "/api/admin/dev/sample-data" : { + "delete" : { + "description" : "접두어로 식별해 실데이터는 남깁니다", + "operationId" : "clean", + "parameters" : [ { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "additionalProperties" : { + "format" : "int32", + "type" : "integer" + }, + "type" : "object" + } + } + }, + "description" : "OK" + } + }, + "summary" : "샘플 데이터 제거", + "tags" : [ "어드민 - 개발용 샘플 데이터" ] + }, + "post" : { + "description" : "지역별 정책과 정원 관측 이력을 넣습니다", + "operationId" : "seed", + "parameters" : [ { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "additionalProperties" : { + "format" : "int32", + "type" : "integer" + }, + "type" : "object" + } + } + }, + "description" : "OK" + } + }, + "summary" : "샘플 데이터 적재", + "tags" : [ "어드민 - 개발용 샘플 데이터" ] + } + }, + "/api/admin/facilities/bookings" : { + "get" : { + "operationId" : "bookingList", + "parameters" : [ { + "in" : "query", + "name" : "page", + "required" : false, + "schema" : { + "default" : 0, + "format" : "int32", + "type" : "integer" + } + }, { + "in" : "query", + "name" : "size", + "required" : false, + "schema" : { + "default" : 20, + "format" : "int32", + "type" : "integer" + } + }, { + "in" : "query", + "name" : "facilityId", + "required" : false, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "in" : "query", + "name" : "status", + "required" : false, + "schema" : { + "type" : "string" + } + }, { + "in" : "query", + "name" : "keyword", + "required" : false, + "schema" : { + "type" : "string" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/AdminBookingSearchResponse" + } + } + }, + "description" : "OK" + } + }, + "summary" : "예약 목록 조회", + "tags" : [ "어드민 - 시설 예약" ] + } + }, + "/api/admin/facilities/bookings/dashboard" : { + "get" : { + "description" : "통계, 최근 예약, 오늘의 예약을 함께 반환", + "operationId" : "bookingDashboard", + "parameters" : [ { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "additionalProperties" : { + "type" : "object" + }, + "type" : "object" + } + } + }, + "description" : "OK" + } + }, + "summary" : "예약 대시보드 요약", + "tags" : [ "어드민 - 시설 예약" ] + } + }, + "/api/admin/facilities/bookings/facility/{facilityId}" : { + "get" : { + "operationId" : "facilityBookings", + "parameters" : [ { + "in" : "path", + "name" : "facilityId", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "in" : "query", + "name" : "page", + "required" : false, + "schema" : { + "default" : 0, + "format" : "int32", + "type" : "integer" + } + }, { + "in" : "query", + "name" : "size", + "required" : false, + "schema" : { + "default" : 20, + "format" : "int32", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/AdminBookingSearchResponse" + } + } + }, + "description" : "OK" + } + }, + "summary" : "시설별 예약 조회", + "tags" : [ "어드민 - 시설 예약" ] + } + }, + "/api/admin/facilities/bookings/statistics" : { + "get" : { + "operationId" : "bookingStatistics", + "parameters" : [ { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/AdminBookingStatsResponse" + } + } + }, + "description" : "OK" + } + }, + "summary" : "예약 통계 조회", + "tags" : [ "어드민 - 시설 예약" ] + } + }, + "/api/admin/facilities/bookings/status/{status}" : { + "get" : { + "operationId" : "statusBookings", + "parameters" : [ { + "in" : "path", + "name" : "status", + "required" : true, + "schema" : { + "type" : "string" + } + }, { + "in" : "query", + "name" : "page", + "required" : false, + "schema" : { + "default" : 0, + "format" : "int32", + "type" : "integer" + } + }, { + "in" : "query", + "name" : "size", + "required" : false, + "schema" : { + "default" : 20, + "format" : "int32", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/AdminBookingSearchResponse" + } + } + }, + "description" : "OK" + } + }, + "summary" : "상태별 예약 조회", + "tags" : [ "어드민 - 시설 예약" ] + } + }, + "/api/admin/facilities/bookings/today" : { + "get" : { + "operationId" : "todayBookings", + "parameters" : [ { + "in" : "query", + "name" : "page", + "required" : false, + "schema" : { + "default" : 0, + "format" : "int32", + "type" : "integer" + } + }, { + "in" : "query", + "name" : "size", + "required" : false, + "schema" : { + "default" : 20, + "format" : "int32", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/AdminBookingSearchResponse" + } + } + }, + "description" : "OK" + } + }, + "summary" : "오늘의 예약 조회", + "tags" : [ "어드민 - 시설 예약" ] + } + }, + "/api/admin/facilities/bookings/{bookingId}" : { + "delete" : { + "operationId" : "deleteBooking", + "parameters" : [ { + "in" : "path", + "name" : "bookingId", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "description" : "OK" + } + }, + "summary" : "예약 삭제", + "tags" : [ "어드민 - 시설 예약" ] + }, + "get" : { + "operationId" : "bookingDetail", + "parameters" : [ { + "in" : "path", + "name" : "bookingId", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/AdminBookingDetailResponse" + } + } + }, + "description" : "OK" + } + }, + "summary" : "예약 상세 조회", + "tags" : [ "어드민 - 시설 예약" ] + } + }, + "/api/admin/facilities/bookings/{bookingId}/status" : { + "patch" : { + "operationId" : "updateBookingStatus_1", + "parameters" : [ { + "in" : "path", + "name" : "bookingId", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/AdminStatusUpdateRequest" + } + } + }, + "required" : true + }, + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/AdminBookingDetailResponse" + } + } + }, + "description" : "OK" + } + }, + "summary" : "예약 상태 변경", + "tags" : [ "어드민 - 시설 예약" ] + } + }, + "/api/admin/health/records" : { + "get" : { + "operationId" : "list_4", + "parameters" : [ { + "in" : "query", + "name" : "pageable", + "required" : true, + "schema" : { + "$ref" : "#/components/schemas/Pageable" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/PageHealthRecordResponse" + } + } + }, + "description" : "OK" + } + }, + "summary" : "건강기록 목록 조회", + "tags" : [ "어드민 - 건강기록" ] + } + }, + "/api/admin/health/records/{id}" : { + "delete" : { + "operationId" : "delete_4", + "parameters" : [ { + "in" : "path", + "name" : "id", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "description" : "OK" + } + }, + "summary" : "건강기록 삭제", + "tags" : [ "어드민 - 건강기록" ] + }, + "get" : { + "operationId" : "detail_4", + "parameters" : [ { + "in" : "path", + "name" : "id", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/HealthRecordResponse" + } + } + }, + "description" : "OK" + } + }, + "summary" : "건강기록 상세 조회", + "tags" : [ "어드민 - 건강기록" ] + } + }, + "/api/admin/hospitals" : { + "get" : { + "operationId" : "list_3", + "parameters" : [ { + "in" : "query", + "name" : "pageable", + "required" : true, + "schema" : { + "$ref" : "#/components/schemas/Pageable" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/PageHospitalInfoResponse" + } + } + }, + "description" : "OK" + } + }, + "summary" : "병원 목록 조회", + "tags" : [ "어드민 - 병원" ] + } + }, + "/api/admin/hospitals/{id}" : { + "delete" : { + "operationId" : "delete_3", + "parameters" : [ { + "in" : "path", + "name" : "id", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "description" : "OK" + } + }, + "summary" : "병원 삭제", + "tags" : [ "어드민 - 병원" ] + }, + "get" : { + "operationId" : "detail_3", + "parameters" : [ { + "in" : "path", + "name" : "id", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/HospitalInfoResponse" + } + } + }, + "description" : "OK" + } + }, + "summary" : "병원 상세 조회", + "tags" : [ "어드민 - 병원" ] + } + }, + "/api/admin/notifications" : { + "get" : { + "operationId" : "list_2", + "parameters" : [ { + "in" : "query", + "name" : "pageable", + "required" : true, + "schema" : { + "$ref" : "#/components/schemas/Pageable" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/PageNotificationInfoResponse" + } + } + }, + "description" : "OK" + } + }, + "summary" : "알림 목록 조회", + "tags" : [ "어드민 - 알림" ] + }, + "post" : { + "description" : "특정 사용자에게 알림 생성", + "operationId" : "create_1", + "parameters" : [ { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/AdminNotificationCreateRequest" + } + } + }, + "required" : true + }, + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/NotificationInfoResponse" + } + } + }, + "description" : "OK" + } + }, + "summary" : "알림 발송", + "tags" : [ "어드민 - 알림" ] + } + }, + "/api/admin/notifications/{id}" : { + "delete" : { + "operationId" : "delete_2", + "parameters" : [ { + "in" : "path", + "name" : "id", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "description" : "OK" + } + }, + "summary" : "알림 삭제", + "tags" : [ "어드민 - 알림" ] + }, + "get" : { + "operationId" : "detail_2", + "parameters" : [ { + "in" : "path", + "name" : "id", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/NotificationInfoResponse" + } + } + }, + "description" : "OK" + } + }, + "summary" : "알림 상세 조회", + "tags" : [ "어드민 - 알림" ] + } + }, + "/api/admin/policies" : { + "get" : { + "description" : "수정 요청과 1:1 로 대응하는 원본 값을 반환합니다 (사용자용 PolicyDto 는 가공된 값이라 수정에 쓸 수 없음)", + "operationId" : "list_1", + "parameters" : [ { + "in" : "query", + "name" : "pageable", + "required" : true, + "schema" : { + "$ref" : "#/components/schemas/Pageable" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/PageAdminPolicyDetailResponse" + } + } + }, + "description" : "OK" + } + }, + "summary" : "정책 목록 조회", + "tags" : [ "어드민 - 정책" ] + }, + "post" : { + "description" : "재배포 없이 새 정책 추가", + "operationId" : "create", + "parameters" : [ { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/AdminPolicyRequest" + } + } + }, + "required" : true + }, + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/AdminPolicyDetailResponse" + } + } + }, + "description" : "OK" + } + }, + "summary" : "정책 등록", + "tags" : [ "어드민 - 정책" ] + } + }, + "/api/admin/policies/verification-status" : { + "get" : { + "description" : "미검증 정책이 많은 지역 순", + "operationId" : "status_1", + "parameters" : [ { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "items" : { + "additionalProperties" : { + "type" : "object" + }, + "type" : "object" + }, + "type" : "array" + } + } + }, + "description" : "OK" + } + }, + "summary" : "지역별 검증 현황", + "tags" : [ "어드민 - 정책 검증" ] + } + }, + "/api/admin/policies/{id}" : { + "delete" : { + "operationId" : "delete_1", + "parameters" : [ { + "in" : "path", + "name" : "id", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "description" : "OK" + } + }, + "summary" : "정책 삭제", + "tags" : [ "어드민 - 정책" ] + }, + "get" : { + "operationId" : "detail_1", + "parameters" : [ { + "in" : "path", + "name" : "id", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/AdminPolicyDetailResponse" + } + } + }, + "description" : "OK" + } + }, + "summary" : "정책 상세 조회", + "tags" : [ "어드민 - 정책" ] + }, + "patch" : { + "description" : "요청 JSON 에 담긴 키만 반영합니다. 키가 없으면 기존 값을 유지하고, 키가 있는데 값이 null 이면 해당 항목을 비웁니다", + "operationId" : "patch", + "parameters" : [ { + "in" : "path", + "name" : "id", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/JsonNode" + } + } + }, + "required" : true + }, + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/AdminPolicyDetailResponse" + } + } + }, + "description" : "OK" + } + }, + "summary" : "정책 부분 수정", + "tags" : [ "어드민 - 정책" ] + }, + "put" : { + "description" : "요청에 담긴 값으로 전체를 덮어씁니다. 보내지 않은 항목은 null 이 되므로, 일부만 고칠 때는 PATCH 를 쓰세요", + "operationId" : "update", + "parameters" : [ { + "in" : "path", + "name" : "id", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/AdminPolicyRequest" + } + } + }, + "required" : true + }, + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/AdminPolicyDetailResponse" + } + } + }, + "description" : "OK" + } + }, + "summary" : "정책 전체 교체", + "tags" : [ "어드민 - 정책" ] + } + }, + "/api/admin/policies/{policyId}/verify" : { + "delete" : { + "description" : "추정치로 되돌림", + "operationId" : "unverify", + "parameters" : [ { + "in" : "path", + "name" : "policyId", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "description" : "OK" + } + }, + "summary" : "검증 표시 해제", + "tags" : [ "어드민 - 정책 검증" ] + }, + "post" : { + "description" : "확인한 금액을 확정으로 전환", + "operationId" : "verify", + "parameters" : [ { + "description" : "정책 ID", + "in" : "path", + "name" : "policyId", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "금액 근거 출처 URL", + "in" : "query", + "name" : "sourceUrl", + "required" : false, + "schema" : { + "type" : "string" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "additionalProperties" : { + "type" : "object" + }, + "type" : "object" + } + } + }, + "description" : "OK" + } + }, + "summary" : "정책 금액 검증 표시", + "tags" : [ "어드민 - 정책 검증" ] + } + }, + "/api/admin/public-data/benefits/sync" : { + "post" : { + "description" : "육아 관련 서비스만 정책으로 갱신", + "operationId" : "syncBenefits", + "parameters" : [ { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "additionalProperties" : { + "type" : "object" + }, + "type" : "object" + } + } + }, + "description" : "OK" + } + }, + "summary" : "정부 지원 서비스 동기화", + "tags" : [ "어드민 - 공공데이터" ] + } + }, + "/api/admin/public-data/facilities/geocode" : { + "post" : { + "description" : "좌표 없는 시설의 주소를 좌표로 변환", + "operationId" : "geocode", + "parameters" : [ { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "additionalProperties" : { + "type" : "object" + }, + "type" : "object" + } + } + }, + "description" : "OK" + } + }, + "summary" : "시설 좌표 보정", + "tags" : [ "어드민 - 공공데이터" ] + } + }, + "/api/admin/public-data/facilities/notify-vacancy" : { + "post" : { + "description" : "대기자가 있는 시설에 새로 난 자리를 알린다", + "operationId" : "notifyVacancies", + "parameters" : [ { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "additionalProperties" : { + "type" : "object" + }, + "type" : "object" + } + } + }, + "description" : "OK" + } + }, + "summary" : "빈자리 알림 실행", + "tags" : [ "어드민 - 공공데이터" ] + } + }, + "/api/admin/public-data/facilities/sync" : { + "post" : { + "description" : "시설 코드 기준으로 갱신", + "operationId" : "syncFacilities", + "parameters" : [ { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "additionalProperties" : { + "type" : "object" + }, + "type" : "object" + } + } + }, + "description" : "OK" + } + }, + "summary" : "전국 어린이집 동기화", + "tags" : [ "어드민 - 공공데이터" ] + } + }, + "/api/admin/public-data/hospitals/sync" : { + "post" : { + "description" : "요양기호 기준으로 갱신", + "operationId" : "syncHospitals", + "parameters" : [ { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "additionalProperties" : { + "type" : "object" + }, + "type" : "object" + } + } + }, + "description" : "OK" + } + }, + "summary" : "소아청소년과 병원 동기화", + "tags" : [ "어드민 - 공공데이터" ] + } + }, + "/api/admin/public-data/kindergartens/sync" : { + "post" : { + "description" : "유치원명·주소 기준으로 갱신", + "operationId" : "syncKindergartens", + "parameters" : [ { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "additionalProperties" : { + "type" : "object" + }, + "type" : "object" + } + } + }, + "description" : "OK" + } + }, + "summary" : "전국 유치원 동기화", + "tags" : [ "어드민 - 공공데이터" ] + } + }, + "/api/admin/public-data/policies/notify-deadline" : { + "post" : { + "description" : "신청 마감이 임박한 지원금을 대상자에게 알린다", + "operationId" : "notifyDeadlines", + "parameters" : [ { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "additionalProperties" : { + "type" : "object" + }, + "type" : "object" + } + } + }, + "description" : "OK" + } + }, + "summary" : "마감 임박 알림 실행", + "tags" : [ "어드민 - 공공데이터" ] + } + }, + "/api/admin/reports" : { + "get" : { + "operationId" : "pendingReports", + "parameters" : [ { + "in" : "query", + "name" : "pageable", + "required" : true, + "schema" : { + "$ref" : "#/components/schemas/Pageable" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/PageReportResponse" + } + } + }, + "description" : "OK" + } + }, + "summary" : "미처리 신고 목록 조회", + "tags" : [ "어드민 - 신고 처리" ] + } + }, + "/api/admin/reports/{reportId}" : { + "patch" : { + "description" : "ACCEPTED 로 처리하면 대상 게시글·댓글이 숨김 처리", + "operationId" : "resolve_1", + "parameters" : [ { + "in" : "path", + "name" : "reportId", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "처리 결과 (ACCEPTED 또는 REJECTED)", + "in" : "query", + "name" : "status", + "required" : true, + "schema" : { + "enum" : [ "PENDING", "ACCEPTED", "REJECTED" ], + "type" : "string" + } + }, { + "description" : "처리 메모", + "in" : "query", + "name" : "note", + "required" : false, + "schema" : { + "type" : "string" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/ReportResponse" + } + } + }, + "description" : "OK" + } + }, + "summary" : "신고 처리", + "tags" : [ "어드민 - 신고 처리" ] + } + }, + "/api/admin/sync/forecast-accuracy/measure" : { + "post" : { + "description" : "과거 관측으로 백테스트를 돌려 기간별 정확도를 다시 계산", + "operationId" : "measureForecastAccuracy", + "parameters" : [ { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "additionalProperties" : { + "type" : "object" + }, + "type" : "object" + } + } + }, + "description" : "OK" + } + }, + "summary" : "예측 정확도 측정 실행", + "tags" : [ "어드민 - 주기 작업" ] + } + }, + "/api/admin/sync/status" : { + "get" : { + "description" : "작업별 마지막 성공 시각, 경과 시간, 신선도 기준 초과 여부", + "operationId" : "status", + "parameters" : [ { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "additionalProperties" : { + "type" : "object" + }, + "type" : "object" + } + } + }, + "description" : "OK" + } + }, + "summary" : "주기 작업 상태", + "tags" : [ "어드민 - 주기 작업" ] + } + }, + "/api/admin/users" : { + "get" : { + "operationId" : "list", + "parameters" : [ { + "in" : "query", + "name" : "pageable", + "required" : true, + "schema" : { + "$ref" : "#/components/schemas/Pageable" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/PageAdminUserResponse" + } + } + }, + "description" : "OK" + } + }, + "summary" : "사용자 목록 조회", + "tags" : [ "어드민 - 사용자" ] + } + }, + "/api/admin/users/active" : { + "get" : { + "operationId" : "activeUsers", + "parameters" : [ { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "items" : { + "$ref" : "#/components/schemas/UserDto" + }, + "type" : "array" + } + } + }, + "description" : "OK" + } + }, + "summary" : "활성 사용자 목록", + "tags" : [ "어드민 - 사용자" ] + } + }, + "/api/admin/users/by-region/{region}" : { + "get" : { + "operationId" : "usersByRegion", + "parameters" : [ { + "in" : "path", + "name" : "region", + "required" : true, + "schema" : { + "type" : "string" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "items" : { + "$ref" : "#/components/schemas/UserDto" + }, + "type" : "array" + } + } + }, + "description" : "OK" + } + }, + "summary" : "지역별 사용자 조회", + "tags" : [ "어드민 - 사용자" ] + } + }, + "/api/admin/users/by-type/{userType}" : { + "get" : { + "operationId" : "usersByType", + "parameters" : [ { + "in" : "path", + "name" : "userType", + "required" : true, + "schema" : { + "type" : "string" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "items" : { + "$ref" : "#/components/schemas/UserDto" + }, + "type" : "array" + } + } + }, + "description" : "OK" + } + }, + "summary" : "사용자 유형별 조회", + "tags" : [ "어드민 - 사용자" ] + } + }, + "/api/admin/users/recently-active" : { + "get" : { + "operationId" : "recentlyActiveUsers", + "parameters" : [ { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "items" : { + "$ref" : "#/components/schemas/UserDto" + }, + "type" : "array" + } + } + }, + "description" : "OK" + } + }, + "summary" : "최근 활동 사용자 목록", + "tags" : [ "어드민 - 사용자" ] + } + }, + "/api/admin/users/search" : { + "get" : { + "description" : "이름 또는 이메일 키워드로 검색", + "operationId" : "search", + "parameters" : [ { + "in" : "query", + "name" : "keyword", + "required" : true, + "schema" : { + "type" : "string" + } + }, { + "in" : "query", + "name" : "type", + "required" : false, + "schema" : { + "type" : "string" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "items" : { + "$ref" : "#/components/schemas/UserDto" + }, + "type" : "array" + } + } + }, + "description" : "OK" + } + }, + "summary" : "사용자 검색", + "tags" : [ "어드민 - 사용자" ] + } + }, + "/api/admin/users/statistics" : { + "get" : { + "operationId" : "statistics", + "parameters" : [ { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/UserStatsResponse" + } + } + }, + "description" : "OK" + } + }, + "summary" : "사용자 통계 조회", + "tags" : [ "어드민 - 사용자" ] + } + }, + "/api/admin/users/verified" : { + "get" : { + "operationId" : "verifiedUsers", + "parameters" : [ { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "items" : { + "$ref" : "#/components/schemas/UserDto" + }, + "type" : "array" + } + } + }, + "description" : "OK" + } + }, + "summary" : "이메일 인증 완료 사용자 목록", + "tags" : [ "어드민 - 사용자" ] + } + }, + "/api/admin/users/{id}" : { + "delete" : { + "description" : "물리 삭제 대신 soft delete 로 비활성화", + "operationId" : "delete", + "parameters" : [ { + "in" : "path", + "name" : "id", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "description" : "OK" + } + }, + "summary" : "사용자 탈퇴 처리", + "tags" : [ "어드민 - 사용자" ] + }, + "get" : { + "operationId" : "detail", + "parameters" : [ { + "in" : "path", + "name" : "id", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/AdminUserResponse" + } + } + }, + "description" : "OK" + } + }, + "summary" : "사용자 상세 조회", + "tags" : [ "어드민 - 사용자" ] + }, + "patch" : { + "description" : "이름·연락처·역할·활성 상태만 변경할 수 있습니다", + "operationId" : "update_1", + "parameters" : [ { + "in" : "path", + "name" : "id", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/AdminUserUpdateRequest" + } + } + }, + "required" : true + }, + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/AdminUserResponse" + } + } + }, + "description" : "OK" + } + }, + "summary" : "사용자 정보 수정", + "tags" : [ "어드민 - 사용자" ] + } + }, + "/api/admin/users/{id}/activate" : { + "put" : { + "description" : "비활성화된 사용자를 다시 활성화합니다", + "operationId" : "activate", + "parameters" : [ { + "in" : "path", + "name" : "id", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/ApiSuccess" + } + } + }, + "description" : "OK" + } + }, + "summary" : "사용자 활성화", + "tags" : [ "어드민 - 사용자" ] + } + }, + "/api/admin/users/{id}/reactivate" : { + "put" : { + "description" : "소프트 삭제된 계정을 복구합니다. 탈퇴한 본인은 로그인할 수 없으므로 관리자만 수행할 수 있습니다", + "operationId" : "reactivate", + "parameters" : [ { + "in" : "path", + "name" : "id", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/ApiSuccess" + } + } + }, + "description" : "OK" + } + }, + "summary" : "탈퇴 계정 복구", + "tags" : [ "어드민 - 사용자" ] + } + }, + "/api/admin/users/{id}/role" : { + "put" : { + "description" : "PARENT / ADMIN 등 역할을 변경합니다", + "operationId" : "updateRole", + "parameters" : [ { + "in" : "path", + "name" : "id", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "additionalProperties" : { + "type" : "string" + }, + "type" : "object" + } + } + }, + "required" : true + }, + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/ApiSuccess" + } + } + }, + "description" : "OK" + } + }, + "summary" : "사용자 역할 변경", + "tags" : [ "어드민 - 사용자" ] + } + }, + "/api/public-data/childcare-education" : { + "get" : { + "operationId" : "getChildcareEducation", + "parameters" : [ { + "description" : "교육 유형", + "in" : "query", + "name" : "educationType", + "required" : false, + "schema" : { + "type" : "string" + } + }, { + "description" : "페이지 번호", + "in" : "query", + "name" : "pageNo", + "required" : false, + "schema" : { + "default" : 1, + "format" : "int32", + "type" : "integer" + } + }, { + "description" : "페이지당 행 수", + "in" : "query", + "name" : "numOfRows", + "required" : false, + "schema" : { + "default" : 10, + "format" : "int32", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/PublicDataResponseObject" + } + } + }, + "description" : "OK" + } + }, + "summary" : "육아 교육 정보 조회", + "tags" : [ "공공데이터 API" ] + } + }, + "/api/public-data/childcare-facilities" : { + "get" : { + "description" : "지역별 육아 관련 시설 정보 조회", + "operationId" : "getChildcareFacilities", + "parameters" : [ { + "description" : "지역명", + "in" : "query", + "name" : "region", + "required" : false, + "schema" : { + "type" : "string" + } + }, { + "description" : "페이지 번호", + "in" : "query", + "name" : "pageNo", + "required" : false, + "schema" : { + "default" : 1, + "format" : "int32", + "type" : "integer" + } + }, { + "description" : "페이지당 행 수", + "in" : "query", + "name" : "numOfRows", + "required" : false, + "schema" : { + "default" : 10, + "format" : "int32", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/PublicDataResponseObject" + } + } + }, + "description" : "OK" + } + }, + "summary" : "육아 시설 정보 조회", + "tags" : [ "공공데이터 API" ] + } + }, + "/api/public-data/childcare-policies" : { + "get" : { + "operationId" : "getChildcarePolicies", + "parameters" : [ { + "description" : "정책 유형", + "in" : "query", + "name" : "policyType", + "required" : false, + "schema" : { + "type" : "string" + } + }, { + "description" : "페이지 번호", + "in" : "query", + "name" : "pageNo", + "required" : false, + "schema" : { + "default" : 1, + "format" : "int32", + "type" : "integer" + } + }, { + "description" : "페이지당 행 수", + "in" : "query", + "name" : "numOfRows", + "required" : false, + "schema" : { + "default" : 10, + "format" : "int32", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/PublicDataResponseObject" + } + } + }, + "description" : "OK" + } + }, + "summary" : "보육 정책 정보 조회", + "tags" : [ "공공데이터 API" ] + } + }, + "/api/public-data/childcare-subsidies" : { + "get" : { + "operationId" : "getChildcareSubsidies", + "parameters" : [ { + "description" : "지역명", + "in" : "query", + "name" : "region", + "required" : false, + "schema" : { + "type" : "string" + } + }, { + "description" : "페이지 번호", + "in" : "query", + "name" : "pageNo", + "required" : false, + "schema" : { + "default" : 1, + "format" : "int32", + "type" : "integer" + } + }, { + "description" : "페이지당 행 수", + "in" : "query", + "name" : "numOfRows", + "required" : false, + "schema" : { + "default" : 10, + "format" : "int32", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/PublicDataResponseObject" + } + } + }, + "description" : "OK" + } + }, + "summary" : "육아 지원금 정보 조회", + "tags" : [ "공공데이터 API" ] + } + }, + "/api/public-data/custom/{endpoint}" : { + "get" : { + "description" : "사용자 정의 엔드포인트로 공공데이터 API를 호출", + "operationId" : "callCustomApi", + "parameters" : [ { + "description" : "API 엔드포인트", + "in" : "path", + "name" : "endpoint", + "required" : true, + "schema" : { + "type" : "string" + } + }, { + "description" : "쿼리 파라미터", + "in" : "query", + "name" : "params", + "required" : true, + "schema" : { + "additionalProperties" : { + "type" : "string" + }, + "type" : "object" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/PublicDataResponseObject" + } + } + }, + "description" : "OK" + } + }, + "summary" : "커스텀 API 호출", + "tags" : [ "공공데이터 API" ] + } + }, + "/api/public-data/pediatric-hospitals" : { + "get" : { + "operationId" : "getPediatricHospitals", + "parameters" : [ { + "description" : "지역명", + "in" : "query", + "name" : "region", + "required" : false, + "schema" : { + "type" : "string" + } + }, { + "description" : "페이지 번호", + "in" : "query", + "name" : "pageNo", + "required" : false, + "schema" : { + "default" : 1, + "format" : "int32", + "type" : "integer" + } + }, { + "description" : "페이지당 행 수", + "in" : "query", + "name" : "numOfRows", + "required" : false, + "schema" : { + "default" : 10, + "format" : "int32", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/PublicDataResponseObject" + } + } + }, + "description" : "OK" + } + }, + "summary" : "소아과 병원 정보 조회", + "tags" : [ "공공데이터 API" ] + } + }, + "/api/public/care-facilities/swagger/db-facilities" : { + "get" : { + "operationId" : "swaggerGetDbFacilities", + "parameters" : [ { + "description" : "페이지 번호", + "example" : 0, + "in" : "query", + "name" : "page", + "required" : false, + "schema" : { + "default" : 0, + "format" : "int32", + "type" : "integer" + } + }, { + "description" : "한 페이지 결과 수", + "example" : 10, + "in" : "query", + "name" : "size", + "required" : false, + "schema" : { + "default" : 10, + "format" : "int32", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "additionalProperties" : { + "type" : "object" + }, + "type" : "object" + } + } + }, + "description" : "OK" + } + }, + "summary" : "DB 저장된 보육시설 목록", + "tags" : [ "돌봄시설 공공데이터" ] + } + }, + "/api/public/care-facilities/swagger/stats" : { + "get" : { + "description" : "DB에 저장된 보육시설 통계 정보 조회", + "operationId" : "swaggerGetStats", + "parameters" : [ { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "additionalProperties" : { + "type" : "object" + }, + "type" : "object" + } + } + }, + "description" : "OK" + } + }, + "summary" : "보육시설 통계", + "tags" : [ "돌봄시설 공공데이터" ] + } + }, + "/api/public/care-facilities/swagger/sync" : { + "get" : { + "description" : "Swagger UI에서 쉽게 테스트할 수 있는 GET 방식 동기화", + "operationId" : "swaggerSync", + "parameters" : [ { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "additionalProperties" : { + "type" : "object" + }, + "type" : "object" + } + } + }, + "description" : "OK" + } + }, + "summary" : "Swagger용 보육시설 동기화", + "tags" : [ "돌봄시설 공공데이터" ] + } + }, + "/api/public/care-facilities/sync-all" : { + "post" : { + "description" : "공공데이터에서 모든 보육시설 정보를 조회하고 DB에 저장", + "operationId" : "syncAllChildcareFacilities", + "parameters" : [ { + "description" : "시도명", + "example" : "서울특별시", + "in" : "query", + "name" : "sido", + "required" : false, + "schema" : { + "default" : "서울특별시", + "type" : "string" + } + }, { + "description" : "시군구명", + "example" : "강남구", + "in" : "query", + "name" : "sigungu", + "required" : false, + "schema" : { + "default" : "강남구", + "type" : "string" + } + }, { + "description" : "한 페이지 결과 수", + "example" : 100, + "in" : "query", + "name" : "numOfRows", + "required" : false, + "schema" : { + "default" : 100, + "format" : "int32", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "additionalProperties" : { + "type" : "object" + }, + "type" : "object" + } + } + }, + "description" : "OK" + } + }, + "summary" : "전체 보육시설 정보 동기화", + "tags" : [ "돌봄시설 공공데이터" ] + } + }, + "/auth/kakao/complete-registration" : { + "post" : { + "description" : "카카오 로그인 후 신규 사용자의 이름과 역할을 설정하여 가입을 완료", + "operationId" : "completeRegistration", + "parameters" : [ { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/KakaoRegistrationRequest" + } + } + }, + "required" : true + }, + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/UserDto" + } + } + }, + "description" : "OK" + } + }, + "summary" : "카카오 신규 사용자 가입 완료", + "tags" : [ "카카오 인증" ] + } + }, + "/auth/kakao/login" : { + "post" : { + "description" : "카카오 인증 코드를 받아 로그인하거나 신규 사용자 생성", + "operationId" : "kakaoLogin", + "parameters" : [ { + "description" : "카카오 인증 코드", + "in" : "query", + "name" : "code", + "required" : true, + "schema" : { + "type" : "string" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/TokenDto" + } + } + }, + "description" : "OK" + } + }, + "summary" : "카카오 OAuth 로그인/회원가입", + "tags" : [ "카카오 인증" ] + } + }, + "/auth/kakao/login-url" : { + "get" : { + "description" : "카카오 OAuth 로그인을 위한 URL 생성", + "operationId" : "getKakaoLoginUrl", + "parameters" : [ { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "additionalProperties" : { + "type" : "object" + }, + "type" : "object" + } + } + }, + "description" : "OK" + } + }, + "summary" : "카카오 로그인 URL 생성", + "tags" : [ "카카오 인증" ] + } + }, + "/auth/login" : { + "post" : { + "description" : "이메일과 비밀번호로 로그인", + "operationId" : "login", + "parameters" : [ { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/LoginRequestDto" + } + } + }, + "required" : true + }, + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/TokenDto" + } + } + }, + "description" : "OK" + } + }, + "summary" : "일반 로그인", + "tags" : [ "인증" ] + } + }, + "/auth/logout" : { + "post" : { + "description" : "서버에 등록된 리프레시 토큰 세션을 모두 폐기합니다", + "operationId" : "logout", + "parameters" : [ { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/ApiSuccess" + } + } + }, + "description" : "OK" + } + }, + "summary" : "로그아웃", + "tags" : [ "인증" ] + } + }, + "/auth/refresh" : { + "post" : { + "description" : "Refresh Token 으로 새로운 Access Token 을 발급토큰은 HttpOnly 쿠키에서 우선 읽고, 없으면 요청 본문에서 읽습니다.", + "operationId" : "refreshToken", + "parameters" : [ { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/RefreshTokenRequest" + } + } + } + }, + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/TokenDto" + } + } + }, + "description" : "OK" + } + }, + "summary" : "토큰 갱신", + "tags" : [ "인증" ] + } + }, + "/auth/register" : { + "post" : { + "description" : "새로운 사용자 등록", + "operationId" : "register_1", + "parameters" : [ { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/SignUpRequest" + } + } + }, + "required" : true + }, + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/TokenDto" + } + } + }, + "description" : "OK" + } + }, + "summary" : "회원가입", + "tags" : [ "인증" ] + } + }, + "/auth/send-code" : { + "post" : { + "operationId" : "sendVerificationCode", + "parameters" : [ { + "in" : "query", + "name" : "email", + "required" : true, + "schema" : { + "type" : "string" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/ApiSuccess" + } + } + }, + "description" : "OK" + } + }, + "summary" : "이메일 인증 코드 발송", + "tags" : [ "인증" ] + } + }, + "/auth/verify" : { + "get" : { + "description" : "이메일 인증 토큰을 검증", + "operationId" : "verifyEmail", + "parameters" : [ { + "in" : "query", + "name" : "token", + "required" : true, + "schema" : { + "type" : "string" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/ApiSuccess" + } + } + }, + "description" : "OK" + } + }, + "summary" : "이메일 인증", + "tags" : [ "인증" ] + } + }, + "/auth/verify-code" : { + "post" : { + "description" : "발송된 인증 코드를 검증", + "operationId" : "verifyCode", + "parameters" : [ { + "in" : "query", + "name" : "email", + "required" : true, + "schema" : { + "type" : "string" + } + }, { + "in" : "query", + "name" : "code", + "required" : true, + "schema" : { + "type" : "string" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/ApiSuccess" + } + } + }, + "description" : "OK" + } + }, + "summary" : "이메일 인증 코드 검증", + "tags" : [ "인증" ] + } + }, + "/chatbot/chat" : { + "post" : { + "description" : "챗봇과 대화를 시작", + "operationId" : "sendMessage", + "parameters" : [ { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/ChatbotMessageRequest" + } + } + }, + "required" : true + }, + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/ChatbotMessageResponse" + } + } + }, + "description" : "OK" + } + }, + "summary" : "챗봇 메시지 전송", + "tags" : [ "챗봇" ] + } + }, + "/chatbot/feedback" : { + "post" : { + "description" : "챗봇 메시지에 대한 피드백 처리", + "operationId" : "processFeedback", + "parameters" : [ { + "description" : "메시지 ID", + "in" : "query", + "name" : "messageId", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "도움됨 여부", + "in" : "query", + "name" : "isHelpful", + "required" : true, + "schema" : { + "type" : "boolean" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/ChatbotFeedbackDtoResponse" + } + } + }, + "description" : "OK" + } + }, + "summary" : "메시지 피드백 처리", + "tags" : [ "챗봇" ] + } + }, + "/chatbot/history" : { + "get" : { + "description" : "사용자의 챗봇 대화 기록 조회", + "operationId" : "getChatHistory", + "parameters" : [ { + "description" : "세션 ID", + "in" : "query", + "name" : "sessionId", + "required" : false, + "schema" : { + "type" : "string" + } + }, { + "description" : "페이지 번호", + "in" : "query", + "name" : "page", + "required" : false, + "schema" : { + "default" : 0, + "format" : "int32", + "type" : "integer" + } + }, { + "description" : "페이지 크기", + "in" : "query", + "name" : "size", + "required" : false, + "schema" : { + "default" : 20, + "format" : "int32", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "items" : { + "$ref" : "#/components/schemas/ChatbotChatHistoryDtoResponse" + }, + "type" : "array" + } + } + }, + "description" : "OK" + } + }, + "summary" : "대화 기록 조회", + "tags" : [ "챗봇" ] + } + }, + "/chatbot/messages/date-range" : { + "get" : { + "operationId" : "getMessagesByDateRange", + "parameters" : [ { + "description" : "(사용하지 않음) 대상은 인증 주체로 결정됩니다", + "in" : "query", + "name" : "userId", + "required" : false, + "schema" : { + "type" : "string" + } + }, { + "description" : "시작일시 (yyyy-MM-ddTHH:mm:ss)", + "in" : "query", + "name" : "startDate", + "required" : true, + "schema" : { + "type" : "string" + } + }, { + "description" : "종료일시 (yyyy-MM-ddTHH:mm:ss)", + "in" : "query", + "name" : "endDate", + "required" : true, + "schema" : { + "type" : "string" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "items" : { + "$ref" : "#/components/schemas/ChatbotChatHistoryDtoResponse" + }, + "type" : "array" + } + } + }, + "description" : "OK" + } + }, + "summary" : "기간별 메시지 조회", + "tags" : [ "챗봇" ] + } + }, + "/chatbot/messages/helpful" : { + "get" : { + "operationId" : "getMessagesByHelpfulStatus", + "parameters" : [ { + "description" : "(사용하지 않음) 대상은 인증 주체로 결정됩니다", + "in" : "query", + "name" : "userId", + "required" : false, + "schema" : { + "type" : "string" + } + }, { + "description" : "도움됨 여부", + "in" : "query", + "name" : "isHelpful", + "required" : true, + "schema" : { + "type" : "boolean" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "items" : { + "$ref" : "#/components/schemas/ChatbotChatHistoryDtoResponse" + }, + "type" : "array" + } + } + }, + "description" : "OK" + } + }, + "summary" : "도움됨 여부별 메시지 조회", + "tags" : [ "챗봇" ] + } + }, + "/chatbot/messages/intent" : { + "get" : { + "operationId" : "getMessagesByIntentType", + "parameters" : [ { + "description" : "(사용하지 않음) 대상은 인증 주체로 결정됩니다", + "in" : "query", + "name" : "userId", + "required" : false, + "schema" : { + "type" : "string" + } + }, { + "description" : "의도 타입 (GREETING, QUESTION, COMPLAINT, THANKS, GOODBYE, HEALTH_INFO, UNKNOWN)", + "in" : "query", + "name" : "intentType", + "required" : true, + "schema" : { + "type" : "string" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "items" : { + "$ref" : "#/components/schemas/ChatbotChatHistoryDtoResponse" + }, + "type" : "array" + } + } + }, + "description" : "OK" + } + }, + "summary" : "의도 타입별 메시지 조회", + "tags" : [ "챗봇" ] + } + }, + "/chatbot/messages/search" : { + "get" : { + "operationId" : "searchMessagesByKeyword", + "parameters" : [ { + "description" : "(사용하지 않음) 대상은 인증 주체로 결정됩니다", + "in" : "query", + "name" : "userId", + "required" : false, + "schema" : { + "type" : "string" + } + }, { + "description" : "검색 키워드", + "in" : "query", + "name" : "keyword", + "required" : true, + "schema" : { + "type" : "string" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "items" : { + "$ref" : "#/components/schemas/ChatbotChatHistoryDtoResponse" + }, + "type" : "array" + } + } + }, + "description" : "OK" + } + }, + "summary" : "키워드로 메시지 검색", + "tags" : [ "챗봇" ] + } + }, + "/chatbot/sessions" : { + "get" : { + "description" : "사용자의 챗봇 세션 목록 조회", + "operationId" : "getSessions", + "parameters" : [ { + "description" : "페이지 번호", + "in" : "query", + "name" : "page", + "required" : false, + "schema" : { + "default" : 0, + "format" : "int32", + "type" : "integer" + } + }, { + "description" : "페이지 크기", + "in" : "query", + "name" : "size", + "required" : false, + "schema" : { + "default" : 10, + "format" : "int32", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "items" : { + "$ref" : "#/components/schemas/ChatbotSessionDtoResponse" + }, + "type" : "array" + } + } + }, + "description" : "OK" + } + }, + "summary" : "세션 목록 조회", + "tags" : [ "챗봇" ] + } + }, + "/chatbot/sessions/count" : { + "get" : { + "operationId" : "getSessionCountByUser", + "parameters" : [ { + "description" : "(사용하지 않음) 대상은 인증 주체로 결정됩니다", + "in" : "query", + "name" : "userId", + "required" : false, + "schema" : { + "type" : "string" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "additionalProperties" : { + "format" : "int64", + "type" : "integer" + }, + "type" : "object" + } + } + }, + "description" : "OK" + } + }, + "summary" : "사용자별 세션 수 조회", + "tags" : [ "챗봇" ] + } + }, + "/chatbot/sessions/date-range" : { + "get" : { + "description" : "특정 기간의 세션 조회", + "operationId" : "getSessionsByDateRange", + "parameters" : [ { + "description" : "(사용하지 않음) 대상은 인증 주체로 결정됩니다", + "in" : "query", + "name" : "userId", + "required" : false, + "schema" : { + "type" : "string" + } + }, { + "description" : "시작일시 (yyyy-MM-ddTHH:mm:ss)", + "in" : "query", + "name" : "startDate", + "required" : true, + "schema" : { + "type" : "string" + } + }, { + "description" : "종료일시 (yyyy-MM-ddTHH:mm:ss)", + "in" : "query", + "name" : "endDate", + "required" : true, + "schema" : { + "type" : "string" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "items" : { + "$ref" : "#/components/schemas/ChatbotSessionDtoResponse" + }, + "type" : "array" + } + } + }, + "description" : "OK" + } + }, + "summary" : "기간별 세션 조회", + "tags" : [ "챗봇" ] + } + }, + "/chatbot/sessions/status" : { + "get" : { + "description" : "특정 상태의 세션 조회", + "operationId" : "getSessionsByStatus", + "parameters" : [ { + "description" : "(사용하지 않음) 대상은 인증 주체로 결정됩니다", + "in" : "query", + "name" : "userId", + "required" : false, + "schema" : { + "type" : "string" + } + }, { + "description" : "세션 상태 (ACTIVE, INACTIVE, CLOSED)", + "in" : "query", + "name" : "status", + "required" : true, + "schema" : { + "type" : "string" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "items" : { + "$ref" : "#/components/schemas/ChatbotSessionDtoResponse" + }, + "type" : "array" + } + } + }, + "description" : "OK" + } + }, + "summary" : "상태별 세션 조회", + "tags" : [ "챗봇" ] + } + }, + "/children" : { + "get" : { + "operationId" : "getMyChildren", + "parameters" : [ { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "items" : { + "$ref" : "#/components/schemas/ChildInfoResponse" + }, + "type" : "array" + } + } + }, + "description" : "OK" + } + }, + "summary" : "내 아이 목록 조회", + "tags" : [ "아이 관리" ] + }, + "post" : { + "description" : "아이를 등록하고 생년월일 기준 표준 예방접종 일정을 자동 생성", + "operationId" : "createChild", + "parameters" : [ { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/ChildCreateRequest" + } + } + }, + "required" : true + }, + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/ChildInfoResponse" + } + } + }, + "description" : "OK" + } + }, + "summary" : "아이 등록", + "tags" : [ "아이 관리" ] + } + }, + "/children/overview" : { + "get" : { + "description" : "모든 자녀의 접종·대기·다자녀 혜택을 한 번에 조회", + "operationId" : "overview", + "parameters" : [ { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/SiblingOverviewResponse" + } + } + }, + "description" : "OK" + } + }, + "summary" : "자녀 통합 현황", + "tags" : [ "아이 관리" ] + } + }, + "/children/{childId}" : { + "delete" : { + "operationId" : "deleteChild", + "parameters" : [ { + "in" : "path", + "name" : "childId", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "description" : "OK" + } + }, + "summary" : "아이 삭제", + "tags" : [ "아이 관리" ] + }, + "get" : { + "operationId" : "getChild", + "parameters" : [ { + "in" : "path", + "name" : "childId", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/ChildInfoResponse" + } + } + }, + "description" : "OK" + } + }, + "summary" : "아이 상세 조회", + "tags" : [ "아이 관리" ] + }, + "put" : { + "operationId" : "updateChild", + "parameters" : [ { + "in" : "path", + "name" : "childId", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/ChildCreateRequest" + } + } + }, + "required" : true + }, + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/ChildInfoResponse" + } + } + }, + "description" : "OK" + } + }, + "summary" : "아이 정보 수정", + "tags" : [ "아이 관리" ] + } + }, + "/children/{childId}/growth" : { + "get" : { + "description" : "기록된 키/몸무게를 WHO 성장 표준과 비교한 백분위와 함께 반환백분위는 참고 지표이며 진단은 의료진 판단을 따릅니다.", + "operationId" : "getGrowthChart", + "parameters" : [ { + "in" : "path", + "name" : "childId", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "지표 (WEIGHT 또는 HEIGHT)", + "in" : "query", + "name" : "metric", + "required" : false, + "schema" : { + "default" : "WEIGHT", + "enum" : [ "WEIGHT", "HEIGHT" ], + "type" : "string" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "items" : { + "$ref" : "#/components/schemas/GrowthPointResponse" + }, + "type" : "array" + } + } + }, + "description" : "OK" + } + }, + "summary" : "성장 곡선 조회", + "tags" : [ "아이 관리" ] + } + }, + "/children/{childId}/growth/latest" : { + "get" : { + "operationId" : "getLatestGrowth", + "parameters" : [ { + "in" : "path", + "name" : "childId", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "in" : "query", + "name" : "metric", + "required" : false, + "schema" : { + "default" : "WEIGHT", + "enum" : [ "WEIGHT", "HEIGHT" ], + "type" : "string" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/GrowthPointResponse" + } + } + }, + "description" : "OK" + } + }, + "summary" : "최근 측정 백분위 조회", + "tags" : [ "아이 관리" ] + } + }, + "/children/{childId}/vaccinations" : { + "get" : { + "description" : "표준 일정에 따른 접종 예정일과 완료 여부 반환", + "operationId" : "getVaccinationSchedule", + "parameters" : [ { + "in" : "path", + "name" : "childId", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "items" : { + "$ref" : "#/components/schemas/VaccinationScheduleResponse" + }, + "type" : "array" + } + } + }, + "description" : "OK" + } + }, + "summary" : "예방접종 일정 조회", + "tags" : [ "아이 관리" ] + } + }, + "/children/{childId}/vaccinations/overdue" : { + "get" : { + "operationId" : "getOverdueVaccinations", + "parameters" : [ { + "in" : "path", + "name" : "childId", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "items" : { + "$ref" : "#/components/schemas/VaccinationScheduleResponse" + }, + "type" : "array" + } + } + }, + "description" : "OK" + } + }, + "summary" : "미접종(기한 경과) 목록 조회", + "tags" : [ "아이 관리" ] + } + }, + "/children/{childId}/vaccinations/{scheduleId}/complete" : { + "patch" : { + "operationId" : "completeVaccination", + "parameters" : [ { + "in" : "path", + "name" : "childId", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "in" : "path", + "name" : "scheduleId", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "실제 접종일 (미지정 시 오늘)", + "in" : "query", + "name" : "completedDate", + "required" : false, + "schema" : { + "format" : "date", + "type" : "string" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/VaccinationScheduleResponse" + } + } + }, + "description" : "OK" + } + }, + "summary" : "접종 완료 처리", + "tags" : [ "아이 관리" ] + } + }, + "/community/blocks" : { + "get" : { + "operationId" : "getBlockedUsers", + "parameters" : [ { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "items" : { + "format" : "int64", + "type" : "integer" + }, + "type" : "array" + } + } + }, + "description" : "OK" + } + }, + "summary" : "내가 차단한 사용자 목록", + "tags" : [ "커뮤니티 모더레이션" ] + } + }, + "/community/blocks/{userId}" : { + "delete" : { + "operationId" : "unblockUser", + "parameters" : [ { + "in" : "path", + "name" : "userId", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "description" : "OK" + } + }, + "summary" : "사용자 차단 해제", + "tags" : [ "커뮤니티 모더레이션" ] + }, + "post" : { + "description" : "차단한 사용자의 글과 댓글이 목록에서 보이지 않습니다", + "operationId" : "blockUser", + "parameters" : [ { + "in" : "path", + "name" : "userId", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "description" : "OK" + } + }, + "summary" : "사용자 차단", + "tags" : [ "커뮤니티 모더레이션" ] + } + }, + "/community/comments/{commentId}" : { + "delete" : { + "operationId" : "deleteComment", + "parameters" : [ { + "description" : "댓글 ID", + "in" : "path", + "name" : "commentId", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/ApiSuccess" + } + } + }, + "description" : "OK" + } + }, + "summary" : "댓글 삭제", + "tags" : [ "커뮤니티" ] + }, + "put" : { + "operationId" : "updateComment", + "parameters" : [ { + "description" : "댓글 ID", + "in" : "path", + "name" : "commentId", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/CommunityUpdateCommentRequest" + } + } + }, + "required" : true + }, + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/CommunityCommentResponse" + } + } + }, + "description" : "OK" + } + }, + "summary" : "댓글 수정", + "tags" : [ "커뮤니티" ] + } + }, + "/community/latest" : { + "get" : { + "description" : "최근 작성된 게시글 목록을 페이징으로 조회", + "operationId" : "getLatestPosts", + "parameters" : [ { + "description" : "페이지 번호 (0부터 시작)", + "example" : 0, + "in" : "query", + "name" : "page", + "required" : false, + "schema" : { + "default" : 0, + "format" : "int32", + "type" : "integer" + } + }, { + "description" : "페이지당 항목 수", + "example" : 10, + "in" : "query", + "name" : "size", + "required" : false, + "schema" : { + "default" : 10, + "format" : "int32", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/CommunityPageResponseCommunityPostResponse" + } + } + }, + "description" : "OK" + } + }, + "summary" : "최신 게시글 조회", + "tags" : [ "커뮤니티" ] + } + }, + "/community/popular" : { + "get" : { + "description" : "인기 있는 게시글 목록을 페이징으로 조회", + "operationId" : "getPopularPosts", + "parameters" : [ { + "description" : "페이지 번호 (0부터 시작)", + "example" : 0, + "in" : "query", + "name" : "page", + "required" : false, + "schema" : { + "default" : 0, + "format" : "int32", + "type" : "integer" + } + }, { + "description" : "페이지당 항목 수", + "example" : 10, + "in" : "query", + "name" : "size", + "required" : false, + "schema" : { + "default" : 10, + "format" : "int32", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/CommunityPageResponseCommunityPostResponse" + } + } + }, + "description" : "OK" + } + }, + "summary" : "인기 게시글 조회", + "tags" : [ "커뮤니티" ] + } + }, + "/community/posts" : { + "get" : { + "description" : "커뮤니티 게시글 목록을 페이징으로 조회", + "operationId" : "getAllPosts", + "parameters" : [ { + "description" : "페이지 번호 (0부터 시작)", + "example" : 0, + "in" : "query", + "name" : "page", + "required" : false, + "schema" : { + "default" : 0, + "format" : "int32", + "type" : "integer" + } + }, { + "description" : "페이지당 항목 수", + "example" : 10, + "in" : "query", + "name" : "size", + "required" : false, + "schema" : { + "default" : 10, + "format" : "int32", + "type" : "integer" + } + }, { + "description" : "정렬 필드 (createdAt, viewCount, likeCount 등)", + "example" : "createdAt", + "in" : "query", + "name" : "sortBy", + "required" : false, + "schema" : { + "type" : "string" + } + }, { + "description" : "정렬 방향 (ASC, DESC)", + "example" : "DESC", + "in" : "query", + "name" : "sortDirection", + "required" : false, + "schema" : { + "type" : "string" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/CommunityPageResponseCommunityPostResponse" + } + } + }, + "description" : "OK" + } + }, + "summary" : "게시글 목록 조회", + "tags" : [ "커뮤니티" ] + }, + "post" : { + "description" : "새로운 게시글을 작성", + "operationId" : "createPost", + "parameters" : [ { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/CommunityCreatePostRequest" + } + } + }, + "required" : true + }, + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/CommunityPostResponse" + } + } + }, + "description" : "OK" + } + }, + "summary" : "게시글 작성", + "tags" : [ "커뮤니티" ] + } + }, + "/community/posts/bookmarked" : { + "get" : { + "description" : "현재 사용자가 북마크한 게시글 목록 조회", + "operationId" : "getBookmarkedPosts", + "parameters" : [ { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "items" : { + "$ref" : "#/components/schemas/CommunityPostResponse" + }, + "type" : "array" + } + } + }, + "description" : "OK" + } + }, + "summary" : "북마크한 게시글 목록", + "tags" : [ "커뮤니티" ] + } + }, + "/community/posts/liked" : { + "get" : { + "description" : "현재 사용자가 좋아요한 게시글 목록 조회", + "operationId" : "getLikedPosts", + "parameters" : [ { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "items" : { + "$ref" : "#/components/schemas/CommunityPostResponse" + }, + "type" : "array" + } + } + }, + "description" : "OK" + } + }, + "summary" : "좋아요한 게시글 목록", + "tags" : [ "커뮤니티" ] + } + }, + "/community/posts/{postId}" : { + "delete" : { + "operationId" : "deletePost", + "parameters" : [ { + "description" : "게시글 ID", + "in" : "path", + "name" : "postId", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/ApiSuccess" + } + } + }, + "description" : "OK" + } + }, + "summary" : "게시글 삭제", + "tags" : [ "커뮤니티" ] + }, + "get" : { + "description" : "특정 게시글의 상세 정보 조회", + "operationId" : "getPost", + "parameters" : [ { + "description" : "게시글 ID", + "in" : "path", + "name" : "postId", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/CommunityPostDetailResponse" + } + } + }, + "description" : "OK" + } + }, + "summary" : "게시글 상세 조회", + "tags" : [ "커뮤니티" ] + }, + "put" : { + "operationId" : "updatePost", + "parameters" : [ { + "description" : "게시글 ID", + "in" : "path", + "name" : "postId", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/CommunityUpdatePostRequest" + } + } + }, + "required" : true + }, + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/CommunityPostResponse" + } + } + }, + "description" : "OK" + } + }, + "summary" : "게시글 수정", + "tags" : [ "커뮤니티" ] + } + }, + "/community/posts/{postId}/bookmark" : { + "post" : { + "description" : "게시글을 북마크에 추가하거나 제거", + "operationId" : "toggleBookmark", + "parameters" : [ { + "description" : "게시글 ID", + "in" : "path", + "name" : "postId", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "additionalProperties" : { + "type" : "object" + }, + "type" : "object" + } + } + }, + "description" : "OK" + } + }, + "summary" : "게시글 북마크", + "tags" : [ "커뮤니티" ] + } + }, + "/community/posts/{postId}/bookmark-count" : { + "get" : { + "description" : "특정 게시글의 북마크 수 조회", + "operationId" : "getBookmarkCount", + "parameters" : [ { + "description" : "게시글 ID", + "in" : "path", + "name" : "postId", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "additionalProperties" : { + "format" : "int64", + "type" : "integer" + }, + "type" : "object" + } + } + }, + "description" : "OK" + } + }, + "summary" : "게시글 북마크 수", + "tags" : [ "커뮤니티" ] + } + }, + "/community/posts/{postId}/comments" : { + "get" : { + "description" : "특정 게시글의 댓글 목록 조회", + "operationId" : "getComments", + "parameters" : [ { + "description" : "게시글 ID", + "in" : "path", + "name" : "postId", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "items" : { + "$ref" : "#/components/schemas/CommunityCommentResponse" + }, + "type" : "array" + } + } + }, + "description" : "OK" + } + }, + "summary" : "댓글 목록 조회", + "tags" : [ "커뮤니티" ] + }, + "post" : { + "description" : "게시글에 댓글을 작성", + "operationId" : "createComment", + "parameters" : [ { + "description" : "게시글 ID", + "in" : "path", + "name" : "postId", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/CommunityCreateCommentRequest" + } + } + }, + "required" : true + }, + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/CommunityCommentResponse" + } + } + }, + "description" : "OK" + } + }, + "summary" : "댓글 작성", + "tags" : [ "커뮤니티" ] + } + }, + "/community/posts/{postId}/like" : { + "post" : { + "description" : "게시글에 좋아요를 추가하거나 제거", + "operationId" : "toggleLike", + "parameters" : [ { + "description" : "게시글 ID", + "in" : "path", + "name" : "postId", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "additionalProperties" : { + "type" : "object" + }, + "type" : "object" + } + } + }, + "description" : "OK" + } + }, + "summary" : "게시글 좋아요", + "tags" : [ "커뮤니티" ] + } + }, + "/community/posts/{postId}/like-count" : { + "get" : { + "description" : "특정 게시글의 좋아요 수 조회", + "operationId" : "getLikeCount", + "parameters" : [ { + "description" : "게시글 ID", + "in" : "path", + "name" : "postId", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "additionalProperties" : { + "format" : "int64", + "type" : "integer" + }, + "type" : "object" + } + } + }, + "description" : "OK" + } + }, + "summary" : "게시글 좋아요 수", + "tags" : [ "커뮤니티" ] + } + }, + "/community/reports" : { + "post" : { + "description" : "신고가 누적되면 관리자 확인 전까지 자동으로 숨김 처리", + "operationId" : "report", + "parameters" : [ { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/ReportCreateRequest" + } + } + }, + "required" : true + }, + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/ReportResponse" + } + } + }, + "description" : "OK" + } + }, + "summary" : "게시글·댓글 신고", + "tags" : [ "커뮤니티 모더레이션" ] + } + }, + "/community/search" : { + "get" : { + "description" : "키워드로 게시글을 페이징 검색", + "operationId" : "searchPosts", + "parameters" : [ { + "description" : "검색 키워드", + "in" : "query", + "name" : "keyword", + "required" : true, + "schema" : { + "type" : "string" + } + }, { + "description" : "페이지 번호 (0부터 시작)", + "example" : 0, + "in" : "query", + "name" : "page", + "required" : false, + "schema" : { + "default" : 0, + "format" : "int32", + "type" : "integer" + } + }, { + "description" : "페이지당 항목 수", + "example" : 10, + "in" : "query", + "name" : "size", + "required" : false, + "schema" : { + "default" : 10, + "format" : "int32", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/CommunityPageResponseCommunityPostResponse" + } + } + }, + "description" : "OK" + } + }, + "summary" : "게시글 검색", + "tags" : [ "커뮤니티" ] + } + }, + "/community/tags" : { + "get" : { + "operationId" : "getAllTags", + "parameters" : [ { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "items" : { + "$ref" : "#/components/schemas/CommunityTagResponse" + }, + "type" : "array" + } + } + }, + "description" : "OK" + } + }, + "summary" : "태그 목록 조회", + "tags" : [ "커뮤니티" ] + } + }, + "/facilities" : { + "get" : { + "description" : "등록된 모든 육아 시설 목록 조회", + "operationId" : "getAllFacilities", + "parameters" : [ { + "description" : "페이지 번호 (0부터)", + "in" : "query", + "name" : "page", + "required" : false, + "schema" : { + "format" : "int32", + "type" : "integer" + } + }, { + "description" : "페이지 크기 (최대 200)", + "in" : "query", + "name" : "size", + "required" : false, + "schema" : { + "format" : "int32", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "items" : { + "$ref" : "#/components/schemas/CareFacilityInfo" + }, + "type" : "array" + } + } + }, + "description" : "OK" + } + }, + "summary" : "전체 시설 목록 조회", + "tags" : [ "육아 시설" ] + } + }, + "/facilities/advanced-search" : { + "post" : { + "description" : "다양한 조건을 조합하여 시설 검색", + "operationId" : "advancedSearch", + "parameters" : [ { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/CareFacilityAdvancedSearchRequest" + } + } + }, + "required" : true + }, + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "items" : { + "$ref" : "#/components/schemas/CareFacilityInfo" + }, + "type" : "array" + } + } + }, + "description" : "OK" + } + }, + "summary" : "고급 검색", + "tags" : [ "육아 시설" ] + } + }, + "/facilities/age" : { + "get" : { + "description" : "특정 연령대에 적합한 육아 시설 목록 조회", + "operationId" : "getFacilitiesByAgeRange", + "parameters" : [ { + "description" : "최소 연령", + "in" : "query", + "name" : "minAge", + "required" : true, + "schema" : { + "format" : "int32", + "type" : "integer" + } + }, { + "description" : "최대 연령", + "in" : "query", + "name" : "maxAge", + "required" : true, + "schema" : { + "format" : "int32", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "items" : { + "$ref" : "#/components/schemas/CareFacilityInfo" + }, + "type" : "array" + } + } + }, + "description" : "OK" + } + }, + "summary" : "연령대별 시설 조회", + "tags" : [ "육아 시설" ] + } + }, + "/facilities/available-spots" : { + "get" : { + "description" : "최소 자리 수 이상의 빈 자리가 있는 시설 조회", + "operationId" : "getFacilitiesWithSpots", + "parameters" : [ { + "description" : "최소 자리 수", + "example" : 1, + "in" : "query", + "name" : "minSpots", + "required" : false, + "schema" : { + "default" : 1, + "format" : "int32", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "items" : { + "$ref" : "#/components/schemas/CareFacilityInfo" + }, + "type" : "array" + } + } + }, + "description" : "OK" + } + }, + "summary" : "빈 자리 있는 시설 조회", + "tags" : [ "육아 시설" ] + } + }, + "/facilities/bookings/today" : { + "get" : { + "description" : "오늘 날짜의 예약 목록 조회", + "operationId" : "getTodayBookings", + "parameters" : [ { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "items" : { + "$ref" : "#/components/schemas/BookingResponse" + }, + "type" : "array" + } + } + }, + "description" : "OK" + } + }, + "summary" : "오늘의 예약 조회", + "tags" : [ "육아 시설" ] + } + }, + "/facilities/bookings/user" : { + "get" : { + "description" : "현재 로그인한 사용자의 예약 목록 조회", + "operationId" : "getUserBookings", + "parameters" : [ { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "items" : { + "$ref" : "#/components/schemas/BookingResponse" + }, + "type" : "array" + } + } + }, + "description" : "OK" + } + }, + "summary" : "사용자별 예약 목록 조회", + "tags" : [ "육아 시설" ] + } + }, + "/facilities/bookings/{bookingId}" : { + "delete" : { + "description" : "예약을 취소", + "operationId" : "cancelBooking", + "parameters" : [ { + "description" : "예약 ID", + "in" : "path", + "name" : "bookingId", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/ApiSuccess" + } + } + }, + "description" : "OK" + } + }, + "summary" : "예약 취소", + "tags" : [ "육아 시설" ] + }, + "get" : { + "description" : "특정 예약의 상세 정보 조회", + "operationId" : "getBookingById", + "parameters" : [ { + "description" : "예약 ID", + "in" : "path", + "name" : "bookingId", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/BookingResponse" + } + } + }, + "description" : "OK" + } + }, + "summary" : "예약 상세 조회", + "tags" : [ "육아 시설" ] + }, + "put" : { + "description" : "기존 예약 정보 수정", + "operationId" : "updateBooking", + "parameters" : [ { + "description" : "예약 ID", + "in" : "path", + "name" : "bookingId", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/UpdateBookingRequest" + } + } + }, + "required" : true + }, + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/BookingResponse" + } + } + }, + "description" : "OK" + } + }, + "summary" : "예약 수정", + "tags" : [ "육아 시설" ] + } + }, + "/facilities/bookings/{bookingId}/status" : { + "put" : { + "operationId" : "updateBookingStatus", + "parameters" : [ { + "description" : "예약 ID", + "in" : "path", + "name" : "bookingId", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "새로운 상태", + "in" : "query", + "name" : "status", + "required" : true, + "schema" : { + "type" : "string" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/BookingResponse" + } + } + }, + "description" : "OK" + } + }, + "summary" : "예약 상태 업데이트", + "tags" : [ "육아 시설" ] + } + }, + "/facilities/forecast-accuracy" : { + "get" : { + "description" : "과거 관측으로 같은 예측을 다시 계산해 실제 결과와 비교한 측정값. 확률대별 실제 적중률과, 항상 평균으로 답했을 때(기준선)와의 비교를 함께 준다. 표본이 부족한 기간은 목록에 없다.", + "operationId" : "getForecastAccuracy", + "parameters" : [ { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "items" : { + "$ref" : "#/components/schemas/ForecastAccuracyResponse" + }, + "type" : "array" + } + } + }, + "description" : "OK" + } + }, + "summary" : "입소 예측 정확도", + "tags" : [ "육아 시설" ] + } + }, + "/facilities/keyword" : { + "get" : { + "description" : "키워드로 시설명 또는 주소 검색", + "operationId" : "searchByKeyword", + "parameters" : [ { + "description" : "검색 키워드", + "in" : "query", + "name" : "keyword", + "required" : true, + "schema" : { + "type" : "string" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "items" : { + "$ref" : "#/components/schemas/CareFacilityInfo" + }, + "type" : "array" + } + } + }, + "description" : "OK" + } + }, + "summary" : "키워드 검색", + "tags" : [ "육아 시설" ] + } + }, + "/facilities/location/{location}" : { + "get" : { + "description" : "특정 지역의 육아 시설 목록 조회", + "operationId" : "getFacilitiesByLocation", + "parameters" : [ { + "description" : "지역명", + "in" : "path", + "name" : "location", + "required" : true, + "schema" : { + "type" : "string" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "items" : { + "$ref" : "#/components/schemas/CareFacilityInfo" + }, + "type" : "array" + } + } + }, + "description" : "OK" + } + }, + "summary" : "지역별 시설 조회", + "tags" : [ "육아 시설" ] + } + }, + "/facilities/new" : { + "get" : { + "description" : "최근 등록된 육아 시설 목록 조회", + "operationId" : "getNewFacilities", + "parameters" : [ { + "description" : "조회할 시설 수", + "example" : 10, + "in" : "query", + "name" : "limit", + "required" : false, + "schema" : { + "default" : 10, + "format" : "int32", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "items" : { + "$ref" : "#/components/schemas/CareFacilityInfo" + }, + "type" : "array" + } + } + }, + "description" : "OK" + } + }, + "summary" : "신규 시설 조회", + "tags" : [ "육아 시설" ] + } + }, + "/facilities/operating-hours" : { + "get" : { + "description" : "특정 운영 시간을 가진 육아 시설 목록 조회", + "operationId" : "getFacilitiesByOperatingHours", + "parameters" : [ { + "description" : "운영 시간", + "in" : "query", + "name" : "operatingHours", + "required" : true, + "schema" : { + "type" : "string" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "items" : { + "$ref" : "#/components/schemas/CareFacilityInfo" + }, + "type" : "array" + } + } + }, + "description" : "OK" + } + }, + "summary" : "운영 시간별 시설 조회", + "tags" : [ "육아 시설" ] + } + }, + "/facilities/popular" : { + "get" : { + "description" : "평점 기준으로 인기 있는 육아 시설 목록 조회", + "operationId" : "getPopularFacilities", + "parameters" : [ { + "description" : "조회할 시설 수", + "example" : 10, + "in" : "query", + "name" : "limit", + "required" : false, + "schema" : { + "default" : 10, + "format" : "int32", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "items" : { + "$ref" : "#/components/schemas/CareFacilityInfo" + }, + "type" : "array" + } + } + }, + "description" : "OK" + } + }, + "summary" : "인기 시설 조회", + "tags" : [ "육아 시설" ] + } + }, + "/facilities/radius" : { + "get" : { + "description" : "특정 위치 기준 반경 내의 육아 시설 검색", + "operationId" : "getFacilitiesWithinRadius", + "parameters" : [ { + "description" : "위도", + "in" : "query", + "name" : "latitude", + "required" : true, + "schema" : { + "format" : "double", + "type" : "number" + } + }, { + "description" : "경도", + "in" : "query", + "name" : "longitude", + "required" : true, + "schema" : { + "format" : "double", + "type" : "number" + } + }, { + "description" : "반경 (km)", + "in" : "query", + "name" : "radius", + "required" : true, + "schema" : { + "format" : "double", + "type" : "number" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "items" : { + "$ref" : "#/components/schemas/CareFacilityInfo" + }, + "type" : "array" + } + } + }, + "description" : "OK" + } + }, + "summary" : "반경 내 시설 검색", + "tags" : [ "육아 시설" ] + } + }, + "/facilities/rating" : { + "get" : { + "description" : "최소 평점 이상의 육아 시설 조회", + "operationId" : "getFacilitiesByRating", + "parameters" : [ { + "description" : "최소 평점 (0.0 ~ 5.0)", + "in" : "query", + "name" : "minRating", + "required" : true, + "schema" : { + "format" : "double", + "type" : "number" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "items" : { + "$ref" : "#/components/schemas/CareFacilityInfo" + }, + "type" : "array" + } + } + }, + "description" : "OK" + } + }, + "summary" : "평점별 시설 조회", + "tags" : [ "육아 시설" ] + } + }, + "/facilities/recommend/age" : { + "get" : { + "description" : "아이의 연령에 맞는 육아 시설을 추천", + "operationId" : "recommendFacilitiesByAge", + "parameters" : [ { + "description" : "아이 연령", + "in" : "query", + "name" : "childAge", + "required" : true, + "schema" : { + "format" : "int32", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "items" : { + "$ref" : "#/components/schemas/CareFacilityInfo" + }, + "type" : "array" + } + } + }, + "description" : "OK" + } + }, + "summary" : "아이 연령별 시설 추천", + "tags" : [ "육아 시설" ] + } + }, + "/facilities/reviews/{reviewId}" : { + "delete" : { + "operationId" : "deleteReview", + "parameters" : [ { + "in" : "path", + "name" : "reviewId", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/ApiSuccess" + } + } + }, + "description" : "OK" + } + }, + "summary" : "시설 리뷰 삭제", + "tags" : [ "육아 시설" ] + }, + "put" : { + "operationId" : "updateReview", + "parameters" : [ { + "in" : "path", + "name" : "reviewId", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/ReviewRequest" + } + } + }, + "required" : true + }, + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/ReviewResponse" + } + } + }, + "description" : "OK" + } + }, + "summary" : "시설 리뷰 수정", + "tags" : [ "육아 시설" ] + } + }, + "/facilities/search" : { + "post" : { + "description" : "다양한 조건으로 육아 시설 검색", + "operationId" : "searchFacilities", + "parameters" : [ { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/CareFacilitySearchRequest" + } + } + }, + "required" : true + }, + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/CareFacilityListResponse" + } + } + }, + "description" : "OK" + } + }, + "summary" : "복합 조건 시설 검색", + "tags" : [ "육아 시설" ] + } + }, + "/facilities/statistics" : { + "get" : { + "description" : "육아 시설 관련 통계 정보 조회", + "operationId" : "getFacilityStatistics", + "parameters" : [ { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/CareFacilityStatsResponse" + } + } + }, + "description" : "OK" + } + }, + "summary" : "시설 통계 조회", + "tags" : [ "육아 시설" ] + } + }, + "/facilities/tuition-fee" : { + "get" : { + "description" : "최대 등록금 이하의 시설 조회", + "operationId" : "getFacilitiesByTuitionFee", + "parameters" : [ { + "description" : "최대 등록금 (원)", + "in" : "query", + "name" : "maxFee", + "required" : true, + "schema" : { + "format" : "int32", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "items" : { + "$ref" : "#/components/schemas/CareFacilityInfo" + }, + "type" : "array" + } + } + }, + "description" : "OK" + } + }, + "summary" : "등록금 범위별 시설 조회", + "tags" : [ "육아 시설" ] + } + }, + "/facilities/type/{facilityType}" : { + "get" : { + "description" : "특정 유형의 육아 시설 목록 조회", + "operationId" : "getFacilitiesByType", + "parameters" : [ { + "description" : "시설 유형 (KINDERGARTEN: 유치원, DAYCARE: 어린이집, PLAYGROUP: 놀이방, NURSERY: 보육원, OTHER: 기타)", + "in" : "path", + "name" : "facilityType", + "required" : true, + "schema" : { + "enum" : [ "KINDERGARTEN", "DAYCARE", "PLAYGROUP", "NURSERY", "OTHER" ], + "type" : "string" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "items" : { + "$ref" : "#/components/schemas/CareFacilityInfo" + }, + "type" : "array" + } + } + }, + "description" : "OK" + } + }, + "summary" : "시설 유형별 조회", + "tags" : [ "육아 시설" ] + } + }, + "/facilities/waitlist/me" : { + "get" : { + "description" : "등록한 대기 기록 조회", + "operationId" : "myWaitlists", + "parameters" : [ { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "items" : { + "additionalProperties" : { + "type" : "object" + }, + "type" : "object" + }, + "type" : "array" + } + } + }, + "description" : "OK" + } + }, + "summary" : "내 대기 목록", + "tags" : [ "육아 시설" ] + } + }, + "/facilities/waitlist/{waitlistId}" : { + "patch" : { + "description" : "입소 또는 포기를 남겨 대기 기간을 확정합니다", + "operationId" : "resolve", + "parameters" : [ { + "in" : "path", + "name" : "waitlistId", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "ADMITTED 또는 GAVE_UP", + "in" : "query", + "name" : "status", + "required" : true, + "schema" : { + "type" : "string" + } + }, { + "in" : "query", + "name" : "resolvedAt", + "required" : false, + "schema" : { + "format" : "date", + "type" : "string" + } + }, { + "in" : "query", + "name" : "note", + "required" : false, + "schema" : { + "type" : "string" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "description" : "OK" + } + }, + "summary" : "대기 결과 기록", + "tags" : [ "육아 시설" ] + } + }, + "/facilities/{facilityId}/admission-forecast" : { + "get" : { + "description" : "관측된 정원 변동으로 자리가 날 확률을 추정", + "operationId" : "forecastAdmission", + "parameters" : [ { + "description" : "시설 ID", + "in" : "path", + "name" : "facilityId", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "아이 월령", + "example" : 18, + "in" : "query", + "name" : "childAgeMonths", + "required" : false, + "schema" : { + "format" : "int32", + "type" : "integer" + } + }, { + "description" : "예측 기간(개월)", + "example" : 6, + "in" : "query", + "name" : "horizonMonths", + "required" : false, + "schema" : { + "format" : "int32", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/AdmissionForecastResponse" + } + } + }, + "description" : "OK" + } + }, + "summary" : "입소 가능 시점 예측", + "tags" : [ "육아 시설" ] + } + }, + "/facilities/{facilityId}/bookings" : { + "get" : { + "operationId" : "getFacilityBookings", + "parameters" : [ { + "description" : "시설 ID", + "in" : "path", + "name" : "facilityId", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "items" : { + "$ref" : "#/components/schemas/BookingResponse" + }, + "type" : "array" + } + } + }, + "description" : "OK" + } + }, + "summary" : "시설별 예약 목록 조회", + "tags" : [ "육아 시설" ] + }, + "post" : { + "description" : "특정 육아 시설에 예약 생성", + "operationId" : "createBooking", + "parameters" : [ { + "description" : "시설 ID", + "in" : "path", + "name" : "facilityId", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/CreateBookingRequest" + } + } + }, + "required" : true + }, + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/BookingResponse" + } + } + }, + "description" : "OK" + } + }, + "summary" : "시설 예약 생성", + "tags" : [ "육아 시설" ] + } + }, + "/facilities/{facilityId}/bookings/today" : { + "get" : { + "description" : "특정 시설의 오늘 예약 목록 조회", + "operationId" : "getTodayBookingsByFacility", + "parameters" : [ { + "description" : "시설 ID", + "in" : "path", + "name" : "facilityId", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "items" : { + "$ref" : "#/components/schemas/BookingResponse" + }, + "type" : "array" + } + } + }, + "description" : "OK" + } + }, + "summary" : "시설별 오늘의 예약 조회", + "tags" : [ "육아 시설" ] + } + }, + "/facilities/{facilityId}/popularity" : { + "get" : { + "description" : "충원율 추이로 수요 수준과 변동 분석", + "operationId" : "getPopularity", + "parameters" : [ { + "description" : "시설 ID", + "in" : "path", + "name" : "facilityId", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/FacilityPopularityResponse" + } + } + }, + "description" : "OK" + } + }, + "summary" : "시설 인기도 조회", + "tags" : [ "육아 시설" ] + } + }, + "/facilities/{facilityId}/waitlist" : { + "post" : { + "description" : "대기 순번과 신청일을 남깁니다", + "operationId" : "register", + "parameters" : [ { + "description" : "시설 ID", + "in" : "path", + "name" : "facilityId", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/WaitlistRequest" + } + } + }, + "required" : true + }, + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "additionalProperties" : { + "type" : "object" + }, + "type" : "object" + } + } + }, + "description" : "OK" + } + }, + "summary" : "대기 신청 기록", + "tags" : [ "육아 시설" ] + } + }, + "/facilities/{facilityId}/waitlist/stats" : { + "get" : { + "description" : "입소한 사람들의 기록 기반", + "operationId" : "stats", + "parameters" : [ { + "in" : "path", + "name" : "facilityId", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/WaitlistStatsResponse" + } + } + }, + "description" : "OK" + } + }, + "summary" : "실제 대기 기간 통계", + "tags" : [ "육아 시설" ] + } + }, + "/facilities/{id}" : { + "get" : { + "description" : "시설 ID로 특정 육아 시설의 상세 정보 조회", + "operationId" : "getFacilityById", + "parameters" : [ { + "description" : "시설 ID", + "in" : "path", + "name" : "id", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/CareFacilityInfo" + } + } + }, + "description" : "OK" + } + }, + "summary" : "시설 상세 조회", + "tags" : [ "육아 시설" ] + } + }, + "/facilities/{id}/rating" : { + "post" : { + "description" : "특정 시설의 평점을 업데이트", + "operationId" : "updateRating", + "parameters" : [ { + "description" : "시설 ID", + "in" : "path", + "name" : "id", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "평점 (0.0 ~ 5.0)", + "in" : "query", + "name" : "rating", + "required" : true, + "schema" : { + "format" : "double", + "type" : "number" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/ApiSuccess" + } + } + }, + "description" : "OK" + } + }, + "summary" : "시설 평점 업데이트", + "tags" : [ "육아 시설" ] + } + }, + "/facilities/{id}/reviews" : { + "get" : { + "operationId" : "getFacilityReviews", + "parameters" : [ { + "in" : "path", + "name" : "id", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "items" : { + "$ref" : "#/components/schemas/ReviewResponse" + }, + "type" : "array" + } + } + }, + "description" : "OK" + } + }, + "summary" : "시설 리뷰 목록 조회", + "tags" : [ "육아 시설" ] + }, + "post" : { + "operationId" : "createReview", + "parameters" : [ { + "in" : "path", + "name" : "id", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/ReviewRequest" + } + } + }, + "required" : true + }, + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/ReviewResponse" + } + } + }, + "description" : "OK" + } + }, + "summary" : "시설 리뷰 작성", + "tags" : [ "육아 시설" ] + } + }, + "/facilities/{id}/view" : { + "post" : { + "description" : "특정 시설의 조회수를 증가시킵니다", + "operationId" : "incrementViewCount_1", + "parameters" : [ { + "description" : "시설 ID", + "in" : "path", + "name" : "id", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/ApiSuccess" + } + } + }, + "description" : "OK" + } + }, + "summary" : "시설 조회수 증가", + "tags" : [ "육아 시설" ] + } + }, + "/facilities/{id}/with-reviews" : { + "get" : { + "description" : "리뷰 정보를 포함한 시설 상세 정보 조회", + "operationId" : "getFacilityWithReviews", + "parameters" : [ { + "description" : "시설 ID", + "in" : "path", + "name" : "id", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/CareFacilityInfo" + } + } + }, + "description" : "OK" + } + }, + "summary" : "시설 상세 조회 (리뷰 포함)", + "tags" : [ "육아 시설" ] + } + }, + "/health/alerts" : { + "get" : { + "description" : "사용자의 건강 관련 알림 조회", + "operationId" : "getHealthAlerts", + "parameters" : [ { + "description" : "사용자 ID", + "in" : "query", + "name" : "userId", + "required" : true, + "schema" : { + "type" : "string" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "items" : { + "$ref" : "#/components/schemas/HealthAlertResponse" + }, + "type" : "array" + } + } + }, + "description" : "조회 성공" + }, + "401" : { + "content" : { + "application/json" : { + "schema" : { + "items" : { + "$ref" : "#/components/schemas/HealthAlertResponse" + }, + "type" : "array" + } + } + }, + "description" : "인증 필요" + }, + "500" : { + "content" : { + "application/json" : { + "schema" : { + "items" : { + "$ref" : "#/components/schemas/HealthAlertResponse" + }, + "type" : "array" + } + } + }, + "description" : "서버 오류" + } + }, + "summary" : "건강 알림 조회", + "tags" : [ "건강 관리" ] + } + }, + "/health/checkups/schedule" : { + "get" : { + "operationId" : "getCheckupSchedule", + "parameters" : [ { + "description" : "아동 ID", + "in" : "query", + "name" : "childId", + "required" : true, + "schema" : { + "type" : "string" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "items" : { + "$ref" : "#/components/schemas/CheckupScheduleResponse" + }, + "type" : "array" + } + } + }, + "description" : "OK" + } + }, + "summary" : "건강 검진 스케줄 조회", + "tags" : [ "건강 관리" ] + } + }, + "/health/children/age-range" : { + "get" : { + "description" : "특정 연령 범위에 해당하는 자녀 조회", + "operationId" : "getChildrenByAgeRange", + "parameters" : [ { + "description" : "사용자 ID", + "in" : "query", + "name" : "userId", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "최소 연령", + "in" : "query", + "name" : "minAge", + "required" : true, + "schema" : { + "format" : "int32", + "type" : "integer" + } + }, { + "description" : "최대 연령", + "in" : "query", + "name" : "maxAge", + "required" : true, + "schema" : { + "format" : "int32", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "items" : { + "$ref" : "#/components/schemas/ChildInfoResponse" + }, + "type" : "array" + } + } + }, + "description" : "OK" + } + }, + "summary" : "연령 범위별 자녀 조회", + "tags" : [ "건강 관리" ] + } + }, + "/health/children/gender" : { + "get" : { + "description" : "특정 성별의 자녀 조회", + "operationId" : "getChildrenByGender", + "parameters" : [ { + "description" : "사용자 ID", + "in" : "query", + "name" : "userId", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "성별 (MALE, FEMALE)", + "in" : "query", + "name" : "gender", + "required" : true, + "schema" : { + "type" : "string" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "items" : { + "$ref" : "#/components/schemas/ChildInfoResponse" + }, + "type" : "array" + } + } + }, + "description" : "OK" + } + }, + "summary" : "성별 자녀 조회", + "tags" : [ "건강 관리" ] + } + }, + "/health/children/search" : { + "get" : { + "operationId" : "searchChildrenByName", + "parameters" : [ { + "description" : "사용자 ID", + "in" : "query", + "name" : "userId", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "검색할 이름", + "in" : "query", + "name" : "name", + "required" : true, + "schema" : { + "type" : "string" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "items" : { + "$ref" : "#/components/schemas/ChildInfoResponse" + }, + "type" : "array" + } + } + }, + "description" : "OK" + } + }, + "summary" : "이름으로 자녀 검색", + "tags" : [ "건강 관리" ] + } + }, + "/health/children/special-needs" : { + "get" : { + "operationId" : "getChildrenWithSpecialNeeds", + "parameters" : [ { + "description" : "사용자 ID", + "in" : "query", + "name" : "userId", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "items" : { + "$ref" : "#/components/schemas/ChildInfoResponse" + }, + "type" : "array" + } + } + }, + "description" : "OK" + } + }, + "summary" : "특별한 요구사항이 있는 자녀 조회", + "tags" : [ "건강 관리" ] + } + }, + "/health/hospitals" : { + "get" : { + "description" : "등록된 모든 병원 정보 조회", + "operationId" : "getAllHospitals", + "parameters" : [ { + "description" : "페이지 번호 (0부터)", + "in" : "query", + "name" : "page", + "required" : false, + "schema" : { + "format" : "int32", + "type" : "integer" + } + }, { + "description" : "페이지 크기 (최대 200)", + "in" : "query", + "name" : "size", + "required" : false, + "schema" : { + "format" : "int32", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "items" : { + "$ref" : "#/components/schemas/HospitalInfoResponse" + }, + "type" : "array" + } + } + }, + "description" : "OK" + } + }, + "summary" : "모든 병원 조회", + "tags" : [ "건강 관리" ] + } + }, + "/health/hospitals/likes" : { + "get" : { + "description" : "로그인한 사용자가 찜해 둔 병원 목록", + "operationId" : "getLikedHospitals", + "parameters" : [ { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "items" : { + "$ref" : "#/components/schemas/HospitalInfoResponse" + }, + "type" : "array" + } + } + }, + "description" : "OK" + } + }, + "summary" : "찜한 병원 목록 조회", + "tags" : [ "건강 관리" ] + } + }, + "/health/hospitals/nearby" : { + "get" : { + "description" : "위치 기반으로 근처 병원 조회", + "operationId" : "getNearbyHospitals", + "parameters" : [ { + "description" : "위도", + "in" : "query", + "name" : "lat", + "required" : true, + "schema" : { + "format" : "double", + "type" : "number" + } + }, { + "description" : "경도", + "in" : "query", + "name" : "lng", + "required" : true, + "schema" : { + "format" : "double", + "type" : "number" + } + }, { + "description" : "반경(km)", + "in" : "query", + "name" : "radius", + "required" : true, + "schema" : { + "format" : "double", + "type" : "number" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "items" : { + "$ref" : "#/components/schemas/HospitalInfoResponse" + }, + "type" : "array" + } + } + }, + "description" : "OK" + } + }, + "summary" : "근처 병원 조회", + "tags" : [ "건강 관리" ] + } + }, + "/health/hospitals/popular" : { + "get" : { + "description" : "좋아요가 많은 인기 병원들 조회", + "operationId" : "getPopularHospitals", + "parameters" : [ { + "description" : "조회할 개수", + "in" : "query", + "name" : "limit", + "required" : false, + "schema" : { + "default" : 10, + "format" : "int32", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "items" : { + "$ref" : "#/components/schemas/HospitalInfoResponse" + }, + "type" : "array" + } + } + }, + "description" : "OK" + } + }, + "summary" : "인기 병원 조회", + "tags" : [ "건강 관리" ] + } + }, + "/health/hospitals/reviews/{reviewId}" : { + "delete" : { + "operationId" : "deleteHospitalReview", + "parameters" : [ { + "description" : "리뷰 ID", + "in" : "path", + "name" : "reviewId", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "(사용하지 않음) 대상은 인증 주체로 결정됩니다", + "in" : "query", + "name" : "userId", + "required" : false, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "description" : "OK" + } + }, + "summary" : "병원 리뷰 삭제", + "tags" : [ "건강 관리" ] + }, + "put" : { + "operationId" : "updateHospitalReview", + "parameters" : [ { + "description" : "리뷰 ID", + "in" : "path", + "name" : "reviewId", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "(사용하지 않음) 대상은 인증 주체로 결정됩니다", + "in" : "query", + "name" : "userId", + "required" : false, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/HealthUpdateHospitalReviewRequest" + } + } + }, + "required" : true + }, + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/HospitalReviewResponse" + } + } + }, + "description" : "OK" + } + }, + "summary" : "병원 리뷰 수정", + "tags" : [ "건강 관리" ] + } + }, + "/health/hospitals/statistics" : { + "get" : { + "description" : "전체 병원 수와 진료과목별 병원 수", + "operationId" : "getHospitalStatistics", + "parameters" : [ { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/HospitalStatsResponse" + } + } + }, + "description" : "OK" + } + }, + "summary" : "병원 수집 현황", + "tags" : [ "건강 관리" ] + } + }, + "/health/hospitals/type/{type}" : { + "get" : { + "description" : "특정 타입의 병원들 조회", + "operationId" : "getHospitalsByType", + "parameters" : [ { + "description" : "병원 타입", + "in" : "path", + "name" : "type", + "required" : true, + "schema" : { + "type" : "string" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "items" : { + "$ref" : "#/components/schemas/HospitalInfoResponse" + }, + "type" : "array" + } + } + }, + "description" : "OK" + } + }, + "summary" : "병원 타입별 조회", + "tags" : [ "건강 관리" ] + } + }, + "/health/hospitals/{id}" : { + "get" : { + "description" : "특정 병원의 상세 정보 조회", + "operationId" : "getHospitalById", + "parameters" : [ { + "description" : "병원 ID", + "in" : "path", + "name" : "id", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/HospitalInfoResponse" + } + } + }, + "description" : "OK" + } + }, + "summary" : "병원 상세 조회", + "tags" : [ "건강 관리" ] + } + }, + "/health/hospitals/{id}/like" : { + "delete" : { + "description" : "병원의 좋아요를 취소", + "operationId" : "unlikeHospital", + "parameters" : [ { + "description" : "병원 ID", + "in" : "path", + "name" : "id", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "(사용하지 않음) 대상은 인증 주체로 결정됩니다", + "in" : "query", + "name" : "userId", + "required" : false, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "type" : "object" + } + } + }, + "description" : "OK" + } + }, + "summary" : "병원 좋아요 취소", + "tags" : [ "건강 관리" ] + }, + "post" : { + "description" : "병원에 좋아요 추가", + "operationId" : "likeHospital", + "parameters" : [ { + "description" : "병원 ID", + "in" : "path", + "name" : "id", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "(사용하지 않음) 대상은 인증 주체로 결정됩니다", + "in" : "query", + "name" : "userId", + "required" : false, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "type" : "object" + } + } + }, + "description" : "OK" + } + }, + "summary" : "병원 좋아요", + "tags" : [ "건강 관리" ] + } + }, + "/health/hospitals/{id}/like-status" : { + "get" : { + "description" : "찜 여부와 총 개수를 함께 반환", + "operationId" : "getHospitalLikeStatus", + "parameters" : [ { + "description" : "병원 ID", + "in" : "path", + "name" : "id", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/HospitalLikeStatusResponse" + } + } + }, + "description" : "OK" + } + }, + "summary" : "병원 좋아요 상태 조회", + "tags" : [ "건강 관리" ] + } + }, + "/health/hospitals/{id}/likes" : { + "get" : { + "operationId" : "getHospitalLikeCount", + "parameters" : [ { + "description" : "병원 ID", + "in" : "path", + "name" : "id", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "format" : "int64", + "type" : "integer" + } + } + }, + "description" : "OK" + } + }, + "summary" : "병원 좋아요 수 조회", + "tags" : [ "건강 관리" ] + } + }, + "/health/hospitals/{id}/reviews" : { + "get" : { + "description" : "특정 병원의 모든 리뷰 조회", + "operationId" : "getHospitalReviews", + "parameters" : [ { + "description" : "병원 ID", + "in" : "path", + "name" : "id", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "items" : { + "$ref" : "#/components/schemas/HospitalReviewResponse" + }, + "type" : "array" + } + } + }, + "description" : "OK" + } + }, + "summary" : "병원 리뷰 조회", + "tags" : [ "건강 관리" ] + }, + "post" : { + "description" : "병원에 리뷰를 작성", + "operationId" : "createHospitalReview", + "parameters" : [ { + "description" : "병원 ID", + "in" : "path", + "name" : "id", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "(사용하지 않음) 대상은 인증 주체로 결정됩니다", + "in" : "query", + "name" : "userId", + "required" : false, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/HealthCreateHospitalReviewRequest" + } + } + }, + "required" : true + }, + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/HospitalReviewResponse" + } + } + }, + "description" : "OK" + } + }, + "summary" : "병원 리뷰 작성", + "tags" : [ "건강 관리" ] + } + }, + "/health/recommendations" : { + "get" : { + "description" : "아동 연령 기반 정책/시설 연계 추천 제공", + "operationId" : "getIntegratedRecommendations", + "parameters" : [ { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "additionalProperties" : { + "type" : "object" + }, + "type" : "object" + } + } + }, + "description" : "OK" + } + }, + "summary" : "연계 추천 조회", + "tags" : [ "건강 관리" ] + } + }, + "/health/records" : { + "post" : { + "operationId" : "createHealthRecord", + "parameters" : [ { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/HealthCreateHealthRecordRequest" + } + } + }, + "required" : true + }, + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/HealthRecordResponse" + } + } + }, + "description" : "OK" + } + }, + "summary" : "건강 정보 등록", + "tags" : [ "건강 관리" ] + } + }, + "/health/records/attachments/{attachmentId}" : { + "delete" : { + "description" : "건강 기록 첨부파일을 비활성화", + "operationId" : "deleteAttachment", + "parameters" : [ { + "in" : "path", + "name" : "attachmentId", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/ApiSuccess" + } + } + }, + "description" : "OK" + } + }, + "summary" : "건강 기록 첨부 삭제", + "tags" : [ "건강 관리" ] + } + }, + "/health/records/date-range-asc" : { + "get" : { + "description" : "특정 기간의 건강 기록을 오래된순으로 조회", + "operationId" : "getHealthRecordsByDateRangeAsc", + "parameters" : [ { + "description" : "아동 ID", + "in" : "query", + "name" : "childId", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "시작일 (yyyy-MM-dd)", + "in" : "query", + "name" : "startDate", + "required" : true, + "schema" : { + "type" : "string" + } + }, { + "description" : "종료일 (yyyy-MM-dd)", + "in" : "query", + "name" : "endDate", + "required" : true, + "schema" : { + "type" : "string" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "items" : { + "$ref" : "#/components/schemas/HealthRecordResponse" + }, + "type" : "array" + } + } + }, + "description" : "OK" + } + }, + "summary" : "기간별 건강 기록 조회 (오래된순)", + "tags" : [ "건강 관리" ] + } + }, + "/health/records/type" : { + "get" : { + "operationId" : "getHealthRecordsByType", + "parameters" : [ { + "description" : "아동 ID", + "in" : "query", + "name" : "childId", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "기록 타입 (VACCINATION, CHECKUP, MEDICATION, SYMPTOM, OTHER)", + "in" : "query", + "name" : "recordType", + "required" : true, + "schema" : { + "type" : "string" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "items" : { + "$ref" : "#/components/schemas/HealthRecordResponse" + }, + "type" : "array" + } + } + }, + "description" : "OK" + } + }, + "summary" : "타입별 건강 기록 조회", + "tags" : [ "건강 관리" ] + } + }, + "/health/records/user/{userId}" : { + "get" : { + "description" : "특정 사용자의 모든 건강 정보 조회", + "operationId" : "getUserHealthRecords", + "parameters" : [ { + "description" : "사용자 ID", + "in" : "path", + "name" : "userId", + "required" : true, + "schema" : { + "type" : "string" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "items" : { + "$ref" : "#/components/schemas/HealthRecordResponse" + }, + "type" : "array" + } + } + }, + "description" : "OK" + } + }, + "summary" : "사용자별 건강 정보 조회", + "tags" : [ "건강 관리" ] + } + }, + "/health/records/{recordId}" : { + "delete" : { + "operationId" : "deleteHealthRecord", + "parameters" : [ { + "description" : "건강 정보 ID", + "in" : "path", + "name" : "recordId", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "description" : "OK" + } + }, + "summary" : "건강 정보 삭제", + "tags" : [ "건강 관리" ] + }, + "get" : { + "operationId" : "getHealthRecord", + "parameters" : [ { + "description" : "건강 정보 ID", + "in" : "path", + "name" : "recordId", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/HealthRecordResponse" + } + } + }, + "description" : "OK" + } + }, + "summary" : "건강 정보 조회", + "tags" : [ "건강 관리" ] + }, + "put" : { + "operationId" : "updateHealthRecord", + "parameters" : [ { + "description" : "건강 정보 ID", + "in" : "path", + "name" : "recordId", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/HealthUpdateHealthRecordRequest" + } + } + }, + "required" : true + }, + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/HealthRecordResponse" + } + } + }, + "description" : "OK" + } + }, + "summary" : "건강 정보 수정", + "tags" : [ "건강 관리" ] + } + }, + "/health/records/{recordId}/attachments" : { + "get" : { + "description" : "건강 기록의 첨부파일 목록 조회", + "operationId" : "getAttachments", + "parameters" : [ { + "in" : "path", + "name" : "recordId", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "items" : { + "$ref" : "#/components/schemas/HealthRecordAttachmentResponse" + }, + "type" : "array" + } + } + }, + "description" : "OK" + } + }, + "summary" : "건강 기록 첨부 조회", + "tags" : [ "건강 관리" ] + }, + "post" : { + "description" : "건강 기록에 첨부파일 메타 정보 추가", + "operationId" : "addAttachment", + "parameters" : [ { + "in" : "path", + "name" : "recordId", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/HealthRecordAttachmentRequest" + } + } + }, + "required" : true + }, + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/HealthRecordAttachmentResponse" + } + } + }, + "description" : "OK" + } + }, + "summary" : "건강 기록 첨부 추가", + "tags" : [ "건강 관리" ] + } + }, + "/health/records/{recordId}/attachments/upload" : { + "post" : { + "description" : "이미지 또는 PDF 를 업로드하고 건강기록에 연결합니다", + "operationId" : "upload", + "parameters" : [ { + "in" : "path", + "name" : "recordId", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "설명", + "in" : "query", + "name" : "description", + "required" : false, + "schema" : { + "type" : "string" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "requestBody" : { + "content" : { + "multipart/form-data" : { + "schema" : { + "properties" : { + "file" : { + "description" : "업로드할 파일", + "format" : "binary", + "type" : "string" + } + }, + "required" : [ "file" ], + "type" : "object" + } + } + } + }, + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/AttachmentResponse" + } + } + }, + "description" : "OK" + } + }, + "summary" : "첨부파일 업로드", + "tags" : [ "건강기록 첨부 업로드" ] + } + }, + "/health/records/{recordId}/attachments/{attachmentId}/download" : { + "get" : { + "description" : "본인 건강기록의 첨부파일만 받을 수 있습니다", + "operationId" : "download", + "parameters" : [ { + "in" : "path", + "name" : "recordId", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "첨부파일 ID", + "in" : "path", + "name" : "attachmentId", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "format" : "binary", + "type" : "string" + } + } + }, + "description" : "OK" + } + }, + "summary" : "첨부파일 내려받기", + "tags" : [ "건강기록 첨부 업로드" ] + } + }, + "/health/statistics" : { + "get" : { + "description" : "사용자의 건강 관련 통계 조회", + "operationId" : "getHealthStatistics", + "parameters" : [ { + "description" : "사용자 ID", + "in" : "query", + "name" : "userId", + "required" : true, + "schema" : { + "type" : "string" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/HealthStatsResponse" + } + } + }, + "description" : "OK" + } + }, + "summary" : "건강 통계 조회", + "tags" : [ "건강 관리" ] + } + }, + "/health/vaccines/schedule" : { + "get" : { + "operationId" : "getVaccineSchedule", + "parameters" : [ { + "description" : "아동 ID", + "in" : "query", + "name" : "childId", + "required" : true, + "schema" : { + "type" : "string" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "items" : { + "$ref" : "#/components/schemas/VaccineScheduleResponse" + }, + "type" : "array" + } + } + }, + "description" : "OK" + } + }, + "summary" : "예방접종 스케줄 조회", + "tags" : [ "건강 관리" ] + } + }, + "/legal/privacy-policy" : { + "get" : { + "description" : "동의 화면에 표시할 원문", + "operationId" : "privacyPolicy", + "parameters" : [ { + "description" : "버전 (미지정 시 현재 시행본)", + "in" : "query", + "name" : "version", + "required" : false, + "schema" : { + "type" : "string" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "text/markdown;charset=UTF-8" : { + "schema" : { + "type" : "string" + } + } + }, + "description" : "OK" + } + }, + "summary" : "개인정보 처리방침", + "tags" : [ "약관·방침" ] + } + }, + "/legal/terms" : { + "get" : { + "description" : "동의 화면에 표시할 원문", + "operationId" : "terms", + "parameters" : [ { + "in" : "query", + "name" : "version", + "required" : false, + "schema" : { + "type" : "string" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "text/markdown;charset=UTF-8" : { + "schema" : { + "type" : "string" + } + } + }, + "description" : "OK" + } + }, + "summary" : "서비스 이용약관", + "tags" : [ "약관·방침" ] + } + }, + "/legal/version" : { + "get" : { + "description" : "동의 이력에 기록할 버전", + "operationId" : "currentVersion", + "parameters" : [ { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "additionalProperties" : { + "type" : "string" + }, + "type" : "object" + } + } + }, + "description" : "OK" + } + }, + "summary" : "현재 시행 버전", + "tags" : [ "약관·방침" ] + } + }, + "/notifications" : { + "get" : { + "operationId" : "getAllNotifications", + "parameters" : [ { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "items" : { + "$ref" : "#/components/schemas/NotificationInfoResponse" + }, + "type" : "array" + } + } + }, + "description" : "OK" + } + }, + "summary" : "알림 목록 조회", + "tags" : [ "알림 관리" ] + }, + "post" : { + "description" : "새로운 알림 생성", + "operationId" : "createNotification", + "parameters" : [ { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/NotificationCreateRequest" + } + } + }, + "required" : true + }, + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/NotificationInfoResponse" + } + } + }, + "description" : "OK" + } + }, + "summary" : "알림 생성", + "tags" : [ "알림 관리" ] + } + }, + "/notifications/channels" : { + "get" : { + "description" : "각 채널을 이 사용자에게 지금 실제로 발송할 수 있는지와, 불가능하면 그 이유", + "operationId" : "getNotificationChannels", + "parameters" : [ { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "items" : { + "$ref" : "#/components/schemas/NotificationChannelStatusResponse" + }, + "type" : "array" + } + } + }, + "description" : "OK" + } + }, + "summary" : "알림 채널 상태 조회", + "tags" : [ "알림 관리" ] + } + }, + "/notifications/count" : { + "get" : { + "operationId" : "getTotalNotificationCount", + "parameters" : [ { + "description" : "사용자 ID", + "in" : "query", + "name" : "userId", + "required" : true, + "schema" : { + "type" : "string" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "additionalProperties" : { + "format" : "int64", + "type" : "integer" + }, + "type" : "object" + } + } + }, + "description" : "OK" + } + }, + "summary" : "전체 알림 개수 조회", + "tags" : [ "알림 관리" ] + } + }, + "/notifications/count-by-status" : { + "get" : { + "operationId" : "getNotificationCountByReadStatus", + "parameters" : [ { + "description" : "사용자 ID", + "in" : "query", + "name" : "userId", + "required" : true, + "schema" : { + "type" : "string" + } + }, { + "description" : "읽음 여부 (true: 읽음, false: 읽지 않음)", + "in" : "query", + "name" : "isRead", + "required" : true, + "schema" : { + "type" : "boolean" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "additionalProperties" : { + "format" : "int64", + "type" : "integer" + }, + "type" : "object" + } + } + }, + "description" : "OK" + } + }, + "summary" : "읽음 상태별 알림 개수 조회", + "tags" : [ "알림 관리" ] + } + }, + "/notifications/date-range" : { + "get" : { + "description" : "특정 기간의 알림 조회", + "operationId" : "getNotificationsByDateRange", + "parameters" : [ { + "description" : "사용자 ID", + "in" : "query", + "name" : "userId", + "required" : true, + "schema" : { + "type" : "string" + } + }, { + "description" : "시작일시 (yyyy-MM-ddTHH:mm:ss)", + "in" : "query", + "name" : "startDate", + "required" : true, + "schema" : { + "type" : "string" + } + }, { + "description" : "종료일시 (yyyy-MM-ddTHH:mm:ss)", + "in" : "query", + "name" : "endDate", + "required" : true, + "schema" : { + "type" : "string" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "items" : { + "$ref" : "#/components/schemas/NotificationInfoResponse" + }, + "type" : "array" + } + } + }, + "description" : "OK" + } + }, + "summary" : "기간별 알림 조회", + "tags" : [ "알림 관리" ] + } + }, + "/notifications/delivery-status/{notificationId}" : { + "get" : { + "operationId" : "getDeliveryStatus", + "parameters" : [ { + "description" : "알림 ID", + "in" : "path", + "name" : "notificationId", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/NotificationDeliveryStatusResponse" + } + } + }, + "description" : "OK" + } + }, + "summary" : "알림 전송 상태 조회", + "tags" : [ "알림 관리" ] + } + }, + "/notifications/mark-read" : { + "put" : { + "description" : "알림을 읽음으로 표시", + "operationId" : "markAsRead_1", + "parameters" : [ { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/NotificationMarkAsReadRequest" + } + } + }, + "required" : true + }, + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/ApiSuccess" + } + } + }, + "description" : "OK" + } + }, + "summary" : "알림 읽음 처리", + "tags" : [ "알림 관리" ] + } + }, + "/notifications/preferences" : { + "get" : { + "operationId" : "getNotificationPreferences", + "parameters" : [ { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "items" : { + "$ref" : "#/components/schemas/NotificationSettingsResponse" + }, + "type" : "array" + } + } + }, + "description" : "OK" + } + }, + "summary" : "알림 설정 목록 조회", + "tags" : [ "알림 관리" ] + }, + "post" : { + "description" : "사용자의 알림 설정을 저장", + "operationId" : "saveNotificationPreference", + "parameters" : [ { + "description" : "사용자 ID", + "in" : "query", + "name" : "userId", + "required" : true, + "schema" : { + "type" : "string" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/NotificationSettingsResponse" + } + } + }, + "required" : true + }, + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/NotificationSettingsResponse" + } + } + }, + "description" : "OK" + } + }, + "summary" : "알림 설정 저장", + "tags" : [ "알림 관리" ] + }, + "put" : { + "description" : "사용자의 모든 알림 설정을 한 번에 업데이트", + "operationId" : "updateNotificationPreferences", + "parameters" : [ { + "description" : "사용자 ID", + "in" : "query", + "name" : "userId", + "required" : true, + "schema" : { + "type" : "string" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/NotificationSettingsResponse" + } + } + }, + "required" : true + }, + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/NotificationSettingsResponse" + } + } + }, + "description" : "OK" + } + }, + "summary" : "전체 알림 설정 업데이트", + "tags" : [ "알림 관리" ] + } + }, + "/notifications/preferences/disable-all" : { + "put" : { + "operationId" : "disableAllNotifications", + "parameters" : [ { + "description" : "사용자 ID", + "in" : "query", + "name" : "userId", + "required" : true, + "schema" : { + "type" : "string" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/ApiSuccess" + } + } + }, + "description" : "OK" + } + }, + "summary" : "모든 알림 설정 비활성화", + "tags" : [ "알림 관리" ] + } + }, + "/notifications/preferences/reset" : { + "put" : { + "description" : "사용자의 알림 설정을 기본값으로 초기화", + "operationId" : "resetNotificationPreferences", + "parameters" : [ { + "description" : "사용자 ID", + "in" : "query", + "name" : "userId", + "required" : true, + "schema" : { + "type" : "string" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/ApiSuccess" + } + } + }, + "description" : "OK" + } + }, + "summary" : "알림 설정 초기화", + "tags" : [ "알림 관리" ] + } + }, + "/notifications/preferences/{notificationType}" : { + "get" : { + "operationId" : "getNotificationPreferenceByType", + "parameters" : [ { + "description" : "사용자 ID", + "in" : "query", + "name" : "userId", + "required" : true, + "schema" : { + "type" : "string" + } + }, { + "description" : "알림 타입", + "in" : "path", + "name" : "notificationType", + "required" : true, + "schema" : { + "type" : "string" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/NotificationSettingsResponse" + } + } + }, + "description" : "OK" + } + }, + "summary" : "특정 알림 타입 설정 조회", + "tags" : [ "알림 관리" ] + } + }, + "/notifications/preferences/{notificationType}/channels/{channel}" : { + "put" : { + "description" : "사용자의 특정 알림 타입의 채널별 설정을 업데이트", + "operationId" : "updateChannelPreference", + "parameters" : [ { + "description" : "사용자 ID", + "in" : "query", + "name" : "userId", + "required" : true, + "schema" : { + "type" : "string" + } + }, { + "description" : "알림 타입", + "in" : "path", + "name" : "notificationType", + "required" : true, + "schema" : { + "type" : "string" + } + }, { + "description" : "채널", + "in" : "path", + "name" : "channel", + "required" : true, + "schema" : { + "type" : "string" + } + }, { + "description" : "활성화 여부", + "in" : "query", + "name" : "enabled", + "required" : true, + "schema" : { + "type" : "boolean" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/NotificationSettingsResponse" + } + } + }, + "description" : "OK" + } + }, + "summary" : "채널별 설정 업데이트", + "tags" : [ "알림 관리" ] + } + }, + "/notifications/push-token" : { + "post" : { + "operationId" : "registerPushToken", + "parameters" : [ { + "description" : "사용자 ID", + "in" : "query", + "name" : "userId", + "required" : true, + "schema" : { + "type" : "string" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/NotificationRegisterPushTokenRequest" + } + } + }, + "required" : true + }, + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/ApiSuccess" + } + } + }, + "description" : "OK" + } + }, + "summary" : "푸시 알림 토큰 등록", + "tags" : [ "알림 관리" ] + } + }, + "/notifications/read-all" : { + "put" : { + "description" : "사용자의 모든 알림을 읽음 상태로 변경", + "operationId" : "markAllAsRead", + "parameters" : [ { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/ApiSuccess" + } + } + }, + "description" : "OK" + } + }, + "summary" : "모든 알림 읽음 처리", + "tags" : [ "알림 관리" ] + } + }, + "/notifications/settings" : { + "put" : { + "operationId" : "updateSettings", + "parameters" : [ { + "description" : "사용자 ID", + "in" : "query", + "name" : "userId", + "required" : true, + "schema" : { + "type" : "string" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/NotificationUpdateSettingsRequest" + } + } + }, + "required" : true + }, + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/ApiSuccess" + } + } + }, + "description" : "OK" + } + }, + "summary" : "알림 설정 수정", + "tags" : [ "알림 관리" ] + } + }, + "/notifications/settings/{userId}" : { + "get" : { + "operationId" : "getNotificationSettings", + "parameters" : [ { + "description" : "사용자 ID", + "in" : "path", + "name" : "userId", + "required" : true, + "schema" : { + "type" : "string" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "additionalProperties" : { + "type" : "object" + }, + "type" : "object" + } + } + }, + "description" : "OK" + } + }, + "summary" : "알림 설정 조회", + "tags" : [ "알림 관리" ] + }, + "put" : { + "description" : "사용자의 알림 설정을 업데이트", + "operationId" : "updateNotificationSettings", + "parameters" : [ { + "description" : "사용자 ID", + "in" : "path", + "name" : "userId", + "required" : true, + "schema" : { + "type" : "string" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "additionalProperties" : { + "type" : "object" + }, + "description" : "알림 설정", + "type" : "object" + } + } + }, + "required" : true + }, + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "additionalProperties" : { + "type" : "object" + }, + "type" : "object" + } + } + }, + "description" : "OK" + } + }, + "summary" : "알림 설정 업데이트", + "tags" : [ "알림 관리" ] + } + }, + "/notifications/statistics/{userId}" : { + "get" : { + "description" : "사용자의 알림 관련 통계 조회", + "operationId" : "getNotificationStatistics", + "parameters" : [ { + "description" : "사용자 ID", + "in" : "path", + "name" : "userId", + "required" : true, + "schema" : { + "type" : "string" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "additionalProperties" : { + "type" : "object" + }, + "type" : "object" + } + } + }, + "description" : "OK" + } + }, + "summary" : "알림 통계 조회", + "tags" : [ "알림 관리" ] + } + }, + "/notifications/stats" : { + "get" : { + "operationId" : "getNotificationStats", + "parameters" : [ { + "description" : "사용자 ID", + "in" : "query", + "name" : "userId", + "required" : true, + "schema" : { + "type" : "string" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/NotificationStatsResponse" + } + } + }, + "description" : "OK" + } + }, + "summary" : "알림 통계 조회", + "tags" : [ "알림 관리" ] + } + }, + "/notifications/stream" : { + "get" : { + "description" : "연결 직후 connected 이벤트, 새 알림마다 notification 이벤트(JSON, id=알림 id)가 온다. 25초마다 heartbeat 주석. 끊기면 다시 연결하고 목록을 새로 불러온다.", + "operationId" : "stream", + "parameters" : [ { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "text/event-stream" : { + "schema" : { + "$ref" : "#/components/schemas/SseEmitter" + } + } + }, + "description" : "OK" + } + }, + "summary" : "알림 실시간 수신 (SSE)", + "tags" : [ "알림 관리" ] + } + }, + "/notifications/templates" : { + "get" : { + "operationId" : "getNotificationTemplates", + "parameters" : [ { + "description" : "알림 타입", + "in" : "query", + "name" : "type", + "required" : false, + "schema" : { + "type" : "string" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "items" : { + "$ref" : "#/components/schemas/NotificationTemplateResponse" + }, + "type" : "array" + } + } + }, + "description" : "OK" + } + }, + "summary" : "알림 템플릿 조회", + "tags" : [ "알림 관리" ] + } + }, + "/notifications/test" : { + "post" : { + "operationId" : "sendTestNotification", + "parameters" : [ { + "description" : "사용자 ID", + "in" : "query", + "name" : "userId", + "required" : true, + "schema" : { + "type" : "string" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/NotificationSendTestRequest" + } + } + }, + "required" : true + }, + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/ApiSuccess" + } + } + }, + "description" : "OK" + } + }, + "summary" : "테스트 알림 발송", + "tags" : [ "알림 관리" ] + } + }, + "/notifications/type" : { + "get" : { + "description" : "특정 타입의 알림 조회", + "operationId" : "getNotificationsByType", + "parameters" : [ { + "description" : "사용자 ID", + "in" : "query", + "name" : "userId", + "required" : true, + "schema" : { + "type" : "string" + } + }, { + "description" : "알림 타입 (SYSTEM, POLICY, FACILITY, COMMUNITY, CHATBOT, HEALTH)", + "in" : "query", + "name" : "notificationType", + "required" : true, + "schema" : { + "type" : "string" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "items" : { + "$ref" : "#/components/schemas/NotificationInfoResponse" + }, + "type" : "array" + } + } + }, + "description" : "OK" + } + }, + "summary" : "알림 타입별 조회", + "tags" : [ "알림 관리" ] + } + }, + "/notifications/unread" : { + "get" : { + "description" : "사용자의 읽지 않은 알림 목록 조회", + "operationId" : "getUnreadNotifications", + "parameters" : [ { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "items" : { + "$ref" : "#/components/schemas/NotificationInfoResponse" + }, + "type" : "array" + } + } + }, + "description" : "OK" + } + }, + "summary" : "읽지 않은 알림 조회", + "tags" : [ "알림 관리" ] + } + }, + "/notifications/{notificationId}" : { + "delete" : { + "operationId" : "deleteNotification", + "parameters" : [ { + "description" : "알림 ID", + "in" : "path", + "name" : "notificationId", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/ApiSuccess" + } + } + }, + "description" : "OK" + } + }, + "summary" : "알림 삭제", + "tags" : [ "알림 관리" ] + }, + "get" : { + "description" : "특정 알림의 상세 정보 조회", + "operationId" : "getNotification", + "parameters" : [ { + "description" : "알림 ID", + "in" : "path", + "name" : "notificationId", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/NotificationInfoResponse" + } + } + }, + "description" : "OK" + } + }, + "summary" : "알림 상세 조회", + "tags" : [ "알림 관리" ] + }, + "put" : { + "operationId" : "updateNotification", + "parameters" : [ { + "description" : "알림 ID", + "in" : "path", + "name" : "notificationId", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/NotificationCreateRequest" + } + } + }, + "required" : true + }, + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/NotificationInfoResponse" + } + } + }, + "description" : "OK" + } + }, + "summary" : "알림 수정", + "tags" : [ "알림 관리" ] + } + }, + "/notifications/{notificationId}/open" : { + "get" : { + "description" : "클릭을 집계한 뒤 해당 화면으로 이동", + "operationId" : "open", + "parameters" : [ { + "description" : "알림 ID", + "in" : "path", + "name" : "notificationId", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "이동할 화면 (policies, facilities 등)", + "in" : "query", + "name" : "target", + "required" : false, + "schema" : { + "type" : "string" + } + }, { + "description" : "대상 식별자", + "in" : "query", + "name" : "targetId", + "required" : false, + "schema" : { + "type" : "string" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "description" : "OK" + } + }, + "summary" : "알림 열기", + "tags" : [ "알림" ] + } + }, + "/notifications/{notificationId}/read" : { + "put" : { + "description" : "알림을 읽음 상태로 변경", + "operationId" : "markAsRead", + "parameters" : [ { + "description" : "알림 ID", + "in" : "path", + "name" : "notificationId", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/ApiSuccess" + } + } + }, + "description" : "OK" + } + }, + "summary" : "알림 읽음 처리", + "tags" : [ "알림 관리" ] + } + }, + "/policies" : { + "get" : { + "description" : "등록된 모든 육아 정책 목록 조회", + "operationId" : "getAllPolicies", + "parameters" : [ { + "description" : "페이지 번호 (0부터)", + "in" : "query", + "name" : "page", + "required" : false, + "schema" : { + "format" : "int32", + "type" : "integer" + } + }, { + "description" : "페이지 크기 (최대 200)", + "in" : "query", + "name" : "size", + "required" : false, + "schema" : { + "format" : "int32", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "items" : { + "$ref" : "#/components/schemas/PolicyDto" + }, + "type" : "array" + } + } + }, + "description" : "OK" + } + }, + "summary" : "전체 정책 목록 조회", + "tags" : [ "육아 정책" ] + } + }, + "/policies/active" : { + "get" : { + "description" : "현재 신청 기간 내에 있는 정책 조회", + "operationId" : "getActivePoliciesByDate", + "parameters" : [ { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "items" : { + "$ref" : "#/components/schemas/PolicyDto" + }, + "type" : "array" + } + } + }, + "description" : "OK" + } + }, + "summary" : "신청 기간이 유효한 정책 조회", + "tags" : [ "육아 정책" ] + } + }, + "/policies/age" : { + "get" : { + "description" : "월령 범위에 해당하는 정책 조회", + "operationId" : "getPoliciesByAgeRange", + "parameters" : [ { + "description" : "최소 월령", + "example" : 0, + "in" : "query", + "name" : "minAge", + "required" : true, + "schema" : { + "format" : "int32", + "type" : "integer" + } + }, { + "description" : "최대 월령", + "example" : 71, + "in" : "query", + "name" : "maxAge", + "required" : true, + "schema" : { + "format" : "int32", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "items" : { + "$ref" : "#/components/schemas/PolicyDto" + }, + "type" : "array" + } + } + }, + "description" : "OK" + } + }, + "summary" : "연령대별 정책 조회", + "tags" : [ "육아 정책" ] + } + }, + "/policies/bookmarks" : { + "get" : { + "description" : "현재 로그인한 사용자의 정책 북마크 목록 조회", + "operationId" : "getBookmarks", + "parameters" : [ { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "items" : { + "$ref" : "#/components/schemas/PolicyBookmarkResponse" + }, + "type" : "array" + } + } + }, + "description" : "OK" + } + }, + "summary" : "정책 북마크 목록", + "tags" : [ "육아 정책" ] + } + }, + "/policies/categories" : { + "get" : { + "operationId" : "getPolicyCategories", + "parameters" : [ { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "items" : { + "type" : "string" + }, + "type" : "array" + } + } + }, + "description" : "OK" + } + }, + "summary" : "정책 카테고리 목록 조회", + "tags" : [ "육아 정책" ] + } + }, + "/policies/category/{category}" : { + "get" : { + "description" : "특정 카테고리의 육아 정책 목록 조회", + "operationId" : "getPoliciesByCategory", + "parameters" : [ { + "description" : "정책 카테고리", + "in" : "path", + "name" : "category", + "required" : true, + "schema" : { + "type" : "string" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "items" : { + "$ref" : "#/components/schemas/PolicyDto" + }, + "type" : "array" + } + } + }, + "description" : "OK" + } + }, + "summary" : "카테고리별 정책 조회", + "tags" : [ "육아 정책" ] + } + }, + "/policies/child-age" : { + "get" : { + "description" : "해당 월령의 아이가 받을 수 있는 정책 조회", + "operationId" : "getPoliciesByChildAge", + "parameters" : [ { + "description" : "아이 월령", + "example" : 24, + "in" : "query", + "name" : "childAge", + "required" : true, + "schema" : { + "format" : "int32", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "items" : { + "$ref" : "#/components/schemas/PolicyDto" + }, + "type" : "array" + } + } + }, + "description" : "OK" + } + }, + "summary" : "아이 연령별 정책 조회", + "tags" : [ "육아 정책" ] + } + }, + "/policies/latest" : { + "get" : { + "description" : "최근 등록된 육아 정책 목록 조회", + "operationId" : "getLatestPolicies", + "parameters" : [ { + "description" : "조회할 정책 수", + "example" : 10, + "in" : "query", + "name" : "limit", + "required" : false, + "schema" : { + "default" : 10, + "format" : "int32", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "items" : { + "$ref" : "#/components/schemas/PolicyDto" + }, + "type" : "array" + } + } + }, + "description" : "OK" + } + }, + "summary" : "최신 정책 조회", + "tags" : [ "육아 정책" ] + } + }, + "/policies/location/{location}" : { + "get" : { + "description" : "특정 지역의 육아 정책 목록 조회", + "operationId" : "getPoliciesByLocation", + "parameters" : [ { + "description" : "지역명", + "in" : "path", + "name" : "location", + "required" : true, + "schema" : { + "type" : "string" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "items" : { + "$ref" : "#/components/schemas/PolicyDto" + }, + "type" : "array" + } + } + }, + "description" : "OK" + } + }, + "summary" : "지역별 정책 조회", + "tags" : [ "육아 정책" ] + } + }, + "/policies/missed-benefits" : { + "get" : { + "description" : "자녀가 대상이었으나 지나간 지원금과 소급 가능 여부 조회", + "operationId" : "getMissedBenefits", + "parameters" : [ { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/MissedBenefitSummaryResponse" + } + } + }, + "description" : "OK" + } + }, + "summary" : "놓친 지원금 조회", + "tags" : [ "육아 정책" ] + } + }, + "/policies/popular" : { + "get" : { + "description" : "인기 있는 육아 정책 목록 조회", + "operationId" : "getPopularPolicies", + "parameters" : [ { + "description" : "조회할 정책 수", + "example" : 10, + "in" : "query", + "name" : "limit", + "required" : false, + "schema" : { + "default" : 10, + "format" : "int32", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "items" : { + "$ref" : "#/components/schemas/PolicyDto" + }, + "type" : "array" + } + } + }, + "description" : "OK" + } + }, + "summary" : "인기 정책 조회", + "tags" : [ "육아 정책" ] + } + }, + "/policies/recommendations" : { + "get" : { + "description" : "자녀 월령과 거주지에 맞는 정책을 추천", + "operationId" : "getRecommendations", + "parameters" : [ { + "description" : "추천 개수", + "example" : 10, + "in" : "query", + "name" : "limit", + "required" : false, + "schema" : { + "default" : 10, + "format" : "int32", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "items" : { + "$ref" : "#/components/schemas/PersonalizedPolicyResponse" + }, + "type" : "array" + } + } + }, + "description" : "OK" + } + }, + "summary" : "맞춤 정책 추천", + "tags" : [ "육아 정책" ] + } + }, + "/policies/regional-comparison" : { + "get" : { + "description" : "지역별 예상 수령액을 계산해 현재 거주지와 비교", + "operationId" : "compareRegionalBenefits", + "parameters" : [ { + "description" : "자녀 ID (미지정 시 최근 등록 자녀)", + "in" : "query", + "name" : "childId", + "required" : false, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "전망 기간(년)", + "example" : 5, + "in" : "query", + "name" : "years", + "required" : false, + "schema" : { + "format" : "int32", + "type" : "integer" + } + }, { + "description" : "상위 노출 지역 수", + "example" : 10, + "in" : "query", + "name" : "limit", + "required" : false, + "schema" : { + "format" : "int32", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/RegionalBenefitComparisonResponse" + } + } + }, + "description" : "OK" + } + }, + "summary" : "거주지별 지원금 비교", + "tags" : [ "육아 정책" ] + } + }, + "/policies/search" : { + "post" : { + "description" : "다양한 조건으로 육아 정책 검색", + "operationId" : "searchPolicies", + "parameters" : [ { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/PolicySearchRequest" + } + } + }, + "required" : true + }, + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/PolicyListResponse" + } + } + }, + "description" : "검색 성공" + }, + "400" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/PolicyListResponse" + } + } + }, + "description" : "잘못된 요청" + }, + "500" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/PolicyListResponse" + } + } + }, + "description" : "서버 오류" + } + }, + "summary" : "정책 검색", + "tags" : [ "육아 정책" ] + } + }, + "/policies/statistics" : { + "get" : { + "description" : "육아 정책 관련 통계 정보 조회", + "operationId" : "getPolicyStatistics", + "parameters" : [ { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/PolicyStatsSimpleResponse" + } + } + }, + "description" : "OK" + } + }, + "summary" : "정책 통계 조회", + "tags" : [ "육아 정책" ] + } + }, + "/policies/{policyId}" : { + "get" : { + "description" : "정책 ID로 특정 육아 정책의 상세 정보 조회", + "operationId" : "getPolicy", + "parameters" : [ { + "description" : "정책 ID", + "in" : "path", + "name" : "policyId", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/PolicyDto" + } + } + }, + "description" : "OK" + } + }, + "summary" : "정책 상세 조회", + "tags" : [ "육아 정책" ] + } + }, + "/policies/{policyId}/amount-reports" : { + "get" : { + "description" : "확정까지 몇 명이 더 필요한지 조회", + "operationId" : "getAmountConsensus", + "parameters" : [ { + "description" : "정책 ID", + "in" : "path", + "name" : "policyId", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/BenefitAmountConsensusResponse" + } + } + }, + "description" : "OK" + } + }, + "summary" : "제보 합의 현황", + "tags" : [ "육아 정책" ] + }, + "post" : { + "description" : "받은 금액을 알려 정보를 함께 채웁니다", + "operationId" : "reportAmount", + "parameters" : [ { + "description" : "정책 ID", + "in" : "path", + "name" : "policyId", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/BenefitAmountReportRequest" + } + } + }, + "required" : true + }, + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/BenefitAmountConsensusResponse" + } + } + }, + "description" : "OK" + } + }, + "summary" : "지원금 실수령액 제보", + "tags" : [ "육아 정책" ] + } + }, + "/policies/{policyId}/apply" : { + "get" : { + "description" : "클릭을 집계한 뒤 신청 페이지로 리다이렉트", + "operationId" : "apply", + "parameters" : [ { + "description" : "정책 ID", + "in" : "path", + "name" : "policyId", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "description" : "OK" + } + }, + "summary" : "지원금 신청 링크 이동", + "tags" : [ "육아 정책" ] + } + }, + "/policies/{policyId}/bookmarks" : { + "delete" : { + "description" : "현재 로그인한 사용자의 정책 북마크 삭제", + "operationId" : "removeBookmark", + "parameters" : [ { + "description" : "정책 ID", + "in" : "path", + "name" : "policyId", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/ApiSuccess" + } + } + }, + "description" : "OK" + } + }, + "summary" : "정책 북마크 삭제", + "tags" : [ "육아 정책" ] + }, + "post" : { + "description" : "현재 로그인한 사용자의 정책 북마크 추가", + "operationId" : "addBookmark", + "parameters" : [ { + "description" : "정책 ID", + "in" : "path", + "name" : "policyId", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/PolicyBookmarkResponse" + } + } + }, + "description" : "OK" + } + }, + "summary" : "정책 북마크 추가", + "tags" : [ "육아 정책" ] + } + }, + "/policies/{policyId}/view" : { + "post" : { + "description" : "특정 정책의 조회수를 증가시킵니다", + "operationId" : "incrementViewCount", + "parameters" : [ { + "description" : "정책 ID", + "in" : "path", + "name" : "policyId", + "required" : true, + "schema" : { + "format" : "int64", + "type" : "integer" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/ApiSuccess" + } + } + }, + "description" : "OK" + } + }, + "summary" : "정책 조회수 증가", + "tags" : [ "육아 정책" ] + } + }, + "/users/me" : { + "delete" : { + "description" : "데이터는 보존되며 필요시 복구 가능", + "operationId" : "deleteMe", + "parameters" : [ { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/ApiSuccess" + } + } + }, + "description" : "OK" + } + }, + "security" : [ { + "Bearer Authentication" : [ ] + } ], + "summary" : "회원 탈퇴 (소프트 삭제)", + "tags" : [ "사용자" ] + }, + "get" : { + "description" : "현재 로그인한 사용자의 프로필 정보 조회", + "operationId" : "getCurrentUserProfile", + "parameters" : [ { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/UserDto" + } + } + }, + "description" : "OK" + } + }, + "security" : [ { + "Bearer Authentication" : [ ] + } ], + "summary" : "내 프로필 조회", + "tags" : [ "사용자" ] + }, + "put" : { + "description" : "이름·연락처·생년월일·성별·주소 등을 수정", + "operationId" : "updateProfile", + "parameters" : [ { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/UserUpdateRequestDto" + } + } + }, + "required" : true + }, + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/UserDto" + } + } + }, + "description" : "OK" + } + }, + "security" : [ { + "Bearer Authentication" : [ ] + } ], + "summary" : "내 프로필 수정", + "tags" : [ "사용자" ] + } + }, + "/users/me/deactivate" : { + "put" : { + "description" : "데이터는 보존되며 관리자를 통해 복구할 수 있습니다", + "operationId" : "deactivateMe", + "parameters" : [ { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/ApiSuccess" + } + } + }, + "description" : "OK" + } + }, + "security" : [ { + "Bearer Authentication" : [ ] + } ], + "summary" : "내 계정 비활성화", + "tags" : [ "사용자" ] + } + }, + "/users/me/location" : { + "put" : { + "description" : "주변 시설 추천에 사용할 현재 위치를 갱신", + "operationId" : "updateMyLocation", + "parameters" : [ { + "description" : "위도", + "in" : "query", + "name" : "latitude", + "required" : true, + "schema" : { + "format" : "double", + "type" : "number" + } + }, { + "description" : "경도", + "in" : "query", + "name" : "longitude", + "required" : true, + "schema" : { + "format" : "double", + "type" : "number" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/UserDto" + } + } + }, + "description" : "OK" + } + }, + "security" : [ { + "Bearer Authentication" : [ ] + } ], + "summary" : "내 위치 갱신", + "tags" : [ "사용자" ] + } + }, + "/users/me/nickname" : { + "patch" : { + "description" : "표시 닉네임을 변경", + "operationId" : "updateNickname_1", + "parameters" : [ { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "additionalProperties" : { + "type" : "string" + }, + "description" : "새로운 닉네임", + "type" : "object" + } + } + }, + "required" : true + }, + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/ApiSuccess" + } + } + }, + "description" : "OK" + } + }, + "security" : [ { + "Bearer Authentication" : [ ] + } ], + "summary" : "닉네임 변경", + "tags" : [ "사용자" ] + } + }, + "/users/me/profile-completion" : { + "get" : { + "description" : "내 프로필의 완성도를 확인", + "operationId" : "checkProfileCompletion_1", + "parameters" : [ { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/UserProfileCompletionResponse" + } + } + }, + "description" : "OK" + } + }, + "security" : [ { + "Bearer Authentication" : [ ] + } ], + "summary" : "프로필 완성도 체크", + "tags" : [ "사용자" ] + } + }, + "/users/me/profile-image" : { + "post" : { + "description" : "이미지 파일을 올리고 저장된 URL 을 돌려준다", + "operationId" : "uploadMyProfileImage", + "parameters" : [ { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "requestBody" : { + "content" : { + "multipart/form-data" : { + "schema" : { + "properties" : { + "file" : { + "description" : "이미지 파일", + "format" : "binary", + "type" : "string" + } + }, + "required" : [ "file" ], + "type" : "object" + } + } + } + }, + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/ProfileImageResponse" + } + } + }, + "description" : "OK" + } + }, + "security" : [ { + "Bearer Authentication" : [ ] + } ], + "summary" : "프로필 이미지 업로드", + "tags" : [ "사용자" ] + }, + "put" : { + "operationId" : "updateMyProfileImage", + "parameters" : [ { + "description" : "프로필 이미지 URL", + "in" : "query", + "name" : "profileImageUrl", + "required" : true, + "schema" : { + "type" : "string" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "description" : "OK" + } + }, + "security" : [ { + "Bearer Authentication" : [ ] + } ], + "summary" : "프로필 이미지 변경", + "tags" : [ "사용자" ] + } + }, + "/users/privacy/account" : { + "delete" : { + "description" : "개인 식별 정보를 익명화하고 계정을 비활성화", + "operationId" : "deleteAccount", + "parameters" : [ { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "description" : "OK" + } + }, + "summary" : "회원 탈퇴", + "tags" : [ "개인정보" ] + } + }, + "/users/privacy/consents" : { + "get" : { + "description" : "항목별 현재 동의 여부와 동의한 약관 버전 반환", + "operationId" : "getConsents", + "parameters" : [ { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/ConsentStatusResponse" + } + } + }, + "description" : "OK" + } + }, + "summary" : "동의 상태 조회", + "tags" : [ "개인정보" ] + }, + "post" : { + "description" : "동의 이력은 덮어쓰지 않고 새 기록으로 남습니다", + "operationId" : "updateConsent", + "parameters" : [ { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/ConsentUpdateRequest" + } + } + }, + "required" : true + }, + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/ConsentStatusResponse" + } + } + }, + "description" : "OK" + } + }, + "summary" : "동의/철회 기록", + "tags" : [ "개인정보" ] + } + }, + "/users/privacy/consents/history" : { + "get" : { + "operationId" : "getConsentHistory", + "parameters" : [ { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "items" : { + "$ref" : "#/components/schemas/ConsentHistoryItem" + }, + "type" : "array" + } + } + }, + "description" : "OK" + } + }, + "summary" : "동의 이력 전체 조회", + "tags" : [ "개인정보" ] + } + }, + "/users/privacy/export" : { + "get" : { + "description" : "개인정보 열람권 행사를 위한 데이터 export", + "operationId" : "exportMyData", + "parameters" : [ { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "additionalProperties" : { + "type" : "object" + }, + "type" : "object" + } + } + }, + "description" : "OK" + } + }, + "summary" : "내 데이터 내려받기", + "tags" : [ "개인정보" ] + } + }, + "/users/profile" : { + "get" : { + "description" : "현재 로그인한 사용자의 프로필 정보 조회", + "operationId" : "getCurrentUserProfile_1", + "parameters" : [ { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/UserDto" + } + } + }, + "description" : "OK" + } + }, + "security" : [ { + "Bearer Authentication" : [ ] + } ], + "summary" : "내 프로필 조회", + "tags" : [ "사용자" ] + }, + "put" : { + "description" : "이름·연락처·생년월일·성별·주소 등을 수정", + "operationId" : "updateProfile_1", + "parameters" : [ { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/UserUpdateRequestDto" + } + } + }, + "required" : true + }, + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/UserDto" + } + } + }, + "description" : "OK" + } + }, + "security" : [ { + "Bearer Authentication" : [ ] + } ], + "summary" : "내 프로필 수정", + "tags" : [ "사용자" ] + } + }, + "/users/profile/completion" : { + "get" : { + "description" : "내 프로필의 완성도를 확인", + "operationId" : "checkProfileCompletion", + "parameters" : [ { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/UserProfileCompletionResponse" + } + } + }, + "description" : "OK" + } + }, + "security" : [ { + "Bearer Authentication" : [ ] + } ], + "summary" : "프로필 완성도 체크", + "tags" : [ "사용자" ] + } + }, + "/users/profile/nickname" : { + "patch" : { + "description" : "표시 닉네임을 변경", + "operationId" : "updateNickname", + "parameters" : [ { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "additionalProperties" : { + "type" : "string" + }, + "description" : "새로운 닉네임", + "type" : "object" + } + } + }, + "required" : true + }, + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/ApiSuccess" + } + } + }, + "description" : "OK" + } + }, + "security" : [ { + "Bearer Authentication" : [ ] + } ], + "summary" : "닉네임 변경", + "tags" : [ "사용자" ] + } + }, + "/users/{userId}" : { + "delete" : { + "description" : "본인만 요청할 수 있습니다", + "operationId" : "deleteUser", + "parameters" : [ { + "description" : "사용자 ID", + "in" : "path", + "name" : "userId", + "required" : true, + "schema" : { + "type" : "string" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/ApiSuccess" + } + } + }, + "description" : "OK" + } + }, + "security" : [ { + "Bearer Authentication" : [ ] + } ], + "summary" : "회원 탈퇴 (구 경로)", + "tags" : [ "사용자" ] + } + }, + "/users/{userId}/deactivate" : { + "put" : { + "description" : "본인만 요청할 수 있습니다", + "operationId" : "deactivateUser", + "parameters" : [ { + "description" : "사용자 ID", + "in" : "path", + "name" : "userId", + "required" : true, + "schema" : { + "type" : "string" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/ApiSuccess" + } + } + }, + "description" : "OK" + } + }, + "security" : [ { + "Bearer Authentication" : [ ] + } ], + "summary" : "계정 비활성화 (구 경로)", + "tags" : [ "사용자" ] + } + }, + "/users/{userId}/location" : { + "put" : { + "description" : "본인만 변경할 수 있습니다. 신규 클라이언트는 /users/me/location 을 사용하세요", + "operationId" : "updateUserLocation", + "parameters" : [ { + "description" : "사용자 ID", + "in" : "path", + "name" : "userId", + "required" : true, + "schema" : { + "type" : "string" + } + }, { + "description" : "위도", + "in" : "query", + "name" : "latitude", + "required" : true, + "schema" : { + "format" : "double", + "type" : "number" + } + }, { + "description" : "경도", + "in" : "query", + "name" : "longitude", + "required" : true, + "schema" : { + "format" : "double", + "type" : "number" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/UserDto" + } + } + }, + "description" : "OK" + } + }, + "security" : [ { + "Bearer Authentication" : [ ] + } ], + "summary" : "위치 갱신 (구 경로)", + "tags" : [ "사용자" ] + } + }, + "/users/{userId}/profile-image" : { + "put" : { + "description" : "본인만 변경할 수 있습니다. 신규 클라이언트는 /users/me/profile-image 를 사용하세요", + "operationId" : "updateProfileImage", + "parameters" : [ { + "description" : "사용자 ID", + "in" : "path", + "name" : "userId", + "required" : true, + "schema" : { + "type" : "string" + } + }, { + "description" : "프로필 이미지 URL", + "in" : "query", + "name" : "profileImageUrl", + "required" : true, + "schema" : { + "type" : "string" + } + }, { + "description" : "API 버전. 생략하면 현재 버전(1). 지원하지 않는 값이면 400", + "in" : "header", + "name" : "X-API-Version", + "required" : false, + "schema" : { + "default" : "1", + "type" : "string" + } + } ], + "responses" : { + "200" : { + "description" : "OK" + } + }, + "security" : [ { + "Bearer Authentication" : [ ] + } ], + "summary" : "프로필 이미지 변경 (구 경로)", + "tags" : [ "사용자" ] + } + } + }, + "security" : [ { + "Bearer Authentication" : [ ] + } ], + "servers" : [ { + "description" : "현재 환경 서버", + "url" : "http://localhost:8082" + } ], + "tags" : [ { + "description" : "동의 이력, 데이터 열람 및 파기 API", + "name" : "개인정보" + }, { + "description" : "통합 건강 관리 API (건강 정보, 병원, 리뷰)", + "name" : "건강 관리" + }, { + "description" : "예방접종 수첩, 진료 기록 사진 등 파일 업로드 API", + "name" : "건강기록 첨부 업로드" + }, { + "description" : "공공데이터 포털 API 호출", + "name" : "공공데이터 API" + }, { + "description" : "공공데이터 포털의 돌봄시설 정보 API", + "name" : "돌봄시설 공공데이터" + }, { + "description" : "본인 계정 관리 API (프로필, 위치, 탈퇴)", + "name" : "사용자" + }, { + "description" : "아이 등록·조회 및 예방접종 일정 API", + "name" : "아이 관리" + }, { + "description" : "알림 API", + "name" : "알림" + }, { + "description" : "육아 관련 알림 관리 API", + "name" : "알림 관리" + }, { + "description" : "이용약관 및 개인정보 처리방침", + "name" : "약관·방침" + }, { + "description" : "공공데이터 연동 전 기능 확인용", + "name" : "어드민 - 개발용 샘플 데이터" + }, { + "description" : "관리자 전용 건강기록 관리 API", + "name" : "어드민 - 건강기록" + }, { + "description" : "공공데이터 수동 동기화 API", + "name" : "어드민 - 공공데이터" + }, { + "description" : "관리자 대시보드 요약 API", + "name" : "어드민 - 대시보드" + }, { + "description" : "관리자 전용 병원 관리 API", + "name" : "어드민 - 병원" + }, { + "description" : "관리자 전용 사용자 관리 API", + "name" : "어드민 - 사용자" + }, { + "description" : "관리자 전용 예약 관리 API", + "name" : "어드민 - 시설 예약" + }, { + "description" : "관리자 전용 커뮤니티 신고 처리 API", + "name" : "어드민 - 신고 처리" + }, { + "description" : "관리자 전용 알림 관리 API", + "name" : "어드민 - 알림" + }, { + "description" : "관리자 전용 정책 관리 API", + "name" : "어드민 - 정책" + }, { + "description" : "지원금 금액 수기 검증", + "name" : "어드민 - 정책 검증" + }, { + "description" : "동기화·알림 작업 실행 상태", + "name" : "어드민 - 주기 작업" + }, { + "description" : "퍼널·리텐션 지표", + "name" : "어드민 - 지표" + }, { + "description" : "관리자 전용 게시글 모더레이션 API", + "name" : "어드민 - 커뮤니티" + }, { + "description" : "육아 시설 관련 API", + "name" : "육아 시설" + }, { + "description" : "육아 시설 정보 및 검색 API", + "name" : "육아 시설" + }, { + "description" : "육아 정책 정보 및 검색 API", + "name" : "육아 정책" + }, { + "description" : "통합 인증 API (일반 로그인, 토큰 갱신)", + "name" : "인증" + }, { + "description" : "육아 관련 챗봇 서비스 API", + "name" : "챗봇" + }, { + "description" : "카카오 OAuth 로그인 및 회원가입 API", + "name" : "카카오 인증" + }, { + "description" : "육아 커뮤니티 게시글 및 댓글 관리 API", + "name" : "커뮤니티" + }, { + "description" : "게시글·댓글 신고 및 사용자 차단 API", + "name" : "커뮤니티 모더레이션" + } ] +} diff --git a/package.json b/package.json index 54bca0f..78e7579 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,8 @@ "test:watch": "vitest", "typecheck": "tsc --noEmit", "prepare": "husky", - "lint:fix": "eslint . --fix" + "lint:fix": "eslint . --fix", + "sync:openapi": "node scripts/sync-openapi.mjs" }, "dependencies": { "@lukemorales/query-key-factory": "^1.3.4", diff --git a/scripts/sync-openapi.mjs b/scripts/sync-openapi.mjs new file mode 100644 index 0000000..131f45e --- /dev/null +++ b/scripts/sync-openapi.mjs @@ -0,0 +1,42 @@ +/** + * 서버가 고정해 둔 OpenAPI 스펙을 가져온다. + * + * 서버 저장소(CareCode_Interface)의 `docs/api/openapi.json` 이 원본이고, 여기서는 사본을 둔다. + * 사본을 두는 이유: 계약 대조 테스트가 네트워크 없이도 돌아야 하고, CI 결과가 서버 저장소의 + * 상태에 따라 흔들리면 안 된다. 사본이 낡는 문제는 매일 도는 `openapi-drift` 워크플로가 잡는다. + * + * npm run sync:openapi # main 에서 가져온다 + * OPENAPI_SRC=../CareCode_Interface/docs/api/openapi.json npm run sync:openapi # 로컬 체크아웃에서 + * OPENAPI_REF=feat/some-branch npm run sync:openapi # 다른 브랜치에서 + */ +import { copyFileSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs' +import { dirname, resolve } from 'node:path' + +const TARGET = resolve('openapi/openapi.json') +const ref = process.env.OPENAPI_REF ?? 'main' +const remote = `https://raw.githubusercontent.com/CareCode-Repo/CareCode_Interface/${ref}/docs/api/openapi.json` + +mkdirSync(dirname(TARGET), { recursive: true }) + +if (process.env.OPENAPI_SRC) { + const source = resolve(process.env.OPENAPI_SRC) + copyFileSync(source, TARGET) + console.log(`로컬 파일에서 스펙을 복사했습니다: ${source}`) +} else { + const response = await fetch(remote) + if (!response.ok) { + console.error(`스펙을 가져오지 못했습니다 (${response.status}): ${remote}`) + process.exit(1) + } + writeFileSync(TARGET, await response.text(), 'utf-8') + console.log(`서버 저장소(${ref})에서 스펙을 가져왔습니다.`) +} + +// 내용이 스펙 모양인지 최소한 확인한다. 404 HTML 을 그대로 저장해 두면 대조가 통째로 무의미해진다. +const spec = JSON.parse(readFileSync(TARGET, 'utf-8')) +const paths = Object.keys(spec.paths ?? {}).length +if (paths < 100) { + console.error(`스펙 경로가 ${paths}개뿐입니다. 파일이 잘못된 것 같아 실패로 처리합니다.`) + process.exit(1) +} +console.log(`경로 ${paths}개, 스키마 ${Object.keys(spec.components?.schemas ?? {}).length}개`) diff --git a/src/apis/__tests__/openapi-contract.test.ts b/src/apis/__tests__/openapi-contract.test.ts new file mode 100644 index 0000000..c52ccb5 --- /dev/null +++ b/src/apis/__tests__/openapi-contract.test.ts @@ -0,0 +1,120 @@ +/** + * 프런트가 부르는 경로가 서버에 실제로 있는지 확인한다. + * + * 서버에서 지운 경로(`/oauth2/kakao/auth-url`)를 프런트가 계속 불러 메인 화면의 카카오 로그인이 + * 아무 반응 없던 일이 있었다. 타입 검사도 린트도 이런 불일치를 잡지 못한다 — 경로는 문자열이기 때문이다. + * + * 그래서 서버가 고정해 둔 OpenAPI 스펙(`openapi/openapi.json`, 서버 저장소 `docs/api/openapi.json`)과 + * `src/apis/*.ts` 의 호출을 대조한다. 스펙 갱신: `npm run sync:openapi` + */ +import { readdirSync, readFileSync } from 'node:fs' +import { join } from 'node:path' +import { describe, expect, it } from 'vitest' + +const API_DIR = join(process.cwd(), 'src/apis') +const SPEC_PATH = join(process.cwd(), 'openapi/openapi.json') + +type Spec = { paths: Record> } +type Call = { method: string; path: string; file: string; raw: string } + +const spec: Spec = JSON.parse(readFileSync(SPEC_PATH, 'utf-8')) + +const PLACEHOLDER = '{}' + +/** + * 경로를 세그먼트로 나눈다. 값이 들어가는 자리는 `{}` 로 둔다. + * + * 프런트의 `${type}` 은 경로 변수일 수도 있고(`${facilityId}`), 리터럴 값의 유니온일 수도 있다 + * (`${'privacy-policy' | 'terms'}`). 어느 쪽인지 문자열만 보고는 알 수 없으므로 한 세그먼트 와일드카드로 본다. + */ +const toSegments = (path: string): string[] => + path + .split('?')[0] + .replace(/\$\{[^}]*\}/g, PLACEHOLDER) + .replace(/\{[^}/]*\}/g, PLACEHOLDER) + .replace(/\/+$/, '') + .split('/') + +const segmentsMatch = (front: string[], server: string[]): boolean => + front.length === server.length && + front.every( + (segment, index) => + segment === server[index] || segment === PLACEHOLDER || server[index] === PLACEHOLDER, + ) + +const serverRoutes: { method: string; segments: string[]; path: string }[] = [] +for (const [path, methods] of Object.entries(spec.paths)) { + for (const method of Object.keys(methods)) { + serverRoutes.push({ method: method.toUpperCase(), segments: toSegments(path), path }) + } +} + +/** `CareCode.get('/facilities')`, `CareCode.post(\`/facilities/${id}/bookings\`, body)` 를 뽑는다. */ +const collectCalls = (): Call[] => { + const calls: Call[] = [] + for (const file of readdirSync(API_DIR).filter((name) => name.endsWith('.ts'))) { + const source = readFileSync(join(API_DIR, file), 'utf-8') + const pattern = /CareCode\.(get|post|put|patch|delete)\s*(?:<[^>]*>)?\(\s*([`'"])([^`'"]+)\2/g + let match: RegExpExecArray | null + while ((match = pattern.exec(source)) !== null) { + calls.push({ + method: match[1].toUpperCase(), + path: match[3], + file, + raw: `${match[1].toUpperCase()} ${match[3]}`, + }) + } + } + return calls +} + +describe('OpenAPI 계약 대조', () => { + it('스펙이 비어 있지 않다 — 빈 파일을 두고 통과하는 사고 방지', () => { + expect(Object.keys(spec.paths).length).toBeGreaterThan(100) + expect( + serverRoutes.some((route) => route.method === 'POST' && route.path === '/auth/login'), + ).toBe(true) + }) + + it('src/apis 에서 호출을 찾아낸다', () => { + expect(collectCalls().length).toBeGreaterThan(100) + }) + + it('프런트가 부르는 모든 경로가 서버 스펙에 있다', () => { + const missing = collectCalls() + .filter((call) => { + const segments = toSegments(call.path) + return !serverRoutes.some( + (route) => route.method === call.method && segmentsMatch(segments, route.segments), + ) + }) + .map((call) => { + // 같은 경로에 다른 메서드만 있는 경우를 알려 주면 원인을 바로 안다. + const segments = toSegments(call.path) + const others = serverRoutes + .filter((route) => segmentsMatch(segments, route.segments)) + .map((route) => route.method) + return `${call.raw} (${call.file})${others.length ? ` — 서버에는 ${[...new Set(others)].join(',')} 만 있음` : ''}` + }) + + expect( + missing, + [ + '서버 스펙에 없는 경로를 부르고 있습니다.', + '서버가 경로를 바꿨다면 프런트를 고치고, 스펙이 낡았다면 `npm run sync:openapi` 로 갱신하세요.', + '', + ...missing, + ].join('\n'), + ).toEqual([]) + }) + + it('지워진 옛 경로를 다시 부르면 잡아낸다 — 이 검사가 실제로 동작하는지 확인', () => { + // 카카오 로그인이 조용히 깨졌던 그 경로. 스펙에 없어야 하고, 대조에서 걸려야 한다. + const removed = toSegments('/oauth2/kakao/auth-url') + expect( + serverRoutes.some( + (route) => route.method === 'GET' && segmentsMatch(removed, route.segments), + ), + ).toBe(false) + }) +})