<?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: Victor Minbeom Joo</title>
    <description>The latest articles on DEV Community by Victor Minbeom Joo (@front-line).</description>
    <link>https://dev.to/front-line</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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3971317%2Fc7a35308-1c43-4452-b5d4-f8802b27e54d.jpg</url>
      <title>DEV Community: Victor Minbeom Joo</title>
      <link>https://dev.to/front-line</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/front-line"/>
    <language>en</language>
    <item>
      <title>Ransomware wiped a client's entire server. I rebuilt it solo in 2 months.</title>
      <dc:creator>Victor Minbeom Joo</dc:creator>
      <pubDate>Sat, 06 Jun 2026 14:02:10 +0000</pubDate>
      <link>https://dev.to/front-line/ransomware-wiped-a-clients-entire-server-i-rebuilt-it-solo-in-2-months-51n</link>
      <guid>https://dev.to/front-line/ransomware-wiped-a-clients-entire-server-i-rebuilt-it-solo-in-2-months-51n</guid>
      <description>&lt;p&gt;It started with a phone call.&lt;/p&gt;

&lt;p&gt;One afternoon I picked up a referral call. The founder of a small company — call them Company B — was on the line, and his voice was tight. Their whole service had been wiped overnight. Ransomware.&lt;/p&gt;

&lt;p&gt;Company B ran a gym membership and community platform: gyms checked members in, members logged workouts and joined contests inside the app. It was a hybrid app — native shell with a WebView — and the backend ran on PHP/Laravel. They were on &lt;strong&gt;shared web hosting&lt;/strong&gt;, and an attacker rode a vulnerability in that hosting straight into their directory and encrypted everything. Source code, uploads, config. All of it locked.&lt;/p&gt;

&lt;p&gt;And the service was &lt;em&gt;live&lt;/em&gt;. Gyms depended on it daily. Every hour it stayed down, real businesses couldn't operate.&lt;/p&gt;

&lt;p&gt;I took the job — on the condition that I'd work it solo.&lt;/p&gt;

&lt;h2&gt;
  
  
  The backups existed, and that made it worse
&lt;/h2&gt;

&lt;p&gt;The first thing I checked wasn't the code. It was the backup situation.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Source code:&lt;/strong&gt; no backup. A developer &lt;em&gt;might&lt;/em&gt; have an old local copy, but it would be far behind production.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Database:&lt;/strong&gt; there was a backup — but it was taken &lt;em&gt;long before&lt;/em&gt; the infection. Restoring it meant the last several months of members, attendance records, and points were simply gone.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here's the trap: having an old backup is harder to reason about than having none. With nothing, your only option is "rewrite." With a stale backup, you have an asset that &lt;em&gt;looks&lt;/em&gt; usable but isn't — close enough to tempt you, wrong enough to burn you.&lt;/p&gt;

&lt;h2&gt;
  
  
  We didn't pay — and I proposed one more thing
&lt;/h2&gt;

&lt;p&gt;Two decisions had to be made.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Pay the ransom?&lt;/strong&gt; No. There's no guarantee the decryption key even works, and paying once puts you on the list for the next attack. The rebuild was achievable at this scale, so paying made no sense.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Scope of the rewrite.&lt;/strong&gt; Here I made a proposal: convert the video player from WebView to a &lt;strong&gt;native module&lt;/strong&gt;. The app streamed workout videos through a WebView player that handled background playback, screen-lock, and quality poorly — and video &lt;em&gt;was&lt;/em&gt; the core content. It was something they'd need to fix eventually anyway. Since we were rewriting the source from scratch, I argued, this was the cheapest moment to also fix it. It was out of "recovery" scope and meant extra cost, but the founder agreed: the moment you're rebuilding from rubble is, paradoxically, the best moment to change structure.&lt;/p&gt;

&lt;p&gt;The project's shape was set: &lt;strong&gt;rewrite + upgrade, 2 months.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  I started with consulting, not code
&lt;/h2&gt;

&lt;p&gt;For the first two weeks I barely wrote any code.&lt;/p&gt;

&lt;p&gt;Instead I spent the time understanding how the business actually ran: what role the app played on the gym floor, when members logged in most, what each feature did and why. I talked with the founder repeatedly and documented every feature's current behavior and what he wanted to improve while we were at it.&lt;/p&gt;

&lt;p&gt;If the old code had survived, this phase would have been much shorter. But with the source gone, the founder's memory and the operators' experience were the &lt;em&gt;only&lt;/em&gt; design sources. Every screen flow, every notification trigger, had to be reconstructed and redefined.&lt;/p&gt;

