<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>초기 개발 on monkshark.dev</title><link>https://monkshark.github.io/tags/%EC%B4%88%EA%B8%B0-%EA%B0%9C%EB%B0%9C/</link><description>Recent content in 초기 개발 on monkshark.dev</description><generator>Hugo -- gohugo.io</generator><language>ko</language><lastBuildDate>Thu, 09 Apr 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://monkshark.github.io/tags/%EC%B4%88%EA%B8%B0-%EA%B0%9C%EB%B0%9C/index.xml" rel="self" type="application/rss+xml"/><item><title>#5 - Flutter 첫 한 달</title><link>https://monkshark.github.io/p/first-month/</link><pubDate>Thu, 09 Apr 2026 00:00:00 +0000</pubDate><guid>https://monkshark.github.io/p/first-month/</guid><description>&lt;h2 id="12월-7일-같은-날의-두-커밋"&gt;&lt;a href="#12%ec%9b%94-7%ec%9d%bc-%ea%b0%99%ec%9d%80-%eb%82%a0%ec%9d%98-%eb%91%90-%ec%bb%a4%eb%b0%8b" class="header-anchor"&gt;&lt;/a&gt;12월 7일, 같은 날의 두 커밋
&lt;/h2&gt;&lt;p&gt;2023년 12월 7일. &lt;a class="link" href="https://github.com/Monkshark/hansol_hs_java_app" target="_blank" rel="noopener"
 &gt;Java 레포&lt;/a&gt;에 v0.12.3 Beta 마지막 커밋을 남기고, 같은 날 Flutter 레포에 first commit을 찍었다. 하나를 끝내고 바로 다음을 시작한 것이다.&lt;/p&gt;
