<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>검은곰의 아카이브</title>
    <link>https://zerodice0.tistory.com/</link>
    <description>검은곰의 잡다한 기록 페이지.</description>
    <language>ko</language>
    <pubDate>Wed, 1 Jul 2026 02:05:05 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>은곰군</managingEditor>
    <image>
      <title>검은곰의 아카이브</title>
      <url>https://tistory1.daumcdn.net/tistory/1772864/attach/19cb55d677684998870ccb1200ee4ef0</url>
      <link>https://zerodice0.tistory.com</link>
    </image>
    <item>
      <title>Flutter iOS 실기기 디버깅 시 &amp;quot;Dart VM Service was not discovered after 60 seconds.&amp;quot; 오류 해결하기</title>
      <link>https://zerodice0.tistory.com/321</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;문제 상황&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;flutter run&lt;/code&gt; 명령으로 iOS 실기기에 앱을 배포하면, 빌드와 설치까지는 정상적으로 진행됩니다. 하지만 그 이후 아래와 같은 메시지가 출력되며 디버거 연결에 실패합니다.&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;Launching lib/main.dart on iPhone in debug mode...
Running Xcode build...
Xcode build done.                                           12.3s
Installing and launching...

Waiting for VM Service to become available...&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;약 60초간 대기한 뒤 아래 오류와 함께 종료됩니다.&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;Error: Failed to attach to the VM Service.
Dart VM Service was not discovered after 60 seconds.

Possible causes:
- The device is not connected to the same network as the host machine.
- The device is using a VPN.
- The application is not running in debug mode on the device.&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앱 자체는 실기기에 정상 설치되어 실행까지 되지만, Hot Reload, breakpoint, DevTools 등 디버깅 기능을 전혀 사용할 수 없는 상태입니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;원인 분석: Flutter는 어떻게 VM Service를 찾는가&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 문제를 이해하려면, Flutter가 iOS 실기기의 VM Service에 연결하는 메커니즘을 알아야 합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;VM Service 연결 흐름&lt;/h3&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;[Flutter CLI] --USB--&amp;gt; [iOS 디바이스: 앱 설치 &amp;amp; 실행]
                              |
                     앱이 VM Service 시작
                     (랜덤 포트에서 리스닝)
                              |
                     mDNS(Bonjour)로 서비스 브로드캐스트
                              |
[Flutter CLI] &amp;lt;--mDNS 발견-- [VM Service 포트 정보]
                              |
                     포트 포워딩으로 디버거 연결&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;핵심은 &lt;b&gt;mDNS(Bonjour)&lt;/b&gt; 입니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;Flutter CLI가 USB를 통해 앱을 실기기에 설치하고 실행합니다.&lt;/li&gt;
&lt;li&gt;앱은 디버그 모드로 시작되며, Dart VM Service가 임의의 포트에서 리스닝을 시작합니다.&lt;/li&gt;
&lt;li&gt;앱은 &lt;b&gt;mDNS(Bonjour)&lt;/b&gt; 프로토콜을 사용하여 로컬 네트워크에 VM Service의 존재와 포트 번호를 브로드캐스트합니다.&lt;/li&gt;
&lt;li&gt;Flutter CLI는 이 mDNS 브로드캐스트를 수신하여 VM Service의 주소와 포트를 발견합니다.&lt;/li&gt;
&lt;li&gt;발견된 정보를 기반으로 포트 포워딩을 설정하고 디버거를 연결합니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;왜 mDNS 발견이 실패하는가&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;mDNS는 로컬 네트워크 멀티캐스트에 의존하기 때문에, 다양한 환경적 요인으로 실패할 수 있습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;iOS 로컬 네트워크 권한&lt;/b&gt;: iOS 14 이상에서 도입된 로컬 네트워크 접근 권한이 거부된 경우, mDNS 브로드캐스트가 차단됩니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;네트워크 환경&lt;/b&gt;: 기업 네트워크, 게스트 Wi-Fi 등에서 멀티캐스트 패킷이 차단될 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;방화벽&lt;/b&gt;: Mac의 방화벽 설정이 mDNS 패킷 수신을 차단하는 경우가 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;VPN&lt;/b&gt;: VPN이 활성화되어 있으면 네트워크 라우팅이 변경되어 로컬 멀티캐스트가 정상 동작하지 않을 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;USB 연결 불안정&lt;/b&gt;: 케이블 또는 포트 문제로 통신이 불안정한 경우에도 발생할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;일반적인 해결 시도&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;온라인에서 자주 제안되는 해결 방법들을 정리합니다. 많은 경우 이 방법들로 해결이 되지만, 그렇지 않은 경우도 있습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. iOS 로컬 네트워크 권한 확인&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;iOS 설정 &amp;gt; 개인정보 보호 &amp;gt; 로컬 네트워크에서 해당 앱의 권한이 허용되어 있는지 확인합니다. 앱을 삭제 후 재설치하면 권한을 다시 요청받을 수 있습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. 같은 네트워크 연결 확인&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Mac과 iOS 디바이스가 동일한 Wi-Fi 네트워크에 연결되어 있는지 확인합니다. 또는 iPhone의 개인 핫스팟에 Mac을 연결하여 단순한 네트워크 환경을 만들어봅니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. Mac 방화벽 비활성화&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시스템 설정 &amp;gt; 네트워크 &amp;gt; 방화벽을 일시적으로 비활성화하여 방화벽이 원인인지 확인합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4. VPN 비활성화&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;VPN이 활성화되어 있다면 비활성화한 뒤 다시 시도합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;5. 캐시 정리 및 재설치&lt;/h3&gt;
&lt;pre class=&quot;properties&quot;&gt;&lt;code&gt;# Flutter 캐시 정리
flutter clean
flutter pub get

# iOS 빌드 캐시 정리
cd ios
rm -rf Pods Podfile.lock
pod install --repo-update
cd ..

# DerivedData 정리
rm -rf ~/Library/Developer/Xcode/DerivedData

