Repository navigation
update: Production Swagger 공개 전환 및 클라이언트 연동 가이드 추가 #28
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,211 @@ | ||||||
| # Client Integration Guide | ||||||
|
|
||||||
| 클라이언트(게임 앱)가 Fantasy 서버를 통해 무엇을, 어떤 순서로 호출해야 하는지 정리한 문서입니다. | ||||||
| 개별 필드 정의가 아니라 **호출 흐름과 규약**에 초점을 둡니다. 실제 요청/응답 스키마는 서버의 `/swagger`에서 확인할 수 있습니다. | ||||||
|
|
||||||
| ## 1. 기본 규약 | ||||||
|
|
||||||
| | 항목 | 내용 | | ||||||
| |---|---| | ||||||
| | Base 경로 | 모든 엔드포인트는 `/v1` 접두사 사용 | | ||||||
| | 프로토콜 | **HTTP** (배포 환경 포트 제약으로 HTTPS 미사용) | | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @gemini-code-assist[bot] HTTP 사용은 동일 라인의 앞선 코멘트와 같이 학교 포트 제약으로 인지·수용한 의도된 결정입니다. 역방향 프록시/터널을 통한 HTTPS 경로는 추후 별도 검토 예정입니다. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 사용자의 상황과 의도를 충분히 이해했습니다. 학교 환경의 제약으로 인해 현재 단계에서 HTTP를 사용해야 한다는 점, 그리고 향후 역방향 프록시 등을 통해 HTTPS를 적용할 계획이 있다는 점을 명확히 인지했습니다. 보안 권고 사항을 수용해주셔서 감사합니다. |
||||||
| | 인증 | JWT Bearer — 보호 엔드포인트는 `Authorization: Bearer {accessToken}` 헤더 필요 | | ||||||
| | 본문 형식 | `application/json` | | ||||||
| | API 문서 | `/swagger` (현재 무인증 공개) | | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @gemini-code-assist[bot] Swagger 무인증 공개는 클라이언트 연동용 스키마 참조 제공을 위해 이번 PR에서 의도적으로 결정한 정책입니다(HTTP 환경, 리스크 인지·수용). IP 허용목록 등 강화는 추후 별도 검토하겠습니다. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 의견 주셔서 감사합니다. 보안 위험에 대한 인지 및 수용 정책을 확인했습니다. 추후 환경 개선 시 고려해 주시기 바랍니다. |
||||||
| | 헬스 체크 | `GET /v1/health` — 인증 불필요, `{ status, timestamp }` 반환 | | ||||||
|
|
||||||
| ### 응답 래퍼 | ||||||
|
|
||||||
| 모든 응답은 공통 래퍼(`CommonApiResponse`)로 감싸집니다. | ||||||
|
|
||||||
| ```json | ||||||
| { | ||||||
| "status": "...", // 성공/실패 구분 문자열 (SDK가 설정) | ||||||
| "code": 200, // HTTP 상태 코드 | ||||||
| "message": "로그인 성공.", // 사람이 읽는 메시지 | ||||||
| "data": { } // 실제 페이로드 (없으면 null) | ||||||
| } | ||||||
| ``` | ||||||
|
|
||||||
| - 컨트롤러가 DTO를 반환하면 `data`에 그대로 담겨 200으로 래핑됩니다. | ||||||
| - 회원가입처럼 생성 성공은 **201**, 본문 없는 성공은 **204**로 내려갈 수 있습니다. | ||||||
| - 클라이언트는 `data`만 사용하면 되고, `message`는 UI 피드백용으로 활용할 수 있습니다. | ||||||
|
|
||||||
| ### 에러 | ||||||
|
|
||||||
| 서버는 예외를 던지면 동일한 래퍼 형태로 에러를 내려줍니다. 주요 코드: | ||||||
|
|
||||||
| | Code | 의미 | 대표 상황 | | ||||||
| |---|---|---| | ||||||
| | 400 | 잘못된 요청 | 유효성 위반, 티켓 부족, 비정상 클릭 수, 미해금 스킬 장착 등 | | ||||||
| | 401 | 인증 실패 | 로그인 실패, 토큰 만료/무효, 리프레시 토큰 재사용 감지 | | ||||||
| | 403 | 권한 없음 | 타인의 골드 던전 런에 접근 | | ||||||
| | 404 | 없음 | 플레이어/스킬/스테이지 데이터 없음 | | ||||||
| | 409 | 충돌 | 이메일 중복, 다른 직업의 플레이어 존재, 광고 보상 중복 수령 | | ||||||
| | 429 | 요청 과다 | 레이트리밋 초과 (`Too Many Requests` 텍스트) | | ||||||
|
|
||||||
| ### 레이트리밋 | ||||||
|
|
||||||
| | 정책 | 한도 | 기준 | 적용 대상 | | ||||||
| |---|---|---|---| | ||||||
| | `login` | 1분에 5회 | 클라이언트 IP | `POST /v1/auth/login` | | ||||||
| | `game` | 1초에 30회 | 계정 ID(JWT `sub`) | `/v1/player/*`, `/v1/dungeons/*`, 게임 데이터 조회 | | ||||||
|
|
||||||
| 429를 받으면 클라이언트는 재시도 간격을 두어야 합니다. | ||||||
|
|
||||||
| ## 2. 전체 흐름 | ||||||
|
|
||||||
| ``` | ||||||
| [최초] signup → login → player/init(직업 선택) | ||||||
| [재접속] login(또는 refresh) → player/init(기존 데이터 로드) | ||||||
| [플레이] basic/state ↔ basic/claim · loadout · skill/unlock · weapon · boss · gold-runs | ||||||
| [토큰] accessToken 만료 → auth/refresh 로 갱신 | ||||||
| [종료] logout | ||||||
| ``` | ||||||
|
|
||||||
| 핵심 원칙: | ||||||
|
|
||||||
| - **로그인 직후 반드시 `player/init`을 호출**해 플레이어 상태를 확보합니다. (없으면 생성, 있으면 로드 — 멱등) | ||||||
| - 상태를 바꾸는 호출(`loadout`, `skill/unlock`, 던전 정산 등)은 응답에 **최신 `player` 전체 스냅샷**을 포함합니다. 클라이언트는 이를 단일 진실 소스로 삼으면 됩니다. | ||||||
| - 변화량은 `changes`(델타)로 함께 내려오므로 획득 연출에 사용합니다. | ||||||
|
|
||||||
| ## 3. 인증 / 계정 | ||||||
|
|
||||||
| | 메서드 | 경로 | 인증 | 설명 | | ||||||
| |---|---|---|---| | ||||||
| | POST | `/v1/account/signup` | ✗ | 회원가입. `email`(≤50, 이메일형식), `password`(8~20). 이메일 중복 시 409 | | ||||||
| | POST | `/v1/auth/login` | ✗ | 로그인. `email`,`password` → 토큰 발급. 레이트리밋 `login` | | ||||||
| | POST | `/v1/auth/refresh` | ✗ | 토큰 갱신. `refreshToken` → 새 토큰 세트 | | ||||||
| | POST | `/v1/auth/logout` | ✓ | 로그아웃. 서버의 리프레시 토큰 폐기 | | ||||||
| | DELETE | `/v1/account` | ✓ | 계정 삭제. 본문 `password` 재확인. 플레이어 데이터·토큰 모두 제거 | | ||||||
|
|
||||||
| ### 토큰 사용 규칙 | ||||||
|
|
||||||
| 로그인/갱신 응답의 `data`: | ||||||
|
|
||||||
| ```json | ||||||
| { "accessToken": "...", "refreshToken": "...", "accessTokenExpiresAt": 1735660800 } | ||||||
| ``` | ||||||
|
|
||||||
| - `accessToken`: 보호 API 호출 시 `Authorization: Bearer` 헤더에 사용. 기본 수명 **15분**. | ||||||
| - `accessTokenExpiresAt`: Unix epoch(초). 클라이언트는 이 시각 이전에 갱신을 준비합니다. | ||||||
| - `refreshToken`: 수명 **30일**. **회전식(rotating)** 입니다. | ||||||
| - `refresh` 호출 시마다 **새 refreshToken이 발급되고 이전 토큰은 무효화**됩니다. | ||||||
| - 응답으로 받은 새 토큰을 반드시 저장하고 다음 갱신에 사용해야 합니다. | ||||||
| - 이미 사용한(이전) 토큰을 다시 보내면 **재사용 감지로 401** 처리됩니다 → 재로그인 필요. | ||||||
|
Comment on lines
+93
to
+95
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Refresh Token Rotation (RTR) 적용 시 동시성(Race Condition) 고려 리프레시 토큰 회전(RTR) 방식을 사용할 때, 클라이언트(게임 앱)에서 여러 비동기 요청이 동시에 만료되어 각각 이 경우 첫 번째 요청이 성공하여 토큰이 갱신되면, 거의 동시에 도달한 두 번째 요청은 이미 무효화된 이전 토큰을 사용하게 되므로 재사용 감지(401) 로직이 작동하여 사용자가 강제로 로그아웃되는 현상이 발생할 수 있습니다. 개선 제안:
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @gemini-code-assist[bot] RTR 동시 갱신 레이스 컨디션 지적은 타당합니다. 클라이언트 측 갱신 직렬화/큐잉 안내는 곧 진행할 문서 정리에서 함께 검토하고, 서버 측 Grace Period 도입은 별도 서버 변경으로 분리하겠습니다. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 네, 알겠습니다. 클라이언트 측 갱신 직렬화/큐잉 안내는 문서에 반영하고, 서버 측 Grace Period 도입은 별도 서버 변경으로 분리하여 진행하는 방향에 동의합니다. 해당 이슈를 잘 인지하고 계시니, 이후 작업 시 참고하시기 바랍니다. |
||||||
|
|
||||||
| ## 4. 플레이어 | ||||||
|
|
||||||
| 모든 경로 `/v1/player/*` — 인증 필요, 레이트리밋 `game`. | ||||||
|
|
||||||
| | 메서드 | 경로 | 본문 | 설명 | | ||||||
| |---|---|---|---| | ||||||
| | POST | `/v1/player/init` | `{ jobType }` | 플레이어 생성/로드 | | ||||||
| | POST | `/v1/player/loadout` | `{ weaponId?, activeSkills[] }` | 장착 무기·액티브 스킬 저장 | | ||||||
| | POST | `/v1/player/skill/unlock` | `{ skillId }` | 스킬 해금 (SP 소모) | | ||||||
|
|
||||||
| - **init**: 플레이어가 없으면 `jobType`으로 신규 생성(201), 있으면 기존 데이터 로드(200). `jobType`은 **최초 생성 시에만 의미**가 있고, 이미 다른 직업으로 존재하면 **409**. 따라서 재접속 시에도 안전하게 호출 가능합니다. | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 플레이어 로드/생성 흐름 설계 검토 (init API) 설명에 따르면 이 경우, 새로운 기기에서 로그인한 클라이언트는 기존 플레이어의 존재 여부나 직업(JobType)을 알지 못하는 상태에서 개선 제안:
현재 가이드 문서상에 이 흐름에 대한 해결책(예: 409 응답 바디에 기존 플레이어 정보가 포함되는지 등)이 누락되어 있다면 보완이 필요해 보입니다.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @gemini-code-assist[bot] 지적이 타당합니다. player/init의 생성·로드 겸용과 직업 불일치 409 모호함을 해소하기 위해 GET /v1/player(200/404, 로드) + POST /v1/player(201/409, 생성)로 분리하는 재설계를 진행합니다. 별도 스펙/브랜치로 처리합니다. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 제안해주신 |
||||||
| - **loadout**: `weaponId`는 보유 무기여야 하고, `activeSkills`는 **해금된 액티브 스킬**만 허용(패시브·미해금·중복 → 400). 저장과 함께 방치 보상 정산이 함께 일어나 `changes`에 골드/경험치/레벨업이 포함될 수 있습니다. | ||||||
| - **skill/unlock**: 선행 스킬 해금 + SP 충분 + 해당 직업 스킬이어야 함. 이미 해금된 스킬이면 `wasAlreadyUnlocked=true`로 멱등 응답. | ||||||
|
|
||||||
| ## 5. 게임 데이터(레퍼런스) | ||||||
|
|
||||||
| 인증 필요, 레이트리밋 `game`. 정적 테이블이므로 **클라이언트가 1회 조회 후 캐시**하는 것을 권장합니다. | ||||||
|
|
||||||
| | 메서드 | 경로 | 설명 | | ||||||
| |---|---|---| | ||||||
| | GET | `/v1/jobs/{jobType}/skills` | 직업별 스킬 테이블 | | ||||||
| | GET | `/v1/jobs/{jobType}/weapons` | 직업별 무기 테이블 | | ||||||
| | GET | `/v1/levels` | 레벨별 필요 경험치·보상 SP | | ||||||
| | GET | `/v1/stages` | 스테이지별 몬스터 HP·초당 골드/경험치 | | ||||||
|
|
||||||
| > 이 엔드포인트들은 enum 값을 **문자열 이름**(`"Warrior"`, `"C"`, `"AtkPercent"`)으로 반환합니다. | ||||||
|
|
||||||
| ## 6. 던전 | ||||||
|
|
||||||
| 모든 경로 `/v1/dungeons/*` — 인증 필요, 레이트리밋 `game`. | ||||||
|
|
||||||
| ### 6.1 기본(방치) 던전 | ||||||
|
|
||||||
| | 메서드 | 경로 | 설명 | | ||||||
| |---|---|---| | ||||||
| | GET | `/v1/dungeons/basic/state` | 방치 상태 스냅샷 (읽기 전용) | | ||||||
| | POST | `/v1/dungeons/basic/claim` | 방치 보상 정산 | | ||||||
|
|
||||||
| - `state`는 `stage`, `lastCalculatedAt`, `serverNow`, `maxOfflineSeconds`(28800초 = **8시간**), `combatPower`(DPS), `goldPerSecond`, `xpPerSecond`를 반환합니다. | ||||||
| - 클라이언트는 `serverNow`와 `lastCalculatedAt`을 기준으로 누적 보상을 **로컬에서 표시**하고, 실제 지급은 `claim`으로 받습니다. | ||||||
| - `claim`은 경과 시간(최대 8시간으로 캡)만큼 골드/경험치를 지급하고, DPS가 현재 스테이지를 클리어할 수 있으면 `maxStage`를 +1 올린 뒤 `lastCalculatedAt`을 현재로 리셋합니다. 앱 포그라운드 진입 시 호출을 권장합니다. | ||||||
|
|
||||||
| ### 6.2 무기 던전 / 보스 던전 (즉시 전투) | ||||||
|
|
||||||
| | 메서드 | 경로 | 설명 | | ||||||
| |---|---|---| | ||||||
| | POST | `/v1/dungeons/weapon` | 무기 파밍. 클리어(`DPS×30 ≥ 몬스터HP`) 시 확률 드랍 | | ||||||
| | POST | `/v1/dungeons/boss` | 보스 전투. 보스HP = 일반 몬스터HP×5 | | ||||||
|
|
||||||
| - 무기 던전 드랍 확률(클리어 시): B등급 20%, C등급 70%, 강화 스크롤 30%. | ||||||
| - 보스 클리어 시: 미스릴 +1, 경험치 = `스테이지 초당경험치 × 10`, **A등급 무기 확정 드랍**, 레벨업 가능. 미클리어면 보상 없음. | ||||||
|
|
||||||
| ### 6.3 골드 던전 (클릭형, 티켓 소모) | ||||||
|
|
||||||
| | 메서드 | 경로 | 설명 | | ||||||
| |---|---|---| | ||||||
| | GET | `/v1/dungeons/tickets` | 티켓 현황 조회 | | ||||||
| | POST | `/v1/dungeons/gold-tickets/ad-reward` | 광고 보상 티켓 +1 (하루 1회) | | ||||||
| | POST | `/v1/dungeons/gold-runs` | 런 시작 (티켓 1장 소모) | | ||||||
| | POST | `/v1/dungeons/gold-runs/{runId}/claim` | 런 결과 정산 | | ||||||
|
|
||||||
| 티켓 규칙: | ||||||
|
|
||||||
| - 매일(**KST 기준 날짜**) 첫 접근 시 자동으로 **3장 충전**됩니다(지연 지급). | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. '지연 지급'이라는 표현은 네트워크 지연이나 의도적인 지급 보류(delayed payment)로 오해하기 쉽습니다. 매일 첫 접근 시점에 필요한 계산을 수행하여 충전하는 방식(Lazy Loading)을 의미한다면, '최초 요청 시점에 충전' 또는 '첫 요청 시점에 실시간 충전'과 같이 표현을 명확히 수정하는 것이 클라이언트 개발자의 혼선을 줄일 수 있습니다.
Suggested change
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @gemini-code-assist[bot] '지연 지급' 표현이 모호하다는 지적 반영해 '최초 요청 시점에 충전'으로 수정했습니다. 이 문서는 곧 플레이어 흐름 재설계 작업에서 함께 정리됩니다. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 네, 확인했습니다. 해당 문서는 향후 플레이어 흐름 재설계와 함께 최신화될 예정이라는 점 인지했습니다. 추가로, 문서의 160번 라인에 있는 '지연 지급' 표현을 '최초 요청 시점에 충전'으로 수정해주셔서 감사합니다. 클라이언트 개발자 입장에서 훨씬 명확한 가이드가 될 것입니다. |
||||||
| - 광고 보상으로 하루 1회 +1 가능. 같은 날 두 번 시도하면 **409**. | ||||||
|
|
||||||
| 런 흐름: | ||||||
|
|
||||||
| 1. `gold-runs` 호출 → 티켓 1장 소모, 런 생성. 응답: `runId`, `startedAt`, `durationSeconds`(30), `expiresAt`, `maxClicks`(15×30 = **450**). 티켓이 없으면 **400**. | ||||||
| 2. 30초 동안 클라이언트가 클릭 수를 집계. | ||||||
| 3. `gold-runs/{runId}/claim`에 `{ clicks }` 전송. 서버 검증: | ||||||
| - 런 소유자 불일치 → 403 | ||||||
| - `expiresAt` 초과(시작+30초+여유 30초) → 400 | ||||||
| - `clicks > maxClicks` 또는 **경과 시간 대비 과다 클릭** → 400 (어뷰징 방지) | ||||||
| 4. 보상: 클릭당 **10골드**, 2% 확률로 미스릴 1. | ||||||
| 5. 이미 정산된 런을 다시 호출하면 **동일 보상으로 멱등 응답**(중복 지급 없음). | ||||||
|
|
||||||
| ## 7. 공통 데이터 구조 | ||||||
|
|
||||||
| ### PlayerDataResponse (`player`) | ||||||
|
|
||||||
| 상태 변경 응답들이 공통으로 포함하는 플레이어 전체 스냅샷: | ||||||
|
|
||||||
| ``` | ||||||
| jobType, level, maxStage, lastWeaponId?, activeSkills[], | ||||||
| gold, exp, enhancementScroll, mithril, sp, | ||||||
| weapons[ { weaponId, count, enhancementLevel, awakeningCount } ], | ||||||
| skills[ { skillId, isUnlocked } ] | ||||||
| ``` | ||||||
|
|
||||||
| ### ChangesDto (`changes`) | ||||||
|
|
||||||
| 이번 호출로 발생한 변화량(델타). 연출/토스트용: | ||||||
|
|
||||||
| ``` | ||||||
| gold, exp, sp, mithril, enhancementScroll, dungeonTickets, | ||||||
| levelUps[], unlockedSkillIds[], acquiredWeaponIds[], maxStage | ||||||
| ``` | ||||||
|
|
||||||
| ### Enum | ||||||
|
|
||||||
| | Enum | 값 (순서값) | | ||||||
| |---|---| | ||||||
| | JobType | `Warrior`(0), `Archer`(1), `Mage`(2) | | ||||||
| | WeaponGrade | `C`(0), `B`(1), `A`(2), `S`(3) | | ||||||
| | SkillEffectType | `AtkFlat`, `AtkPercent`, `HpFlat`, `HpPercent`, `CritRate`, `CritDmg`, `CooldownReduce`, `ElementalBoost` | | ||||||
|
|
||||||
| > 게임 데이터 조회 엔드포인트(5장)는 enum을 **문자열 이름**으로 반환합니다. | ||||||
| > 플레이어/던전 응답의 enum 직렬화 형태(이름 vs 순서값)는 `/swagger`의 실제 응답으로 확인 후 매핑하세요. | ||||||
|
|
||||||
| ## 8. 시간 처리 | ||||||
|
|
||||||
| - 서버 시각은 모두 **UTC**입니다. 응답의 시각 필드(`serverNow`, `lastCalculatedAt`, `expiresAt` 등)는 UTC 기준입니다. | ||||||
| - 단, 일일 리셋(던전 티켓·광고 보상)은 **KST(UTC+9) 날짜** 기준으로 판정됩니다. | ||||||
| - 클라이언트는 로컬 시계 대신 서버가 내려준 시각(`serverNow`)을 기준으로 동기화하는 것을 권장합니다. | ||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
보안 위험 안내 (HTTP 사용 및 JWT 전송)
현재 배포 환경의 포트 제약으로 인해 HTTPS 대신 HTTP 프로토콜을 사용한다고 명시되어 있습니다. 하지만 HTTP 환경에서 JWT Bearer 토큰(
Authorization헤더)을 전송할 경우, 네트워크 상에서 토큰이 평문으로 노출되어 중간자 공격(MITM)을 통해 쉽게 탈취될 수 있습니다.학교 포트 제약이 있더라도, Nginx 등의 역방향 프록시(Reverse Proxy)를 설정하거나 Cloudflare 등을 활용하여 비표준 포트에서도 HTTPS를 적용하는 것을 강력히 권장합니다.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@gemini-code-assist[bot] HTTP 사용은 학교 서버 포트포워딩 제약(외부 443 확보 불가로 표준 ACME 검증 불가)으로 인지·수용한 의도된 결정입니다. 문서도 이 제약을 명시하고 있어 결함이 아닙니다. 비표준 포트 HTTPS(DuckDNS+Caddy DNS-01 등) 경로는 추후 별도 검토 예정입니다.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
이해했습니다. 학교 서버 환경의 물리적/네트워크적 제약으로 인해 HTTPS 적용이 어려운 상황임을 명확히 인지했습니다. 문서에 해당 제약을 명시하고 의도된 설계임을 밝혀주셨으므로, 해당 이슈는 해결된 것으로 간주하겠습니다. 추후 환경 개선 시 HTTPS 도입을 검토하시겠다는 계획도 확인했습니다.