# 날씨 앱 [STEP 2-2] Blu, Jenna
>안녕하세요! 코리(@corykim0829)🐶!
🌙**TEAM LuNna**🌙 의 Blu, Jenna입니다!
>
>STEP 2-2에서는 위도와 경도를 주소로 변환하는 로직 구현 및 HTTP GET 명시적 호출을 구현에 대해 학습하고 적용해 보았어요!
>STEP을 세분화하여 부분적으로 학습을 진행하고 코드를 작성하게 되니까 해당 부분에 대해 조금 더 많이 찾아보고 이해할 수 있어서 좋은 시간이었습니다!
>
>이번 리뷰도 잘 부탁드려요! 감사합니다! 🙇🏻🙇🏻
<br>
# 🧑🏼💻 작업 목록
## 위도와 경도를 주소로 변환하기
- [x] CL LocationManagerDelegate의 `locationManager(_:didUpdateLocations:)`의 매개변수 locations로 현재 위도, 경도를 포함한 CLLocation 타입 가져오기
- [x] CLGeocoder에 위에서 가져온 타입을 활용하여 현재 위치의 장소 정보 가져오기
- [x] 가져온 장소 정보를 활용하여 주소로 변환하기
↳ 장소 정보의 형태에 관한 고민이 있어 구체적인 구현은 보류, 추후 상황에 따라 별도의 타입으로 분리하고자 함
## HTTP GET 메서드를 명시적으로 호출하기
- [x] `URLRequest`의 `httpMethod` 변수값을 "GET"으로 명시적 호출
<br>
# 📚 학습 키워드 및 학습 내용
## 1. HTTP Method
> 🖇️ 참고한 공식문서:
> - [URLRequest](https://developer.apple.com/documentation/foundation/urlrequest)
> - [NSURLRequest](https://developer.apple.com/documentation/foundation/nsurlrequest#1776617)
> - [httpMethod](https://developer.apple.com/documentation/foundation/urlrequest/2011415-httpmethod)
- **학습 내용**
- httpMethod
- URLRequest & NSURLRequest
- 로드 요청에 대한 두 가지 필수 속성을 캡술화함
- 로드할 URL
- 사용되는 정책
- HTTP/HTTPS 요청의 경우 HTTP method(GET, POST...)와 헤더를 포함
- HTTP method를 지정하기 위한 `httpMethod` 프로퍼티는 `NSURLRequest` 클래스의 프로퍼티임
- Foundation 프레임워크는 `URLRequest`클래스와 해당 가변 클래스인 `NSMutableURLRequest`에 연결된 `URLRequest` 구조체를 제공함,
**즉, `NSURLRequest`에 있는 component들을 `URLRequest`에서 사용할 수 있음!**
- httpMethod의 기본 HTTP method는 GET
- **적용 과정**
- 문서에 따르면 `"GET"`이 default값
```Swift
The default HTTP method is “GET”.
```
- 'HTTP GET 메서드 명시적 호출'이 요구사항이라 아래와 같이 set해주는 코드를 추가해주긴 했지만, 아래 아쉬운 점과 더불어 '명시적 호출'을 제대로 구현한 게 맞는가에 대한 의문이 듦
```Swift
request.httpMethod = "GET"
```
- **아쉬운 점**
- 문서에서 알 수 있다시피 String? 타입이라 String("GET") 리터럴값을 직접 넣어줘야 했음
- 휴먼에러가 발생하기 쉬운 부분이라고 생각되는데 원래 이렇게 사용하는 게 맞는 건지, 놓친 부분이 있는지 궁금함
<br>
## 2. CLGeocoder
> 🖇️ 참고한 공식문서:
> - [CLGeocoder](https://developer.apple.com/documentation/corelocation/clgeocoder)
> - [CLPlacemark](https://developer.apple.com/documentation/corelocation/clplacemark)
- **학습 내용**
- CLGeocoder
- Core Location 프레임워크 내부의 클래스
- 위도와 경도로 이루어진 좌표와 사용자 친화적인 주소 표현 사이의 변환 서비스를 제공하는 클래스
- 일반적으로 거리, 도시, 주, 국가 및 지역정보를 포함함
- forward geocoding method (**순방향**)
- 사용자가 읽을 수 있는 주소로 위도와 경도를 찾음
- 관심 지점이나 해당 위치의 건물과 같은 지정 위치에 대한 추가정보를 반환할 수 있음
- 제공된 정보가 여러 위치를 산출할 경우 여러 개의 placemark가 반환될 수 있음
- reverse geocoding method (**역방향**) ✅
- 위도와 경도를 가지고 사용자가 읽을 수 있는 주소를 찾음
- `reverseGeocodeLocation` 사용
- forward / reverse 모두 `CLPlacemark` 형태로 반환
- CLPlacemark
- 장소의 이름, 주소 및 기타 관련 정보를 포함하는 좌표에 대한 **사용자 친화적인 설명**
- 지정된 위/경도에 대한 placemark 데이터를 저장
- 좌표, 국가, 지역, 주, 도시 및 거리 주소와 같은 정보 포함
- 관심지점 및 지리적인 데이터가 포함될 수 있음
- reverse geocoding을 하는 경우 CLPlacemark 개체를 반환받음
- Detail properties
|프로퍼티명|설명|
|:---|:---|
|`throughfare`|The street address associated with the placemark.<br>**거리 주소(도로명주소의 ~로)**|
|`subThroughfare`|Additional street-level information for the placemark.<br>**추가 거리수준 정보(상세주소)**|
|`locality`|The city associated with the placemark.<br>**도시('시'로 끝나는 행정구역)**|
|`subLocality`|Additional city-level information for the placemark.<br>**추가 도시수준 정보(동/면/~로)**|
|`adminstrativeArea`|The state or province associated with the placemark.<br>**주 혹은 지방 정보(행정구역 중 가장 넓은 범위, 도/특별시/광역시)**|
|`subAdminstrativeArea`|Additional administrative area information for the placemark.<br>**추가 행정구역 정보(행정구역 중 군)**|
|`postalCode`|The postal code associated with the placemark.<br>**우편번호**|
|`country`|The name of the country or region associated with the placemark.<br>**국가명**|
|`name`|The name of the placemark.<br>**placemark의 이름(보통 throughfare + subThroughfare)**|
- **적용 과정**
- CLLocationManager으로 가져온 CLLocation 타입의 location으로 reverse geocoding 을 진행
- **문제와 해결**
|문제와 해결|내용|
|:---:|:---|
|문제|기존에 Coustom Location으로 지정한 좌표(37.53, 126.96)를 기준으로 주소를 가져오는 경우 '구'에 해당하는 '용산구'를 불러오는 프로퍼티가 없음|
|해결|***해결중!!*** 외부 라이브러리가 제약된 상황이라 출력된 정보를 가지고 가공해야 하는지 방법을 찾아보는 중|
<br>
# 🙋🏻 질문 거리
## 1. Geocoder 사용 시 주소체계의 차이에 따른 문제점
- Core Location의 좌표를 통해 CLGeocoder로 reverse geocoding한 결과로 반환된 CLPlacemark상에는 `대한민국 서울특별시 용산구 한강로3가 40-1030`으로 주소가 잘 담겨있으나, '구'에 해당하는 주소를 가져오는 프로퍼티를 찾지 못했습니다.
- LLDB를 통하여 공식문서 내부에 존재하는 프로퍼티를 모두 호출해 보았지만 구에 해당하는 프로퍼티가 없었습니다.

- 주소체계마다 다른 것인지를 알아보기 위해 시뮬레이터의 Custom Location을 변경하여 진행해 본 결과, 도/시 체계를 가지고 있는 경우(예: 경기도, 전라남도)는 `administrativeArea`에 도에 해당하는 값이, `locality`는 시에 해당하는 값이 나오지만, 시/구 체계를 가지고 있는 경우(예: 서울시, 광주광역시)는 `administrativeArea`와 `locality`가 시에 해당하는 값으로 동일하게 나왔습니다.
또한, 도/시 체계와 도/군 체계에서도 호출해야 하는 프로퍼티에 차이가 있다는 점을 알게 되었어요.

<br>
- 주소체계에 따라 존재하는 값과 존재하지 않는 값이 있고, `administrativeArea`와 `locality`가 동일한 문제가 발생하였고 이를 해결하기 위해 다른 방법을 찾아보았지만, 만족스러운 방법은 아니었습니다!
- 전체 주소(`대한민국 서울특별시 용산구 한강로3가 40-1030`)를 가지고 올 수 있다면, 해당 주소를 공백문자 `' '` 기준으로 분할하고, 구에 해당되는 index 번호를 가져올까 시도해 보았습니다.
- 이를 위해 전체 주소를 가져올 수 있는 프로퍼티에 대해 찾아보고 있던 중 `addressDictionary`를 발견하였고, lldb 로그로 조회해 본 결과 "FormattedAddressLines" key를 사용하면 전체 주소와 우편번호가 담긴 배열에 접근할 수 있다는 사실을 알게 되었습니다. 해당 부분을 학습하기 위해 공식문서를 찾아본 결과 Deprecated된 프로퍼티였습니다.

- 전체 주소를 가져올 수 있는 프로퍼티가 없으므로, 현재는 `.description.components(separatedBy: ", ")`으로 리턴된 `CLPlacemark`를 분리시킨 후, 전체 주소에 해당하는 값만 가져오는 방식으로 구현해 두었어요! 하지만 이 경우 index로 접근하게 되면서 발생할 에러에 대한 위험성이 있겠다 판단했습니다. 더 좋은 방법을 찾아보려 하였으나 아직 찾지 못했어요...! 🥲

- 외부 라이브러리나 API를 사용하지 않고, CLGeocoder만 활용해서 적절한 형태의 주소(가공이 크게 필요하지 않은 데이터)를 불러올 수 있는 방법이 없을까요?
- 주소를 사용자에게 보여주는 많은 어플들이 주소체계와 상관없이 시/구/동에 해당하는 주소가 명확히 나오는 것 같아요 👀 현업에서는 CLGeocoder만 사용하는지, 아니면 다른 방식을 사용 중인지 궁금합니다!