<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: baanbok</title>
    <description>The latest articles on DEV Community by baanbok (@baanbok).</description>
    <link>https://dev.to/baanbok</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4025349%2F3c627c82-665e-4ff5-b256-7d9152405f49.png</url>
      <title>DEV Community: baanbok</title>
      <link>https://dev.to/baanbok</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/baanbok"/>
    <language>en</language>
    <item>
      <title>The night before launch, every door was wide open</title>
      <dc:creator>baanbok</dc:creator>
      <pubDate>Tue, 14 Jul 2026 13:57:42 +0000</pubDate>
      <link>https://dev.to/baanbok/the-night-before-launch-every-door-was-wide-open-3kj6</link>
      <guid>https://dev.to/baanbok/the-night-before-launch-every-door-was-wide-open-3kj6</guid>
      <description>&lt;p&gt;At the end of the last post I mentioned a bill. This post is that bill.&lt;/p&gt;

&lt;p&gt;Let me start with three lines from the commit log.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;06/28 13:18  feat: enforce auth (401) — no token, no entry
06/28 13:41  fix: resource ownership checks (IDOR) — check items, body metrics, templates
06/28 23:04  submitted to App Store review
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I locked every door, and ten hours later I pressed the submit button. This post is about how those doors got left open in the first place — and who found them.&lt;/p&gt;

&lt;h2&gt;
  
  
  How the backdoor was born
&lt;/h2&gt;

&lt;p&gt;Rewind to the first two days. There was no app yet, no login screen, and testing the server API meant dealing with tokens. Annoying. So I added a convenience: &lt;strong&gt;a fallback where &lt;code&gt;?userId=1&lt;/code&gt; in the query string just... makes you that user.&lt;/strong&gt; No token needed. For development, it's heaven. One curl line and everything works.&lt;/p&gt;

&lt;p&gt;It's the textbook "runs right now" code. And as I said in the last post, the problem with this kind of code is that it never shows up in a demo. Every feature works. The house looks perfectly fine with the doors open.&lt;/p&gt;

&lt;p&gt;Day-6 me was drunk on the feature list and had forgotten the door existed.&lt;/p&gt;

&lt;h2&gt;
  
  
  I asked the builder to inspect the building
&lt;/h2&gt;

&lt;p&gt;The weekend before submission, I stopped adding features and gave my AI pair a different job:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;"Real users are going to touch this now. Review the entire server from a security standpoint — auth, permissions, data exposure. Think like an attacker."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The same pair that had been laying bricks all week put on an inspector's hat and started tapping its own walls. A few turns later, the report came back.&lt;/p&gt;

&lt;p&gt;The summary: &lt;strong&gt;without any token, just by changing &lt;code&gt;?userId=&lt;/code&gt;, anyone could read and modify any user's data.&lt;/strong&gt; Meals, workouts, body weight — everything. The server didn't have authentication. It had authentication-shaped decoration.&lt;/p&gt;

&lt;p&gt;Here's the part that actually chilled me, though — that door wasn't an AI mistake. &lt;strong&gt;I asked for it, I reviewed it, I merged it.&lt;/strong&gt; If this were company code, nine years of habit would have flagged it in review instantly. But it was &lt;em&gt;my&lt;/em&gt; project, so "I'll remove it later" felt fine. That's how the speed bill arrives: with interest, right before launch.&lt;/p&gt;

&lt;h2&gt;
  
  
  That night
&lt;/h2&gt;

&lt;p&gt;I fixed it the same night, straight through.&lt;/p&gt;

&lt;p&gt;The policy was deliberately blunt, because every exception is a future backdoor:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;No token → 401. Everywhere.&lt;/strong&gt; No fallbacks. The whitelist is login and signup, nothing else.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ownership checks on every resource.&lt;/strong&gt; "Does this check item actually belong to this token's owner?" — verified server-side, every time. That also kills IDOR probing with other people's IDs.&lt;/li&gt;
&lt;li&gt;All authorization decisions live on the server. Blocking things only in the client is the same as not blocking them.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I tore it out through the early morning, the commits landed Sunday afternoon — 13:18 auth enforcement, 13:41 ownership checks — and at 23:04 that night, I submitted for review.&lt;/p&gt;

