My-Run-Club
올해 초중반쯤, JavaScript 를 이용한 러닝기록 웹 사이트를 프로젝트로 구현한 적이 있다.
그리고 중후반쯤, TypeScript 로 리팩토링을 진행했었다.
그리고 Vue 와 Flutter 앱 언어를 공부를 해보다가 앱용으로 다시 한 번 프로젝트로 해보고 싶은 욕심에 진행하게 되었다.
주요 화면
- 시작화면
- 홈 화면
- 러닝 추가 화면
- 상세 화면
모든 섹션 저장 | 삭제 |
---|
| |
주요 기능
1. 러닝 기록 CRUD 기능
- 러닝 활동 추가 : 홈 화면 우측 상단의 '+' 버튼을 클릭시 활동 추가 화면으로 이동한다. 활동 추가 화면에서 정보 (날짜, 거리, 운동시간, 페이스)를 사용자의 입력을 통해 저장을 하면 러닝 활동이 생성이 된다.
- 러닝 활동 읽기 : 홈 화면 하단에는 추가된 러닝 활동 리스트를 볼 수 있다.
- 러닝 활동 변경 : 홈 화면의 러닝 활동 리스트 중 각각의 러닝 활동을 클릭시 상세 화면으로 이동한다. 상세 화면에서 간단히 입력한 정보를 볼 수 있고, 추가적으로 러닝 활동에 대한 러닝 강도, 러닝 장소, 메모를 추가적으로 정보를 입력할 수 있다.
- 러닝 활동 삭제 : 러닝 활동 상세 화면에서 제목 우측의 쓰레기통 아이콘 클릭시 작은 하단 모달 스크린을 통해 삭제 확인을 통해 삭제를 확정하거나 취소할 수 있다.
2. 러닝 기록 요약
- 주, 월, 년 주기로 기록 요약 : 추가된 러닝 활동들을 상단 탭을 활용해 주, 월, 년 주기로 평균치의 기록을 요약하여 볼 수 있도록 했다.(추가적으로 전체 탭이 있지만 아직 구현하지 못했다.)
- 바 차트 정리 : 주기 기준으로 글, 숫자로 요약된 위젯 아래, 주(월 ~ 일), 월(1일 ~ 30/31일), 년(1월 ~ 12월)을 분리하여 기록된 활동이 있다면 기록을 기준으로 바차트로 파랗게 표시할 수 있도록 했다. 바차트를 클릭시 해당 달린 거리를 표시할 수 있다.
3. 러닝 기록 DB
- Firebase 연동 : 러닝 활동 추가 화면에서 정보를 입력 후, 저장 버튼을 누르면 firebase cloud-store 의 Runnings 라는 컬렉션 안에 자동으로 생성된 문서 ID 에 입력한 정보들이 쌓이게 된다.
- 전역 상태 관리 Provider : 추가된 러닝 활동들은 사용되는 위젯이 많기 때문에 유지보수를 위해 Provider 를 사용하여 간단히 firebase 에서 읽어와 리스트로 저장을 해둔채로 StreamBuilder 를 이용해 불러올 수 있도록 했다.
어려웠던 점
- 다수의 ChangeNotifierProvider 사용
: flutter 언어를 배울 때 이젠 클론 코딩을 통해 Provider 라는 개념을 가졌고, 활용할 수 있었다. 전역으로 관리할 것이 늘어나 Provider 를 추가했고 이를 다 같이 사용하기 위해서는 main.dart
파일에서 MultiProvider 로 두 개의 ChangeNotifierProvider 를 묶어주어야 했다.
- Firebase 연동
: 로컬 스토리지 DB 의 한계를 해결하기 위해 Firebase DB 를 이용했다. [TIL] Flutter 와 Firebase 연동하기로 블로깅을 할 정도로 설정과 단계와 오류가 많았다. 특히나 cocoapod 를 설치하는 데 오류가 생겨서 온갖 stackoverflow 와 블로그들을 찾아다녔고 이를 다시 설치해줌에 해결을 해서 해결하는데만 이틀은 걸렸다. 다만, IOS 앱만으로 구연해서 안드로이드 앱 구현에는 아직 미흡한 점이 있다.
문서 ID 내 다양한 필드에는 이름, 날짜, 거리, 운동페이스, 운동시간, 강도, 장소, 메모 등이 들어가는데 그 중 firebase에서 날짜는 Timestamp 형으로 저장할 수 있었다. 그래서 flutter 에서는 showDatePicker
와 showTimePicker
를 통해 입력한 날짜 DateTime 와 시각 TimeofDay 를 통합하여 Timestamp 형으로 변환시켜주어야 했다.
- Tab Controller
:dart 언어를 완벽하게 이해 후 프로젝트를 진행하기보다는 진행하면서 익히고 싶었기 때문에 flutter 의 위젯 패키지들을 이용하는데 있어서 미숙했다. 특히나 활동 기록들을 주, 월, 년으로 기준을 나누어 보여주고 싶었기 때문에 탭 위젯의 필요성이 높았다.
먼저 선택할 Tab Bar 들과 그 개수에 맞는 TabBarView 들이 설정해주어야 한다. TabController를 이용해 선택한 Tab Bar와 TabBarView 가 동기화시켜주기 때문에 DefaultTabController를 사용해야 탭의 내용이 들어있는 TabBarView 들이 정상적으로 보여줄 수 있었다.
TabBarView 의 child 들은 담는 위젯과 데이터가 많아서 계속해서 OverFlow 가 발생하는 문제가 있었다. TabBarView 의 child 들을SingleChildScrollView로 설정을 하고 싶었는데, TabBarView은 Container 위젯이 아닌 Expanded 위젯으로 감싸여야지 오류가 해결할 수 있었다.
- Bar Chart
: 차트로 하고 싶은 것은 내 욕심이기도 했다. 숫자의 기록보다는 차트로써의 기록도 한 눈에 보여주면 숫자와 그림의 조합이 사용자에게 더 편리하게 느껴질 것 같은 이유였다.
먼저 fl_chart
패키지를 설치하였고, 속성이 많아서 document 를 참조하였다.
위는 github fl_chart documents 에 나와있는 내용이다. 기본적으로는 다음과 같은 코드를 거친다. Barchart
안에 안에 차트에 쓰일 데이터에 관한 속성들을 설정한다.
BarchartData
내 속성들 중
groupsSpace
과 alignment
는 데이터들의 간격이나 정렬을 설정한다.
titleData
는 차트 좌우상하에 표시되는 titles 의 표시에 대한 설정이다.
barTouchData
는 바를 터치했을 경우에 설정할 수 있는 상호작용의 속성이다.
gridData
나 borderData
는 차트안의 grid 나 border 에 관한 속성이고,
maxY
와 minY
는 수평적으로 최솟값과 최대값을 지정할 수 있다.
가장 중요한 barGroups
는 한 바 차트에 관한 데이터들을 리스트로 묶어놓은 List<BarChartGroupData>
형식이다. BarChartGroupData
는 다음 속성을 가진다.
x
는 horizontal axis 값으로 간단히 말하면 index 값으로 생각하면 되고, barTods
는 차트에 쓰이는 데이터를 세세하게 정하는 속성으로 이해하면 된다.
그 중 중요한 속성만 말하자면 toY
는 fromY
의 default 값인 0부터 올라가는 차트 값이고, gradient
는 눈에 보이는 차트에 대한 색이나 정렬 속성이다.
간단히 요약을 하고자했는데 조금 길어졌다. 어쨋든 주, 월, 년에 대한 각각의 데이터들을 먼저 초기화 시킨 후, 뽑아낸 데이터들을 초기화 시킨 barchartData
의 barTods
속성 안 toY
값들만 조정하면 되기 때문에 이 값들만 누적합으로 계산하였다.
초기화 작업 | 데이터 대입 작업 |
---|
| |
더 구현해보고 싶은 점
- 데이터 요약 세분화 : 현재 주, 월, 년에서 오늘을 기준으로 이번주, 이번월, 이번 연도로만 설정이 되어있다. 내가 바라던 바는 주에서는 이번주를 기준으로 최근 4주를, 모든 월과 모든 연도에 맞는 요약된 데이터로 표시해보고 싶다. 주는 바라던 대로 진행을 했다가 약간의 꼬임이 있어서 주석처리를 한 상태이다.
- 구체적인 장소 데이터 : 장소에 관해서는 현재 도로, 트랙, 산으로만 입력이 가능하다. 욕심으로는 지도 api 를 이용해서 간략한 아이콘을 이용한 장소 선택이 아니라 실질적인 장소를 클릭하거나 선택해서 데이터를 저장해보고 싶기도 하다.
마치며
웹만 고집하였던 내가 앱 언어에 대해 그냥 해보자라는 마음가짐으로 시작하였다. 간단한 클론 코딩 강의 하나만 듣고 무작정 생각해놨던 프로젝트를 진행하면서 기능이나 언어에 대해 익히니 더 잘 습득되는 느낌이었다. 어쩌면 react 보다 더 간단한 flutter 에 더 빠지게 된 것 같기도 하다. 해야할 기능도 해보고 싶은 기능도 꽤 있지만 일단 이주안에 구현할 수 있는 정도는 이정도 인 것 같아 블로깅과 리드미를 진행한다. 앞으로 어떻게 더 리팩토링을 진행할지 어떤 것을 구현할지도 궁금하고 재밌어진다.