# ๐ ์คํ ๋ง์ผ
## ๋ชฉ์ฐจ
* [Project Storage](#-project-storage)
* [Team](#-team)
* [Run screen](#-run-screen)
* [Development Environment and Library](#-development-environment-and-library)
* [Timeline](#-timeline)
* [week1](#week-1)
* [week2](#week-2)
* [week3](#week-3)
* [week4](#week-4)
* [Project Contents](#project-contents)
* [Core Feature Experience](#-core-feature-experience)
* [TroubleShooting](#-troubleshooting)
* [Reference page](#reference-page)
## ๐พ Project Storage
>**ํ๋ก์ ํธ ๊ธฐ๊ฐ** : 2022-07-11 ~ 2022-08-05<br>
**์๊ฐ** : ๋คํธ์ํฌ ํต์ ์ ํตํด ์ํ API๋ฅผ ๊ฐ์ ธ์ ๋ฌผ๊ฑด์ ๋งค๋งคํ๋ ์ฑ์
๋๋ค. <br>
**๋ฆฌ๋ทฐ์ด** : [**๋ผ์ด์ธ**](https://github.com/ryan-son)
## ๐ฅ Team
| [ํ์ด](https://github.com/seohyeon2) | [์ธ์ฒด์ธ](https://github.com/unchain123) |
|:---:|:---:|
|<img src = "https://i.imgur.com/0UjNUFH.jpg" width="250" height="250">|<img src = "https://i.imgur.com/GlPnCo7.png" width="250" height="250">|
---
## ๐บ Run screen
### Home screen
| ListCollectionView | GridCollectionView |
|:---:|:---:|
|<img src = https://i.imgur.com/SBqTBAk.gif width=200 height=400>|<img src = https://i.imgur.com/op5su98.gif width=200 height=400>|
### Product registration screen
| ์ํ ๋ฑ๋ก ๊ณผ์ | ์ํ ๋ฑ๋ก ์ฑ๊ณต | ์ํ ๋ฑ๋ก ์คํจ |
|:---:|:---:|:---:|
|<img src = https://i.imgur.com/YjuWno2.gif width=200 height=400>|<img src = https://i.imgur.com/XVGljW8.png width=200 height=400>|<img src = https://i.imgur.com/1tiOGeA.png width=200 height=400>|
## ๐ Development Environment and Library
[]()
[]()
[]()
---
## ๐ Timeline
### Week 1
- **2022-07-11 (์)**
- ์คํ๋ง์ผ I STEP1: URLSession์ ๋ํด์ ํ์
ํ๊ธฐ ์ํด ๊ณต๋ถ
- **2022-07-12 (ํ)**
- ์คํ๋ง์ผ I STEP1: STEP1 PR
- **2022-07-13 (์)**
- ์คํ๋ง์ผ I STEP1: URLSession์ ๋ํด ๋ค์ ๊ณต๋ถํ๊ณ CollectionView ๊ณต๋ถ
- **2022-07-14 (๋ชฉ)**
- ์คํ๋ง์ผ I STEP1: ๋ฆฌํฉํ ๋ง
- **2022-07-15 (๊ธ)**
- ์คํ๋ง์ผ I STEP1: Readme.md ์์ฑ ๋ฐ ๋ฆฌํฉํ ๋ง
### Week 2
- **2022-07-18 (์)**
- ์คํ๋ง์ผ I STEP2: ๋ฆฌํฉํ ๋ง
- **2022-07-19 (ํ)**
- ์คํ๋ง์ผ I STEP1: CollectionView ๊ณต๋ถ
- **2022-07-20 (์)**
- ์คํ๋ง์ผ I STEP2: List Collection View, Segmented Control ๊ตฌํ
- **2022-07-21 (๋ชฉ)**
- ์คํ๋ง์ผ I STEP2: ์คํ ๋ ์ด์์ ๋ฐ Grid ๊ตฌํ
- **2022-07-22 (๊ธ)**
- ์คํ๋ง์ผ I STEP2: Readme.md ์์ฑ ๋ฐ STEP2 PR
### Week 3
- **2022-07-25 (์)**
- ์คํ๋ง์ผ II STEP1: multipart/form-data ๊ตฌ์กฐ ๊ณต๋ถ ๋ฐ ์์ ์ฝ๋ ์์ฑ
- **2022-07-26 (ํ)**
- ์คํ๋ง์ผ I STEP1: ๋ฆฌํฉํ ๋ง
- **2022-07-27 (์)**
- ์คํ๋ง์ผ I STEP2: ๋ฆฌํฉํ ๋ง
- **2022-07-28 (๋ชฉ)**
- ์คํ๋ง์ผ II STEP1: http๋ฉ์๋ ๊ณต๋ถ๋ฐ POST ๋ฉ์๋ ๊ตฌํ
- **2022-07-29 (๊ธ)**
- ์คํ๋ง์ผ II STEP1: POST ๋ฉ์๋ ๊ตฌํ ๋ฐ ๋ ์ด์์ ๊ตฌํ
### Week 4
- **2022-08-01 (์)**
- ์คํ๋ง์ผ II STEP1: RegistrationViewController UI ๊ตฌํ
- **2022-08-02 (ํ)**
- ์คํ๋ง์ผ II STEP1: POST ๋ฉ์๋ ์์ ๋ฐ ํค๋ณด๋ ๊ตฌํ
- **2022-08-03 (์)**
- ์คํ๋ง์ผ II STEP2: STEP2์ ํ์ํ ๊ฐ๋
๊ณต๋ถ
- **2022-08-04 (๋ชฉ)**
- ์คํ๋ง์ผ II STEP1: ๋ฆฌํฉํ ๋ง
- **2022-08-05 (๊ธ)**
- ์คํ๋ง์ผ II STEP1: ๋ฆฌํฉํ ๋ง
- ์คํ๋ง์ผ II STEP2: RegistrationViewController UI ๋ฐ ๊ธฐ๋ฅ ๊ตฌํ
---
## โ๏ธ Project Contents
### ๐ป Core Feature Experience
- [x] UIAlertController ์ก์
์ completion handler ํ์ฉ
- [x] UIAlertController์ textFields ํ์ฉ
- [x] UICollectionView ๋ฅผ ํตํ ์ข์ฐ ์คํฌ๋กค ๊ธฐ๋ฅ ๊ตฌํ
---
### ๐ TroubleShooting
#### 1. Application Test VS Library Test
- ApplicationTest์ LibraryTest์ ์ฐจ์ด๋ ๊ทน๋ช
ํ๋ค.
- ApplicationTest๋ iOS์ฑ๊ณผ ๊ด๋ จ๋ ๋ถ๋ถ์ ๊ฒ์ฌํ ๋ ์ฃผ๋ก ์ฌ์ฉํ๋ค.
- LibraryTest๋ ์ฑ๊ณผ ์๊ด์๋ ๋ก์ง์ ํ
์คํธํ๊ธฐ ์ํด ์ฌ์ฉํ๋ค.
- ํธ์คํธ ์ฑ์ ์๋ฎฌ๋ ์ดํฐ์ ์ค์นํ ํ์๊ฐ ์์ด์ ํ
์คํธ๊ฐ ๋ ๋น ๋ฅด๊ณ ์ด๋ฐ๊ธ์ฉ ๋์์ด ๋ถ์์ ํ ์๋ฎฌ๋ ์ดํฐ์ ์ํฅ์ ๋๋ฐ๋๋ค.
- ์๋์ ๊ฐ์ด ๊ธฐ์กด์ ํ
์คํธ๋ฅผ ์งํํ์ ๋์ LivraryTest๋ก ๋ฐ๊ฟ์ ํ
์คํธ๋ฅผ ์งํํ์ ๋ ํ
์คํธ๋น ๊ฑธ๋ฆฌ๋ ์๊ฐ์ด ๊ฑฐ์ 10๋ฐฐ์ ๊ฐ๊น์ด ์ ์๋ฏธํ ๊ฒฐ๊ณผ๋ฅผ ์ป์ ์ ์์๋ค.
|Application Test ๊ฑธ๋ฆฐ์๊ฐ|Library Test ๊ฑธ๋ฆฐ์๊ฐ|
|--|--|
|<img src = https://i.imgur.com/onFx9QR.png width = 300 height = 100> |<img src = https://i.imgur.com/OZAEbUi.png width = 700 height = 100>|
#### 2. URLSession Unit Test
- ๋น๋๊ธฐ ํ
์คํธ ์, ์ฌ์ง๊ณผ ๊ฐ์ด XCTAssert ๋ฉ์๋๊ฐ ํธ์ถ์กฐ์ฐจ ๋์ง ์๊ณ ํ
์คํธ๊ฐ ๋๋ ๋ฒ๋ฆฐ๋ค.
- `expectation(description:), fulfill(), wait(for:timeout:` ์ฝ๋๋ฅผ ์ด์ฉํ์๋๋ ๋น๋๊ธฐ ์์
์ ๊ธฐ๋ค๋ฆฌ๊ฒ ๋์ด, ํ
์คํธ๊ฐ ๊ฐ๋ฅํ๊ฒ ๋์๋ค.

#### 3. ๋คํธ์ํฌ ๋งตํ๋ชจ๋ธ ํธ๋ฌ๋ธ
- ๋คํธ์ํฌ์์ ๋ง์ง๋ง ํ์ด์ง๊น์ง ๋ฐ์ดํฐ๋ฅผ ๋ฐ์์ค๋ ์ฌ๊ทํจ์๋ฅผ ๋ง๋ค์๋๋ฐ ๋ง์ง๋ง ํ์ด์ง๋ 137์ด์๋๋ฐ 72๋ฒ ํ์ด์ง์์ ์ฌ๊ทํจ์๊ฐ ํ์ถํ๋ ์ด์๊ฐ ๋ฐ์ํ๋ค.
- LLDB๋ฅผ ์ด์ฉํด ํจ์์ ๋ถ๊ธฐ๋ง๋ค ํ์ธ์ ํ์ ๋ 72๋ฒ์งธ ํ์ด์ง๋ฅผ ๋์ฝ๋ฉ ํ๋ ๊ณผ์ ์์ ๋งตํ์ ์คํจํ์ฌ ํจ์๋ฅผ ํ์ถํจ.
- ๋ฌธ์ ๊ฐ ์๊ธด ํค๊ฐ(price, bargainPrice, discountedPrice)์ด Double๊ฐ์ด ์๋๋ผ Int๋ก ๋ชจ๋ธ์ ๋ง๋ค์๊ธฐ ๋๋ฌธ์ Double๊ฐ์ ๋ํ๋ด๋ 72๋ฒ์งธ ํ์ด์ง์์๋ ๋งตํ์ ์คํจ ํ๋ ๊ฒ์ด์๋ค.
- ๋ฌธ์ ๊ฐ ์๋ ํค๊ฐ์ ํ์
์ Double๋ก ๋ฐ๊ฟ์ ํด๊ฒฐ ํ ์ ์์๋ค.
- ๋ง์ผ์ ์ํ๊ฐ๊ฒฉ๋ค์ด ํํ๋ฟ๋ง ์๋๋ผ USD๋ฑ ์ธํ๋ ํฌํจ์ด ๋์๊ธฐ ๋๋ฌธ์ Int๋ก ํ๋ ๊ฒ์ ์ ๋๋ก๋ ๋ชจ๋ธ๋ง์ด ์๋์๋ ๊ฒ ๊ฐ๋ค. ์ฌ์ํ ๋ถ๋ถ๋ ์ ํ์ธํด์ ์ด๋ฐ ์ค์๋ฅผ ํ์ง ์๋๋ก ํด์ผ ๊ฒ ๋ค.
| ๋คํธ์ํฌ ๋งตํ๋ชจ๋ธ | ์๋ฒ ์ ๋ณด | ํธ๋ฌ๋ธ ๊ฒฐ๊ณผ |
|:--:|:--:|:--:|
|<img src = https://i.imgur.com/x9fe0O9.png width = 180 height = 60> |<img src = https://i.imgur.com/3BQxRVi.png width = 500 height = 200>|<img src = https://i.imgur.com/MoPV79O.png width = 800 height = 200>|
#### 4. ๋ฆฌ์คํธ ํ์์ collectionview์์ ์ด๋ฏธ์ง์ ํฌ๊ธฐ๊ฐ ์์์ง๋ ํ์
- ์ฒ์ UICollectionView์ Listํ์๋ ์ด์์์ ์ก์ ๋ ์๋์ ๊ฐ์ด apperance๋ฅผ ์ค์ ํด ์คฌ๋ค.
```swift
let config = UICollectionLayoutListConfiguration(appearance: .plain)
//์ฒ์์ค์
imageStackView.widthAnchor.constraint(lessThanOrEqualToConstant: 80),
imageStackView.heightAnchor.constraint(lessThanOrEqualToConstant: 80)
//๋ณ๊ฒฝํด๋ณธ์ค์
imageStackView.widthAnchor.constraint(equalToConstant: 80),
imageStackView.heightAnchor.constraint(equalToConstant: 80)
```
- ๊ทธ๋ฌ๋๋ ์ฒ์์ ์๋์ ์ฌ์ง๊ณผ ๊ฐ์ด ์ฌ์ง์ด ์๊ฒ ํํ๋๋ ์
๋ค์ด ์์๊ณ ์ด ์์ธ์ด lessThanOrEqual์ด๋ผ๊ณ ํ๊ธฐ ๋๋ฌธ์ ์์์ ๋ฒ๋ฆฌ๋๊ฑฐ๋ผ๊ณ ์๊ฐํด์ equalToConstant๋ก ๋ณ๊ฒฝ์ ํ๋๋ ์๋์ ๊ฐ์ด Autolayout์์ ์ถฉ๋์ด ์ผ์ด๋๋ ๊ฒ์ ํ์ธ ํ ์ ์์๋ค.
| ์ถฉ๋ ์์ธ |
|:--:|
|<img src = https://i.imgur.com/LwSy5Os.png width = 600 height = 150>|
| ์ถฉ๋ ํ๋ฉด |
|<img src = https://i.imgur.com/rfAzEsn.png width = 250 height = 500>|
- ์ฐ๋ฆฌ๊ฐ ํ์ธํ ์ถฉ๋ ์์ธ์ `UICollectionLayoutListConfiguration(appearance: .plain)`์ด ๋ด๋ถ์ ์ผ๋ก ๋์ด๋ฅผ 44๋ก ์ค์ ํด์ฃผ๊ณ ์๋ค๋ ๊ฒ์ด์๋ค. ๊ทธ๋์ ์ฐ๋ฆฌ๊ฐ ์ค์ ํด์ค heightAncor = 80 ๊ณผ๋ ์ถฉ๋์ ์ผ์ผ์ผฐ๊ณ ๋ ๊ฐ์ค์ ์ด๋ค ๊ฐ์ด ๋ง๋์ง ํ๋จํ์ง ๋ชปํ ์ปดํ์ผ๋ฌ๊ฐ ๋ ๊ฐ์ ๋ฌด์์๋ก ๋ด๋ณด๋ด๊ณ ์๋ค๊ณ ํ๋จํ๋ค.
- ์ฒ์์ผ๋ก ์๊ฐํ๋ ํด๊ฒฐ ๋ฐฉ๋ฒ์ ์ด๋ฏธ์ง์ ํฌ๊ธฐ์ Priority๋ฅผ ๋์ฌ์ ์
์ ํฌ๊ธฐ๊ฐ ์๋ ์ด๋ฏธ์ง์ ํฌ๊ธฐ๋ฅผ ๋ฐ์ํ๋๋ก ํ๊ฒ ํ๋ ๋ฐฉ๋ฒ ์ด์๋๋ฐ ์ด ๋ฐฉ๋ฒ์ ์ฌ์ฉํ๋ ์ด๋ฏธ์ง๋ฅผ ์ ์ธํ ๋ค๋ฅธ ๋ ์ด๋ธ๋ค์ ๋ฐ๋ ค๋๋ฒ๋ฆฌ๋ ํ์์ด ๋ฐ์ํ์ฌ ๋์์ ์ฐพ๊ฒ ๋์๋ค
- ์ต์ข
์ ์ผ๋ก ์ฐ๋ฆฌ๊ฐ ์ ํํ ๋ฐฉ๋ฒ์ ๋ด๋ถ์ ์ผ๋ก ์ ์ ์๋ ๊ฐ์ด ์ง์ ๋์ด์๋ `UICollectionViewCompositionalLayout.list`๊ฐ ์๋ `UICollectionViewCompositionalLayout(section: )`์ผ๋ก ๋ณ๊ฒฝํด์ ์ง์ collectionView์ item,group,section์ ์ฌ์ด์ฆ๋ฅผ ์ง์ ํด ์ฃผ๋ ๋ฐฉ๋ฒ ์ด์๋ค.
#### 5.snapshot apply ์์ ์ค๋ฅ
- ๊ธฐ์กด `snapshot`์ `apply` ์ ์ฉ์ ๋ฐ์ดํฐ๋ฅผ ๋ฐ์์ค๋ ์์ (`getProductList`ํธ์ถ ์)์๋ง ์งํ๋์๋ค.
๊ทธ๋ฌ๋๋ `getProductList` ๋ฉ์๋๋ก ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ค๋ ์๊ฐ ๋์์๋ `segmentedControl`๋ก layout ๋ณ๊ฒฝ์ด ๊ฐ๋ฅํ์ง๋ง,
๋ชจ๋ ๋ฐ์ดํฐ๋ฅผ ๋ฐ์์จ ํ๋ก๋ layout์ ๋ณ๊ฒฝํด ์ฃผ๋ฉด ์๋์ ๊ฐ์ด layout ์์ฒด๊ฐ ๋ ์๊ฐ๋ ํ์์ด ๋ฐ์ํ๋ค.
| ์ค๋ฅํ๋ฉด |
|:--:|
|<img src = https://i.imgur.com/tt55i4h.png width = 200 height = 300>|
- debug ์ฐฝ์ ํตํด layout์ด ๊นจ์ง๋ ์์ ๊ณผ `getProductList` ๋ฉ์๋์ escaping closer ์ข
๋ฃ ์์ ๊ณผ ๋์ผํ๋ค๋ ๊ฒ์ ์ ์ ์์๋ค.
์ด๋ฅผ ํตํด ๋ชจ๋ ๋ฐ์ดํฐ๊ฐ ๋ฐ์ ์จ ํ์๋ `apply` ์ ์ฉ์ ํด์ฃผ๋ฉด ๋๊ฒ ๋ค๋ ์์ด๋์ด๋ฅผ ์ป์ ์ ์์๊ณ ,
`segmentedControl`์์ ๋ฐ๊ฟ ๋์๋ `apply` ์ ์ฉ์ ํด์ฃผ์๋๋ layout ๊นจ์ง ํ์์ ํด๊ฒฐ ํ ์ ์์๋ค.
| ๊ธฐ์กด์ ์ฝ๋ | ํด๊ฒฐํ ์ฝ๋ |
| :--: | :--: |
|<img src = https://i.imgur.com/orryKJl.png width = 400 height = 200>|<img src = https://i.imgur.com/ZK8yfsf.png width = 400 height = 200>|
#### 6. URLRequest Timeinterval Test
- URLRequest์ Timeinterval ๊ฐ์ default๊ฐ์ด 60์ด์ธ๋ฐ ์ด ์๊ฐ์ ๋์ผ๋ฉด ์ด๋ป๊ฒ ๋๋์ง ํ์ธํ๊ธฐ ์ํด ์ค๊ธฐ๊ธฐ๋ก ํ
์คํธ๋ฅผ ์งํ ํด ๋ณด์๋ค.
- ์ค๊ธฐ๊ธฐ์์ ํ
์คํธ ํ ๋ ์๋์ ๊ฐ์ ์ปจ๋์
์ผ๋ก ์ค์ ์ ํด์ค ๋ค์ ํ
์คํธ๋ฅผ ์งํ ํ๋ค.
<img src = https://i.imgur.com/4VYU6h0.png width = 225 height = 200>
- ๊ฒฐ๊ณผ๋ฅผ ๋น ๋ฅด๊ฒ ํ์ธํ๊ธฐ ์ํด Timeinterval์ 10์ด๋ก ์ค์ ํ๊ณ ์งํ ํ์๊ณ 10์ด๊ฐ ์ง๋ ๋ค์์๋ ์๋์ ๊ฐ์ด ์ฐ๋ฆฌ๊ฐ ์ค์ ํด์ค ์ผ๋ฟ ๋ฉ์ธ์ง๋ฅผ ํ์ธ ํ ์ ์์๋ค.
| ์ผ๋ฟ๋ฉ์ธ์ง | ์ดํ ๋ก๋ฉ๋ทฐ|
| :--: | :--: |
|<img src = https://i.imgur.com/YLyBtW9.png width = 200 height = 400>|<img src = https://i.imgur.com/2STJ1Ms.png width = 200 height = 400>|
### 7. remove Observer
- ์ํ๋ฑ๋ก ํ๋ฉด์์ ํค๋ณด๋์ ์
๋ ฅ ์ํ๋ฅผ ํ์ธํ๊ธฐ ์ํด NotificationCenter๋ฅผ ์ฌ์ฉํด Observer๋ฅผ ์ถ๊ฐํ ๋ค ๋ค์ remove Observer๋ฅผ ํด์ผ ํ๋ค๊ณ ์๊ฐํ๊ณ removeOBserver๋ฉ์๋๋ฅผ ์ฌ์ฉ ํ์๋๋ฐ ์ด๊ฒ ๊ผญ ํ์ํ ๊น์? ๋ผ๋ ๋ฆฌ๋ทฐ์ด์ ๋ง์ ๋ฃ๊ณ ๊ณต์๋ฌธ์๋ฅผ ์ฐพ์๋ณด์๋ค.
- ์๋์ ๊ฐ์ ๊ธ์ ๋ฐ๊ฒฌํ๊ณ ์ฐ๋ฆฌ์ ํ๊ฒ ๋ฒ์ ์ 14.0์ด๊ธฐ ๋๋ฌธ์ ๋๊ตฌ๋ณด๋ค ๋น ๋ฅด๊ฒ removeObserver๋ฉ์๋๋ฅผ ์ง์ ๋ค.
<img src = https://i.imgur.com/8v6wmC5.png width = 500 height = 50>
---
### Reference page
- [Implementing Modern Collection Views](https://developer.apple.com/documentation/uikit/views_and_controls/collection_views/implementing_modern_collection_views)