# 실기기에서 앱 삭제 후 재실행
flutter run&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;6. 디바이스 신뢰 재설정&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;USB 케이블을 분리했다가 다시 연결하고, 디바이스에서 &quot;이 컴퓨터를 신뢰하겠습니까?&quot; 대화상자가 나타나면 신뢰를 선택합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;7. &lt;code&gt;--verbose&lt;/code&gt; 플래그로 상세 로그 확인&lt;/h3&gt;
&lt;pre class=&quot;applescript&quot;&gt;&lt;code&gt;flutter run --verbose&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;--verbose&lt;/code&gt; 옵션을 추가하면 mDNS 발견 과정의 상세 로그를 확인할 수 있어 어느 단계에서 실패하는지 파악하는 데 도움이 됩니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;최종 해결: Xcode 실행 + VSCode Attach&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 방법들을 모두 시도해도 문제가 해결되지 않는 경우, &lt;b&gt;mDNS 발견 과정 자체를 우회&lt;/b&gt;하는 방법이 있습니다. Xcode에서 앱을 직접 실행하고, VSCode에서 이미 실행 중인 앱에 디버거를 attach하는 방식입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Step 1: Xcode에서 앱 실행&lt;/h3&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;# Runner.xcworkspace를 Xcode에서 열기
open ios/Runner.xcworkspace&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Xcode에서:&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;상단의 디바이스 선택 메뉴에서 연결된 iOS 실기기를 선택합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Run (▶)&lt;/b&gt; 버튼을 눌러 앱을 실행합니다.&lt;/li&gt;
&lt;li&gt;Xcode 콘솔에서 아래와 같은 VM Service URL이 출력되는 것을 확인합니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class=&quot;cs&quot;&gt;&lt;code&gt;flutter: The Dart VM service is listening on http://127.0.0.1:00000/XXXXXXXXXX=/&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Xcode는 USB를 통한 직접 통신을 사용하므로 mDNS에 의존하지 않습니다. 따라서 mDNS 관련 문제를 완전히 우회할 수 있습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Step 2: VSCode에서 Attach&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Xcode에서 앱이 실행되고 있는 상태에서, VSCode의 디버깅 기능을 활용하려면 &lt;b&gt;attach&lt;/b&gt; 방식으로 연결합니다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;launch.json 설정&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;.vscode/launch.json&lt;/code&gt; 파일에 다음 설정을 추가합니다.&lt;/p&gt;
&lt;pre class=&quot;json&quot;&gt;&lt;code&gt;{
  &quot;version&quot;: &quot;0.2.0&quot;,
  &quot;configurations&quot;: [
    {
      &quot;name&quot;: &quot;Flutter: Attach&quot;,
      &quot;type&quot;: &quot;dart&quot;,
      &quot;request&quot;: &quot;attach&quot;
    }
  ]
}&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Attach 실행&lt;/h4&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;VSCode에서 &lt;b&gt;Run and Debug (Ctrl+Shift+D / Cmd+Shift+D)&lt;/b&gt; 패널을 엽니다.&lt;/li&gt;
&lt;li&gt;상단 드롭다운에서 &lt;b&gt;&quot;Flutter: Attach&quot;&lt;/b&gt; 를 선택합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Start Debugging (F5)&lt;/b&gt; 를 누릅니다.&lt;/li&gt;
&lt;li&gt;Flutter extension이 자동으로 실행 중인 VM Service를 탐지하여 연결합니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;연결이 성공하면 VSCode 하단 상태바가 주황색으로 변하며, 다음 기능들을 모두 사용할 수 있습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Breakpoint 디버깅&lt;/b&gt;: 코드에 breakpoint를 설정하고 실행 흐름을 추적&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Hot Reload&lt;/b&gt;: 코드 변경 시 &lt;code&gt;Ctrl+S&lt;/code&gt; / &lt;code&gt;Cmd+S&lt;/code&gt;로 즉시 반영&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Hot Restart&lt;/b&gt;: 앱 상태를 초기화하며 재시작&lt;/li&gt;
&lt;li&gt;&lt;b&gt;DevTools&lt;/b&gt;: Flutter Inspector, Performance 탭 등 DevTools 연동&lt;/li&gt;
&lt;li&gt;&lt;b&gt;변수 검사&lt;/b&gt;: Debug 패널에서 변수 값 확인 및 Watch 표현식 사용&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Tip&lt;/b&gt;: &lt;code&gt;flutter attach&lt;/code&gt; CLI 명령도 동일한 역할을 합니다. 터미널에서 &lt;code&gt;flutter attach&lt;/code&gt;를 실행하면 VM Service를 탐지하여 연결을 시도하며, Hot Reload(&lt;code&gt;r&lt;/code&gt;), Hot Restart(&lt;code&gt;R&lt;/code&gt;) 등을 사용할 수 있습니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;launch vs attach: 무엇이 다른가&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Flutter 디버깅에서 &lt;b&gt;launch&lt;/b&gt;와 &lt;b&gt;attach&lt;/b&gt;는 앱 실행 주체와 디버거 연결 방식이 다릅니다.&lt;/p&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;구분&lt;/th&gt;
&lt;th&gt;launch&lt;/th&gt;
&lt;th&gt;attach&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;앱 실행 주체&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;Flutter CLI / VSCode가 빌드부터 실행까지 전체 담당&lt;/td&gt;
&lt;td&gt;외부(Xcode, 이미 실행 중인 앱 등)에서 실행된 앱에 연결&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;VM Service 발견&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;mDNS(Bonjour) 기반 자동 발견&lt;/td&gt;
&lt;td&gt;이미 실행 중인 VM Service에 직접 연결&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;빌드 과정&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;flutter run&lt;/code&gt;이 빌드, 설치, 실행을 모두 수행&lt;/td&gt;
&lt;td&gt;빌드/설치는 별도로 처리 (Xcode 등)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;mDNS 의존성&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;있음 (발견 실패 시 타임아웃)&lt;/td&gt;
&lt;td&gt;없음 (직접 연결)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;사용 시나리오&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;일반적인 개발 워크플로우&lt;/td&gt;
&lt;td&gt;mDNS 문제 우회, Native 코드 동시 디버깅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;Hot Reload&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;지원&lt;/td&gt;
&lt;td&gt;지원&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;Breakpoint&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;지원&lt;/td&gt;
&lt;td&gt;지원&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;언제 어떤 방식을 사용해야 하는가&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;launch를 사용하는 경우:&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;mDNS가 정상 동작하는 네트워크 환경&lt;/li&gt;
&lt;li&gt;Flutter 코드만 수정하는 일반적인 개발&lt;/li&gt;
&lt;li&gt;빠른 개발-테스트 사이클이 필요한 경우&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;attach를 사용하는 경우:&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;mDNS 발견이 실패하는 환경&lt;/li&gt;
&lt;li&gt;Xcode에서 네이티브 코드와 Flutter 코드를 동시에 디버깅해야 하는 경우&lt;/li&gt;
&lt;li&gt;이미 실기기에서 실행 중인 앱에 디버거를 연결하고 싶은 경우&lt;/li&gt;
&lt;li&gt;CI/CD 환경에서 빌드와 디버깅을 분리해야 하는 경우&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;정리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Flutter iOS 실기기 디버깅에서 &quot;Dart VM Service was not discovered&quot; 오류는 mDNS 기반 서비스 발견이 실패할 때 발생합니다. 로컬 네트워크 권한, 네트워크 환경, 방화벽, VPN 등 다양한 원인이 있으며, 이를 해결하기 위한 일반적인 방법들을 먼저 시도해볼 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래도 해결이 되지 않는다면, Xcode에서 앱을 직접 실행하고 VSCode에서 attach하는 방식으로 mDNS 의존성을 완전히 우회할 수 있습니다. 이 방법은 단순히 우회책이 아니라, 네이티브 코드와 Flutter 코드를 동시에 디버깅할 수 있다는 점에서 실무에서도 유용한 워크플로우입니다.&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;mDNS 문제 발생 시 해결 체크리스트:

