owned this note
owned this note
Published
Linked with GitHub
# 동기화 메모장 [STEP3/4] Jiseong, Toni, 애플사이다
## STEP3 구현내용 및 고민한 점
### 구현 내용
- 클라우드 (Dropbox) 연동을 위해 Cocoa Pod 및 SwiftyDropbox 라이브러리를 활용했습니다.
- 코어데이터를 다른 기기와 동기화 할 수 있도록 DropBoxManager 타입 및 uploadToDropBox/downloadFromDropBox 메서드를 구현했습니다.
- 클라우드 다운로드 시점 : 앱 실행 시 초기화면에서 DropBox Safari ViewController를 present하고, DropBox 로그인이 성공했을 때 다운로드 하도록 구현하였습니다. (추후 로그인 실패 후 다시 로그인 시도를 할 수 있도록 버튼을 추가할 예정입니다.)
- 클라우드의 데이터를 다운로드하여 저장하는 위치는 PersistentContainer의 `defaultDirectoryURL`으로 설정했고, overwrite 모드로 구현하였습니다.
- 클라우드 업로드 시점 : 메모 추가/삭제할 때, 메모 업데이트할 때 (`textViewDidEndEditing` 메서드) 업로드를 하도록 구현하였습니다.
- 메모를 추가/삭제/수정할 때 (사용자가 메모를 작성한 뒤) 클라우드에 저장되어있는 데이터와 사용자의 CoreData에 저장되어 있는 데이터는 일치하므로 클라우드의 데이터를 다운받을 때 Overwrite를 하여도 문제가 없도록 구현하였습니다.
## STEP4 구현내용 및 고민한 점
### SearchBar 추가
- 메모 목록 상단에 SearchBar를 구현했습니다. 사용자의 입력값을 제목 또는 본문에 포함하고 있는 메모를 검색결과로 보여주도록 했습니다.
- 이를 위해 `Custom TableViewController`인 `searchResultViewController` 타입을 추가했습니다. 그리고 MaterTableViewController에서 초기화했고, 생성자 주입을 통해 MaterTableViewController의 DataSource의 memos를 전달하도록 했습니다. 그리고 서치바에 텍스트를 입력할 때마다 호출되는 updateSearchResults 메서드 내부에서 searchResultViewController의 searchMemo 메서드를 호출하여 메모를 필터링했습니다.
```swift
final class MasterTableViewController: UITableViewController {
private(set) var memoDataSource: MasterTableViewDataSourceProtocol?
weak var delegate: MemoSelectionDelegate?
lazy var searchResultViewController = SearchResultTableViewController(memos: memoDataSource?.retrieveMemos(), delegate: delegate)
// ...
}
```
- 처음에는 searchResultViewController와 masterTableViewController가 모두 동일한 memos 배열 데이터를 사용하므로 기존의 DataSource를 두 ViewController 모두 사용하도록 시도했습니다. 그런데 이 과정에서 타입캐스팅을 위해 DataSource가 ViewController를 알고 있어야하는 문제가 있었고, 의존성이 다시 높아진다고 판단하여 이 방법을 사용하지 않았습니다.
### Dark Mode 미지원 레이블 추가적으로 지원
테이블 뷰의 텍스트들은 DarkMode를 지원했지만, DetailView의 텍스트뷰의 텍스트는 지원이 안되고 있어 이를 수정해주었습니다.
```swift
// 수정 전
let titleAttributes = [NSAttributedString.Key.font: UIFont.preferredFont(forTextStyle: .title1)]
let bodyAttributes = [NSAttributedString.Key.font: UIFont.preferredFont(forTextStyle: .body)]
// 수정 후
let titleAttributes = [NSAttributedString.Key.font: UIFont.preferredFont(forTextStyle: .title1),
NSAttributedString.Key.foregroundColor: UIColor.label]
let bodyAttributes = [NSAttributedString.Key.font: UIFont.preferredFont(forTextStyle: .body),
NSAttributedString.Key.foregroundColor: UIColor.label]
```
## 해결하지 못한 점
### 1. DropBox 업로드/다운로드 오류
`uploadToDropBox` 메서드로 클라우드 업로드 (overwrite)를 할 때, 처음에는 문제가 없었는데 갑자기 DropBox의 3개 sqlite 파일 중 1개 (CloudNotes.sqlite)만 업데이트가 안되는 문제가 발생했습니다.
CoreData가 저장된 `Application Support` 폴더 내부의 파일을 확인해봤는데, CoreData 파일은 정상적으로 업로드된 것을 확인했습니다. 그리고 업로드 response 출력문을 확인했을 때 3개 파일 모두 정상적으로 업로드된 것을 확인했습니다.