&lt;p&gt;The one mercy: at that point, the app had exactly &lt;strong&gt;one user. Me.&lt;/strong&gt; There was nobody to walk through the open door. So the damage was zero — but let's be honest, that's not skill. That's luck. If I had shipped without knowing, gotten real users, and &lt;em&gt;then&lt;/em&gt; someone found it? This series wouldn't be a build log. It would be an apology letter.&lt;/p&gt;

&lt;h2&gt;
  
  
  The rule this left me with
&lt;/h2&gt;

&lt;p&gt;Every vibe-coding conversation eventually hits the same worry: "how can you trust AI code?"&lt;/p&gt;

&lt;p&gt;After this incident, my answer settled: &lt;strong&gt;I don't trust it. I verify it. And I make the AI do the verifying too.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Sounds contradictory, but the key is the role. The AI laying bricks and the AI doing inspection look at the same code with different eyes. If you only ever say "build this" and never say "now attack it," the second pair of eyes never opens. And knowing &lt;em&gt;what to ask for&lt;/em&gt; — knowing that "security review" belongs on the pre-launch checklist at all — that doesn't come from the tool. That comes from nine years of watching other people's servers catch fire.&lt;/p&gt;

&lt;p&gt;Speed from the AI, accountability on me. Three posts in, that line isn't a slogan anymore. It's what a man writes after a night without sleep.&lt;/p&gt;

&lt;p&gt;Next post is a change of pace — dogfooding my own app through my own cut. Featuring: the mystery of the list that saved but showed up empty (culprit: a JPA trap that gets 9-year veterans too), and the day I learned a frozen number on screen is worse than no number at all.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Baanbok is free on the &lt;a href="https://apps.apple.com/app/id6785158508" rel="noopener noreferrer"&gt;App Store&lt;/a&gt; — no sign-up required, guest mode gets you everything.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>security</category>
      <category>backend</category>
      <category>sideprojects</category>
    </item>
    <item>
      <title>Zero React Native experience to a 6-day MVP — what "vibe coding" actually looked like</title>
      <dc:creator>baanbok</dc:creator>
      <pubDate>Mon, 13 Jul 2026 02:30:25 +0000</pubDate>
      <link>https://dev.to/baanbok/zero-react-native-experience-to-a-6-day-mvp-what-vibe-coding-actually-looked-like-1lo4</link>
      <guid>https://dev.to/baanbok/zero-react-native-experience-to-a-6-day-mvp-what-vibe-coding-actually-looked-like-1lo4</guid>
      <description>&lt;p&gt;In the prologue I said I ran &lt;code&gt;git init&lt;/code&gt; on the night of June 24th. This post is about the six days that followed.&lt;/p&gt;

&lt;p&gt;Fair warning: this is not an "AI made coding easy!" post. If anything, it's the opposite. Roughly half of what I did over those six days was &lt;strong&gt;distrusting what the AI produced.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The hand I was dealt
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Backend dev, 9 years. Java, Kotlin, Spring, JPA — on this turf I do everything from design to deployment alone.&lt;/li&gt;
&lt;li&gt;But: nine years of &lt;strong&gt;MySQL and MariaDB only.&lt;/strong&gt; I picked PostgreSQL for this project for the deeply professional reason that I'd always wanted to try it. So even on my home turf, one thing was brand new.&lt;/li&gt;
&lt;li&gt;React Native: zero lines written. Ever.&lt;/li&gt;
&lt;li&gt;Expo? I genuinely thought it was a trade fair.&lt;/li&gt;
&lt;li&gt;Time budget: weekday evenings after work and the gym — roughly 10pm to midnight — plus weekends.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The old me would have started with "step 1: complete a React Native course." And we all know how that goes. The side project dies quietly somewhere around week 3 of the course. My GitHub has three repos that died exactly that death.&lt;/p&gt;

&lt;p&gt;This time I skipped the course and sat an AI down as my pair.&lt;/p&gt;