&lt;p&gt;첫 커밋은 &lt;code&gt;flutter create&lt;/code&gt; 그 자체였다. 137개 파일, 5,126줄. Flutter가 자동 생성하는 프로젝트 템플릿이다. android, ios, web, linux, macos, windows — 모든 플랫폼의 보일러플레이트가 포함되어 있었다.&lt;/p&gt;
&lt;p&gt;하지만 이 커밋에 이미 Java에서 가져온 파일 3개가 들어 있었다:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;lib/GetMealData.dart
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;lib/GetNoticeData.dart
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;lib/GetTimeTableData.dart
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Java의 &lt;code&gt;getMealData.java&lt;/code&gt;, &lt;code&gt;getNoticeData.java&lt;/code&gt;, &lt;code&gt;getTimetableData.java&lt;/code&gt;를 Dart로 포팅한 것이다. 프로젝트를 만들자마자 가장 먼저 한 일이 NEIS API 연동 코드를 옮기는 것이었다.&lt;/p&gt;
&lt;h2 id="첫째-주-뼈대-잡기-127--1213"&gt;&lt;a href="#%ec%b2%ab%ec%a7%b8-%ec%a3%bc-%eb%bc%88%eb%8c%80-%ec%9e%a1%ea%b8%b0-127--1213" class="header-anchor"&gt;&lt;/a&gt;첫째 주: 뼈대 잡기 (12/7 ~ 12/13)
&lt;/h2&gt;&lt;h3 id="화면-구조"&gt;&lt;a href="#%ed%99%94%eb%a9%b4-%ea%b5%ac%ec%a1%b0" class="header-anchor"&gt;&lt;/a&gt;화면 구조
&lt;/h3&gt;&lt;p&gt;둘째 커밋(12/8)에서 화면 4개의 껍데기를 만들었다:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;lib/Screens/homeScreen.dart +28줄
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;lib/Screens/mainScreen.dart +11줄
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;lib/Screens/mealScreen.dart +29줄
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;lib/Screens/noticeScreen.dart +29줄
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Java 프로토타입과 동일한 구조다. 홈, 급식, 공지. BottomNavigation으로 전환하는 방식도 같았다. 이미 Java에서 검증한 화면 흐름을 그대로 가져왔다.&lt;/p&gt;
&lt;h3 id="파일-구조-리팩토링"&gt;&lt;a href="#%ed%8c%8c%ec%9d%bc-%ea%b5%ac%ec%a1%b0-%eb%a6%ac%ed%8c%a9%ed%86%a0%eb%a7%81" class="header-anchor"&gt;&lt;/a&gt;파일 구조 리팩토링
&lt;/h3&gt;&lt;p&gt;셋째 커밋(12/10)에서 바로 파일 구조를 정리했다:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;GetMealData.dart → Data/mealDataApi.dart
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;GetNoticeData.dart → Data/noticeDataApi.dart
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;GetTimeTableData.dart → Data/tiemtableDataApi.dart
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;루트에 흩어져 있던 API 파일들을 &lt;code&gt;Data/&lt;/code&gt; 폴더로 모았다. 파일명도 PascalCase에서 camelCase로 바꿨다. Java 습관을 Dart 컨벤션으로 전환하는 과정이었다. (참고로 &lt;code&gt;tiemtable&lt;/code&gt;은 오타다. 나중에 &lt;code&gt;timetable&lt;/code&gt;로 고쳤다.)&lt;/p&gt;
&lt;h3 id="알림-첫-시도-1212--1213"&gt;&lt;a href="#%ec%95%8c%eb%a6%bc-%ec%b2%ab-%ec%8b%9c%eb%8f%84-1212--1213" class="header-anchor"&gt;&lt;/a&gt;알림 첫 시도 (12/12 ~ 12/13)
&lt;/h3&gt;&lt;p&gt;Flutter 시작 5일 만에 알림 기능에 손을 댔다. &lt;a class="link" href="https://monkshark.github.io/p/meal-notification/" &gt;#3&lt;/a&gt;에서 자세히 다뤘지만, &lt;code&gt;NotificationManager.dart&lt;/code&gt; 165줄을 만들고, &lt;code&gt;FirebaseCloudMessaging.dart&lt;/code&gt;를 넣었다 4시간 만에 삭제하는 사건이 이때 일어났다.&lt;/p&gt;
&lt;p&gt;돌이켜보면 너무 일찍 손을 댄 것이었다. 화면 구조도 다 안 잡힌 상태에서 알림까지 만들려고 했으니.&lt;/p&gt;
&lt;h2 id="둘째-주-기능-구현-1215--1220"&gt;&lt;a href="#%eb%91%98%ec%a7%b8-%ec%a3%bc-%ea%b8%b0%eb%8a%a5-%ea%b5%ac%ed%98%84-1215--1220" class="header-anchor"&gt;&lt;/a&gt;둘째 주: 기능 구현 (12/15 ~ 12/20)
&lt;/h2&gt;&lt;p&gt;12월 17일에 커밋이 9개다. 하루에 9번. 이 시기가 가장 집중적으로 개발한 때였다.&lt;/p&gt;
&lt;p&gt;이 주에 만든 것들:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;급식 화면&lt;/strong&gt; — NEIS API 연동, 조식/중식/석식 표시, 날짜 이동&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;시간표 화면&lt;/strong&gt; — 학년/반 선택, 요일별 시간표 표시&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;설정 화면&lt;/strong&gt; — 학년/반 저장, 알림 on/off&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;로그인/회원가입&lt;/strong&gt; — Firebase Auth 연동&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;달력&lt;/strong&gt; — 학사일정 표시&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;12월 20일에는 커밋이 7개. 이 이틀(17일, 20일)에 전체 첫 달 커밋의 거의 절반이 몰려 있다. 기숙사에서 자습 시간과 주말을 전부 개발에 쏟은 날들이다.&lt;/p&gt;
&lt;h2 id="셋째-주-api-안정화-1220--1227"&gt;&lt;a href="#%ec%85%8b%ec%a7%b8-%ec%a3%bc-api-%ec%95%88%ec%a0%95%ed%99%94-1220--1227" class="header-anchor"&gt;&lt;/a&gt;셋째 주: API 안정화 (12/20 ~ 12/27)
&lt;/h2&gt;&lt;p&gt;12월 25일, 크리스마스에도 코딩했다. 이날 커밋은 API 3개를 전부 리팩토링한 것이다:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;lib/API/MealDataApi.dart +72줄, -65줄
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;lib/API/NoticeDataApi.dart +54줄, -38줄
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;lib/API/TimetableDataApi.dart +38줄, -27줄
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Java에서 포팅한 초기 코드가 Dart답지 않았다. &lt;code&gt;HttpURLConnection&lt;/code&gt; 스타일로 작성했던 걸 &lt;code&gt;http&lt;/code&gt; 패키지의 &lt;code&gt;get()&lt;/code&gt; 방식으로 바꾸고, 에러 핸들링을 추가하고, JSON 파싱을 정리했다.&lt;/p&gt;
&lt;p&gt;12월 27일에는 파일명을 Dart 컨벤션(snake_case)으로 전환했다:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;MealDataApi.dart → meal_data_api.dart
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NoticeDataApi.dart → notice_data_api.dart
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;TimetableDataApi.dart → timetable_data_api.dart
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Java의 PascalCase → Dart의 snake_case. 이런 사소한 컨벤션 전환이 프로젝트 초기에 계속 있었다.&lt;/p&gt;
&lt;h2 id="넷째-주-meal-모델-17"&gt;&lt;a href="#%eb%84%b7%ec%a7%b8-%ec%a3%bc-meal-%eb%aa%a8%eb%8d%b8-17" class="header-anchor"&gt;&lt;/a&gt;넷째 주: Meal 모델 (1/7)
&lt;/h2&gt;&lt;p&gt;1월 7일 커밋에서 &lt;code&gt;Meal&lt;/code&gt; 데이터 모델이 처음 등장한다:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;lib/Data/meal.dart +13줄
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;그 전까지는 급식 데이터를 &lt;code&gt;String&lt;/code&gt;으로만 다뤘다. Java 시절과 똑같이 API 응답을 문자열로 받아서 화면에 바로 뿌렸다. 하지만 급식 정보에는 메뉴, 칼로리, 영양정보, 날짜, 끼니 구분 등 여러 필드가 있고, 이걸 하나의 모델 클래스로 묶어야 코드가 정리된다.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Meal&lt;/code&gt; 모델을 만들면서 동시에 &lt;code&gt;meal_card.dart&lt;/code&gt;가 95줄이나 추가되었다. 급식 카드 위젯이 별도 파일로 분리된 것이다. Java에서는 &lt;code&gt;MealFragment&lt;/code&gt; 하나에 271줄이 전부 들어 있었는데, Flutter에서는 위젯 단위로 분리하기 시작했다.&lt;/p&gt;
&lt;h2 id="첫-달의-숫자"&gt;&lt;a href="#%ec%b2%ab-%eb%8b%ac%ec%9d%98-%ec%88%ab%ec%9e%90" class="header-anchor"&gt;&lt;/a&gt;첫 달의 숫자
&lt;/h2&gt;&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;항목&lt;/th&gt;
 &lt;th&gt;수치&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;기간&lt;/td&gt;
 &lt;td&gt;2023-12-07 ~ 2024-01-07&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;커밋 수&lt;/td&gt;
 &lt;td&gt;36&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;가장 많은 날&lt;/td&gt;
 &lt;td&gt;12/17 (9커밋), 12/20 (7커밋)&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;커밋 0개인 날&lt;/td&gt;
 &lt;td&gt;12/9, 12/11, 12/14, 12/16, 12/21~24, 12/26, 12/28~1/6&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;커밋이 없는 날이 꽤 많다. 매일 코딩한 게 아니라, &lt;strong&gt;할 수 있는 날에 몰아서&lt;/strong&gt; 했다. 기숙사 생활이라 평일 저녁 자습 시간과 주말이 개발 시간이었고, 시험이나 학교 일정이 있으면 며칠씩 손을 못 대기도 했다. (근데 사실 공부는 안했다.)&lt;/p&gt;
