<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>CELLAXON</title>
    <link>https://cellaxon.tistory.com/</link>
    <description></description>
    <language>ko</language>
    <pubDate>Thu, 9 Apr 2026 20:16:51 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>cellaxon</managingEditor>
    <image>
      <title>CELLAXON</title>
      <url>https://tistory1.daumcdn.net/tistory/5897923/attach/4055519e2f7a41be941c31495aef2c8c</url>
      <link>https://cellaxon.tistory.com</link>
    </image>
    <item>
      <title>React 프로젝트를 내부망에 가져가서 사용하려면?</title>
      <link>https://cellaxon.tistory.com/36</link>
      <description>&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;상황에 처해봐야 문제를 해결할 방법을 찾게 되니 말입니다.&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;pnpm을 사용하고 있다는 조건입니다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 프로젝트 루트 경로에 '&lt;b&gt;.npmrc&lt;/b&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;2. 아래의 내용을 붙여넣습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1762136103635&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# .npmrc 파일
virtual-store-dir=.pnpm
store-dir=./.pnpm-store
modules-dir=./node_modules&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;3. 외부망 환경에서 아래의 명령을 실행합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1762136179636&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;pnpm install&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;4. 프로젝트 폴더를 통째로 압축합니다. ('.pnpm', '.pnpm-store', 'node_modules' 등 모든 파일과 폴더를 포함해서 압축)&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;5. 내부망으로 가져가서 압축을 풀고 아래의 명령을 실행합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1762136278570&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;pnpm install -offline&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;&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;&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;&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;/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;</description>
      <category>프로그래밍</category>
      <author>cellaxon</author>
      <guid isPermaLink="true">https://cellaxon.tistory.com/36</guid>
      <comments>https://cellaxon.tistory.com/36#entry36comment</comments>
      <pubDate>Mon, 3 Nov 2025 11:19:44 +0900</pubDate>
    </item>
    <item>
      <title>Solid 프로젝트 시작하기</title>
      <link>https://cellaxon.tistory.com/35</link>
      <description>&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;저도 현실 순응을 위해 리액트 프로젝트를 오랜만에 시작하려 했더니&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;일단 요새 리액트 프로젝트 시작은 Vite 아니면 Next로 하고 있는 것 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Svelte를 계속 써왔기 때문에 Vite로 리액트 프로젝트를 만들 수 있는 건 알고 있었는데&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;새로운 프로젝트를 시작해보려고 아래의 명령을 실행했습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1757633744882&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;npm create vite@latest&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프레임워크 선택 화면부터 뭐가 많네요.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;310&quot; data-origin-height=&quot;432&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qSsv5/btsQvPNLSJT/iWYGKOK711ecLTPON9z6AK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qSsv5/btsQvPNLSJT/iWYGKOK711ecLTPON9z6AK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qSsv5/btsQvPNLSJT/iWYGKOK711ecLTPON9z6AK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqSsv5%2FbtsQvPNLSJT%2FiWYGKOK711ecLTPON9z6AK%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;310&quot; height=&quot;432&quot; data-origin-width=&quot;310&quot; data-origin-height=&quot;432&quot;/&gt;&lt;/span&gt;&lt;/figure&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;&lt;br /&gt;아는 것 반 모르는 것 반이라 물어봤습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;각 웹 프레임워크에 대한 설명과 점유율, 성능, 추세를 요약하면 다음과 같습니다. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;Vanilla&lt;/b&gt;: 순수 자바스크립트로 프레임워크 없이 직접 개발하는 방식입니다. 가장 가볍고 성능이 뛰어나지만 규모가 커질수록 관리가 어려워집니다. 최근에는 코드 단순함과 빠른 초기 로딩 때문에 작고 빠른 앱에 다시 주목받는 추세입니다. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;Vue&lt;/b&gt;: 가볍고 배우기 쉽고 성능이 좋은 프레임워크로, 컴포넌트 기반 UI 개발에 강점이 있습니다. 커뮤니티와 생태계가 크며, 점유율은 꾸준히 높고 증가 추세입니다. 디렉티브와 반응성 시스템이 뛰어나며 빠른 렌더링을 지원합니다. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;React&lt;/b&gt;: 가장 인기 있는 프레임워크로, Virtual DOM으로 효율적인 UI 업데이트와 강력한 생태계를 자랑합니다. 점유율은 매우 높지만 규모가 커질수록 퍼포먼스 최적화가 필요합니다. Hooks 도입 이후 개발 경험이 크게 향상되었고, 전체적으로는 안정적인 성장세입니다. Preact: React와 API 호환되면서 크기를 크게 줄인 경량화 버전입니다. 모바일 등 리소스가 한정된 환경에서 성능이 좋고, 점유율은 React 대비 작지만 빠르게 성장하고 있습니다. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;Lit&lt;/b&gt;: Web Components 표준 기반으로 빠르고 가벼우며, 빌드 없이 바로 작동합니다. React 대비 16-30% 빠른 렌더링 성능이 특징이며 점차 관심이 늘고 있고 성장 중입니다. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;Svelte&lt;/b&gt;: 컴파일 타임에 대부분 작업을 처리해 가상 DOM 없이 빠른 렌더링을 제공합니다. 번들 크기가 작고 성능이 매우 뛰어나며, 학습 곡선이 완만하고 모바일 최적화에 강점이 있습니다. React 대비 빠르게 성장하는 추세입니다. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;Solid&lt;/b&gt;: React 스타일의 선언적 UI를 유지하면서도 세밀한 반응성으로 최고의 성능을 자랑합니다. React 대비 훨씬 빠른 실행 속도를 내며 점유율은 낮지만 주목받고 있습니다. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;Qwik&lt;/b&gt;: 최초 로딩 시 JS를 거의 보내지 않고 필요한 시점에만 JS를 실행하는 혁신적 접근법으로 극초기 로딩 속도가 매우 빠릅니다. 아직 초기 단계지만 퍼포먼스 중심으로 주목받고 있습니다. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;Angular&lt;/b&gt;: 구글이 지원하는 대형 프레임워크로 양방향 바인딩과 강력한 기능을 제공합니다. 대규모 앱에 적합하지만 무거움과 복잡성 문제로 인해 점유율이 다른 프레임워크 대비 주춤한 상태입니다. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;Marko&lt;/b&gt;: 서버 사이드 렌더링과 빠른 클라이언트 렌더링에 강점을 가진 프레임워크로, 주로 대형 웹사이트에 사용됩니다. 점유율은 낮지만 신뢰성 높은 성능을 제공합니다[추가 정보는 제한적]. &lt;br /&gt;&lt;br /&gt;요약하면 React와 Vue는 점유율이 가장 크고 안정적 성장세이며, Svelte와 Solid, Qwik은 최신 퍼포먼스 최적화 추세로 급성장하는 중입니다. Angular는 레거시 대형 프로젝트에 주로 쓰이고 있으며, Preact와 Lit는 경량화와 표준 호환을 무기로 점차 사용자가 늘어나고 있습니다.&lt;/blockquote&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 중에서는 Svelte, Sveltekit의 열렬한 지지자이기는 한데 최근에 운영중인 서비스를 React에서 Solid로 전환한다는 이야기를 본적이 있어서 Solid에 관심이 가더라고요. 비슷하기도 하고, 이쪽으로 전환하는 수요도 생기지 않을까 싶은 생각이들어 한 번 시작이라도 해보기로 했습니다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;838&quot; data-origin-height=&quot;90&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bTMqPr/btsQuTb1lwp/kQkQvpvth6BOqnpg17Cn11/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bTMqPr/btsQuTb1lwp/kQkQvpvth6BOqnpg17Cn11/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bTMqPr/btsQuTb1lwp/kQkQvpvth6BOqnpg17Cn11/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbTMqPr%2FbtsQuTb1lwp%2FkQkQvpvth6BOqnpg17Cn11%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;838&quot; height=&quot;90&quot; data-origin-width=&quot;838&quot; data-origin-height=&quot;90&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&quot;&lt;b&gt;TanStack Router&lt;/b&gt;&quot;는 React와 같은 자바스크립트 프레임워크에서 사용하는 최신 라우팅 라이브러리입니다. 타입스크립트 기반으로 강력한 타입 안전성을 제공하며, 파일 기반 라우팅(File-based Routing)을 지원해 파일을 생성하면 자동으로 URL 경로가 매핑되는 구조로 개발 효율성을 높이는 게 장점입니다. 또한 코드 분할, 중첩 레이아웃, 효율적 데이터 로딩 같은 고급 기능도 갖추고 있어 대규모 애플리케이션에도 적합합니다.&lt;br /&gt;&lt;br /&gt;명령어 &quot;npm create -- tsrouter-app@latest TARGET_DIR --framework Solid --interactive&quot;는 pnpm이나 npm을 이용해 TanStack Router 기반의 최신 샘플 프로젝트를 Solid 프레임워크를 사용하여 생성하는 방법입니다.&lt;br /&gt;&lt;br /&gt;- &quot;npm create&quot;는 최신 패키지 기반 템플릿 프로젝트를 생성하는 명령어입니다.&lt;br /&gt;- &quot;tsrouter-app@latest&quot;는 TanStack Router 관련 템플릿(보통 TypeScript 기반)을 지정합니다.&lt;br /&gt;- &quot;TARGET_DIR&quot;는 생성할 프로젝트 폴더 이름(경로)입니다.&lt;br /&gt;- &quot;--framework Solid&quot;는 React 대신 Solid라는 UI 프레임워크를 사용하겠다는 옵션입니다.&lt;br /&gt;- &quot;--interactive&quot;는 선택사항을 대화형으로 받아 설정할 수 있게 합니다.&lt;br /&gt;&lt;br /&gt;즉, 이 명령어는 Solid 프레임워크용 TanStack Router 기본 앱을 자동으로 설정하는 스크립트라 볼 수 있습니다. Solid 개발 환경에서 TanStack Router를 쉽게 시작할 때 사용합니다.&lt;/blockquote&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;&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;Sveltekit을 사용하면서 파일 라우팅에 길들여진 몸이라 File Router를 선택했습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;455&quot; data-origin-height=&quot;121&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/4ZYn5/btsQwfrSEGh/mqa88a92Mjsj82QupZ9aW0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/4ZYn5/btsQwfrSEGh/mqa88a92Mjsj82QupZ9aW0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/4ZYn5/btsQwfrSEGh/mqa88a92Mjsj82QupZ9aW0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F4ZYn5%2FbtsQwfrSEGh%2Fmqa88a92Mjsj82QupZ9aW0%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;455&quot; height=&quot;121&quot; data-origin-width=&quot;455&quot; data-origin-height=&quot;121&quot;/&gt;&lt;/span&gt;&lt;/figure&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;테일윈드는 쓰지 않는 것으로 결정했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한참 열심히 쓰던 때가 있었는데 요즘은 AI가 CSS를 잘 만들어주기도 하고&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;그 때 가서 고치기에는 너무 늦습니다.&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;그런 의미에선 Lit을 쓰는 것이 제 방향성과 맞기는 한데요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;요거는 나중에 한 번 시도해보겠습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;328&quot; data-origin-height=&quot;52&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dWEoAK/btsQu3rV6z6/MBI2INoFnxFF2b6ohRjV4K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dWEoAK/btsQu3rV6z6/MBI2INoFnxFF2b6ohRjV4K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dWEoAK/btsQu3rV6z6/MBI2INoFnxFF2b6ohRjV4K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdWEoAK%2FbtsQu3rV6z6%2FMBI2INoFnxFF2b6ohRjV4K%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;328&quot; height=&quot;52&quot; data-origin-width=&quot;328&quot; data-origin-height=&quot;52&quot;/&gt;&lt;/span&gt;&lt;/figure&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;또 새로운 것이 나왔습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;180&quot; data-origin-height=&quot;85&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/WS6c5/btsQwQ6pER9/cbCBMMvoDWG6of3ECys1r1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/WS6c5/btsQwQ6pER9/cbCBMMvoDWG6of3ECys1r1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/WS6c5/btsQwQ6pER9/cbCBMMvoDWG6of3ECys1r1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FWS6c5%2FbtsQwQ6pER9%2FcbCBMMvoDWG6of3ECys1r1%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;180&quot; height=&quot;85&quot; data-origin-width=&quot;180&quot; data-origin-height=&quot;85&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;위의 툴체인 선택 화면은 개발 환경에서 코드 품질과 스타일 검사를 위해 선택할 수 있는 도구 목록입니다. 각 항목에 대해 설명드리면 다음과 같습니다. &lt;br /&gt;&lt;br /&gt;- &lt;b&gt;None&lt;/b&gt;: 별도의 코드 스타일이나 검사 도구를 사용하지 않음을 의미합니다.&lt;br /&gt;- &lt;b&gt;Biome&lt;/b&gt;: 코드 포맷팅과 정적 분석 기능을 제공하는 도구로, JavaScript 및 TypeScript 코드의 스타일과 품질을 관리합니다. ESLint와 비슷한 역할을 수행하지만 좀 더 통합된 환경을 제공합니다. &lt;br /&gt;- &lt;b&gt;ESLint&lt;/b&gt;: 가장 널리 사용되는 JavaScript/TypeScript 정적 코드 분석 도구입니다. 코드의 문법 오류, 스타일 문제, 버그 가능성 등을 검사하여 개발자가 더 안정적이고 일관성 있는 코드를 작성하도록 돕습니다. &lt;br /&gt;&lt;br /&gt;즉, 이 툴체인 선택은 Solid 같은 프레임워크 프로젝트를 만들 때 사용할 코드 스타일 검사 및 정적 분석 도구를 결정하는 단계입니다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;써본 적은 없지만 Biome을 선택했습니다.&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;Clerk, Chadcn, MCP, Sentry를 빼고는 뭔지 잘 모르겠습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;487&quot; data-origin-height=&quot;311&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bu8Iu3/btsQvxmf0sL/NwkxBB6PtpVGPZ2Yr5KPM1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bu8Iu3/btsQvxmf0sL/NwkxBB6PtpVGPZ2Yr5KPM1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bu8Iu3/btsQvxmf0sL/NwkxBB6PtpVGPZ2Yr5KPM1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbu8Iu3%2FbtsQvxmf0sL%2FNwkxBB6PtpVGPZ2Yr5KPM1%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;487&quot; height=&quot;311&quot; data-origin-width=&quot;487&quot; data-origin-height=&quot;311&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;각 애드온(add-on)의 설명과 필요한지 여부는 다음과 같습니다:&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Clerk&lt;/b&gt;: 사용자 인증(로그인, 회원가입, 세션 관리 등)을 쉽게 추가할 수 있는 도구입니다. 인증 기능이 필요하면 꼭 선택하세요.&lt;br /&gt;&lt;b&gt;Convex&lt;/b&gt;: 현재 정보에서는 구체적 정의가 없지만, 일반적으로 Convex는 볼록 최적화 관련 용어이며, 애드온 맥락에선 특정 서비스일 수 있어 추가 확인 필요합니다.&lt;br /&gt;&lt;b&gt;DB&lt;/b&gt;: 데이터베이스 관련 기능(저장, 조회)을 추가합니다. 애플리케이션에서 데이터 저장이 필요하면 선택합니다.&lt;br /&gt;&lt;b&gt;Form&lt;/b&gt;: 폼 관리 기능을 제공합니다. 사용자 입력 폼이 필요한 경우 유용합니다.&lt;br /&gt;&lt;b&gt;MCP:&lt;/b&gt; 대규모 언어 모델(AI)과 외부 데이터/시스템 연결을 위한 표준 프로토콜입니다. AI 모델과 연결할 때 필요합니다.&lt;br /&gt;&lt;b&gt;Neon&lt;/b&gt;: 서버리스(Postgres) 데이터베이스 서비스로, 서버리스 환경의 안정적인 DB가 필요할 때 선택합니다.&lt;br /&gt;&lt;b&gt;Netlify&lt;/b&gt;: 배포 및 서버리스 백엔드 서비스입니다. 정적 사이트나 웹앱을 쉽게 배포하려면 선택합니다.&lt;br /&gt;&lt;b&gt;oRPC&lt;/b&gt;: 타입 안전한 API 개발 도구로, 타입스크립트 기반에서 안전하게 API를 구축하려면 선택합니다.&lt;br /&gt;&lt;b&gt;Sentry&lt;/b&gt;: 오류 추적 및 성능 모니터링 도구로, 앱 안정성 확보가 필요하면 필수입니다.&lt;br /&gt;&lt;b&gt;Shadcn&lt;/b&gt;: UI 컴포넌트 라이브러리일 가능성이 큽니다. UI 개발을 빠르게 하려면 도움이 됩니다.&lt;br /&gt;&lt;b&gt;Start&lt;/b&gt;: 프로젝트 초기 설정 및 구동에 관련된 애드온일 가능성이 높습니다.&lt;br /&gt;&lt;b&gt;Store&lt;/b&gt;: 상태 관리 라이브러리입니다. 애플리케이션 상태를 관리할 때 필요합니다.&lt;br /&gt;&lt;b&gt;T3Env&lt;/b&gt;: 환경변수 관리 도구로, 여러 환경에서 앱 실행 시 환경변수를 쉽게 관리합니다.&lt;br /&gt;&lt;b&gt;tRPC&lt;/b&gt;: 타입 안전한 원격 프로시저 호출(RPC) 라이브러리로, 프론트엔드와 백엔드 간 타입 안전 API 통신에 유용합니다.&lt;br /&gt;&lt;b&gt;Table&lt;/b&gt;: 데이터 테이블 컴포넌트 또는 기능을 추가합니다. 테이블 UI가 필요할 때 선택합니다.&lt;br /&gt;&lt;b&gt;Query&lt;/b&gt;: 데이터 쿼리 및 캐싱 기능을 제공하는 라이브러리로, 서버 상태 관리에 쓰입니다.&lt;br /&gt;&lt;br /&gt;필요한 애드온은 프로젝트 목적에 따라 다릅니다. 예를 들어, 인증이 필요하면 Clerk, 데이터 저장이 필요하면 DB/Neon, 에러 모니터링은 Sentry, 타입 안전 API는 oRPC 또는 tRPC, UI 컴포넌트는 Shadcn, 상태 관리는 Store에 선택하면 됩니다. 배포는 Netlify가 편리합니다. 폼 입력이 많다면 Form을 고려하세요.&lt;/blockquote&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;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1232&quot; data-origin-height=&quot;66&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nd43h/btsQvBoEVrT/SJPrxeXndeuwofuECYNqeK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nd43h/btsQvBoEVrT/SJPrxeXndeuwofuECYNqeK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nd43h/btsQvBoEVrT/SJPrxeXndeuwofuECYNqeK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fnd43h%2FbtsQvBoEVrT%2FSJPrxeXndeuwofuECYNqeK%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;1232&quot; height=&quot;66&quot; data-origin-width=&quot;1232&quot; data-origin-height=&quot;66&quot;/&gt;&lt;/span&gt;&lt;/figure&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;Solid를 어떻게 사용하는지 참고하려고 선택했습니다.&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;885&quot; data-origin-height=&quot;909&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bN2Baj/btsQt9fbJWb/UgdP78HnffkoleysDoPqQK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bN2Baj/btsQt9fbJWb/UgdP78HnffkoleysDoPqQK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bN2Baj/btsQt9fbJWb/UgdP78HnffkoleysDoPqQK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbN2Baj%2FbtsQt9fbJWb%2FUgdP78HnffkoleysDoPqQK%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;885&quot; height=&quot;909&quot; data-origin-width=&quot;885&quot; data-origin-height=&quot;909&quot;/&gt;&lt;/span&gt;&lt;/figure&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;프로젝트 생성의 전체 과정입니다.&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;프로젝트 폴더로 이동해서 README.md 파일을 보니&amp;nbsp;.env 파일에 ANTHROPIC_API_KEY를 넣으라고 합니다.&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;혹시 pnpm을 설치하지 않으셨다면 먼저 설치해주시기 바랍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1757636812085&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;npm install -g pnpm&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;&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;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1757636835130&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;pnpm install&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1032&quot; data-origin-height=&quot;1090&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bgBwOi/btsQt2Alc0S/MfNIWdDPbb3v7TBSWDcsX0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bgBwOi/btsQt2Alc0S/MfNIWdDPbb3v7TBSWDcsX0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bgBwOi/btsQt2Alc0S/MfNIWdDPbb3v7TBSWDcsX0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbgBwOi%2FbtsQt2Alc0S%2FMfNIWdDPbb3v7TBSWDcsX0%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;1032&quot; height=&quot;1090&quot; data-origin-width=&quot;1032&quot; data-origin-height=&quot;1090&quot;/&gt;&lt;/span&gt;&lt;/figure&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;&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;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1757636893053&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;pnpm run dev&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;569&quot; data-origin-height=&quot;247&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/GKcWK/btsQt9sJ3wP/YYxj88Rj2bZYwtx8W6m7D1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/GKcWK/btsQt9sJ3wP/YYxj88Rj2bZYwtx8W6m7D1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/GKcWK/btsQt9sJ3wP/YYxj88Rj2bZYwtx8W6m7D1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FGKcWK%2FbtsQt9sJ3wP%2FYYxj88Rj2bZYwtx8W6m7D1%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;569&quot; height=&quot;247&quot; data-origin-width=&quot;569&quot; data-origin-height=&quot;247&quot;/&gt;&lt;/span&gt;&lt;/figure&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;&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;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1757637134681&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;http://localhost:3000/&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;883&quot; data-origin-height=&quot;845&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qfMPI/btsQwQFk6O8/7yRlIkN1zzjzztkLFO00M1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qfMPI/btsQwQFk6O8/7yRlIkN1zzjzztkLFO00M1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qfMPI/btsQwQFk6O8/7yRlIkN1zzjzztkLFO00M1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqfMPI%2FbtsQwQFk6O8%2F7yRlIkN1zzjzztkLFO00M1%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;883&quot; height=&quot;845&quot; data-origin-width=&quot;883&quot; data-origin-height=&quot;845&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1057&quot; data-origin-height=&quot;1070&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ctyMQz/btsQxboYscf/o02KhxJehMKNjXPlmmjvJK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ctyMQz/btsQxboYscf/o02KhxJehMKNjXPlmmjvJK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ctyMQz/btsQxboYscf/o02KhxJehMKNjXPlmmjvJK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FctyMQz%2FbtsQxboYscf%2Fo02KhxJehMKNjXPlmmjvJK%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;1057&quot; height=&quot;1070&quot; data-origin-width=&quot;1057&quot; data-origin-height=&quot;1070&quot;/&gt;&lt;/span&gt;&lt;/figure&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로젝트를 열어보니 역시 생김새는 React와 비슷한 느낌이네요.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1373&quot; data-origin-height=&quot;1255&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cW9e6U/btsQv02Llhg/43aPeYKOdQJxiOOFuksdXk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cW9e6U/btsQv02Llhg/43aPeYKOdQJxiOOFuksdXk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cW9e6U/btsQv02Llhg/43aPeYKOdQJxiOOFuksdXk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcW9e6U%2FbtsQv02Llhg%2F43aPeYKOdQJxiOOFuksdXk%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;1373&quot; height=&quot;1255&quot; data-origin-width=&quot;1373&quot; data-origin-height=&quot;1255&quot;/&gt;&lt;/span&gt;&lt;/figure&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;example에서 TanStack Chat을 선택하면서 그 전의 선택들이 무색하게 되어버렸네요.&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;실행 화면을 보니 뭔가 백엔드가 포함된 느낌이라 찾아보니 TanStack Start가 풀스택 프레임워크를 만들어준다고 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Next 대신 사용하면 될 것 같기도 한데 개인적으로 Next든 Sveltekit이든 SSR 용도까지는 괜찮다고 생각해도&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이걸로 DB에 접근하거나 본격적으로 백엔드로 사용하는 건 좀 불안한 면이 있다고 생각합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(ASP.NET을 했던 입장으로 할 말이 아닌거 같기는 하지만;)&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;라이브러리의 불안전한 부분에서 발생하건 사용자의 실수로 발생하건 API 키를 노출하게 되거나 다른 문제들을 유발할 수 있다고 생각해서 개인적으로는 프론트와 백엔드는 분리되어야 한다고 생각하고 있습니다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예제 프로젝트에서 쓰인 TanStack이 무엇인지 궁금해서 자료를 더 찾아봤습니다.&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://tanstack.com/&quot;&gt;https://tanstack.com/&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1757638668232&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;TanStack | High Quality Open-Source Software for Web Developers&quot; data-og-description=&quot;Headless, type-safe, powerful utilities for complex workflows like Data Management, Data Visualization, Charts, Tables, and UI Components.&quot; data-og-host=&quot;tanstack.com&quot; data-og-source-url=&quot;https://tanstack.com/&quot; data-og-url=&quot;https://tanstack.com/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/buWjQ8/hyZIYhhAd4/WSUqLCEpWgYhptkoP7H00K/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/bntxNm/hyZIXJqgoe/k4k0sUPleNzQS4A0UoHw6K/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/f1bmQ/hyZI0lPKb6/Wh3CVgWkX34juRpncyVOQ1/img.png?width=500&amp;amp;height=500&amp;amp;face=0_0_500_500&quot;&gt;&lt;a href=&quot;https://tanstack.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://tanstack.com/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/buWjQ8/hyZIYhhAd4/WSUqLCEpWgYhptkoP7H00K/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/bntxNm/hyZIXJqgoe/k4k0sUPleNzQS4A0UoHw6K/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/f1bmQ/hyZI0lPKb6/Wh3CVgWkX34juRpncyVOQ1/img.png?width=500&amp;amp;height=500&amp;amp;face=0_0_500_500');&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;TanStack | High Quality Open-Source Software for Web Developers&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Headless, type-safe, powerful utilities for complex workflows like Data Management, Data Visualization, Charts, Tables, and UI Components.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;tanstack.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;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;b&gt;TanStack 라이브러리 생태계&lt;/b&gt;&lt;br /&gt;TanStack은 웹 개발을 위한 강력한 오픈소스 라이브러리 모음집으로, 헤드리스하고 타입 안전한 유틸리티들을 제공합니다. 각 라이브러리는 특정 도메인에 특화되어 있으며, 높은 성능과 개발자 경험을 중시하여 개발되었습니다.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;TanStack Query (구 React Query)&lt;br /&gt;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;용도&lt;/b&gt;&lt;br /&gt;서버 상태 관리를 위한 라이브러리로, 웹 애플리케이션에서 서버 데이터 가져오기, 캐싱, 동기화, 업데이트를 간편하게 처리합니다.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;주요 기능&lt;/b&gt;&lt;br /&gt;- 데이터 캐싱 및 재사용: 동일한 queryKey로 요청된 데이터를 캐시에서 재사용&lt;br /&gt;- 자동 백그라운드 갱신: 데이터가 stale 상태가 되면 자동으로 서버에서 새 데이터를 가져옴&lt;br /&gt;- 간편한 상태 관리: isLoading, isPending, isError 등의 상태를 자동으로 관리&lt;br /&gt;- 무한 스크롤: useInfiniteQuery 훅으로 무한 스크롤 구현 지원&lt;br /&gt;- 쿼리 재시도: 요청 실패 시 기본적으로 3번 재시도&lt;br /&gt;&lt;br /&gt;&lt;b&gt;장점&lt;/b&gt;&lt;br /&gt;- 반복적인 데이터 fetching 코드 감소&lt;br /&gt;- 서버와 클라이언트 간 데이터 동기화 최적화&lt;br /&gt;- 캐싱을 통한 불필요한 API 호출 방지&lt;br /&gt;- 무한 스크롤, 쿼리 취소, 오프라인 mutation 지원&lt;br /&gt;&lt;br /&gt;&lt;b&gt;단점&lt;/b&gt;&lt;br /&gt;- SWR(4.2kB)에 비해 번들 크기가 큰 편(11.4kB)&lt;br /&gt;- 기능이 많아 초기 학습 곡선이 있을 수 있음&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;TanStack Router&lt;br /&gt;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;용도&lt;/b&gt;&lt;br /&gt;타입 안전한 파일 시스템 기반 라우팅을 제공하는 React 라우터 라이브러리.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;주요 기능&lt;/b&gt;&lt;br /&gt;- 파일 기반 라우팅: Next.js처럼 직관적인 디렉토리 구조 기반 라우팅&lt;br /&gt;- 타입 안전성: TypeScript와 완벽 통합되어 런타임 오류 방지&lt;br /&gt;- 자동 코드 분할: Critical과 Non-Critical 라우트 구분으로 성능 최적화&lt;br /&gt;- 자동 완성: Link 컴포넌트의 to 속성에서 경로 자동 완성 지원&lt;br /&gt;&lt;br /&gt;&lt;b&gt;장점&lt;/b&gt;&lt;br /&gt;- 컴파일 시점에 라우팅 오류 감지&lt;br /&gt;- 초기 로딩 시 필요한 리소스만 로드하여 성능 개선&lt;br /&gt;- React Router보다 간편하고 빠른 개발&lt;br /&gt;- 중첩 라우팅과 레이아웃 관리 용이&lt;br /&gt;&lt;br /&gt;&lt;b&gt;단점&lt;/b&gt;&lt;br /&gt;- 상대적으로 새로운 라이브러리로 커뮤니티 생태계가 작음&lt;br /&gt;- 기존 React Router 코드 마이그레이션 비용&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;TanStack Table&lt;br /&gt;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;용도&lt;/b&gt;&lt;br /&gt;강력한 테이블과 데이터그리드 생성을 위한 헤드리스 라이브러리.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;주요 기능&lt;/b&gt;&lt;br /&gt;- 컬럼 관리: 정렬, 필터링, 그룹화, 순서 변경, 크기 조절&lt;br /&gt;- 행 관리: 선택, 확장/축소, 페이지네이션, 고정&lt;br /&gt;- 전역 기능: 전체 테이블 검색, 필터링&lt;br /&gt;- 가상화 지원: TanStack Virtual과 연동하여 대용량 데이터 처리&lt;br /&gt;&lt;br /&gt;&lt;b&gt;장점&lt;/b&gt;&lt;br /&gt;거의 모든 형태의 테이블 구현 가능&lt;br /&gt;- 헤드리스 설계로 자유로운 스타일링&lt;br /&gt;- 높은 성능과 개발자 경험 중시&lt;br /&gt;- React, Vue, Solid 등 다양한 프레임워크 지원&lt;br /&gt;&lt;br /&gt;&lt;b&gt;단점&lt;/b&gt;&lt;br /&gt;- 문서화가 완벽하지 않아 학습에 시간 소요&lt;br /&gt;- 데이터나 컬럼 참조 변경 시 무한 렌더링 주의 필요&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;TanStack Virtual&lt;br /&gt;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;용도&lt;/b&gt;&lt;br /&gt;대용량 리스트의 가상 스크롤링을 통한 성능 최적화 라이브러리.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;주요 기능&lt;/b&gt;&lt;br /&gt;가상화: 화면에 보이는 요소만 렌더링하여 DOM 수 최소화&lt;br /&gt;동적 높이: 각기 다른 높이를 가진 리스트 아이템 지원&lt;br /&gt;스크롤 제어: scrollToOffset, scrollToIndex 함수 제공&lt;br /&gt;&lt;br /&gt;&lt;b&gt;장점&lt;/b&gt;&lt;br /&gt;- 수만 개 아이템도 원활한 성능 보장&lt;br /&gt;- 동적 높이 지원으로 유연한 레이아웃 구현&lt;br /&gt;- 메모리 사용량 최소화&lt;br /&gt;&lt;br /&gt;&lt;b&gt;단점&lt;/b&gt;&lt;br /&gt;- 구현 복잡도가 높아 초기 설정 시간 소요&lt;br /&gt;- 기존 라이브러리 대비 생태계가 작음&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;TanStack Form&lt;br /&gt;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;용도&lt;/b&gt;&lt;br /&gt;타입 안전한 폼 상태 관리 라이브러리.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;주요 기능&lt;/b&gt;&lt;br /&gt;- 제어된 입력: 모든 폼 필드를 제어 상태로 관리&lt;br /&gt;- 유효성 검사: 고급 유효성 검사 기능과 비동기 검증 지원&lt;br /&gt;- 타입 안전성: TypeScript와 완벽 통합&lt;br /&gt;&lt;br /&gt;&lt;b&gt;장점&lt;/b&gt;&lt;br /&gt;- React Hook Form 대비 더 깔끔한 상태 관리&lt;br /&gt;- 예측 가능한 제어된 입력 방식&lt;br /&gt;- 복잡한 폼 요구사항 충족 가능&lt;br /&gt;&lt;br /&gt;&lt;b&gt;단점&lt;/b&gt;&lt;br /&gt;- React Hook Form에 비해 상대적으로 새로운 라이브러리&lt;br /&gt;- 제어된 입력만 지원하여 비제어 폼 방식 사용 불가&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;TanStack Start&lt;br /&gt;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;용도&lt;/b&gt;&lt;br /&gt;TanStack Router 기반의 풀스택 React 프레임워크 (현재 베타).&lt;br /&gt;&lt;br /&gt;&lt;b&gt;주요 기능&lt;/b&gt;&lt;br /&gt;- 서버 사이드 렌더링: 완전한 문서 SSR과 스트리밍&lt;br /&gt;- 서버 함수: 서버 측 로직 실행 지원&lt;br /&gt;- 번들링: Vite, Nitro 등 통합&lt;br /&gt;&lt;br /&gt;&lt;b&gt;장점&lt;/b&gt;&lt;br /&gt;- 타입 안전한 풀스택 개발 환경&lt;br /&gt;- Next.js의 대안으로 부상&lt;br /&gt;- TanStack 생태계와의 완벽한 통합&lt;br /&gt;&lt;br /&gt;&lt;b&gt;단점&lt;/b&gt;&lt;br /&gt;- 아직 베타 버전으로 프로덕션 사용에 제한&lt;br /&gt;- Next.js 대비 생태계와 커뮤니티가 작음&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;TanStack Store&lt;br /&gt;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;용도&lt;/b&gt;&lt;br /&gt;외부 스토어 상태 관리를 위한 경량 라이브러리.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;주요 기능&lt;/b&gt;&lt;br /&gt;- 간단한 상태 관리: 전통적인 액션이나 리듀서 없이 useState처럼 사용&lt;br /&gt;- 함수형 업데이트: 함수 업데이트만으로 상태 변경&lt;br /&gt;&lt;br /&gt;&lt;b&gt;장점&lt;/b&gt;&lt;br /&gt;- 매우 간단한 API로 쉬운 학습&lt;br /&gt;- 작은 번들 크기&lt;br /&gt;- Redux나 Zustand의 대안&lt;br /&gt;&lt;br /&gt;&lt;b&gt;단점&lt;/b&gt;&lt;br /&gt;- 상대적으로 새로운 라이브러리로 검증 부족&lt;br /&gt;- 복잡한 상태 관리에는 제한적일 수 있음&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;TanStack 생태계는 각 도메인별로 특화된 강력한 도구들을 제공하며, 모든 라이브러리가 타입 안전성과 성능을 중시하여 개발되었습니다. 특히 헤드리스 설계를 통해 높은 자유도를 제공하며, 현대적인 웹 개발 트렌드에 부합하는 솔루션들을 제공합니다.&lt;/blockquote&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;
