
# <img src = "https://hackmd.io/_uploads/B1r7f2cya.png" width = "35"> ํ๋ก์ ํธ ๋งค๋์
## Ground Rules
### ๐ข ์คํฌ๋ผ
- ์ค์ 9์ 30๋ถ์ ๋์ค์ฝ๋์์ ์งํ
- ์ ๊นจ๊ธฐ
- ๊ธ์ผ ์งํ ์ฌํญ ๊ณต์ ํ๊ธฐ(์ค๋์ ํ ์ผ)
### ๐ ํ๋ก์ ํธ ๊ท์น
- ๋ค์ด๋ฐ ์ค์ํ๊ธฐ(๊ฐ์ด๋ ๋ผ์ธ)
- ๋ธ๋์น
- main
- ์ ์ถ - step1, step2
- ์ฐ๋ฆฌ๊ฐ ์์
ํ - whales, minsup
- ์ฝ๋์ ๋ํ ๊ธฐ๋ก ๊ทธ๋๊ทธ๋ ํ๊ธฐ
- ์ค๊ฐ์ค๊ฐ ๋ฆฌ๋๋ฏธ ์์ฑ
- ํ์
์์ฑ์๋ก ์์ฑ๋ ํ๋กํผํฐ๋ ํ์
์๋ต
### โ๏ธ ์ปค๋ฐ ๊ท์น - ๊น๋ชจ์ง
- โจ Feat: ๊ธฐ๋ฅ ์ถ๊ฐ
- โป๏ธ Refactor: ๊ธฐ๋ฅ๊ณผ ๊ด๋ จ๋ ๊ฐ์ /์ ๋ฉด์์
- ๐ฉน Chore: ๋น๋ ์
๋ฌด ์์ , ํจํค์ง ๊ด๋ จ ์์ , ํ๊ฒฝ ์ค์ ๋ฑ
- ๐ Fix: ์ค๋ฅ ์์
- ๐ Style: ๋ค์ด๋ฐ, ์ปจ๋ฒค์
, ํฌ๋ฉง ์์
- ๐ Docs: ๋ฌธ์ ์ถ๊ฐ ๋ฐ ์์
- โ
Test: ํ
์คํธ ์ถ๊ฐ
- ์ปค๋ฐ ๋จ์: ๊ธฐ๋ฅ ๋จ์, chore ๋ฌถ์ด์ ์ปค๋ฐ
### ๐ฉ๐ปโโ๏ธ ํ ๊ท์น
- TIL, ์ผ์ผ ํ๊ณ ์์ฑ ์๊ฐ(๋งค์ผ 22์๋ถํฐ 1์๊ฐ ์์ฑ ์งํ)
- ์ปจ๋์
์ด ์ข์ง ์์ ๋๋ ๊ผญ ๋งํด์ฃผ๊ธฐ!!
- ๋ฐฉํด๊ธ์ง์๊ฐ : 2์ - 9์
### ๐ ์ค์ผ์ค
- ์๋ชฉ
| ์๊ฐ | ๋ด์ฉ | ์์ธ |
| :--------: | :--------: | :--------: |
| 09:30-10:00 | ์คํฌ๋ผ | |
| 10:00-12:00 | **ํ๋ํ์ต ์์ต** | |
| 14:00-17:00 | **ํ๋ํ์ต** | |
| 19:00-22:00 | ํ๋ก์ ํธ | ํ์์ ๊ฐ์ธ๊ณต๋ถ |
| ๊ทธ ํ | TIL ๋ฐ ๊ฐ์ธ์๊ฐ | |
- ํ์๊ธ
| ์๊ฐ | ๋ด์ฉ | ์์ธ |
| :--------: | :--------: | :--------: |
| 09:30-10:00 | ์คํฌ๋ผ | |
| 10:00-12:00 | ํ๋ก์ ํธ | |
| 14:00-17:00 | ํ๋ก์ ํธ ๋ฐ ๊ฐ์ธ๊ณต๋ถ | |
| 19:00-22:00 | ๊ฐ์ธ๊ณต๋ถ | ํ์์ ํ๋ก์ ํธ |
| ๊ทธ ํ | TIL ๋ฐ ๊ฐ์ธ์๊ฐ | |
- ์์ธ์ฌํญ
- ์ผ์ํค: 10.5-6
- ๋ฆฌ๋ทฐ๋ฅผ ๋ฐ์ผ๋ฉด ์ ๋์ ์ผ๋ก!
- ์ถ์ ๋ชฉ๊ธ OffDay
## ์ผ์ผ ์คํฌ๋ผ
### ๐ 09/18 ์
- ์ค๋์ ์ปจ๋์
- Minsup๐ฆ: ๋๋ฌด ํ๋ ํ๋ฃจ...๐ซ
- Whales๐ฌ: ์ ์๊ณ ์ ์ฌ๊ณ ๋ง์งฑํฉ๋๋ค!!
- ํน์ด์ฌํญ
- Minsup๐ฆ: ์์ต๋๋ค!
- Whales๐ฌ: ์ปด๋ฐ์ธ ๋๋ฌด ์ด๋ ค์์..๐คฏ
- ์ค๋ ํ ์ผ
- [x] ๊ทธ๋ผ์ด๋ ๋ฃฐ
- [x] ๊ธฐ์ ์คํ ์์ํ๊ธฐ
### ๐ 09/19 ํ
- ์ค๋์ ์ปจ๋์
- Minsup๐ฆ: ์ฝ๊ฐ ํผ๊ณค...?
- Whales๐ฌ: ์ ์กธ๋ฆฝ๋๋ค...?!
- ํน์ด์ฌํญ
- Minsup๐ฆ: ์์ต๋๋ค!
- Whales๐ฌ: ์ ๋ ์์ต๋๋ค. ๋ฌด๋๋ฌด๋ํ ํ๋ฃจ!!
- ์ค๋ ํ ์ผ
- [x] ๊ทธ๋ฆฐ๊ณผ ๊ธฐ์ ์คํ ์์ํด์ ์ ํ๊ธฐ (์คํ 2์)
- [x] ๋ชฉํ - STEP 1 PR ๋ณด๋ด๊ธฐ
### ๐ 09/20 ์
- ์ค๋์ ์ปจ๋์
- Minsup๐ฆ: ์์พํ์ง ์์ง๋ง..์ข์ต๋๋ค.
- Whales๐ฌ: ํน ์์์ ์์ฃผ ์์พํฉ๋๋ค.
- ํน์ด์ฌํญ
- Minsup๐ฆ: ๋ชจ๊ฐ์ฝ๊ฐ ์์ต๋๋ค
- Whales๐ฌ: ์ญ์ ์ฌ๋์ ์ ์ ์ ์์ผํฉ๋๋ค.
- ์ค๋ ํ ์ผ
- [x] SwiftUI ๋ง์ ธ๋ณด๊ธฐ
- [x] Step2 ์์ 2:30
### ๐ 09/21 ๋ชฉ
- ์ค๋์ ์ปจ๋์
- Minsup๐ฆ: ์ข์ต๋๋ค.
- Whales๐ฌ: ์ค๋์ ๋๋ฌด๋๋ฌด ์กธ๋ฆฝ๋๋ค
- ํน์ด์ฌํญ
- Minsup๐ฆ: ์์ต๋๋ค.
- Whales๐ฌ: ์ด์ฌํ ๊ณต๋ถํด์ผํฉ๋๋ค!!!
- ์ค๋ ํ ์ผ
- [x] ํ๋ํ์ต
- [x] Step2 ์ชผ๊ฐ๋ณด๊ธฐ (์ถ๊ฐํ๋ ๋ถ๋ถ๊น์ง๊ฐ 2-1)
- [x] Whales - ๋์ !! ํผ์์ ์ถ๊ฐํ๋ ๊ฒ๊น์ง ๊ตฌํํด๋ณด๊ธฐ
- [x] Minsup - ์ํคํ
์ฒ ๊ณ ๋ฏผ. ํ์ผ๊ตฌ์กฐ, ๋ธ๋์น, ๋จธ์ง ๋ฑ
- [x] MVVM ์ ์ฉ
### ๐ 09/22 ๊ธ
- ์ค๋์ ์ปจ๋์
- Minsup๐ฆ: ์ ์ค์ต๋๋ค~~
- Whales๐ฌ: ์ ์ด ๋ถ์กฑํจ์ด ๋๊ปด์ง๋๋ค์
- ํน์ด์ฌํญ
- Minsup๐ฆ: PR ๋์
- Whales๐ฌ: ๋ค์ ์ค์ ๋์ !! ์ผ์ฐ์ผ์ฐ!!
- ์ค๋ ํ ์ผ
- [x] Whales - Environment ํค์๋๋ก ๋ค์ ๋์ !!
- [x] README
- [x] Minsup - Refactoring
### ๐ 09/25 ์
- ์ค๋์ ์ปจ๋์
- Minsup๐ฆ: ์ข์ต๋๋ค.
- Whales๐ฌ: ๋ชธ์ด ์ผ์ฌ์ผ์ฌ ์ข์ง ์์ต๋๋ค๐
- ํน์ด์ฌํญ
- Minsup๐ฆ: ์์ต๋๋ค.
- Whales๐ฌ: ํ๋ฃจ๋ฅผ ๋ ๋ ค๋จน์์ต๋๋ค์....๐ซ
- ์ค๋ ํ ์ผ
- [x] ํ๋ํ์ต
### ๐ 09/26 ํ
- ์ค๋์ ์ปจ๋์
- Minsup๐ฆ: ์ข์ต๋๋ค.
- Whales๐ฌ: ๋ชธ์ด ์ ์ข์๊ฑด ๊ด์ฐฎ์๋ฐ ์์ฃผ์์ฃผ ํผ๊ณคํ๋ค์
- ํน์ด์ฌํญ
- Minsup๐ฆ: ์ ๋
์ฝ์
- Whales๐ฌ: ๋น๊ฐ ์ต๋๋ค....๋น๊ฐ ์์์ค....
- ์ค๋ ํ ์ผ
- [x] ๋ฆฌ๋ทฐ ๋ฐ์ ๋ถ๋ถ ์์
### ๐ 09/27 ์
- ์ค๋์ ์ปจ๋์
- Minsup๐ฆ: ์ข์ต๋๋ค. ํ๋ณตํฉ๋๋ค.
- Whales๐ฌ: ๋ฆ์ ....์ค์ต๋๋ค?
- ํน์ด์ฌํญ
- Minsup๐ฆ: ์์ต๋๋ค.
- Whales๐ฌ: Async / Await...์ด๋ ค์์.....
- ์ค๋ ํ ์ผ
- [x] ํ๋ํ์ต
- [x] Whales - ๋ฉํ ๋ง
- [x] Minsup - 2์ฐจ ํผ๋๋ฐฑ ๋ฐ์
### ๐ 10/01 ์ผ
- ์ค๋์ ์ปจ๋์
- Minsup๐ฆ: ์ข์ต๋๋ค. ํ๋ณตํฉ๋๋ค.
- Whales๐ฌ: ํน ์์๊ณ ์์ฃผ ์ ์ฌ์์ต๋๋ค.
- ํน์ด์ฌํญ
- Minsup๐ฆ: ์์ต๋๋ค.
- Whales๐ฌ: ์ธ๋๋ค ์ง ๊ฐ๋ค ์์ต๋๋ค ํคํฟ
- ์ค๋ ํ ์ผ
- [x] STEP 2-2 PR ๋ณด๋ด๊ธฐ
- [x] README ์ถ๊ฐ ์์ฑ
### ๐ 10/03 ํ
- ์ค๋์ ์ปจ๋์
- Minsup๐ฆ: ์ข์ต๋๋ค!!
- Whales๐ฌ: ์๋ฌด๋๋ ๊ฐ๊ธฐ๊ฐ ์ค๋ ค๋ ๋ด
๋๋ค์์์
- ํน์ด์ฌํญ
- Minsup๐ฆ: ๋ฆ์ ...
- Whales๐ฌ: ๋ฏผ์ญ ๋ฆ์ ์ด์๋ฉด ์ ๋ ์ข ๋ ์๊ณ ์ค๊ฒ ์ต๋๋ค ํํณ
- ์ค๋ ํ ์ผ
- [x] STEP 2-2 ๋ฆฌ๋ทฐ ๋ฐ์ ๋ถ๋ถ ์์ ํ๊ธฐ
- [x] STEP3 ์์! - Realm ๊ณต๋ถ
### ๐ 10/04 ์
- ์ค๋์ ์ปจ๋์
- Minsup๐ฆ: ๋งค์ฐ ์กธ๋ฆฝ๋๋ค?
- Whales๐ฌ: ํน ์์์ ์์ฃผ ๊ฐ์ดํฉ๋๋ค!!!
- ํน์ด์ฌํญ
- Minsup๐ฆ: ๋์์ธ ํจํด ๊ณต๋ถํ๊ณ ๋ฐํ์ค๋น๋ฅผ ํด์ผํฉ๋๋ค. 10์์ฏค?
- Whales๐ฌ: Realm ๋๋ฌด ์ด๋ ค์์.. MVVM ํน๊ฐ ๊ธฐ๋๋ฉ๋๋ค!!!
- ์ค๋ ํ ์ผ
- [ ] Realm ์ ์ฉ
- [ ] MVVM ํน๊ฐ
- [ ] PR step3 ๋์ (?)
### ๐ 10/05 ๋ชฉ
- ์ค๋์ ์ปจ๋์
- Minsup๐ฆ:
- Whales๐ฌ: ์ค๋์ ๋งค์ฐ๋งค์ฐ ํผ๊ณคํฉ๋๋ค์์์์์์
- ํน์ด์ฌํญ
- Minsup๐ฆ:
- Whales๐ฌ: ๋์์ธํจํด ๋ฐํ!! ๋จ๋ฆฝ๋๋ค ํํํํ
- ์ค๋ ํ ์ผ
- [ ] ๋์์ธํจํด ๋ฐํ ์ค๋น
- [ ] ํ๋ํ์ต - ๋์์ธํจํด ๋ฐํ
- [ ] Whales - ์ผ์ํค (์คํ 4:30~)
- [ ] Minsup - STEP 3
### ๐ 10/06 ๊ธ
- ์ค๋์ ์ปจ๋์
- Minsup๐ฆ:
- Whales๐ฌ:
- ํน์ด์ฌํญ
- Minsup๐ฆ:
- Whales๐ฌ:
- ์ค๋ ํ ์ผ
- [ ] Whales - ์ผ์ํค (~์คํ 4:30), ๋ฉํ ๋ง(๋ฐค 10~12์)
- [ ]
- [ ]
# <img src = "https://hackmd.io/_uploads/B1r7f2cya.png" width = "35"> ํ๋ก์ ํธ ๋งค๋์ <img src = "https://hackmd.io/_uploads/Bkf_435kT.png" width = "30"><img src = "https://hackmd.io/_uploads/rJhCN3qkp.png" width = "30">
- ํ๋ก์ ํธ ๊ธฐ๊ฐ: [2023๋
9์ 18์ผ ~ 10์ 6์ผ](https://github.com/WhalesJin/ios-project-manager/wiki/ํ์๋ผ์ธ)
- ํ๋ก์ ํธ ํ์: [Whales <img src = "https://hackmd.io/_uploads/Bkf_435kT.png" width = "20">](https://github.com/WhalesJin) , [Minsup <img src = "https://hackmd.io/_uploads/rJhCN3qkp.png" width = "20">](https://github.com/agilestarskim)
- ํ๋ก์ ํธ ๋ฆฌ๋ทฐ์ด: [GREEN <img src = "https://hackmd.io/_uploads/H1pGWNoyp.png" width = "20">](https://github.com/GREENOVER)
---
## ๐ ๋ชฉ์ฐจ
๐ [์๊ฐ](#์๊ฐ) </br>
๐ป [์คํ ํ๋ฉด](#์คํ_ํ๋ฉด) </br>
๐ ๏ธ [์ฌ์ฉ ๊ธฐ์ ](#์ฌ์ฉ_๊ธฐ์ ) </br>
๐ [๋ค์ด์ด๊ทธ๋จ](#Diagram) </br>
๐งจ [ํธ๋ฌ๋ธ ์ํ
](#ํธ๋ฌ๋ธ_์ํ
) </br>
๐ [์ฐธ๊ณ ๋งํฌ](#์ฐธ๊ณ _๋งํฌ) </br>
๐ฉโ๐งโ๐ง [about TEAM](#about_TEAM) </br>
</br>
## ๐ ์๊ฐ<a id="์๊ฐ"></a>
<img src = "https://hackmd.io/_uploads/Bkf_435kT.png" width = "20"><img src = "https://hackmd.io/_uploads/rJhCN3qkp.png" width = "20"> : ํ๋์ ํ๋ก์ ํธ๋ฅผ ์ธ๋ถํํ์ฌ ๊ด๋ฆฌํ ์ ์๋ ์ดํ๋ฆฌ์ผ์ด์
์
๋๋ค.
์นธ๋ฐ๋ณด๋๋ฅผ ์ฌ์ฉํ์ฌ TODO, DOING, DONE์ผ๋ก ๋ถ๋ฅํด ์งํ๋๋ฅผ ํ ๋์ ํ์ธํ ์ ์์ต๋๋ค.
๊ฐ ์
์ ๊ธธ๊ฒ ํด๋ฆญํ์ฌ ํ ์ผ์ ์ํ๋ฅผ ๋ณ๊ฒฝํ ์ ์๊ณ ์ค์์ดํ๋ฅผ ํตํด ์ญ์ ํ ์ ์์ต๋๋ค.
์๋จ ๋ฐ์ ์์นํ + ๋ฒํผ์ ๋๋ฌ ์๋ก์ด ์
์ ์ถ๊ฐํ๊ฑฐ๋ ๊ธฐ์กด์ ์
์ ํด๋ฆญํ์ฌ ์์ ํ ์ ์์ต๋๋ค.
</br>
## ๐ป ์คํ ํ๋ฉด<a id="์คํ_ํ๋ฉด"></a>
| ๊ธฐ๋ณธ ํ๋ฉด |
| :--------: |
| <img src = "https://hackmd.io/_uploads/BkzTn1Pga.png" width = "600"> |
| ์ ํ ์ผ ์ถ๊ฐ |
| :--------: |
| <img src = "https://hackmd.io/_uploads/rJC22ywgp.gif" width = "600"> |
| ๊ธฐ์กด ํ ์ผ ํธ์ง |
| :--------: |
| <img src = "https://hackmd.io/_uploads/ByIcjJwlp.gif" width = "600"> |
| ์นดํ
๊ณ ๋ฆฌ ๋ณ๊ฒฝ |
| :--------: |
| <img src = "https://hackmd.io/_uploads/r18qskPlT.gif" width = "600"> |
</br>
## ๐ ๏ธ ์ฌ์ฉ ๊ธฐ์ <a id="์ฌ์ฉ_๊ธฐ์ "></a>
| ๊ตฌํ ๋ด์ฉ | ๋๊ตฌ |
|:---:|:---:|
|UI|SwiftUI|
|์ํคํ
์ณ|ํด๋ฆฐ ์ํคํ
์ณ|
|๋์์ธํจํด|MVVM|
|๋ก์ปฌ ๋ฐ์ดํฐ|Realm|
|๋ฆฌ๋ชจํธ ๋ฐ์ดํฐ|Firebase|
</br>
## ๐ Diagram<a id="Diagram"></a>
### ๐ UML
<img src = "https://hackmd.io/_uploads/HkGA5h9y6.png" width = "800">
</br>
# Separator
## ๐งจ ํธ๋ฌ๋ธ ์ํ
<a id="ํธ๋ฌ๋ธ_์ํ
"></a>
### 1๏ธโฃ ๊ธฐ์ ์คํ ์ค์
#### 1. ๋ทฐ ๋๋ก์ - SwiftUI
UIKit์ ๋นํด ๋ค์๊ณผ ๊ฐ์ ์ฅ์ ์ ๋๊ปด์ SwiftUI๋ก ์ ํํ์์ต๋๋ค.
- ๋ทฐ ๊ทธ๋ฆฌ๊ธฐ ๊ฐ๋จํ๋ค.
- ๋ ์ด์์ ๋ง์ด ์๊ฐ ์ ๋บ๊น
- ์ฝ๋๊ฐ ์งง๊ณ ์ง๊ด์ ์ด๋ค.
- ์ฌ๋ฐ๋ค.
#### 2. ์ํคํ
์ฒ - ํด๋ฆฐ ์ํคํ
์ฒ + MVVM
ํ๋ก์ ํธ๋ค์ ์ฝ๋๋ฅผ ๋ณด๋ฉด ์ฒด๊ณ๋ ์๋ ๊ฒ ๊ฐ๊ณ , ๋ณต์ก์ฑ์ด ๋ง์ด ์ฝํ์๋ ๋๋์ด๋ผ ์ด๋ ๊ฒ ์ค๊ตฌ๋๋ฐฉํ์ง์๊ณ ๊ท์น์ด ์๊ฑฐ๋ ์์กด๋ฐฉํฅ์ด ์ผ์ ํ์ผ๋ฉด ์ข๊ฒ ๋ค๋ ์๊ฐ์ ํ์ต๋๋ค.
์ด๋ฅผ ํด๊ฒฐํด์ฃผ๋ ๊ฒ์ด ์์กด์ฑ ๊ท์น์ ๋ํ ์๊ธฐ๋ฅผ ํ๋ `ํด๋ฆฐ ์ํคํ
์ฒ`๋ผ๊ณ ์๊ฐํฉ๋๋ค. ํด๋ฆฐ ์ํคํ
์ฒ๋ ์ด๋ก ์ ์ด๊ณ ์ถ์์ ์ธ ๋๋์ด๋ผ ๋ฐฉ๋ฒ์ด ๋๊ฒ ๋ค์ํด ๋ณด์๊ณ , ๊ทธ ์ค์์๋ ์ ํฌ๋ MVVM์ ์ ๋ชฉํด์
**ํด๋ฆฐ ์ํคํ
์ฒ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก MVVM**์ ๊ตฌํํด๋ณด์์ต๋๋ค.
#### 3. ๋ก์ปฌ๋ฐ์ดํฐ - Realm
CoreData์ ๋นํด ๋ค์๊ณผ ๊ฐ์ ์ฅ์ ๋ค์ด ๋ ์๋ฟ์์ Realm์ผ๋ก ๊ฒฐ์ ํ์ต๋๋ค.
- ์๋๊ฐ CoreData๋ณด๋ค ํจ์ฌ ๋น ๋ฅด๋ค.
- ์ง๊ด์ ์ธ API๋ฅผ ์ ๊ณตํ๊ณ ์์ด ์ฌ์ฉ์ฑ์ด ์ข๋ค.
- ์ธ๋ถ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ธด ํ์ง๋ง MongoDB๊ฐ ๊ด๋ฆฌํ๊ณ ์์ด ์ ๋ขฐ์ฑ์ด ๋๋ค.
- ๋ฌธ์ ์ ๋ฆฌ๊ฐ ์ ๋์ด์๊ณ ์ปค๋ฎค๋ํฐ๊ฐ ์ ์์ฑ๋์ด์์ด ์ ๋ณด ์ต๋์ด ๋น ๋ฅด๋ค.
- SPM์ ์ง์ํ๋ค.
- Entity Mappingํ ๋ CoreData๋ณด๋ค ํจ์ฌ ํธํ๋ค.
-> CoreData๋ ๊ฐ์ฒด ์์ฑ ์ context๊ฐ ํ์ํ๋ค.
#### 4. ๋ฆฌ๋ชจํธ๋ฐ์ดํฐ - Firebase
iCloud์ Firebase ์ค์ ๊ณ ๋ฏผ์ด ๋์ด ๋ ๊ฐ์ง๋ฅผ ๋น๊ตํด๋ณด๊ณ ๊ฒฐ๋ก ์ ์ผ๋ก Firebase๊ฐ ํ์ฌ ํ๋ก์ ํธ์๋ ๋ ์ข์ ๊ฒ ๊ฐ๋ค๊ณ ํ๋จํด์ Firebase๋ก ์ ํํ์์ต๋๋ค.
<img src = "https://hackmd.io/_uploads/H18Ofyvyp.png" width = 80>
- ํธ์์ฑ์ด ์ข๋ค. CoreData์์ ์ฐ๋์ด ์ข๋ค.
์ฝ์ด๋ฐ์ดํฐ๋ฅผ ์์๋ฐ์ ํด๋์ค ์ฌ์ฉ
[NSPersistentCloudKitContainer](https://developer.apple.com/documentation/coredata/nspersistentcloudkitcontainer)
- iCloud๋ ์ ๊ณต์ด ์ฝํ๋ค.
- iCloud ๊ณ์ ์ ์ฐ๋ฏ๋ก ์น๊ตฌ๊ฐ ๋์ด์์ผ๋ฉด ์ ์ฅ ์์น์ ๋ฐ๋ผ ์ ๊ทผ ์์ค์ ์ ํ ์ ์๋ค.
- ์์กด์ฑ ๊ด๋ฆฌ๋๊ตฌ ํ์์๋ค.
- [CloudKit](https://developer.apple.com/kr/icloud/cloudkit/)
<img src = "https://hackmd.io/_uploads/SyrlGJDy6.png" width = 110>
- ์๋๋ก์ด๋๋ ๊ฐ์ด ๊ณต์ ๊ฐ ๊ฐ๋ฅํ๋ค. (ํฌํธํด๋ฆฌ์ค๋ก ์ข๋ค)
- ๋จ์ ์ ๋น์ธ๋ค.
- ์์กด์ฑ ๊ด๋ฆฌ๋๊ตฌ : ์ฝ์ฝ์ํ์ด๋ **SPM**
- ์๋๋ก์ด๋ ์ปค๋ฒ๋ ์ปค๋ฆฌ์ด โ Firebase
- ์ ๊ณตํด์ฃผ๋ ์๋น์ค๊ฐ ๋ง๋ค. All in One
- ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ ์
ํ
์ด ๋ค ๋์ด์๋ค.
- ๋ณด์ ์๋ฃจ์
๋ ๋ค ์ค์น๋์ด์๋ค.
- ๋ฐ์ดํฐ ์ผํฐ. ์์ธ๋ ์กด์ฌํ๋ค.
- ๊ธฐ๋ณธ์๊ฑด์ด ์๋์ ๊ฐ์์ ํ์ ๋ฒ์ ํธํ๋ ๋ฌธ์ ์๋ค.
- Xcode 14.1 ์ด์
- iOS 11 ์ด์
- ๋จ์ : ์ง์ DB์ ์ ๊ทผํ๋๊น ๋ณด์์ด ์ฝํ๋ค
### 2๏ธโฃ CUSTOM MODIFIER
๐จ **๋ฌธ์ ์ ** <br>
Custom View๋ฅผ alert ํํ๋ก ๋์ฐ๊ธฐ ์ํ ๋ฐฉ๋ฒ์ ๋ชจ์ํ์ต๋๋ค. ๊ธฐ๋ณธ API๋ ์ฃผ์ด์ง์ง ์์ ์ง์ ๊ตฌํ์ ํด์ผํ์ต๋๋ค.
๐ก **ํด๊ฒฐ๋ฐฉ๋ฒ** <br>
ZStack์ผ๋ก ๋ฐฐ๊ฒฝ๊ณผ alert์ ๋๋๊ณ ๊ทธ ์ฌ์ด์ ๊ฒ์ ๋ถํฌ๋ช
๋ทฐ๋ฅผ ๋ฃ์ด alert์ด ๋์ด์๋ ํจ๊ณผ๋ฅผ ๋ง๋ค์์ต๋๋ค. binding์ ์ด์ฉํด ์ต๋ํ SwiftUI API์ ๋น์ทํ๊ฒ ๋ง๋ค์์ต๋๋ค.
<br>
### 3๏ธโฃ ViewModel ์ ์ธ ๋ฐฉ์
๐จ **๋ฌธ์ ์ ** <br>
์ฒ์์ ์๋์ ๊ฐ์ด ViewModel์ ๊ฐ View ์์ ์ค์ฒฉํ์
์ผ๋ก ๊ตฌํํ์ต๋๋ค. ์ด ๋ฐฉ๋ฒ์ ViewModel์ด๋ ์ด๋ฆ์ ๊ฐ ๋ทฐ์์ ์ค๋ณตํด์ ์ฌ์ฉํ ์ ์๋ค๋ ์ฅ์ ์ด ์์ต๋๋ค. ํ์ง๋ง View์์ ๋ค๋ฅธ View์ViewModel์ ์ ๊ทผํ๋ ค๋ฉด ๋ทฐ์ด๋ฆ.๋ทฐ๋ชจ๋ธ ์ด๋ฐ์์ผ๋ก ์ ๊ทผํด์ผํ๋ค๋ ๋จ์ ์ด ์์์ต๋๋ค.
```swift
extension KanbanView {
final class ViewModel: ObservableObject { ... }
}
struct KanbanView: View {
@ObservedObject var vm = ViewModel()
...
}
```
๐ก **ํด๊ฒฐ๋ฐฉ๋ฒ** <br>
์ ์ญ์ ์ผ๋ก ์ฌ์ฉ ๊ฐ๋ฅํ๊ฒ๋ ๋ฐ๋ก ๋นผ๋ด์ด ํ์
์ ์์ฑํ์์ต๋๋ค.
```swift
final class KanbanViewModel: ObservableObject { }
```
<br>
### 4๏ธโฃ TaskFormView ์ฌํ์ฉ
๐จ **๋ฌธ์ ์ ** <br>
TaskFormView์์ Create์ Edit์ ๊ตฌํํ๊ธฐ ์ํด ์ค๋ณต๋ ๋ถ๋ถ๋ค์ ์ด๋ป๊ฒ ์ฒ๋ฆฌํ ๊น ๊ณ ๋ฏผํ์ต๋๋ค.
๐ก **ํด๊ฒฐ๋ฐฉ๋ฒ** <br>
1๏ธโฃ View์ init์์ ๋ถ๊ธฐ์ฒ๋ฆฌ
view๋ฅผ initํ ๋ optinal Task๋ฅผ ์ฌ์ฉํด, create์ผ ๊ฒฝ์ฐ nil, edit์ผ ๊ฒฝ์ฐ ์์ ํ task๋ฅผ ์ฃผ์
ํ์ฌ ๋ถ๊ธฐ์ฒ๋ฆฌ๋ฅผ ํ์์ต๋๋ค. ๋จ์ ์ init์ ๋ก์ง์ด ๋ค์ด๊ฐ ๋ณต์กํด์ง๊ณ ๊ธฐ๋ฅ์ด ์ถ๊ฐ๋ ๋๋ง๋ค ์์ ํ ๋ถ๋ถ๋ ๋ง์์ง๊ณ ์ฌ์ฉํ์ง ์์ ๋ฉ์๋๋ค์ viewModel์ ๋ชจ๋ ์ง์ด๋ฃ์ด์ผํ๋ค๋ ๋ฌธ์ ๊ฐ ์์์ต๋๋ค.
[Optional Task๋ฅผ ์ด์ฉ](https://github.com/WhalesJin/ios-project-manager/blob/f2d72324a03fabdb7f51d02ce3442bcc2aaa28e3/ProjectManager/ProjectManager/Presentation/Kanban/TaskForm/TaskFormView.swift)
2๏ธโฃ Protocol์ ์ด์ฉํด ๊ตฌํํ๊ธฐ
Create์ Edit์ ๊ด์ฐฐํด๋ณด๋ ์ค๋ณต๋๋ ๋ถ๋ถ์ด ๋ง์์ ํ๋กํ ์ฝ๋ก ๊ธฐ๋ฅ ์ ์ ํ Create์ Edit์ ViewModel์ ๊ฐ๊ฐ ๋ฐ๋ก ๋ง๋ค์ด์ ๋ทฐ๋ชจ๋ธ์ ์ฃผ์
ํ๋ ํ์์ผ๋ก ๊ตฌํํด๋ดค์ต๋๋ค. ๋จ์ ์ ๊ธฐ๋ฅ์ด ์ถ๊ฐ๋ ๋๋ง๋ค ๊ฐ ๋ทฐ๋ชจ๋ธ์ ๋๊ฐ์ ๋ฉ์๋์ ํ๋กํผํฐ๋ฅผ ์ต์ง๋ก ๋ง๋ค์ด์ผํ๋ค๋ ๋จ์ ์ด ์์ต๋๋ค.
[Protocol ์ฌ์ฉ](https://github.com/WhalesJin/ios-project-manager/blob/ddea938b958136009b59b3b63a54f7b339904648/ProjectManager/ProjectManager/Presentation/Kanban/TaskForm/TaskFormView.swift)
<br>
### 5๏ธโฃ Move to ๊ธฐ๋ฅ ๊ตฌํํ๊ธฐ
๐จ **๋ฌธ์ ์ ** <br>
๊ธฐ์กด ์ฝ๋๋ todos, doings, dones๋ฅผ ๊ฐ๊ฐ ๋ถ๋ฆฌ๋ ๋ฐฐ์ด๋ก ๊ตฌํ๋์ด์์ด์ ํ ๋ฐฐ์ด์์ ๋ค๋ฅธ ๋ฐฐ์ด๋ก ๋ณ๊ฒฝํ๋ ค๋ฉด ๊ธฐ์กด ๋ฐฐ์ด์์ removeํ๊ณ ๋ค๋ฅธ ๋ฐฐ์ด์์ append ํ๋ ๋ฐฉ์์ผ๋ก ์งํ๋์ด์ผ ํ์ต๋๋ค. ์ด๋ ๊ฒ ์ง๊ฒ ๋๋ฉด ์ํ๋ณํ์ ๋ฐ๋ฅธ ๋ฉ์๋๋ค์ ์ค๋ณต์ด ๋์ด๋ ๋ค๋ฅธ ๋ฐฉ๋ฒ์ ๊ณ ๋ฏผํด๋ณด์์ต๋๋ค.
```swift
func moveFromTodo(task: Task, to other: String) {
if other == "DOING" {
moveToDoingFromTodo(task: task)
} else {
moveToDoneFromTodo(task: task)
}
}
func moveToDoingFromTodo(task: Task) {
guard let index = todos.firstIndex(of: task) else { return }
todos.remove(at: index)
doings.append(task)
}
func moveToDoneFromTodo(task: Task) {
guard let index = todos.firstIndex(of: task) else { return }
todos.remove(at: index)
dones.append(task)
}
```
๐ก **ํด๊ฒฐ๋ฐฉ๋ฒ** <br>
1๏ธโฃ state ์์ฑ์ ์ถ๊ฐํด state๋ฅผ ๊ธฐ์ค์ผ๋ก ํํฐ๋งํ์ฌ ๋ฐฐ์ด์ ๋ถ๋ฆฌํ์์ต๋๋ค.
์ด ๋ฐฉ๋ฒ์ ์ค์ ๋ก ์์๋ฅผ ๋ค๋ฅธ ๋ฐฐ์ด๋ก ์ด๋์ํค๋ ๊ฒ์ด ์๋๋ผ ์ํ๋ง ๋ฐ๊ฟ์ผ๋ก์ ์ด๋ํ๋ ๊ฒ์ฒ๋ผ ๋ณด์ด๊ฒ ํ ์ ์๋ ์ฅ์ ์ด ์์ต๋๋ค. ํ์ง๋ง ์ด ๊ณผ์ ์์ ์๋ณธ tasks ๋ฐฐ์ด ์์๋๋ก ์์๋ค์ด ๋ณด์ฌ์ง๊ธฐ ๋๋ฌธ์ ์ ํฌ๊ฐ ์ํ๋ ์์๋๋ก ๋ณด์ฌ์ง์ง ์์์ต๋๋ค.๋ฐ๋ผ์ ์์์ ์์๋ฅผ ์ด๋ค ๊ธฐ์ค์ผ๋ก ๋ณด์ฌ์ฃผ์ด์ผํ ์ง ๊ธฐํํด์ผํ๊ณ ๊ฒฐ๊ตญ date๋ฅผ ๊ธฐ์ค์ผ๋ก ์ ๋ ฌํ์ฌ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ์์ต๋๋ค.
```swift
@Published var tasks: [Task]
var todos: [Task] {
return tasks.filter { $0.state == .todo }
}
var doings: [Task] {
return tasks.filter { $0.state == .doing }
}
var dones: [Task] {
return tasks.filter { $0.state == .done }
}
init(tasks: [Task] = []) {
self.tasks = tasks
self.tasks.sort { $0.date < $1.date }
}
func create(_ task: Task) {
tasks.append(task)
tasks.sort { $0.date < $1.date }
}
```
<br>
## ๐ ์ฐธ๊ณ ๋งํฌ<a id="์ฐธ๊ณ _๋งํฌ"></a>
- <Img src = "https://hackmd.io/_uploads/Hyyrii91T.png" width="20"/> [Firebase](https://firebase.google.com/?hl=ko)
- <Img src = "https://hackmd.io/_uploads/B1pu3oq1a.png" width="20"/> [Realm ์ค์น](https://www.mongodb.com/docs/realm/sdk/swift/install/#std-label-ios-install)
- [๐ Apple Docs: CloudKit](https://developer.apple.com/kr/icloud/cloudkit/)
- [๐ Apple Docs: List](https://developer.apple.com/documentation/swiftui/list)
- [๐ Apple Docs: ViewModifier](https://developer.apple.com/documentation/swiftui/viewmodifier)
- [๐ Apple Docs: GeometryReader](https://developer.apple.com/documentation/swiftui/geometryreader)
- [๐ Apple Docs: ScrollViewReader](https://developer.apple.com/documentation/swiftui/scrollviewreader)
- [๐ Apple Docs: UnitPoint](https://developer.apple.com/documentation/swiftui/unitpoint)
- [๐ Apple Docs: ]()
- [๐ WWDC: ]()
- [๐ WWDC: ]()
- [๐ WWDC: ]()
- [๐ StackOverflow: ViewModel Protocol](https://stackoverflow.com/questions/59503399/how-to-define-a-protocol-as-a-type-for-a-observedobject-property)
- <Img src = "https://github.com/mint3382/ios-calculator-app/assets/124643545/56986ab4-dc23-4e29-bdda-f00ec1db809b" width="20"/> [์ผ๊ณฐ๋ท๋ท: Test Double](https://yagom.net/courses/unit-test-์์ฑํ๊ธฐ/lessons/ํ
์คํธ๋ฅผ-์ํ-๊ฐ์ฒด-๋ง๋ค๊ธฐ/topic/ํ
์คํธ๋ฅผ-์ํ-๊ฐ์ฒด๋ฅผ-์ด์ฉํด์-ํ
์คํธ-์์ฑํ๊ธฐ/)
- <Img src = "https://hackmd.io/_uploads/ByTEsGUv3.png" width="20"/> [blog: URL ์ฒ๋ฆฌ ๋ฐฉ๋ฒ](https://ios-development.tistory.com/1014)
<br>
---
## ๐ฉโ๐งโ๐ง about TEAM<a id="about_TEAM"></a>
| <Img src = "https://hackmd.io/_uploads/r1elEh5ka.png" width="100"> | ๐ฌWhales๐ฌ | https://github.com/WhalesJin |
| :--------: | :--------: | :--------: |
| <Img src = "https://hackmd.io/_uploads/HkTfN2cyp.png" width="100"> | **Minsup** | **https://github.com/agilestarskim** |
- [ํ์๋ผ์ธ ๋งํฌ](https://github.com/WhalesJin/ios-project-manager/wiki/ํ์๋ผ์ธ)
<details>
|๋ ์ง|๋ด์ฉ|
|:--:|--|
|2023.09.18(์)| - ๊ธฐ์ ์คํ ์กฐ์ฌ ๋ฐ ๊ฒฐ์ |
|2023.09.19(ํ)| - `SwiftUI`๋ก ํ๋ก์ ํธ UI ๋ณ๊ฒฝ ๋ฐ ์์ด์ฝ ์ถ๊ฐ <br> - `Realm` ๋ฐ `Firebase` ํจํค์ง ์ถ๊ฐ |
|2023.09.20(์)| - `ํด๋ฆฐ์ํคํ
์ฒ` + `MVVM` ๊ตฌ์กฐ ์์ฑ <br> - `CellView`, `ListView`, `TodoView` ๊ตฌํ |
|2023.09.21(๋ชฉ)| - `TaskAddView` ์ด๊ณ ๋ซ๊ธฐ ๊ตฌํ |
|2023.09.22(๊ธ)| - README ์์ฑ <br> - `TaskAddView`๋ฅผ `TaskFormView`๋ก ์์ ๋ฐ ๋ก์ง ๊ตฌํ <br> - Column header์ ์นด๋ ๊ฐ์, ์ง๋ ๋ ์ง ๋นจ๊ฐ์์ผ๋ก ํ์ ๋ฑ UI ๊ฐ์ |
|2023.09.26(ํ)| - `TaskFormView`์ UI ๋ฐ ์์ธ ๋ก์ง ๋ณ๊ฒฝ <br> - `View`์ ๋ฐ๋ณต `modifier`๋ฅผ `custom Modifier`๋ก ๋ถ๋ฆฌ <br> - ๊ธธ๊ฒ ๋๋ฌ ์ํ ๋ณ๊ฒฝ ๋ฐ ์ค์์ดํ ์ญ์ ๊ตฌํ |
|2023.09.27(์)| - ํค๋ณด๋๋ก ์ธํด `TextEditor` ๊ฐ๋ฆฌ๋ ๋ฌธ์ ํด๊ฒฐ <br> - 2์ฐจ ํผ๋๋ฐฑ ๋ฐ์|
|2023.09.29(๊ธ)| - ์นด๋ ํด๋ฆญ ์ `Edit` ๊ธฐ๋ฅ ์ถ๊ฐ |
|2023.09.30(ํ )| - `separator` ๊ฐ๊ฒฉ ์ ๊ฑฐ |
</details>
</br>
### ๐ฅ ํ ํ๊ณ <a id="ํ_ํ๊ณ "></a>
- [ํ ํ๊ณ ๋งํฌ]()
### ๐๐ป ์ฐ๋ฆฌํ ์ํ ์
### ๐ ์๋ก์๊ฒ ์ข์๋ ์ ํผ๋๋ฐฑ
- Dear. Minsup
- Dear. Whales ๐
----