왜 DropBox 폴더에서만 이러한 문제가 발생하는지 파악하고자 콘솔창의 에러문구를 모두 검색해봤지만 해결할 수 없었습니다.
```
// 다운로드 시 발생
CoreData: error: -executeRequest: encountered exception = I/O error for database at /Users/hyojuson/Library/Developer/CoreSimulator/Devices/05F35EA9-9E39-492C-8223-F54BBC92A49F/data/Containers/Data/Application/5D565A17-0D9F-4738-A637-D2A9DA49FFE9/Library/Application Support/CloudNotes.sqlite. SQLite error code:6922, 'disk I/O error' with userInfo = {
NSFilePath = "/Users/hyojuson/Library/Developer/CoreSimulator/Devices/05F35EA9-9E39-492C-8223-F54BBC92A49F/data/Containers/Data/Application/5D565A17-0D9F-4738-A637-D2A9DA49FFE9/Library/Application Support/CloudNotes.sqlite";
NSSQLiteErrorDomain = 6922;
}
[error] error: (6922) I/O error for database at /Users/hyojuson/Library/Developer/CoreSimulator/Devices/05F35EA9-9E39-492C-8223-F54BBC92A49F/data/Containers/Data/Application/5D565A17-0D9F-4738-A637-D2A9DA49FFE9/Library/Application Support/CloudNotes.sqlite. SQLite error code:6922, 'disk I/O error'
// 다운로드 및 업로드 시 발생
[logging] BUG IN CLIENT OF libsqlite3.dylib: database integrity compromised by API violation: vnode unlinked while in use: /Users/hyojuson/Library/Developer/CoreSimulator/Devices/05F35EA9-9E39-492C-8223-F54BBC92A49F/data/Containers/Data/Application/5D565A17-0D9F-4738-A637-D2A9DA49FFE9/Library/Application Support/CloudNotes.sqlite-wal
```
커밋을 되돌리거나, 조원 모두가 실행을 해봐도 같은 오류가 발생하였습니다.
### 2. 메모 추가 직후 검색
기존에 있던 메모를 검색하는 작업은 괜찮았지만 새 메모를 추가직후에 해당 메모는 검색이 안되는 버그가 있습니다.
### 3. 메모 검색 후 삭제
특정 메모를 검색한 뒤 메모를 삭제하면 코어데이터나, 검색창을 끈 뒤의 테이블뷰에서는 정상적으로 삭제가 되는데 검색창을 띄운 상태에선 삭제가 되지 않는 버그가 있습니다.
## 궁금한 점
### `Download`와 `Upload`의 시점
클라우드를 이용한 메모이기에, 어떤 시점에서 클라우드를 통해 데이터를 주고 받을 지에 대한 고민을 해보았습니다.
아무래도 모든 메모는 사용자가 직접 수정 또는 추가하기 전에 가장 최신버전의 메모에 기입을 해야한다고 생각을 해서, `Download`는 앱의 `Scene Delegate`에 구현을 해주었습니다.
그리고 반대로, 사용자가 모든 메모의 작성이 끝나면 `Upload`가 되어야한다고 생각을 했기에, 실제 메모를 적을 수 있는 `textView`의 `Delegate`인 `textViewDidEndEditing 에 구현을 해주었습니다.
이렇게 저희가 생각한 다운로드 및 업로드의 시점이 적절한지 여쭙고 싶습니다.