Splitwise의 무료 P2P 대안인 PeerSplit을 아이디어부터 출시까지 단 2주 만에 구축했습니다!
PeerSplit은 그룹 비용을 분할하기 위한 로컬 우선 앱입니다. 오프라인에서 작동하고 100% 무료이며 비공개이며 가입이나 개인 데이터가 필요하지 않습니다.
제가 구축한 방법과 그 과정에서 배운 모든 내용은 다음과 같습니다.
저는 친구 및 룸메이트와 함께 비용을 관리하기 위해 수년 동안 Splitwise를 사용해 왔습니다. 하지만 최근 일일 거래 한도와 방해가 되는 광고로 인해 사용하기가 불편해졌습니다.
저는 데이터를 저장하거나 동기화하는 데 서버가 필요하지 않은 무료 개인정보 보호 우선 대안을 원했습니다. 제3자 서버에 투자하는 비용은 신뢰하지 않습니다.
운동 추적기 및 방해 없는 글쓰기 앱과 같은 P2P, 로컬 우선 프로젝트를 진행한 후 비용 분할에도 동일한 접근 방식을 적용할 수 있다는 것을 깨달았습니다.
그래서 PeerSplit이 탄생했습니다. 앱 디자인을 시작했습니다.
저는 UI 디자인이 형편없어요.
몇 달 전만 해도 PeerSplit만큼 세련된 UI를 구축할 수 있을 거라고는 생각하지 못했습니다. (어떤 사람들은 Splitwise보다 UX가 더 좋다고 말하기도 합니다.)
그럼 제가 어떻게 그 일을 할 수 있었나요? Nuxt UI.
Nuxt UI는 멋지고 놀라운 개발자 경험(DX)을 갖추고 있습니다.
@nuxt/icon, @nuxtjs/tailwindcss 및 @nuxtjs/colormode와 같은 다른 유용한 Nuxt 모듈도 함께 제공됩니다.
제가 해야 할 일은 기본 색상을 선택하는 것뿐이었고 PeerSplit의 UI를 통합하는 데 필요한 모든 구성 요소(아이콘, 다크 모드 및 기타 모든 것)가 있었습니다.
로컬 데이터 저장 및 동기화를 위해 wa-sqlite를 기반으로 CRDT(충돌 없는 복제 데이터 유형)를 사용하는 cr-sqlite를 사용했습니다.
CRDT는 충돌을 자동으로 처리하므로 P2P 시스템에 적합합니다. 따라서 사용자는 오프라인으로 작업할 수 있고 다시 연결하면 변경 사항이 원활하게 병합됩니다.
그러나 cr-sqlite는 자체적으로 네트워크를 통해 변경 사항을 동기화하지 않습니다. 변경 사항을 내보내고 병합하는 API만 제공합니다. 이러한 변경 사항은 기기 간에 수동으로 보내야 합니다.
보안 P2P 동기화를 처리하기 위해 P2P 분산 그래프 데이터베이스를 제공하는 Gun.js를 사용했습니다.
Gun의 gun.user API를 사용하면 각 그룹에 대해 암호화된 노드를 만들 수 있습니다. 그룹의 모든 변경 사항은 해당 노드에 저장되고 그룹 구성원과만 동기화되므로 모든 것이 비공개로 유지됩니다.
사용자가 작업을 수행하면 cr-sqlite에서 내보낸 변경 사항을 노드에 푸시합니다. 사용자가 다시 온라인으로 돌아오면 Gun은 새로운 변경 사항을 동기화하여 모든 사람을 최신 상태로 유지합니다.
이를 성능 좋은 방식으로 구현하는 것은 까다로웠습니다. 자세한 내용은 여기에서 소스코드를 확인하실 수 있습니다.
Splitwise(현재 PeerSplit)의 멋진 기능 중 하나는 "부채 단순화"입니다.
작동 방식은 다음과 같습니다. A가 B에게 빚을 지고 B가 C에게 빚을 졌다면 A는 C에게 직접 지불하여 상환 횟수를 줄일 수 있습니다.
PeerSplit에서는 먼저 각 사람의 순 잔액을 계산합니다. 그런 다음 잔액을 정렬하고 매번 최소 한 사람의 잔액을 0으로 만들기 위해 하나씩 결제를 제안합니다.
이 정렬을 통해 모든 사람이 자신의 기기에서 동일한 상환 내역을 볼 수 있습니다.
100% 최적은 아니지만(일부 그룹은 여전히 최대 n-1 지불금을 보유할 수 있음) 대부분의 경우 잘 작동합니다.
최적의 솔루션은 계산이 기하급수적이며 몇 가지 지불액만 절약할 수 있습니다. 따라서 이것이 단순성과 속도를 위한 최선의 절충안이었습니다!
export const groupGetPayments = (group) => { const payments = []; const balances = Object.entries(groupGetBalances(group)).map(([a, b]) => [ b, a, ]); balances.sort(); let i = 0, j = balances.length - 1; while (i balances[j][0]) { payments.push({ from: balances[i][1], to: balances[j][1], value: round(balances[j][0]), }); balances[i][0] = balances[j][0]; balances[j][0] = 0; } else { payments.push({ from: balances[i][1], to: balances[j][1], value: round(-balances[i][0]), }); balances[j][0] = balances[i][0]; balances[i][0] = 0; } } return payments; };
PeerSplit이 오프라인 앱으로 작동하기를 원했지만 여러 기본 애플리케이션을 구축하거나 앱 스토어에 게시하는 데 오랜 시간이 걸리는 번거로움을 겪고 싶지 않았습니다. 따라서 PWA(Progressive Web App)를 선택한 것이 확실한 선택이었습니다.
PWA는 최고의 웹 앱과 모바일 앱을 결합하여 사용자가 오프라인 기능을 즐기면서 기기에 PWA를 설치할 수 있도록 해줍니다.
Nuxt 앱을 PWA로 변환하기 위해 vite-pwa를 사용했습니다.
Figma에서 SVG 로고를 디자인하고 이를 사용하여 vite-pwa의 자산 생성기를 통해 필요한 모든 PWA 자산을 생성했습니다.
그 후 PWA 매니페스트를 구성했고 vite-pwa가 자동으로 서비스 워커를 설정했습니다.
내 앱이 오프라인에서 완벽하게 작동할 수 있도록 모든 경로를 사전 렌더링하도록 Nuxt를 구성했습니다.
이제 끝났습니다. 읽어주셔서 감사합니다!
PeerSplit이 방금 Product Hunt에 출시되었습니다! 첫 번째 출시이므로 여러분의 지원과 피드백을 부탁드립니다.
제품 검색에서 PeerSplit을 확인하세요.
PeerSplit은 공정한 소스이므로 GitHub에 자유롭게 기여하거나 기능 요청을 제출하세요.
PeerSplit는 그룹 비용을 쉽고 비공개적으로 분할하고 추적하는 데 도움이 되는 무료 로컬 우선 P2P 앱입니다.
부인 성명: 제공된 모든 리소스는 부분적으로 인터넷에서 가져온 것입니다. 귀하의 저작권이나 기타 권리 및 이익이 침해된 경우 자세한 이유를 설명하고 저작권 또는 권리 및 이익에 대한 증거를 제공한 후 이메일([email protected])로 보내주십시오. 최대한 빨리 처리해 드리겠습니다.
Copyright© 2022 湘ICP备2022001581号-3