라벨이 Flutter인 게시물 표시

프로젝트 사면초가

이미지
드디어 저의 사면초가 프로젝트가 완성되었습니다. 군복무 시절, 일이 없어 잔류로 남아있는 일과 시간에는 시간이 잘 가지 않고 심심하기도 해서 보드게임을 즐기곤 했습니다. 각종 보드 게임, 체스, 오목, 장기 등 여러 게임들을 했는데, 저는 그 중 장기가 가장 재미있었습니다. 체스나 오목은 어렸을 때에도 많이 해봤는데, 장기는 태어나서 처음 해봤습니다. 규칙을 아예 모르고 있었습니다. 처음 장기판과 기물들을 자세히 보았더니 예전에 넷마블 알까기 게임이 생각났습니다. 그 게임은 알고 보니 장기판과 장기 기물들을 빌린 거였네요. 전역 후 지금까지도 온라인 게임으로 장기를 두고 있습니다. 장기는 저의 취미로 깊게 자리 잡았습니다. 사면초가( 四面楚歌) '사방에서 초나라 노래가 흘러나온다는 뜻으로, 적에게 완전히 포위되어 희망이 없는 고립무원(孤立無援)의 상태를 이르는 말' 장기는 초한전쟁을 배경으로 만들어진 게임이라고 합니다. 초나라가 한나라와의 전투에서 패배하였고, 한나라가 초나라의 사기를 꺾기 위해서 항복한 초나라 병사들에게 노래를 부르게 했습니다. 초나라의 패왕인 항우가 사방에서 들려오는 초나라의 노래를 듣고  ‘초는 이미 유방에게 넘어간 것인가? 어떻게 포로의 수가 저렇게 많은가!’ 라며  탄식을 하였다고 합니다. 사면초가의 상황을 맞이한거죠. 저의 프로젝트는 한나라의 기물이 지속적으로 부활하면서 초나라의 왕을 노립니다. 유저는 초나라 진영에서 플레이 하고, 초나라는 끊임없이 쳐들어오는 한나라의 공격을 막으면서 최대한 오래 버티는 게임입니다. 그렇게 결국 초나라는 힘이 빠지면서 사방의 한나라 기물들에게 위협받을 것이고, 사면초가의 상황을 맞이한 초나라의 왕은 결국 죽게 됩니다. 메인 스크린 홈 게임 시작, 도움말, 환경 설정으로 이루어진 홈 스크린입니다. 대국에서 사용할 골드를 정하고 포진을 선택하여 게임을 시작할 수 있습니다. 도움말을 통해 게임에 대한 상세한 설명을 참고할 수 있습니다. 환경설정을 통해 효과음 볼륨 조절을 할 수 있습니다. ...

렌더링 된 이미지 크기 구하기

렌더링 된 이미지의 크기를 구하고 싶을 때가 있습니다. 화면의 크기에 따라 반응형으로 이미지의 크기가 변경되고, 이미지의 크기에 따라 다른 위젯의 크기를 변경해 주고 싶을 때가 있습니다. 이미지 크기를 가져오는 법 1. 이미지 위젯에 key를 넣어줘야 합니다. 키를 하나 만들어주세요. /// GlobalKey 를 생성하여 이미지 위젯의 상태를 추적 final GlobalKey imageBoardKey = GlobalKey (); 2. 이미지 위젯에 key를 넣어주세요. Image ( image : imageBoard , key : imageBoardKey , ), 3.  key의 currentContext -> findRenderObject를 통해 RenderBox 객체를 가져옵니다. /// 이미지의 넓이 또는 높이를 이용하여 기물의 위치를 정의 final renderBox = imageBoardKey . currentContext ?. findRenderObject () as RenderBox ; 4. renderBox의 size를 통해 Size 객체를 얻고 width와 height를 구할 수 있습니다. final size = renderBox. size ; 이미지를 미리 로드하기 이미지를 렌더링 하기 위해서 에셋, 네트워크 통신 등 이미지를 읽어와야 합니다. 이 과정은 비동기적으로 이루어지는데, 만약 이미지를 로드 하기 전에 이미지의 크기를 구하려 한다면 size의 width와 height의 크기가 0으로 반환 될 것입니다. 예컨대 StatefulWidget의 initState 함수에 위 단락의 3, 4번과 같이 코드를 작성한다면 이미지의 크기를 구할 수 없을 수도 있습니다. 또는 addPostFrameCallback을 통해 위젯 트리의 완성을 기다려 준다 하더라도 이미지의 로딩 시간이 길면 initState를 통해 크기를 구할 수 없습니다. 초반에 이미지의 크기를 바로 구하고 싶으시다면 이미지를 미리 로드 해야 합니다....

팩토리 패턴을 응용한 플러터의 클린 아키텍처

이미지
클린 아키텍처 전 아직도 이 그림이 뭔지 하나도 모르겠습니다. 그럼에도 불구하고 여러 블로그를 탐방하며 클린 아키텍처를 최대한 이해하려고 했고, 저만의 클린 코드를 작성해 보았습니다. 클린 아키텍처를 공부하면서 맘에 안들었던 점 폴더 구조가 크게 두가지가 있습니다. Feature-first와 Layer-first 입니다. 최상위에 위치하는 폴더가 앱의 기능 단위인 것과 클린 아키텍처의 Data, Domain, Presentation 계층인 것입니다. 그런데 전... 둘 다 썩 맘에 들지 않았습니다. Feature-first는 기능 단위로 코드 구조가 눈에 확 들어와서 좋긴 한데, 둘 이상의 Feature가 공유하는 코드가 있다면 그게 전부 common 폴더로 모이게 됩니다. 그러면 common 폴더가 비대해지면서 폴더 구조의 체계가 모호해지는 부분이 있습니다. Layer-first는 기능을 수정해야 할 때 폴더를 이리 저리 돌아다녀야 하고... 좀 난잡한 느낌이 듭니다. 그리고 클린 아키텍처를 공부하면서 새롭게 배운 단어들이 생소했습니다. Entity, DTO, Domain, Presentation... 이 단어들을 쓰고 싶지 않았습니다. 뭐 얼마든지 바꾸면 되겠지만, 네이밍 관련해서도 깊게 고민했습니다. 실제로 저와 같이 사이드 프로젝트 진행하는 동료들이 제 프로젝트를 보고 원하는 코드를 찾는 데 좀 어려웠다고 전했습니다. 클린 아키텍처를 잘 모르는 개발자라면 entity가 뭐고, domain이 뭔지 잘 모릅니다. 또한 DTO 클래스의 필요성을 전혀 느끼지 못했습니다. 왜냐하면 Dart에는 factory 생성자가 있기 때문입니다. 굳이 DTO 클래스를 만들지 않더라도 충분히 외부 환경에 유연하게 대응할 수 있겠다고 생각했습니다. 그렇게 고민을 하면서 저만의 클린 코드를 만들게 되었습니다. 먼저, 코드의 세부 구성부터 보여드리겠습니다. 외부 모델 DTO와 내부 모델 Entity -> Model로 통일 데이터 모델의 경우, DTO와 Entity로 나눕니다....