# ๐Ÿ—‚ Gyro Data ํ”„๋กœ์ ํŠธ ## ๐Ÿ“˜ ๋ชฉ์ฐจ - [๐Ÿ‘ฉโ€๐Ÿ’ป ํ”„๋กœ์ ํŠธ ๋ฐ ๊ฐœ๋ฐœ์ž ์†Œ๊ฐœ๐Ÿ‘จโ€๐Ÿ’ป](#-ํ”„๋กœ์ ํŠธ-๋ฐ-๊ฐœ๋ฐœ์ž-์†Œ๊ฐœ) - [โš™๏ธ ๊ฐœ๋ฐœํ™˜๊ฒฝ ๋ฐ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ](#-๊ฐœ๋ฐœํ™˜๊ฒฝ-๋ฐ-๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ) - [๐ŸŸฆ ํ”„๋กœ์ ํŠธ ๋กœ๊ณ ](#-Gyro-Data-ํ”„๋กœ์ ํŠธ-๋กœ๊ณ ) - [โ‡๏ธ ํ•ต์‹ฌ ํ‚ค์›Œ๋“œ](#-ํ‚ค์›Œ๋“œ) - [๐Ÿ“ฑ ๊ตฌํ˜„ ํ™”๋ฉด](#-๊ตฌํ˜„-ํ™”๋ฉด) - [๐Ÿ‘ฉ๐Ÿปโ€ ์ฝ”๋“œ ์„ค๋ช…](#-์ฝ”๋“œ-์„ค๋ช…) - [๐Ÿ“ ํด๋” ๊ตฌ์กฐ](#-ํด๋”-๊ตฌ์กฐ) - [โšก๏ธ ํŠธ๋Ÿฌ๋ธ” ์ŠˆํŒ…](#%EF%B8%8F-ํŠธ๋Ÿฌ๋ธ”-์ŠˆํŒ…) - [๐Ÿ”— ์ฐธ๊ณ  ๋งํฌ](#-์ฐธ๊ณ -๋งํฌ) <br> ## ํ”„๋กœ์ ํŠธ ๋ฐ ๊ฐœ๋ฐœ์ž ์†Œ๊ฐœ > **์†Œ๊ฐœ** : 6์ถ• ๋ฐ์ดํ„ฐ(acc 3์ถ• + gyro 3์ถ•)๋ฅผ ๋‹ค๋ค„๋ณด๊ณ , ๋ฐ์ดํ„ฐ๋ฅผ ์ƒ์„ฑํ•˜์—ฌ CoreData์™€ jsonํŒŒ์ผ๋กœ ์ €์žฅํ•˜๊ณ , ๋ถˆ๋Ÿฌ์˜ค๋Š” ์•ฑ์ž…๋‹ˆ๋‹ค.<br>**ํ”„๋กœ์ ํŠธ ๊ธฐ๊ฐ„** : 2022.12.26 ~ 2022.12.30<br> | **[์—˜๋ Œ(Ellen)](https://github.com/jcrescent61)** | **[์–ธ์ฒด์ธ(Unchain)](https://github.com/unchain123)** | **[์˜ˆํ†ค(Yeton)](https://github.com/yeeton37)** | |:---:|:---:|:---:| |<img src="https://i.imgur.com/s7IBwC1.jpg" width="270" height="250"/>|<img src="https://i.imgur.com/I4RtOVg.png" width="270" height="250"/>|<img src="https://i.imgur.com/5cHjgY4.jpg" width="270" height="250"/>| ### ์—˜๋ Œ(Ellen) - MVVM ์•„ํ‚คํ…์ฒ˜ ๊ตฌ์กฐ ์„ค๊ณ„ - ์ธก์ • ๋ฐ ํ”Œ๋ ˆ์ด ๋กœ์ง ๊ตฌํ˜„ - AnalysisView ์ธก์ • ํ™”๋ฉด ๊ตฌํ˜„ ### ์–ธ์ฒด์ธ(unchain) - ๊ทธ๋ž˜ํ”„๋ทฐ ๊ตฌํ˜„ - SwiftUI์™€ UIKit ๋ฐ์ดํ„ฐ ๋ฐ”์ธ๋”ฉ - ๋ฉ”์ธํ™”๋ฉด ๊ตฌํ˜„ ### ์˜ˆํ†ค(Yeton) - ์ฝ”์–ด๋ฐ์ดํ„ฐ ๊ตฌํ˜„ - ํŒŒ์ผ๋งค๋‹ˆ์ € ๊ตฌํ˜„ - PlayView ๊ตฌํ˜„ <br> ## ๊ฐœ๋ฐœํ™˜๊ฒฝ ๋ฐ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ [![swift](https://img.shields.io/badge/swift-5-orange)]() [![xcode](https://img.shields.io/badge/Xcode-14.2-blue)]() [![img](https://img.shields.io/badge/CoreData-red)](https://firebase.google.com/products/firestore?hl=ko) [![FileManager](https://img.shields.io/badge/FileManager-yellow)]() <br> ## ๐ŸŸฆ Gyro Data ํ”„๋กœ์ ํŠธ ๋กœ๊ณ  <img src="https://i.imgur.com/drLuvoF.png" width="270" height="250"/> ## ๐Ÿ’ก ํ‚ค์›Œ๋“œ - **`Combine`** - **`FileManager`** - **`SwiftUI`** - **`Charts(SwiftUI)`** - **`CoreData`** - **`MVVM`** - **`UITableView`** - **`GraphView`** - **`DataFormatting`** - **`SwiftUI + Combine`** - **`UIKit`** <br> ## ๐Ÿ“ฑ ๊ตฌํ˜„ ํ™”๋ฉด |**๋ฉ”์ธ ํ™”๋ฉด** | **์ธก์ • ํ™”๋ฉด** | | -------- | -------- | |![](https://i.imgur.com/mUKJ5s3.gif)| ![](https://i.imgur.com/17Hyo3a.gif) | <br> | Play ํ™”๋ฉด | View ํ™”๋ฉด | | -------- | -------- | | ![](https://i.imgur.com/OEqRGZg.gif) | ![](https://i.imgur.com/EsIpraY.gif) | <br> **FileManager ์ €์žฅ** - ๊ทธ๋ž˜ํ”„๋ฅผ ๊ทธ๋ ค์ฃผ๋Š” ๋ชจ๋ธ์„ ์ €์žฅ - file url ๊ฒฝ๋กœ๋ฅผ ํƒ€๊ณ  ๋“ค์–ด๊ฐ€๋ฉด ์•„๋ž˜์™€ ๊ฐ™์€ ํŒŒ์ผ์ด ์ƒ์„ฑ๋˜์–ด ์žˆ์Œ ![](https://i.imgur.com/u09xI0C.png) **CoreData ์ €์žฅ** - ํ…Œ์ด๋ธ” ๋ทฐ ์…€์„ ๊ทธ๋ ค์ฃผ๋Š” ๋ชจ๋ธ์„ CoreData์— ์ €์žฅ <br> ## ๐Ÿ‘ฉ๐Ÿปโ€๐Ÿ’ป ์ฝ”๋“œ ์„ค๋ช… <details> <summary> CoreData </summary> - `GraphFileManager` : File์— json ๋ฐ์ดํ„ฐ ํ˜•ํƒœ๋กœ ๊ทธ๋ž˜ํ”„ ๊ด€๋ จ ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜๋Š” FileManager Manager - `CoreDataManager` : CoreData์— key value ํ˜•ํƒœ๋กœ ์…€ ๊ด€๋ จ ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜๋Š” CoreData Manager <br> </details> <br> <details> <summary> Model </summary> - `CellModel` : Cell์— ๋ณด์—ฌ์ง€๋Š” ๋ชจ๋ธ ํƒ€์ž… - `GraphModel` : Graph์— ๋ณด์—ฌ์ง€๋Š” ๋ชจ๋ธ ํƒ€์ž… - `AnalysisType` : Acc์™€ Gyro ํƒ€์ž…์„ ์„ ํƒํ•  ์ˆ˜ ์žˆ๋Š” enum </details> <br> <details> <summary> Manager </summary> - `AnalysisManager` : ์ธก์ •์„ ์‹œ์ž‘ํ•˜๊ณ  ์ข…๋ฃŒํ•˜๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ํƒ€์ž… </details> <br> <details> <summary> Domain </summary> - `GraphRecordViewModel`: ๊ทธ๋ž˜ํ”„์™€ ๊ด€๋ จ๋œ ๋ชจ๋ธ์„ ์ „๋‹ฌ๋ฐ›์•„ ๋ทฐ์ปจํŠธ๋กค๋Ÿฌ์— ์ „๋‹ฌํ•ด์ฃผ๋Š” ๋ทฐ ๋ชจ๋ธ - `GraphRecordViewController`: ์ผ๋ฐ˜ View์™€ Play View๋ฅผ ์กฐ๊ฑด์— ๋งž๊ฒŒ ํ™”๋ฉด์— ๋ณด์—ฌ์ฃผ๋Š” ๋ทฐ ์ปจํŠธ๋กค๋Ÿฌ - `AnalyzeListViewController`: ์ฒซ ๋ฒˆ์งธ ํ™”๋ฉด, ์ธก์ •์ด ์™„๋ฃŒ๋˜๋ฉด ๊ธฐ๋ก๋˜๋Š” ํ…Œ์ด๋ธ” ๋ทฐ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ๋ทฐ ์ปจํŠธ๋กค๋Ÿฌ - `AnalyzeListViewModel`: ์…€์— ๋ณด์—ฌ์ค„ ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌํ•ด์ฃผ๋Š” ๋ทฐ ๋ชจ๋ธ - `AnalysisTableViewCell`: ํ…Œ์ด๋ธ” ๋ทฐ์— ๋ณด์—ฌ์งˆ ์˜คํ† ๋ ˆ์ด์•„์›ƒ๊ณผ ์š”์†Œ๋“ค์„ ์„ค์ •ํ•œ ์…€ - `HostingViewController`: SwiftUI์˜ ๋ทฐ์™€ UIKit์˜ ์ฝ”๋“œ๋ฅผ ์—ฐ๊ฒฐํ•ด์ฃผ๊ธฐ ์œ„ํ•ด ์ƒ์„ฑํ•œ ๋ทฐ ์ปจํŠธ๋กค๋Ÿฌ - `AnalyzeViewController`: ์ธก์ • ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด ๊ทธ๋ž˜ํ”„๊ฐ€ ์‹ค์‹œ๊ฐ„์œผ๋กœ ์ธก์ •๋˜์–ด ๊ทธ๋ ค์ง€๋Š” ํ™”๋ฉด์„ ๋ณด์—ฌ์ฃผ๋Š” ๋ทฐ ์ปจํŠธ๋กค๋Ÿฌ - `AnalyzeViewModel`: ์ธก์ •๋œ ๊ฐ’์„ ์ฝ”์–ด๋ฐ์ดํ„ฐ์— ์ €์žฅํ•˜๋Š” ๋ทฐ ๋ชจ๋ธ </details> <br> <details> <summary> Extension </summary> - `UIColor+`: ์ž์ฃผ ์‚ฌ์šฉ๋˜๋Š” ์ƒ‰์„ ์ง€์ •ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ™•์žฅ - `UIView+` : ๋ทฐ์ปจํŠธ๋กค๋Ÿฌ์— ๋ทฐ๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๊ธฐ๋Šฅ์„ ํ™•์žฅ - `Date+`: DateFormatter๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋‚ ์งœ ํ˜•์‹ ๊ธฐ๋Šฅ ํ™•์žฅ </details> <br> <details> <summary> SupportFile </summary> - `GyroData`: CoreData์— ์กด์žฌํ•˜๋Š” Entity ํƒ€์ž… </details> <br> ## ๐Ÿ“ ํด๋” ๊ตฌ์กฐ ``` . โ”œโ”€โ”€ AppDelegate.swift โ”œโ”€โ”€ CoreData โ”‚ย ย  โ”œโ”€โ”€ CoreDataManager.swift โ”‚ย ย  โ””โ”€โ”€ GraphFileManager.swift โ”œโ”€โ”€ Domain โ”‚ย ย  โ”œโ”€โ”€ Analyze โ”‚ย ย  โ”‚ย ย  โ”œโ”€โ”€ AnalyzeViewController.swift โ”‚ย ย  โ”‚ย ย  โ”œโ”€โ”€ AnalyzeViewModel.swift โ”‚ย ย  โ”‚ย ย  โ””โ”€โ”€ HostingViewController.swift โ”‚ย ย  โ”œโ”€โ”€ GraphView.swift โ”‚ย ย  โ”œโ”€โ”€ Record โ”‚ย ย  โ”‚ย ย  โ”œโ”€โ”€ GraphRecordView.swift โ”‚ย ย  โ”‚ย ย  โ””โ”€โ”€ GraphRecordViewModel.swift โ”‚ย ย  โ””โ”€โ”€ TableView โ”‚ย ย  โ”œโ”€โ”€ AnalyzeListViewController.swift โ”‚ย ย  โ”œโ”€โ”€ AnalyzeListViewModel.swift โ”‚ย ย  โ””โ”€โ”€ Cell โ”‚ย ย  โ””โ”€โ”€ AnalysisTableViewCell.swift โ”œโ”€โ”€ Extension โ”‚ย ย  โ”œโ”€โ”€ UIColor+.swift โ”‚ย ย  โ”œโ”€โ”€ UIDate+.swift โ”‚ย ย  โ””โ”€โ”€ UIView+.swift โ”œโ”€โ”€ Manager โ”‚ย ย  โ””โ”€โ”€ AnalysisManager.swift โ”œโ”€โ”€ Model โ”‚ย ย  โ””โ”€โ”€ AnalysisType.swift โ”œโ”€โ”€ SceneDelegate.swift โ”œโ”€โ”€ SupportFile โ”‚ย ย  โ”œโ”€โ”€ Assets.xcassets โ”‚ย ย  โ”‚ย ย  โ”œโ”€โ”€ AccentColor.colorset โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ””โ”€โ”€ Contents.json โ”‚ย ย  โ”‚ย ย  โ”œโ”€โ”€ AppIcon.appiconset โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ””โ”€โ”€ Contents.json โ”‚ย ย  โ”‚ย ย  โ””โ”€โ”€ Contents.json โ”‚ย ย  โ”œโ”€โ”€ Base.lproj โ”‚ย ย  โ”‚ย ย  โ””โ”€โ”€ LaunchScreen.storyboard โ”‚ย ย  โ”œโ”€โ”€ GyroData.xcdatamodeld โ”‚ย ย  โ”‚ย ย  โ””โ”€โ”€ GyroData.xcdatamodel โ”‚ย ย  โ”‚ย ย  โ””โ”€โ”€ contents โ”‚ย ย  โ””โ”€โ”€ Info.plist โ””โ”€โ”€ ios-wanted-GyroData.txt ``` ## โšก๏ธ ํŠธ๋Ÿฌ๋ธ” ์ŠˆํŒ… ### 1. UIKit๊ณผ SwiftUI์˜ Charts์˜ ๋ฐ์ดํ„ฐ ๋ฐ”์ธ๋”ฉ ์ฒ˜์Œ ๊ณผ์ œ๋ฅผ ๋ฐ›๊ณ  ์ฐจํŠธ๋ฅผ ๊ทธ๋ฆฌ๋ ค๊ณ  ํ•  ๋•Œ ์˜ฌํ•ด **WWDC**์—์„œ ๋ณด์•˜๋˜ **SwiftUI Charts**๊ฐ€ ์ƒ๊ฐ์ด ๋‚ฌ์Šต๋‹ˆ๋‹ค. iOS16์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์‹  ๊ธฐ์ˆ ์ด๊ธฐ๋„ ํ•ด์„œ ํ•œ๋ฒˆ ์ ์šฉํ•ด๋ณด๊ณ  ์‹ถ์€ ๋งˆ์Œ์— SwiftUIView๋ฅผ ๊ทธ๋ ค์„œ **UIHostingViewcontroller**๋ฅผ ์ด์šฉํ•˜์—ฌ ์‚ฌ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค. charts๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋งŒ๋“  ๊ทธ๋ž˜ํ”„๋ทฐ์— ๋ฐ์ดํ„ฐ๊ฐ€ ๋ฐ”๋กœ ๋ฐ˜์˜์ด ๋˜์ง€์•Š๋Š” ํŠธ๋Ÿฌ๋ธ”์ด ์ผ์–ด๋‚ฌ์Šต๋‹ˆ๋‹ค. ์ปด๋ฐ”์ธ์„ ์‚ฌ์šฉํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ๋ฐ์ดํ„ฐ ๋ฐ”์ธ๋”ฉ์ด ์ž˜ ๋์„๊ฑฐ๋ผ๊ณ  ํŒ๋‹จ์„ ํ–ˆ์—ˆ์ง€๋งŒ ๊ทธ๊ฒƒ์€ UIKit์˜ ๊ด€์ ์—์„œ๋Š” ๋‹น์—ฐํ–ˆ์ง€๋งŒ SwiftUIView๋Š” ํ”„๋กœํผํ‹ฐ๋ ˆํผ๋กœ ๋ฐ”์ธ๋”ฉ๋œ ๋ฐ์ดํ„ฐ์—๋งŒ ๋ทฐ๋ฅผ ์ƒˆ๋กœ ๊ทธ๋ฆฌ๊ธฐ ๋•Œ๋ฌธ์— ๋‹ค๋ฅธ๋ฐฉ๋ฒ•์„ ์ฐพ์•„์•ผ ํ–ˆ์Šต๋‹ˆ๋‹ค. ์ฒ˜์Œ์—๋Š” ObservableObject๋ฅผ ์ด์šฉํ•˜์—ฌ ๋ฐ”์ธ๋”ฉ์„ ์‹œ๋„ ํ–ˆ์—ˆ๋Š”๋ฐ ์–ด๋–ค ์ด์œ ์—์„ ์ง€ ๋ฐ”์ธ๋”ฉ์ด ์ž˜ ๋˜์ง€ ์•Š์•˜๊ณ  Environmentobject๋ฅผ ํ™œ์šฉํ•˜๊ธฐ๋กœ ํ–ˆ์Šต๋‹ˆ๋‹ค. ์ผ๋ฐ˜์ ์ธ ๋ฐ์ดํ„ฐ์˜ ์ „๋‹ฌ์€ ObservableObject๋ฅผ ์ด์šฉ ํ•˜์ง€๋งŒ ๋ชจ๋“  ๋ทฐ๊ฐ€ ๋™์ผ ํ•œ ๋ชจ๋ธ์„ ๊ฐ€๋ฆฌํ‚ค๊ณ  ๋ฐ์ดํ„ฐ์˜ ๋ณ€ํ™”์— ์ฆ‰์‹œ ์—…๋ฐ์ดํŠธ๊ฐ€ ํ•„์š”ํ•œ ๊ฒฝ์šฐ์— ์‚ฌ์šฉํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. **Environmentobject**์˜ ์žฅ์ ์ด ๋ฐ์ดํ„ฐ์˜ ๋ณ€๊ฒฝ์— ๋”ฐ๋ผ ์–ด๋–ค ๋ถ€๋ถ„์ด๋“  ๋™๊ธฐํ™”๋ฅผ ๋ณด์žฅ ํ•œ๋‹ค๋Š” ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ### 2. ๋‹จ๋ฐฉํ–ฅ ๊ตฌ์กฐ์˜ MVVM ์„ค๊ณ„ <img src="https://i.imgur.com/3kUJ679.png" width="600"/> ๋ฐ์ดํ„ฐ ํ๋ฆ„์„ ์˜ค์ง **๋‹จ๋ฐฉํ–ฅ**์œผ๋กœ ํ๋ฅด๊ฒŒ ๊ตฌํ˜„ํ–ˆ์Šต๋‹ˆ๋‹ค. ๋ฐ์ดํ„ฐ ํ๋ฆ„์ด ๋‹จ์ˆœํ•˜์—ฌ ์ƒˆ๋กœ์šด ๊ธฐ๋Šฅ์ด ์ถ”๊ฐ€๋˜์–ด๋„ ๋ฆฌํŒฉํ† ๋ง์— ์šฉ์ดํ•ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ Swift์˜ **ํ”„๋กœํ† ์ฝœ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ํŒจ๋Ÿฌ๋‹ค์ž„**์„ ์ฑ„ํƒํ•˜์—ฌ ViewModel์˜ Input ์‹œ๊ทธ๋„๊ณผ Output ์‹œ๊ทธ๋„ ๋ชจ๋‘๋ฅผ Protocol์„ ์‚ฌ์šฉํ•˜์—ฌ ์ธํ„ฐํŽ˜์ด์Šคํ™” ํ–ˆ์Šต๋‹ˆ๋‹ค. <br> ### 3. Model ํƒ€์ž…์— ๋Œ€ํ•œ ๊ณ ๋ฏผ ์ฒ˜์Œ Model์„ ๊ตฌ์ƒํ•˜์˜€์„ ๋•Œ์—๋Š” Model ๋‚ด๋ถ€ ํ”„๋กœํผํ‹ฐ์˜ ํƒ€์ž…์— ์•„๋ž˜์™€ ๊ฐ™์ด Core Data์—์„œ ์ œ๊ณตํ•˜๋Š” ๊ธฐ๋ณธ ํƒ€์ž…์ด ์•„๋‹Œ ์ปค์Šคํ…€ํ•œ ํƒ€์ž…์ด ์กด์žฌํ–ˆ์Šต๋‹ˆ๋‹ค. ```swift struct GyroDataModel: Codable { let id: UUID let analysisType: AnalysisType let savedAt: [Date] let measurementTime: Double } ``` ์ปค์Šคํ…€ ํ•œ ํƒ€์ž…์ธ `AnalysisType, [Date]` ๋“ฑ์„ **Core Data**์— ๋„ฃ์–ด์ฃผ๊ณ ์ž ํ–ˆ์œผ๋‚˜ ์ด๋ฏธ ๋งŒ๋“ค์–ด์ง„ entity์™€ ํŒŒ์ผ์„ ์ˆ˜์ •ํ•˜๋Š” ๊ฒƒ์— ์–ด๋ ค์›€์„ ๊ฒช์—ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ `์•„์ดํฐ ์•ฑ๋งˆ๋‹ค ์กด์žฌํ•˜๋Š” ๊ณต๊ฐ„์„ ๊ด€๋ฆฌํ•˜๋Š” ๋งค๋‹ˆ์ €`์ธ **FileManager**๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ์‹์„ ์ถ”๊ฐ€ํ•˜์˜€์Šต๋‹ˆ๋‹ค. ๊ฒฐ๋ก ์ ์œผ๋กœ **CoreData**๋Š” `์…€์— ๋ณด์—ฌ์ง€๋Š” ๊ธฐ๋ณธ์ ์ธ ํƒ€์ž…์„ ์ €์žฅ`ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉํ–ˆ๊ณ , **FileManager**๋Š” `์•„์ดํฐ ์•ฑ ๋‚ด๋ถ€ ๊ฒฝ๋กœ์— json ํ˜•ํƒœ๋กœ ์ปค์Šคํ…€ ํ•œ ํƒ€์ž…์„ ์ €์žฅ`ํ•  ๋•Œ ์‚ฌ์šฉํ•˜์—ฌ ๋‘ ๊ฐ€์ง€ ๋ฐฉ์‹์„ ๋ชจ๋‘ ์ฑ„ํƒํ•˜์˜€์Šต๋‹ˆ๋‹ค. ## ๐Ÿ”— ์ฐธ๊ณ  ๋งํฌ - [FileManager](https://leeari95.tistory.com/32) - [FileManager](https://developer.apple.com/documentation/foundation/filemanager) - [Combine](https://developer.apple.com/documentation/combine) - [Charts](https://developer.apple.com/documentation/charts/creating-a-chart-using-swift-charts) - [environmentobject๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๋ฐ์ดํ„ฐ ๋ฐ”์ธ๋”ฉ](https://www.hackingwithswift.com/quick-start/swiftui/whats-the-difference-between-observedobject-state-and-environmentobject)