&lt;h2 id="돌아보면"&gt;&lt;a href="#%eb%8f%8c%ec%95%84%eb%b3%b4%eb%a9%b4" class="header-anchor"&gt;&lt;/a&gt;돌아보면
&lt;/h2&gt;&lt;p&gt;첫 한 달의 핵심은 &lt;strong&gt;Java에서 검증한 구조를 Dart로 옮기는 것&lt;/strong&gt;이었다. 화면 구조, API 파싱, 데이터 흐름 — 전부 Java에서 한 번 해봤던 것들이다. 덕분에 &amp;ldquo;무엇을 만들어야 하는지&amp;quot;는 고민하지 않았고, &amp;ldquo;Flutter에서는 이걸 어떻게 만드는지&amp;quot;에만 집중할 수 있었다.&lt;/p&gt;
&lt;p&gt;동시에 Java 습관을 하나씩 버리는 과정이기도 했다. 파일 이름, 폴더 구조, 코딩 컨벤션을 Dart 방식으로 바꿔가면서, 코드가 점점 &amp;ldquo;Flutter다워&amp;quot;졌다. 이 전환은 첫 달에 끝나지 않고 이후 몇 달간 계속되었다.&lt;/p&gt;
&lt;h2 id="다음-글에서는"&gt;&lt;a href="#%eb%8b%a4%ec%9d%8c-%ea%b8%80%ec%97%90%ec%84%9c%eb%8a%94" class="header-anchor"&gt;&lt;/a&gt;다음 글에서는
&lt;/h2&gt;&lt;p&gt;첫 달에 포팅한 NEIS API 급식 파싱이 이후 어떻게 진화했는지 — 캐싱, 월 단위 프리페치, SWR 패턴까지의 과정을 다룬다.&lt;/p&gt;</description></item></channel></rss>