&lt;h2&gt;
  
  
  The division of labor — this is the whole trick
&lt;/h2&gt;

&lt;p&gt;People hear "vibe coding" and picture typing "make me an app" and watching magic happen. Six days in, my conclusion is different: &lt;strong&gt;it only works when the division of labor is explicit.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;What I kept:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The domain model.&lt;/strong&gt; A three-layer structure — Template → Schedule → Daily Check. Checks are hierarchical with three states. Daily logs are &lt;em&gt;snapshot copies&lt;/em&gt; of the template, so editing a template never rewrites your history. Decisions like these are human work. This is where nine years actually got spent.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;API design and the entire server.&lt;/strong&gt; Home turf.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;And verification.&lt;/strong&gt; Whether AI-written code gets merged is my call, every time.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What I delegated:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Every React Native screen.&lt;/strong&gt; Components, navigation, state management — the conventions of an ecosystem I didn't know.&lt;/li&gt;
&lt;li&gt;Hundreds of "how do I do X in Expo?" questions. Hours of doc-diving compressed into a few conversation turns.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So I drew the blueprints, the AI laid the bricks, and I walked around tapping the walls. It's a lot like the code review I do at my day job — except this reviewer never sleeps and never sulks.&lt;/p&gt;

&lt;h2&gt;
  
  
  The six days, replayed from the commit log
&lt;/h2&gt;

&lt;p&gt;I dug up the actual commit log to write this post. It didn't match my memory. The log is scarier.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Day 0 — June 24 (Wed), night.&lt;/strong&gt;&lt;br&gt;
App repo at 21:54, server repo at 21:55. One minute apart. And the second commit of the night, in &lt;em&gt;both&lt;/em&gt; repos, isn't code — it's &lt;code&gt;docs: add CLAUDE.md&lt;/code&gt;, an architecture document written for my AI pair. I onboarded it the way you'd onboard a human teammate: design intent and next steps, written down before bed. Looking back, this was the move that bought the speed. &lt;strong&gt;In vibe coding, the first real commit is context, not code.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Day 1 — June 25 (Thu).&lt;/strong&gt;&lt;br&gt;
6:52am, before leaving for work: &lt;code&gt;backend API complete&lt;/code&gt;. Migrations, service layer, REST endpoints — a full loop in under a day. Home turf is fast.&lt;/p&gt;

&lt;p&gt;The real event was that night. 21:50 template screen → 21:56 schedule → 22:11 trends → 22:16 settings → 23:13 login. &lt;strong&gt;A screen landing every 6, 15, 5 minutes&lt;/strong&gt; — from a guy who had never written a line of RN. Here's what it actually looked like: I define "this screen, this data, this structure," the AI builds it, I poke at it in the simulator, and if it holds, I commit. That loop ran all night. I felt like a magician. Completely lost track of time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Day 2 — June 26 (Fri).&lt;/strong&gt;&lt;br&gt;
Free-tier gating, pick-one meal slots, a "+2.5kg?" double-progression hint. And then, at 17:58, this commit: &lt;code&gt;fix: enforce JWT userId in all controllers — remove ?userId= param dependency&lt;/code&gt;. Early on, for convenience, I'd let a query parameter switch the user. That day I started tearing the backdoor out. What I didn't know yet was how uncomfortably close I'd cut it. Next post.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Day 3 — June 27 (Sat).&lt;/strong&gt;&lt;br&gt;
No daytime commits. Gym, and time with my wife. The deep-work session started at night and rolled into —&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Day 4 — June 28 (Sun).&lt;/strong&gt;&lt;br&gt;
Five commits in the 2am range: account deletion, onboarding coach marks, a new app icon. One of them, at 2:28am: &lt;code&gt;fix: JPQL path (userId → user.id)&lt;/code&gt;. That one compiles clean and &lt;strong&gt;crashes on boot&lt;/strong&gt; — a landmine specific to the JPA + PostgreSQL combo that nine years of MySQL had never shown me. It would bite me again later, more than once.&lt;/p&gt;

