RN기반 SnapPal 개발 회고 겸 개발 과정 발생한 이슈를 두서없이 정리
글 보러가기
AppStore - SnapPal 보러가기
사진 기반 펜팔 앱을 Expo RN + Supabase로 개발함.
✱ 믿고 응원해준 여자친구와 구매해준 사람들께 감사함. 신기한 경험이었음.
POST
요청의 body를 변경할 수 없으며 Supabase Edge Functions
혹은 HTTP
요청 가능.✱ Trigger로 DB 조작하면 트랜잭션이 안걸린다. 트랜잭션 필요하면 rpc(프로시저)를 써야했는데, 백엔드 개발자가 아니다보니 하나의 작업을 트랜잭션 없이 해야하는 상황이 있는지 모르겠음.
Supabase SDK 클라이언트단에서 쉽게 DB에 접근 및 조작이 가능.
✱ 마찬가지로 백엔드 개발에 친숙하지 않아 어디까지 SDK를 이용하고 어디서부터 프로시저 처리하는지 애매했음.
expo-image
의 cachePolicy
만 믿고 있었음. url을 키로 캐시처리함.signedUrl
를 이용해 비공개 이미지 접근을 핸들링함.expo-image
가 미지원.✱ 결국 이미지의 id를 key로 캐싱하는 로직을 구현했음.
✱ 개발 초기에 알아서 금방 되돌렸다.
expo-camera
컴포넌트가 언마운트되도 IOS의 카메라 인디케이터(녹색 불)가 꺼지지 않는 이슈✱1. expo-router
의 useFocusEffect()
훅으로 명시적 unmount 해줘 해결.
if (!isScreenFocused) {
return null
}
✱2. issue탭 내용으론 이걸로 안되는 사람들도 있는 듯.
✱3. Expo Go 말고 프로덕션 빌드에서 해결되기도 하는 듯.
✱ 오류 발생 시 3초 간격으로 재요청하도록 에러 처리
const onError = (event: ImageErrorEventData) => {
const now = Date.now();
if (now - lastErrorTimeRef.current < RETRY_DELAY) return; // 3초당 한 번씩만 실행
if (retryCount < MAX_RETRIES) {
lastErrorTimeRef.current = now;
setTimeout(() => {
setRetryCount((prevCount) => prevCount + 1);
}, RETRY_DELAY);
} else {
// RETRY_COUNT 초과
console.error(event.error);
setIsLoading(false);
setError(event.error);
}
};
✱ 계속 그렇듯이 DB에 미숙해 애매했던 지점.
✱ 자주 요청하는 쿼리에 join
이 필요한데 최적화 위해 updatedAt
컬럼을 중복해서 둠.
안티패턴일까?
/chats/[chatId]/detail/[photoId]
replace()
를 실행해도 경로가 제대로 안날아가고 남아있는 버그가 있었음.✱ replace
전 현재 path 조회해 dismissAll()
-> 필요한 페이지로 push
중첩하는 식으로 처리
✱ 버그가 아니라 dynamic route 겹치지 말라는 걸 얼핏 본 거 같기도 하다.
random
함수보다 나은 방법을 원했고✱ 가중치 알고리즘은 과하다 생각해 last_received_at
컬럼을 두어 안 받은게 오래 된 순으로 뿌려줌.
last_activity_at
컬럼을 두고 일주일 간격 배치 처리로 비활성 유저를 분배 리스트에서 제외✱ soft delete 처리하고 일주일 간 신고 내역 없으면 삭제하는 식으로 구현
✱ prod / dev 환경 구분해 에러 메세지 처리(앞으로)
✱ prod는 로그로만 남긴다.
truncate
가 포함.truncate
가 실행되는 문제 발생✱ 원래 그런건지는 모르겠음. rpc내에서 권한 체크 후 에러 던지는 식으로 대응
✱ i18n을 콜드스타트마다 받을 수 없으니 translate 함수 구현
✱ 번역문을 DB에 담아둘까 하다가 함수 메모리에 올리고 사용했는데,뭐가 나은 방식일지는 테스트 못해봄.
✱ token 테이블을 profile 테이블과 따로 두어 관리
✱ push 알림 전송 시 유저의 모든 토큰 조회
✱ 유저 시나리오를 정리하고 이에 맞게 구현