&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;폭발적인 생태계가 계속 폭발을 거듭하는 느낌입니다.&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;요즈음에 느끼는건데&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;한국 시장 안에서는 대중적이지 않으면 선택받기가 쉽지 않네요.&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;br /&gt;일단 자바 스프링과 리액트로 프로젝트를 하나 진행해보고&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; 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;&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>
      <author>cellaxon</author>
      <guid isPermaLink="true">https://cellaxon.tistory.com/35</guid>
      <comments>https://cellaxon.tistory.com/35#entry35comment</comments>
      <pubDate>Fri, 12 Sep 2025 11:15:37 +0900</pubDate>
    </item>
    <item>
      <title>Vision Model Tester(YOLOv9, RF-DETR ONNX Model Test)</title>
      <link>https://cellaxon.tistory.com/34</link>
      <description>&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 id=&quot;ember135&quot; style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;지난 게시물(Rust에서 RF-DETR ONNX 모델을 사용한 이미지 객체 식별)에서 모델만 YOLOv9로 변경해서 테스트 해보려는 목적으로 시작했는데 주섬주섬 이 기능 저 기능들을 넣다보니 RF-DETR 모델을 넣는데까지 왔습니다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p id=&quot;ember136&quot; style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;바이브 코딩으로 여기까지 올 수 있다는게 놀랍기도 하지만 그 중간 과정에서 실패도 많았습니다. 특히 단계별로 만들어갈 때 어느 순간 잘 동작하는 코드를 날려버린다던지 자꾸 의도하지 않은 방향으로 틀어버리거나 몇 차례 시도 후 안되면 싹 갈아 엎어버리는 행동을 보여서 다시 시도해보기를 반복했네요. 그 덕에 토큰이 녹아내려서 Auto로 바꿔서 작업을 했더니 점점 쓸모 없는 코드만 찍어내더라구요.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p id=&quot;ember137&quot; style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;여기까지의 테스트는 지금 준비하고 있는 서비스를 본격적으로 시작하기 전에 해본 가벼운 테스트입니다. 비전 모델에 대한 테스트는 여기까지로 마무리짓고 본 경기를 시작할 예정이예요.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p id=&quot;ember138&quot; style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;여기까지의 작업물이 Rust로 유사한 작업을 해보려는 분들께 도움이 되었으면 합니다.&lt;/p&gt;
