웹 소설이나 출판 소설, 게임 스토리 등 내용을 담은 글이라면 모든 상관없이 글을 읽고 느낀 감정에 대한 기록을 남기는 앱.
무언가 잘 못 먹었는지 탈이 났다... 운동도 가지 못하고 골골거리며 회복중인지라 오늘은 푹 쉰 후 내일 다시 작업을 시작해야겠다.
추가로 PopupMenuItem 관련으로 Flutter 이슈에 올린 것에 대한 피드백이 와서 확인해 보니 popupMenu
의 최소 width 치가 적용된 것이라고 한다.
constraints를 사용해 width를 제어하는 방법이 해당 문제를 위해 설계되는 것이라고 알려주며 이후 해당 이슈는 close 되었다. 이번 프로젝트를 진행하며 다양한 경험을 하게 되는 것 같아 기쁘다.
몸 상태가 무리없이 움직일 정도는 되어서 운동 후 개발 진행하였다.
지난주 발견하였던 카테고리 UI 영역을 상위 위젯에서 겹쳐지는 문제의 경우 GridView에 childAspectRatio
로 item 가로 세로 비율을 설정해주는 것으로 해결하였다!
도움이 된 링크
https://stackoverflow.com/questions/69586316/how-to-prevent-gridview-from-shrinking-in-flutter
홈 메인 화면에도 GetView
를 통한 컨트롤러 사용으로 코드 개선을 진행하고 히스토리 화면 작업을 진행하고 있다.
다른 부분에서 큰 어려움은 없지만 Clipper에 외곽선과 함께 모양 변형 주는 부분에서 조금 애먹는 중... Clipper는 역시 사용히 어려운 것 같다. 그래도 노력 끝에 원하는 모양은 완성할 수 있었다.
히스토리 화면 구현 및 작품 상세 화면에 대한 개선을 진행하였다.
또한 서버에서 받아오는 데이터의 순서가 최신순으로 들어오지 않아 정렬을 하여 최신순으로 확인 가능하도록 수정하였으며, 그 이외에는 별다른 어려움이 존재하지 않았다.
화면 상세에서 특정 기능들은 UI만 먼저 구현되어 있는 상태이기 때문에 다음 작업은 해당에 관한 상세 기능 구현으로 아래의 작업을 진행할 예정이다. 💪
오후에 따로 일정이 있었다, 모든 걸 떠나서 정말 좋은 자리였다.
나에게 부족한 점이 뭔지 자세하게 알 수 있었고 보완해야 할 점을 새로운 시각으로 보며 듣고 다양한 깨달음과 함께 나 자신이 부끄러워졌다.
이렇게 후회할 만한 어린 행동들을 했었구나 하며. 일정을 진행하며 들었던 정보들은 개인적으로 복기하며 보완해 나가야겠다.
일정 소화 후에는 저녁 중에 작품 및 감상 삭제 기능 제작을 진행하였다.
삭제 기능에서 다소 헤메기도 하였는데 FirebaseStore
의 경우 doc
의 하위로 필드까지 들어가면 삭제가 불가능하기에 작품 삭제 후 해당 작품에 대한 감상을 일괄적으로 삭제할 때 아래와 같이 연속해서 삭제 요청을 던져야만 했다.
해당 방식으로 아래와 같은 코드가 나왔다, 묘하게 복잡스러운 코드로 보인다.
Future<void> deleteReports(String workServerId) async {
final QuerySnapshot deleteReport = await firebaseStore.store
.collection("report")
.where("workServerId", isEqualTo: workServerId)
.get(); // 작품코드를 통해 하위 리포트 가져오기
for (var report in deleteReport.docs) {
try {
firebaseStore.store.collection("report").doc(report.id).delete();
} catch (e) {
rethrow;
}
}
}
더 깔끔하고 최적화하며 구현할 수 있는 방법을 찾아봐야겠다.
팀 프로젝트 진행 후 시간이 남아 아래와 같이 개선해 보았다.
내일 관련 코드들 한꺼번에 관련 개선 형태로 전환해야겠다.
Future<void> deleteReports(String workServerId) async {
try {
final QuerySnapshot deleteReport = await firebaseStore.store
.collection("report")
.where("workServerId", isEqualTo: workServerId)
.get(); // 작품코드를 통해 하위 리포트 가져오기
// 비동기적으로 여러 문서를 삭제하기를 기다리기
await Future.wait(
deleteReport.docs.map((report) async {
if (report.exists) { // 문서가 존재하는지 확인 후 삭제
await firebaseStore.store.collection("report").doc(report.id).delete();
}
}),
);
} catch (e) {
rethrow;
}
}
provider, controller 코드 개선과 함께
작품 공통 감상 작성을 위한 작품 코드 확인 및 입력 UI 제작을 진행하였다.
팀 사이드 프로젝트 쪽을 일정에 맞추어 빠르게 작업하기 위해 일단 UI 먼저 제작하였고, 이후 작품을 공통으로 사용하기 위한 API 연결과 작품을 같이 불러와 어떻게 구분해 사용할지에 대해 고민하고 작업하게 될 것 같다.
공통 작품에 대한 내용은 Firebase 실시간 데이터베이스를 통해 아래와 같은 구조로 저장하고 있었지만 현재 해당 데이터베이스 하위의 데이터를 체크하고 유저를 추가하는 작업을 진행하려 하니 현 구조가 비효율적이라는 걸 알 수 있었다.
본래는 work 하위로 작품 ID가 Key가 되고 그 하위로 초대 코드와 허용 유저를 저장하는 방식으로 구조를 잡았었다.
하지만 앱에서는 초대 코드로 허용 작품을 찾아야 하기에 작품 ID가 Key가 되면 모든 하위를 돌아가며 코드를 확인해야 하는 문제가 생긴다. 즉, 필요 이상으로 데이터 검증이 많이 필요하게 된 것이다.
처음에는 해당 문제를 크게 인지하지 못했다가 구현하게 되니 문제를 인지할 수 있게 되어 Key를 작품 ID가 아닌 초대 코드로 두고 하위에 작품 ID를 두는 것으로 데이터 구조 변경 예정이다.
구조 변경 후 앱에서의 연결을 진행하였다.
유저 데이터에 추가된 초대 코드 저장 및 로그인 시 로드 후 Prefs로 저장, 초대된 작품 정보 앱 시작 시 가져오기와 초대 코드 등록 후 화면에 등록하는 등 생각보다 추가적으로 진행해야 하는 것들이 많아 시간이 걸렸지만 만족스럽게 작동한다!
그 과정 속에서 초대 작품을 가져오는 기능을 추가하면서 초대 코드들이 List<String>
으로 저장되어 있어 해당 방법을 찾는 데 조금 시간이 걸리기도 했다. 해결 방법은 아래와 같이 비교하여 사용하면 리스트 와 리스트를 대조해 결과를 얻을 수 있었다.
Future<QuerySnapshot> getInviteWork() async {
final inviteWorks = PrefsUtils.getStringList(PrefsUtils.inviteWork);
return await firebaseStore.store
.collection('work')
.where("inviteCode", whereIn: inviteWorks)
.get();
}
위 코드에서 사용된 whereIn
은 배열 형태로 여러 값을 받아서 해당 필드가 그중 하나와 일치하는지를 검사하는 기능이다.
작품 공유 후속으로 감상에 대한 공유도 진행하고 있다, 다만 고민인 것이 생겼다면 감상의 현 데이터 구조로는 바로 원하는 값을 가져올 수 없다는 것.
데이터 구조는 초대 코드를 가지고 있지 않기 때문에 가져오기 위해서는 작품의 ID가 필요하다.
현재 상태로는 개발 방법은 3가지 정도 있다.
굳이 데이터를 쌓지 않고 필요시에만 가져오는 첫 번째 방안이 그나마 좋은 방향인 것 같아 지금은 추가 좀 기울어져 있지만 위 방법 중 어느 방향으로 진행할지 고민이다.
결국 첫 번째 방법을 이용해 개발하였다.
공유된 작품에 대한 삭제나 타 유저가 작성한 감상에 대한 수정 및 삭제 불가능하도록 분기 처리를 진행하고 동시에 공유된 작품, 감상인지 유저가 구분할 수 없는 UI였기에 각 위젯 하단에 공유 표시를 보이도록 UI 쪽도 함께 개선 진행하도록 하였다.