Provider Fallback과 Data Normalization이 만든 작은 API Gateway지난 글에서 Readium Backend는 단순한 서버가 아니라 외부 API를 보호하는 계층이라는 이야기를 했다. 그 서버는 사용자 데이터를 저장하지도 않고, 복잡한 비즈니스 로직을 수행하지도 않는다. 대신 모바일 앱과 외부 세계 사이에서 요청을 중계하고, 인증을 처리하며, API 키를 보호하는 역할을 맡는다.그렇게 보면 이 서버는 매우 단순해 보인다. 하지만 실제로 기능을 하나씩 추가하다 보면, 이 단순한 서버가 점점 다른 성격을 가지기 시작한다. 특히 책 검색 기능을 구현하면서 그 변화가 분명하게 드러났다. 처음에는 단순히 Kakao Books API 하나만 호출하면 충분할 것이라고 생각했다. 하지만 ..
지난 글에서는 Readium 앱 뒤에 존재하는 아주 작은 서버에 대해 이야기했다. 처음 이 앱을 설계할 때만 해도 나는 가능한 한 서버를 만들지 않으려고 했다. 독서 기록이라는 데이터는 본질적으로 개인적인 것이고, 대부분의 기능은 사용자 기기 안에서 충분히 동작할 수 있기 때문이다. 실제로 Readium의 핵심 데이터 구조는 지금도 전부 로컬 데이터베이스에 저장되어 있으며, 네트워크 연결이 없어도 독서 세션 기록이나 타임라인 기능은 문제없이 동작한다. 하지만 앱을 실제로 만들다 보니 완전히 서버가 없는 구조를 유지하는 것은 생각보다 쉽지 않다는 사실을 깨닫게 되었다. 문제는 책 메타데이터였다. 사용자가 독서 기록을 남기기 위해서는 먼저 읽고 있는 책을 선택해야 한다. 대부분의 독서 앱은 검색창에 책 제목..
Readium 개발기는 하나의 독서 기록 앱이 만들어지는 과정을 기록한 시리즈다. 단순히 앱 기능을 구현하는 이야기가 아니라, 왜 그런 구조를 선택했는지, 어떤 설계가 무너졌고 어떻게 다시 세워졌는지, 그리고 실제로 앱이 스토어에 올라가기까지 어떤 현실적인 문제들을 마주했는지를 차근차근 따라간다. 이 시리즈는 한 개인이 독서 기록 앱을 직접 만들기로 결심한 순간에서 시작해, 도메인 설계의 붕괴와 재정렬, 세션 기반 기록 모델의 구현, 이벤트 중심 Timeline 구조의 선택 같은 기술적인 고민을 다룬다. 그리고 그 과정에서 자연스럽게 등장한 로컬 우선(Local-first) 아키텍처, 외부 책 메타데이터 API를 보호하기 위한 최소 서버, 그리고 실제 Android와 iOS 앱을 출시하기까지의 경험까지 ..
— 서버 없는 앱을 만들려다 서버를 만들게 된 이유독서 기록 앱을 직접 만들겠다고 마음먹었을 때, 나는 꽤 단순한 그림을 머릿속에 그리고 있었다. 사용자가 책을 읽고, 세션을 기록하고, 그 기록이 타임라인 형태로 쌓여가는 앱. 서버는 굳이 필요 없을 것 같았다. 모든 기록은 개인적인 것이고, 기기 안에만 있어도 충분했기 때문이다. 심지어 그게 더 자연스럽다고 느껴졌다. 독서는 원래 개인적인 활동이고, 독서 기록 역시 누군가에게 공유하기 위해 남기는 것이 아니라 스스로의 시간을 돌아보기 위해 남기는 것이니까.그래서 Readium의 초기 설계는 처음부터 Local-first 방향으로 시작됐다. 핵심 데이터는 서버가 아니라 앱 내부에 저장하고, 네트워크 연결이 없어도 앱은 완전히 동작해야 한다는 원칙이었다. ..
세션 토글을 정리하고 나서야 비로소 안정감이 생겼다.정책은 UseCase 안에 모였고, 상태와 수치는 역할에 맞게 분리되었다.그런데 또 하나의 질문이 남아 있었다.그 모든 변화는 어디에 남길 것인가?세션이 시작되면 시작 이벤트가 생긴다.세션이 종료되면 종료 이벤트가 생긴다.진행률이 100이면 완독 이벤트가 생긴다.이 모든 것은 “기록”이다.그렇다면 Timeline은 무엇이어야 할까?1. 처음엔 Timeline을 ‘상태 요약’으로 만들려고 했다처음 설계할 때는 이런 유혹이 있었다.Timeline 카드에 바로 보여줄 데이터를 저장하자.책 제목도 넣고,진행률도 넣고,세션 길이도 넣고,심지어 계산된 통계값도 넣자.즉, TimelineEvent를 “UI에 최적화된 테이블”로 만들고 싶었다.하지만 곧 이상한 느낌이..
2편에서 나는 도메인을 다시 정렬했다.ReadingRecord는 상태를 관리하고, ReadingSession은 시간과 수치를 다루며, TimelineEvent는 사실을 기록하도록 역할을 분리했다. 그 순간에는 구조가 꽤 단단해졌다고 느꼈다. 마치 복잡했던 퍼즐이 맞춰진 것처럼 보였다. 하지만 도메인 설계는 개념으로 끝나지 않는다.그 위에 실제 동작을 올리는 순간, 진짜 문제가 드러난다. 그 첫 시험대가 바로 toggleSession이었다. 겉으로 보면 단순하다.버튼 하나, 조건 하나.“읽기 시작”과 “읽기 종료”를 번갈아 수행하면 된다. 그런데 이 버튼 하나에, 내가 정의한 모든 도메인 정책이 걸려 있었다. 1. 처음에는 정말 단순해 보였다처음 머릿속에 그렸던 구조는 이랬다.노트에 적힌 그대로였다.if ..
2026.03.01 - [Readium] - 📚 Readium 개발기 #1 - 왜 나는 독서 기록 앱을 직접 만들기로 했는가 1편에서 나는 “독서는 상태가 아니라 흐름이다”라고 썼다.지금 돌아보면 그 문장은 꽤 단단해 보인다. 마치 처음부터 명확했던 철학처럼 보일 수도 있다. 하지만 실제로는 그렇지 않았다. 그 문장은 여러 번의 설계 실패와 구조 붕괴를 겪은 뒤에야 겨우 남은 결론이었다.앱을 설계할 때 우리는 자주 착각한다. 처음 그린 구조가 논리적으로 말이 되면, 그것이 충분히 괜찮은 설계라고 믿는다. 나 역시 그랬다. 처음에 그린 도메인 모델은 단순했고, 그래서 더 이상적인 것처럼 느껴졌다. 그러나 개발을 조금만 진행해도 그 단순함은 금세 균열을 드러냈다. 이번 글은 그 균열이 어떻게 시작되었고, ..
왜 나는 독서 기록 앱을 직접 만들기로 했는가앱을 만들겠다고 처음부터 생각했던 건 아니다.거창한 목표도 없었다.창업을 하겠다는 생각도 없었고, 서비스를 키워보겠다는 계획도 없었다.그냥, 책을 읽다가 불편했다.그리고 그 불편함이 계속 머릿속에 남아 있었다.1. 기록이 남지 않는 독서나는 책을 많이 읽는 사람은 아니다.하지만 읽을 때는 꽤 집중해서 읽는다. 한 번 잡으면 몇 시간씩 읽기도 한다.그런데 문제는 항상 이거였다. 책을 덮고 나면, 그 시간이 사라진다.오늘 몇 분 읽었는지며칠 만에 완독했는지중간에 얼마나 쉬었는지읽다가 왜 멈췄는지기억은 남아 있지만, 기록은 없다.그래서 독서 앱을 깔았다.2. 기존 독서 앱들이 채워주지 못한 것앱스토어에는 독서 앱이 넘쳐난다.통계가 화려하고, 디자인도 세련되고, 소..
- Total
- Today
- Yesterday
- css커스터마이징
- 1인 개발
- 티스토리
- WSL개발환경
- 인터넷문화
- 오픈소스
- 로컬 우선 아키텍처
- Flutter 앱 개발
- ChatGPTCodex
- AI와인터넷
- 온라인신원인증
- 블로그디자인
- 웹디자인
- 로컬우선아키텍처
- SQLite 앱 아키텍처
- 이벤트아키텍처
- Windows개발
- CodexApp
- 프론트엔드
- 도메인설계
- 앱 도메인 설계
- Google Play 출시
- 트랜잭션 설계
- Readium개발기
- Readium 개발기
- NanoClaw
- 티스토리스킨
- Idempotent 처리
- 한국인터넷역사
- 다크모드
| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | |||||
| 3 | 4 | 5 | 6 | 7 | 8 | 9 |
| 10 | 11 | 12 | 13 | 14 | 15 | 16 |
| 17 | 18 | 19 | 20 | 21 | 22 | 23 |
| 24 | 25 | 26 | 27 | 28 | 29 | 30 |
| 31 |