2025년 4월 1일부터 앱스토어 출시 2025년 6월 17일까지 약 2개월 반 정도의 기간 동안 개인 프로젝트 Refly를 출시하게 되었습니다. 프로젝트를 시작한 계기부터 제작, 출시까지 과정을 되돌아보며 저의 고민 기록 앱 Refly에 대해서 소개하고자 합니다.
프로젝트를 시작하기 전까지는 여러 프로젝트를 병행하면서, 동아리 강의 자료를 만들고 강의도 진행하고, 스터디 그룹도 운영하는 등 정말 정신없이 바쁜 시간을 보내고 있었습니다.
그런데 다양한 활동을 하다 보니, 하나의 프로젝트에 온전히 집중하기가 어려웠고, 자연스럽게 트러블슈팅에 대한 회고도 제대로 기록하지 못하는 경우가 많았습니다.
결국 같은 문제를 반복해서 겪는 일이 생기면서, '기록의 중요성'을 절실히 느꼈죠.물론 블로그에 해결했던 트러블슈팅 과정을 정리해두긴 하지만, 블로그는 아무래도 시간과 장소의 제약이 있어서 언제든지 바로 기록하기에는 한계가 있습니다.
그래서 "이슈가 생겼을 때 바로 기록하고, 나중에 해결하면 해결책까지 함께 정리해둘 수 있는 앱이 있었으면 좋겠다"는 생각이 들었고, 그 필요성에서 이번 프로젝트를 시작하게 되었습니다.
- 프레임워크 : Flutter
- 상태관리 : Riverpod / flutter_hooks
- 아키텍처 : MVVM / Clean Architecture
- 백엔드 : Supabase / Supabase Edge Functions
- 기타 : Freezed / Equatable / Go_Router
이번 프로젝트에서 저는 상태관리 라이브러리로 Riverpod을 선택했습니다.
빠른 앱 개발과 배포도 물론 중요했지만, 이 프로젝트를 단순한 결과물이 아니라 나만의 공부 기회라고 생각했기 때문입니다.사실 저는 그동안 Riverpod이나 flutter_hooks를 본격적으로 사용해본 경험이 없었습니다.
하지만 최근 많은 커뮤니티와 개발자들이 Riverpod을 적극 활용하는 흐름을 보면서,
이번 개인 프로젝트를 통해 해당 라이브러리들의 개념과 활용법을 직접 체득할 수 있는 좋은 기회라고 판단했습니다.단순히 기능 구현만을 목표로 하는 것이 아니라,
프로젝트를 통해 새로운 기술을 익히고 실전 경험을 쌓는 것도 이 프로젝트의 중요한 목적 중 하나였습니다.
아무래도 개인 프로젝트이고 제가 사용할 앱이다 보니 저의 시점으로 사용자 페르소나를 만들어 앱을 기획하게 되었습니다. 그러다 보니 아래와 같이 지향점을 설정할 수 있었습니다.
사용자가 언제든 앱을 통해 고민을 기록할 수 있어야 한다.
제가 이번 프로젝트를 시작할 때 가장 중요하게 생각한 것은 “언제든지 고민을 바로 기록할 수 있어야 한다”는 점이었습니다.
문제는 항상 예상치 못한 순간에 갑자기 떠오르기 마련인데, 그럴 때마다 복잡한 절차 없이 바로 열고, 바로 적을 수 있는 환경이 필요했습니다. 제가 그랬거든요 ㅎㅎ하나의 화면에서 모든 기능을 처리하고 싶다.
사용자로서 여러 화면을 오가는 것이 번거롭게 느껴질 때가 많았습니다.
그래서 저는 하나의 UI 안에서 고민 기록 → 해결 → 정리까지 전체 흐름을 처리할 수 있도록 UX를 설계했습니다.
기록하고, 해결하고, 필요할 때 다시 찾는 과정을 끊기지 않고 자연스럽게 이어가고 싶었거든요.기기를 바꿔도 나의 고민은 사라지지 않아야 한다.
고민 기록은 단발성 메모가 아니라, 시간이 지나도 다시 꺼내볼 수 있어야 의미가 있습니다.
그래서 기기를 바꿔도 데이터가 유지되도록 서버에 저장하는 구조로 만들었습니다.
다만 너무 복잡한 로그인 절차는 오히려 진입 장벽이 될 수 있기 때문에, 간단하면서도 안정적인 로그인 방식을 고민하게 되었고, 구글 로그인과 애플 로그인을 통한 로그인 방식을 구현했습니다.제가 올해 기종 바꿔야되서 이런 기능을 추가한건 안비밀입니다.😎
날짜별 기록과 해결률 시각화
단순히 기록만 하는 것이 아니라, 내가 언제 어떤 고민을 했고, 얼마나 해결해왔는지 돌아볼 수 있으면 좋겠다는 니즈도 있었습니다.
그래서 날짜별로 기록을 조회할 수 있는 기능과 함께, 전체 기록 중 해결된 고민의 비율을 시각적으로 확인할 수 있는 기능도 추가했습니다.
스스로의 성장과 문제 해결 과정을 눈으로 확인할 수 있다는 점에서 나를 더욱 채찍질 할 수 있기를...
개인 프로젝트이다 보니 트러블 슈팅 다음으로 어려웠던 것은 디자인이었습니다.
처음 프로토타입을 제작할 때 나의 지인들에게 많은 손가락질을 받았습니다 ㅠㅠ
"공대생이들이란...", "이거 색상 진짜 바꿔라", "이거 꼭 있어야 되냐?"피그마 처음 써보는데 어떡하라고....
그렇게 디자인에서 갈팡질팡하면서 일주일이나 낭비했고 저는 함께 프로젝트를 진행하는 디자이너에게 조언을 구걸했습니다. 그는 그저 빛, 신이었습니다. 여러 당근과 채찍을 맞으며...
그렇게 지금의 Refly 앱의 출시 디자인이 완성되었습니다.
솔직히 UI 배치는 아직 남들이 흉봐도 이제 피그마는 조금 자신이 생겼습니다 ㅎㅎ
프로젝트를 제작하며 여러 이슈를 겪고 고민을 했습니다. 그 중 몇몇 사례를 소개하고자 합니다.바텀 시트 트랜지션에 따른 부가 위젯 애니메이션 구현 고민
제가 제작한 UI에서는, 사용자의 시트 제스처에 따라 여러 위젯들이 함께 트랜지션과 오퍼시티 애니메이션을 수행하도록 구성했습니다.
예를 들어, 시트를 아래로 내리면 달력 위젯과 통계(Stat) 위젯이 함께 부드럽게 내려오며 점점 나타나는 효과를 기획했죠.![]()
하지만 여기서 한 가지 고려해야 할 점이 있었습니다.
시트와 각 위젯들이 반응형 크기를 가지기 때문에, 디바이스의 해상도나 화면 크기에 따라 이동 거리가 달라질 수밖에 없었다는 점입니다.
정적인 값으로는 모든 디바이스에서 일관된 애니메이션을 줄 수 없었기 때문에, 저는 스크롤 오프셋에 따라 위젯이 어느 정도 이동해야 하는지를 계산할 수 있는 공식을 직접 유도해 적용했습니다.또한, 오늘 날짜를 표시하는 방식도 특별히 설계했습니다.
오늘 날짜에 해당하는 위젯이 가로 스크롤 가능한 달력 위젯 위에 자연스럽게 겹치도록 위치시키고, 애니메이션 중에 해당 위젯의 투명도를 점점 올리는 방식으로 시각적 효과를 주었습니다.
이 방식은 사용자가 오늘 날짜에 자연스럽게 집중할 수 있도록 돕는 동시에, 시각적 이질감 없이 매끄러운 UX를 제공하는 데 중점을 두었습니다.Riverpod을 최대한 활용하여 재사용성과 유지보수성, 성능 최적화
Riverpod을 도입하면서, 저는 공식 문서에서 권장하는 방식인 riverpod_generator 기반 코드 제네레이션을 적극 활용했습니다.
기존에 사용하던 Provider와 살짝 다른 방식이었기에 공식문서를 많이 참조하여 학습하게 되었으나 이 방식은 정적 분석에 유리할 뿐 아니라, 향후 Riverpod API 변경이나 마이그레이션에 빠르게 대응할 수 있다는 점에서 큰 장점을 가집니다. 실제로 이러한 구조 덕분에 유지보수에 대한 부담이 훨씬 줄어들었습니다.
생성된 Provider는 ConsumerWidget이나 HookConsumerWidget 등에서 손쉽게 접근할 수 있어 UI 코드가 훨씬 깔끔해졌습니다.
또한 성능 최적화를 위해 select를 적극 활용했습니다.
특히 트리 구조상에서 불필요한 렌더링이 일어날 수 있는 위젯들에 대해, 필요한 값만 구독하도록 설계하여 성능 저하 없이 효율적인 상태 관리를 구현할 수 있었습니다.또한, 추후 Clean Architecture도 손쉽게 도입할 수 있는 구조가 되었습니다.
// 프로젝트에서 select 사용 예 Widget build(BuildContext context, WidgetRef ref) { final theme = Theme.of(context); final name = ref.watch(userViewModelProvider .selectAsync((it) => it.userMetadata?["name"] as String)); return FutureBuilder<String>( ... }); }
아키텍처 설계에 관한 고민
이번 프로젝트에서는 Supabase를 활용해 백엔드 인프라를 구성했습니다.
그러나 실제 구현 과정에서는 단순한 API 호출을 넘어서, 사용자의 유스케이스에 따라 복합적인 처리 흐름이 필요한 경우가 많았습니다.
예를 들어, 사용자의 고민 목록을 불러오는 경우에는 단순히 데이터를 가져오는 것이 아니라, 먼저 인증/인가 과정을 거쳐 유효한 사용자임을 확인한 후에야 서버에서 데이터를 요청해야 하는 구조가 필요했습니다.이처럼 여러 계층의 책임이 얽히는 복잡한 유스케이스를 명확하게 분리하고 관리하기 위해, 저는 Clean Architecture를 도입하기로 결정했습니다.
특히 핵심적인 설계 방향은 다음과 같습니다:
- UseCase 계층을 통해 실제 비즈니스 로직을 독립적으로 정의
- Repository 인터페이스를 통해 데이터 접근을 추상화하고, 구현체(Supabase 연동)는 외부 계층에 위임
결과적으로, 유스케이스와 레포지토리를 명확하게 분리함으로써 코드의 재사용성과 가독성이 크게 향상되었으며, 향후 유지보수나 확장에서도 유연하게 대응할 수 있는 기반을 마련할 수 있었습니다.
안드로이드 배포 시 실제 기기가 필요함.
앱을 너무 오랜만에 출시를 해서 그런지 플레이스토어의 정책이 조금 변했다는 것을 알게 되었습니다. 일단 저는 실제 안드로이드 기기를 소지해야된다는 것 때문에 안드로이드 출시를 추후로 미루게 되었습니다 ㅠㅠ 하지만 빠른 시일 내에 공기계를 구입하여 안드로이드도 출시를 할 예정입니다.
빠른 출시만을 목적으로 했기에 테스트 커버리지가 없다.
사실, 이런저런 핑계를 대자면 여러 활동과 아르바이트 등을 하면서 틈틈히 열심히 하긴 했으나 프로젝트를 위한 시간이 많이 없었습니다.!
그래서 빠른 출시를 위해 일단 테스트 커버리지는 거의 0퍼센트에 가까운데요. 향후 앱을 지속적으로 배포하면서 성능 향상을 위한 리팩토링과 더불어 테스트 커버리지 100%달성을 위해 테스트를 작성할 예정입니다.
Refly에서 나의 고민을 해결해줄 조언자가 있으면 좋겠다.
Refly는 아직 개인의 고민과 해결책을 등록하는 용도로 설계되었습니다만, 추후 업데이트를 통해서 AI를 이용한 고민 조언과 하루 요약 서비스도 추가할 예정입니다 ㅎㅎ
Appstore
https://apps.apple.com/kr/app/%EB%A6%AC%ED%94%8C%EB%9D%BC%EC%9D%B4/id6747218275
PlayStore
향후 출시 예정
많은 관심 부탁드리며 피드백 및 개선사항 qazws78941@gmail.com으로 연락주시면 달게 받겠습니다!