<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title><![CDATA[Logan's blog]]></title>
    <link>https://tech.bodoc.co.kr/logan</link>
    <atom:link href="https://tech.bodoc.co.kr/logan/rss.xml" rel="self" type="application/rss+xml" />
    <description><![CDATA[개발자 Logan의 기술 블로그.]]></description>
    <language>en-us</language>
    <lastBuildDate>Wed, 20 May 2026 00:00:00 GMT</lastBuildDate>
    <item>
      <title><![CDATA[AWS SDK가 SSO 토큰 캐시를 끌고 들어왔다 — publish 직전에 발이 두 번 걸린 이야기]]></title>
      <link>https://tech.bodoc.co.kr/logan/posts/visual-builder-oss-traps-and-handbook</link>
      <guid isPermaLink="true">https://tech.bodoc.co.kr/logan/posts/visual-builder-oss-traps-and-handbook</guid>
      <pubDate>Wed, 20 May 2026 00:00:00 GMT</pubDate>
      <dc:creator><![CDATA[Logan]]></dc:creator>
      <description><![CDATA[umbrella 패키지가 webpack에서 node:fs를 끌고 들어와 런타임을 깨뜨린 사고, 그리고 라이브러리를 외부에서 어떻게 쓰는지에 대한 솔직한 안내.]]></description>
      <category>essay</category>
      <category><![CDATA[oss]]></category>
      <category><![CDATA[visual-builder]]></category>
      <category><![CDATA[aws-sdk]]></category>
      <category><![CDATA[webpack]]></category>
      <category><![CDATA[npm-publish]]></category>
      <category><![CDATA[react-native-web]]></category>
    </item>
    <item>
      <title><![CDATA[OSS 본체부터 만들 뻔했다가, 기존 프로젝트 안에서 먼저 갈아엎고 옮긴 건에 대하여..]]></title>
      <link>https://tech.bodoc.co.kr/logan/posts/visual-builder-oss-nine-phase-extraction</link>
      <guid isPermaLink="true">https://tech.bodoc.co.kr/logan/posts/visual-builder-oss-nine-phase-extraction</guid>
      <pubDate>Wed, 20 May 2026 00:00:00 GMT</pubDate>
      <dc:creator><![CDATA[Logan]]></dc:creator>
      <description><![CDATA[라이브러리 본체를 새 repo에서 짜기 전에, 기존 프로젝트 안에서 먼저 어댑터 모양으로 코드를 다 갈아엎고 시작한 이유. 그 순서가 만들어준 Chromatic 회귀 0건이라는 안전망에 대한 이야기.]]></description>
      <category>essay</category>
      <category><![CDATA[oss]]></category>
      <category><![CDATA[visual-builder]]></category>
      <category><![CDATA[refactoring]]></category>
      <category><![CDATA[chromatic]]></category>
      <category><![CDATA[visual-regression]]></category>
      <category><![CDATA[migration]]></category>
    </item>
    <item>
      <title><![CDATA[스토리북에 박혀있던 Visual Builder를 npm으로 분리하기로 한 날]]></title>
      <link>https://tech.bodoc.co.kr/logan/posts/visual-builder-oss-why-and-adapter-design</link>
      <guid isPermaLink="true">https://tech.bodoc.co.kr/logan/posts/visual-builder-oss-why-and-adapter-design</guid>
      <pubDate>Wed, 20 May 2026 00:00:00 GMT</pubDate>
      <dc:creator><![CDATA[Logan]]></dc:creator>
      <description><![CDATA[기존 프로젝트 안에 8,400 라인이 쌓여 있던 Visual Builder를 외부 라이브러리로 분리하기로 한 이유. 그리고 분리 설계의 한가운데에 있었던 어댑터 인터페이스 세 개 이야기.]]></description>
      <category>essay</category>
      <category><![CDATA[oss]]></category>
      <category><![CDATA[visual-builder]]></category>
      <category><![CDATA[library-extraction]]></category>
      <category><![CDATA[adapter-pattern]]></category>
      <category><![CDATA[react]]></category>
      <category><![CDATA[design-system]]></category>
    </item>
    <item>
      <title><![CDATA[Remote Config 갱신은 두 번 호출한다 — validateOnly + If-Match]]></title>
      <link>https://tech.bodoc.co.kr/logan/posts/note-rc-etag-and-validate-only</link>
      <guid isPermaLink="true">https://tech.bodoc.co.kr/logan/posts/note-rc-etag-and-validate-only</guid>
      <pubDate>Mon, 18 May 2026 00:00:00 GMT</pubDate>
      <dc:creator><![CDATA[Logan]]></dc:creator>
      <description><![CDATA[한 줄 publish가 만들 수 있는 두 가지 사고 — 잘못된 구조로 깨지는 것, 모르고 덮어쓰는 것. 두 줄짜리 안전망.]]></description>
      <category>note</category>
      <category><![CDATA[remote-config]]></category>
      <category><![CDATA[firebase]]></category>
      <category><![CDATA[ota]]></category>
      <category><![CDATA[concurrency]]></category>
    </item>
    <item>
      <title><![CDATA[OTA 메시지는 문법으로 강제한다]]></title>
      <link>https://tech.bodoc.co.kr/logan/posts/note-ota-message-grammar</link>
      <guid isPermaLink="true">https://tech.bodoc.co.kr/logan/posts/note-ota-message-grammar</guid>
      <pubDate>Mon, 18 May 2026 00:00:00 GMT</pubDate>
      <dc:creator><![CDATA[Logan]]></dc:creator>
      <description><![CDATA[사람이 적는 한 줄이 시스템의 끝까지 흘러가게 만들려면, 입구에서 한 번 단호하게 막아야 함.]]></description>
      <category>note</category>
      <category><![CDATA[ota]]></category>
      <category><![CDATA[eas-update]]></category>
      <category><![CDATA[design]]></category>
    </item>
    <item>
      <title><![CDATA[옛 코드를 지우지 않은 이유 — 옅은 이유의 결정적 가치]]></title>
      <link>https://tech.bodoc.co.kr/logan/posts/note-codepush-as-graveyard</link>
      <guid isPermaLink="true">https://tech.bodoc.co.kr/logan/posts/note-codepush-as-graveyard</guid>
      <pubDate>Mon, 18 May 2026 00:00:00 GMT</pubDate>
      <dc:creator><![CDATA[Logan]]></dc:creator>
      <description><![CDATA[`codepush.release.js`는 처음엔 그냥 남아 있던 파일이었음. 도입을 마치고 보니 의외로 세 가지 일을 하고 있었음.]]></description>
      <category>note</category>
      <category><![CDATA[operations]]></category>
      <category><![CDATA[code-archaeology]]></category>
      <category><![CDATA[ota]]></category>
    </item>
    <item>
      <title><![CDATA[파이프라인은 끝의 일 — GitLab CI · preflight · 비밀 마스킹 · Dooray로 묶다]]></title>
      <link>https://tech.bodoc.co.kr/logan/posts/eas-update-gitlab-ci-pipeline</link>
      <guid isPermaLink="true">https://tech.bodoc.co.kr/logan/posts/eas-update-gitlab-ci-pipeline</guid>
      <pubDate>Mon, 18 May 2026 00:00:00 GMT</pubDate>
      <dc:creator><![CDATA[Logan]]></dc:creator>
      <description><![CDATA[코드는 이미 만들어져 있을 때 우리가 누르는 단 하나의 버튼. when:manual 트리거, ota_preflight 환경 검증, redactArg 비밀 마스킹, Dooray 한 줄 알림까지 — 4편짜리 시리즈를 묶어주는 마지막 한 겹.]]></description>
      <category>essay</category>
      <category><![CDATA[expo]]></category>
      <category><![CDATA[eas-update]]></category>
      <category><![CDATA[gitlab-ci]]></category>
      <category><![CDATA[ota]]></category>
      <category><![CDATA[release-strategy]]></category>
    </item>
    <item>
      <title><![CDATA[rebuild 없는 정직한 승격 — staging의 바로 그 번들을 production으로]]></title>
      <link>https://tech.bodoc.co.kr/logan/posts/eas-update-republish-staging-to-production</link>
      <guid isPermaLink="true">https://tech.bodoc.co.kr/logan/posts/eas-update-republish-staging-to-production</guid>
      <pubDate>Mon, 18 May 2026 00:00:00 GMT</pubDate>
      <dc:creator><![CDATA[Logan]]></dc:creator>
      <description><![CDATA[production 배포가 staging을 다시 한 번 빌드하는 일이 되면 우리는 다른 binary를 운영합니다. EAS Update의 `update:republish`로 같은 groupId를 production 채널에 묶어, QA가 본 그 번들 그대로 사용자에게 보내는 흐름.]]></description>
      <category>essay</category>
      <category><![CDATA[expo]]></category>
      <category><![CDATA[eas-update]]></category>
      <category><![CDATA[ota]]></category>
      <category><![CDATA[release-strategy]]></category>
      <category><![CDATA[gitlab-ci]]></category>
    </item>
    <item>
      <title><![CDATA[한 단어로 클라이언트 분기를 가르는 4모드 — 메시지가 데이터가 되는 디자인]]></title>
      <link>https://tech.bodoc.co.kr/logan/posts/ota-four-update-modes</link>
      <guid isPermaLink="true">https://tech.bodoc.co.kr/logan/posts/ota-four-update-modes</guid>
      <pubDate>Mon, 18 May 2026 00:00:00 GMT</pubDate>
      <dc:creator><![CDATA[Logan]]></dc:creator>
      <description><![CDATA[EAS Update에는 `--mandatory` 한 줄이 없어요. 대신 우리는 OTA 메시지 한 줄에 4가지 모드를 박아 넣어, 사람이 적는 한 줄이 시스템의 끝까지 흘러가게 만들었습니다.]]></description>
      <category>essay</category>
      <category><![CDATA[expo]]></category>
      <category><![CDATA[eas-update]]></category>
      <category><![CDATA[ota]]></category>
      <category><![CDATA[remote-config]]></category>
      <category><![CDATA[release-strategy]]></category>
    </item>
    <item>
      <title><![CDATA[OTA 공백기를 끝낸 이주 — CodePush 흔적 위에 다시 그린 EAS Update]]></title>
      <link>https://tech.bodoc.co.kr/logan/posts/codepush-to-eas-update-migration</link>
      <guid isPermaLink="true">https://tech.bodoc.co.kr/logan/posts/codepush-to-eas-update-migration</guid>
      <pubDate>Mon, 18 May 2026 00:00:00 GMT</pubDate>
      <dc:creator><![CDATA[Logan]]></dc:creator>
      <description><![CDATA[한번 가졌다가 잃고, 한참을 OTA 없이 살았던 시간. 다시 OTA가 필요해진 계기와, 옛 CodePush 스크립트를 옆에 두고 EAS Update 위에 새로 배선한 도입기.]]></description>
      <category>essay</category>
      <category><![CDATA[expo]]></category>
      <category><![CDATA[eas-update]]></category>
      <category><![CDATA[codepush]]></category>
      <category><![CDATA[ota]]></category>
      <category><![CDATA[migration]]></category>
    </item>
    <item>
      <title><![CDATA[QA가 staging 빌드에서 OTA를 골라 받는 트릭 — Updates URL을 런타임에 갈아 끼우기]]></title>
      <link>https://tech.bodoc.co.kr/logan/posts/eas-preview-updates-on-staging</link>
      <guid isPermaLink="true">https://tech.bodoc.co.kr/logan/posts/eas-preview-updates-on-staging</guid>
      <pubDate>Mon, 18 May 2026 00:00:00 GMT</pubDate>
      <dc:creator><![CDATA[Logan]]></dc:creator>
      <description><![CDATA[QA가 검증하려면 보통 빌드 하나에 OTA 하나가 묶여 있어요. 그 묶임을 풀어, 한 staging 빌드 안에서 QA 브랜치의 어떤 OTA든 골라 받을 수 있게 만든 작은 화면 한 칸의 이야기.]]></description>
      <category>essay</category>
      <category><![CDATA[expo]]></category>
      <category><![CDATA[eas-update]]></category>
      <category><![CDATA[qa]]></category>
      <category><![CDATA[react-native]]></category>
      <category><![CDATA[trick]]></category>
    </item>
    <item>
      <title><![CDATA[Storybook 위에 Visual Builder를 박았습니다 — 디자이너가 직접 합성하는 도구를 만든 이야기]]></title>
      <link>https://tech.bodoc.co.kr/logan/posts/visual-builder-on-top-of-storybook</link>
      <guid isPermaLink="true">https://tech.bodoc.co.kr/logan/posts/visual-builder-on-top-of-storybook</guid>
      <pubDate>Fri, 15 May 2026 00:00:00 GMT</pubDate>
      <dc:creator><![CDATA[Logan]]></dc:creator>
      <description><![CDATA[Plasmic 같은 SaaS 대신 사내에서 직접 만든 page builder. Storybook 안에 박고, 결과는 JSON으로만, S3 + 정적 런타임으로 서버 0개. 만든 과정과 앞으로의 활용 기대.]]></description>
      <category>essay</category>
      <category><![CDATA[storybook]]></category>
      <category><![CDATA[visual-builder]]></category>
      <category><![CDATA[tooling]]></category>
      <category><![CDATA[s3]]></category>
    </item>
    <item>
      <title><![CDATA[RN-Web Storybook 운영 함정 6가지 — SVG color, flex-wrap, device frame width]]></title>
      <link>https://tech.bodoc.co.kr/logan/posts/react-native-storybook-pitfalls</link>
      <guid isPermaLink="true">https://tech.bodoc.co.kr/logan/posts/react-native-storybook-pitfalls</guid>
      <pubDate>Fri, 15 May 2026 00:00:00 GMT</pubDate>
      <dc:creator><![CDATA[Logan]]></dc:creator>
      <description><![CDATA[검증 단계에서 마주친 6가지 함정과 우회법. production 베끼기의 위험, SVG color prop 무시, flex-wrap trailing gap, device frame width mismatch 등.]]></description>
      <category>essay</category>
      <category><![CDATA[storybook]]></category>
      <category><![CDATA[react-native]]></category>
      <category><![CDATA[pitfalls]]></category>
    </item>
    <item>
      <title><![CDATA[Figma to Storybook 자동 변환 파이프라인 — SECTION 분할과 시각 회귀 루프]]></title>
      <link>https://tech.bodoc.co.kr/logan/posts/figma-to-storybook-pipeline</link>
      <guid isPermaLink="true">https://tech.bodoc.co.kr/logan/posts/figma-to-storybook-pipeline</guid>
      <pubDate>Fri, 15 May 2026 00:00:00 GMT</pubDate>
      <dc:creator><![CDATA[Logan]]></dc:creator>
      <description><![CDATA[Figma URL에서 .stories.tsx까지 — REST API, 휴리스틱 매핑, SECTION을 케이스 스토리로 쪼개기, 시각 회귀 보정 루프 전체.]]></description>
      <category>essay</category>
      <category><![CDATA[storybook]]></category>
      <category><![CDATA[figma]]></category>
      <category><![CDATA[automation]]></category>
    </item>
    <item>
      <title><![CDATA[Storybook 페이지 스토리를 일괄 삭제한 이유 — mock의 함정]]></title>
      <link>https://tech.bodoc.co.kr/logan/posts/storybook-page-stories-deprecation</link>
      <guid isPermaLink="true">https://tech.bodoc.co.kr/logan/posts/storybook-page-stories-deprecation</guid>
      <pubDate>Fri, 15 May 2026 00:00:00 GMT</pubDate>
      <dc:creator><![CDATA[Logan]]></dc:creator>
      <description><![CDATA[99% 완성된 페이지 스토리 106개를 한 번에 지운 결정. mock이 production과 어긋나는 순간 검수 가치가 0이 된다는 한 줄에서 시작된 회고.]]></description>
      <category>essay</category>
      <category><![CDATA[storybook]]></category>
      <category><![CDATA[decisions]]></category>
      <category><![CDATA[retrospective]]></category>
    </item>
    <item>
      <title><![CDATA[Storybook 스토리 작성 표준 — argTypes, play 함수, fn vs action]]></title>
      <link>https://tech.bodoc.co.kr/logan/posts/storybook-story-conventions</link>
      <guid isPermaLink="true">https://tech.bodoc.co.kr/logan/posts/storybook-story-conventions</guid>
      <pubDate>Fri, 15 May 2026 00:00:00 GMT</pubDate>
      <dc:creator><![CDATA[Logan]]></dc:creator>
      <description><![CDATA[검증 단계에서 200개에 가까운 스토리를 짜며 손에 굳은 한 줄 규칙들. 표준 골격, fn() vs action() 선택 기준, Portal modal 대응, styled-components 금지까지.]]></description>
      <category>essay</category>
      <category><![CDATA[storybook]]></category>
      <category><![CDATA[testing]]></category>
      <category><![CDATA[conventions]]></category>
    </item>
    <item>
      <title><![CDATA[React Native Web Storybook으로 잡는 회귀와 못 잡는 회귀]]></title>
      <link>https://tech.bodoc.co.kr/logan/posts/react-native-storybook-coverage-and-limits</link>
      <guid isPermaLink="true">https://tech.bodoc.co.kr/logan/posts/react-native-storybook-coverage-and-limits</guid>
      <pubDate>Fri, 15 May 2026 00:00:00 GMT</pubDate>
      <dc:creator><![CDATA[Logan]]></dc:creator>
      <description><![CDATA[RN 프로젝트에 Storybook을 도입할지 결정할 때 가장 중요한 표 한 장. 잡히는 회귀 7종과 못 잡는 회귀 9종을 솔직하게 정리합니다.]]></description>
      <category>essay</category>
      <category><![CDATA[storybook]]></category>
      <category><![CDATA[react-native]]></category>
      <category><![CDATA[testing]]></category>
    </item>
    <item>
      <title><![CDATA[Storybook 도입 1년 회고 — 안전망의 모양]]></title>
      <link>https://tech.bodoc.co.kr/logan/posts/storybook-one-year-retrospective</link>
      <guid isPermaLink="true">https://tech.bodoc.co.kr/logan/posts/storybook-one-year-retrospective</guid>
      <pubDate>Fri, 15 May 2026 00:00:00 GMT</pubDate>
      <dc:creator><![CDATA[Logan]]></dc:creator>
      <description><![CDATA[RN 프로젝트에 Storybook을 도입하고 1년. 채워진 칸, 비어있는 칸, 그리고 다시 시작한다면 다르게 할 결정들.]]></description>
      <category>essay</category>
      <category><![CDATA[storybook]]></category>
      <category><![CDATA[retrospective]]></category>
      <category><![CDATA[react-native]]></category>
    </item>
    <item>
      <title><![CDATA[Storybook을 디바이스 안으로 — DebugView에 심은 on-device 카탈로그]]></title>
      <link>https://tech.bodoc.co.kr/logan/posts/storybook-on-device-in-debugview</link>
      <guid isPermaLink="true">https://tech.bodoc.co.kr/logan/posts/storybook-on-device-in-debugview</guid>
      <pubDate>Fri, 15 May 2026 00:00:00 GMT</pubDate>
      <dc:creator><![CDATA[Logan]]></dc:creator>
      <description><![CDATA[RN-Web Storybook만으로는 닿지 못한 칸이 있었어요. @storybook/react-native를 DebugView 안에 토글로 끼우고, gesture · IME · Reanimated worklet 같은 회귀를 디바이스 QA 전에 한 번 더 거르는 그물을 추가한 이야기.]]></description>
      <category>essay</category>
      <category><![CDATA[storybook]]></category>
      <category><![CDATA[react-native]]></category>
      <category><![CDATA[on-device]]></category>
      <category><![CDATA[debugview]]></category>
    </item>
    <item>
      <title><![CDATA[Storybook 도입 과정에서 손에 남은 것들 — 그리고 앞으로의 기대]]></title>
      <link>https://tech.bodoc.co.kr/logan/posts/storybook-introduction-takeaways</link>
      <guid isPermaLink="true">https://tech.bodoc.co.kr/logan/posts/storybook-introduction-takeaways</guid>
      <pubDate>Fri, 15 May 2026 00:00:00 GMT</pubDate>
      <dc:creator><![CDATA[Logan]]></dc:creator>
      <description><![CDATA[검증을 마치고 도입을 시작하는 시점에서 정리하는 결정들. 안전망의 모양, 못 채운 칸, 앞으로 활용하면서 측정하고 싶은 것들.]]></description>
      <category>essay</category>
      <category><![CDATA[storybook]]></category>
      <category><![CDATA[introduction]]></category>
      <category><![CDATA[react-native]]></category>
    </item>
  </channel>
</rss>