4. ํ์ต๋ด์ฉ ๋ฐ ๋ฌธ์ ํด๊ฒฐ
๐๐ป๐๐ปโโ๏ธ๐จ ํ๋ก์ ํธ ๊ธฐ๊ฐ: 23.03.13
~ 23.04.14
Blu | Jenna |
- ์ปค๋ฐ ๊ท์น
- โจย Git Commit Convention
- Prefix ์ ์ฒด ์๋ฌธ์,
[prefix]
feat
ย = ์ฃผ๋ก ์ฌ์ฉ์์๊ฒ ์๋ก์ด ๊ธฐ๋ฅ์ด ์ถ๊ฐ๋๋ ๊ฒฝ์ฐfix
ย = ์ฌ์ฉ์๊ฐ ์ฌ์ฉํ๋ ๋ถ๋ถ์์ bug๊ฐ ์์ ๋๋ ๊ฒฝ์ฐdocs
ย = ๋ฌธ์์ ๋ณ๊ฒฝ ์ฌํญ์ด ์๋ ๊ฒฝ์ฐconfig
= ํ๋ก์ ํธ ์ด๊ธฐ ์ค์ ์style
ย = ์ธ๋ฏธ์ฝ๋ก ์ ๊น๋จน์ด์ ์ถ๊ฐํ๋ ๊ฒ ๊ฐ์ด ํ์์ ์ธ ๋ถ๋ถ์ ๋ค๋ฃจ๋ ๊ฒฝ์ฐ (์ฝ๋์ ๋ณํ๊ฐ ์์ฐ์ ์ธ ๊ฒ์ด ์๋ ๊ฒฝ์ฐ)refactor
ย = production code๋ฅผ ์์ ํ๋ ๊ฒฝ์ฐ (๋ณ์์ ๋ค์ด๋ฐ์ ์์ ํ๋ ๊ฒฝ์ฐ)test
ย = ํ ์คํธ ์ฝ๋๋ฅผ ์์ ํ๊ฑฐ๋, ์ถ๊ฐํ๋ ๊ฒฝ์ฐ (์ฝ๋์ ๋ณํ๊ฐ ์์ฐ์ ์ธ ๊ฒ์ด ์๋ ๊ฒฝ์ฐ)chore
ย = ๋ณ๋ก ์ค์ํ์ง ์์ ์ผ์ ์์ ํ๋ ๊ฒฝ์ฐ (์ฝ๋์ ๋ณํ๊ฐ ์์ฐ์ ์ธ ๊ฒ์ด ์๋ ๊ฒฝ์ฐ)- +)
design
= UI ๋์์ธ์ ๋ณ๊ฒฝํ์ ๋
- Prefix ์ ์ฒด ์๋ฌธ์,
- โจย Git Commit Convention
- ๋ธ๋์น โ step ๋ณ๋ก ๊ตฌ๋ถ, PR ์ main์ผ๋ก ์ ์ก
- ์ฒ์ฒํ ์ฐจ๊ทผ์ฐจ๊ทผ, ํ๋์ฉ ํ๊ธฐ
- ๋ชจ๋ธ/๋คํธ์ํน ํ์
๊ตฌํ
- Open Weather Map์ ๋ ์จ API์ ๋ฐ์ดํฐ ํ์์ ๊ณ ๋ คํ ๋ชจ๋ธ ํ์ ๊ตฌํ
- ์๋, ๊ฒฝ๋๋ฅผ ์ฌ์ฉํ์ฌ ๋ ์จ๋ฅผ ํธ์ถ ํ ์ ์๋๋ก
WeatherURL
ํ์ ๊ตฌํ
- ๐๏ธ keyword:
API Key
,URLSession
,Codable
,JSONDecoder
,CodingKey
- STEP 1 PR ๐
- ์์น์ ๋ณด ํ์ธ ๋ฐ ๋ ์จ API ํธ์ถ
- ์๋ฎฌ๋ ์ดํฐ์ ์๋์ ๊ฒฝ๋๋ฅผ Custom์ผ๋ก ์ค์
- CoreLocation๊ณผ API๋ฅผ ํตํด ํ์ฌ ์ขํ์ ๋ ์จ Data ํธ์ถ
CLLocationManagerDelegate
์locationManager(_:didUpdateLocations:)
์ ๋งค๊ฐ๋ณ์ locations๋ก ํ์ฌ ์๋, ๊ฒฝ๋๋ฅผ ํฌํจํCLLocation
ํ์ ๊ฐ์ ธ์ค๊ธฐ
- ๐๏ธ keyword:
CoreLocation
,URLComponent
,HTTP Method
,CLGeocoder
- STEP 2-1 PR ๐
- STEP 2-2 PR ๐
- UI๊ตฌํ
Collection View
๋ฅผ ํ์ฉํ์ฌ ์ฑ์ UI ๊ตฌํ- header view์ ํ์ฌ ๋ ์จ ์ ์ฉ
- cell์ 5์ผ ์๋ณด ์ ์ฉ
- ์ฝ๋๋ฒ ์ด์ค AutoLayout ๊ตฌํ
- ๐๏ธ keyword:
CollectionView
,DateFormatter
,UICollectionViewCompositionalLayout
,URLComponents
,UIRefreshControl
- STEP 3-1 PR ๐
- STEP 3-2 PR ๐
๐๏ธใ์ฐธ๊ณ ํ ๋ฌธ์: API Key, Keeping API Keys Safe
- ํ์ต ๋ด์ฉ
- ๊ฐ์ธ๋ณ๋ก ๋ฐ๊ธ, API๋ฅผ ํธ์ถํ๊ธฐ ์ํ key
- ๊ณต๊ฐํ๋ฉด ์ ๋จ
- ์ ์ฉ ๊ณผ์
- url์ฟผ๋ฆฌ์ ๋ค์ด๊ฐ๋ ๋ด์ฉ์ด๋ผ... โ ํ์ฌ๋ ๋ฌธ์์ด ๋ฐฐ์ด์ .joined(separator: "&")์ฒ๋ฆฌํ๋ ๋ฐฉ์์ผ๋ก ๊ตฌํํ์ผ๋, ๋ค์ ์คํ
์์
URLQueryItem
(์ถ๊ฐํ์ตํค์๋+)์ ๋ํ ํ์ต ์งํ ํ ๋ฆฌํํ ๋ง ์์ !
- url์ฟผ๋ฆฌ์ ๋ค์ด๊ฐ๋ ๋ด์ฉ์ด๋ผ... โ ํ์ฌ๋ ๋ฌธ์์ด ๋ฐฐ์ด์ .joined(separator: "&")์ฒ๋ฆฌํ๋ ๋ฐฉ์์ผ๋ก ๊ตฌํํ์ผ๋, ๋ค์ ์คํ
์์
- ๋ฌธ์ ์ ํด๊ฒฐ
- ์จ๊ฒจ์ผ ํ์ โ ์ฌ๋ฐ๊ธ, ์จ๊ธฐ๊ธฐ (์๋ ์ง๋ฌธ์ฌํญ์!)
๐๏ธใ์ฐธ๊ณ ํ ๊ณต์๋ฌธ์: URLSession
- ํ์ต ๋ด์ฉ
- URLSession์ ์ฑ๊ธํด ์ธ์คํด์ค(shared)๋ฅผ ์ ๊ณต
- ์ธ์คํด์ค๋ฉ์๋ '.data(for:
URLRequest
)'์ ๋ฐํํ์(Data, URLResponse)
- ์ ์ฉ ๊ณผ์
- api๋ณ url๋ก
URLRequest
๋ฅผ ๋ฏธ๋ฆฌ ๋ง๋ค์ด ์ธ์๋ก ์ฌ์ฉ ('.data(from:URL
)' ์ฌ์ฉํ์ง ์์) - ์ง๊ธ ๋จ๊ณ์์ response ์์ด data๋ง ํ ๋นํ์ฌ ํ์ฉ โ ๋ค์ ์คํ ์์ ์ฌ์ฉํ ์์
- api๋ณ url๋ก
- ๋ฌธ์ ์ ํด๊ฒฐ
- ๋ฐ์ดํฐ ๋ถ๋ฌ์ค๊ธฐ๋ ๋น๋๊ธฐ๋ก ์ด๋ฃจ์ด์ง๋, ๋ถ๋ฌ์จ ๋ฐ์ดํฐ๋ฅผ ํ์ฉํ๋ ๊ฑด ๋ฉ์ธ์ค๋ ๋์์ ์ฒ๋ฆฌ๋์ด์ผ ํจ
- ๋์ ํ์ธ ๋ฐฉ๋ฒ: ViewController์ viewDidLoad()์์
Task { ... }
์์ ๋ฌถ์ด์ ์คํ async
-await
ํ์ฉ์ ๋์ (๊ธฐํ๊ฐ ๋๋ค๋ฉด GCD ๋ฑ ๋ค๋ฅธ ๋ฐฉ์์ผ๋ก๋ ํด๋ณด๊ณ ์ถ์ด์!)
- ๋์ ํ์ธ ๋ฐฉ๋ฒ: ViewController์ viewDidLoad()์์
- ๋ฐ์ดํฐ ๋ถ๋ฌ์ค๊ธฐ๋ ๋น๋๊ธฐ๋ก ์ด๋ฃจ์ด์ง๋, ๋ถ๋ฌ์จ ๋ฐ์ดํฐ๋ฅผ ํ์ฉํ๋ ๊ฑด ๋ฉ์ธ์ค๋ ๋์์ ์ฒ๋ฆฌ๋์ด์ผ ํจ
๐๏ธใ์ฐธ๊ณ ํ ๊ณต์๋ฌธ์:
-
ํ์ต ๋ด์ฉ
-
Encodable
๊ณผยDecodable
์ ํฉ์ฑ ํ๋กํ ์ฝ -
JSONDecoder
๋Codable
์ ์ฑํํ class๋ก, ์๋์ ์ ๋ค๋ฆญ ๋ฉ์๋๋ฅผ ํตํด (JSONํ์์)Data๋ฅผ ์ํ๋ ๋ชจ๋ธํ์ ์ผ๋ก ๋ณํํ ์ ์์func decode<T>(_ type: T.Type, from: Data) -> T { }
-
-
์ ์ฉ ๊ณผ์
- ์๋ ์ด์ ๋ก, ๋ชจ๋ธ๋ค์ด
Codable
์ด ์๋Decodable
๋ง ์ฑํํ๋๋ก ํจdecode(_:from:)
๋ฌธ์์ ๋ฐ๋ฅด๋ฉด type๋งค๊ฐ๋ณ์์ ๋ค์ด๊ฐ ์ ๋ค๋ฆญ ์ธ์๋ Codable์ด ์๋ โDecodableโ๋ง ์ค์ํ๋ฉด ๋๋ค๋ ์กฐ๊ฑด์- ์ฐ๋ฆฌ๊ฐ ์ฌ์ฉํ๊ณ ์ ํ๋ API๋ ๋ ์จ ๋ฐ์ดํฐ๋ก, encodingํ๋ ์ํฉ์ ๊ณ ๋ คํ์ง ์์๋ ๋จ
(์ ์ด์ ๋๋ถ๋ถ์ api๋ get ์ ์ฉ์ผ๋ก ํ์ ๋์ด ์์)
- ์๋ ์ด์ ๋ก, ๋ชจ๋ธ๋ค์ด
-
๋ฌธ์ ์ ํด๊ฒฐ
.decode(type: ๋ชจ๋ธํ์ ๋ช , from: api๋ฐ์ดํฐ)
์ โ๋ชจ๋ธ ํ์ ๋ช โ- ํ์
๋ช
์ ๋ฌ๋ฆฌ ํ๊ธฐ ์ํด ๋ฉ์๋๋ ํ์
์ ๋(ํ์ฅ์ฑ์ ๊ณ ๋ คํ๋ฉด ๋ ์ด์) ๋ง๋ค๊ฑฐ๋ ๋งค๊ฐ๋ณ์๋ก
weatherRange
๋ฅผ ๋ฃ์ด์ค์ผ ํ์ Decodable
์ ์ฑํํ๋ฉฐ weatherRangeํ์ ์์ฑ์ ์๊ตฌํ๋whetherComposable
ํ๋กํ ์ฝ์ ์๋ก ์ ์ํ์ฌ, JSON๋ฐ์ดํฐ๋ฅผ ๋ฐ์์ฌ ์ฃผ์ ๋ชจ๋ธ 2๊ฐ๊ฐ ์ค์ํ๋๋ก ํจWeatherParser
ํ์ ์ ์ ๋ค๋ฆญ(<T: WheterComposable>
)์ ์ ์ฉํ์ฌT.self
๋ก โํ์ ๋ช โ์ ๋ฐ์์ฌ ์ ์๋๋ก ํจ
- ํ์
๋ช
์ ๋ฌ๋ฆฌ ํ๊ธฐ ์ํด ๋ฉ์๋๋ ํ์
์ ๋(ํ์ฅ์ฑ์ ๊ณ ๋ คํ๋ฉด ๋ ์ด์) ๋ง๋ค๊ฑฐ๋ ๋งค๊ฐ๋ณ์๋ก
๐๏ธใ์ฐธ๊ณ ํ ๊ณต์๋ฌธ์: CodingKey
- ํ์ต ๋ด์ฉ
- JSON data์ key์ ๋ชจ๋ธ์ ํ๋กํผํฐ ๋ค์ด๋ฐ์ ๋ค๋ฅด๊ฒ ์ฐ๊ณ ์ถ์ ๊ฒฝ์ฐ, ์ธ์ฝ๋ฉ&๋์ฝ๋ฉ ๊ณผ์ ์์ ๋์ ๋งค์นญํด์ฃผ๋ โํ๋กํ ์ฝโ
- ๋ณดํต ํด๋น ๋ชจ๋ธ ๋ด๋ถ์ ์ค์ฒฉ์ด๊ฑฐํ์ผ๋ก ์ ์ธํด์ ์ฐ๋ฉฐ, ๋ชจ๋ธ ๋ด ๋ชจ๋ ํ๋กํผํฐ์ ๋ํ case๋ฅผ ์์ฑํด์ค์ผ ํจ
- ์ ์ฉ ๊ณผ์
- ๋ฐ์์จ ๋ฐ์ดํฐ๋ฅผ ๊ทธ๋๋ก ์ฐ๊ธฐ์๋ ๋ค์ด๋ฐ ๊ฐ์ด๋๋ผ์ธ์ ์๋ฐฐ๋๋ ๋ถ๋ถ์ด ๋ง์์ โ ๊ณ ์ณ์ค์ผ ํด์ ์ธ ์๋ฐ์ ์์์
- ๋ฌธ์ ์ ํด๊ฒฐ
- ๋ชจ๋ธ์ ํ๋กํผํฐ ์ค JSON Data์ key์ ์ผ์นํ๋ ํญ๋ชฉ์ด ์๋ ๊ฒฝ์ฐ decoding ๊ณผ์ ์์ error๊ฐ ๋ฐ์ํ์์
- ViewController์
ViewDidLoad()
๋ฉ์๋๋ฅผ ํ์ฉํ์ง ์๊ณ LLDB๋ฅผ ํตํด ๋๋ฒ๊น ์ ์๋ํ์๊ณ ๊ทธ ๊ณผ์ ์์p data
๋ฅผ ์คํํ๋ ๊ฒฝ์ฐ ์๋์ ๊ฐ์ ์๋ฌ ๋ฐ์error: expression failed to parse: warning: <EXPR>:11:7: warning: initialization of variable '$__lldb_error_result' was never used; consider replacing with assignment to '_' or removing it var $__lldb_error_result = __lldb_tmp_error ~~~~^~~~~~~~~~~~~~~~~~~~ _ error: <EXPR>:19:5: error: cannot find '$__lldb_injected_self' in scope $__lldb_injected_self.$__lldb_wrapped_expr_15( ^~~~~~~~~~~~~~~~~~~~~
- ๊ณ ๋ฏผ ๋ฐ ๊ฒ์ํด ๋ณธ ๊ฒฐ๊ณผ lldb ๋๋ฒ๊ฑฐ๊ฐ ์ ๋ค๋ฆญ์ ํ์ฉํ๋ ๋ถ๋ถ์ธ
T.self
๋ฅผ ์ถ๋ก ํ์ง ๋ชปํด์ ์๊ธฐ๋ ๋ฌธ์ ๋ผ๊ณ ํ๋จ! - LLDB๋ฅผ ํตํด ๋๋ฒ๊น ํ๋ ๊ณผ์ ์ ์ถ๊ฐ ํ์ตํ๋๋ก ํ๊ณ , ์ฐ์ ์ ์ผ๋ก ์ ์ ์๋๋์์ ๋์ components๋ค๊ณผ ์ค๋ฅ๊ฐ ๋ฐ์ํ์ ์์ ์ components๋ค๊ณผ ๋น๊ตํ์ฌ ์ค๋ฅ๊ฐ ๋ฐ์ํ๋ ๋ถ๋ถ์ ์ฐพ์ ์์ ํ ์ ์์์
๐๏ธใ์ฐธ๊ณ ํ ๊ณต์๋ฌธ์:
-
ํ์ต ๋ด์ฉ
- Core Location์ ์ฌ์ฉํ๊ธฐ ์ํด์๋
CoreLocation
ํ๋ ์์ํฌ๋ฅผ importํด์ผ ํจ - Core Location์ ์ฅ์น์ ์ง๋ฆฌ์ ์์น์ ๋ฐฉํฅ์ ์ป๋ ๊ฒ์ผ๋ก
CLLocationManager
ํด๋์ค์ ์ธ์คํด์ค๋ก Core Location ์๋น์ค๋ฅผ ๊ตฌ์ฑํ๊ณ ์ฌ์ฉํ๊ณ ์ค์ง์ํฌ ์ ์์ - Core Location์ผ๋ก ์ ์ ์๋ ์ ๋ณด
- ์์น ์ ๋ฐ์ดํธ
- ์ง์ญ ๋ชจ๋ํฐ๋ง
- iBeacon ๊ฐ์ง ๋ฐ ์ฐพ๊ธฐ
- ๋์นจ๋ฐ์ ๋ฐฉํฅ
- Core Location์ ์ฌ์ฉํ๊ธฐ ์ํด์๋ ์น์ธ์ ์์ฒญํด์ผ ํจ
- ์น์ธ ๋ณ๊ฒฝ์ ๋น๋กฏํ ์ด๋ฒคํธ๋
CLLocationManagerDelegate
ํ๋กํ ์ฝ์ ์ค์ํ๋ ๊ฐ์ฒด์์ ์์
- ์น์ธ ๋ณ๊ฒฝ์ ๋น๋กฏํ ์ด๋ฒคํธ๋
CLLocationManager
์ธ์คํด์ค๊ฐ ํ ๋น๋๋ฉด ์์คํ ์ด delegate์locationManagerDidChangeAuthorization(_:)
๋ฉ์๋์ ์ฑ์ ์น์ธ ์ํ๋ฅผ ๋ณด๊ณ ํจ- ๊ทธ๋ ๊ธฐ ๋๋ฌธ์ manager๊ฐ ๊ตฌ์ฑ๋๋ ์์ ์ delegate๋ฅผ ์ฆ์ ํ ๋นํด์ผ ํจ
- ์์น ์๋น์ค ๊ถํ
- When In Use์ Always๊ฐ ์์
- ๊ณต์๋ฌธ์์์๋ ๊ฐ๋ฅํ๋ฉด When In Use๋ง ์ฌ์ฉํ๋ ๊ฒ์ ๊ถ์ฅ
- ์์น ์ ๋ณด๋ ๋ฏผ๊ฐํ ๊ฐ์ธ์ ๋ณด์ด๊ธฐ ๋๋ฌธ์ ์ฌ์ฉ์์๊ฒ ์์น ์ฌ์ฉ์ ๋ํ ์ค๋ช ์ด ํ์ํจ
- Core Location์ ์ฌ์ฉํ๊ธฐ ์ํด์๋
-
์ ์ฉ ๊ณผ์
- ์๋ฎฌ๋ ์ดํฐ์ ์ปค์คํ ์ผ๋ก ์ค์ ํด ๋ ํ์ฌ ์์น ๋ฐ์์ค๊ธฐ
-
๋ฌธ์ ์ ํด๊ฒฐ
๋ฌธ์ ์ ํด๊ฒฐ ๋ด์ฉ ๋ฌธ์ ViewController์ viewDidLoad()
๋ฉ์๋ ๋ด๋ถ์locationManager.requestLocation()
๋ฅผ ํธ์ถํ๋ ๊ฒฝ์ฐlocationManager(didFailWithError:)
๊ฐ ํธ์ถ๋๋ ๋ฌธ์ ํด๊ฒฐ ํ์ต ๋ด์ฉ์ฒ๋ผ CLLocationManager ํ ๋น ์ ๊ถํ์ ํ์ธํ๋ ๋ฉ์๋๊ฐ ํธ์ถ๋๋ฏ๋ก, ์ฌ์ฉ์์๊ฒ ๊ถํ ์์ฒญ์ ํ๊ธฐ ์ ์ ์์น ์ ๋ณด๋ฅผ ์์ฒญํ๊ฒ ๋จ! ์ด๋ก ์ธํด location์ ๋ฐ์์ฌ ์ ์์ด์ error handling ๊ด๋ จ ๋ฉ์๋๊ฐ ํธ์ถ๋จ!
โญ๏ธ๊ถํ์ ํ์ธํ๋ ๋ฉ์๋ ๋ด๋ถ์์๋ง location์ ํธ์ถํ๋๋ก ๋ฆฌํฉํ ๋ง -
์์ฌ์ด ์ ์ ๋ ฅ ์ฌ์ฉ์ ์ต์ ํ ํ ์ ์๋ ์ค์ ์ ๋ํ ํ์ต์ ์ถ๊ฐ๋ก ์งํํ์ง ๋ชปํด์ ์์ฌ์ ์ง๋ง, STEP 2-2์์ ํจ๊ป ํ์ต ํ ๋ฐ์ํ๊ธฐ๋ก ํจ!
๐๏ธใ์ฐธ๊ณ ํ ๊ณต์๋ฌธ์:
- ํ์ต ๋ด์ฉ
URLComponents
์ธ์คํด์ค๋URL?
ํ์ ํ๋กํผํฐ๋ฅผ ๊ฐ์งURLQueryItem
์ key, value ํํ๋ก ์์ฑpath
์์ฑ์ String์ append,queryItems
์ [URLQueryItem
]์ ํ ๋น ํน์ appendํด์ฃผ๋ฉด ์๋์ผ๋ก url์ ์๋ง์ ์์์ผ๋ก ์ถ๊ฐ๋จ
- ์ ์ฉ ๊ณผ์
- ์๋ ์ด์ ๋ก URLComponents๋ฅผ ์ฌ์ฉํ๋๋ก ๋ฆฌํํ ๋ง์ ๋์
- ๊ธฐ์กด์ ๋นํด ๋ฌธ์์ด ๊ด๋ จ ์ฐ์ฐ์ ์ค์ด๊ณ ๊ธฐ๋ณธ์ ๊ณต ํ์ ์ ํ์ฉํ๊ณ ์ ํจ,
- URL์ ๊ตฌ์ฑ์์์ ๋ณด๋ค ๊ตฌ์กฐ์ ์ผ๋ก ์ ๊ทผํ๊ณ ํ์ฉํ ์ ์๊ฒ ๋ค๋ ์ฅ์ ์ ๊ณ ๋ ค
- ์ ์ฉ ๋ฐฉ๋ฒ
baseURL
์ ๊ธฐ๋ฐ์ผ๋ก URLComponents ์ธ์คํด์ค๋ฅผ ๋ง๋ค์ด ํ์ํpath
,query
๋งค๊ฐ๋ณ์๋ค์ ์ถ๊ฐยทํ ๋น- ์์ฑ๋ ์ธ์คํด์ค์ url์ ์ต์
๋๋ฐ์ธ๋ฉํ์ฌ ์๋ฌ๋ฅผ ๋์ง๊ฑฐ๋ url(
URL
ํ์ )์ ๋ฐํ
- ์๋ ์ด์ ๋ก URLComponents๋ฅผ ์ฌ์ฉํ๋๋ก ๋ฆฌํํ ๋ง์ ๋์
- ๋ฌธ์ ์ ํด๊ฒฐ
๋ฌธ์ ์ ํด๊ฒฐ ๋ด์ฉ ๊ธฐ์กด URLComponents์ธ์คํด์ค๋ฅผ static ํ๋กํผํฐ๋ก ์ ์ธ, path๋ ํด๋น ์ธ์คํด์ค.path.append("String")
ํด์ฃผ๋ ์์ผ๋ก ๊ตฌํ๋ฌธ์ static ํ๋กํผํฐ๋ค ๋ณด๋, WeatherParser.make(at:weatherRange:)
๋ฉ์๋๊ฐ ํธ์ถ๋ ๋๋ง๋ค path๊ฐ ๋ฐ๋์ง ์๊ณ ๋ง๋ถ์ฌ์ง๋(append) ๋ฌธ์ ํด๊ฒฐ static ํ๋กํผํฐ๋ก๋ URLComponents ์์ฑ์์ ํ์ํ baseURL
(String) ํํ๋ง ์ ์ฅ, ๋ฉ์๋ body ๋ด์์ URLComponents ์ธ์คํด์ค๋ฅผ ์์ฑํ์ฌ ์ฐ๋๋ก ์์
๐๏ธใ์ฐธ๊ณ ํ ๊ณต์๋ฌธ์:
-
ํ์ต ๋ด์ฉ
- 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๊ฐThe default HTTP method is โGETโ.
- 'HTTP GET ๋ฉ์๋ ๋ช
์์ ํธ์ถ'์ด ์๊ตฌ์ฌํญ์ด๋ผ ์๋์ ๊ฐ์ด setํด์ฃผ๋ ์ฝ๋๋ฅผ ์ถ๊ฐํด์ฃผ๊ธด ํ์ง๋ง, ์๋ ์์ฌ์ด ์ ๊ณผ ๋๋ถ์ด '๋ช
์์ ํธ์ถ'์ ์ ๋๋ก ๊ตฌํํ ๊ฒ ๋ง๋๊ฐ์ ๋ํ ์๋ฌธ์ด ๋ฆ
request.httpMethod = "GET"
- ๋ฌธ์์ ๋ฐ๋ฅด๋ฉด
-
์์ฌ์ด ์
- ๋ฌธ์์์ ์ ์ ์๋ค์ํผ String? ํ์ ์ด๋ผ String("GET") ๋ฆฌํฐ๋ด๊ฐ์ ์ง์ ๋ฃ์ด์ค์ผ ํ์
- ํด๋จผ์๋ฌ๊ฐ ๋ฐ์ํ๊ธฐ ์ฌ์ด ๋ถ๋ถ์ด๋ผ๊ณ ์๊ฐ๋๋๋ฐ ์๋ ์ด๋ ๊ฒ ์ฌ์ฉํ๋ ๊ฒ ๋ง๋ ๊ฑด์ง, ๋์น ๋ถ๋ถ์ด ์๋์ง ๊ถ๊ธํจ
๐๏ธใ์ฐธ๊ณ ํ ๊ณต์๋ฌธ์:
- ํ์ต ๋ด์ฉ
- 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.
๊ฑฐ๋ฆฌ ์ฃผ์(๋๋ก๋ช ์ฃผ์์ ~๋ก)subThroughfare
Additional street-level information for the placemark.
์ถ๊ฐ ๊ฑฐ๋ฆฌ์์ค ์ ๋ณด(์์ธ์ฃผ์)locality
The city associated with the placemark.
๋์('์'๋ก ๋๋๋ ํ์ ๊ตฌ์ญ)subLocality
Additional city-level information for the placemark.
์ถ๊ฐ ๋์์์ค ์ ๋ณด(๋/๋ฉด/~๋ก)adminstrativeArea
The state or province associated with the placemark.
์ฃผ ํน์ ์ง๋ฐฉ ์ ๋ณด(ํ์ ๊ตฌ์ญ ์ค ๊ฐ์ฅ ๋์ ๋ฒ์, ๋/ํน๋ณ์/๊ด์ญ์)subAdminstrativeArea
Additional administrative area information for the placemark.
์ถ๊ฐ ํ์ ๊ตฌ์ญ ์ ๋ณด(ํ์ ๊ตฌ์ญ ์ค ๊ตฐ)postalCode
The postal code associated with the placemark.
์ฐํธ๋ฒํธcountry
The name of the country or region associated with the placemark.
๊ตญ๊ฐ๋ชname
The name of the placemark.
placemark์ ์ด๋ฆ(๋ณดํต throughfare + subThroughfare)
- CLGeocoder
- ์ ์ฉ ๊ณผ์
- CLLocationManager์ผ๋ก ๊ฐ์ ธ์จ CLLocation ํ์ ์ location์ผ๋ก reverse geocoding ์ ์งํ
- ๋ฌธ์ ์ ํด๊ฒฐ
๋ฌธ์ ์ ํด๊ฒฐ ๋ด์ฉ ๋ฌธ์ ๊ธฐ์กด์ Coustom Location์ผ๋ก ์ง์ ํ ์ขํ(37.53, 126.96)๋ฅผ ๊ธฐ์ค์ผ๋ก ์ฃผ์๋ฅผ ๊ฐ์ ธ์ค๋ ๊ฒฝ์ฐ '๊ตฌ'์ ํด๋นํ๋ '์ฉ์ฐ๊ตฌ'๋ฅผ ๋ถ๋ฌ์ค๋ ํ๋กํผํฐ๊ฐ ์์ ํด๊ฒฐ ํด๊ฒฐ์ค!! ์ธ๋ถ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ์ ์ฝ๋ ์ํฉ์ด๋ผ ์ถ๋ ฅ๋ ์ ๋ณด๋ฅผ ๊ฐ์ง๊ณ ๊ฐ๊ณตํด์ผ ํ๋์ง ๋ฐฉ๋ฒ์ ์ฐพ์๋ณด๋ ์ค
๐๏ธใ์ฐธ๊ณ ํ ๊ณต์๋ฌธ์:
- ํ์ต ๋ด์ฉ
UICollectionViewCompositionalLayout
- Collection View ๋ ์ด์์์ ํ ์ข ๋ฅ
- ์ ์์ฑ์ด ๋๊ณ ์ ์ฐํ ๋ฐฐ์ด๋ก ์์ดํ ์ ๊ฒฐํฉํ ์ ์๋ ๋ ์ด์์ ๊ฐ์ฒด
list(using:)
๋ฉ์๋ ์ฌ์ฉ ์ ์ง์ ๋ ๊ตฌ์ฑ์ list ์น์ ๋ง ํฌํจํ๋ ๋ ์ด์์์ ๊ตฌ์ฑ- ์ ๋ฉ์๋๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํด์๋
UICollectionLayoutListConfiguration
์ผ๋ก layout์ ๊ตฌ์ฑํด ์ฃผ์ด์ผ ํจ
UICollectionLayoutListConfiguration
- list์ header์ footer๋ฅผ ์ค์ ํ๊ธฐ ์ํด ํ์ํ ๊ตฌ์กฐ์ฒด
headerMode
,footerMode
ํ๋กํผํฐ๋ฅผ .supplementary๋ก ์ค์ ํ์ฌ ๋ณด์กฐ view๋ฅผ ์ฌ์ฉํ์ฌ header, footer ํ์ ๊ฐ๋ฅ- ์ ํ๋กํผํฐ๋ค์ .none์ด ๊ธฐ๋ณธ๊ฐ,
headerMode
์ ๊ฒฝ์ฐ .firstItemInSection์ผ๋ก Section ๋ด์ ์ฒซ ๋ฒ์งธ ์์ดํ ์ ํค๋๋ก ์ฌ์ฉํ ์ ์์ backgroundColor
๋ ๋ฐฐ๊ฒฝ์์ ์์ ํ ์์ ๊ธฐ ์ํ ํ๋กํผํฐ- ๊ธฐ๋ณธ ๊ฐ์ nil์ด์ง๋ง, ์ด๋ system background color๋ฅผ ์ฌ์ฉํ ๊ฒ โ ์ฐ๋ฆฌ ํ๋ก์ ํธ์์๋ white๋ก ์ง์ ๋จ
- appearance๋ก list์ ๋ชจ์์ ์ง์ ํด์ค ์ ์์
UICollectionViewListCell
- list ๊ธฐ๋ฅ๊ณผ ๊ธฐ๋ณธ ์คํ์ผ์ ์ฌ์ฉํ๊ธฐ ์ํด ์ฌ์ฉ๋๋ Collection View cell ํด๋์ค
- list์ ์ ์ก์ธ์๋ฆฌ๋ ์ํธ์์ฉ ๋์ ๋ฑ์ ์ง์ํ๋ ํ์
UIBackgroundConfiguration
- View์ ๋ํด ๋ฐฐ๊ฒฝ์ ๊ตฌ์ฑํ๋ ํ์
- UIButton์ ์ง์ ์ ์ฉํ๊ฑฐ๋ UICollectionView/UITableView์ cell, header, footer์ ์ ์ฉํ ์ ์์
- ์ ์ฉ ๊ณผ์
- FlowLayout์์ CompositionalLayout์ผ๋ก ๋ฆฌํฉํ ๋งํ๋ ๊ณผ์ ์์
UICollectionViewCell
๋์UICollectionViewListCell
์ผ๋ก ๋์ฒดํ๋ ค๊ณ ํ์์ผ๋ ํ์ฌ ํ๋ก์ ํธ ๋ด์์๋ list์ ๊ธฐ๋ฅ์ ์ฌ์ฉํ ์ผ์ด ์์ผ๋ฏ๋ก ํ์ต๋ง ์งํ
- FlowLayout์์ CompositionalLayout์ผ๋ก ๋ฆฌํฉํ ๋งํ๋ ๊ณผ์ ์์
- ๋ฌธ์ ์ ํด๊ฒฐ
- View์ backgroundColor๋ฅผ .clear๋ก ์ค์ ํ์์ผ๋ ๋ฐฐ๊ฒฝ์์ด ์ฌ๋ผ์ง์ง ์๋ ๋ฌธ์ ๋ฐ์
- View๋ฅผ ๊ตฌ์ฑํ๋ configuration์ backgroundColor๋ฅผ .clear๋ก ํด์ฃผ์ด์ผ ๋ฐฐ๊ฒฝ์์ด ์ฌ๋ผ์ง
- ์์ฌ์ด ์
defaultContentConfiguration()
์ ํ์ฉํ์ฌ ์ ์ ๊ตฌ์ฑํด๋ณด์ง ๋ชปํ ๊ฒ์ด ์กฐ๊ธ ์์ฌ์
๐๏ธใ์ฐธ๊ณ ํ ๊ณต์๋ฌธ์:
-
์ ์ฉ ๊ณผ์
- ๊ธฐ์กด) ๋ ์จ ๋ฐ์ดํฐ/์์ด์ฝ ์ค ๋ฌด์์ ๋ถ๋ฌ์ค๊ธฐ ์ํ url์ด๋์ ๋ฐ๋ผ URL ๊ตฌ์ฑ์์๊ฐ ๋ฌ๋ผ์ ธ ๋งค๊ฐ๋ณ์๊ฐ ๋ค๋ฅธ ๋ฉ์๋๋ฅผ ์ฌ๋ฟ ๊ตฌํํ๋ ๊ณผ์ ์์ ์ค๋ณตํํ์ด ๋ค์ ๋ฐ์
- ์์ )
- ๊ธฐ์กด์๋ path, queryItems ํ๋กํผํฐ๋ง ํ์ฉํ์ง๋ง, ์ด๋ฒ์๋ scheme, host ๋ฑ ๋ค๋ฅธ url์์๋ ์ ๊ทน์ ์ผ๋ก ๋ค๋ค๋ณด๊ธฐ๋ก ํจ
- ๋ฐ์ดํฐ/์์ด์ฝ์ ๋ถ๋ฌ์ค๊ธฐ ์ํ ๋ฉ์๋ ๊ฐ๊ฐ์์ path, queryItems๋ฅผ ์ง์ ํ ๋นํด์คฌ๋ ๊ธฐ์กด ์ฝ๋๊ฐ OCP์ ์ข์ง ์๋ค๊ณ ํ๋จ, ๋ถ๋ฌ์ฌ ํ์ ์ ๋ฐ๋ผ ์ฌ๋ฌ ๊ฐ์ง url์์๋ค(scheme, host, path, query ๋ฑ)์ ๊ณ์ฐ์์ฑ์ผ๋ก ์๋ ค์ฃผ๋ WeatherRouter ์ด๊ฑฐํ์ ๊ตฌํ
- URL ๋ฐ URLRequest๋ฅผ ๋ง๋๋ ๊ธฐ๋ฅ์ ์ฐ๊ด์ฑ์ด ๊น์ WeatherRouter์ ๋งก๊ธฐ๊ณ , ์ค์ ๋ก ๋ฐ์ดํฐ๋ฅผ ๋ฐ์์ค๋ ๊ธฐ๋ฅ๋ง WeatherParser์ ๊ตฌํ
-
๋ฌธ์ ์ ํด๊ฒฐ
ํธ๋ฌ๋ธ์ํ A ์ ๋ค๋ฆญํ์ ๋ช ์ ๋ฌธ์ ๐ฐ - ๋ถ๋ฌ์ฌ ํ์ ์ ๋ฐ๋ฅธ ์ค๋ณต๋ก์ง์ ์ต๋ํ ํตํฉํ๋ ค๊ณ ํ์ผ๋, ์ด๋๊น์ง๋ url์์ฑ ๋ฐ ๋ณํ์ ์ํ ์ ๋ณด๋ฅผ ๋งค๊ฐ๋ณ์๋ฅผ ํตํด ์ ๋ฌํด์ค์ผ ํ๋ฏ๋ก ์ ๋ค๋ฆญํ์ ๊ด๋ จ ๋ฌธ์ ์ ์ด ๋ฐ์
- WeatherParser์์ ๋ ์จ๋ฐ์ดํฐ๊ฐ ์๋ ๋ ์จ์์ด์ฝ์ parseํ๋ ๋ฉ์๋๋ WeatherParser์ ์ ๋ค๋ฆญํ์ T์ ์ ๋ณด๋ฅผ ํ์๋ก ํ์ง ์์์๋ ํธ์ถ๋ถ์์ ์ ๋ค๋ฆญ ํ์ ์ ๋ฃ์ด์ค์ผ ํ์ผ๋ฏ๋ก ๋ถํ์&์ ์ ์น ์์ ๋น์ฉ์ ๋ฐ์์ํด๐ - WeatherParserํ์ ์ด ์๋, ๋ ์จ๋ฐ์ดํฐ๋ฅผ ๋ถ๋ฌ์ค๋ ๋ฉ์๋์๋ง ๋จ๋ ์ผ๋ก ์ ๋ค๋ฆญํ์ ์ ๋ถ์ด๊ธฐ๋ก ํจ ํธ๋ฌ๋ธ์ํ B ์ ๋ค๋ฆญํ์ ์ถ๋ก ๋ฌธ์ ๐ฐ - ์ ๋ค๋ฆญ ๋ฉ์๋์ ํธ์ถ๋ถ์์ ์ ๋ค๋ฆญํ์ ์ ์ถ๋ก ํ๊ธฐ ์ํ ๋จ์๋ฅผ ์๊ตฌ
- ๋ฉ์๋์ ๋ฐํํ์ ๋ด์ ์์์ ํ์ ์ ๋ช ์ํ๋ ค ํ์ผ๋, ํ์ ์ธ์์ด ๋์ด๋๊ณ ์ด๋ฌํ ์ ์์ฌํญ์ ๊ณต์ ๊ฐ ํ๋ฐํ์ง ์๋ค๋ฉด ์ด๋ฅผ ๋์ณ ํด๋จผ์๋ฌ๊ฐ ๋ฐ์ํ ์ฌ์ง๊ฐ ํฌ๋ค๋ ์ฐ๋ ค ๋ฐ์๐ - ์ ๋ค๋ฆญํ์ T์ ์ถ๋ก ์ ์ํ ๋จ์( T.Type
)๋ฅผ ํด๋น ๋ฉ์๋์ ๋งค๊ฐ๋ณ์๋ก ๋ฐ๋๋ก ๊ฐ์ ํจ์ผ๋ก์จ ์์ ์ฐ๋ ค๋ฅผ ํด๊ฒฐ -
์์ฌ์ด ์
- host ํ๋กํผํฐ์ ๊ฒฝ์ฐ ๋งจ์์ "api." ์ธ์๋ ๋ชจ๋ ๋์ผํจ
- ์๋ 3๊ฐ์ง๋ฅผ ๊ณ ๋ฏผํ๋ค๊ฐ 3๋ฒ์ ํํ์ง๋ง, ์ฌ์ ํ ์ค๋ณตํํ์ด ๋ง์ ์ข์ ๋ฐฉ๋ฒ์ธ์ง ํ์ ์ด ์์ง ์์
- 'api.'๋ฅผ ์ ์ธํ ๋ถ๋ถ(openweathermap.org)์ ๊ณตํต์์๋ก ์ ์ธ ํ, ํ์ชฝ์๋ง 'api.'๋ฅผ ๋ถ์ฌ host์ ํ ๋นํ๋ ๋ฐฉ๋ฒ,
subhost: String
๊ณ์ฐ์์ฑ์ ๋ง๋ค์ด ํ์ชฝ์ "api.", ํ์ชฝ์ ""๋ฅผ ๋ฃ์ ํ host = subhost + host ํด์ฃผ๋ ๋ฐฉ๋ฒ,- ํ์ชฝ์ "api.open
org", ํ์ชฝ์ "openorg"์ host์ ํ ๋นํ๋ ๋ฐฉ๋ฒ
๐๏ธใ์ฐธ๊ณ ํ ๊ณต์๋ฌธ์:
- ํ์ต ๋ด์ฉ
UIRefreshControl
์ธ์คํด์ค์addTarget(_:action:for:)
๋ก action method๋ฅผ ๋ํด์ฃผ๋ฉด target์ refreshControl์ beginRefreshing์ ๊ฐ์งํ๊ณ controlEvents๋ฅผ ์ํด selector์์ ๋ฃ์ด ๋ objc๋ฉ์๋๋ฅผ ์คํํจUICollectionView
์ธ์คํด์ค๋UIRefreshControl?
ํ์ ์refreshControl
ํ๋กํผํฐ๋ฅผ ๊ฐ์ง (๋ฐ๋ผ์ ๊ธฐ๋ณธ๊ฐ์ด nil์ด๋ฏ๋ก ์๋ก์ด UIRefreshControl ์ธ์คํด์ค๋ฅผ ๋ง๋ค์ด addTargetํ ํ ํ ๋นํด์ค์ผ ํจ)
- ์ ์ฉ ๊ณผ์
configureRefreshControl()
๋ฉ์๋ ๋ฐ objc๋ฉ์๋refreshCollectionView()
๋ฅผ ViewController์ ๊ตฌํ