1. iOS 로컬 네트워크 권한 확인
2. 동일 네트워크 연결 확인
3. Mac 방화벽 / VPN 비활성화
4. flutter clean &amp;amp; 캐시 정리
5. 디바이스 신뢰 재설정
6. (그래도 안되는 경우) Xcode 실행 + VSCode Attach&lt;/code&gt;&lt;/pre&gt;</description>
      <category>Programming/Flutter</category>
      <category>flutter</category>
      <category>개발환경</category>
      <category>디버깅</category>
      <author>은곰군</author>
      <guid isPermaLink="true">https://zerodice0.tistory.com/321</guid>
      <comments>https://zerodice0.tistory.com/321#entry321comment</comments>
      <pubDate>Fri, 6 Mar 2026 15:47:56 +0900</pubDate>
    </item>
    <item>
      <title>Whisper Auto Caption by zerodice0 v1.1.0</title>
      <link>https://zerodice0.tistory.com/320</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/zerodice0/fcpx-auto-captions/releases/tag/v1.1.0&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://github.com/zerodice0/fcpx-auto-captions/releases/tag/v1.1.0&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1769990664316&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;Release v1.1.0 &amp;middot; zerodice0/fcpx-auto-captions&quot; data-og-description=&quot;v1.1.0 Release Notes 개선 SRT 변환기에서 언어 옵션 제거 불필요한 기능 단순화로 사용성 개선 폰트 및 스타일 설정은 Title Style에서 직접 설정 가능 버그 수정 다중 라인 자막 파싱 개선 2줄 이상의 자&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/zerodice0/fcpx-auto-captions/releases/tag/v1.1.0&quot; data-og-url=&quot;https://github.com/zerodice0/fcpx-auto-captions/releases/tag/v1.1.0&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/5iUWn/dJMb9iICbQF/LFl902TsTchrXd5IKTNjL0/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/mNdJg/dJMb8RRMYtW/0kkjJefZoqlSuzaZMnlKrk/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/zerodice0/fcpx-auto-captions/releases/tag/v1.1.0&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/zerodice0/fcpx-auto-captions/releases/tag/v1.1.0&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/5iUWn/dJMb9iICbQF/LFl902TsTchrXd5IKTNjL0/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/mNdJg/dJMb8RRMYtW/0kkjJefZoqlSuzaZMnlKrk/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Release v1.1.0 &amp;middot; zerodice0/fcpx-auto-captions&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;v1.1.0 Release Notes 개선 SRT 변환기에서 언어 옵션 제거 불필요한 기능 단순화로 사용성 개선 폰트 및 스타일 설정은 Title Style에서 직접 설정 가능 버그 수정 다중 라인 자막 파싱 개선 2줄 이상의 자&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음과 같은 사항이 변경됐습니다.&amp;nbsp;&lt;br /&gt;[SRT to FCPXML]&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 자막이 공백으로 시작될 경우 시작 부분의 공백을 제거하도록 수정&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 자막에 줄바꿈이 포함되어있을 경우 첫번째 줄만 Basic Title로 변경되는 문제 수정&lt;/p&gt;</description>
      <category>개발기록</category>
      <category>whisper</category>
      <category>whisperAutoCaption</category>
      <category>영상편집</category>
      <category>자막</category>
      <author>은곰군</author>
      <guid isPermaLink="true">https://zerodice0.tistory.com/320</guid>
      <comments>https://zerodice0.tistory.com/320#entry320comment</comments>
      <pubDate>Mon, 2 Feb 2026 09:06:29 +0900</pubDate>
    </item>
    <item>
      <title>Whisper Auto Caption by zerodice0 v1.0.1</title>
      <link>https://zerodice0.tistory.com/319</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;릴리즈 노트 및 다운로드 링크&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;굳이 본문 내용이 궁금하지 않으신 분들을 위한 다운로드 링크입니다. 기존 Whisper Auto Caption에서 개선된 기능은 다음과 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. Whisper.cpp v1.8.3을 참조하도록 업데이트&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. Whisper.cpp에서 지원하는 모든 인자값을 사용자가 커스터마이징 할 수 있도록 수정하고, 각 인자값에 대한 설명 추가&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. mp3 파일 이외의 wav, mp4 등의 영상 및 음원 파일을 사용할 수 있도록 수정&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. Large-V3, Large-V3 Turbo 등의 모델 추가&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5. SRT 자막을 FCPXML 파일로 변환하는 기능 추가&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;6. SRT 자막을 FCPXML 파일로 변환 시 좌표값(X, Y) 및 정렬(Left, Center, Right) 등의 값을 변경 가능하도록 수정&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;7. 허깅 페이스에서 받은 GGML 모델을 커스텀 모델로 추가할 수 있는 기능 추가&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/zerodice0/fcpx-auto-captions/releases/tag/v1.0.1&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://github.com/zerodice0/fcpx-auto-captions/releases/tag/v1.0.1&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1769330479663&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;Release v1.0.1 &amp;middot; zerodice0/fcpx-auto-captions&quot; data-og-description=&quot;What's New / 새로운 기능 ✨ New Features / 새 기능 SRT to FCPXML Converter - Convert SRT subtitle files to Final Cut Pro X projects SRT 자막 파일을 Final Cut Pro X 프로젝트로 변환 Custom GGML Whisper Models - Load ...&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/zerodice0/fcpx-auto-captions/releases/tag/v1.0.1&quot; data-og-url=&quot;https://github.com/zerodice0/fcpx-auto-captions/releases/tag/v1.0.1&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/Isdka/dJMb84p26kT/4yX24xHrJKufBFsbn7yht0/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/s8wwH/dJMb9cBCtLB/QHDqIMks2jmYTb0rfaCmu0/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/zerodice0/fcpx-auto-captions/releases/tag/v1.0.1&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/zerodice0/fcpx-auto-captions/releases/tag/v1.0.1&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/Isdka/dJMb84p26kT/4yX24xHrJKufBFsbn7yht0/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/s8wwH/dJMb9cBCtLB/QHDqIMks2jmYTb0rfaCmu0/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Release v1.0.1 &amp;middot; zerodice0/fcpx-auto-captions&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;What's New / 새로운 기능 ✨ New Features / 새 기능 SRT to FCPXML Converter - Convert SRT subtitle files to Final Cut Pro X projects SRT 자막 파일을 Final Cut Pro X 프로젝트로 변환 Custom GGML Whisper Models - Load ...&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;개요&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Whisper Auto Caption은 Whisper가 나온 2023년에 배포된 레포지터리로, 파이널컷을 사용하는 사람들이 Whisper를 사용해서 영상의 자막을 쉽게 만들 수 있는 프로젝트였습니다. 원본 브랜치는 다음과 같죠. 다만, 배포 이후 3년간 변경된 사항이 없었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a style=&quot;color: #0070d1;&quot; href=&quot;https://github.com/shaishaicookie/fcpx-auto-captions&quot;&gt;&lt;br /&gt;&lt;/a&gt;&lt;a href=&quot;https://github.com/shaishaicookie/fcpx-auto-captions&quot;&gt;https://github.com/shaishaicookie/fcpx-auto-captions&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1769331413261&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;GitHub - shaishaicookie/fcpx-auto-captions:   Auto Captions for Final Cut Pro Powered by OpenAI's Whisper Model&quot; data-og-description=&quot;  Auto Captions for Final Cut Pro Powered by OpenAI's Whisper Model - shaishaicookie/fcpx-auto-captions&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/shaishaicookie/fcpx-auto-captions&quot; data-og-url=&quot;https://github.com/shaishaicookie/fcpx-auto-captions&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/NKKJM/dJMb9cBCtMk/k0y6TdBfPVOOs4MnuIl7D1/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/NBBZf/dJMb9iaLvrv/BR6hxLHrfsmYdesWh3gVlK/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/shaishaicookie/fcpx-auto-captions&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/shaishaicookie/fcpx-auto-captions&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/NKKJM/dJMb9cBCtMk/k0y6TdBfPVOOs4MnuIl7D1/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/NBBZf/dJMb9iaLvrv/BR6hxLHrfsmYdesWh3gVlK/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;GitHub - shaishaicookie/fcpx-auto-captions:   Auto Captions for Final Cut Pro Powered by OpenAI's Whisper Model&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;  Auto Captions for Final Cut Pro Powered by OpenAI's Whisper Model - shaishaicookie/fcpx-auto-captions&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Whisper.cpp는 그 사이에도 꽤 많은 변경사항이 있었고, 레포지터리 자체도 20개 정도 포크됐음에도 불구하고 풀 리퀘스트가 된 이력은 없었습니다. 다른 분들이 원본 브랜치에서 파생한 뒤 어떤 식으로 관리하고 있고 기능 추가를 하고 있는지는 잘 모르겠습니다. 아마도 포크된 브랜치를 검색했을 때 두 개 정도만 검색되는 걸 봐선, 비공개 레포지터리로 운영하고 있는지도 모르겠구요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어찌됐건 개인적으로 가장 필요했던 기능은 SRT로 추출한 자막을 파이널 컷으로 싱크를 맞춘 뒤, Whisper가 잘못 추출한 자막을 수정한 내용들을 일일히 교정한 다음 FCPXML로 변환하는 기능이었습니다. 파이널 컷으로 교정한 SRT 자막을 FCPXML으로 변환할 때는 보통 &lt;a href=&quot;https://ko.editingtools.io/subtitles/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://ko.editingtools.io/subtitles/&lt;/a&gt; 을 이용하긴 했는데, 옵션을 선택해도 무조건 중앙 정렬로 다운로드 되고 좌표값이 0, 0 기준으로 적용되곤 했습니다. 물론 Basic Title로 변환한 이후 전체 선택한 다음 좌표값을 변경하는 방법도 있긴 하지만, Text Position값을 변경하는 것과 Transform Position을 변경하는 것과는 아무래도 차이가 있었으니까요. 좌표를 잘못 지정할 시 자막이 길어지면 잘리는 문제를 포함해서 말이죠.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아무튼 이런 기능들을 포함해서, Claude를 사용해 필요한 기능들을 주섬주섬 추가했습니다. 허깅 페이스에서 찾아보니 꽤 많은 whisper 모델들이 있었기에, 이런 모델들을 사용자가 추가할 수 있는 기능이라던가... Swift를 잘 모르는 상태에서 Claude만 사용해 개선을 진행하다보니, 조금 부족한 부분이 있을지도 모르겠습니다. 일단 배포 용량을 대폭 낮추고, 이래저래 편의성을 추가했으니 이용하시다가 불편하신 점은 블로그 댓글, 혹은 유튜브, 깃허브 이슈로 등재해주시면 시간이 날 때 수정하도록 하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모쪼록 도움이 됐으면 좋겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;감사합니다. 검은곰이었습니다. :)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>개발기록</category>
      <category>FCPX</category>
      <category>whisper</category>
      <category>whisperAutoCaption</category>
      <category>위스퍼</category>
      <category>위스퍼오토캡션</category>
      <category>파이널컷</category>
      <author>은곰군</author>
      <guid isPermaLink="true">https://zerodice0.tistory.com/319</guid>
      <comments>https://zerodice0.tistory.com/319#entry319comment</comments>
      <pubDate>Sun, 25 Jan 2026 18:00:04 +0900</pubDate>
    </item>
    <item>
      <title>불안 장애와 인공 지능과 2026년의 경계선에서</title>
      <link>https://zerodice0.tistory.com/318</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;2026년이 밝았다.&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; 한동안 회고를 기재하지 않았는데, 별달리 쓸 말도 없고 매년마다 다른 사람들보다 몇 걸음은 커녕 한참이나 뒤쳐졌다는 생각에서 헤어나오지 못했기 때문이었을 듯 하다. 마치 마라톤 경주에 참가했지만 나를 제외한 모든 이들은 아득히 먼 곳으로 앞서나가고, 나 혼자 숨을 헐떡이며 포기하지도 못한 채 가슴을 부여잡고 뛰는 듯 했다. 그러한 탓인지 지난 한해동안 무엇을 했는지, 이번 해에는 무엇을 할 것인지, 목적을 잃는 경우가 많았다. 대부분의 경우 남들이 하나 둘 씩 회고록을 올리는 것을 보며, 나도 회고라는 걸 써야지...같은 생각을 한 뒤 하얀 바탕만 한참동안 바라보다가 창을 닫아버리기 일수였다. 재밌는 글을 쓰는 재주는 없기에 시작부터 지루하고 고리타분한 이야기가 되어버렸지만, 아무튼 그렇게 됐다. 어영부영 포기하지도 못한 채 이직만이 유일한 답인 것처럼 수십 수백 기업에 스팸 문자같은 이력서를 반복해서 찔러넣다, 이러지도 저러지도 못한 채 2026년 병오년이 밝았다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2025년엔 무엇을 했을까?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; 2025년은 그야말로 LLM의 해였다. ChatGPT의 할루시네이션으로 인해 빚어지는 오만가지 문제들에도 불구하고 ChatGPT를 신봉하는 주변 사람들로 인해 고생을 하는 것으로 시작하여, Claude Code에 월마다 $20씩 지급하다 급기에는 $100씩 지급하기에 이르렀다. 처음에는 간단한 사이드 프로젝트를 만들어보려고 깔짝거리던 바이브 코딩을 몇 달에 걸쳐 삽질을 하고, 이제는 대부분의 메인 프로젝트에 도입했다. 여전히 바이브 코딩에 대해서는 회의적인 시각도 많지만, 도입함으로써 얻는 이점이 상당했으며 바이브 코딩으로 인한 부작용을 어느정도 감당할 수 있다고 판단했기 때문이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; MCP를 통해 연계하던 다른 서비스들은 Claude Code에 도입된 Skill로 래핑되는 경우가 많았고, 이로 인해 토큰도 어느정도 경감할 수 있었다. 그렇다보니 커밋을 진행하거나 이슈를 작성하고, 진행상황을 댓글로 작성하는 작업들을 템플릿화 하여 맞추는 일들도 가능하겠거니 싶었다. 또한 코드를 커밋할 때마다 AI가 이슈에 진행 내용을 댓글로 정리하게끔 함으로써, 매주 작성해야되는 주간업무보고서도 어느정도 AI가 어떤 내용을 진행했는지 작성할 수 있게 됐다. 개인적인 입장으로는 문서와 관련된 귀찮은 일들을 전부 AI에게 맡기게 되어, 제대로 글이 작성됐는지는 보고된 내용을 기반으로 검토만 하게 됐다. 필요한 내용은 직접 수정하거나 AI에게 피드백을 하던지 하고, 나는 문제가 되는 상황에만 집중하면 될 수 있게 됐다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; AI가 보급됨에 따라 이를 어떻게 활용하는게 좋은지 의견이 분분한 가운데, 가장 중요한 것으로 생각되는 것들은 스펙 주도 개발(Spec-Driven Development)이었다. AI의 산출물인 코드를 어떻게 제어할 것인가, 라는 내용에 가장 큰 영향을 미친 내용들이 아닌가싶다. 어찌됐건 AI가 실제로 구현하기 전에 계획을 첨예하게 다듬으면, AI는 해당 지시대로 코드를 작성할테니 어느정도 결과물을 예측 가능하다는 것이 주요 골자였던 것 같은데. 실제로 계획을 첨예하게 다듬다보면 컨텍스트를 Compact하거나 혹은 진행 과정에서 업데이트해야되는 문서가 많다던가 여러가지 이유로 누락되는 사항들이 생겼었다. Opus 4.5까지 여러 모델들이 개선되면서 어느정도는 해결된 문제긴 하지만, 얼마나 계획서를 디테일하게 다듬어야 최적의 결과가 나오는지도 2025년에 겪었던 주된 골칫거리 중 하나였다. 마크다운 형식으로 쌓여가는 결과물도 마찬가지. 아무튼 작성된 것들은 읽지 않으면 어떤 문제가 있고, 어떻게 해결이 됐는지 파악할 수 없으므로 바이브 코딩의 결과물이 점점 작성자로부터 멀어지는 결과가 되는 원인이었던 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; 해당 내용 역시 Claude Code가 Jira에 이슈를 작성하고, 진행 상황에 대해 댓글로 정리하게 되면서 어느정도는 해결이 됐다. 정확히는 이슈의 내용과 처리 과정은 Jira에서 확인한다는 내용이 뇌의 한 구석에 자리를 잡게되며, 자연스럽게 문제가 어떻게 해결됐는지 보려면 Jira를 확인하게 된 것 같지만. 어찌됐건 이러한 내용을 기반으로 사이드 프로젝트는 Linear를 통해 관리하게 됐다. 거진 2025년 말, 2026년 초가 되어서야 그렇게 된 것 같지만.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; 쓸데없는 말들이 길어졌지만 정리해보면 2025년은 대부분의 업무를 AI를 통해서 진행하게 됐고, 문서화 등 귀찮은 작업 역시 AI에게 맡기게 되며 문제 해결에 좀 더 집중할 수 있게 된 한 해였다. 2026년은 어떻게 될지 모르겠다. AI가 더 똑똑해지는 것도, 더 적은 토큰으로 더 많은 일을 하게 되는 것도, 어느쪽도 기대되는 한 해다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;일상 생활에서의 AI&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; 원래 여행을 가면 영상을 찍고 정리하는 걸 좋아했지만, 아무래도 아마추어 수준에서 할 수 있는 일이라고는 적당히 컷 편집을 하고, 내용을 정리하여 자막을 다는 정도였을 것이다. 2025년에는 SUNO v5가 출시되어 한국어 가사도 기가막히게(?) 뽑아내는 덕에, 여행기를 작성한 뒤 이를 노래로 만들어 적당히 컷 편집을 해서 개제하게 됐다. 원래도 돈이 될 정도로 재밌는 글을 쓰거나 혹은 기가막힌 영상을 뽑아내기 보다, 심심할 때 한 번씩 추억을 회상하려고 보기 위한 목적이 강하다보니 여전히 조회수는 미비하지만... 그래도 틈틈히 꺼내보기도 적당하고, 유쾌해서 즐겁다. 기회가 된다면 2023년~2024년에 다녀온 여행들도 SUNO로 정리해서 올려놓을까싶다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; Whisper같은 경우 자막을 만드는 데 빼놓을 수 없는 존재가 됐는데, 영상이 길면 길수록 퀄리티가 떨어지는 문제가 있었다. 이러한 문제는 SUNO로 만든 곡의 길이를 일반적으로 3분 정도로 조절하면서 해결됐다. 개인 여행기다보니 AI에게 모든 것을 일임할 수는 없지만, 그럼에도 불구하고 편집 속도를 가속화하는데 AI가 혁혁한 공을 세웠다는 것은 부인할 수 없는 사실이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; AI 모델이 발달하면 발달할수록 전체적인 기능이 강화될테니, 2026년에도 기대된다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;불안장애에 대하여&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; 해마다 연말이 될 때마다 불안장애를 몇 차례 겪었으나, 점진적으로 회복까지 걸리는 시간이 줄어들더니 2025년에는 거의 겪지 않았다. 이는 심리학 관련된 서적을 읽은 것이 어느정도 도움이 되기도 했고, 한편으로는 AI의 발달로 인해 하고싶은 것들이 생길 때마다 바로바로 진행을 했기 때문이기도 했다. SUNO를 사용해서 노래를 만든 뒤 일상 및 여행 영상을 편집하고, 이런 저런 사이드 프로젝트를 진행하고. 또 프로젝트를 진행하다 필요한 툴이나 플러그인이 생기면 바로바로 작성을 시도했다. 예전이라면 가능한가, 불가능한가 여부를 따졌을 시간에 일단 AI에게 요청을 하여 구현하기 시작한 것이다. 할루시네이션에 의해 잘못된 판단을 하든, 아니면 시간과 토큰을 낭비한 채 처음으로 돌아오는 것은 큰 문제가 아니었는데, 어차피 시도해볼지 말지 고민하면서 낑낑거리는 시간이나 AI와 함께 삽질을 하며 낑낑거리는 시간이나 거기서 거기기 때문. 오히려 쓸데없는 걱정을 하는 시간에 뭘 하려고 하다보니 불안장애같은 게 생길 껀덕지가 없었던 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; 2026년에는 어떻게 될진 모르겠다. 현재 대부분의 업무는 AI가 작성한 코드를 검토하고, AI가 반복해서 해결하지 못하면 구현된 코드를 검토하고, AI가 작성한 문서를 검토하는 것들이다. 아마 2026년에는 더 심하면 심해졌지, 덜하지는 않을 듯 하다. 항간에서는 AI가 개발자를 대체하면 어떻게 할 것인가로 떠들석한 듯 하다. 대부분은 개발을 현업에서 하고 있지는 않을 것 같다. 아마 개발자를 대체한다기보단, 개발자라는 포지션 자체가 많이 달라지지 않을까싶다. 프로젝트가 어떻게 굴러가야 될 지의 방향을 논의하고 코드를 작성하는 사람이 개발자였다면, 앞으로 AI가 지금처럼 발전하게 된다면 QA로써의 역할이 강해지지 않을까, 하는 생각을 해본다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; 그런 생각을 하다보니 불안하기는 커녕, 발달한 AI를 통해 어떤 것들을 더 할 수 있을지 두근거린다. 과연 2026년에는 어떤 일들이 기다리고 있을까.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;정리하며&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; 회고라는 명목하에 2025년과 2026년의 경계선에서, 어떤 일들을 겪었고 어떤 심정인지 정리해보는 시간을 가져봤다. 개인적으로 2025년은 힘든 일들도 많았고, 즐거운 일들도 많았다. 앞으로 AI가 지금처럼 발전하게 된다면, 나의 업무나 할 수 있는 일들도 다양하게 커질 것 같다. 몇 해에 걸쳐서 나를 힘들게 했던 불안장애도 AI가 발달함과 동시에 얼추 해결이 된 것 같아, 2026년은 정말 여러모로 기대되는 해이다.&lt;/p&gt;</description>
      <category>Life journal/회고</category>
      <author>은곰군</author>
      <guid isPermaLink="true">https://zerodice0.tistory.com/318</guid>
      <comments>https://zerodice0.tistory.com/318#entry318comment</comments>
      <pubDate>Sun, 4 Jan 2026 15:24:40 +0900</pubDate>
    </item>
    <item>
      <title>ghostty 설정 백업</title>
      <link>https://zerodice0.tistory.com/317</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;ghostty가 빠르고 좋다는 얘기를 주워듣고, 팔랑거리는 귀를 참을 수 없어서 사용해봤다. 이전에는 iTerm2를 사용했기 때문에 아무래도 일부 단축키가 다른것과, 마우스를 아무리 조작해도 현재 열려있는 pane을 닫을 수 없어서 영 불편했다. 빠르면 장땡인가싶어 투덜거리며, 문서를 조금 찾아보니 이런저런 키 바인딩과 관련된 내용(&lt;a href=&quot;https://ghostty.org/docs/config/keybind/reference&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://ghostty.org/docs/config/keybind/reference&lt;/a&gt;)이 보인다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;iTerm2에서 사용하던 폰트와 탭 전환 키들을 설정하고 난 뒤, 이래저래 살펴보니 생각보다 많은 기능들을 제공한다. 그렇구나, 아무도 깡통으로는 사용하지 않는 녀석이구나. 문득 클로드 코드에게 ghostty의 키 바인딩 문서 주소를 던져주고 프롬프트로 이런저런 설정을 요청하면 과연 잘 설정해줄지 궁금해졌다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/4dwD1/dJMcacuOwH6/ieXIkKdgU8emOkXLBm1FeK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/4dwD1/dJMcacuOwH6/ieXIkKdgU8emOkXLBm1FeK/img.png&quot; data-origin-width=&quot;1278&quot; data-origin-height=&quot;882&quot; data-is-animation=&quot;false&quot; style=&quot;width: 49.1072%; margin-right: 10px;&quot; data-widthpercent=&quot;49.68&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/4dwD1/dJMcacuOwH6/ieXIkKdgU8emOkXLBm1FeK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F4dwD1%2FdJMcacuOwH6%2FieXIkKdgU8emOkXLBm1FeK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1278&quot; height=&quot;882&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/6bC16/dJMcafrxlNk/KR26MQX8GSCViLazOlkfp1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/6bC16/dJMcafrxlNk/KR26MQX8GSCViLazOlkfp1/img.png&quot; data-origin-width=&quot;1281&quot; data-origin-height=&quot;873&quot; data-is-animation=&quot;false&quot; style=&quot;width: 49.73%;&quot; data-widthpercent=&quot;50.32&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/6bC16/dJMcafrxlNk/KR26MQX8GSCViLazOlkfp1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F6bC16%2FdJMcafrxlNk%2FKR26MQX8GSCViLazOlkfp1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1281&quot; height=&quot;873&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단순한 키 바인딩 뿐만 아니라 체이닝 같은 아직 지원하지 않는 기능을 파악하고, 다른 방법들을 제안해주는 걸 보니 확실히 똑똑하긴 하다. 아무튼 이걸로 문서에 기재되어있는 내용을 파악하는데다, 문서에 없는 내용은 깃허브 레포지터리에 기재된 이슈들을 파악하는 것을 확인해서, 자잘자잘하게 키를 추가했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;막상 전부 추가하고나니 집에 있는 맥 스튜디오에 설정하는게 귀찮을 것 같았는데, Iris 키보드 키 맵을 레포지터리에 올려놨던 것처럼 적당히 쉘 스크립트와 함께 올려놓으면 되겠다 싶었다. VSCode에서 사용하던 창 관련 키를 추가해놓고, 스크롤과 창 사이즈 변경과 관련된 키들을 추가해놨는데, 이제 스크롤 하려고 일일히 마우스 커서를 이동하지 않아도 되서 몹시 편하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;좋네, ghostty.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/zerodice0/ghostty_config&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://github.com/zerodice0/ghostty_config&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1764635762874&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;GitHub - zerodice0/ghostty_config: ghostty config backup repository&quot; data-og-description=&quot;ghostty config backup repository. Contribute to zerodice0/ghostty_config development by creating an account on GitHub.&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/zerodice0/ghostty_config&quot; data-og-url=&quot;https://github.com/zerodice0/ghostty_config&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/clBoO9/hyZO1D6iIV/kpfrH5HtPlOcyOkHiJ3PjK/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/BBPWi/hyZNCToRFc/KLaG88varV3ZhicyIwI5nk/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/zerodice0/ghostty_config&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/zerodice0/ghostty_config&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/clBoO9/hyZO1D6iIV/kpfrH5HtPlOcyOkHiJ3PjK/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/BBPWi/hyZNCToRFc/KLaG88varV3ZhicyIwI5nk/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;GitHub - zerodice0/ghostty_config: ghostty config backup repository&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;ghostty config backup repository. Contribute to zerodice0/ghostty_config development by creating an account on GitHub.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Programming/개발환경</category>
      <category>ghostty</category>
      <category>터미널</category>
      <author>은곰군</author>
      <guid isPermaLink="true">https://zerodice0.tistory.com/317</guid>
      <comments>https://zerodice0.tistory.com/317#entry317comment</comments>
      <pubDate>Tue, 2 Dec 2025 09:45:32 +0900</pubDate>
    </item>
    <item>
      <title>아이리스 키보드 펌웨어 업데이트(zerodice0 v1.3.2)</title>
      <link>https://zerodice0.tistory.com/316</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; Claude code Opus 4.5 모델이 업데이트되고 난 이후로, 키보드 용량을 좀 최적화 할 수 있지 않을까 싶어서 이래저래 돌려봤다. (개인적으로 생각하기에) 리소스를 좀 많이 잡아먹어서 사용하기 애매한 LED 효과들을 쳐내고, const를 #define으로 변경해서 메모리를 최적화해줬다.(물론 클로드가.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; 조금 사용해보니 LED도 내 설정대로 변경하고 싶은 요소 중 하나인데 USB를 연결할 때마다 OS를 감지해서 설정이 되다보니 애매하게 거슬려서, OS감지해서 LED를 설정하는 기능은 제거했다. 그 외에도 MacOS에서는 언어 변경 단축키를 ScrollLock에서 F19로 변경했다. ScrollLock으로 설정해놨더니 약간의 딜레이가 있었고, 뿐만 아니라 영어로 변경한 뒤 shift를 눌러 대문자를 입력하려고 하니 다시 한글로 변경되는 문제가 발생했기 때문. 거기에 더해서 종종 언어를 변경한 뒤 입력하다보면 자동으로 언어가 변경되어 골치아픈 경우가 생겼는데, 이런 경우 해결하기 위해 카라비너를 사용해 ScrollLock을 F19로 치환하는 경우가 있는 모양이었다. 카라비너 툴을 따로 설치하기는 귀찮았기 때문에(...), 아예 MacOS에서 언어 변경 키(Fn1+RShift)를 누르면 F19가 입력되도록 변경. MacOS마다 단축키 설정을 변경해줘야된다는게 살짝 아쉽긴 하지만, 결과는 생각보다 효과적이었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; 아무튼 이래저래 펌웨어 용량도 Rev.7 기준으로 98%가량 소진하다가 95%로 낮췄으니, 사용하다가 아쉬운게 있으면 또 업데이트 해야지... ' ㅇ')&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/zerodice0/iris56_keymap/releases/tag/1.3.2&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://github.com/zerodice0/iris56_keymap/releases/tag/1.3.2&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1764634960730&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;Release 1.3.2: macOS 한영키를 F19로 변경 &amp;middot; zerodice0/iris56_keymap&quot; data-og-description=&quot;Release Notes - December 1, 2025 Summary This release changes the macOS language switching key from Ctrl+Space to F19. This change requires manual configuration in macOS System Settings to assign F...&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/zerodice0/iris56_keymap/releases/tag/1.3.2&quot; data-og-url=&quot;https://github.com/zerodice0/iris56_keymap/releases/tag/1.3.2&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bgt32n/hyZNBUtqyY/IUpK0Qhko9O87GecCBWZ70/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/zFGxI/hyZNy4w9GY/P0gzmKunEgFTYxy9rcAn7k/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/zerodice0/iris56_keymap/releases/tag/1.3.2&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/zerodice0/iris56_keymap/releases/tag/1.3.2&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bgt32n/hyZNBUtqyY/IUpK0Qhko9O87GecCBWZ70/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/zFGxI/hyZNy4w9GY/P0gzmKunEgFTYxy9rcAn7k/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Release 1.3.2: macOS 한영키를 F19로 변경 &amp;middot; zerodice0/iris56_keymap&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Release Notes - December 1, 2025 Summary This release changes the macOS language switching key from Ctrl+Space to F19. This change requires manual configuration in macOS System Settings to assign F...&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Machine, Device/키보드</category>
      <category>iris</category>
      <category>keebio</category>
      <category>Keyboard</category>
      <category>QMK</category>
      <category>키보드</category>
      <author>은곰군</author>
      <guid isPermaLink="true">https://zerodice0.tistory.com/316</guid>
      <comments>https://zerodice0.tistory.com/316#entry316comment</comments>
      <pubDate>Tue, 2 Dec 2025 09:33:42 +0900</pubDate>
    </item>
    <item>
      <title>아이리스 키보드 펌웨어 업데이트(zerodice0 v1.2.0)</title>
      <link>https://zerodice0.tistory.com/315</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; 이전에 업데이트된 QMK 키 코드에 맞춰 마이그레이션하는 과정에서, 클로드 코드가 입력한 키 코드 중 KC_WH_R, KC_WH_L키가 제대로 동작하지 않는 문제가 있었다. 별 대단한 문제는 아니기에 거진 3주간 그냥 사용하고 있었는데, 막상 고치려다보니 키 코드를 하나하나 찾아서 수정하긴 귀찮았기에 클로드 코드에게 물어보고 수정된 내용을 살펴보기(...)로 했다. 검증을 열심히 하면 펌웨어 올려놓기 전에 찾을 수 있겠지. 아무튼 그 과정에서 QMK Firmware에 USB로 연결한 컴퓨터의 OS를 감지할 수 있는 기능이 &lt;s&gt;오래전에&lt;/s&gt; 추가됐다는 사실을 알 수 있었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; 재밌어보여서 클로드 코드에게 물어서 연결한 os에 상관없이 마우스 스크롤 방향을 동일하게 일치시키고, 동일한 단축키로 언어를 변경하고 스크린샷을 찍을 수 있도록 펌웨어를 수정했다. 스크린샷을 캡쳐하는 기능은 맥OS와 안드로이드에서만 테스트해봤는데, 아쉽게도 스크린샷을 캡쳐해서 클립보드에 복사하는 기능은 안드로이드에서 동작하지 않았다. 그래서 fn3+6, 7, 8, 9, 0에 할당한 기능들은 아마도 맥OS를 제외하면 제대로 동작하지 않지 않으려나싶다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; 물론 클로드 코드가 스크롤 키를 tap_code()로 구현해서 스크롤 키를 누르고 있으면 깔짝 스크롤되고 만다던가, 다국어 변경 키를 OS마다 다르게 할당하는 바람에 제대로 동작하지 않아 결국에는 키 코드 표를 확인해가며 수정했다던가, 이래저래 번거로운(?) 일이 있긴 했지만 재밌는 경험이었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; 아무튼 클로드 코드가 멋대로 맥OS에 연결하면 하얀색, 윈도우에 연결하면 파란색, Linux/안드로이드에 연결하면 초록색 led가 켜지도록 해놨는데, 이건 이거대로 괜찮아서 마음에 든다. 물론 새로운 컴퓨터에 연결할 때마다 led 설정이 초기화된다는 건 조금 아쉽긴 하지만, 까짓거 나중에 고치지 뭐...&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/zerodice0/iris56_keymap/releases/tag/1.2.0&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://github.com/zerodice0/iris56_keymap/releases/tag/1.2.0&lt;/a&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1762255167466&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;Release 1.2.0: docs: 멀티 OS 호환성 문서화 및 저장소 구조 명확화 &amp;middot; zerodice0/iris56_keymap&quot; data-og-description=&quot;Release Notes - November 4, 2025 Summary This release implements a comprehensive OS-agnostic keyboard shortcuts system using static keycode mapping with helper functions. The update replaces runtim...&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/zerodice0/iris56_keymap/releases/tag/1.2.0&quot; data-og-url=&quot;https://github.com/zerodice0/iris56_keymap/releases/tag/1.2.0&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/t1AdZ/hyZMAGQjGT/XC8ZpqIoiOQQhW4OKlf9ok/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/rQWtA/hyZMF2rnY2/KeWoHmgQdvCKpSDi5N9mN1/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/zerodice0/iris56_keymap/releases/tag/1.2.0&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/zerodice0/iris56_keymap/releases/tag/1.2.0&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/t1AdZ/hyZMAGQjGT/XC8ZpqIoiOQQhW4OKlf9ok/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/rQWtA/hyZMF2rnY2/KeWoHmgQdvCKpSDi5N9mN1/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Release 1.2.0: docs: 멀티 OS 호환성 문서화 및 저장소 구조 명확화 &amp;middot; zerodice0/iris56_keymap&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Release Notes - November 4, 2025 Summary This release implements a comprehensive OS-agnostic keyboard shortcuts system using static keycode mapping with helper functions. The update replaces runtim...&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Machine, Device/키보드</category>
      <author>은곰군</author>
      <guid isPermaLink="true">https://zerodice0.tistory.com/315</guid>
      <comments>https://zerodice0.tistory.com/315#entry315comment</comments>
      <pubDate>Tue, 4 Nov 2025 20:31:17 +0900</pubDate>
    </item>
    <item>
      <title>daum_postcode_search 1.0.0 업데이트</title>
      <link>https://zerodice0.tistory.com/314</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;서론&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;daum_postcode_search는 Daum 우편번호 서비스를 Flutter 애플리케이션에 쉽게 통합할 수 있는 패키지입니다. 그동안 패키지는 특정 WebView 라이브러리에 의존하는 형태로 개발되어 왔습니다. 이번 1.0.0 버전에서는 완전히 새로운 아키텍처로 재설계되었으며, 더 이상 특정 WebView 패키지에 의존하지 않는 zero-dependency 패키지로 탈바꿈했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 글에서는 1.0.0 버전에서 무엇이 변경되었는지, 왜 이런 변경을 결정했는지, 그리고 기존 사용자들이 어떻게 마이그레이션할 수 있는지 자세히 살펴보겠습니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;주요 변경사항&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. Zero-Dependency 아키텍처&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 중요한 변경사항은 패키지에서 모든 WebView 의존성을 제거했다는 점입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;이전 (0.0.3)&lt;/b&gt;:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;code&gt;flutter_inappwebview&lt;/code&gt; 의존성 필수&lt;/li&gt;