&lt;p&gt;Daytime: i18n (Korean/English), notifications, kg/lb units. And at 23:04 — &lt;strong&gt;submitted to the App Store.&lt;/strong&gt; Four days after &lt;code&gt;git init&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Day 5 — June 29 (Mon).&lt;/strong&gt;&lt;br&gt;
Rejected. Two issues. Fixed after work, resubmitted as build 4 at 21:47.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Day 6 — June 30 (Tue).&lt;/strong&gt;&lt;br&gt;
Didn't sit still while waiting on review: completion feedback, a rest timer between sets, one-line daily notes.&lt;/p&gt;

&lt;p&gt;So — I remembered it as "an MVP in 6 days." The log says the app had taken shape by night two, went to review on day four, and by day six had already eaten a rejection and been resubmitted. My memory was modest. The log was precise.&lt;/p&gt;

&lt;h2&gt;
  
  
  It wasn't free, though
&lt;/h2&gt;

&lt;p&gt;If I stopped here, this would read like a vibe-coding hype post. That's not what this is.&lt;/p&gt;

&lt;p&gt;AI code is optimized for &lt;em&gt;runs right now&lt;/em&gt;. And nine years in backend teaches you exactly what "runs right now" leaves behind: temporary hacks, over-broad exception handling, convenience doors left unlocked. None of it shows up in a demo. It shows up in production, at the worst possible moment.&lt;/p&gt;

&lt;p&gt;Day-6 me was drunk on having a working MVP and didn't notice the bill piling up. How much it came to — I'll write that next. Hint: I found it right before launch, and I did not sleep that night.&lt;/p&gt;

&lt;p&gt;One rule survived all six days, and it's the one I'd give anyone trying this: &lt;strong&gt;speed from the AI, accountability on me.&lt;/strong&gt; If something in this app breaks, it's not the AI's fault. It's mine, for skipping verification.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Baanbok is free on the &lt;a href="https://apps.apple.com/app/id6785158508" rel="noopener noreferrer"&gt;App Store&lt;/a&gt; — no sign-up required, guest mode gets you everything.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Next: the night before launch, when I found the door wide open.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>reactnative</category>
      <category>sideprojects</category>
      <category>kotlin</category>
    </item>
    <item>
      <title>I deleted every fitness app I tried. So I built my own — in 17 days, after work.</title>
      <dc:creator>baanbok</dc:creator>
      <pubDate>Sat, 11 Jul 2026 16:55:33 +0000</pubDate>
      <link>https://dev.to/baanbok/i-deleted-every-fitness-app-i-tried-so-i-built-my-own-in-17-days-after-work-2f48</link>
      <guid>https://dev.to/baanbok/i-deleted-every-fitness-app-i-tried-so-i-built-my-own-in-17-days-after-work-2f48</guid>
      <description>&lt;h2&gt;
  
  
  I'm a back-end developer in Korea.
&lt;/h2&gt;

&lt;p&gt;Nine years of Java, Kotlin, and Spring — all of it building other people's servers. Until last month, there wasn't a single app with my name on it in any store.&lt;/p&gt;

&lt;p&gt;That changed in 17 days: 172 commits, 30 database migrations, 5 languages. A fitness and diet app called &lt;b&gt;Baanbok&lt;/b&gt; — it's Korean for repetition. It's live on the App Store now, and currently fighting its way through Google Play's closed-testing gauntlet (a mandatory 14-day gate — 5 days to go).&lt;/p&gt;

&lt;p&gt;The numbers make it sound like a hackathon story. It wasn't. I have a full-time job. I just opened my laptop every evening after work and stacked a little more on top of yesterday's pile.&lt;/p&gt;

&lt;p&gt;This series is the log of those 17 days. But honestly, the story starts three years earlier.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why the app is called "Repetition"
&lt;/h2&gt;

&lt;p&gt;In the spring of 2023, I was in a bad place. I'll keep the details to myself, but I'll tell you the part that matters for this story: the heaviest thing I carried wasn't sadness. It was guilt. The kind that renews itself every morning — you did nothing again today. I learned firsthand how deep that spiral goes.&lt;/p&gt;

