Conversation
There was a problem hiding this comment.
🤖 AI 코드 리뷰 - 아키텍처 관점
completion 기반 Repository 시그니처를 async/throws로 전환하고, 카카오 로컬 API 기반 실제 구현체(KakaoNearbyPlaceRepository, KakaoPlaceSearchRepository, KakaoReverseGeocodingRepository)와 공용 네트워크 레이어(APIClient, Endpoint, NetworkError)를 추가하는 PR이다. 계층 분리 원칙은 전반적으로 준수되어 있으나, Data 계층 응답 모델이 Domain 에러 타입(AppError)을 직접 참조하는 부분과, APIClient 프로토콜이 구체 타입(NetworkError)과 결합된 에러 흐름, KakaoLocalEndpoint의 헤더 계산 시 APIKey를 직접 호출하는 구조에 아키텍처적 우려가 있다.
sangYuLv
left a comment
There was a problem hiding this comment.
고생 많으셨습니다!
네트워크 레이어 이후에 잘 사용할 수 있게 잘 구축해주셨네요!
코멘트 확인 부탁드립니다 🦦
| let place = try? await self.getNearbyPlaceUseCase.execute(coordinate: coordinate) | ||
| guard !Task.isCancelled else { return } | ||
| completion(coordinate, place?.name ?? "현재 위치") | ||
| } |
There was a problem hiding this comment.
하나의 유즈케이스 안에서 현재 좌표 받고, 그 좌표로 근처 장소 검색한 뒤 결과를 ChatViewModel에게 돌려주는 방향은 어떨까요?
| hasSearched = false | ||
| errorMessage = nil | ||
| allPlaces = [] | ||
| applyFilter() |
There was a problem hiding this comment.
장소 검색 결과가 비도록 처리했는데 applyFilter 호출이 필요한 이유가 궁금합니다!
| /// 카카오 카테고리 검색 기반 주변 장소 조회 | ||
| /// 카테고리 검색은 요청당 카테고리 1개만 지원하므로, 관심 카테고리를 병렬 요청한 뒤 가장 가까운 결과 1개를 선택 | ||
| /// 지도 이동 1회당 카테고리 수만큼 호출이 발생 — PlaceSelectionViewModel의 디바운스/최소 이동 거리 필터로 호출량을 제한 | ||
| final class KakaoNearbyPlaceRepository: NearbyPlaceRepository { |
There was a problem hiding this comment.
카테고리 검색 기반인 이유가 우리 서비스에서 다루는 장소 타입만 검색해서 가져올 목적인 것으로 이해했습니다.
처음 코드를 읽을 때, 키워드로 장소 검색하는 곳에서 사용하는 레파지토리인 줄 알았습니다.
장소 검색 화면에서 사용자가 장소를 필터링하는 기능 때문에 카테고리 기반이라는 설명이 그 화면에서 사용되는 것이라고 이해됐었습니다.
PlaceType으로 매핑되는 카테고리만 포함하는 것도 중요한 내용이지만, 가까운 장소를 찾아내는 것만 주석에서 강조해도 좋을 듯 합니다!
+) 카테고리 수만큼 호출이 발생하는 게 부담스러워진다면 (1)근처 장소 목록을 조회하고, (2)우리가 다루는 카테고리에 포함되는 장소가 있는지 확인하고 (3)없다면 반경을 넓혀서 다시 조회하는 게 호출 횟수를 줄이는 방향일 수도 있을 듯 합니다! 검토 부탁드려요!
JIRA
📝 작업 내용
📌 요약
PlaceSearchRepository(키워드 검색)NearbyPlaceRepository(주변 장소)ReverseGeocodingRepository(역지오코딩)Endpoint/APIClient공용 네트워크 레이어를 새로 구축🔍 상세
[1] API 키 / 네트워크 레이어
Config.xcconfig에 카카오 REST API 키 추가,Info.plist에KakaoRestAPIKey항목으로 연결APIKey: Info.plist 키 조회 캡슐화, 키 미설정 시assertionFailure로 개발 중 조기 발견NetworkError→AppError매핑 추가Endpoint프로토콜: baseURL/path/method/query/header를 선언적으로 표현,makeURLRequest()로URLRequest생성APIClient(URLSessionAPIClient):async throws기반 공용 요청 실행기상태 코드 검증 → 디코딩 →
NetworkError매핑까지 한 곳에서 처리[2] Repository async 전환
async throws로 전환SearchPlaceCardViewModel,PlaceSelectionViewModel이 새 요청 시작 전 이전Task를 취소하도록 변경[3] 카카오 로컬 API 연동
KakaoLocalEndpoint다음 3종 정의/v2/local/search/keyword.json)/v2/local/search/category.json)/v2/local/geo/coord2address.json)KakaoCategoryGroupCodeKakaoPlaceResponse/KakaoAddressResponsePlace매핑category_group_code기반PlaceType매핑KakaoNearbyPlaceRepositorywithThrowingTaskGroup으로 병렬 요청 후 가장 가까운 결과 채택AppDIContainer+Register에서 3개 Repository를 Mock에서 실제 구현으로 교체[4] 현재 위치 표시 개선
GetNearbyPlaceUseCase로 조회한 실제 장소명/주소 표시💬 리뷰 노트
[1] 카카오 로컬 API를 선택한 이유
이번에 필요한 기능은 키워드 검색, 좌표 반경 내 POI 조회, 역지오코딩 3가지입니다. 검토한 선택지는 아래와 같습니다.
역지오코딩(NCP)과 키워드 검색(Developers)이 서로 다른 서비스라 키가 두 벌 필요합니다.
필요한 기능을 가장 적은 통합 비용으로 커버하는 카카오 로컬 API를 선택했습니다.
다만 카카오 로컬 API는 국내 좌표만 지원합니다.
해외 좌표에서는 검색/조회가 모두 실패하고 폴백 문구가 표시됩니다.
이 앱이 국내 사용자만 대상으로 한다는 전제하에 진행했고,
추후 해외 지원이 필요해지면 MapKit 등을 보조로 추가하는 등의 별도 작업이 필요합니다.
[2] 후속 이슈 (별도 이슈 분리)
size=15, API 자체 최댓값)만 조회하는데,광범위한 지명 키워드는 관련도 랭킹에서 원하는 결과가 15위 밖으로 밀릴 수 있음.
카카오 좌표 데이터가 세분화되어 있어 랜드마크보다 그 안의 작은 상호가 좌표상 더 가깝게 잡히는 경우가 있음.
jira - 정확도 향상이 필요하다는 이슈
[3] 기타 리뷰 포인트
PlaceSelectionViewModel의 기존 디바운스(300ms)/최소 이동 거리(20m) 필터로 호출량을 억제하고 있지만,실사용 패턴에 따라 쿼터 소모가 클 수 있어 모니터링이 필요합니다.
name과address를 같은 값(도로명 주소)으로 채웠습니다.place.name하나만 참조해도 항상 의미 있는 문구가 나오게 하기 위한 선택입니다.📸 영상 / 이미지
build.mp4
시뮬레이터 위치 설정(37.5665, 126.9780)