&lt;li&gt;특정 WebView 구현에 강하게 결합됨&lt;/li&gt;
&lt;li&gt;패키지 크기: 3~4MB (의존성 포함)&lt;/li&gt;
&lt;li&gt;사용자는 InAppWebView만 선택 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;현재 (1.0.0)&lt;/b&gt;:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Zero dependencies&lt;/li&gt;
&lt;li&gt;로컬 HTTP 서버와 HTML 자산만 제공&lt;/li&gt;
&lt;li&gt;패키지 크기: 약 50KB&lt;/li&gt;
&lt;li&gt;사용자가 WebView 선택 가능 (webview_flutter, flutter_inappwebview 또는 기타)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. 획기적인 패키지 크기 감소&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1.0.0 버전은 패키지 크기를 98.5% 감소시켰습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;0.0.3&lt;/b&gt;: 약 3~4MB&lt;/li&gt;
&lt;li&gt;&lt;b&gt;1.0.0&lt;/b&gt;: 약 50KB&lt;/li&gt;
&lt;li&gt;&lt;b&gt;감소율&lt;/b&gt;: 98.5%&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이는 사용자의 최종 애플리케이션 번들 크기를 크게 줄일 수 있으며, 특히 모바일 환경에서 다운로드 시간과 설치 크기를 개선합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. 사용자에게 선택권 부여&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 개발자들은 자신의 프로젝트에 맞는 WebView 구현을 자유롭게 선택할 수 있습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;webview_flutter&lt;/b&gt;: 공식 Flutter WebView 플러그인, 더 간단한 API&lt;/li&gt;
&lt;li&gt;&lt;b&gt;flutter_inappwebview&lt;/b&gt;: 더 많은 고급 기능과 커스터마이제이션 옵션&lt;/li&gt;
&lt;li&gt;&lt;b&gt;기타 WebView 패키지&lt;/b&gt;: 다른 솔루션도 자유롭게 사용 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러한 유연성은 프로젝트의 요구사항에 따라 최적의 솔루션을 선택할 수 있게 해줍니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;새로운 기능 및 API&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. DaumPostcodeLocalServer&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;로컬 HTTP 서버를 관리하는 클래스입니다. 이 서버는 HTML 자산을 제공하고 WebView에서 접근 가능한 엔드포인트를 만듭니다.&lt;/p&gt;
&lt;pre class=&quot;axapta&quot;&gt;&lt;code&gt;import 'package:daum_postcode_search/daum_postcode_search.dart';