&lt;p&gt;That May, I signed up for a gym. First time in my life. 98 kg, zero muscle, no idea what I was doing.&lt;/p&gt;

&lt;p&gt;There was no grand resolution. I just went. Then I went again the next day. The weights were embarrassing and my form was terrible, but on the walk home after each session, the guilt went quiet for a while.&lt;/p&gt;

&lt;p&gt;That was three years ago. I'm still going.&lt;/p&gt;

&lt;p&gt;What pulled me out wasn't willpower. It was repetition. So when I built an app three years later, there was only ever one name for it. Calling it anything else would have felt like skipping out on a debt.&lt;/p&gt;

&lt;p&gt;(Fun fact: the romanization should technically be "Banbok," but I couldn't let an app built on never punishing you start with the word "ban." So it got an extra a. The only thing banned in this app is the word itself.)&lt;/p&gt;




&lt;h2&gt;
  
  
  Okay, but what does the app do?
&lt;/h2&gt;

&lt;p&gt;This year I started a proper 16-week cut, and figured I'd finally track things seriously. I installed every fitness and diet app I could find. Then I deleted every single one.&lt;/p&gt;

&lt;p&gt;They all demanded the same thing: daily input. Search the food, type the grams, save. Chicken breast, 200g. Same as yesterday. Same as tomorrow.&lt;/p&gt;

&lt;p&gt;Here's the thing about being on a cut — your days are almost comically repetitive. The meal plan is fixed. The workout split is fixed. The information content of my day is basically zero. And these apps wanted me to re-enter that zero, by hand, every single day.&lt;/p&gt;

&lt;p&gt;As a backend dev, this offended me on a professional level. It's recomputing an identical response on every request. These apps don't cache. And humans have far less patience than servers — we drop the connection after about three days, then leave a review blaming ourselves for it.&lt;/p&gt;

&lt;p&gt;So the idea was one sentence: &lt;b&gt;check, don't log.&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;Design your plan once, with as much care as you want. Then every day, the app lays out today's list and you just tap what you did. Macros and volume aggregate themselves from your checks. And one more rule, the one I refused to negotiate on: the app never, ever scolds you for a missed day. I know exactly what guilt does to a person. I wasn't going to ship a guilt machine.&lt;/p&gt;

&lt;p&gt;On June 24th, at night, I ran&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git init.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  What's coming in this series
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;How a backend dev with zero React Native experience got to an MVP in 6 days by pairing with AI — and what "vibe coding" actually looks like in practice&lt;/li&gt;
&lt;li&gt;The night before launch, when I discovered my server's auth had a door wide open (AI builds fast; locking up is still your job)&lt;/li&gt;
&lt;li&gt;Dogfooding my own app through my own cut, and learning that a frozen number on screen is worse than no number&lt;/li&gt;
&lt;li&gt;Why I killed the streak feature — the industry's default retention answer — and what I stole from an old racing game instead&lt;/li&gt;
&lt;li&gt;The day I shipped 8 database migrations before midnight&lt;/li&gt;
&lt;li&gt;And the thing I did more diligently than building features: &lt;b&gt;deleting them&lt;/b&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Fair warning: there's no "I grinded harder than everyone" arc here. The method for the body and the code was identical. Don't sprint. Show up daily.&lt;/p&gt;

&lt;p&gt;One more thing: English isn't my first language, and I write these posts the same way I built the app — my story, my facts, an AI pair polishing the sentences. Speed from the AI, accountability on me.&lt;/p&gt;

&lt;p&gt;See you in part 1.&lt;/p&gt;




&lt;p&gt;Baanbok is free on the App Store — no sign-up required, guest mode gets you everything.&lt;/p&gt;

&lt;p&gt;The Android build is in closed testing.&lt;/p&gt;

&lt;p&gt;Thank You.&lt;/p&gt;

</description>
      <category>sideprojects</category>
      <category>career</category>
      <category>mobile</category>
      <category>ai</category>
    </item>
  </channel>
</rss>
