1월, 2025의 게시물 표시

프로젝트 사면초가

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

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

렌더링 된 이미지의 크기를 구하고 싶을 때가 있습니다. 화면의 크기에 따라 반응형으로 이미지의 크기가 변경되고, 이미지의 크기에 따라 다른 위젯의 크기를 변경해 주고 싶을 때가 있습니다. 이미지 크기를 가져오는 법 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를 통해 크기를 구할 수 없습니다. 초반에 이미지의 크기를 바로 구하고 싶으시다면 이미지를 미리 로드 해야 합니다....

개발자로 전직하기

이미지
과거를 돌아보면 저는 개발자가 되기 위해 인생을 살아온 것은 아니었습니다. 그냥 살다 보니 저의 진로가 개발자로 정해졌습니다. 컴퓨터 게임을 좋아했다 보니까 컴퓨터와 관련된 직업을 갖고 싶다는 생각에... 고등학생이었을 때 C언어를 공부해봤고 그 이후 무지성으로 소프트웨어학과에 진학하게 되었습니다. 소프트웨어학과는 게임과는 크게 상관 없었습니다. 시꺼먼 화면에 이상한 영어 글자를 쓰고 읽는 학과입니다. 코딩은 생각보다 그렇게 재미 없지는 않았습니다. 저의 뇌가 '너 코딩에 재능이 있을수도 있어.' 라고 말해주는 느낌이었죠. 그렇게 C 언어부터 시작해서 자바, 파이썬, 리액트, 뷰, 도커와 쿠버네티스, MySQL, 그리고 지금 저의 주무기가 된 플러터까지.. 학교다니면서 다양한 기술들을 찍먹해봤네요. (물론 지금은 플러터 빼고 다 까먹었습니다!) 예전에는 개발자가 되기 위한 명확한 가이드가 많지 않았던 것 같습니다. 진로를 설정하면서 개발자에 대한 속 시원한 정보를 얻은 적이 없던 것 같습니다. 물론 요즘은 개발자 블로거, 유튜버가 많이 생겨나서 어디서든 손쉽게 정보를 얻을 수 있습니다. 옛날 생각을 하며 개발자에 대한 글을 적어보았습니다. 프로그래밍 첫 입문 전 처음에 윤성우의 열혈 C 프로그래밍이라는... 엄청나게 유명한 C 언어 책을 구매해서 공부했습니다. 변수 선언하기, 조건문, 반복문 등 문법을 배우고 printf 함수를 통해 콘솔에 찍어보는 연습을 하였습니다. 그 이후에는 윤성우의 열혈 자료구조라는... 데이터의 자료구조에 대해 공부하게 되었죠. 자료구조를 만들고... 역시나 콘솔에 찍어보고... 결과를 확인했습니다. 저는 너무 답답했습니다. '대체 이걸로 뭘 할 수 있다는걸까?' 라는 질문만 머릿속에서 맴돌았습니다. 콘솔 찍기를 잘 한다고 해서 웹사이트와 앱을 만들거나, 밥을 지어 먹을 수 있는 전기밥솥을 만들거나, ChatGPT같은 인공지능을 만들 수는 없습니다. 이렇게 배우는게 맞나? 삐뚤어진 다이아몬드 콘솔 찍기 콘...

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

이미지
클린 아키텍처 전 아직도 이 그림이 뭔지 하나도 모르겠습니다. 그럼에도 불구하고 여러 블로그를 탐방하며 클린 아키텍처를 최대한 이해하려고 했고, 저만의 클린 코드를 작성해 보았습니다. 클린 아키텍처를 공부하면서 맘에 안들었던 점 폴더 구조가 크게 두가지가 있습니다. 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로 나눕니다....