// 서버 생성
final server = DaumPostcodeLocalServer(
  address: 'localhost',  // 기본값
  port: 8080,            // 기본값
);

// 서버 시작
await server.start();

// 서버 URL 사용
print(server.url);  // http://localhost:8080

// 서버 상태 확인
print(server.isRunning);  // true

// 서버 종료
await server.stop();&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. DaumPostcodeCallbackParser&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;WebView에서 받은 콜백 데이터를 파싱하여 주소 정보 모델로 변환합니다. 다양한 콜백 방식을 지원합니다.&lt;/p&gt;
&lt;pre class=&quot;dart&quot;&gt;&lt;code&gt;// PostMessage 방식
final result = DaumPostcodeCallbackParser.fromPostMessage(jsonData);

// JavaScript Handler 방식
final result = DaumPostcodeCallbackParser.fromJsHandler(data);

// URL Scheme 방식
final result = DaumPostcodeCallbackParser.fromUrlScheme(url);

// 결과 사용
if (result != null) {
  print('주소: ${result.address}');
  print('우편번호: ${result.zonecode}');
}&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. DaumPostcodeAssets&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;HTML 파일 경로를 상수로 제공하여 필요한 HTML 버전을 쉽게 선택할 수 있습니다.&lt;/p&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;// 4가지 콜백 메커니즘 제공
DaumPostcodeAssets.urlScheme      // URL Scheme 콜백
DaumPostcodeAssets.postMessage    // PostMessage (webview_flutter 권장)
DaumPostcodeAssets.jsHandler      // JS Handler (flutter_inappwebview 권장)
DaumPostcodeAssets.jsChannel      // JS Channel&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4. 다양한 콜백 메커니즘&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;WebView 구현의 특성에 맞게 4가지 다른 콜백 방식을 제공합니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;URL Scheme&lt;/b&gt;: 고전적인 방식, 어느 WebView에서나 작동&lt;/li&gt;
&lt;li&gt;&lt;b&gt;PostMessage&lt;/b&gt;: 웹 표준 방식, webview_flutter에 최적화&lt;/li&gt;
&lt;li&gt;&lt;b&gt;JavaScript Handler&lt;/b&gt;: InAppWebView의 고급 기능 활용&lt;/li&gt;
&lt;li&gt;&lt;b&gt;JavaScript Channel&lt;/b&gt;: Dart와 JavaScript 간의 양방향 통신&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Breaking Changes 및 마이그레이션&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Breaking Changes&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;0.0.4 버전에서 1.0.0으로 업그레이드할 때 주의해야 할 주요 변경사항은 다음과 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;제거된 기능&lt;/b&gt;:&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;code&gt;DaumPostcodeSearch&lt;/code&gt; 위젯 - 더 이상 사용 불가&lt;/li&gt;
&lt;li&gt;모든 WebView 관련 콜백 (&lt;code&gt;onConsoleMessage&lt;/code&gt;, &lt;code&gt;onReceivedError&lt;/code&gt; 등)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;flutter_inappwebview&lt;/code&gt; 의존성&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;새로운 방식&lt;/b&gt;:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;사용자가 직접 WebView 통합을 구현해야 함&lt;/li&gt;
&lt;li&gt;로컬 서버와 콜백 파서를 이용하여 수동으로 통합&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;마이그레이션 방법&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Step 1: pubspec.yaml 업데이트&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;이전 (0.0.4)&lt;/b&gt;:&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;dependencies:
  daum_postcode_search: ^0.0.4&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;현재 (1.0.0)&lt;/b&gt;:&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;dependencies:
  daum_postcode_search: ^1.0.0
  webview_flutter: ^4.8.0  # 또는 flutter_inappwebview: ^6.1.5&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Step 2: 코드 마이그레이션&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;이전 (0.0.4)&lt;/b&gt;:&lt;/p&gt;