&lt;p id=&quot;ember139&quot; style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p id=&quot;ember140&quot; style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;프로젝트를 받으시려면 아래의 사이트에 방문하시면 됩니다.&lt;/p&gt;
&lt;p id=&quot;ember141&quot; style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/cellaxon/vision_model_tester&quot;&gt;https://github.com/cellaxon/vision_model_tester&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1754973455953&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 - cellaxon/vision_model_tester&quot; data-og-description=&quot;Contribute to cellaxon/vision_model_tester development by creating an account on GitHub.&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/cellaxon/vision_model_tester&quot; data-og-url=&quot;https://github.com/cellaxon/vision_model_tester&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/xYDlk/hyZylic7mC/Lf4kRKxLXKz1r9yW1PkIB1/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/cOgigL/hyZyrbFmMP/rJ10Ezr33jbuEDmBwxB950/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/cellaxon/vision_model_tester&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/cellaxon/vision_model_tester&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/xYDlk/hyZylic7mC/Lf4kRKxLXKz1r9yW1PkIB1/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/cOgigL/hyZyrbFmMP/rJ10Ezr33jbuEDmBwxB950/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 - cellaxon/vision_model_tester&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Contribute to cellaxon/vision_model_tester 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;pre id=&quot;code_1754973471661&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;git clone https://github.com/cellaxon/vision_model_tester&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;&lt;br /&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;모델 파일은 아래의 명령을 사용해서 받으세요.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1754973499740&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 1) 디렉토리 생성
mkdir -p assets/models/yolov9 assets/models/rf-detr

# 2) YOLOv9 모델 다운로드
curl -L -o assets/models/yolov9/gelan-c.onnx https://huggingface.co/Xenova/yolov9-onnx/resolve/main/gelan-c.onnx
curl -L -o assets/models/yolov9/yolov9-c.onnx https://huggingface.co/Xenova/yolov9-onnx/resolve/main/yolov9-c.onnx
# 선택적으로 추가 다운로드
curl -L -o assets/models/yolov9/gelan-e.onnx https://huggingface.co/Xenova/yolov9-onnx/resolve/main/gelan-e.onnx
curl -L -o assets/models/yolov9/yolov9-e.onnx https://huggingface.co/Xenova/yolov9-onnx/resolve/main/yolov9-e.onnx

