ㅤ 피그마에서 디자인을 하면서, 처음에는 이런 모양의 그래프를 그리고 싶었다. ㅤ 근데, 생각보다 이걸 만드는게 잘 안보이더라. line에서 곡선을 사용해서 만들려고 하니 뭔가 계속 울퉁불퉁한 원이 되어버리고, path를 사용해서 그리자니 더 이상하고. 흠… ㅤ 뭔가 방법이 있을 것 같아서 찾아봤더니, 실제로 있더라! 아래같은 방법으로 진행하면 되는거였다. 나는 몰랐지.. 이리 쉬운건지 ㅋㅋㅋ 작년에도 똑같은 디자인을 했던 적이 있었는데, 한 번 찾아보고 할 걸 그랬다. 작년에는 path 가지고 울퉁불퉁하게 대충 원 따라 만들었던 것 같은데,, ㅤ ellipse 원을 그려준다. ㅤ 오른쪽에 있는 arc를 당겨 원하는 각도를 만들어준다. ㅤ 가운데 ratio를 당겨서 원하는 폭을 만들어준다. ㅤ 각도를 원..
오늘도 쌩고생을 했다. 매주 쌩고생거리가 계속 등장하는 것 같다. ㅜㅜ 심지어 오늘은 다트 문법에 당했다. ㅤ List 뒤에 원소를 추가하고 싶을 때는 append가 아닌 add 함수를 사용해야 한다. 블로그 글을 쓰기 위해서 가져왔는데, 이제야 함수의 차이점이 보인다. ㅤ append 쪽 설명을 읽어보면 “Insert element at the end of the [Iterable]” 이라고 되어있다. 나는 요걸 보고 철썩같이 믿고 썼는데, 아무리 디버깅을 해도 해결이 안돼서 한숨만 푹푹 쉬고 있었지… 근데 요게 문제였을 줄은 몰랐다… 파이어베이스에 복잡하게 쿼리를 날리고 결과를 조인해야 하는 기능이라 중간에 뭐가 잘못되었는지 디버거 켜놓고 값 계속 확인하면서 찾아나섰는데, 제일 마지막에 결과 합쳐서 ..
ㅤ 최근에 해결하는데에 꼬박 4일이 걸린 문제가 있었다 ㅜㅜㅜㅜㅜ ㅤ 뷰에서 작은 컴포넌트 위젯에서 GestureDetector를 통해 PanGesture를 인식하고, 터치 좌표값을 받아다가 뷰에게 전달하고, 뷰에서 이를 받아다가 setState로 값을 수정하면 다른 위젯에서 이 값으로 UI를 그리는 로직을 작성하고 있었다. 대충 그림으로 그리면 아래와 같다. ㅤ 이를 위해서 대략적으로 아래 플로우로 실행을 제어하려고 했다. View에서 GestureDetector가 달린 위젯에 콜백함수를 전달 onPanUpdate 시 콜백함수 호출 콜백함수에서 setState 실행 뷰 다시 그리기 position UI 반영 ㅤ 그런데 왠걸? onPanUpdate 함수가 1-2번 호출되고나면 콜백함수가 더 이상 실행되지..
ㅤ 처음에 클린 아키텍처를 프로젝트에 반영하려고 하면서 어떻게 구조를 설계해야하나 고민을 할 때, 아래같은 내용을 담은 적이 있었다. 그리고, 이게 다시 한 번 불편하다고 느낀 상황이 와버렸다! ㅋㅋㅋ ㅤ 아래 이미지처럼 import 문의 크기를 줄이기 위해 열심히 GBDF를 적용해 간소화를 적용하고 있었다. ㅤ 그런데, 저렇게 줄이고 나니깐 각 파일에서 어떤 계층을 참고하고 있는지 더 선명하게 보이기 시작했다. 다시 말하자면, domain 모델에서도 data 계층의 파일들을 import 하여 사용하고 있는게 더 눈에 잘 띄기 시작했다. ㅤ 물론 이게 riverpod 방식으로 파일 구조를 짜려다보니, 앞서 올린 고민 이미지에서 그린 것 처럼 domain에서 data에서 작성한 파일을 필연적으로 impor..
너무나도 객체지향스러운 방식인 오버로딩을 다트 언어에서는 사용할 수가 없었다. 나는 코드를 가독성 넘치면서 깔끔하게 작성하는데에 있어서 오버라이딩, 오버로딩만큼이나 유용한 도구가 없다고 생각했는데, 요런게 제공이 잘 되지 않다보니 좀 불편함을 느끼게 되는 것 같다. ㅤ 아래가 내가 희망하던 코드의 방식이고 // 내가 짜고싶은 코드 List getEntityList({ DateTime bySelectedDate, }) { ... } List getEntityList({ String bySelectedUserId, }) { ... } // -> 이걸 사용하는 시점에는 list = getEntityList(bySelectedDate: DateTime); list = getEntityList(bySelected..
Data Layer 쪽의 리펙토링을 진행하면서, 내가 데이터 계층의 Repository Impl 클래스를 파이어베이스에 의존적이게 코드를 작성하고 있다는 걸 깨달았다. 클린 아키텍처의 의의를 ‘쉽게 갈아끼울 수 있는 백엔드와 프론트엔드’ 라고 생각하고 적용하려고 노력하고 있기 때문에, 범용 클래스를 무조건 “특정 서비스에 의존적이지 않은 형태”로 작성해야 한다고 생각한다. 이에 요걸 분리하기 위해서 여러가지 고민을 했고, 이걸 글로 남겨두려고 한다! ㅤ 현재 계층 구조와 설계한 사용 모델들을 간략하게 써보면 아래와 같다. Presentation Layer에서는 뷰 계층의 model을 사용한다. Domain Layer에서는 Entity를 사용한다. Data Layer에서는 데이터 계층의 model을 사용한..
파이어베이스에서 데이터를 받아올 때 시간과 날짜를 나타내는 자료형이 Timestamp였고, 플러터에서는 Datetime을 사용하고 있었다. 나는 Timestamp가 flutter(dart)의 내부 클래스이고, datetime과 timestamp가 같은 타입이라고 생각했는데, Timestamp는 Firestore 프레임워크에 포함된 타입이며 datetime으로 사용하기 위해서는 명시적으로 형변환 과정을 거쳐야 하는 것을 확인했다. ㅤ 검색해서 찾다보니 누군가는 Timestamp가 더 세밀한 초 (millisecond)를 표현할 수 있는 자료형이라고 했는데, 파이어베이스에서는 초 단위까지만 입력이 가능하고, DateTime 클래스의 프로퍼티에 microsecond 단위의 데이터를 넣을 수 있는 것으로 보아서..
열심히 프로젝트 구조를 클린 아키텍처 구조로 개선하고 있다. 내가 싼 똥이 점점 정리되는 중이라고 느껴진다. 뭔가 다시 작업을 시작하면 더 깔끔하고 편리하게 작업을 진행할 수 있을 것 같은 느낌이랄까…? ㅋㅋㅋㅋ ㅤ 그래도 나름의 고민을 거듭하면서 구조를 개선해나가고 있는 중이다. 이번 차례에는 Data Layer에 대한 대공사를 진행하고 있는데, repository - repository impl - datasource 의 관계를 어떻게 구성하는게 적절한 지에 대해 고민을 열심히 하고 있다. ㅤ (대충 뭔가 호작질중) ㅤ 그렇게 설계한 2번째 구조는 아래와 같다. ㅤ 먼저 repository와 repository impl은 1대1 관계로 작성해주었다. 각 repository는 interface로서 구현..
ㅤ 클린 아키텍처를 적용하기 위해 기존의 프로젝트를 리팩토링 하고있다. ㅤ 기존에는 각 기능(뷰) 별로 폴더 내에 presentation, domain, data 세 가지 layer를 모두 배치하고, 각 계층 내에 필요한 폴더를 따로 만들어서 관리하고 있었는데, 여러 기능에서 공유되어야 하는 usecase가 하나의 기능 폴더에 귀속되어 있어 다른 기능쪽에서 끌어서 사용해도 되나? 라는 걱정이 많이 되었었는데, 요런 부분들을 타파하기 위해 완전 구조 개선을 시도하고 있다. ㅤ 개선을 시도한 내용은 아래와 같다. 모든 폴더에 따로 놓여있는 모델 → Entity로 이름을 바꿔 한 폴더에서 관리하기 동일한 개념이지만 여러 개로 구현되어있는 모델은 하나로 정리하기 여기저기 흩어진 usecase를 한 폴더에서 관리..
이번에 프로젝트의 전반적인 구조를 클린 아키텍처로 구현해보는 것을 하나의 과제로 삼고 진행해보려 노력했다. 아무래도 구조 자체가 추상화가 많이 되어있다보니, 구조의 의도를 이해하는데에 시간과 노력이 꽤나 들어갔던 것 같다. 아키텍처를 잘 써보고 싶어서 요런 고민도 했었고 Riverpod을 통해 클린 아키텍처를 적절히 구현하려고 요런 고민도 했었다. ㅤ 그리고 실제로 계층 구조를 나누고 그 위에 코드로 기능들을 구현을 하면서 여러가지 장단점이 눈에 들어왔다. 물론 내가 처음에 구조를 잘못 나눠 불편한 점도 많이 있었지만, 어떻게 해야 좀 더 의도에 적합하게 코드를 작성할 수 있을 지도 눈에 들어오기 시작했다. 그 경험들을 잊기전에 짧게 기록으로 남겨두려 한다. ㅤ 단점부터 시작하자 러닝코스트가 너무 높다!..