&lt;pre class=&quot;moonscript&quot;&gt;&lt;code&gt;import 'package:daum_postcode_search/daum_postcode_search.dart';

// 이전에는 위젯으로 제공됨
DaumPostcodeSearch(
  onConsoleMessage: (_, message) =&amp;gt; print(message),
  onReceivedError: (controller, request, error) =&amp;gt; setState(...),
)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;현재 (1.0.0) - webview_flutter 예제&lt;/b&gt;:&lt;/p&gt;
&lt;pre class=&quot;scala&quot;&gt;&lt;code&gt;import 'package:daum_postcode_search/daum_postcode_search.dart';
import 'package:webview_flutter/webview_flutter.dart';

class PostcodeSearchPage extends StatefulWidget {
  @override
  State&amp;lt;PostcodeSearchPage&amp;gt; createState() =&amp;gt; _PostcodeSearchPageState();
}

class _PostcodeSearchPageState extends State&amp;lt;PostcodeSearchPage&amp;gt; {
  late DaumPostcodeLocalServer _server;
  late WebViewController _controller;

  @override
  void initState() {
    super.initState();
    _initializeServer();
  }

  Future&amp;lt;void&amp;gt; _initializeServer() async {
    _server = DaumPostcodeLocalServer();
    await _server.start();
    setState(() {});
  }