# 3) RF-DETR 모델 다운로드
curl -L -o assets/models/rf-detr/rf-detr.onnx https://huggingface.co/onnx-community/rfdetr_base-ONNX/resolve/main/onnx/model.onnx&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;ONNX Runtime이 없다면 아래의 명령을 사용해서 설치하시면 됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1754973523695&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;pip install onnxruntime&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;제가 테스트한 환경은 아래와 같습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Python 3.9.22&lt;/li&gt;
&lt;li&gt;Rust 1.88.0&lt;/li&gt;
&lt;li&gt;macOS Sequoia 15.6, Windows 10, Windows 11&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2025-08-12 오후 12.11.57.png&quot; data-origin-width=&quot;2036&quot; data-origin-height=&quot;1241&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/pYvvC/btsPNH4HWeo/amjeBtrqRa3jtzcGqgpuLK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/pYvvC/btsPNH4HWeo/amjeBtrqRa3jtzcGqgpuLK/img.png&quot; data-alt=&quot;YOLOv9-E&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/pYvvC/btsPNH4HWeo/amjeBtrqRa3jtzcGqgpuLK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FpYvvC%2FbtsPNH4HWeo%2FamjeBtrqRa3jtzcGqgpuLK%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;2036&quot; height=&quot;1241&quot; data-filename=&quot;스크린샷 2025-08-12 오후 12.11.57.png&quot; data-origin-width=&quot;2036&quot; data-origin-height=&quot;1241&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;YOLOv9-E&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2025-08-12 오후 12.46.10.png&quot; data-origin-width=&quot;2037&quot; data-origin-height=&quot;1241&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dXfbxl/btsPRmktfZX/dpeRxM7JEikuKmJNyZnJzk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dXfbxl/btsPRmktfZX/dpeRxM7JEikuKmJNyZnJzk/img.png&quot; data-alt=&quot;RF-DETR&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dXfbxl/btsPRmktfZX/dpeRxM7JEikuKmJNyZnJzk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdXfbxl%2FbtsPRmktfZX%2FdpeRxM7JEikuKmJNyZnJzk%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;2037&quot; height=&quot;1241&quot; data-filename=&quot;스크린샷 2025-08-12 오후 12.46.10.png&quot; data-origin-width=&quot;2037&quot; data-origin-height=&quot;1241&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;RF-DETR&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;잘 되시기를 바랍니다.&lt;/span&gt;&lt;/p&gt;</description>
      <category>프로그래밍/Rust</category>
      <author>cellaxon</author>
      <guid isPermaLink="true">https://cellaxon.tistory.com/34</guid>
      <comments>https://cellaxon.tistory.com/34#entry34comment</comments>
      <pubDate>Tue, 12 Aug 2025 13:41:43 +0900</pubDate>
    </item>
    <item>
      <title>Rust에서 RF-DETR ONNX 모델을 사용한 이미지 객체 식별</title>
      <link>https://cellaxon.tistory.com/33</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;이전 프로젝트에서 YOLOX를 사용해볼 수 있는 기회가 있었습니다. 당시에 Rust로 프로젝트를 제작하고 있었기 때문에 PyTorch로 학습된 모델을 Rust에서 돌려보기위해 여러 방법들을 시도해보았습니다. 이 때 ONNX을 알게 되어 onnx로 모델을 변환하고 실행하는 시도도 해보았습니다. 최종적으로는 속도 차이로 tch-rs(파이토치 러스트 바인딩)을 사용하여 실행하는 것으로 결론을 내렸습니다. 당시에 아쉬웠던 부분은 YOLOX의 동작 속도였는데요. 우연찮게 LinkedIn에서 Roboflow의 RF-DETR 에 대한 게시물을 발견하게 되었고 나중에 기회가 되면 써봐야지 했습니다.&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;&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;프로젝트에서 ONNX 모델을 사용할 예정이기 때문에 ONNX Runtime 설치가 필요합니다.&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;a href=&quot;https://onnxruntime.ai/&quot;&gt;https://onnxruntime.ai/&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기에서는 macOS에서 사용하는 것을 가정하고 있으므로 아래의 명령어를 사용하여 설치하시기 바랍니다.&lt;/p&gt;
&lt;pre id=&quot;code_1753936191980&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;pip install onnxruntime&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;&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;a href=&quot;https://github.com/cellaxon/rf_detr_onnx_test&quot;&gt;https://github.com/cellaxon/rf_detr_onnx_test&lt;/a&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1753936278555&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;git clone https://github.com/cellaxon/rf_detr_onnx_test
cd rf_detr_onnx_test&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;&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;아래의 사이트에 방문하셔서 model.onnx 파일을 다운로드 받으시기 바랍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://huggingface.co/onnx-community/rfdetr_base-ONNX/tree/main/onnx&quot;&gt;https://huggingface.co/onnx-community/rfdetr_base-ONNX/tree/main/onnx&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;rf_detr_onnx_test 폴더 하위에 assets/models 폴더를 생성하시고&lt;br /&gt;다운로드 받으신 모델 파일을 복사해주세요&lt;/p&gt;
&lt;pre id=&quot;code_1753936426163&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# assets/models 폴더 생성 (없는 경우)
mkdir -p assets/models

# 모델 파일을 assets/models/model.onnx로 이동
mv ~/Downloads/model.onnx assets/models/&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 실행해보겠습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1753936498460&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;cargo run --release&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;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1202&quot; data-origin-height=&quot;831&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/labrH/btsPENW2r3R/mPLnkudmprfmToGwRwGvRK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/labrH/btsPENW2r3R/mPLnkudmprfmToGwRwGvRK/img.png&quot; data-alt=&quot;프로그램 실행 화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/labrH/btsPENW2r3R/mPLnkudmprfmToGwRwGvRK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlabrH%2FbtsPENW2r3R%2FmPLnkudmprfmToGwRwGvRK%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;1202&quot; height=&quot;831&quot; data-origin-width=&quot;1202&quot; data-origin-height=&quot;831&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;프로그램 실행 화면&lt;/figcaption&gt;
&lt;/figure&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;추론을 시작하려면 좌측 상단의 Select Image 버튼을 누른 다음 대상 이미지를 선택하시면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1205&quot; data-origin-height=&quot;1349&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cjWfgn/btsPEOIpGhW/OOGAYvDyts28BXqyV0tDRk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cjWfgn/btsPEOIpGhW/OOGAYvDyts28BXqyV0tDRk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cjWfgn/btsPEOIpGhW/OOGAYvDyts28BXqyV0tDRk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcjWfgn%2FbtsPEOIpGhW%2FOOGAYvDyts28BXqyV0tDRk%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;1205&quot; height=&quot;1349&quot; data-origin-width=&quot;1205&quot; data-origin-height=&quot;1349&quot;/&gt;&lt;/span&gt;&lt;/figure&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;잘 되시나요?&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;처음에는 터미널에서 실행하고 파일로 이미지를 출력하는 형태로 만들었는데 아무래도 결과를 바로 볼 수 있는 편이 좋을 것 같아 GUI를 붙이고 이것저것 테스트하면서 뜯어고치다보니 여기까지 왔습니다.&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;GUI는 Dioxus를 써보려했으나 Cursor가 몇 번 시도 후에 egui로 방향을 틀어버리더라고요. 익숙해서 좋긴했지만 Dioxus는 언제 써볼 수 있을런지 모르겠습니다. AI가 스스로 포기하는 걸 보면 아직 쓰면 안될 것 같기도 하고요.&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;처음에는 출력하는 ID가 COCO class 인 줄 알았는데 아니었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;고양이가 개로 나오고 개는 말로 표시되는 문제가..&lt;br /&gt;아래의 파일을 참고하시면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://huggingface.co/onnx-community/rfdetr_base-ONNX/blob/main/config.json&quot;&gt;https://huggingface.co/onnx-community/rfdetr_base-ONNX/blob/main/config.json&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;모델이 입력받는 이미지의 크기가 560x560으로 고정되어 있어 입력으로 넣는 이미지를 비율 그대로 축소해서 넣은 다음 추론을 실행하고 결과를 다시 원본 이미지의 위치로 변환한 뒤에 표시해주도록 만들었습니다.&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;아무래도 Rust에서 이런 작업을 하시는 분들이 없어서인지 여기까지 오는데 생각보다 애로 사항이 많았습니다만 다행히 여기까지 만들 수 있었습니다.&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;이 다음으로 뭔가 만들게 된다면 영상 파일이나 카메라 영상을 OpenCV로 읽어서 실시간 추론을 해보면 좋을 것 같네요.&lt;/p&gt;</description>
      <category>프로그래밍/Rust</category>
      <category>egui</category>
      <category>onnx</category>
      <category>RF-DETR</category>
      <category>Roboflow</category>
      <category>Rust</category>
      <author>cellaxon</author>
      <guid isPermaLink="true">https://cellaxon.tistory.com/33</guid>
      <comments>https://cellaxon.tistory.com/33#entry33comment</comments>
      <pubDate>Thu, 31 Jul 2025 14:07:13 +0900</pubDate>
    </item>
    <item>
      <title>Rust + Slint UI + Kameo Actor Model</title>
      <link>https://cellaxon.tistory.com/32</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;새로운 일을 시작하면서 Slint를 처음으로 사용해보았습니다.&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;Rust에서 본격적으로 개발을 하다 보면 Tokio와 Task를 피해갈 수가 없습니다. 상당히 많은 라이브러리들이 비동기를 기본으로 지원하다 보니 거기에 맞추어 개발을 할 수 밖에 없는데요. 개별적으로 동작하는 Task 사이에 데이터를 공유하자면 Arc&amp;lt;Mutex&amp;lt;T&amp;gt;&amp;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;Arc&amp;lt;Mutex&amp;lt;T&amp;gt;&amp;gt;를 사용하기 시작하면 deadlock 발생 확률이 생깁니다. Rust가 좋은 언어이지만 deadlock 발생 가능성까지는 컴파일러에서 알아채지 못합니다. 조금만 주의를 잃어도 lock이 걸린 상태에서 다시 lock을 시도하는 등의 잘못된 코드를 작성하게 되고, 컴파일러는 오류 메세지 없이 빌드해내지만 실행해보면 어디선가 루프가 멈추는 상황이 발생하는데 추적이 쉽지 않습니다.&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;Channel을 사용하게 되면 간단히 tx 데이터를 써넣고, 데이터를 읽는 측에서는 비동기 상태로 대기하다가 rx를 통해 데이터를 읽을 수 있을 때에만 반응하면 됩니다. Channel을 사용할 때의 문제점이라면 이렇게 각 컴포넌트 간에 명시적인 연결 지점이 생기게 되고, 그로인한 의존성이 생긴다는 것과 채널들이 많아지면 각 채널들의 이름을 정하는 것부터 어디서 데이터가 오고 가는 것인지에 대해 판단하기가 간단하지 않게 됩니다.&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;이 정도쯤 되면 세상에 더 좋은 방법이 있을 거라고 생각하게 됩니다. 그래서 더 좋은 해결책을 찾다보니 Actor 모델을 찾게 되었습니다.&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;Actor 모델에 대해서 더 필요성을 느꼈던 것 중에 하나는 Bevy Engine에서 Plugin 단위로 컴포넌트를 만들어 사용하면서 각각의 컴포넌트들이 자신에 대한 통제권을 가지고 외부와 격리된 채로 최소한의 필요한 데이터만 주고 받게 만드는 것의 장점을 알게 되었기 때문입니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;동시에 여러 사람이 하나의 프로젝트에서 작업을 하더라도 다른 요소에 대한 개발을 한다면 코드가 충돌하는 상황이 줄어듭니다.&lt;/li&gt;