&lt;p&gt;I also took the chance to &lt;strong&gt;re-architect&lt;/strong&gt;. Rather than faithfully recreating the old structure, I cleaned it up for the current requirements. That paid off later in maintenance and iteration speed. Those two "slow" weeks ended up saving time — I got almost no "wait, why is it like this?" rework, because everything was built for present requirements from the start.&lt;/p&gt;

&lt;h2&gt;
  
  
  Two months, five features
&lt;/h2&gt;

&lt;p&gt;The work list:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Rewrite:&lt;/strong&gt; push notifications, attendance, contests, points system.&lt;br&gt;
&lt;strong&gt;Upgrade (my add-on proposal):&lt;/strong&gt; video player → native module.&lt;/p&gt;

&lt;p&gt;Priorities were clear:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Push + attendance.&lt;/strong&gt; These are what get members opening the app daily. If they're broken, reopening doesn't rebuild the habit.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Contests + points.&lt;/strong&gt; Re-engagement levers for the gyms — natural to add once tier 1 was stable.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Native video.&lt;/strong&gt; Playback already worked via WebView, so this was last.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Because the service was already live, "wait until everything is done" was not an option. I shipped &lt;strong&gt;sequentially&lt;/strong&gt; — finish a feature, test, deploy, move on — so gyms could get back to at least minimal functionality fast.&lt;/p&gt;

&lt;h2&gt;
  
  
  The data couldn't be undone
&lt;/h2&gt;

&lt;p&gt;The hardest part wasn't technical. It was the &lt;strong&gt;missing data&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Recent signups, recent attendance, contest history, accumulated points — all blank. Not a clean slate, just an unreliable one.&lt;/p&gt;

&lt;p&gt;This wasn't mine to communicate. Company B served many gyms, and the gyms had the direct relationship with members. The founder handled loss disclosure and compensation with each gym directly. My job was to draw a precise technical line: "restorable up to backup point A; everything after is unrecoverable." If that line is fuzzy, the client sets wrong expectations with their customers, and that becomes a bigger conflict later.&lt;/p&gt;

&lt;p&gt;Stating technical facts clearly, and making business decisions on top of them, are two different jobs. The first was mine. The second was the client's.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why solo actually helped
&lt;/h2&gt;

&lt;p&gt;Looking back, working alone was an advantage in this specific case:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Decision speed.&lt;/strong&gt; When every hour mattered, there was no "team alignment" step. One layer between the founder and me. Ask, decide, ship.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Design coherence.&lt;/strong&gt; I designed all five features, so the seams were smooth — how points tie into attendance, how contest entry triggers a push. Split across people, those joints are where friction lives.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Clear ownership.&lt;/strong&gt; If it broke, it was on me; if it worked, that was on me too. That was steadying, not stressful.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The limit is just as real: five features in two months solo only works &lt;em&gt;at that scale&lt;/em&gt;. Knowing that boundary before taking the job mattered.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rehosting and a real backup system
&lt;/h2&gt;

&lt;p&gt;When the service was fully back, one task remained. Staying on the same shared host was not an option. I migrated hosting and rebuilt the whole backup discipline — &lt;strong&gt;scheduled backups, off-site copies, and recovery drills.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Most small companies only build this &lt;em&gt;after&lt;/em&gt; their first disaster. Company B was no different — the cost of backups only felt real once recovery was behind them. I finished that migration too. It wasn't in the recovery quote, but we agreed: stop here and it happens again.&lt;/p&gt;

&lt;h2&gt;
  
  
  What stuck with me afterward
&lt;/h2&gt;

&lt;p&gt;The lasting takeaway was about what recovery &lt;em&gt;is&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Recovery isn't restoring the original state. Often there is no original state to restore to — the code is gone, the data is a stale backup, the history in between is permanently blank. The actual work is &lt;strong&gt;deciding what to rebuild, what to abandon, and what to make better while you're in there.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;So a recovery project always starts by figuring out &lt;em&gt;what is truly necessary&lt;/em&gt; — together with the client. Skip that and go straight to code, and a month later you get "why do we even need this?" By then it's too late.&lt;/p&gt;

&lt;p&gt;When I took that first call, my opening line wasn't "how fast can I fix it." It was: &lt;em&gt;"Let's first sort out what to bring back, and what to make better while we're at it."&lt;/em&gt; That frame steadied the entire project.&lt;/p&gt;




&lt;p&gt;Have you ever had to rebuild something with no usable backup? I'm curious how others drew the "restorable vs. gone" line with clients.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>security</category>
      <category>webdev</category>
      <category>career</category>
    </item>
    <item>
      <title>Hello, dev.to — I'm Victor: 10+ years full-stack, two CTO runs, now solo and writing in the open</title>
      <dc:creator>Victor Minbeom Joo</dc:creator>
      <pubDate>Sat, 06 Jun 2026 13:57:51 +0000</pubDate>
      <link>https://dev.to/front-line/hello-devto-im-victor-10-years-full-stack-two-cto-runs-now-solo-and-writing-in-the-open-1bo2</link>
      <guid>https://dev.to/front-line/hello-devto-im-victor-10-years-full-stack-two-cto-runs-now-solo-and-writing-in-the-open-1bo2</guid>
      <description>&lt;p&gt;Hi. I'm &lt;strong&gt;Victor&lt;/strong&gt;, a full-stack engineer based in South Korea, and this is my first post here.&lt;/p&gt;

