🚀 Description
홈의 '가까운순' 필터 칩(PinFilter.nearby)과 하단 탭바의 '저장' 탭은 둘 다 사용자 현재 위치가 있어야 동작합니다. 지금 저장소에는 CoreLocation 을 쓰는 코드가 한 줄도 없고(grep CLLocationManager 결과 0건), App/Info.plist 에 위치 권한 사용 목적 문자열도 없습니다. 즉 위치를 얻을 방법 자체가 없는 상태입니다.
현재 상태를 정리하면:
PinFilter.nearby 는 enum 케이스와 칩 라벨("가까운순", HomeContentView.swift:278)만 있고, 정렬 기준이 될 좌표가 없습니다.
FetchPinsUseCase.execute(rooms:filter:) 는 좌표를 받지 않습니다 — nearby 를 서버에 요청하려면 기준 좌표를 실어 보내야 하는데 시그니처에 자리가 없습니다.
- '저장' 탭(
FeatureArchive)은 방 리스트만 띄우고, 지도 진입 시 카메라를 어디에 둘지(현재 위치 vs 기본 좌표) 정해진 게 없습니다.
이 이슈는 위치 권한 요청 흐름과 위치 제공 계층을 만드는 것까지를 범위로 합니다. 권한이 필요한 두 지점(가까운순 칩 탭, 저장 탭 진입)에서 권한을 요청하고, 허용/거부/제한 각 상태에서 화면이 무엇을 보여줄지까지 정의합니다.
확정된 정책 — 권한은 필요한 순간에 요청한다
앱 최초 진입에서 몰아서 묻지 않고, 위치가 실제로 필요해지는 순간에 요청합니다. 요청 지점은 두 곳입니다.
- 홈에서 '가까운순' 칩을 탭했을 때
- 하단 탭바에서 '저장' 탭에 진입했을 때
사용자가 "왜 위치를 묻는지" 를 화면 맥락으로 이해할 수 있어 허용률과 납득 면에서 낫습니다. 대신 두 진입점이 각각 권한 상태를 다뤄야 하므로, 권한 요청·좌표 획득 흐름은 한 곳(위치 제공 계층)에 두고 각 화면의 reduce 가 그 결과만 받는 형태로 갑니다. 이미 허용된 상태에서 재요청하면 시스템 다이얼로그가 뜨지 않으므로, 각 진입점은 "권한 확인 → (미결정이면) 요청 → 좌표 획득" 한 흐름을 그대로 호출합니다.
설계 시 결정할 것
CoreLocation 을 어느 패키지에 둘 것인가 — MapUI 는 GoogleMaps SDK 를 가두는 브릿지라 성격이 비슷하지만 위치 권한은 UI 가 아닙니다. Core 에 두면 Core 를 의존하는 모든 패키지가 CoreLocation 을 상속받습니다(clean-architecture.md 의 Core 배치 기준 참고). 새 패키지(LocationService 등) 분리도 후보입니다.
- Domain 경계 — Feature 는
CLLocation 이 아니라 순수 value type(MapUI.MapCoordinate 또는 Domain 의 새 VO)을 봐야 합니다. 어느 쪽을 쓸지 정합니다.
- 거부·제한 시 fallback — '가까운순' 칩을 비활성화할지, 다음 기준으로 자동 전환할지, 설정 앱 유도 안내를 띄울지. 정확도 축소(
.reducedAccuracy)와 "앱 사용 중에만 허용" 도 상태로 다뤄야 합니다.
범위 밖
- 실제
nearby 서버 정렬 API 연동 — 서버 계약이 정해지면 별도 이슈. 이 이슈는 좌표를 UseCase 까지 흘려보내는 자리를 만드는 데까지입니다.
- 백그라운드 위치 추적(
Always 권한) — 현재 기획에 없습니다. WhenInUse 만 요청합니다.
- 저장 탭 지도 화면 자체의 구현.
✅ TODO
📸 Screenshot(optional)
🚀 Description
홈의 '가까운순' 필터 칩(
PinFilter.nearby)과 하단 탭바의 '저장' 탭은 둘 다 사용자 현재 위치가 있어야 동작합니다. 지금 저장소에는CoreLocation을 쓰는 코드가 한 줄도 없고(grep CLLocationManager결과 0건),App/Info.plist에 위치 권한 사용 목적 문자열도 없습니다. 즉 위치를 얻을 방법 자체가 없는 상태입니다.현재 상태를 정리하면:
PinFilter.nearby는 enum 케이스와 칩 라벨("가까운순",HomeContentView.swift:278)만 있고, 정렬 기준이 될 좌표가 없습니다.FetchPinsUseCase.execute(rooms:filter:)는 좌표를 받지 않습니다 —nearby를 서버에 요청하려면 기준 좌표를 실어 보내야 하는데 시그니처에 자리가 없습니다.FeatureArchive)은 방 리스트만 띄우고, 지도 진입 시 카메라를 어디에 둘지(현재 위치 vs 기본 좌표) 정해진 게 없습니다.이 이슈는 위치 권한 요청 흐름과 위치 제공 계층을 만드는 것까지를 범위로 합니다. 권한이 필요한 두 지점(가까운순 칩 탭, 저장 탭 진입)에서 권한을 요청하고, 허용/거부/제한 각 상태에서 화면이 무엇을 보여줄지까지 정의합니다.
확정된 정책 — 권한은 필요한 순간에 요청한다
앱 최초 진입에서 몰아서 묻지 않고, 위치가 실제로 필요해지는 순간에 요청합니다. 요청 지점은 두 곳입니다.
사용자가 "왜 위치를 묻는지" 를 화면 맥락으로 이해할 수 있어 허용률과 납득 면에서 낫습니다. 대신 두 진입점이 각각 권한 상태를 다뤄야 하므로, 권한 요청·좌표 획득 흐름은 한 곳(위치 제공 계층)에 두고 각 화면의 reduce 가 그 결과만 받는 형태로 갑니다. 이미 허용된 상태에서 재요청하면 시스템 다이얼로그가 뜨지 않으므로, 각 진입점은 "권한 확인 → (미결정이면) 요청 → 좌표 획득" 한 흐름을 그대로 호출합니다.
설계 시 결정할 것
CoreLocation을 어느 패키지에 둘 것인가 —MapUI는 GoogleMaps SDK 를 가두는 브릿지라 성격이 비슷하지만 위치 권한은 UI 가 아닙니다.Core에 두면Core를 의존하는 모든 패키지가CoreLocation을 상속받습니다(clean-architecture.md의 Core 배치 기준 참고). 새 패키지(LocationService등) 분리도 후보입니다.CLLocation이 아니라 순수 value type(MapUI.MapCoordinate또는 Domain 의 새 VO)을 봐야 합니다. 어느 쪽을 쓸지 정합니다..reducedAccuracy)와 "앱 사용 중에만 허용" 도 상태로 다뤄야 합니다.범위 밖
nearby서버 정렬 API 연동 — 서버 계약이 정해지면 별도 이슈. 이 이슈는 좌표를 UseCase 까지 흘려보내는 자리를 만드는 데까지입니다.Always권한) — 현재 기획에 없습니다.WhenInUse만 요청합니다.✅ TODO
CoreLocation을 가둘 패키지 결정 + 권한/위치 제공 프로토콜 정의 (Sendable, async 인터페이스)CLLocationManager델리게이트 → async 브릿지)App/Info.plist에NSLocationWhenInUseUsageDescription추가 (문구는 기획·디자인과 확정)FetchPinsUseCase/PinRepository에 기준 좌표 전달 경로 추가 (nearby일 때만 필요)HomeStorereduce 에 연결MockPinRepository에 좌표 기반nearby목 데이터 반영📸 Screenshot(optional)