&lt;li&gt;서로 간의 의존성이 낮기 때문에 코드를 이해하기도 쉬워집니다.&lt;/li&gt;
&lt;li&gt;이벤트의 추상화가 잘 되어 있다면 컴포넌트를 다른 것으로 교체하는 일도 쉬워집니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 장점들이 기존 프로젝트를 Actor 모델로 재구성하면서 발생하는 복잡도를 감당할 만큼은 된다는 생각이 들었습니다. 특히 slint를 사용해보니 Actor 모델을 적용하는 것이 UI를 제어하거나 UI에서 발생한 이벤트를 처리하기에 더 좋겠다는 생각이 들더라구요.&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;&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;처음 Slint를 써 보시는 분들 보다는 Slint를 사용해서 본격적인 프로젝트를 제작하시는 분들이 Actor 모델을 적용할 수 있도록 참고할만한 예제를 만들었습니다.&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/cellaxon/slint_and_kameo_test&quot;&gt;https://github.com/cellaxon/slint_and_kameo_test&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;이게 생각보다 파일과 폴더의 개수가 많아져서 프로젝트를 생성하고 각 파일을 만드는 과정을 모두 기록하기에는 어렵네요. 기본적인 아이디어와 데이터의 흐름에 대한 설명만 남겨두겠습니다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본적인 구성은 다음과 같습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Slint UI : 화면에 표시되는 GUI 요소&lt;/li&gt;
&lt;li&gt;UI Actor : Slint UI에서 보내오는 메세지에 대한 처리와 UI Actor에서 받은 UI 제어 메세지를 Slint UI에 전달하는 Acotr&lt;/li&gt;
&lt;li&gt;Core Actor : 비지니스 로직이 동작하는 Actor&lt;/li&gt;
&lt;/ul&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;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;Slint 에서 발생하는 UI 이벤트는 callback 함수를 통해 처리합니다. 이 때 callback 함수에 UI Actor에 대한 레퍼런스를 남겨두어 이벤트가 발생할 때 UI Actor에 메세지를 전달하도록 했습니다.&lt;/li&gt;
&lt;li&gt;UI Actor는 Slint UI로부터 받은 메세지를 Core Actor에 전달합니다.&lt;/li&gt;
&lt;li&gt;Core Actor는 받은 메세지를 처리하고 UI Actor에 처리한 결과를 전달합니다.&lt;/li&gt;
&lt;li&gt;UI Actor는 Core Actor로부터 받은 데이터를 Slint UI로 전달합니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;1753762598870.png&quot; data-origin-width=&quot;925&quot; data-origin-height=&quot;822&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bagZej/btsPCjiy3K5/rZHqxY9Z3BBr0mrjnp0Mnk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bagZej/btsPCjiy3K5/rZHqxY9Z3BBr0mrjnp0Mnk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bagZej/btsPCjiy3K5/rZHqxY9Z3BBr0mrjnp0Mnk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbagZej%2FbtsPCjiy3K5%2FrZHqxY9Z3BBr0mrjnp0Mnk%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;925&quot; height=&quot;822&quot; data-filename=&quot;1753762598870.png&quot; data-origin-width=&quot;925&quot; data-origin-height=&quot;822&quot;/&gt;&lt;/span&gt;&lt;/figure&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;&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;&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Actor 모델이 silver bullet 같은 것은 아닙니다. 여러 단계의 데이터 중계 과정이 추가되기 때문에 그에 따라 추가해야 할 정의들이 늘어나고, 송신과 수신 처리에 대한 코드를 추가하면서 복잡해지는 부분이 있습니다. 다만 공유 변수 사용으로 인해 실수가 발생할 수 있는 여지를 줄이고, 개별 요소들을 잘 격리하게 됨으로 해서 생기는 장점들이 단점을 상쇄할 수 있다면 충분히 도입할 가치가 있어 보입니다.&lt;/p&gt;</description>
      <category>프로그래밍/Rust</category>
      <author>cellaxon</author>
      <guid isPermaLink="true">https://cellaxon.tistory.com/32</guid>
      <comments>https://cellaxon.tistory.com/32#entry32comment</comments>
      <pubDate>Wed, 30 Jul 2025 13:44:51 +0900</pubDate>
    </item>
    <item>
      <title>Rust + Bevy Engine + egui 시작하기</title>
      <link>https://cellaxon.tistory.com/30</link>
      <description>&lt;p id=&quot;ember1065&quot; style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;길고도 짧았던 프로젝트 하나가 일단락되어 게시물을 작성할 여유가 생겼습니다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p id=&quot;ember1066&quot; style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;Rust를 본격적으로 업무에 사용하기 시작한 것이 2019년도였습니다. 지금도 그렇지만 당시에도 Rust 진영에서 GUI 프로그램 개발을 하기에는 선택지가 많지 않은 상황이었습니다. 그나마 그때에는 간단한 펌웨어 업데이트 프로그램을 만들던 때라 Sciter( &lt;a href=&quot;https://sciter.com/&quot;&gt;https://sciter.com/&lt;/a&gt; )를 사용했었습니다. 지금이라면 Tauri를 선택했겠지만 Tauri가 1.0이 된 게 2022년도 여름에나 되어서였네요.&lt;/p&gt;
&lt;p id=&quot;ember1067&quot; style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;시간이 지나 다시 GUI 프로그램을 만들어야 하는 상황이 왔고, 그때에는 Tauri를 사용했습니다. 그때가 딱 Tauri가 1.0이 된 직후였네요. 차트가 필요해서 Chart.js를 사용해서 실시간으로 업데이트되는 데이터를 표시했습니다. 그리고 그때부터 성능에 한계를 느끼기 시작했어요.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p id=&quot;ember1068&quot; style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;또 이런저런 일들을 하다가 드디어 영상을 3차원 공간에 올려야 하는 일을 하게 되었습니다. 그것도 macOS에서요. 때가 되었구나 싶었습니다. 계속해서 GUI와 관련된 새로운 정보들을 탐색해 왔었고, 다음 개발에는 Bevy Engine을 써야겠다고 염두해 두고 있었거든요. 한편으로 egui도 생각하고 있었습니다. 복잡한 UI 요소들을 넣어야 하는데 Bevy Engine만으로는 불가능했거든요.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p id=&quot;ember1069&quot; style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;C#을 사용한 게 20년 정도 되었고, WPF를 사용한 것도 15년 정도가 되어가는 것 같습니다. 복잡한 UI 요소들을 직접 만들어서 사용해야 할 일들이 많았었는데 쉽고 빠르게 만들 수 있었어요. 지금 기억나는 건 NMEA에 있는 위성 위치와 신호 세기를 표시하는 컨트롤을 만들었던 것과 드론 센서 데이터를 표시하는 실시간 차트를 만들었던 겁니다. 한 화면에서 18개의 실시간 차트를 동시에 그렸더니 WPF의 선 그리기로는 성능이 도저히 안 나와서 결국 백그라운드에서 비트맵에 그린 후에 화면에 붙여 넣는 방법으로 구현을 했었습니다.( &lt;a href=&quot;https://youtu.be/ozzC118UJTk&quot;&gt;https://youtu.be/ozzC118UJTk&lt;/a&gt; ) 여전히 UI 요소들의 편집도 쉽고, 새로운 컨트롤을 만드는 것도 좋지만 윈도우를 벗어나서 사용하기에는 어려움이 있습니다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p id=&quot;ember1070&quot; style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;Bevy Engine과 egui를 사용하기 시작한 게 이제 딱 1년이 되었습니다. 작업을 진행하면서 좋은 점도 있고, 아쉬운 부분들도 있었지만, 충분히 사용할 만하다고 생각하고 있습니다. 개인적으로는 꼭 C#과 WPF를 사용해야 하는 상황이 아니라면 GUI 프로그램을 만드는데 Bevy Engine과 egui를 사용하려 합니다. 물론 현재 가장 크리티컬 한 문제는 한국어 입력이 안 된다는 부분입니다. 이른 시일 내에 해결이 되면 좋겠네요. 개인적으로도 bevy_egui_ime ( &lt;a href=&quot;https://github.com/8bitTD/bevy_egui_ime&quot;&gt;https://github.com/8bitTD/bevy_egui_ime&lt;/a&gt; ) 라이브러리를 한국어 입력이 되도록 수정해 보고 있습니다. 충분히 가능성이 있어 보입니다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p id=&quot;ember1071&quot; style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;C#을 처음 배울 때 좋았던 것이 GUI 프로그램을 너무 쉽게 만들 수 있다는 것이었습니다. &quot;Hello World&quot;를 윈도우 위에 출력하다니. 조금 건너뛰는 느낌이 있기는 하지만 Rust를 처음 접하시더라도 재미있게 무언가를 만들어 보실 수 있다면 좀 더 흥미를 느끼실 수 있지 않을까 생각하고 있습니다. 그런 의미에서 이 게시물을 시작했습니다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p id=&quot;ember1072&quot; style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이제 시작하겠습니다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 id=&quot;ember1074&quot; style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;Rust 설치&lt;/h2&gt;
&lt;p id=&quot;ember1075&quot; style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;Rust 홈페이지의 Getting started 문서를 참고하시기 바랍니다.&lt;/p&gt;
&lt;p id=&quot;ember1076&quot; style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.rust-lang.org/learn/get-started&quot;&gt;https://www.rust-lang.org/learn/get-started&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p id=&quot;ember1077&quot; style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;macOS, Linux, WSL은 아래의 명령어를 사용하여 설치하실 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1753837668544&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 id=&quot;ember1079&quot; style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;br /&gt;새로운 프로젝트 시작&lt;/h2&gt;
&lt;p id=&quot;ember1080&quot; style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;개인적으로는 사용자 폴더 하위에 project 폴더를 만들고 그 아래에 프로젝트를 생성해서 사용하고 있습니다. 개인의 취향에 따르는 문제이니 원하는대로 사용하시면 됩니다.&lt;/p&gt;
&lt;p id=&quot;ember1081&quot; style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;새로운 Rust 프로젝트를 시작하는 명령은 아래와 같습니다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;Cargo new [프로젝트 이름]&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1753837688205&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;cargo new bevy_egui_hello_world&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p id=&quot;ember1083&quot; style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;폴더로 이동해서 생성된 파일을 확인하면 아래와 같은 파일들이 보입니다.&lt;/p&gt;
&lt;div style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;1751415436738.png&quot; data-origin-width=&quot;503&quot; data-origin-height=&quot;369&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bcA7NH/btsPCIoPbXt/41XeUglL69t2uWNAsqyNek/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bcA7NH/btsPCIoPbXt/41XeUglL69t2uWNAsqyNek/img.png&quot; data-alt=&quot;새로 생성한 프로젝트 폴더&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bcA7NH/btsPCIoPbXt/41XeUglL69t2uWNAsqyNek/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbcA7NH%2FbtsPCIoPbXt%2F41XeUglL69t2uWNAsqyNek%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;503&quot; height=&quot;369&quot; data-filename=&quot;1751415436738.png&quot; data-origin-width=&quot;503&quot; data-origin-height=&quot;369&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;새로 생성한 프로젝트 폴더&lt;/figcaption&gt;
&lt;/figure&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;Cargo.toml 파일은 프로젝트의 정보와 의존성 패키지 목록을 관리합니다. 내용을 살펴보면 아래와 같습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;1751415692519.png&quot; data-origin-width=&quot;534&quot; data-origin-height=&quot;339&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bJq6S1/btsPCIh2bcf/wdLoj9JGMaSHjtfqoxD3Rk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bJq6S1/btsPCIh2bcf/wdLoj9JGMaSHjtfqoxD3Rk/img.png&quot; data-alt=&quot;Cargo.toml&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bJq6S1/btsPCIh2bcf/wdLoj9JGMaSHjtfqoxD3Rk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbJq6S1%2FbtsPCIh2bcf%2FwdLoj9JGMaSHjtfqoxD3Rk%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;534&quot; height=&quot;339&quot; data-filename=&quot;1751415692519.png&quot; data-origin-width=&quot;534&quot; data-origin-height=&quot;339&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Cargo.toml&lt;/figcaption&gt;
&lt;/figure&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;&amp;nbsp;&lt;/p&gt;
&lt;h2 id=&quot;ember1088&quot; style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;의존성 추가&lt;/h2&gt;
&lt;p id=&quot;ember1089&quot; style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;현재 프로젝트에 Bevy Engine과 egui 라이브러리를 추가해보겠습니다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;아래의 명령을 사용하여 Bevy Engine을 추가합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1753837769707&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;cargo add bevy&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;다음으로 아래의 명령을 사용하여 bevy_egui를 추가합니다. &lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;이 라이브러리는 Bevy Engine에서 egui를 사용하기 위해 필요한 라이브러리입니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1753837786865&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;cargo add bevy_egui&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p id=&quot;ember1091&quot; style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;마지막으로 egui를 추가합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1753837801470&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;cargo add egui&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p id=&quot;ember1093&quot; style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;위의 명령을 묶어서 한 번에 설치하실 수도 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1753837826901&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;cargo add bevy bevy_egui egui&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;&amp;nbsp;&lt;/p&gt;
&lt;h2 id=&quot;ember1095&quot; style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;VS Code 설치&lt;/h2&gt;
&lt;p id=&quot;ember1096&quot; style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;소스 코드를 편집하는데 VS Code를 사용하겠습니다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;없으시다면 아래의 사이트를 방문하여 다운로드 받고 설치하시기 바랍니다.&lt;/p&gt;
&lt;p id=&quot;ember1097&quot; style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://code.visualstudio.com/&quot;&gt;https://code.visualstudio.com/&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p id=&quot;ember1098&quot; style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;macOS에서는 압축 파일을 다운받게 되는데 압축 파일을 더블 클릭하셔서 압축을 해제하신 후에 생성된 'Visual Studio Code'를 클릭-드래그해서 Finder 좌측에 보이는 '응용 프로그램'에 끌어다 놓고 사용하시면 됩니다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p id=&quot;ember1099&quot; style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;VS Code를 실행하시면 화면 좌측에 버튼들이 표시됩니다. 이 중에 네 개의 사각형이 그려진 버튼을 눌러 확장을 설치할 수 있는 화면으로 이동하시기 바랍니다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;1751416691184.png&quot; data-origin-width=&quot;507&quot; data-origin-height=&quot;251&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/blbKwQ/btsPBE8s3QM/1oq0FmS0SgLHcbSZDMtjNk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/blbKwQ/btsPBE8s3QM/1oq0FmS0SgLHcbSZDMtjNk/img.png&quot; data-alt=&quot;확장&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/blbKwQ/btsPBE8s3QM/1oq0FmS0SgLHcbSZDMtjNk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FblbKwQ%2FbtsPBE8s3QM%2F1oq0FmS0SgLHcbSZDMtjNk%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;507&quot; height=&quot;251&quot; data-filename=&quot;1751416691184.png&quot; data-origin-width=&quot;507&quot; data-origin-height=&quot;251&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;확장&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p id=&quot;ember1101&quot; style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;확장 화면 상단의 검색창을 사용해서 필요한 확장을 설치하실 수 있습니다.&lt;/p&gt;
&lt;p id=&quot;ember1102&quot; style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;Rust 언어를 사용하기 위해 기본적으로 필요한 확장은 다음과 같습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;CodeLLDB&lt;/li&gt;
&lt;li&gt;Crates&lt;/li&gt;
&lt;li&gt;Dependi&lt;/li&gt;
&lt;li&gt;Error Lens&lt;/li&gt;
&lt;li&gt;Even Better TOML&lt;/li&gt;
&lt;li&gt;rust-analyzer&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p id=&quot;ember1104&quot; style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;아래는 사용을 권해드리는 확장입니다. 필요에 따라 설치하시기 바랍니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Alphabetical Sorter&lt;/li&gt;
&lt;li&gt;Code Spell Checker&lt;/li&gt;
&lt;li&gt;Git Graph&lt;/li&gt;
&lt;li&gt;Git History&lt;/li&gt;
&lt;li&gt;Git History Diff&lt;/li&gt;
&lt;li&gt;Indenticator&lt;/li&gt;
&lt;li&gt;Bevy&amp;nbsp;Color&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p id=&quot;ember1106&quot; style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;터미널에서 VS Code를 실행하려면 아래에 설명한 단계를 따라하시기 바랍니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;Command + Shift + P 키를 누릅니다.&lt;/li&gt;
&lt;li&gt;명령 팔레트에 shell을 입력합니다.&lt;/li&gt;
&lt;li&gt;Shell Command: Install 'code' command in PATH 항목을 선택합니다.&lt;/li&gt;
&lt;li&gt;관리자&amp;nbsp;권한&amp;nbsp;요청이&amp;nbsp;뜨면&amp;nbsp;OK를&amp;nbsp;누르고&amp;nbsp;로그인&amp;nbsp;암호를&amp;nbsp;입력합니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;1751419004682.png&quot; data-origin-width=&quot;789&quot; data-origin-height=&quot;394&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/1YDrq/btsPBMyDjwh/Lqx5jWARVR5KcrkdnPHKM1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/1YDrq/btsPBMyDjwh/Lqx5jWARVR5KcrkdnPHKM1/img.png&quot; data-alt=&quot;명령 팔레트 화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/1YDrq/btsPBMyDjwh/Lqx5jWARVR5KcrkdnPHKM1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F1YDrq%2FbtsPBMyDjwh%2FLqx5jWARVR5KcrkdnPHKM1%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;789&quot; height=&quot;394&quot; data-filename=&quot;1751419004682.png&quot; data-origin-width=&quot;789&quot; data-origin-height=&quot;394&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;명령 팔레트 화면&lt;/figcaption&gt;
&lt;/figure&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;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;설치가 완료된 후에 터미널을 새로 열고 아래의 명령을 입력하면 현재 위치에서 VS Code를 바로 실행하실 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1753838030646&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;code .&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;&amp;nbsp;&lt;/p&gt;
&lt;h2 id=&quot;ember1112&quot; style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;Cargo.toml 확인&lt;/h2&gt;
&lt;p id=&quot;ember1113&quot; style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;각 라이브러리의 버전에 따라 아래의 &lt;a style=&quot;color: #0a66c2;&quot; href=&quot;http://main.rs/&quot; data-test-app-aware-link=&quot;&quot;&gt;main.rs&lt;/a&gt;에서 사용할 코드가 작동하지 않을 수도 있습니다. 버전을 확인해보시고 다르다면 아래와 같은 버전으로 변경해주시기 바랍니다.(아직도 Bevy Engine과 bevy_egui, egui의 핵심이 되는 API가 업데이트에 따라 바뀌는 부분들이 있고, 이 부분이 마이그레이션에 어려움을 주기도 합니다)&lt;/p&gt;
&lt;pre id=&quot;code_1753838084074&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;[package]
name = &quot;bevy_egui_hello_world&quot;
version = &quot;0.1.0&quot;
edition = &quot;2024&quot;

[dependencies]
bevy = &quot;0.16.1&quot;
bevy_egui = &quot;0.35.0&quot;
egui = &quot;0.31.1&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 id=&quot;ember1115&quot; style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;br /&gt;main.rs 편집&lt;/h2&gt;
&lt;p id=&quot;ember1116&quot; style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;src 폴더 아래에 &lt;a style=&quot;color: #0a66c2;&quot; href=&quot;http://main.rs/&quot; data-test-app-aware-link=&quot;&quot;&gt;main.rs&lt;/a&gt; 파일이 있습니다. 이 파일을 아래와 같이 수정합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1753838136189&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;use bevy::prelude::*;
use bevy_egui::{egui, EguiContexts, EguiPlugin, EguiPrimaryContextPass};

fn main() {
    App::new()
        .add_plugins(DefaultPlugins)
        .add_plugins(EguiPlugin::default())
        .add_systems(Startup, setup_camera_system)
        .add_systems(EguiPrimaryContextPass, ui_example_system)
        .run();
}

fn setup_camera_system(mut commands: Commands) {
    commands.spawn(Camera2d);
}

fn ui_example_system(mut contexts: EguiContexts) -&amp;gt; Result {
    egui::Window::new(&quot;Hello world&quot;).show(contexts.ctx_mut()?, |ui| {
        ui.label(&quot;Hello world&quot;);
    });
    Ok(())
}&lt;/code&gt;&lt;/pre&gt;
&lt;h2 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 id=&quot;ember1118&quot; style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;실행&lt;/h2&gt;
&lt;p id=&quot;ember1119&quot; style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;아래의 명령을 사용하여 지금까지 작업한 내용을 실행해보겠습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1753838161132&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;cargo run&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;1751420203005.png&quot; data-origin-width=&quot;1285&quot; data-origin-height=&quot;752&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Y77Tx/btsPEsrwWvd/BGymAVYXkOLlbWC2d0XlMK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Y77Tx/btsPEsrwWvd/BGymAVYXkOLlbWC2d0XlMK/img.png&quot; data-alt=&quot;실행 화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Y77Tx/btsPEsrwWvd/BGymAVYXkOLlbWC2d0XlMK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FY77Tx%2FbtsPEsrwWvd%2FBGymAVYXkOLlbWC2d0XlMK%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;1285&quot; height=&quot;752&quot; data-filename=&quot;1751420203005.png&quot; data-origin-width=&quot;1285&quot; data-origin-height=&quot;752&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;실행 화면&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p id=&quot;ember1122&quot; style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;실행이 되셨나요? 축하드립니다. 하지만 여기에서 끝내기에는 여러모로 아쉬움이 남기 때문에 조금 더 작업을 진행해보겠습니다.&lt;/p&gt;
&lt;p id=&quot;ember1123&quot; style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 id=&quot;ember1124&quot; style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;플러그인 구조로 변경&lt;/h2&gt;
&lt;p id=&quot;ember1125&quot; style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;Bevy Engine은 크게 세 가지의 구성 요소가 있습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Resource&lt;/li&gt;
&lt;li&gt;Event&lt;/li&gt;
&lt;li&gt;System&lt;/li&gt;
&lt;/ul&gt;
&lt;p id=&quot;ember1127&quot; style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Resource&lt;/b&gt;는 읽거나 수정이 가능한 전역에서 접근 가능한 데이터로 생각하시면 됩니다. &lt;b&gt;Event&lt;/b&gt;는 이벤트를 발생시키고, 발생한 이벤트를 읽어서 처리하는데 사용합니다. 하나의 이벤트를 여러 곳에서 쓸 수 있고, 또 여러 곳에서 읽어서 사용할 수 있습니다. &lt;b&gt;System&lt;/b&gt;은 첫 번째 인자의 값에 따라 처음 프로그램이 시작될 때 한 번만 실행하거나, 매 프레임마다 호출되는 함수입니다. 여기에서 Resource의 값을 읽거나 변경하고, 이벤트를 발생 시키고, 읽어서 처리할 수 있습니다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p id=&quot;ember1128&quot; style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이러한 구성 요소들을 용도에 따라 또는 화면 단위로 묶어서 플러그인으로 만들 수 있습니다. 플러그인으로 만들면 코드 복잡도가 낮아져서 이해하고 관리하기가 쉬워집니다. 아래에서 제안하는 폴더 구조는 제 개인적인 의견이므로 사용에 익숙해지시면 원하는대로 변경해서 사용하시면 됩니다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p id=&quot;ember1129&quot; style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;플러그인 구조로 변경하는 방법은 아래의 순서대로 따라하시기 바랍니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;src 폴더 하위에 plugins 폴더를 추가합니다.&lt;/li&gt;
&lt;li&gt;plugins&amp;nbsp;폴더에&amp;nbsp;mod.rs&amp;nbsp;파일을&amp;nbsp;추가하고&amp;nbsp;아래의&amp;nbsp;코드를&amp;nbsp;작성합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1753838259126&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;pub mod hello_world;&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;plugins 폴더에 hello_world 폴더를 추가합니다.&lt;/li&gt;
&lt;li&gt;hello_world&amp;nbsp;폴더에&amp;nbsp;mod.rs&amp;nbsp;파일을&amp;nbsp;추가하고&amp;nbsp;아래의&amp;nbsp;코드를&amp;nbsp;작성합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1753838340196&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;pub mod plugin;&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;hello_world 폴더에 plugin.rs 파일을 추가하고 아래의 코드를 작성합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1753838376104&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;use bevy::prelude::*;
use bevy_egui::{EguiContexts, EguiPrimaryContextPass};

pub struct HelloWorldPlugin;

impl Plugin for HelloWorldPlugin {
    fn build(&amp;amp;self, app: &amp;amp;mut App) {
        app.add_systems(EguiPrimaryContextPass, ui_example_system);
    }
}

fn ui_example_system(mut contexts: EguiContexts) -&amp;gt; Result {
    egui::Window::new(&quot;Hello&quot;).show(contexts.ctx_mut()?, |ui| {
        ui.label(&quot;world&quot;);
    });
    Ok(())
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;main.rs 파일을 아래와 같이 수정합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1753838408215&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;mod plugins;

use bevy::prelude::*;
use bevy_egui::EguiPlugin;

fn main() {
    App::new()
        .add_plugins(DefaultPlugins)
        .add_plugins(EguiPlugin::default())
        .add_systems(Startup, setup_camera_system)
        .add_plugins(plugins::hello_world::plugin::HelloWorldPlugin)
        .run();
}

fn setup_camera_system(mut commands: Commands) {
    commands.spawn(Camera2d);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p id=&quot;ember1135&quot; style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;변경이 완료된 폴더의 구조는 아래와 같습니다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;1751422082553.png&quot; data-origin-width=&quot;442&quot; data-origin-height=&quot;284&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/BMf3m/btsPDpoKyXe/xd4hLM4yqvsvVOjLkVumTk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/BMf3m/btsPDpoKyXe/xd4hLM4yqvsvVOjLkVumTk/img.png&quot; data-alt=&quot;hello_world 플러그인&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/BMf3m/btsPDpoKyXe/xd4hLM4yqvsvVOjLkVumTk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FBMf3m%2FbtsPDpoKyXe%2Fxd4hLM4yqvsvVOjLkVumTk%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;442&quot; height=&quot;284&quot; data-filename=&quot;1751422082553.png&quot; data-origin-width=&quot;442&quot; data-origin-height=&quot;284&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;hello_world 플러그인&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p id=&quot;ember1138&quot; style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;실행 결과는 변경 전과 동일합니다. 하지만 이걸로 끝내면 안되겠죠. 아래에서 조금 더 내용을 진행해보도록 하겠습니다.&lt;/p&gt;
&lt;p id=&quot;ember1139&quot; style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 id=&quot;ember1140&quot; style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;현재 시간을 표시하는 프로그램 만들기&lt;/h2&gt;
&lt;p id=&quot;ember1141&quot; style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;버튼을 누르면 버튼을 누른 시간이 텍스트 박스에 차례대로 추가되는 예제를 만들어보겠습니다. 이 기능을 사용하려면 시간 값이 들어있는 문자열을 어디엔가 저장해야하는데요. 이 때 Resource를 사용합니다. 아래의 설명을 차례대로 따라하시기 바랍니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;시간을 원하는 형태로 출력하려면 chrono 크레이트(라이브러리)가 필요합니다. 터미널에서 아래의 명령을 사용하여 라이브러리를 추가합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1753838480831&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;cargo add chrono&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;hello_world 폴더에 resources.rs 파일을 추가하고 아래의 코드를 넣습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1753838514003&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;use bevy::prelude::*;

#[derive(Resource, Default)]
pub struct PluginState {
    pub time_string: String,
}&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;resouces.rs 파일이 hello_world 폴더에 있다는 것을 알리기 위해 hello_world 폴더의 mod.rs 파일을 수정합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1753838561067&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;pub mod plugin;
pub mod resources;&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;hello_world 폴더의 plugin.rs 파일을 아래와 같이 수정합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1753838585488&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;use super::resources::PluginState;
use bevy::prelude::*;
use bevy_egui::{EguiContexts, EguiPrimaryContextPass};
use chrono::Local;

pub struct HelloWorldPlugin;

impl Plugin for HelloWorldPlugin {
    fn build(&amp;amp;self, app: &amp;amp;mut App) {
        app.insert_resource(PluginState::default());
        app.add_systems(EguiPrimaryContextPass, ui_example_system);
    }
}

fn ui_example_system(mut contexts: EguiContexts, mut state: ResMut&amp;lt;PluginState&amp;gt;) -&amp;gt; Result {
    egui::Window::new(&quot;Hello&quot;).show(contexts.ctx_mut()?, |ui| {
        ui.text_edit_multiline(&amp;amp;mut state.time_string);
        if ui.button(&quot;Update Time&quot;).clicked() {
            state.time_string += &amp;amp;format!(&quot;{}\n&quot;, Local::now().format(&quot;%Y-%m-%d %H:%M:%S&quot;));
        }
        if ui.button(&quot;Reset&quot;).clicked() {
            state.time_string = String::new();
        }
    });
    Ok(())
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;작업이 완료된 후 아래의 명령을 사용해서 프로그램을 실행해보겠습니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1753838604199&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;cargo run&lt;/code&gt;&lt;/pre&gt;
&lt;p id=&quot;ember1149&quot; style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;'Update Time' 버튼을 눌러보았습니다.&lt;/p&gt;
&lt;div style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;1751423622829.png&quot; data-origin-width=&quot;490&quot; data-origin-height=&quot;319&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dg86F2/btsPDtxP3Y8/ChKrYiunVkznpaNf46nv8k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dg86F2/btsPDtxP3Y8/ChKrYiunVkznpaNf46nv8k/img.png&quot; data-alt=&quot;프로그램 실행 화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dg86F2/btsPDtxP3Y8/ChKrYiunVkznpaNf46nv8k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdg86F2%2FbtsPDtxP3Y8%2FChKrYiunVkznpaNf46nv8k%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;490&quot; height=&quot;319&quot; data-filename=&quot;1751423622829.png&quot; data-origin-width=&quot;490&quot; data-origin-height=&quot;319&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;프로그램 실행 화면&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p id=&quot;ember1152&quot; style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;뜯어보면 어려운 내용들이 있기는한데 여기서부터 천천히 알아보면 되지 않을까요?&lt;/p&gt;
&lt;p id=&quot;ember1153&quot; style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p id=&quot;ember1154&quot; style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;전체 코드는 아래의 저장소에 올려두었습니다.&lt;/p&gt;
&lt;p id=&quot;ember1155&quot; style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/cellaxon/bevy_egui_hello_world&quot;&gt;https://github.com/cellaxon/bevy_egui_hello_world&lt;/a&gt;&lt;/p&gt;
&lt;p id=&quot;ember1156&quot; style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p id=&quot;ember1157&quot; style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;저장소의 코드를 내려받으려면 아래의 명령을 입력하시면 됩니다.&lt;/p&gt;
&lt;pre id=&quot;code_1753838652271&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;git clone https://github.com/cellaxon/bevy_egui_hello_world&lt;/code&gt;&lt;/pre&gt;
&lt;p id=&quot;ember1159&quot; style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;아마도 git은 설치되어 있을거예요. 그렇죠?&lt;/p&gt;
&lt;p id=&quot;ember1160&quot; style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p id=&quot;ember1161&quot; style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이전에는 Rust를 선뜻 추천하기 어려웠는데 AI 도입으로 격변의 시기를 거치면서 이런 도구들의 도움을 받으면 문법에 조금 약해도 충분히 도전할 만한 상황이 되었습니다. 모르면 원하는 코드를 작성해달라고 하면 잘해줍니다. 코드 설명도 잘해주고요. 틀린 코드 수정은 지금 환경에서는 한 번에 안 될 때가 많지만 이 정도만 해줘도 어디인가 싶네요. 사용자의 의도와 맞지 않을 때도 있지만 상당히 많은 부분을 자동 완성해 주기도 하고요.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p id=&quot;ember1162&quot; style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;Github Copilot을 연간 구독으로 사용하는 중에 소문을 듣고 Windsurf( &lt;a href=&quot;http://windsurf.com/&quot;&gt;http://windsurf.com/&lt;/a&gt; )와 Cursor( &lt;a href=&quot;https://cursor.com/&quot;&gt;https://cursor.com/&lt;/a&gt; )를 차례로 월 결제해서 써봤는데 돈이 아깝지 않았습니다. 오히려 너무 빨리 토큰을 다 써버려서 추가 결제를 해야 하나 망설이게 될 정도였어요. 물론 너무 큰 기대를 하고 계시면 실망하실 수도 있겠지만 맨땅에 헤딩했던 경험이 있으신 분들이라면 충분히 만족하고 쓰실 수 있을 겁니다. 결제가 부담되시거든 무료 버전이라도 써보세요. 꼭.&lt;/p&gt;
&lt;p id=&quot;ember1163&quot; style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p id=&quot;ember1164&quot; style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;길고 긴 Bevy Engine과 egui 입문 게시물이 끝났습니다. 여기까지 작성하는 데 4시간이 걸렸네요. 아마도 이다음 게시물은 Event에 대한 설명이 될 것 같습니다. 적절한 예제를 찾기 위해 노력하겠습니다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p id=&quot;ember1165&quot; style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;감사합니다.&lt;/p&gt;</description>
      <category>프로그래밍/Rust</category>
      <category>bevy</category>
      <category>BevyEngine</category>
      <category>egui</category>
      <category>Rust</category>
      <category>러스트</category>
      <author>cellaxon</author>
      <guid isPermaLink="true">https://cellaxon.tistory.com/30</guid>
      <comments>https://cellaxon.tistory.com/30#entry30comment</comments>
      <pubDate>Wed, 30 Jul 2025 10:25:42 +0900</pubDate>
    </item>
    <item>
      <title>How to Run SteVe OCPP Server with Podman.</title>
      <link>https://cellaxon.tistory.com/31</link>
      <description>&lt;p id=&quot;ember640&quot; style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;macOS 환경에서 SteVe OCPP 서버를 Podman을 사용하여 편리하게 실행하는 방법을 정리하였습니다.&lt;/p&gt;
&lt;p id=&quot;ember641&quot; style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 id=&quot;ember642&quot; style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;Podman 설치&lt;/h2&gt;
&lt;p id=&quot;ember643&quot; style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;Docker Desktop의 대안인 Podman Desktop을 설치하는 것부터 시작하겠습니다.&lt;/p&gt;
&lt;p id=&quot;ember644&quot; style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;Podman의 홈페이지에 가셔서 프로그램을 다운 받습니다.&lt;/p&gt;
&lt;p id=&quot;ember645&quot; style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://podman.io/&quot;&gt;https://podman.io/&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;1751936242743.png&quot; data-origin-width=&quot;1153&quot; data-origin-height=&quot;1000&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/zk0xH/btsPB0XODxa/NxMV8VWYUn4Ykw19C52v11/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/zk0xH/btsPB0XODxa/NxMV8VWYUn4Ykw19C52v11/img.png&quot; data-alt=&quot;Podman 홈페이지&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/zk0xH/btsPB0XODxa/NxMV8VWYUn4Ykw19C52v11/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fzk0xH%2FbtsPB0XODxa%2FNxMV8VWYUn4Ykw19C52v11%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;1153&quot; height=&quot;1000&quot; data-filename=&quot;1751936242743.png&quot; data-origin-width=&quot;1153&quot; data-origin-height=&quot;1000&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Podman 홈페이지&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;Download 버튼을 누른 다음 아래에 나타나는 박스에서&lt;/span&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt; &lt;/span&gt;&lt;b&gt;Podman Desktop for macOS&lt;/b&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;를 클릭하여 프로그램을 다운로드 받고, 설치합니다.&lt;/span&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt; &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;1751936459159.png&quot; data-origin-width=&quot;543&quot; data-origin-height=&quot;380&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b8vHrP/btsPDl7KimP/rAVeSlORdZqJmjUIZx7T31/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b8vHrP/btsPDl7KimP/rAVeSlORdZqJmjUIZx7T31/img.png&quot; data-alt=&quot;podman pkg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b8vHrP/btsPDl7KimP/rAVeSlORdZqJmjUIZx7T31/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb8vHrP%2FbtsPDl7KimP%2FrAVeSlORdZqJmjUIZx7T31%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;543&quot; height=&quot;380&quot; data-filename=&quot;1751936459159.png&quot; data-origin-width=&quot;543&quot; data-origin-height=&quot;380&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;podman pkg&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p id=&quot;ember649&quot; style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;나머지 설치 과정에 대해서는 크게 어려운 것이 없으므로 넘어가겠습니다.&lt;/p&gt;
&lt;p id=&quot;ember650&quot; style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 id=&quot;ember651&quot; style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;Podman Compose 설치&lt;/h2&gt;
&lt;blockquote id=&quot;ember652&quot; style=&quot;background-color: #ffffff; color: #56687a; text-align: start;&quot; data-ke-style=&quot;style1&quot;&gt;Podman-compose는 Podman 컨테이너 엔진을 이용해 여러 컨테이너, 네트워크, 볼륨 등을 한 번에 정의하고 관리할 수 있도록 해주는 오케스트레이션 도구입니다. 이는 &lt;b&gt;Docker Compose와 유사하게 YAML 형식의 Compose 파일&lt;/b&gt;(주로 docker-compose.yml)을 사용하여 애플리케이션 스택을 정의하고, 여러 컨테이너를 한 번에 실행&amp;middot;중지&amp;middot;삭제할 수 있게 해줍니다&lt;/blockquote&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p id=&quot;ember653&quot; style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;여기에서는 docker-compose.yaml 파일을 사용하여 SteVe와 MySQL 서버를 같이 실행하는데 사용합니다. Python이 먼저 설치되어 있어야 합니다.&lt;/p&gt;
&lt;p id=&quot;ember654&quot; style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;아래의 명령을 사용해서 설치하세요.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1753837136020&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;pip3 install podman-compose&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;1751937082143.png&quot; data-origin-width=&quot;1237&quot; data-origin-height=&quot;486&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cwo622/btsPDmMj6Ha/uykIlwTOiemLNdD0V0VDM0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cwo622/btsPDmMj6Ha/uykIlwTOiemLNdD0V0VDM0/img.png&quot; data-alt=&quot;Podman Compose 설치&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cwo622/btsPDmMj6Ha/uykIlwTOiemLNdD0V0VDM0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcwo622%2FbtsPDmMj6Ha%2FuykIlwTOiemLNdD0V0VDM0%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;1237&quot; height=&quot;486&quot; data-filename=&quot;1751937082143.png&quot; data-origin-width=&quot;1237&quot; data-origin-height=&quot;486&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Podman Compose 설치&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 id=&quot;ember657&quot; style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;br /&gt;SteVe 소스 코드 다운로드&lt;/h3&gt;
&lt;p id=&quot;ember658&quot; style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;아래의 명령을 실행하여 저장소에서 소스코드를 가져옵니다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1753837173534&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;git clone https://github.com/steve-community/steve.git&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 id=&quot;ember660&quot; style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;Password 변경&lt;/h3&gt;
&lt;p id=&quot;ember661&quot; style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;docker-compose.yml&lt;/b&gt; 파일의 &lt;b&gt;MYSQL_PASSWORD&lt;/b&gt; 우측의 &lt;b&gt;changeme&lt;/b&gt;를 다른 것으로 변경해서 사용하시기 바랍니다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;1751938231897.png&quot; data-origin-width=&quot;1002&quot; data-origin-height=&quot;875&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/5Jz5J/btsPCiDQ1GX/Npm14iHrRnpSYwuyrSlzTk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/5Jz5J/btsPCiDQ1GX/Npm14iHrRnpSYwuyrSlzTk/img.png&quot; data-alt=&quot;docker-compose.yml&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/5Jz5J/btsPCiDQ1GX/Npm14iHrRnpSYwuyrSlzTk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F5Jz5J%2FbtsPCiDQ1GX%2FNpm14iHrRnpSYwuyrSlzTk%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;1002&quot; height=&quot;875&quot; data-filename=&quot;1751938231897.png&quot; data-origin-width=&quot;1002&quot; data-origin-height=&quot;875&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;docker-compose.yml&lt;/figcaption&gt;
&lt;/figure&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;&lt;b&gt;src/main/resources/config/docker/&lt;/b&gt;&lt;a style=&quot;color: #0a66c2; text-align: start;&quot; href=&quot;http://main.properties/&quot; data-test-app-aware-link=&quot;&quot;&gt;&lt;b&gt;main.properties&lt;/b&gt;&lt;/a&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;파일의&lt;/span&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt; &lt;/span&gt;&lt;b&gt;db.password&lt;/b&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;를 위에서 설정한 것과 동일한 비밀번호로 변경하시기 바랍니다. 그 아래의&lt;/span&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt; &lt;/span&gt;&lt;b&gt;auth.password&lt;/b&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;는 다른 것으로 변경해서 사용해주세요.(아래 파일의 13번째, 18번째 라인입니다)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;1751938380394.png&quot; data-origin-width=&quot;1100&quot; data-origin-height=&quot;1500&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/moDGd/btsPDphZ3nX/V0ORwkcV7htRyfdHEuCgPK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/moDGd/btsPDphZ3nX/V0ORwkcV7htRyfdHEuCgPK/img.png&quot; data-alt=&quot;src/main/resources/config/docker/main.properties&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/moDGd/btsPDphZ3nX/V0ORwkcV7htRyfdHEuCgPK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmoDGd%2FbtsPDphZ3nX%2FV0ORwkcV7htRyfdHEuCgPK%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;1100&quot; height=&quot;1500&quot; data-filename=&quot;1751938380394.png&quot; data-origin-width=&quot;1100&quot; data-origin-height=&quot;1500&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;src/main/resources/config/docker/main.properties&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 id=&quot;ember666&quot; style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;br /&gt;Podman Compose를 사용하여 SteVe 서버 실행&lt;/h3&gt;
&lt;p id=&quot;ember667&quot; style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;SteVe를 받은 폴더에서 아래의 명령을 실행합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1753837356810&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;podman-compose up -d&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;1751938630602.png&quot; data-origin-width=&quot;1488&quot; data-origin-height=&quot;803&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cGB7M9/btsPDUu4zml/UPesZfLnnR65mPRlcRPrCk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cGB7M9/btsPDUu4zml/UPesZfLnnR65mPRlcRPrCk/img.png&quot; data-alt=&quot;podman compose를 사용하여 실행&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cGB7M9/btsPDUu4zml/UPesZfLnnR65mPRlcRPrCk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcGB7M9%2FbtsPDUu4zml%2FUPesZfLnnR65mPRlcRPrCk%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;1488&quot; height=&quot;803&quot; data-filename=&quot;1751938630602.png&quot; data-origin-width=&quot;1488&quot; data-origin-height=&quot;803&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;podman compose를 사용하여 실행&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p id=&quot;ember669&quot; style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;서버 실행에는 약간의 시간이 필요합니다.&lt;/p&gt;
&lt;p id=&quot;ember670&quot; style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;브라우저를 실행하여 아래의 주소를 입력하고 들어가보겠습니다.&lt;/p&gt;
&lt;p id=&quot;ember671&quot; style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a style=&quot;color: #0a66c2;&quot; href=&quot;http://localhost:8180/steve/manager/&quot; data-test-app-aware-link=&quot;&quot;&gt;http://localhost:8180/steve/manager/&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;1751938738111.png&quot; data-origin-width=&quot;1153&quot; data-origin-height=&quot;1000&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/FJ4eh/btsPEpO9npg/vffKeSYkDp92ndZGFBRKm0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/FJ4eh/btsPEpO9npg/vffKeSYkDp92ndZGFBRKm0/img.png&quot; data-alt=&quot;SteVe Server&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/FJ4eh/btsPEpO9npg/vffKeSYkDp92ndZGFBRKm0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FFJ4eh%2FbtsPEpO9npg%2FvffKeSYkDp92ndZGFBRKm0%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;1153&quot; height=&quot;1000&quot; data-filename=&quot;1751938738111.png&quot; data-origin-width=&quot;1153&quot; data-origin-height=&quot;1000&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;SteVe Server&lt;/figcaption&gt;
&lt;/figure&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;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;위에서 수정한&lt;/span&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt; &lt;/span&gt;&lt;a style=&quot;color: #0a66c2; text-align: start;&quot; href=&quot;http://main.properties/&quot; data-test-app-aware-link=&quot;&quot;&gt;main.properties&lt;/a&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;파일의&lt;/span&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt; &lt;/span&gt;&lt;b&gt;auth.user &lt;/b&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;와&lt;/span&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt; &lt;/span&gt;&lt;b&gt;auth.password&lt;/b&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;에 입력한 계정으로 접속하시면 됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;1751938884100.png&quot; data-origin-width=&quot;1274&quot; data-origin-height=&quot;710&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Qf4Jz/btsPBGrGQIH/GkW93xauJI1ZpTvRFikFl0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Qf4Jz/btsPBGrGQIH/GkW93xauJI1ZpTvRFikFl0/img.png&quot; data-alt=&quot;SteVe manager&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Qf4Jz/btsPBGrGQIH/GkW93xauJI1ZpTvRFikFl0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FQf4Jz%2FbtsPBGrGQIH%2FGkW93xauJI1ZpTvRFikFl0%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;1274&quot; height=&quot;710&quot; data-filename=&quot;1751938884100.png&quot; data-origin-width=&quot;1274&quot; data-origin-height=&quot;710&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;SteVe manager&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p id=&quot;ember675&quot; style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;잘 되셨나요?&lt;/p&gt;
&lt;p id=&quot;ember676&quot; style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 id=&quot;ember677&quot; style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;서버 종료&lt;/h3&gt;
&lt;p id=&quot;ember678&quot; style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;SteVe를 받은 폴더에서 아래의 명령을 실행합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1753837450803&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;podman-compose down&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;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;1751938986648.png&quot; data-origin-width=&quot;552&quot; data-origin-height=&quot;168&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/UOn05/btsPBMZFxaP/HsW8AkdSnKlUwHeLuu30q0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/UOn05/btsPBMZFxaP/HsW8AkdSnKlUwHeLuu30q0/img.png&quot; data-alt=&quot;서버 종료&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/UOn05/btsPBMZFxaP/HsW8AkdSnKlUwHeLuu30q0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FUOn05%2FbtsPBMZFxaP%2FHsW8AkdSnKlUwHeLuu30q0%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;552&quot; height=&quot;168&quot; data-filename=&quot;1751938986648.png&quot; data-origin-width=&quot;552&quot; data-origin-height=&quot;168&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;서버 종료&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p id=&quot;ember682&quot; style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;직접 데이터베이스를 설치하는 것보다는 훨씬 쉬운 방법으로 실행할 수 있었습니다.&lt;/p&gt;
&lt;p id=&quot;ember683&quot; style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; 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>
      <author>cellaxon</author>
      <guid isPermaLink="true">https://cellaxon.tistory.com/31</guid>
      <comments>https://cellaxon.tistory.com/31#entry31comment</comments>
      <pubDate>Wed, 30 Jul 2025 10:05:56 +0900</pubDate>
    </item>
    <item>
      <title>[macos] autoenv 사용 및 python venv 환경 구성하기(PyTorch)</title>
      <link>https://cellaxon.tistory.com/29</link>
      <description>&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/hyperupcall/autoenv&quot;&gt;https://github.com/hyperupcall/autoenv&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1744778185154&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 - hyperupcall/autoenv: Directory-based environments.&quot; data-og-description=&quot;Directory-based environments. Contribute to hyperupcall/autoenv development by creating an account on GitHub.&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/hyperupcall/autoenv&quot; data-og-url=&quot;https://github.com/hyperupcall/autoenv&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/iJm34/hyYIhHr9Hy/Kk5ZkjKnhAFQz1dLZaqdp1/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/b8lOzJ/hyYCgYm9GV/df0BfkTPnZmo1RQh2kyS41/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/hyperupcall/autoenv&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/hyperupcall/autoenv&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/iJm34/hyYIhHr9Hy/Kk5ZkjKnhAFQz1dLZaqdp1/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/b8lOzJ/hyYCgYm9GV/df0BfkTPnZmo1RQh2kyS41/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 - hyperupcall/autoenv: Directory-based environments.&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Directory-based environments. Contribute to hyperupcall/autoenv 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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;rust 프로젝트에서 PyTorch와 tch-rs(PyTorch에 대한 rust 바인딩)를 사용하고 있는데&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;
&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;이번에 개발환경을 세팅하다보니 이미 시스템에 python 3.13이 설치되어 있고&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;그래서 프로젝트 루트에 venv를 세팅하고&amp;nbsp;autoenv를 사용하려고 합니다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용 환경을 먼저 설명드리자면 맥미니 m4 / macos 15.4에 zsh을 사용하고 있습니다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. autoenv설치&lt;/p&gt;
&lt;pre id=&quot;code_1744778656770&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;brew install autoenv&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 터미널을 열 때 autoenv가 로딩 되도록 하는 명령(macos / zsh)&lt;/p&gt;
&lt;pre id=&quot;code_1744778701098&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;printf '%s\n' &quot;source $(brew --prefix autoenv)/activate.sh&quot; &amp;gt;&amp;gt; &quot;${ZDOTDIR:-$HOME}/.zprofile&quot;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. venv 환경 구성, PyTorch 설치&lt;/p&gt;
&lt;pre id=&quot;code_1744779072990&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;python3 -m venv .venv
source .venv/bin/activate
pip install torch torchvision torchaudio&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. PyTorch가 설치된 경로 확인&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래의 python 스크립트를 실행하시면 됩니다.&lt;/p&gt;
&lt;pre id=&quot;code_1744779284712&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import torch

# torch 설치 경로 출력
print(torch.__file__)&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5. 프로젝트 루트 폴더에 '.env' 파일 생성&lt;br /&gt;위의 스크립트를 실행하여 알아낸 경로를 아래에 적용해줍니다.&lt;/p&gt;
&lt;pre id=&quot;code_1744778808887&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;if [[ -n &quot;$_AUTOENV_ACTIVATED&quot; ]]; then
    return
fi
export _AUTOENV_ACTIVATED=1

# Directory
DIR=&quot;$(cd &quot;$(dirname &quot;$0&quot;)&quot; &amp;amp;&amp;amp; pwd)&quot;

source .venv/bin/activate
export   LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/usr/local/lib
export DYLD_LIBRARY_PATH=${DIR}/.venv/lib/python3.13/site-packages/torch/lib:$DYLD_LIBRARY_PATH
export          LIBTORCH=${DIR}/.venv/lib/python3.13/site-packages/torch&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;6. 터미널을 재실행하면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <author>cellaxon</author>
      <guid isPermaLink="true">https://cellaxon.tistory.com/29</guid>
      <comments>https://cellaxon.tistory.com/29#entry29comment</comments>
      <pubDate>Wed, 16 Apr 2025 15:24:27 +0900</pubDate>
    </item>
    <item>
      <title>[Error] after updating MacOS 15.4 and caused 'Library not loaded: @executable_path/../Frameworks/libopenblasp-r0.3.29.dylib'.</title>
      <link>https://cellaxon.tistory.com/28</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;opencv를 사용하는 프로젝트가 macos를 15.4로 업데이트 한 이후에 위와 같은 오류를 발생하기 시작했습니다.&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;번들링 후 dylibbundler를 실행했는데도 .app/Contents/Frameworks 폴더에 libopenblasp-r0.3.29.dylib 파일이&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;포함되지 않는 것을 확인하였습니다.&lt;br /&gt;&lt;br /&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;1. 'libopenblasp-r0.3.29.dylib'와 libopenblas.0.dylib' 를 찾아서 /Framework에 복사하였습니다.&lt;br /&gt;&amp;nbsp; &amp;nbsp; ${APP_FOLDER}는 실제 .app 폴더의 경로입니다.&lt;/p&gt;
&lt;pre id=&quot;code_1744591064962&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;cp -v /opt/homebrew/opt/openblas/lib/libopenblasp-r0.3.29.dylib ${APP_FOLDER}/Contents/Frameworks/
cp -v /opt/homebrew/opt/openblas/lib/libopenblas.0.dylib ${APP_FOLDER}/Contents/Frameworks/&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. install_name_tool을 사용하여&amp;nbsp; 'libopenblasp-r0.3.29.dylib'가 참조하는 경로를 수정하였습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1744591152783&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;install_name_tool -change \
  /opt/homebrew/opt/openblas/lib/libopenblas.0.dylib \
  @executable_path/../Frameworks/libopenblas.0.dylib \
  ${APP_FOLDER}/Contents/Frameworks/libopenblasp-r0.3.29.dylib

install_name_tool -change \
  /opt/homebrew/opt/gcc/lib/gcc/current/libgfortran.5.dylib \
  @executable_path/../Frameworks/libgfortran.5.dylib \
  ${APP_FOLDER}/Contents/Frameworks/libopenblasp-r0.3.29.dylib

install_name_tool -change \
  /opt/homebrew/opt/gcc/lib/gcc/current/libgomp.1.dylib \
  @executable_path/../Frameworks/libgomp.1.dylib \
  ${APP_FOLDER}/Contents/Frameworks/libopenblasp-r0.3.29.dylib

install_name_tool -change \
  /opt/homebrew/opt/gcc/lib/gcc/current/libquadmath.0.dylib \
  @executable_path/../Frameworks/libquadmath.0.dylib \
  ${APP_FOLDER}/Contents/Frameworks/libopenblasp-r0.3.29.dylib&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;2.1. 변경 전 참조 경로는 다음과 같습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1744591245384&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;otool -L ./libopenblasp-r0.3.29.dylib 
./libopenblasp-r0.3.29.dylib:
	/opt/homebrew/opt/openblas/lib/libopenblas.0.dylib (compatibility version 0.0.0, current version 0.0.0)
	/opt/homebrew/opt/gcc/lib/gcc/current/libgfortran.5.dylib (compatibility version 6.0.0, current version 6.0.0)
	/opt/homebrew/opt/gcc/lib/gcc/current/libgomp.1.dylib (compatibility version 2.0.0, current version 2.0.0)
	/opt/homebrew/opt/gcc/lib/gcc/current/libquadmath.0.dylib (compatibility version 1.0.0, current version 1.0.0)
	/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1351.0.0)&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;2.2. 변경 후 참조 경로는 다음과 같습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1744591272594&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;otool -L ./libopenblasp-r0.3.29.dylib
./libopenblasp-r0.3.29.dylib:
	@executable_path/../Frameworks/libopenblasp-r0.3.29.dylib (compatibility version 0.0.0, current version 0.0.0)
	@executable_path/../Frameworks/libgfortran.5.dylib (compatibility version 6.0.0, current version 6.0.0)
	@executable_path/../Frameworks/libgomp.1.dylib (compatibility version 2.0.0, current version 2.0.0)
	@executable_path/../Frameworks/libquadmath.0.dylib (compatibility version 1.0.0, current version 1.0.0)
	/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1351.0.0)&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;3. install_name_tool 이후 전체 dylib와 실행파일, .app에 대한 코드 사인을 실행했습니다.&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;&amp;nbsp;&lt;/p&gt;</description>
      <author>cellaxon</author>
      <guid isPermaLink="true">https://cellaxon.tistory.com/28</guid>
      <comments>https://cellaxon.tistory.com/28#entry28comment</comments>
      <pubDate>Mon, 14 Apr 2025 09:50:42 +0900</pubDate>
    </item>
    <item>
      <title>[macOS] PyO3를 사용하여 rust에서 python 코드를 실행하기</title>
      <link>https://cellaxon.tistory.com/27</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;1. 새로운 프로젝트 생성&lt;/p&gt;
&lt;pre id=&quot;code_1740446397428&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;cargo new test_pyo3&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. Cargo.toml 파일에 아래의 내용 추가&lt;/p&gt;
&lt;pre id=&quot;code_1740446451617&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;[dependencies.pyo3]
version = &quot;0.23.4&quot;
features = [&quot;auto-initialize&quot;]&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. main.rs 수정&lt;/p&gt;
&lt;pre id=&quot;code_1740446621429&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;use pyo3::ffi::c_str;
use pyo3::prelude::*;
use pyo3::types::IntoPyDict;

fn main() -&amp;gt; PyResult&amp;lt;()&amp;gt; {
    Python::with_gil(|py| {
        let sys = py.import(&quot;sys&quot;)?;
        let version: String = sys.getattr(&quot;version&quot;)?.extract()?;

        let locals = [(&quot;os&quot;, py.import(&quot;os&quot;)?)].into_py_dict(py)?;
        let code = c_str!(&quot;os.getenv('USER') or os.getenv('USERNAME') or 'Unknown'&quot;);
        let user: String = py.eval(code, None, Some(&amp;amp;locals))?.extract()?;

        println!(&quot;Hello {}, I'm Python {}&quot;, user, version);
        Ok(())
    })
}&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. export를 사용하여 파이썬 경로와 관련된 환경 변수 설정&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;python 라이브러리 경로 확인 스크립트를 실행하여 설치 경로 확인&lt;/p&gt;
&lt;pre id=&quot;code_1740447132541&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;python&quot;&gt;&lt;code&gt;import sysconfig
print(sysconfig.get_config_var(&quot;LIBDIR&quot;))&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;실행 결과&lt;/p&gt;
&lt;pre id=&quot;code_1740447132541&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;python ./scripts/check_python_path.py 
/Users/a1/.local/share/mise/installs/python/3.12.8/lib&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;위의 실행 결과를 아래에 반영하여 터미널에서 실행(영구적으로 사용할 경우 ~/.zshrc 에 추가)&lt;/p&gt;
&lt;pre id=&quot;code_1740446518768&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;export PYTHONHOME=/Users/a1/.local/share/mise/installs/python/3.12.8
export PYTHONPATH=/Users/a1/.local/share/mise/installs/python/3.12.8/lib/python3.12
export DYLD_LIBRARY_PATH=/Users/a1/.local/share/mise/installs/python/3.12.8/lib:$DYLD_LIBRARY_PATH&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5. 프로젝트 실행&lt;/p&gt;
&lt;pre id=&quot;code_1740446679740&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;cargo run&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;실행 결과&lt;/p&gt;
&lt;pre id=&quot;code_1740446777163&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;cargo run --release
   Compiling test_pyo3 v0.1.0 (/Users/a1/project/fitogether_video_new/test_pyo3)
    Finished `release` profile [optimized] target(s) in 0.33s
     Running `target/release/test_pyo3`
Hello a1, I'm Python 3.12.8 (main, Jan 14 2025, 23:36:58) [Clang 19.1.6 ]&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;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://pyo3.rs/v0.23.4/python-from-rust.html#calling-python-in-rust-code&quot;&gt;https://pyo3.rs/v0.23.4/python-from-rust.html#calling-python-in-rust-code&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1740446968963&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Calling Python from Rust - PyO3 user guide&quot; data-og-description=&quot;This chapter of the guide documents some ways to interact with Python code from Rust. Below is an introduction to the 'py lifetime and some general remarks about how PyO3's API reasons about Python code. The subchapters also cover the following topics: Pyt&quot; data-og-host=&quot;pyo3.rs&quot; data-og-source-url=&quot;https://pyo3.rs/v0.23.4/python-from-rust.html#calling-python-in-rust-code&quot; data-og-url=&quot;https://pyo3.rs/v0.23.4/python-from-rust.html#calling-python-in-rust-code&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://pyo3.rs/v0.23.4/python-from-rust.html#calling-python-in-rust-code&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://pyo3.rs/v0.23.4/python-from-rust.html#calling-python-in-rust-code&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&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;Calling Python from Rust - PyO3 user guide&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;This chapter of the guide documents some ways to interact with Python code from Rust. Below is an introduction to the 'py lifetime and some general remarks about how PyO3's API reasons about Python code. The subchapters also cover the following topics: Pyt&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;pyo3.rs&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>프로그래밍/Rust</category>
      <author>cellaxon</author>
      <guid isPermaLink="true">https://cellaxon.tistory.com/27</guid>
      <comments>https://cellaxon.tistory.com/27#entry27comment</comments>
      <pubDate>Tue, 25 Feb 2025 10:30:03 +0900</pubDate>
    </item>
  </channel>
</rss>