&lt;p&gt;I've been writing for a while — just in Korean, on my own blog. I'm starting fresh in English on dev.to because most of what I'm working on now (self-hosted LLMs, full-stack infra, building products as a one-person studio) lives in conversations that happen in English, and I'd rather be &lt;em&gt;in&lt;/em&gt; those conversations than next to them.&lt;/p&gt;

&lt;p&gt;So, a short introduction.&lt;/p&gt;

&lt;h2&gt;
  
  
  The path so far
&lt;/h2&gt;

&lt;p&gt;I've spent &lt;strong&gt;10+ years&lt;/strong&gt; in this work. I started on the frontend, drifted into mobile, and eventually owned the whole stack — frontend, backend, infra, and the decisions that connect them.&lt;/p&gt;

&lt;p&gt;Along the way I did &lt;strong&gt;two CTO runs&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I led a small team to productize an &lt;strong&gt;education SaaS&lt;/strong&gt; — architecting OCR, search, real-time messaging, and lecture streaming, and signing real customers. The thing actually became a business, which taught me more about tradeoffs than any side project ever did.&lt;/li&gt;
&lt;li&gt;I later owned the full technical architecture of another &lt;strong&gt;education platform&lt;/strong&gt; — FE, BE, and DevOps, including the cloud setup and CI/CD pipeline.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;More recently I spent &lt;strong&gt;a year as a remote full-stack contractor for a US SaaS (Wyzly)&lt;/strong&gt;, shipping features and running production on Next.js and Supabase across a 14-hour time difference. Remote-across-timezones is its own skill, and that year sharpened it.&lt;/p&gt;

&lt;p&gt;I've also built &lt;strong&gt;enterprise AI work&lt;/strong&gt; — an LLM agent system for a large organization — and earlier in my career, a stretch of &lt;strong&gt;interactive and kiosk experiences for major Korean enterprises and global brands&lt;/strong&gt; at a creative-tech agency. Different worlds (white-glove enterprise vs. scrappy startup), and I'm glad I saw both.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I'm doing now
&lt;/h2&gt;

&lt;p&gt;These days I run a &lt;strong&gt;solo studio&lt;/strong&gt; and spend most of my energy on two things.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Building my own products.&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Geckoly&lt;/strong&gt; — an AI-assisted care platform for reptile keepers. (Yes, reptiles. It's a real, underserved niche with surprisingly hard problems — image-based species/price prediction, care guidance, the works.)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;BIoTan&lt;/strong&gt; — peer-relative anomaly detection for IoT sensor fleets: instead of setting a threshold per device, it compares each device against its peers and flags the real outliers. No per-device tuning, common drift cancels out.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Running AI infrastructure on my own hardware.&lt;/strong&gt;&lt;br&gt;
A lot of my recent work is figuring out how far you can get on a single &lt;strong&gt;RTX 3090&lt;/strong&gt; — local model serving, an agent runtime that uses tools and cron and touches real files, KV-cache and quantization tuning, RAG pipelines. It's equal parts engineering and cost discipline, and it's the most fun I've had in years.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I'm here
&lt;/h2&gt;

&lt;p&gt;I want to write in the open about the stuff I'm actually doing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Self-hosted LLM infra&lt;/strong&gt; — what works, what melts the GPU, what the docs don't tell you.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Full-stack notes&lt;/strong&gt; — React Server Components, payments, the boring-but-real parts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Building solo&lt;/strong&gt; — the engineering &lt;em&gt;and&lt;/em&gt; the business side, honestly. Including the war stories (I have a good one about ransomware).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I'm also &lt;strong&gt;open to remote contracts and consulting&lt;/strong&gt; with global teams — full-stack and AI-engineering work, or CTO-level architecture. But I'm not here to pitch; I'm here to be useful and to learn in public. If something I write helps you, that's the win.&lt;/p&gt;

&lt;p&gt;If any of this overlaps with what you're working on — local LLMs, indie products, remote contracting — I'd genuinely like to hear how you're approaching it. Leave a comment, and I'll see you in the next post.&lt;/p&gt;

&lt;p&gt;— Victor&lt;/p&gt;

</description>
      <category>introduction</category>
      <category>career</category>
      <category>webdev</category>
      <category>ai</category>
    </item>
  </channel>
</rss>
