오늘 작성할 기능을 개발하면서 정말 뚝배기로 내 머리를 내려치고싶었다. 기본적인 것도 까먹어놓고 됐다고 신나했는데 어쩐지 너무 스무스했다. 하지만 개같이 극복함. 일단 돌아는 가니까^^..
아무튼 전체 기록 페이지를 개발하면서 있었던 삽질기 들어갑니다..!
처음 데이터를 저장하는 방법은 다음과 같이 간단했다.
const saveUserUpdate = async (key, data) => {
try {
const jsonData = JSON.stringify(data)
await AsyncStorage.setItem(key, jsonData)
}
...
}
여기서 치명적인 실수를 하게되는데 AsyncStorage는 기본적으로 키-값 형태의 데이터 저장소로 동작한다. 특정 키에 대한 값을 덮어쓰는 방식이기 때문에 데이터 중첩 저장이 안된다는 점이다.
따라서 변경된 방식은 종료된 운동 데이터를 중첩 저장하기 위해서 서브키를 활용하여 데이터를 누적하도록 하였다.
export async function saveRecordData(key, json) {
...
const existingData = await AsyncStorage.getItem(key)
let parsedData = existingData ? JSON.parse(existingData) : {}
const currentDateData = parsedData[json.currentDate]
if (Array.isArray(currentDateData)) {
currentDateData.push(json.data)
}
else {
parsedData[json.currentDate] = [json.data]
}
await AsyncStorage.setItem(key, JSON.stringify(parsedData))
...
}
또한 조건문에서 확인할 수 있듯이, 날짜에 해당하는 데이터가 이미 배열 형태로 존재한다면 새로운 데이터를 배열에 추가하고, 데이터가 없어 배열이 아닌 경우 새로운 배열을 만들어서 데이터를 저장함으로써 동일한 날짜의 데이터들을 배열로 가질 수 있다.
런플립은 사용자가 운동을 하면 할수록 데이터가 쌓이기 때문에 향후 누적되어있는 대량의 데이터를 효과적으로 보여주어야한다.
FlatList는 필요한 부분만 렌더링하여 메모리 사용과 스크롤링 성능을 향상시키기 때문에 이를 사용하여 전체 기록 페이지를 구현하였다.
상세 기록 페이지의 경우 FlatList에서 받아오는 데이터를 그대로 넘겨주고 화면처럼 배치하였다.
데이터 삭제를 하기 위해선 각 기록 별로 고유 값을 가지고 있어야하는데 데이터 구조를 설계할때 빼먹었다. 헤헷 >,0!
다행히도 운동을 끝낸 시간으로 대체할 수 있을 것 같아 endTime, 그러니까 위의 사진에선 '2023.8.22 18:23' 문자열이 각 기록 데이터를 구분하는 고유키가 되는 셈이다.
먼저 서버에서 데이터베이스에 있는 데이터를 삭제하고 정상 응답을 받으면 로컬 스토리지에 있는 데이터도 삭제하도록 했다.
기존에 날짜 별 데이터를 저장하는 DataByDate 컬렉션은 서브 컬렉션을 통해 동일한 날짜에 데이터가 발생해도 누적되도록 했으며 data와 date 필드를 가지고 있었다.
단순히 데이터 식별을 하기 위해서 날짜로 구분지었으나 고유성이 보장되지 않아서 데이터 삭제시 관련 데이터가 죄다 삭제되는 참사가 일어났다. ㅠㅠ
해서 로컬 스토리지에서 endTime을 고유키로 사용하는 것과 마찬가지로 동일한 데이터로 저장되게 해서 고유성을 부여하고 해당 값을 targetDate로 지정하여 원하는 데이터만 삭제될 수 있도록 하였다.