  @override
  Widget build(BuildContext context) {
    if (!_server.isRunning) {
      return Scaffold(
        body: Center(child: CircularProgressIndicator()),
      );
    }

    return Scaffold(
      appBar: AppBar(title: Text('우편번호 검색')),
      body: WebViewWidget(
        controller: WebViewController()
          ..addJavaScriptChannel(
            'DaumPostcodeChannel',
            onMessageReceived: (JavaScriptMessage message) {
              final result = DaumPostcodeCallbackParser.fromPostMessage(
                message.message,
              );
              if (result != null) {
                print('주소: ${result.address}');
                Navigator.of(context).pop(result);
              }
            },
          )
          ..loadRequest(
            Uri.parse(
              '${_server.url}/${DaumPostcodeAssets.postMessage}',
            ),
          ),
      ),
    );
  }

  @override
  void dispose() {
    _server.stop();
    super.dispose();
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;실제 사용 예제&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;webview_flutter를 사용한 예제&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;webview_flutter는 공식 Flutter WebView 플러그인으로, 더 간단한 API를 제공합니다.&lt;/p&gt;
&lt;pre class=&quot;dart&quot;&gt;&lt;code&gt;import 'package:daum_postcode_search/daum_postcode_search.dart';
import 'package:webview_flutter/webview_flutter.dart';

Future&amp;lt;void&amp;gt; showPostcodeDialog(BuildContext context) async {
  final server = DaumPostcodeLocalServer();
  await server.start();

  if (!context.mounted) return;

  showDialog(
    context: context,
    builder: (context) {
      return Dialog(
        child: WebViewWidget(
          controller: WebViewController()
            ..addJavaScriptChannel(
              'DaumPostcodeChannel',
              onMessageReceived: (message) async {
                final result = DaumPostcodeCallbackParser.fromPostMessage(
                  message.message,
                );
                if (result != null) {
                  Navigator.of(context).pop(result);
                  await server.stop();
                }
              },
            )
            ..loadRequest(
              Uri.parse(
                '${server.url}/${DaumPostcodeAssets.postMessage}',
              ),
            ),
        ),
      );
    },
  );
}&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;flutter_inappwebview를 사용한 예제&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;더 많은 제어와 고급 기능이 필요한 경우 flutter_inappwebview를 사용할 수 있습니다.&lt;/p&gt;
&lt;pre class=&quot;dart&quot;&gt;&lt;code&gt;import 'package:daum_postcode_search/daum_postcode_search.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';

Future&amp;lt;void&amp;gt; showPostcodeDialog(BuildContext context) async {
  final server = DaumPostcodeLocalServer();
  await server.start();

  if (!context.mounted) return;

  showDialog(
    context: context,
    builder: (context) {
      return Dialog(
        child: InAppWebView(
          initialUrlRequest: URLRequest(
            url: WebUri(
              '${server.url}/${DaumPostcodeAssets.jsHandler}',
            ),
          ),
          onWebViewCreated: (controller) {
            controller.addJavaScriptHandler(
              handlerName: 'handleAddressData',
              callback: (args) async {
                final result = DaumPostcodeCallbackParser.fromJsHandler(
                  args[0],
                );
                if (result != null) {
                  Navigator.of(context).pop(result);
                  await server.stop();
                }
              },
            );
          },
        ),
      );
    },
  );
}&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;기술적 개선사항&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. 아키텍처 단순화&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이전 버전은 특정 WebView 구현에 강하게 결합되어 있었습니다. 새로운 버전은 HTTP 서버와 데이터 파서라는 두 가지 핵심 기능만 제공하므로, 아키텍처가 훨씬 단순하고 명확합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. 유지보수성 향상&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;패키지 버전 업그레이드 시 다양한 WebView 라이브러리의 API 변경에 대응할 필요가 없습니다. 사용자가 자신의 WebView 버전을 관리하므로, 패키지는 더 안정적인 상태를 유지할 수 있습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. 확장성 증대&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;로컬 서버 기반의 아키텍처이므로, 향후 다양한 콜백 방식을 추가하거나 새로운 기능을 확장하기가 훨씬 용이합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4. 테스트 용이성&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;WebView에 의존하지 않으므로 로컬 서버와 파서의 로직을 독립적으로 테스트할 수 있습니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;설정 가이드&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Android 설정&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AndroidManifest.xml의 &lt;code&gt;&amp;lt;application&amp;gt;&lt;/code&gt; 태그에 다음을 추가하세요:&lt;/p&gt;
&lt;pre class=&quot;applescript&quot;&gt;&lt;code&gt;&amp;lt;application
    android:usesCleartextTraffic=&quot;true&quot;
    ...&amp;gt;
&amp;lt;/application&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이는 로컬 HTTP 서버 (localhost:8080)에 접속할 때 필요합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;iOS 설정&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Info.plist에 다음을 추가하세요:&lt;/p&gt;
&lt;pre class=&quot;xml&quot;&gt;&lt;code&gt;&amp;lt;key&amp;gt;NSAppTransportSecurity&amp;lt;/key&amp;gt;
&amp;lt;dict&amp;gt;
  &amp;lt;key&amp;gt;NSAllowsArbitraryLoads&amp;lt;/key&amp;gt;&amp;lt;true/&amp;gt;
&amp;lt;/dict&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;결론&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;daum_postcode_search 1.0.0은 패키지의 철학을 근본적으로 변경한 버전입니다. Zero-dependency 아키텍처로 전환함으로써 패키지 크기를 98.5% 감소시켰고, 사용자에게 WebView 선택의 자유도를 부여했으며, 유지보수성과 확장성을 크게 향상시켰습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비록 기존 사용자들은 수동으로 WebView 통합을 구현해야 하는 약간의 추가 작업이 필요하지만, 장기적으로는 더욱 안정적이고 유연한 솔루션을 얻게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 릴리스가 Flutter 커뮤니티에서 우편번호 검색 기능을 더 쉽고 효율적으로 사용하는 데 도움이 되길 바랍니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;유용한 링크&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://pub.dev/packages/daum_postcode_search&quot;&gt;pub.dev 패키지 페이지&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/zerodice0/BlackBearsFlutterLibrary/tree/main/lib/library/daum_postcode_search&quot;&gt;GitHub 저장소&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://postcode.map.daum.net/guide&quot;&gt;Daum 우편번호 서비스&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Programming/Flutter</category>
      <category>daum</category>
      <category>flutter</category>
      <category>우편번호</category>
      <category>주소검색</category>
      <author>은곰군</author>
      <guid isPermaLink="true">https://zerodice0.tistory.com/314</guid>
      <comments>https://zerodice0.tistory.com/314#entry314comment</comments>
      <pubDate>Thu, 16 Oct 2025 11:33:45 +0900</pubDate>
    </item>
    <item>
      <title>macOS Tahoe 26 업데이트 후 SSH 접속이 안되는 경우</title>
      <link>https://zerodice0.tistory.com/313</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;[문제 상황]&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;macOS를 Tahoe 26으로 업데이트 한 이후에 ssh로 접속을 하려하니, 다음과 같은 에러가 발생했다. 이번에 OS가 업데이트되면서 open-ssh 버전이 업데이트 된 듯 한데 기존에 사용하던 ssh-config 설정 파일은 자동으로 변경되지 않아서 발생하는 문제인 것 같다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1758074443515&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/etc/ssh/ssh_config line 56: Bad key types 'ssh-dss,ssh-rsa,rsa-sha2-512,rsa-sha2-256,ecdsa-sha2-nistp256,ssh-ed25519'.
/etc/ssh/ssh_config: terminating, 1 bad configuration options&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ssh-rsa는 SHA1 서명 방식이라 기본적으로 비활성화됐고, 클라이언트 공개키 알고리즘(PubkeyAcceptedAlgorithms)과 호스트키 알고리즘(HostKeyAlgorithms) 설정이 분리됐다. sudo /etc/ssh/ssh_config를 입력해서 문제가 발생한 HostKeyAlgorithms 설정을 주석처리하고, 다음과 같이 설정값을 입력해주자.&lt;/p&gt;
&lt;pre id=&quot;code_1758074825239&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;HostKeyAlgorithms ssh-ed25519,ecdsa-sha2-nistp256
PubkeyAcceptedAlgorithms ssh-ed25519,ecdsa-sha2-nistp256,rsa-sha2-512,rsa-sha2-256&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후 ssh 접속을 시도해보면 문제 없이 접속되는 것을 확인할 수 있다. :)&lt;/p&gt;</description>
      <category>Programming/개발환경</category>
      <category>MacOS</category>
      <category>SSH</category>
      <category>ssh_config</category>
      <category>Tahoe</category>
      <author>은곰군</author>
      <guid isPermaLink="true">https://zerodice0.tistory.com/313</guid>
      <comments>https://zerodice0.tistory.com/313#entry313comment</comments>
      <pubDate>Wed, 17 Sep 2025 11:07:51 +0900</pubDate>
    </item>
    <item>
      <title>앱 초기 부팅 시 Isolate 초기화 실패와 리렌더링</title>
      <link>https://zerodice0.tistory.com/312</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;512&quot; data-origin-height=&quot;512&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/btE2og/btsPGmLILei/64Swbc5Hf6GODyIJRxuTFK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/btE2og/btsPGmLILei/64Swbc5Hf6GODyIJRxuTFK/img.png&quot; data-alt=&quot;출처: Gemini-pro&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/btE2og/btsPGmLILei/64Swbc5Hf6GODyIJRxuTFK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbtE2og%2FbtsPGmLILei%2F64Swbc5Hf6GODyIJRxuTFK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;512&quot; height=&quot;512&quot; data-origin-width=&quot;512&quot; data-origin-height=&quot;512&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처: Gemini-pro&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. 사건의 발단&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; 때는 바야흐로 필요한 앱의 기능 대부분을 만들어가는 시점, 최적화 관련된 문제가 말이 많았다. 정확한 원인은 발견하지 못했지만 초기 부팅시 렌더링 관련해서 리소스를 많이 잡아먹고 있었고, 어디서 렌더링 관련된 문제가 발생하는지 정확히 파악하지 못하고 있었다. 어찌됐건 앱은 출시해야했고 다른 동료분이 앱 초기 부팅 시점에 HTTP 요청을 과도하게 요청해서 문제가 발생한다면, HTTP 요청을 다른 스레드에서 하도록 만들면 되지 않냐는 얘기를 했다. 어찌됐건 당시에는 별달리 뾰족한 방법도 없었기에, 정말 HTTP 요청하는 모듈을 별도 Isolate로 분리했다. 아무튼 Flutter/Dart의 특징에 대해 잘 알고 있는 분도 아니었는데 왜 그런 얘기를 수용했는지 모르겠다. 아마 절박해서 그런거였겠지. 구현과 관련된 내용은 &lt;a href=&quot;https://zerodice0.tistory.com/295&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;이 글&lt;/a&gt;을 참조하자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; 어쨌건 HTTP 요청을 직접적으로 메인 스레드에서 처리하지 않으니 조금은 성능상에 여유가 생긴 것 같았지만, 여전히 퍼포먼스 탭에서 측정해보면 쟁크 현상이 발생하고 있었다. 거기에 추가적으로 앱 초기 실행 시점에 HTTP 요청을 하려면 Isolate를 초기화할 필요가 있었는데, 초기화에 실패해서 HTTP 요청을 못하는 상황이 발생했다. 100% 요청에 실패하는 것도 아니고 디버그 모드에서 증상이 더 잘 발생했으며, 개발폰이라고는 저사양인 폰밖에 없음에도 불구하고 안드로이드에서 더 빈번하게 발생했다. 다행인지 불행인지 릴리즈 모드에서는 좀 덜한 상황이었지만, 앱을 초기화하는 시점에 인증 토큰이 만료되면 자동으로 로그인 API를 요청하는 방식으로 구현해놔서 그런지, 간헐적으로 로그인이 안된다는 점이 가장 환장할 노릇이었다. 아마도 Isolate 초기화에서 무슨 일이 일어나는지 머리로는 알고 있었지만, 실제 동작에 대해서는 정확히 파악하지 못하고 있었기 때문에 문제를 해결하는게 너무 오래 걸린게 아닐까.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2. Isolate가 초기화 시점에 뭘 하길래?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; 정확히는 자식 Isolate가 무슨 작업을 하는가에 따라 다르겠지만, 자식 Isolate와 메인 Isolate는 별도 프로세스로 자원을 공유하지 않는다. 따라서 Isolate가 무엇을 하는지, 혹은 작업이 완료됐는지 전혀 신경쓰지 않는다면 상관없지만, 그렇지 않은 경우에는 통신이 필요하다. 특히 지금같은 상황에서는 HTTP 요청을 자식 Isolate에서 처리하고 있었기 때문에, 자식 Isolate에서 응답을 수신한 뒤 메인 Isolate로 전송해야했다. 이런 식으로 Isolate간에 통신을 하기 위해서는 프로세스 간 통신을 하는 것과 마찬가지로, 별도 소켓을 통해서 통신을 진행해야한다. 메인 Isolate에서 자식 Isolate를 파생한 뒤 소켓을 전송하고, 서로 소켓이 정상적으로 체결됐는지 확인하는 절차가 필요하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; 여기서 메인 Isolate가 처리하는 작업이 많아서 바쁘면 무슨 일이 발생할까? 메인 Isolate에서 자식 Isolate를 파생하고, 소켓을 메시지로 전달하고, 자식 Isolate에서 메인 Isolate가 메시지를 잘 받았는지 대기하게된다. 위에서 언급한 &lt;a href=&quot;https://zerodice0.tistory.com/295&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;구현&lt;/a&gt;에서는 10초동안 초기화되지 않으면 타임아웃 에러를 발생시키는데, 메인 Isolate에서 네이티브에 접근할 경우에는 블로킹이 발생하며 레이아웃이 과도하게 발생하는 경우도 마찬가지다. 렌더링의 우선순위에 대해서는 문서의&amp;nbsp;&lt;a href=&quot;https://docs.flutter.dev/resources/architectural-overview#rendering-and-layout&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Rendering and Layout&lt;/a&gt;에도 명시되어있지 않아 정확하게 알 수는 없지만, 렌더링이 과도하게 발생하면 Isolate간 통신은 렌더링의 우선순위에 밀리다보니 10초동안 통신에 실패하는게 아니었을까.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3. 그래서 무엇을 했는지?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; 우선 메인 Isolate에서 네이티브에 접근하는 동작을 최소화하고, 리렌더링을 발생하지 않는게 중요했다. 초기에 상태관리를 위해 RiverPod을 채용했다면 아마도 이런 문제에 대해 조금 더 자유롭지 않았을까. 하지만 Provider를 채용해서 전역상태를 관리했기 때문에 초기화 시점에 변경되는 상태가 많았고, 이로 인해서 앱 전체가 리렌더링되다보니 문제가 발생했다. 당장 상태관리를 다른 패키지로 교체하기에는 무리가 있었고, 우선은 Selector를 사용해서 리렌더링 횟수 자체를 최소화했다. 특정 상태값이 변경됐을 때만 부분적으로 리렌더링하도록 변경했더니, 아무래도 리렌더링 과정에서 렌더 트리를 파싱 연산에 걸리는 리소스가 줄어든게 아닐까.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; 또한 네이티브에 접근하는 SharedPreference의 호출을 최소화하고, SharedPreference가 필요한 초기화 작업에는 참조를 인자값으로 전달하여 SharedPreference에 두 번 이상 접근하지 않도록 수정했다. Platform.kDebugMode와 같은 플랫폼 연계된 값을 참조하는 것 역시 마찬가지. 아무튼 이런 식으로 네이티브 코드에 대한 접근을 줄이고 렌더링 최적화를 진행하자 Isolate를 초기화하는 과정에서 실패하는 일이 줄어들고, 나아가서는 안드로이드 환경에서 디버그 모드로 동작할 때 핫 리로드 시 앱이 강제 종료하는 경우도 줄어들었다. U ㅈU)&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;4. 결론&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; 앱 초기 개발에는 최적화와 관련된 내용은 우선순위에서 멀어지는 경우가 종종 있다. 특히 StatefulWidget()이나 Selector, Consumer 등을 사용하지 않은 Provider의 사용은 무분별한 렌더링으로 인해 Jank를 발생시킬 수 있고, 네이티브 코드에 대한 접근 및 파일에 접근하는 등의 동작은 메인 Isolate를 블록 상태로 만들기 때문에 의도치 않은 사이드 이펙트를 발생시킬 수 있다. 이런 일이 발생하지 않도록 되도록이면 초기 구현시 렌더링과 네이티브 코드 및 파일 접근에 신경을 쓰면서 구현하도록 하자.&lt;/p&gt;</description>
      <category>Programming/Flutter</category>
      <category>flutter</category>
      <category>isolate</category>
      <category>jank</category>
      <category>rendering</category>
      <author>은곰군</author>
      <guid isPermaLink="true">https://zerodice0.tistory.com/312</guid>
      <comments>https://zerodice0.tistory.com/312#entry312comment</comments>
      <pubDate>Sat, 2 Aug 2025 12:02:19 +0900</pubDate>
    </item>
  </channel>
</rss>