Skip to content

Commit

Permalink
docs: Update README.md
Browse files Browse the repository at this point in the history
  • Loading branch information
maxhyunm authored Sep 15, 2023
1 parent bf0abb4 commit 18725b6
Showing 1 changed file with 113 additions and 23 deletions.
136 changes: 113 additions & 23 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# 📔 일기장
프로젝트 기간: 2023.8.28 ~
프로젝트 기간: 2023.8.28 ~ 2023.9.15

## 📖 목차
1. [🍀 소개](#1.)
Expand Down Expand Up @@ -38,7 +38,10 @@
|2023.09.01| `CoreData`: `Create` 구현|
|2023.09.05| `CoreData`: `UpDate`, `Delete` 구현 <br> `Swipe` `share`, `delete` 구현 <br> `AlertController` 생성 |
|2023.09.06| `CoreData`: `fetchDiary` 구현 |
|2023.09.07| 개인 학습 및 README 작성 |
|2023.09.07| 개인 학습 및 `README` 작성 |
|2023.09.10| `CoreDataError` 생성, 예외처리 추가<br>`AlertVC`로직수정, `Namespace`생성 |
|2023.09.13| `WeatherAPI`통신 진행<br> `WeatherIcon Cache` 구현 <br> `CoreLocation` 생성 <br> `Migration-DiaryV2` 구현 |


</br>

Expand All @@ -48,46 +51,60 @@
├── Diary
│   ├── Protocol
│   │   ├── AlertDisplayble.swift
│   │   └── ShareDiary.swift
│   ├── DataManager
│   │   └── CoreDataManager.swift
│   │   └── ShareDisplayable.swift
│   ├── Extension
│   │   └── DateFormatter+.swift
│   ├── Model
│   │   ├── Diary+CoreDataClass.swift
│   │   ├── Diary+CoreDataProperties.swift
│   │   ├── DecodingManager.swift
│   │   └── DiaryEntity.swift
│   ├── Error
│   │   ├── APIError.swift
│   │   ├── CoreDataError.swift
│   │   └── DecodingError.swift
│   ├── Model
│   │   ├── CoreData
│   │   │   ├── CoreDataManager.swift
│   │   │   ├── Diary+CoreDataClass.swift
│   │   │   └── Diary+CoreDataProperties.swift
│   │   ├── DTO
│   │   │   ├── DecodingManager.swift
│   │   │   └── WeatherResult.swift
│   │   ├── ImageCache
│   │   │   └── ImageCachingManager.swift
│   │   └── Namespace
│   │   ├── AlertNamespace.swift
│   │   └── ButtonNamespace.swift
│   ├── Network
│   │   ├── NetworkConfiguration.swift
│   │   └── NetworkManager.swift
│   ├── Controller
│   │   ├── CreateDiaryViewController.swift
│   │   ├── DiaryDetailViewController.swift
│   │   └── DiaryListViewController.swift
│   ├── View
│   ├── View
│   │ └── DiaryListTableViewCell.swift
│   ├── App
│   │   ├── AppDelegate.swift
│   │   └── SceneDelegate.swift
│   ├── Assets.xcassets
│   ├── Info.plist
│   └── Diary.xcdatamodeld
└── Diary.xcodeproj
├── Diary.xcodeproj
└── README.md

</br>

<a id="5."></a></br>
## 💻 실행 화면

|작동 화면|
| 작동화면 |
|:--:|
|<img src="https://hackmd.io/_uploads/SJkqEgUC3.gif" width="300" height="600"/>|
|<img src="https://hackmd.io/_uploads/H1kYxge1T.gif" width="300"/>|

</br>

<a id="6."></a></br>
## 🪄 핵심 경험
#### 🌟 CoreData를 활용한 데이터 저장
일기 데이터를 위한 저장소로 CoreData를 활용하였습니다.
#### 🌟 MappingModel 파일을 활용한 CoreData Migration 진행
CoreData의 버전 정보를 추가하고 이를 MappingModel로 연결하여 DB 변경사항에 대한 Migration을 진행하였습니다.
#### 🌟 Singleton 패턴을 활용한 CoreDataManager 구현
데이터 처리를 위한 로직 전반을 Singleton 패턴으로 구현하여 앱 전역에서 활용 가능하도록 하였습니다.
#### 🌟 NotificationCenter를 활용한 키보드 인식
Expand All @@ -96,6 +113,8 @@
상황에 따라 ViewController에서 다른 데이터를 표시해야 하는 경우에 대비해 생성자를 활용하였습니다.
#### 🌟 Protocol과 Extension을 활용한 코드 분리
Alert, Swipe 등 별개의 작업으로 분리할 수 있는 내용들은 Protocol과 Extension을 통해 분리하였습니다.
#### 🌟 URLSessionDataTask를 활용한 NetworkManager 구현
하나의 NetworkManager 타입을 구현하여 날씨 API 데이터 통신과 아이콘 이미지 관련 통신에 모두 활용하였습니다.

</br>

Expand Down Expand Up @@ -212,16 +231,87 @@ fetch해 온 일기들 중에 title이 비어있는 건은 걸러낼 수 있도
}
}
```
</br></br>

### 4️⃣ **아이콘 이미지 통신**
🔒 **문제점**</br>
일기장 앱은 모든 셀이 서버통신을 통해 아이콘을 가지고 오도록 구현되어 있습니다. 하지만 날씨 아이콘은 몇 개의 정해진 아이콘을 반복하여 활용합니다. 따라서 동일한 이미지를 매번 통신을 통해 가져오는 것은 비효율적이라고 생각되었습니다.
</br></br>

🔑 **해결방법**</br>
한 번 활용된 이미지는 `NSCache`를 통해 캐싱 처리하여 바로 보여줄 수 있도록 구현하였습니다.

```swift
class ImageCachingManager {
static let shared = NSCache<NSString, UIImage>()
...
}
```

```swift
guard let image = UIImage(data: data) else { return }
DispatchQueue.main.async {
ImageCachingManager.shared.setObject(image, forKey: NSString(string: icon))
self?.weatherIconImageView.image = image
}
```
</br></br>

### 5️⃣ **CoreLocation**
🔒 **문제점 (1) - CoreLocation을 통해 정보를 받아오는 위치**</br>

실질적으로 Location 정보가 필요한 것은 `DiaryDetailViewController`에서 날씨 API를 호출할 때입니다. 때문에 처음에는 `DiaryDetailViewController`에서 활용 동의를 받고 위치 정보를 업데이트하도록 구현하려 하였습니다. 하지만 이렇게 하면 앱을 실행한 뒤 일기장 생성 화면에 넘어가서야 위치정보 활용 동의 창이 활성화되어 흐름상 어색해지고, 또 위치 정보가 제때 업데이트되지 않아 API 호출이 이루어지지 않는 등 다양한 문제가 발생했습니다.
</br></br>

🔑 **해결방법 (1)**</br>
위치 정보 업데이트 자체는 첫 화면인 `DiaryListViewController`에서 진행하고, `DiaryDetailViewController`에서는 API 통신에 필요한 위도, 경도 데이터만 넘겨받을 수 있도록 구현하였습니다.
```swift
let createDiaryView = DiaryDetailViewController(latitude: self.latitude, longitude: self.longitude)
self.navigationController?.pushViewController(createDiaryView, animated: true)
```

또한 위치정보 활용에 동의하지 않은 경우에도 일기 자체는 작성 가능하도록 구현하기 위해(날씨 이모티콘만 제외) 위도, 경도 데이터는 nil로도 전달될 수 있도록 하였습니다.

```swift
init(latitude: Double?, longitude: Double?) {
self.diary = CoreDataManager.shared.createDiary()
self.isNew = true
self.latitude = latitude
self.longitude = longitude

super.init(nibName: nil, bundle: nil)
fetchWeather()
}
```
</br></br>

🔒 **문제점 (2) - 시뮬레이터의 위치 정보 설정**</br>

시뮬레이터로 `CoreLocation` 기능을 테스트하면 시뮬레이터 자체에 설정된 Location 정보에 따라 위치를 표시하게 됩니다. 따라서 이 설정이 None으로 되어있을 경우에는 위치가 정상적으로 불러와지지 않습니다. 이 사실을 간과하여 테스트 과정에서 많은 시행착오를 거쳤습니다.
</br></br>

🔑 **해결방법 (2)**</br>

Custom Location을 활용하여 정상적으로 테스트를 진행할 수 있었습니다.</br>
<img src="https://hackmd.io/_uploads/BJ20Xkgyp.png" width="500">
</br>


<a id="8."></a></br>
## 📚 참고 링크
- [Apple Developer Documentation: Adaptivity and Layout](https://developer.apple.com/design/human-interface-guidelines/layout)
- [Apple Developer Documentation: DateFormatter](https://developer.apple.com/documentation/foundation/dateformatter)
- [Apple Developer Documentation: UITextView](https://developer.apple.com/documentation/uikit/uitextview)
- [Apple Developer Documentation: Core Data](https://developer.apple.com/documentation/coredata)
- [Apple Developer Documentation: Making Apps with Core Data](https://developer.apple.com/videos/play/wwdc2019/230/)
- [Apple Developer Documentation: NSFetchedResultsController](https://developer.apple.com/documentation/coredata/nsfetchedresultscontroller)
- [Apple Developer Documentation: UITextViewDelegate](https://developer.apple.com/documentation/uikit/uitextviewdelegate)
- [Apple Developer Documentation: UISwipeActionsConfiguration](https://developer.apple.com/documentation/uikit/uiswipeactionsconfiguration)

- [Apple Docs: Adaptivity and Layout](https://developer.apple.com/design/human-interface-guidelines/layout)
- [Apple Docs: DateFormatter](https://developer.apple.com/documentation/foundation/dateformatter)
- [Apple Docs: UITextView](https://developer.apple.com/documentation/uikit/uitextview)
- [Apple Docs: Core Data](https://developer.apple.com/documentation/coredata)
- [Apple Docs: Making Apps with Core Data](https://developer.apple.com/videos/play/wwdc2019/230/)
- [Apple Docs: NSFetchedResultsController](https://developer.apple.com/documentation/coredata/nsfetchedresultscontroller)
- [Apple Docs: UITextViewDelegate](https://developer.apple.com/documentation/uikit/uitextviewdelegate)
- [Apple Docs: UISwipeActionsConfiguration](https://developer.apple.com/documentation/uikit/uiswipeactionsconfiguration)
- [Apple Docs: CoreLocation](https://developer.apple.com/documentation/corelocation)
- [Apple Docs: Migrating your data model automatically](https://developer.apple.com/documentation/coredata/migrating_your_data_model_automatically)
- [Apple Docs: NSCache](https://openweathermap.org/current)
- [Open Weather API](https://openweathermap.org/current)

</br>

0 comments on commit 18725b6

Please sign in to comment.