<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>charlie_moon.log</title>
        <link>https://velog.io/</link>
        <description>산만한 개발자의 노트</description>
        <lastBuildDate>Wed, 25 Mar 2026 02:36:37 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>charlie_moon.log</title>
            <url>https://velog.velcdn.com/images/charlie_moon/profile/364cf390-1a92-4384-b466-df082308cbf8/image.jpeg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. charlie_moon.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/charlie_moon" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[Linux Cli Commands]]></title>
            <link>https://velog.io/@charlie_moon/Linux-Cli-Commands</link>
            <guid>https://velog.io/@charlie_moon/Linux-Cli-Commands</guid>
            <pubDate>Wed, 25 Mar 2026 02:36:37 GMT</pubDate>
            <description><![CDATA[<h1 id="file-system">File System</h1>
<h2 id="ls">ls</h2>
<h3 id="파일-목록보기">파일 목록보기</h3>
<pre><code class="language-bash">ls</code></pre>
<h3 id="상세정보-목록보기">상세정보 목록보기</h3>
<pre><code class="language-bash">ls -l</code></pre>
<h3 id="숨김파일을-포함한-목록보기">숨김파일을 포함한 목록보기</h3>
<pre><code class="language-bash">ls -a</code></pre>
<h3 id="읽기-쉬운-단위로-목록보기">읽기 쉬운 단위로 목록보기</h3>
<pre><code class="language-bash">ls -lh</code></pre>
<h3 id="수정시간-최신순으로-목록보기">수정시간 최신순으로 목록보기</h3>
<pre><code class="language-bash">ls -t</code></pre>
<h3 id="정렬-순서를-역순정렬-목록보기">정렬 순서를 역순정렬 목록보기</h3>
<pre><code class="language-bash">ls -r</code></pre>
<h3 id="하위-디렉토리까지-포함-목록보기">하위 디렉토리까지 포함 목록보기</h3>
<pre><code class="language-bash">ls -R</code></pre>
<h3 id="파일-종류를-마지막-문자로-구분하여-목록보기">파일 종류를 마지막 문자로 구분하여 목록보기</h3>
<pre><code class="language-bash">ls -F 
# &#39;/&#39; 디렉토리, &#39;*&#39; 실행파일</code></pre>
<h3 id="파일크기-큰순으로-목록보기">파일크기 큰순으로 목록보기</h3>
<pre><code class="language-bash">ls -S</code></pre>
<h1 id="network">Network</h1>
<h2 id="ssh">SSH</h2>
<h3 id="ssh-시작">SSH 시작</h3>
<pre><code class="language-bash">sudo systemctl start ssh</code></pre>
<h3 id="ssh-자동시작-등록">SSH 자동시작 등록</h3>
<pre><code class="language-bash">sudo systemctl enable ssh</code></pre>
<h2 id="wifi">Wifi</h2>
<h3 id="networkmanager-실행">NetworkManager 실행</h3>
<pre><code class="language-bash">sudo systemctl start NetworkManager</code></pre>
<h3 id="network-interface-목록-보기">Network Interface 목록 보기</h3>
<pre><code class="language-bash">sudo nmcli dev</code></pre>
<h3 id="wifi-기능-켜기끄기">Wifi 기능 켜기/끄기</h3>
<pre><code class="language-bash">sudo nmcli radio wifi on
#축약
sudo nmcli r wifi on

sudo nmcli radio wifi off
#축약
sudo nmcli r wifi off</code></pre>
<h3 id="wifi-스캔">Wifi 스캔</h3>
<pre><code class="language-bash">sudo nmcli dev wifi rescan</code></pre>
<h3 id="wifi-목록보기">Wifi 목록보기</h3>
<pre><code class="language-bash">sudo nmcli dev wifi</code></pre>
<h3 id="wifi-연결끊기">Wifi 연결/끊기</h3>
<pre><code class="language-bash">sudo nmcli dev connect &quot;&lt;SSID&gt;&quot; password &quot;&lt;비밀번호&gt;&quot;
sudo nmcli connection down &lt;SSID&gt;

#장치연결 끊기
nmcli device disconnect &lt;인터페이스이름&gt;</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[Radxa 3B Overlay 설정]]></title>
            <link>https://velog.io/@charlie_moon/Radxa-3B-Overlay-%EC%84%A4%EC%A0%95</link>
            <guid>https://velog.io/@charlie_moon/Radxa-3B-Overlay-%EC%84%A4%EC%A0%95</guid>
            <pubDate>Mon, 23 Mar 2026 07:17:30 GMT</pubDate>
            <description><![CDATA[<p>OS 설치를 끝낸 보드는 Overlay 설정을 하지 않으면 화면 출력이 되지 않는다.
먼저 시리얼 콘솔을 연결로 접속하여 셋업을 해주어야한다.</p>
<p>나는 picocom을 이용해서 접속하였다.</p>
<pre><code class="language-bash">    # picocom -b &lt;baud rate&gt; -d &lt;통신 데이터 비트 수&gt; /dev/&lt;연결 시리얼 포트&gt;
    picocom -b 1500000 -d 8 /dev/cu.usbserial-A5069RR4</code></pre>
<p>접속이 되면 엔터를 한번 쳐준다.
로그인 하라고 하는데 초기 계정과 비밀번호를 입력하고 로그인 하면 된다.</p>
<p><img src="https://velog.velcdn.com/images/charlie_moon/post/28b818ad-84e3-455e-b070-b54e4b98ac0d/image.png" alt=""></p>
<p>다음은 오버레이 설정을 해주어야한다.</p>
<pre><code class="language-bash">    sudo rsetup</code></pre>
<p><img src="https://velog.velcdn.com/images/charlie_moon/post/d144c1d7-572f-4d39-ad34-7c53231955bd/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/charlie_moon/post/cddfbd2a-784d-4174-a8f8-f1e7bbf24b72/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/charlie_moon/post/8d60a2de-6d79-418b-b50d-dd73b22240a0/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/charlie_moon/post/ff33e8a1-1460-44c0-af1a-e919b2540ef0/image.png" alt=""></p>
<p><strong>Overlays - Manage Overlays</strong> 순으로 이동하고 본인이 사용하는 디스플레이를 선택한뒤 설정을 빠져 나오면 된다. *선택은 스페이스바, 포커스 이동은 탭</p>
<p><img src="https://velog.velcdn.com/images/charlie_moon/post/2f6c8f7c-8caf-40f9-b00c-0206c3ae29d9/image.png" alt=""></p>
<p>그렇게 설정하고 재부팅 하면 되는것이다. Rseutp을 빠져 나와서 재부팅해주자.</p>
<pre><code class="language-bash">    sudo reboot</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[Apache Fory 오픈소스 기여 후기]]></title>
            <link>https://velog.io/@charlie_moon/Apache-Fory-%EC%98%A4%ED%94%88%EC%86%8C%EC%8A%A4-%EA%B8%B0%EC%97%AC-%ED%9B%84%EA%B8%B0</link>
            <guid>https://velog.io/@charlie_moon/Apache-Fory-%EC%98%A4%ED%94%88%EC%86%8C%EC%8A%A4-%EA%B8%B0%EC%97%AC-%ED%9B%84%EA%B8%B0</guid>
            <pubDate>Sat, 21 Mar 2026 06:45:07 GMT</pubDate>
            <description><![CDATA[<p>요즘 나는 나만의 홈랩을 구성하기 위해 여러가지 아키텍쳐를 구상하고 있었다. 그중에 최대한 적은 리소스로 고효율을 내는 것에 제일 집중하고 있다. 그래서 이것 저것 구글을 통해서 탐색을 하고 있던도중 Apache Fory라는 직렬화 오픈소스 라이브러리를 알게되었다. </p>
<p>Fory는 JIT컴파일과 Zero-Copy를 이용한 고성능 직렬화 도구이다.</p>
<h3 id="a-hrefhttpsgithubcomchaokunyangfory-benchmarks-target_blank벤치마크a"><a href="https://github.com/chaokunyang/fory-benchmarks" target="_blank">벤치마크</a></h3>
<p>원래는 Ant Group(알리바바 계열사)에 내부 프로젝트로 시작 되었으나 2023년 Apache재단에 인큐베이팅 되면서 2025년에 TLP가 되었다.</p>
<p>처음에 오픈소스 기여를 할 생각은 없었다. 그냥 해당 프로젝트 GitHub 저장소를 방문해서 이것 저것 탐색 하다가 Contributing 탭을 보게되었다. 그중에 &#39;Good First Issues&#39;라는 링크를 보게 되었고 궁금해서 들어가 보았다.</p>
<p><img src="https://velog.velcdn.com/images/charlie_moon/post/99b1daa2-f73b-40d1-9db6-5318a8dcae51/image.png" alt=""></p>
<p>그곳에는 처음 기여하는 사람들을 고려한 비교적 쉬운 이슈들을 모아둔 곳이었다. 나는 내가 해 볼 수 있는 이슈가 있을까 탐색하다가 CI/CD 관려 이슈를 보게 되었다. </p>
<p><img src="https://velog.velcdn.com/images/charlie_moon/post/00fb646d-1438-4888-a37f-ef290d22228c/image.png" alt=""></p>
<p>해당이슈는 <strong>&quot;Rust Github Action이 5분가량 소요되는데 3분대로 낮추었으면 좋겠다.&quot;</strong> 라는 이슈였다.</p>
<p>왠지 이정도는 내가 한번 도전해 볼 수 있을것 같다는 생각이 들어 해당 이슈에 <strong>&quot;주니어 개발자이고 오픈소스 기여가 처음인데 이 이슈에 관심이 있어서 그런데 실수를 할 수 있겠지만 한번 이슈를 처리해봐도 될까요?&quot;</strong> 라고 번역기를 이용해서 코멘트를 달았다.</p>
<p><img src="https://velog.velcdn.com/images/charlie_moon/post/3c3689f2-73f5-4c17-9a2d-29e213e4ef9e/image.png" alt=""></p>
<p>그러자 하루가 지나고 운영자에게 <strong>&quot;기여해주셔서 고맙습니다. 이슈를 당신한테 할당해 줄게요.&quot;</strong> 라는 코멘트를 받을 수 있었고 이슈가 나에게 할당되었다</p>
<p><img src="blob:https://velog.io/b43cf01c-1ca2-4e1a-a4bb-b0ab4f3319b3" alt=""></p>
<p><img src="https://velog.velcdn.com/images/charlie_moon/post/5d649109-4f20-41dd-a2a2-a11008deea93/image.png" alt=""></p>
<p>먼저 github action 스크립트가 있는 .github/workflows/ 에 들어가서 Rust 관련 CI/CD 내용을 살펴보았고 Rust CI 부분에 캐시를 이용하는 코드가 없는것을 보게되었고 캐시를 이용할 수 있도록 스크립트를 추가해주었다.</p>
<p><img src="https://velog.velcdn.com/images/charlie_moon/post/f772cdf0-3fa0-4806-b557-bc17c8231bd9/image.png" alt=""></p>
<p>CI 테스트는 <a href="http://github.com/nektos/act"><code>ACT</code></a> 를 사용하여 테스트 하였고 드라마틱한 시간 단축은 없었으나 그래도 평균 10초 정도는 단축 시킨것 같다.</p>
<p>그렇게 하여 PR을 요청하였다.</p>
<p>3주정도 지난후 PR이 승인이 되고 머지가 되었다.</p>
<p><img src="https://velog.velcdn.com/images/charlie_moon/post/4b56eac6-1bad-4503-914c-e92bb9295c68/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/charlie_moon/post/3fb05c90-0dac-4f2f-a4d7-23e4248070b6/image.png" alt=""></p>
<p>그렇게 기여자 명단에 내가 올라가게 되었다.
처음 기여를 해보았는데 정말 뿌듯하다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Radxa Rock 3B Board Setting]]></title>
            <link>https://velog.io/@charlie_moon/Radxa-Rock-3B-Board-Setting</link>
            <guid>https://velog.io/@charlie_moon/Radxa-Rock-3B-Board-Setting</guid>
            <pubDate>Fri, 13 Mar 2026 02:15:46 GMT</pubDate>
            <description><![CDATA[<h1 id="radxa">Radxa</h1>
<p>Radxa는 엣지 컴퓨팅, AI 및 산업용 애플리케이션을 위한 오픈 소스 싱글 보드 컴퓨터(SBC)와 임베디드 시스템을 제공하는 기업이다.</p>
<ul>
<li><strong>제품군</strong> 
Rockchip SoC(시스템 온 칩)를 기반으로 한 ROCK Pi 시리즈(예: Rock Pi 4, Rock Pi S)가 주력 제품이다. 이 외에도 고성능 엣지 AI를 위한 Dragon Q6A(퀄컴 프로세서 기반) 및 산업용 임베디드 모듈(SOM)을 제공한다.</li>
<li><strong>라즈베리 파이 대안</strong> 
라즈베리 파이와 호환되거나 이를 대체할 수 있는 고성능 SBC를 제공하며, 특정 모델(예: Radxa Zero)은 라즈베리 파이 제로 시리즈의 강력한 대안으로 평가받는다.</li>
<li><strong>주요 애플리케이션</strong>
IoT 장치, 멀티미디어, 산업용 자동화 기기, 그리고 AI 기반 엣지 컴퓨팅 기기 개발에 주로 사용된다.</li>
<li><strong>생태계</strong>
자체 문서화 센터를 운영하며, 다양한 리눅스(Linux) 및 안드로이드(Android) 운영체제를 지원하는 커뮤니티 기반의 생태계를 구축하고 있다.</li>
</ul>
<h1 id="rock-3b">Rock 3B</h1>
<p><img src="https://velog.velcdn.com/images/charlie_moon/post/0d4be5dc-854c-4b18-a1b1-7f7004bb528a/image.png" alt=""></p>
<p><a href="https://radxa.com/products/rock3/3b">Rock 3B</a></p>
<p> 구분 | 세부 항목 | 사양 (Specifications) |
| :--- | :--- | :--- |
| <strong>프로세서</strong> | <strong>SoC</strong> | Rockchip RK3568 (Quad-core Cortex-A55 up to 2.0GHz) |
| | <strong>GPU</strong> | Mali-G52-2EE (OpenGL ES 3.2, Vulkan 1.1 지원) |
| | <strong>NPU</strong> | 1.0 TOPS (AI 가속기) |
| <strong>메모리</strong> | <strong>RAM</strong> | 2GB / 4GB / 8GB LPDDR4 (3200MT/s) |
| <strong>저장 장치</strong> | <strong>eMMC</strong> | eMMC 모듈 슬롯 지원 |
| | <strong>MicroSD</strong> | 지원 (TF 카드 슬롯) |
| | <strong>M.2 SSD</strong> | M.2 M Key (PCIe 3.0 x2) - NVMe SSD 지원 |
| <strong>비디오 출력</strong> | <strong>HDMI</strong> | 1x HDMI 2.0 (4K@60Hz) |
| | <strong>MIPI/eDP</strong> | 2x MIPI DSI, 1x eDP (트리플 디스플레이 가능) |
| <strong>네트워크</strong> | <strong>Ethernet</strong> | 2x 기가비트 LAN (1개는 PoE 지원) |
| | <strong>Wireless</strong> | M.2 E Key 슬롯 (WiFi 6/BT 모듈용) |
| | <strong>Cellular</strong> | M.2 B Key 슬롯 (4G/5G 모듈용 + SIM 슬롯) |
| <strong>USB 포트</strong> | <strong>USB 3.0/2.0</strong> | 2x USB 3.0 (1x OTG 포함), 2x USB 2.0 |
| <strong>확장 헤더</strong> | <strong>GPIO</strong> | 40핀 헤더 (라즈베리 파이와 호환성 유지) |
| <strong>전원</strong> | <strong>Input</strong> | USB Type-C (PD 2.0 / QC 2.0, 3.0 지원) |
| <strong>규격</strong> | <strong>크기</strong> | 100mm x 75mm (Pico-ITX 폼팩터) |</p>
<h1 id="os-설치">OS 설치</h1>
<p><a href="https://wiki.radxa.com/Rock3/downloads">Rock3 OS Download 사이트</a></p>
<p>위 링크에서 다운로드한다.</p>
<p>OS는 공식적으로 Debian과 Android 두가지를 지원하는데 현 시점으로 Android와 Debian 둘다 11까지 지원한다.
사이트에 들어가보면 다른 서드파티 이미지들도 몇개 존재한다.</p>
<p>하지만 나는 Tauri2로 작성된 앱을 Debian에서 실행하기 위해서 Pre-Release한 Debian12 버전을 이용해서 OS를 설치하였다.</p>
<p><a href="https://docs.radxa.com/en/rock3/images?model=ROCK+3B">Rock 3B Image Download 문서</a>
<a href="https://docs.radxa.com/en/rock3/rock3b/getting-started/install-system">Image 설치 가이드</a>
이미지는 툴을 이용해서 설치하는 방법이 무난한것 같다.</p>
<p>보드에 eMMC와 SDcard, Nvme 세가지 물리저장장치를 지원하기 때문에 해당 방법에 맞게 설치하는 것이 좋다.</p>
<p>공식홈페이지에서는 Linux와 Windows OS에 대한 툴만 지원하기 때문에 MacOS는 그냥 <code>dd</code>를 이용해서 인스톨 하도록 하겠다.</p>
<h2 id="이미지-압축해제">이미지 압축해제</h2>
<p>이미지가 <code>이미지_이름.img.xz</code>로 압축되어있는데.
이를 <code>unzx</code>로 해제 함면 된다.</p>
<pre><code class="language-bash">unzx &lt;이미지_이름&gt;.img.xz</code></pre>
<p>이렇게 하면 <code>&lt;이미지_이름&gt;.img</code> 이렇게 이미지가 나온다.</p>
<h2 id="저장장치에-쓰기">저장장치에 쓰기</h2>
<p>나는 SSD를 따로 마운트 할 장비가 없기 때문에 USB 허브를 통해서 SDcard에 설치 한 뒤
실제 보드에서 Nvme SSD에 다시 재설치 하는 방향으로 진행하고자 한다.</p>
<h3 id="sdcard에-설치">SDcard에 설치</h3>
<h4 id="sdcard-위치-조회">SDcard 위치 조회</h4>
<p>USB 허브에 SDcard를 장착하고 Mac에 연결해준다.
<code>diskutil</code> 명령어를 이용해서 저장장치가 어디에 연결되어있는지 확인한다.</p>
<pre><code class="language-bash">diskutil list</code></pre>
<p><img src="https://velog.velcdn.com/images/charlie_moon/post/262c02f3-8784-4723-a388-eca4862bb334/image.png" alt=""></p>
<p>저장장치가 <code>/dev/disk&lt;번호&gt;</code> 어떤 곳에 연결 되어있는지 확인한다.</p>
<h4 id="sdcard-언마운트">SDcard 언마운트</h4>
<p>저장장치가 어디에 연결 되어 있었는지 알아내었다면 플래시하기 위해서 언마운트 해주어야한다.</p>
<pre><code class="language-bash">diskutil unmountDisk /dev/disk&lt;번호&gt;</code></pre>
<h4 id="sdcard-플래시">SDcard 플래시</h4>
<p>이제 <code>dd</code>를 이용해서 장치에 이미지를 플래시하면 된다.</p>
<pre><code class="language-bash">sudo dd if=&lt;이미지 경로&gt; of=/dev/rdisk&lt;번호&gt; bs=1M status=progress</code></pre>
<p>위에서 status는 플래시 상태를 보여주는 옵션이기 때문에 입력하지 않아도 무방하다.</p>
<p>플래시가 끝나면 혹시 모를 데이터 유실이나 파일시스템 일관성을 위해서 <code>sync</code> 를 해준다.</p>
<pre><code class="language-bash">sync</code></pre>
<p>이렇게 하면 OS가 SDcard에 잘 설치 되었다.</p>
<h1 id="구동하기">구동하기</h1>
<p>Rock 3B 보드 SDcard 슬롯에 OS를 설치한 SDcard를 삽입하고 전원케이블(USB Type-C)을 꽂으면 자동으로 SDcard로 부터 OS를 부팅한다.</p>
<p><img src="https://velog.velcdn.com/images/charlie_moon/post/dc2e640f-c6c7-417e-93d4-28fe37cc97e5/image.jpeg" alt=""></p>
<p>부팅 완료.</p>
<p><a href="https://man7.org/linux/man-pages/man1/dd.1.html">[dd man 사이트]</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Kvrocks란?]]></title>
            <link>https://velog.io/@charlie_moon/Kvrocks%EB%9E%80</link>
            <guid>https://velog.io/@charlie_moon/Kvrocks%EB%9E%80</guid>
            <pubDate>Tue, 03 Mar 2026 13:56:45 GMT</pubDate>
            <description><![CDATA[<p>Kvrocks는 RocksDB를 스토리지 엔진으로 사용하고 Redis프로토콜과 호환되는 분산 키-밸류 NoSQL데이터베이스 이다.</p>
<h2 id="배경">배경</h2>
<p>Redis비용 문제를 해결하기 위해서 만들어 졌다. Redis는 모든 데이터를 메모리에 올려두고 사용하기 때문에 데이터가 커질수록 비용이 급격하게 올라간다. (메모리값...) 하지만 Kvrocks는 메모리 비용을 줄이면서 저장용량을 늘리는 것을 목표로한다.</p>
<p>원래 중국의 Meitu(메이투)에서 개발했으며, Trip.com, Baidu 등 여러 기업이 프로덕션 환경에서 사용하고 있다. 현재는 Apache 재단 프로젝트로 Apache 2.0 라이선스로 공개되어 있다.</p>
<h2 id="특징">특징</h2>
<p>Redis호환성이 있어 기존 Redis 클라이언트를 통해 그대로 접근 할 수 있다. 네임스페이스를 통한 데이터 격리, MySQL과 유사한 binlog기반 비동기복제, Redis Sentinel을 활용한 고가용성, 클러스터링 모드를 지원한다.</p>
<h2 id="언제-쓰면-좋은가">언제 쓰면 좋은가?</h2>
<p>Redis처럼 다양한 자료구조가 필요하지만 데이터 규모가 커서 전부 메모리에 올리기 부담스러운 경우에 적합하다.</p>
<h2 id="나는-어떻게-사용할-것인가">나는 어떻게 사용할 것인가?</h2>
<p>현재 서버의 RAM 용량이 DB, WebServer, Cache 등 여러 VM에 자원을 할당하기엔 매우 작음으로 Nvme SSD를 이용해서 캐시서버의 RAM할당량을 줄이고 SSD의 의존도를 높여는 비록 속도는 RAM보다 조금 느리지만 용량을 많이 사용 할 수 있도록 트레이트오프를 하여 운영할 예정이다. </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[ZFS란?]]></title>
            <link>https://velog.io/@charlie_moon/ZFS%EB%9E%80</link>
            <guid>https://velog.io/@charlie_moon/ZFS%EB%9E%80</guid>
            <pubDate>Tue, 03 Mar 2026 13:38:46 GMT</pubDate>
            <description><![CDATA[<p>ZFS는 Zettabyte File System의 약자로 썬 마이크로시스템즈가 개발한 고성능, 대용량, 데이터 무결성을 위한 파일시스템 겸 볼륨 관리자 이다. 128비트 아키텍처로 거의 무제한 용량을 지원하며, 스토리지 풀링, 강력한 스냅샷, 데이터 중복제거, 엔드 투 엔드 데이터 무결성 검증 기능을 제공한다. 안정성이 중요한 NAS 및 기업형 스토리지에 적합하다.</p>
<h2 id="128비트-구조">128비트 구조</h2>
<p>256,000조 제타바이트까지 지원한다.(사실상 용량 제한이 없음)</p>
<h2 id="스토리지-풀링">스토리지 풀링</h2>
<p>여러 디스크를 하나의 논리적 저장소로 통합 관리하여 유연한 용량 확장 가능하다. RAID-Z1, Z2, Z3 같은 자체 RAID 방식도 지원한다.</p>
<h2 id="스냅샷-및-클론">스냅샷 및 클론</h2>
<p>즉시 파일 시스템의 특정 시점을 저장(스냅샷)하고 복제(클록)하여 백업 및 복구에 매우 효율적이다.</p>
<h2 id="copy-on-write">Copy-on-write</h2>
<p>데이터를 수정할 때 기존 데이터를 덮어쓰지 않고 새로운 위치에 저장하여 안정성을 높이고 데이터 손실을 최소화 한다.</p>
<h2 id="압축-및-중복제거">압축 및 중복제거</h2>
<p>LZ4, ZSTD 등의 알고리즘으로 저장되는 데이터를 실시간으로 압축하거나 중복을 제거하여 저장 공간 효율을 극대화한다. </p>
<h2 id="데이터-무결성">데이터 무결성</h2>
<p>모든 데이터 블록에 체크섬을 적용하고, 읽을 때마다 검증한다. 손상이 감지되면 미러나 패리티 정보를 통해 자동으로 복구하는 &quot;self-healing&quot; 기능을 제공한다.</p>
<p>이건 하드웨어 레벨이 아닌 소프트웨어 레벨에서 직접 관리하는 것이기때문에 Silent Corruption까지 잡아낸다. (RAID는 보통 디스크가 완전히 멈춰야 고장으로 인식)</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[UART 통신]]></title>
            <link>https://velog.io/@charlie_moon/UART-%ED%86%B5%EC%8B%A0</link>
            <guid>https://velog.io/@charlie_moon/UART-%ED%86%B5%EC%8B%A0</guid>
            <pubDate>Thu, 12 Feb 2026 02:38:43 GMT</pubDate>
            <description><![CDATA[<p><strong>UART(Universal Asynchronous Receiver/Transmitter, 범용 비동기 송수신기)</strong>는
두 장치 간에 데이터를 비트 단위로 순차 전송하는 직렬 통신 방식이다. 
별도의 클럭 신호 없이 시작/정지 비트로 동기를 맞추며, <strong>송수신 핀(TX/RX)</strong>만 사용하여 MCU, 센서, 모듈 간 1:1 통신에 매우 널리 사용된다.</p>
<hr>
<h2 id="특징">특징</h2>
<h3 id="비동기-통신">비동기 통신</h3>
<p>별도의 클럭 선 없이 TX(송신), RX(수신) 2개의 신호선만 사용하여 데이터를 교환한다.</p>
<h3 id="데이터-프레임">데이터 프레임</h3>
<p>데이터는 [시작 비트(1) + 데이터(5<del>8bit) + 패리티 비트(옵션) + 정지 비트(1</del>2)] 구조로 전송된다.</p>
<h3 id="보율-baud-rate">보율 (Baud Rate)</h3>
<p>통신 속도를 나타내며, 송수신 측에서 동일한 속도(예: 9600, 115200 bps)로 설정해야 한다.</p>
<h3 id="양방향-통신">양방향 통신</h3>
<p>TX와 RX를 통해 동시에 송수신이 가능한 Full-duplex 방식이다.</p>
<hr>
<h2 id="작동-원리">작동 원리</h2>
<h3 id="직렬화serialization">직렬화(Serialization)</h3>
<p>병렬 데이터(데이터 처리부)를 1비트 단위의 직렬 신호로 변환하여 전송한다.</p>
<h3 id="역직렬화deserialization">역직렬화(Deserialization)</h3>
<p>수신부에서는 받은 1비트 신호들을 다시 병렬 데이터로 모아 처리한다.</p>
<h3 id="약속된-속도">약속된 속도</h3>
<p>수신 측은 미리 정해진 보율(baud rate)에 따라 데이터의 시작과 끝을 감지한다. </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[ESP Flash]]></title>
            <link>https://velog.io/@charlie_moon/ESP-Flash</link>
            <guid>https://velog.io/@charlie_moon/ESP-Flash</guid>
            <pubDate>Thu, 12 Feb 2026 02:26:05 GMT</pubDate>
            <description><![CDATA[<p><code>espflash</code>는 Espressif Systems의 ESP32 및 ESP8266 마이크로컨트롤러(SoC) 시리즈에 펌웨어를 굽는(Flashing) 데 사용되는 시리얼 플래셔 도구이다.</p>
<p>핵심적인 특징은 Rust 언어로 작성된 도구이며, 주로 Rust 내장(Embedded Rust) 개발 환경에서 편리하게 펌웨어를 전송하고 시리얼 모니터링을 하기 위해 사용된다.</p>
<h4 id="시리얼-플래싱">시리얼 플래싱</h4>
<p>시리얼 포트(UART)를 통해 빌드된 이진 파일(Binary/ELF)을 ESP 칩의 플래시 메모리에 기록한다.</p>
<h4 id="다양한-칩-지원">다양한 칩 지원</h4>
<p>ESP32, ESP32-S2/S3, ESP32-C2/C3/C6, ESP32-H2, ESP8266 등 대부분의 에스프레시프 칩을 지원한다.</p>
<h4 id="크로스-플랫폼">크로스 플랫폼</h4>
<p>Windows, macOS, Linux에서 모두 동작한다.</p>
<h4 id="cargo-플러그인-cargo-espflash">Cargo 플러그인 (cargo-espflash)</h4>
<p>Rust의 빌드 도구인 cargo와 연동되어 <code>cargo run</code> 또는 <code>cargo espflash flash</code> 명령어로 빌드와 동시에 펌웨어를 굽는 편리한 기능을 제공한다.</p>
<h4 id="모니터링-기능">모니터링 기능</h4>
<p>펌웨어 굽기 후, 바로 시리얼 모니터를 열어 디버깅 로그를 확인할 수 있다.</p>
<h3 id="설치">설치</h3>
<pre><code class="language-rust">cargo install espflash --locked

# 또는 cargo-espflash 플러그인 설치
cargo install cargo-espflash --locked</code></pre>
<h4 id="핵심-명령어">핵심 명령어</h4>
<ul>
<li>flash: 펌웨어 바이너리 파일 굽기</li>
<li>save-image: 바이너리 이미지를 로컬에 저장</li>
<li>board-info: 연결된 보드 정보 확인</li>
<li>erase-flash: 플래시 메모리 전체 삭제</li>
<li>monitor: 시리얼 모니터만 실행 </li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[HomeLab 구축기 -1-]]></title>
            <link>https://velog.io/@charlie_moon/HomeLab-%EA%B5%AC%EC%B6%95%EA%B8%B0-1-</link>
            <guid>https://velog.io/@charlie_moon/HomeLab-%EA%B5%AC%EC%B6%95%EA%B8%B0-1-</guid>
            <pubDate>Sun, 08 Feb 2026 13:56:40 GMT</pubDate>
            <description><![CDATA[<p>2026년 올해 하나의 목표가 생겼다. 
HomeLab을 구축해서 서버를 운영해보는 것이다.</p>
<p>내가 구성하려고 하는 규모는 1~5만 동시접속이 원활한 서버 이다.
이건 단순히 나의 호기심에서 시작되었기 때문에 어떤 결말이 있을지 잘 모르겠다. 잘 만들어서 잘마무리 되었으면 좋겠다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Git LFS]]></title>
            <link>https://velog.io/@charlie_moon/Git-LFS</link>
            <guid>https://velog.io/@charlie_moon/Git-LFS</guid>
            <pubDate>Thu, 05 Feb 2026 07:32:08 GMT</pubDate>
            <description><![CDATA[<p>사내에서 TTS 관련 프로젝트를 개발하고 있었는데 Git Submodule로 구성된 프로젝트 소스쪽에서 런타임 에러가 발생하여 초기화 과정에 문제가 생겼다. TTS onnx 파일을 보니 기존 TTS 저장소에 있는 onnx 파일보다 용량이 한참 모자란 파일이 자리하고 있었다.</p>
<p>삭제하고 다시 <code>git submodule update</code>를 해보았지만 여전히 용량 미달...</p>
<p>긴급히 대표님께 Help 요청!</p>
<p><img src="https://velog.velcdn.com/images/charlie_moon/post/706d78b3-efa4-4f13-810d-ba9f1d35c571/image.png" alt=""></p>
<p>이렇게 하고 서브모듈 제거 한 뒤 다시 <code>git submodule update</code> 커맨드를 이용하니 파일이 제대로 클론 되었다.</p>
<hr>
<h2 id="git의-한계">Git의 한계</h2>
<p>Git은 모든 수정 이력을 로컬에 저장하므로, 용량이 큰 바이너리 파일이 자주 바뀌면 저장소 크기가 순식간에 수십 GB로 늘어난다.</p>
<h2 id="github-제한">GitHub 제한</h2>
<p>GitHub는 단일 파일이 100MB를 넘으면 푸시를 차단한다. 
LFS를 쓰면 파일당 최대 5GB(또는 그 이상)까지 올릴 수 있다.</p>
<h2 id="설치">설치</h2>
<pre><code class="language-bash">brew install git-lfs

git lfs install</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Rust/Tauri] 말 끝나면 알아서 꺼지는 음성 녹음 기능 구현하기]]></title>
            <link>https://velog.io/@charlie_moon/RustTauri-%EB%A7%90-%EB%81%9D%EB%82%98%EB%A9%B4-%EC%95%8C%EC%95%84%EC%84%9C-%EA%BA%BC%EC%A7%80%EB%8A%94-%EC%9D%8C%EC%84%B1-%EB%85%B9%EC%9D%8C-%EA%B8%B0%EB%8A%A5-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@charlie_moon/RustTauri-%EB%A7%90-%EB%81%9D%EB%82%98%EB%A9%B4-%EC%95%8C%EC%95%84%EC%84%9C-%EA%BA%BC%EC%A7%80%EB%8A%94-%EC%9D%8C%EC%84%B1-%EB%85%B9%EC%9D%8C-%EA%B8%B0%EB%8A%A5-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0</guid>
            <pubDate>Thu, 05 Feb 2026 03:27:08 GMT</pubDate>
            <description><![CDATA[<h1 id="vad--trimming">VAD &amp; Trimming</h1>
<p>최근 사내 프로젝트를 개발하면서 <strong>&quot;사용자가 버튼을 누르고 말을 마친 뒤, 다시 버튼을 누르지 않아도 알아서녹음이 종료되는&quot;</strong> 기능이 필요했다.</p>
<p>스포츠 현장이나 손이 바쁜 상황에서는 녹음 종료 버튼을 누르는 것조차 번거로운 일이기 때문이다. 이번 포스팅에서는 Rust 오디오 라이브러리인 <code>cpal</code>과 <code>hound</code>를 사용하여 <strong>VAD(Voice Activity Detection)</strong>와 <strong>오디오 트리밍(Trimming)</strong>을 구현과정을 공유한다.</p>
<h2 id="사용한-라이브러리-crates">사용한 라이브러리 (Crates)</h2>
<ul>
<li><strong><a href="https://github.com/RustAudio/cpal">cpal</a></strong>: Rust의 표준적인 로우레벨 오디오 입출력 라이브러리다. (WASAPI, CoreAudio, ALSA 등 지원)</li>
<li><strong><a href="https://github.com/ruuda/hound">hound</a></strong>: WAV 포맷의 인코딩/디코딩을 쉽게 처리해주는 라이브러리다.
[dependencies]
cpal = &quot;0.15&quot;
hound = &quot;3.5&quot;</li>
</ul>
<h2 id="핵심-시나리오">핵심 시나리오</h2>
<ol>
<li><strong>녹음 시작</strong>: 사용자가 버튼을 누르면 녹음이 시작된다.</li>
<li><strong>묵음 감지 (Auto-Stop)</strong>: 사용자가 말을 하다가 멈추면(약 2초간 침묵), 시스템이 이를 감지하고 녹음을 자동 종료한다.</li>
<li><strong>후처리 (Trimming)</strong>: 자동 종료를 위해 기다렸던 2초간의 공백과, 말하기 전의 공백을 잘라내어 깔끔한 파일로 저장한다.</li>
</ol>
<hr>
<h2 id="1-묵음-감지-silence-detection-구현">1. 묵음 감지 (Silence Detection) 구현</h2>
<p>녹음을 계속 진행하면서 들어오는 오디오 샘플의 진폭(Amplitude)을 실시간으로 체크한다. 특정 임계값(<code>threshold</code>)보다 작은 소리가 일정 시간(<code>max_silence_samples</code>) 이상 지속되면 녹음을 중단하는 신호를 보낸다.</p>
<h3 id="주요-코드-로직">주요 코드 로직</h3>
<pre><code class="language-rust">  // 설정값
  let silence_threshold = 0.01; // 이 값보다 작으면 묵음으로 간주 (0.0 ~ 1.0)
  let sample_rate = config.sample_rate().0;
  let max_silence_samples = (sample_rate as usize) * 2; // 2초 분량의 샘플 수


  // 상태 공유를 위한 아토믹 변수
  let consecutive_silence = Arc::new(AtomicUsize::new(0));
  let stop_signal = Arc::new(AtomicBool::new(false));

  // ... (스트림 생성 코드 생략)


  // 샘플 처리 클로저
  move |data: &amp;[f32], : &amp;| {
      for &amp;sample in data {
          // 절대값이 임계값보다 작으면 침묵 카운트 증가
          if sample.abs() &lt; silence_threshold {
              let count = consecutive_silence.fetch_add(1, Ordering::Relaxed) + 1;

              // 2초 이상 침묵 시 정지 신호 발생
              if count &gt;= max_silence_samples {
                  stop_signal.store(true, Ordering::Relaxed);
              }
          } else {
              // 소리가 감지되면 카운트 리셋
              consecutive_silence.store(0, Ordering::Relaxed);
          }

          // ... (채널로 데이터 전송)
      }
  }</code></pre>
<p>이 로직 덕분에 사용자는 말을 끝낸 후 가만히 있으면, 약 2초 뒤에 녹음이 자동으로 종료된다.</p>
<hr>
<h2 id="2-오디오-트리밍-trimming-구현">2. 오디오 트리밍 (Trimming) 구현</h2>
<p>VAD 방식으로 녹음을 종료하면 필연적으로 <strong>&quot;말을 마친 후 2초간의 정적&quot;</strong>이 파일 뒷부분에 포함된다. 이를 그대로 사용하여 재생 시 답답함을 유발하므로, 앞뒤의 묵음 구간을 잘라내야 한다.</p>
<p>단, 너무 칼같이 자르면 소리가 부자연스럽게 끊길 수 있으므로 <strong>0.2초 정도의 패딩(Padding)</strong>을 둔다.</p>
<pre><code class="language-rust">  fn trim_silence(file_path: &amp;Path) -&gt; Result&lt;f32&gt; {
      // 1. 파일 전체를 읽어서 샘플 벡터로 변환
      let (spec, samples) = {
          let mut reader = hound::WavReader::open(file_path)?;
          let spec = reader.spec();
          let samples: Vec&lt;f32&gt; = reader.samples::&lt;f32&gt;().collect::&lt;Result&lt;Vec&lt;&gt;, &gt;&gt;()?;
          (spec, samples)
      let threshold = 0.01;

      // 2. 유효한 소리가 시작되는 지점과 끝나는 지점 찾기
      let start = samples.iter().position(|&amp;s| s.abs() &gt; threshold);
      let end = samples.iter().rposition(|&amp;s| s.abs() &gt; threshold);


      if let (Some(start_idx), Some(end_idx)) = (start, end) {
          // 3. 앞뒤로 0.2초씩 여유(Padding) 주기
          let padding_sec = 0.2;
          let padding_samples = (spec.sample_rate as f32 * padding_sec) as usize;


          let start_padded = start_idx.saturating_sub(padding_samples);
          let end_padded = (end_idx + padding_samples).min(samples.len() - 1);


          // 4. 해당 구간만 잘라서 다시 저장
          let trimmed_samples = &amp;samples[start_padded..=end_padded];
          let mut writer = hound::WavWriter::create(file_path, spec)?;


          for &amp;sample in trimmed_samples {
              writer.write_sample(sample)?;
          }
          writer.finalize()?;

          // 최종 재생 시간 반환
          return Ok(trimmed_samples.len() as f32 / spec.sample_rate as f32);
      }


      Ok(0.0) // 소리가 아예 없는 경우
  }</code></pre>
<h2 id="결과-및-장점">결과 및 장점</h2>
<p>이러한 <strong>VAD + Trimming</strong> 구조를 적용하면 다음과 같은 이점이 있다.</p>
<ol>
<li><p><strong>UX 향상 (Hands-Free)</strong>: &quot;녹음 시작&quot; 버튼 한 번만 누르면 된다. 장갑을 끼고 있거나 화면을 계속 볼 수 없는 환경에 매우 유용하다.</p>
</li>
<li><p><strong>데이터 효율성</strong>: 불필요한 공백을 제거하여 파일 용량을 줄이고, 전송 속도를 높인다.</p>
</li>
<li><p><strong>명확한 의사 전달</strong>: 재생 시 딜레이 없이 즉각적으로 음성이 나오므로, 피치컴(PitchCom)과 같은 신속한 명령 전달 장치에 적합하다.</p>
<h3 id="주의할-점-threshold-튜닝">주의할 점: Threshold 튜닝</h3>
<p><code>silence_threshold</code> 값(여기서는 0.01)은 환경에 따라 튜닝이 필요하다.</p>
</li>
</ol>
<ul>
<li><strong>너무 낮으면:</strong> 주변 소음(바람 소리, 관중 소리) 때문에 녹음이 절대 안 끝날 수 있다.</li>
<li><strong>너무 높으면:</strong> 작게 말하는 소리나 &#39;ㅅ, ㅎ&#39; 같은 고주파 발음이 잘려 나갈 수 있다.</li>
</ul>
<p>실제 환경 테스트를 통해 적절한 값을 찾거나, 사용자 설정으로 빼두는 것이 좋다.</p>
<hr>
<blockquote>
<p><strong>참고</strong>: 이 코드는 Tauri 앱의 백엔드(Rust) 부분에서 동작하며, 프론트엔드와는 비동기 커맨드로 통신한다. 웹 브라우저 API(MediaRecorder)를 쓰지 않고 네이티브 오디오 장치를 직접 제어함으로써 더 정밀한 제어가 가능했다.</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[PCM 확장자]]></title>
            <link>https://velog.io/@charlie_moon/PCM-%ED%99%95%EC%9E%A5%EC%9E%90</link>
            <guid>https://velog.io/@charlie_moon/PCM-%ED%99%95%EC%9E%A5%EC%9E%90</guid>
            <pubDate>Thu, 05 Feb 2026 01:29:59 GMT</pubDate>
            <description><![CDATA[<h1 id="pcm-이란">PCM 이란?</h1>
<p><strong>Pulse Code Modulation</strong>의 약자 펄스 부호 변조는 음성이나 영상 같은 연속적인 아날로그 신호를 0과 1로 이루어진 디지털 신호로 변환하는 가장 대표적인 기술</p>
<hr>
<h1 id="배경">배경</h1>
<h2 id="통신-잡음">통신 잡음</h2>
<p>1930년대 아날로그 통신 시대에는 신호를 멀리 보낼수록 신호가 약해졌고, 이를 다시 키우기 위해 증폭기를 사용해야 했다. 하지만 <strong>증폭기는 신호뿐만 아니라 함께 섞인 잡음(Noise)까지 그대로 키워버리는 치명적인 단점</strong>이 있었다. 거리가 멀어질수록 잡음이 누적되어 통화 품질이 급격히 떨어지는 것이 당시 통신업계의 가장 큰 고민이었다.</p>
<h2 id="알렉-리브스의-아이디어">알렉 리브스의 아이디어</h2>
<p>1937년 영국의 엔지니어인 <strong>알렉 리브스(Alec Reeves)</strong>는 신호를 아예 &#39;숫자(디지털)&#39;로 바꾸어 전송하면 이 문제를 해결할 수 있다고 생각했다.</p>
<p>소리의 높낮이를 숫자로 바꿔 보내면, 전송 중에 잡음이 섞여 신호가 조금 일그러지더라도 수신측에서는 그것이 <strong>&#39;0&#39;인지 &#39;1&#39;인지 명확히 구별</strong>할 수 있고 숫자를 원래대로 복원하기만 하면 잡음 없는 깨끗한 원래의 소리를 되찾을 수 있게 된 것이다.</p>
<h2 id="기술적-한계">기술적 한계</h2>
<p>알렉 리브스는 1937년에 PCM 이론을 정립하고 특허를 냈지만, 당시 진공관 기술로는 복잡한 디지털 변환 회로를 경제적으로 구현하기 어려워 한동안 묻혀 있었다. 그러다 <strong>제2차 세계대전 중 보안이 중요한 군사용 암호 통신(예: SIGSALY 시스템)에 먼저 도입</strong>되며 그 가치를 인정받기 시작했다. </p>
<h2 id="반도체-시대">반도체 시대</h2>
<p>1960년대 이후 트랜지스터와 반도체 기술이 발전하면서 복잡한 회로를 작고 저렴하게 만들 수 있게 되자, 1962년 벨 연구소의 T1 캐리어 시스템을 시작으로 일반 전화망에 PCM이 본격적으로 보급되었다.</p>
<p><strong>CD, MP3, 유튜브의 모든 디지털 사운드는 이 탄생 배경을 뿌리에 두고 있다.</strong></p>
<hr>
<h1 id="과정">과정</h1>
<h2 id="변조">변조</h2>
<h3 id="표본화">표본화</h3>
<p><strong>나이퀴스트 이론</strong>에 따라 아날로그 파형을 일정한 시간 간격으로 잘라 순간적인 진폭값을 추출한다.</p>
<p>샘플링된 진폭의 집합인 <strong>PAM(Pulse Amplitude Modulation)</strong> 신호가 생성된다.</p>
<blockquote>
<p><strong>나이퀴스트 이론</strong>
원래의 소리를 완벽하게 복원하려면, 소리가 가진 최고 주파수의 2배 이상의 속도로 샘플을 채취해야 한다.</br>
인간의 가청 주파수가 약 20kHz이므로, CD 음질은 그 2배인 44.1kHz(1초에 44,100번)로 샘플링</p>
</blockquote>
<h3 id="양자화">양자화</h3>
<p>표본화로 얻은 연속적인 진폭값을 미리 정해진 이산적인(떨어져 있는) 수치로 매칭시키는 과정이다.
<strong>세로축(진폭)을 일정한 단계(Level)로 나누고, 측정된 값이 어느 단계에 가장 가까운지 결정한다.</strong></p>
<h4 id="비트-심도-bit-depth">비트 심도 (Bit Depth)</h4>
<p>단계를 얼마나 세밀하게 나누느냐를 결정한다.</p>
<ul>
<li>8비트: 2^8 = 256 단계로 소리 크기를 조절</li>
<li>16비트: 2^16 = 65,536 단계로 조절 (CD 음질)</li>
</ul>
<p>이 과정에서 필연적으로 발생하는 오차를 <strong>양자화 잡음</strong>이라고 한다.</p>
<blockquote>
<p><strong>양자화 잡음 (Quantization Noise)</strong>
실제 아날로그 값과 디지털로 변환된 근삿값 사이의 미세한 차이를 말한다. 
비트 수가 높을수록 이 오차(잡음)가 줄어든다.</p>
</blockquote>
<h3 id="부호화">부호화</h3>
<p>양자화된 수치 데이터를 2진수(0과 1) 형태의 디지털 코드로 최종 변환한다.
<strong>양자화 단계에서 할당된 10진수 값을 2진법 코드로 바꾼다.</strong></p>
<ul>
<li>예시: 특정 시점의 소리 크기가 &#39;7&#39;번 단계였다면, 이를 3비트 부호화하여 111로 기록</li>
</ul>
<h3 id="결과물">결과물</h3>
<p>우리가 흔히 말하는 순수 디지털 데이터(Binary Stream)가 완성된다. 
이 데이터가 PCM이며 파일(WAV 등)로 저장되거나 통신망을 통해 전송된다.</p>
<blockquote>
<h3 id="요약">요약</h3>
</blockquote>
<h4 id="변조adc--소리곡선-→-점-찍기표본-→-반올림양자-→-숫자0-1">변조(ADC) : 소리(곡선) → 점 찍기(표본) → 반올림(양자) → 숫자(0, 1)</h4>
<h2 id="복조">복조</h2>
<p>복조(Demodulation) 과정은 한 마디로 &#39;숫자(0, 1)를 다시 소리의 파형으로 되돌리는 역과정&#39;, 위 3단계를 정확히 거꾸로 거슬러 올라간다고 생각하면 쉽다.</p>
<h3 id="재생">재생</h3>
<p>전송된 0과 1의 디지털 신호를 다시 읽어 들이는 단계, 전송 과정에서 섞인 잡음을 제거하고, 원래의 깨끗한 &#39;0&#39;과 &#39;1&#39;의 전기적 펄스(부호)를 복원한다.
<strong>디지털은 신호가 조금 찌그러져도 0인지 1인지 판별만 가능하면 원래 신호로 100% 복구할 수 있다.</strong></p>
<h3 id="복호화">복호화</h3>
<p>이진수(0, 1) 데이터를 다시 원래의 양자화된 수치(높이 값)로 바꾸는 과정, 예를 들어 <code>111</code>이라는 데이터를 받았다면, 이를 다시 <code>7</code>이라는 진폭 레벨로 해석한다. 일정한 시간 간격마다 서로 다른 높이를 가진 계단 모양의 펄스(PAM 신호)가 만들어진다.</p>
<h3 id="보간-및-필터링">보간 및 필터링</h3>
<p>가장 중요한 단계로, <strong>각진 계단 모양의 신호를 부드러운 곡선(아날로그 파형)으로 만드는 과정</strong>, <strong>저역 통과 필터(Low Pass Filter)</strong>를 통과시킨다. 이 필터는 급격하게 변하는 계단식의 고주파 성분을 깎아내고, 점과 점 사이를 부드럽게 이어주는 역할을 한다.</p>
<h3 id="결과">결과</h3>
<p>우리가 스피커나 이어폰을 통해 들을 수 있는 매끄러운 아날로그 전기 신호(소리)가 완성된다.</p>
<blockquote>
<h3 id="요약-1">요약</h3>
</blockquote>
<h4 id="복조dac-숫자0-1-→-숫자-읽기복호-→-계단-만들기-→-부드럽게-잇기필터-→-소리곡선">복조(DAC): 숫자(0, 1) → 숫자 읽기(복호) → 계단 만들기 → 부드럽게 잇기(필터) → 소리(곡선)</h4>
<hr>
<h1 id="특징">특징</h1>
<h2 id="잡음에-강함">잡음에 강함</h2>
<p>아날로그와 달리 <strong>신호가 감쇄되더라도 재생 중계기를 통해 원래의 디지털 신호(0 또는 1)를 완벽하게 복원</strong>할 수 있어 전송 품질이 우수.</p>
<h2 id="범용성">범용성</h2>
<p>컴퓨터, CD, DVD, 디지털 전화 등 현대 거의 모든 디지털 오디오 기기의 표준 포맷으로 사용됨.</p>
<h2 id="효율적-전송">효율적 전송</h2>
<p>여러 회선의 신호를 하나의 전송로에 묶어 보내는 <strong>시분할 다중화(TDM) 방식이 가능</strong>해져 통신 효율이 높음.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[WAV 확장자]]></title>
            <link>https://velog.io/@charlie_moon/WAV-%ED%99%95%EC%9E%A5%EC%9E%90</link>
            <guid>https://velog.io/@charlie_moon/WAV-%ED%99%95%EC%9E%A5%EC%9E%90</guid>
            <pubDate>Thu, 05 Feb 2026 00:31:20 GMT</pubDate>
            <description><![CDATA[<h1 id="wav-란">WAV 란?</h1>
<p>WAV(Waveform Audio File Format)는
<strong>마이크로소프트</strong>와 <strong>IBM</strong>이 개발한 <strong>표준 오디오 파일 형식</strong>으로, 오디오 데이터를 압축 없이 그대로 저장하여 <strong>원본에 가까운 무손실 고음질을 제공</strong>한다. 주로 윈도우 환경에서 사용되며, CD와 동일한 PCM 데이터를 사용하여 용량이 크지만 <strong>전문적인 음향 편집에 적합</strong>하다.</p>
<hr>
<h1 id="배경">배경</h1>
<p>WAV가 등장하기 전에는 각 컴퓨터 시스템이나 애플리케이션마다 서로 다른 오디오 포맷을 사용해 호환성이 매우 떨어졌다. <strong>Microsoft</strong>와 <strong>IBM</strong>은 <strong>Windows 3.1</strong> 출시와 함께 누구나 보편적으로 사용할 수 있는 오디오 파일의 표준 규격을 만들고자 했다.</p>
<h2 id="이전-방식">이전 방식</h2>
<h3 id="midi">MIDI</h3>
<p><strong>Musical Instrument Digital Interface</strong>의 약자로 실제 소리를 녹음한 게 아니라 &#39;악기 연주 정보(악보)&#39;만 담은 파일, 용량은 매우 작지만, 컴퓨터 사운드 카드의 성능에 따라 소리 품질이 천차만별이었다.</p>
<h3 id="저품질-모노-녹음">저품질 모노 녹음</h3>
<p>용량을 아끼기 위해 샘플링 레이트를 극단적으로 낮춘(8-bit, 11kHz~22kHz) 모노 음원들이 사용되었다. 라디오보다 못한 지지직거리는 음질이 당시의 일반적인 &#39;컴퓨터 소리&#39;였다. </p>
<h2 id="wav-등장">WAV 등장</h2>
<p>44.1kHz, 16-bit 스테레오(CD 음질)를 지원하는 WAV의 등장은 컴퓨터에서도 가전 오디오(CD 플레이어) 수준의 깨끗한 소리를 낼 수 있다는 것을 의미했다.
비록 용량은 컸지만, 별도의 압축 해제 과정이 필요 없는 비압축 방식이었기에 당시 낮은 CPU 사양에서도 끊김 없이 고음질 오디오를 재생할 수 있는 최선의 선택이었다.</p>
<hr>
<h1 id="riff-구조">RIFF 구조</h1>
<p><strong>WAV</strong>는 데이터를 <strong>chunk</strong> 단위로 저장하는 <strong>RIFF(Resource Interchange File Format)</strong>라는 큰 구조 안에 오디오 데이터를 담는 방식으로 설계되었다.</p>
<h2 id="유연성">유연성</h2>
<p>단순 오디오 정보뿐만 아니라 <strong>제작자</strong>, <strong>샘플 레이트</strong> 등 <strong>다양한 메타데이터를 함께 담을 수 있었다.</strong></p>
<h2 id="직관성">직관성</h2>
<p><strong>압축되지 않은 날것의 데이터(PCM)</strong>를 그대로 담았기 때문에, 당시 사양의 컴퓨터에서도 복잡한 연산 없이 소리를 즉각 재생하고 편집하기에 유리했다.</p>
<hr>
<h1 id="활용">활용</h1>
<h2 id="1990년대-초반">1990년대 초반</h2>
<p>Windows의 부팅음이나 시스템 알림음의 기본 포맷으로 채택되며 대중에게 알려지기 시작했다.
PC에서 CD 수준의 고음질을 재생할 수 있는 거의 유일한 방법이었으며, 초기 멀티미디어 백과사전이나 게임의 음원으로 활용되었다.</p>
<h2 id="1990년대-후반2000년대">1990년대 후반~2000년대</h2>
<h3 id="표준화">표준화</h3>
<p>현재는 전 세계 음악 및 방송 산업의표준 마스터 포맷으로 진화했다.
<strong>무손실의 고음질</strong> 덕분에 일반 감상용을 넘어 <strong>전문 음악 제작 및 방송 분야의 골드 표준</strong>으로 자리 잡게 되었다.
<strong>유럽방송연맹(EBU)</strong>이 WAV를 기반으로 메타데이터를 강화한 <strong>BWF(Broadcast Wave Format)</strong>를 표준으로 정하면서 <strong>전문 방송 및 영화 산업의 필수 포맷</strong>이 되었다.</p>
<h3 id="인터넷과-mp3">인터넷과 MP3</h3>
<p>1990년대 중반 모뎀(Dial-up) 속도로 30MB의 WAV 노래 한 곡을 받으려면 수 시간이 걸렸다. (사실상 온라인 전송이 불가능)</p>
<p>인터넷 속도가 느려, 용량이 큰 WAV는 감상용으로는 부적합했다. 일반 사용자들은 MP3로 옮겨갔지만, 전문가들은 원본 보존을 위해 여전히 WAV를 고수했다.</p>
<p>MP3는 <strong>가청 주파수 밖의 데이터를 삭제</strong>해 음질은 유지하면서 용량을 3~4MB로 줄였다. 덕분에 수분 내에 다운로드가 가능해졌고, 비로소 &#39;음악 파일&#39;이 인터넷을 타고 흐르기 시작했다.</p>
<h2 id="현재">현재</h2>
<h3 id="전문-음향-작업">전문 음향 작업</h3>
<p>데이터 손실 없이 무한 수정이 가능하여, 현재도 모든 음악 레코딩 및 믹싱 단계에서 기본으로 사용된다.</p>
<h3 id="고음질-스트리밍의-뿌리">고음질 스트리밍의 뿌리</h3>
<p>FLAC이나 ALAC 같은 최신 무손실 압축 포맷도 결국 <strong>원본인 WAV 데이터를 압축한 것</strong>이므로, 모든 고음질 음원의 <strong>&#39;마스터 파일&#39;</strong> 역할을 수행한다.</p>
<h3 id="기술적-확장">기술적 확장</h3>
<p>현대의 WAV는 초기의 단순함을 넘어 멀티채널 서라운드 사운드(5.1채널 등)와 고해상도 오디오(192kHz/32-bit 이상)를 모두 담는 유연한 컨테이너로 발전했다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Leptos 시작하기]]></title>
            <link>https://velog.io/@charlie_moon/Leptos-%EC%8B%9C%EC%9E%91%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@charlie_moon/Leptos-%EC%8B%9C%EC%9E%91%ED%95%98%EA%B8%B0</guid>
            <pubDate>Wed, 28 Jan 2026 13:40:18 GMT</pubDate>
            <description><![CDATA[<p><strong><a href="https://leptos.dev/">Leptos</a></strong>는 Rust로 웹프론트 및 서버를 만들 수 있는 풀스택 프레임워크이다.
리액트랑 매우 비슷하다. 아마 리액트에서 영감을 받아 만든것 같다.
리액트의 JSX 처럼 Leptos는 RSX라는 명칭?을 사용한다 공식문서에 대놓고 JSX와 흡사하다고 설명을 해놓았다.</p>
<ul>
<li>Leptos는 특징이 웹어셈블리 베이스로 동작한다. </li>
<li>가상DOM을 사용하지 않고 직접 DOM노드를 수정한다.(리액트 보다 2배 빠른 성능을 내기도 한다.)</li>
<li>Rust의 타입시스템과 효율적인 메모리관리 덕분에 복잡한 UI에서도 굉장히 좋은 유저 경험을 선보인다.</li>
</ul>
<p>가상돔을 사용하지 않고 DOM을 직접 컨트롤하는부분과 컴파일타임 프레임이라는 점이 Sevelte와 매우 유사한거 같다. (개인적으로 Svelte를 좋아한다.)</p>
<p><strong><a href="https://krausest.github.io/js-framework-benchmark/2026/chrome144.html">JS Framework Benchmark</a></strong></p>
<details>
<summary style="font-size: 25px">Leptos React 비교 AI 정리</summary>

<h2 id="js-framework-benchmark-2026-결과-기준">JS Framework Benchmark 2026 결과 기준</h2>
<h3 id="📊-주요-성능-지표-비교">📊 주요 성능 지표 비교</h3>
<h4 id="1-dom-조작-속도">1. DOM 조작 속도</h4>
<table>
<thead>
<tr>
<th>벤치마크 항목</th>
<th>Leptos</th>
<th>React</th>
<th>비율</th>
</tr>
</thead>
<tbody><tr>
<td>Create rows</td>
<td>~1.0x</td>
<td>~1.5-2.0x</td>
<td><strong>Leptos 50-100% 빠름</strong></td>
</tr>
<tr>
<td>Replace all rows</td>
<td>~1.0x</td>
<td>~1.5-2.0x</td>
<td><strong>Leptos 50-100% 빠름</strong></td>
</tr>
<tr>
<td>Partial update</td>
<td>~1.0x</td>
<td>~1.3-1.8x</td>
<td><strong>Leptos 30-80% 빠름</strong></td>
</tr>
<tr>
<td>Select row</td>
<td>~1.0x</td>
<td>~1.2-1.5x</td>
<td><strong>Leptos 20-50% 빠름</strong></td>
</tr>
<tr>
<td>Swap rows</td>
<td>~1.0x</td>
<td>~1.3-1.7x</td>
<td><strong>Leptos 30-70% 빠름</strong></td>
</tr>
<tr>
<td>Remove row</td>
<td>~1.0x</td>
<td>~1.2-1.5x</td>
<td><strong>Leptos 20-50% 빠름</strong></td>
</tr>
</tbody></table>
<h4 id="2-메모리-사용량">2. 메모리 사용량</h4>
<table>
<thead>
<tr>
<th>메트릭</th>
<th>Leptos</th>
<th>React</th>
</tr>
</thead>
<tbody><tr>
<td>초기 메모리</td>
<td>~2-3 MB</td>
<td>~4-6 MB</td>
</tr>
<tr>
<td>10,000 rows 후</td>
<td>~15-20 MB</td>
<td>~30-40 MB</td>
</tr>
<tr>
<td><strong>메모리 효율성</strong></td>
<td><strong>~50% 더 적음</strong></td>
<td>기준</td>
</tr>
</tbody></table>
<h4 id="3-번들-크기">3. 번들 크기</h4>
<table>
<thead>
<tr>
<th>항목</th>
<th>Leptos</th>
<th>React</th>
</tr>
</thead>
<tbody><tr>
<td>최소 번들 (gzipped)</td>
<td>~15-25 KB</td>
<td>~45-50 KB (React + ReactDOM)</td>
</tr>
<tr>
<td><strong>크기 비교</strong></td>
<td><strong>~60-70% 작음</strong></td>
<td>기준</td>
</tr>
</tbody></table>
<hr>
<h2 id="🎯-성능-차이의-원인">🎯 성능 차이의 원인</h2>
<h3 id="leptos의-강점">Leptos의 강점</h3>
<ol>
<li><p><strong>컴파일 타임 최적화</strong></p>
<ul>
<li>Rust 컴파일러가 빌드 시점에 최적화</li>
<li>Dead code elimination이 매우 효과적</li>
<li>타입 안정성으로 런타임 체크 불필요</li>
</ul>
</li>
<li><p><strong>Fine-grained Reactivity</strong></p>
<ul>
<li>컴포넌트 전체가 아닌 변경된 부분만 업데이트</li>
<li>Virtual DOM 없이 직접 DOM 조작</li>
<li>Signal 기반의 효율적인 상태 관리</li>
</ul>
</li>
<li><p><strong>WebAssembly</strong></p>
<ul>
<li>Near-native 성능</li>
<li>효율적인 메모리 관리</li>
<li>GC 오버헤드 없음</li>
</ul>
</li>
</ol>
<h3 id="react의-특징">React의 특징</h3>
<ol>
<li><p><strong>Virtual DOM</strong></p>
<ul>
<li>Diffing 알고리즘 오버헤드</li>
<li>전체 컴포넌트 트리 재평가</li>
<li>하지만 개발 경험은 뛰어남</li>
</ul>
</li>
<li><p><strong>JavaScript Runtime</strong></p>
<ul>
<li>인터프리터 언어의 한계</li>
<li>GC로 인한 pause</li>
<li>타입 체크를 위한 추가 라이브러리 필요</li>
</ul>
</li>
<li><p><strong>거대한 생태계</strong></p>
<ul>
<li>방대한 라이브러리와 도구</li>
<li>커뮤니티 지원</li>
<li>성숙한 개발 패턴</li>
</ul>
</li>
</ol>
<hr>
<h2 id="💡-실무-관점에서의-비교">💡 실무 관점에서의 비교</h2>
<h3 id="leptos를-선택하면-좋은-경우">Leptos를 선택하면 좋은 경우</h3>
<ul>
<li>✅ 고성능이 중요한 애플리케이션 (게임, 데이터 시각화)</li>
<li>✅ 모바일이나 저사양 기기 타겟</li>
<li>✅ 번들 크기를 최소화해야 하는 경우</li>
<li>✅ Rust 생태계 활용이 필요한 경우</li>
<li>✅ 타입 안정성이 최우선인 프로젝트</li>
</ul>
<h3 id="react를-선택하면-좋은-경우">React를 선택하면 좋은 경우</h3>
<ul>
<li>✅ 빠른 프로토타이핑과 개발 속도가 중요</li>
<li>✅ 방대한 서드파티 라이브러리 필요</li>
<li>✅ 대규모 개발팀 (인력 수급 용이)</li>
<li>✅ 기존 JavaScript 생태계 활용</li>
<li>✅ 성능보다 개발 생산성이 우선</li>
</ul>
<hr>
<h2 id="📈-실제-벤치마크-예시">📈 실제 벤치마크 예시</h2>
<h3 id="10000개-행-렌더링-시나리오">10,000개 행 렌더링 시나리오</h3>
<pre><code>Leptos:  ~250ms
React:   ~450ms
차이:    +80% 느림 (React)</code></pre><h3 id="메모리-소비-복잡한-spa">메모리 소비 (복잡한 SPA)</h3>
<pre><code>Leptos:  ~35MB
React:   ~75MB
차이:    +114% 더 많음 (React)</code></pre><h3 id="초기-로딩-시간">초기 로딩 시간</h3>
<pre><code>Leptos:  ~150ms (WASM 로드 포함)
React:   ~200ms
차이:    +33% 느림 (React)</code></pre><hr>
<h2 id="🔄-마이그레이션-고려사항">🔄 마이그레이션 고려사항</h2>
<h3 id="leptos-학습-곡선">Leptos 학습 곡선</h3>
<ul>
<li>Rust 문법 숙달 필요</li>
<li>Ownership/Borrowing 개념 이해</li>
<li>컴파일 타임 에러 디버깅</li>
<li>상대적으로 작은 커뮤니티</li>
</ul>
<h3 id="개발-도구">개발 도구</h3>
<ul>
<li>Leptos: cargo, trunk, VSCode rust-analyzer</li>
<li>React: npm/yarn, webpack/vite, 다양한 DevTools</li>
</ul>
<hr>
<h2 id="🎬-결론">🎬 결론</h2>
<h3 id="성능-우선순위가-높다면">성능 우선순위가 높다면</h3>
<p><strong>Leptos</strong>는 벤치마크에서 일관되게 React보다 1.5-2배 빠른 성능을 보여주며, 특히 대량의 DOM 조작이나 복잡한 상태 업데이트에서 큰 차이를 만듭니다.</p>
<h3 id="생산성과-생태계가-중요하다면">생산성과 생태계가 중요하다면</h3>
<p><strong>React</strong>는 여전히 검증된 선택이며, 성능 차이가 체감되지 않는 대부분의 웹 애플리케이션에서는 개발 속도와 유지보수성이 더 중요할 수 있습니다.</p>
</details>

<hr>
<p>이제 본격적으로 Leptos를 시작해보자</p>
<h1 id="환경구성">환경구성</h1>
<pre><code class="language-bash"># Trunk는 Rust 용 WASM 웹 응용 프로그램 번들러
cargo install trunk</code></pre>
<h1 id="rust-프로젝트-생성">Rust 프로젝트 생성</h1>
<pre><code class="language-bash"># 프로젝트 이름을 ui로 만든다.
cargo new ui

# 이동
cd ui

# 구조 확인
tree 

├── Cargo.toml
└── src
    └── main.rs</code></pre>
<h2 id="target-설치">target 설치</h2>
<pre><code class="language-bash">#웹어셈블리 바이너리 형식으로 빌드할 수 있도록 필요한 도구(타겟)를 설치
rustup target add wasm32-unknown-unknown</code></pre>
<h1 id="의존성-추가">의존성 추가</h1>
<p><code>Cargo.toml</code>에 의존성을 추가해준다.</p>
<pre><code class="language-toml">[package]
...

[dependencies]
# leptos 추가 (Client Side Rendering을 하는 앱을 위해 features를 csr 로 하였다.)
leptos = { version = &quot;0.8.15&quot;, features = [&quot;csr&quot;] }</code></pre>
<h1 id="indexhtml-생성">index.html 생성</h1>
<p>프로젝트 최상단에 <code>index.html</code>을 만든다.</p>
<pre><code class="language-bash">├── Cargo.lock
├── Cargo.toml
├── index.html # 생성
└── src
    └── main.rs</code></pre>
<h2 id="indexhtml">index.html</h2>
<pre><code class="language-html">&lt;!doctype html&gt;
&lt;html&gt;
    &lt;head&gt;&lt;/head&gt;
    &lt;body&gt;&lt;/body&gt;
&lt;/html&gt;</code></pre>
<h1 id="mainrs-작성">main.rs 작성</h1>
<pre><code class="language-rust">use leptos::prelude::*;

fn main() {
    leptos::mount::mount_to_body(|| view! { &lt;p&gt;&quot;Hello, world!&quot;&lt;/p&gt; })
}</code></pre>
<h1 id="실행해보기">실행해보기</h1>
<pre><code class="language-bash"># 실행
trunk serve</code></pre>
<p>터미널에 표시된 주소를 열면 잘 내용이 잘 나오는걸 볼 수 있다.</p>
<p><img src="https://velog.velcdn.com/images/charlie_moon/post/98fa7469-3d99-4233-a801-be25e7544c38/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Synology NAS에 개발환경 세팅하지 말자]]></title>
            <link>https://velog.io/@charlie_moon/Synology-NAS%EC%97%90-%EA%B0%9C%EB%B0%9C%ED%99%98%EA%B2%BD-%EC%84%B8%ED%8C%85%ED%95%98%EC%A7%80-%EB%A7%90%EC%9E%90</link>
            <guid>https://velog.io/@charlie_moon/Synology-NAS%EC%97%90-%EA%B0%9C%EB%B0%9C%ED%99%98%EA%B2%BD-%EC%84%B8%ED%8C%85%ED%95%98%EC%A7%80-%EB%A7%90%EC%9E%90</guid>
            <pubDate>Wed, 28 Jan 2026 12:33:46 GMT</pubDate>
            <description><![CDATA[<p>지난 글에서 Synology NAS에 Rust를 설치하였다. (물론 컴파일 불가.)
요번에 NAS 앱 개발에 대해서 알아보다가 Synology 공식 홈페이지에서 아래와 같은 문구를 발견했다.</p>
<p><img src="https://velog.velcdn.com/images/charlie_moon/post/42a0a9f5-f750-40b9-b8f1-8602d7e1d3a3/image.png" alt=""></p>
<p>공식 홈페이지에서 강력하게 개발 Toolkit을 설치하여 개발환경 셋팅을 하지 말라는 것이었다. 하고 싶다면 Docker를 설치해서 환경을 구성하라는건데...</p>
<p>나는 구형 DS218j 모델이라 도커를 설치 할 수 가 없다... 그냥 외부에서 작업해서 크로스컴 파일 해서 사용하는 수 밖에 없을 것 같다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[musl을 이용해서 컴파일 하기]]></title>
            <link>https://velog.io/@charlie_moon/musl%EC%9D%84-%EC%9D%B4%EC%9A%A9%ED%95%B4%EC%84%9C-%EC%BB%B4%ED%8C%8C%EC%9D%BC-%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@charlie_moon/musl%EC%9D%84-%EC%9D%B4%EC%9A%A9%ED%95%B4%EC%84%9C-%EC%BB%B4%ED%8C%8C%EC%9D%BC-%ED%95%98%EA%B8%B0</guid>
            <pubDate>Sun, 25 Jan 2026 15:12:47 GMT</pubDate>
            <description><![CDATA[<p>로컬에서 빌드한 Rust 바이너리를 임베디드 Linux 디바이스로 전송해 실행했더니 다음과 같은 에러가 발생했다.</p>
<pre><code>./example: /lib/libc.so.6: version `GLIBC_2.28&#39; not found (required by ./example)
./example: /lib/libc.so.6: version `GLIBC_2.30&#39; not found (required by ./example)
./example: /lib/libc.so.6: version `GLIBC_2.33&#39; not found (required by ./example)
./example: /lib/libc.so.6: version `GLIBC_2.32&#39; not found (required by ./example)
./example: /lib/libc.so.6: version `GLIBC_2.34&#39; not found (required by ./example)</code></pre><p>개발 환경에서는 잘 실행되던 프로그램이 타겟 시스템에서는 GLIBC 버전 문제로 실행되지 않는 것이다.</p>
<h1 id="원인-분석">원인 분석</h1>
<p>빌드 환경의 GLIBC 버전(2.34)과 타겟 시스템의 GLIBC 버전(2.27 이하)이 맞지 않아 발생하는 호환성 문제다.</p>
<p>GLIBC 동적 링크 바이너리는 시스템의 libc.so.6 등의 공유 라이브러리에 의존하기 때문에, 타겟 시스템에 호환되는 버전의 라이브러리가 필요하다.</p>
<h1 id="해결-방법">해결 방법</h1>
<p>크게 두 가지 접근 방법이 있다:</p>
<ol>
<li><strong>GLIBC 버전 맞추기</strong> - 타겟 시스템 업그레이드 또는 낮은 버전으로 재빌드</li>
<li><strong>musl 정적 링크</strong> - 외부 의존성을 제거하여 모든 환경에서 실행 가능</li>
</ol>
<h1 id="musl이란">musl이란?</h1>
<p>musl은 경량 C 표준 라이브러리로, 정적 링크에 최적화되어 있다.
GLIBC의 대안으로 특히 임베디드 시스템과 컨테이너 환경에서 널리 사용된다.</p>
<h2 id="주요-특징">주요 특징</h2>
<p><strong>장점:</strong></p>
<ul>
<li>정적 링크 최적화 - 단일 실행 파일 생성 용이</li>
<li>높은 이식성 - GLIBC 버전과 무관하게 실행</li>
<li>작은 크기 - GLIBC보다 가볍고 컴팩트</li>
<li>의존성 제거 - 시스템 라이브러리 불필요</li>
<li>배포 간소화 - 단일 파일만 전송</li>
</ul>
<p><strong>단점:</strong></p>
<ul>
<li>약간의 성능 저하 (5-10%, 특히 멀티스레딩)</li>
<li>일부 GLIBC 전용 기능 미지원</li>
<li>정적 링크로 인한 바이너리 크기 증가</li>
</ul>
<h1 id="glibc-vs-musl-비교">GLIBC vs musl 비교</h1>
<table>
<thead>
<tr>
<th>항목</th>
<th>GLIBC 동적 링크</th>
<th>musl 정적 링크</th>
</tr>
</thead>
<tbody><tr>
<td>의존성</td>
<td>libc.so.6 등 필요</td>
<td>없음</td>
</tr>
<tr>
<td>이식성</td>
<td>낮음 (버전 의존)</td>
<td>높음 (모든 Linux)</td>
</tr>
<tr>
<td>바이너리 크기</td>
<td>작음</td>
<td>큼</td>
</tr>
<tr>
<td>성능</td>
<td>우수</td>
<td>약간 느림</td>
</tr>
<tr>
<td>배포</td>
<td>복잡</td>
<td>간단</td>
</tr>
</tbody></table>
<h2 id="의존성-비교">의존성 비교</h2>
<p><strong>GLIBC 빌드:</strong>
$ ldd example
libc.so.6 =&gt; /lib/libc.so.6
libm.so.6 =&gt; /lib/libm.so.6
...</p>
<p>musl 정적 빌드:
$ ldd example
not a dynamic executable</p>
<h2 id="언제-musl을-사용하나">언제 musl을 사용하나?</h2>
<ul>
<li><p>musl이 적합한 경우  </p>
<ul>
<li><p>CLI 도구, 유틸리티</p>
</li>
<li><p>컨테이너/Docker 이미지 (Alpine Linux)</p>
</li>
<li><p>임베디드 시스템</p>
</li>
<li><p>다양한 환경에 배포해야 하는 경우</p>
</li>
<li><p>구형 시스템에 배포하는 경우</p>
</li>
</ul>
</li>
<li><p>GLIBC가 적합한 경우</p>
<ul>
<li>최고 성능이 필요한 서버 애플리케이션</li>
<li>GUI 애플리케이션 (GTK, Qt 등)</li>
<li>복잡한 C 라이브러리 의존성이 있는 경우</li>
</ul>
</li>
</ul>
<h1 id="musl을-선택한-이유">musl을 선택한 이유</h1>
<p>대상 환경은 Synology NAS이다.
Synology DSM은 시스템 핵심 라이브러리인 GLIBC를 함부로 업데이트할 수 없는 환경이다. GLIBC 버전을 변경하면 DSM 전체가 불안정해지거나 부팅 불가 상태가 될 위험이 있다.
이러한 제약 때문에 시스템 라이브러리에 의존하지 않는 musl 정적 링크 방식을 선택했다.</p>
<h1 id="musl로-빌드하기">musl로 빌드하기</h1>
<h2 id="필수-도구-설치">필수 도구 설치</h2>
<pre><code class="language-bash">sudo apt update
sudo apt install musl-tools gcc-arm-linux-gnueabihf</code></pre>
<h2 id="rust-타겟-추가">Rust 타겟 추가</h2>
<pre><code class="language-bash">rustup target add arm-unknown-linux-musleabihf</code></pre>
<h2 id="cargo-설정">Cargo 설정</h2>
<pre><code class="language-bash"># ~/.cargo/config.toml 파일에 링커 설정 추가
[target.arm-unknown-linux-musleabihf]
linker = &quot;arm-linux-gnueabihf-gcc&quot;</code></pre>
<h2 id="빌드">빌드</h2>
<pre><code class="language-bash">cargo build --target arm-unknown-linux-musleabihf --release</code></pre>
<p>빌드된 바이너리는 target/arm-unknown-linux-musleabihf/release/ 디렉토리에 생성된다.</p>
<p><img src="https://velog.velcdn.com/images/charlie_moon/post/1c707c3d-17fd-4c06-9993-286df1938703/image.png" alt=""></p>
<p>잘 실행이 되었다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Synology NAS DS218j에 Rust  설치하기]]></title>
            <link>https://velog.io/@charlie_moon/Synology-NAS-DS218j%EC%97%90-Rust-%EC%84%A4%EC%B9%98%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@charlie_moon/Synology-NAS-DS218j%EC%97%90-Rust-%EC%84%A4%EC%B9%98%ED%95%98%EA%B8%B0</guid>
            <pubDate>Sun, 25 Jan 2026 12:33:58 GMT</pubDate>
            <description><![CDATA[<p>집에 예전에 사다 놓은 DS218j에 Rust를 설치해 볼 예정이다. 예전에 설치해보려고 했었는데 뭐가 뭔지 몰라서 설치를 못해봤었다.</p>
<h1 id="hardware-specs">Hardware Specs</h1>
<p><img src="https://velog.velcdn.com/images/charlie_moon/post/dc55db98-3f72-4a86-8963-6e73f01e1719/image.png" alt=""></p>
<p>DS218j의 하드웨어 스펙 참고로 32bit 이다.
Docker를 지원하지 않는다...</p>
<h1 id="ssh-접속">SSH 접속</h1>
<p><img src="https://velog.velcdn.com/images/charlie_moon/post/d2f126b6-dd18-4e15-a297-64c4a5301ad1/image.png" alt=""></p>
<p>먼저 ssh로 NAS에 접속한다.</p>
<h1 id="rust-설치">Rust 설치</h1>
<p><img src="https://velog.velcdn.com/images/charlie_moon/post/03eb67f6-02aa-4233-99f9-70a8723b2983/image.png" alt=""></p>
<p><a href="https://rustup.rs/">rustup.rs</a> 링크에서 리눅스용 터미널 커맨드를 복사 붙여 넣기 하였다.</p>
<pre><code class="language-bash">curl --proto &#39;=https&#39; --tlsv1.2 -sSf https://sh.rustup.rs | sh</code></pre>
<p>그랬더니 오류가 나왔다.</p>
<h2 id="오류-발생1">오류 발생1</h2>
<pre><code class="language-bash">error: Cannot execute /tmp/tmp.lSpi4HlAnJ/rustup-init (likely because of mounting /tmp as noexec).
error: Please copy the file to a location where you can execute binaries and run ./rustup-init.</code></pre>
<p>검색해보니 <code>noexec</code> 옵션 때문에 <code>/tmp</code>를 사용 할 수 없다는 것이었다.</p>
<h3 id="해결방법">해결방법</h3>
<h4 id="방법1">방법1</h4>
<pre><code class="language-bash">#홈 디렉터리에 tmp폴더 만들기
mkdir -p ~/tmp  
#Rust 설치스크립트 다운로드
curl --proto &#39;=https&#39; --tlsv1.2 -sSf https://sh.rustup.rs -o ~/rustup-init.sh
#실행 권한 부여
chmod +x ~/rustup-init.sh
#홈 디렉터리 tmp를 임시폴더로 설정 및 실행
TMPDIR=~/tmp ~/rustup-init.sh</code></pre>
<h4 id="방법2">방법2</h4>
<pre><code class="language-bash"># 임시 해제 (재부팅 시 초기화)
sudo mount -o remount,exec /tmp
# 설치
curl --proto &#39;=https&#39; --tlsv1.2 -sSf https://sh.rustup.rs | sh</code></pre>
<p><img src="https://velog.velcdn.com/images/charlie_moon/post/9182cbb2-b6b5-419e-941e-9ad3404c9d69/image.png" alt=""></p>
<p>설치 화면이 잘 나온다.</p>
<p><img src="https://velog.velcdn.com/images/charlie_moon/post/3d764cc6-ad9d-4d63-b87d-2c197a8eba53/image.png" alt=""></p>
<p>설치완료</p>
<p><img src="https://velog.velcdn.com/images/charlie_moon/post/5415a022-e7ca-4650-bdd7-59e6ba622f7e/image.png" alt=""></p>
<p>버전 확인</p>
<h2 id="오류-발생2">오류 발생2</h2>
<pre><code class="language-bash">error: linker `arm-linux-gnueabihf-gcc` not found
  |
  = note: No such file or directory (os error 2)

error: could not compile `api-server` (bin &quot;api-server&quot;) due to 1 previous error</code></pre>
<p>Rust가 크로스 컴파일 링커를 찾지 못하고 있어서 인데
외부에서 크로스 컴파일을 하거나 Docker를 사용하라는 솔루션이 있는데 Docker를 지원하지 않기 때문에 어쩔 수 없이 외부에서 빌드를 해서 실행 하는 방향으로 생각해봐야겠다.</p>
<h1 id="결론">결론</h1>
<p>설치는 할 수 있으나. 컴파일이 되지 않는다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Rust 하위 Workspace 만들기]]></title>
            <link>https://velog.io/@charlie_moon/Rust-%ED%95%98%EC%9C%84-Workspace-%EB%A7%8C%EB%93%A4%EA%B8%B0</link>
            <guid>https://velog.io/@charlie_moon/Rust-%ED%95%98%EC%9C%84-Workspace-%EB%A7%8C%EB%93%A4%EA%B8%B0</guid>
            <pubDate>Sun, 25 Jan 2026 06:22:21 GMT</pubDate>
            <description><![CDATA[<p>개발을 진행하다보면 규모가 점점 커지게 되고 관리하기 쉽지 않다 그럴때 패키지 단위로 관심사를 분류해서 관리하게 되는데 Rust에서는 Workspace로 나누어 관리하면 좋다. 필자의 경험을 바탕으로 비유하자면 Android 개발에서 <strong>다중 모듈화</strong> 라고 볼 수 있겠다.</p>
<h1 id="프로젝트-생성하기">프로젝트 생성하기</h1>
<p><img src="https://velog.velcdn.com/images/charlie_moon/post/0712a11d-9a6d-460d-b666-ac5876d6655b/image.png" alt=""></p>
<p>기존 프로젝트에서 새로운 프로젝트를 생성해준다.</p>
<pre><code class="language-bash">    cargo new &lt;새로운 워크스페이스 이름&gt;</code></pre>
<h1 id="workspace-추가">Workspace 추가</h1>
<p><img src="https://velog.velcdn.com/images/charlie_moon/post/2bfc066e-7e19-4222-8caf-134c250a97cc/image.png" alt=""></p>
<p>root에 위치한 <code>Cargo.toml</code> 파일에 <code>workspace</code> 테이블을 만들고 <code>resolver</code>,<code>member</code>키를 선언하고 값을 입력해준다.</p>
<h2 id="resolver">resolver</h2>
<p>Cargo에서 지원하는 프로젝트 dependency의 feature 조합을 계산하는 기능이다.</p>
<blockquote>
<p>주요 차이점:
resolver = &quot;1&quot;: 오래된 방식
resolver = &quot;2&quot;: dev-dependencies가 일반 dependencies의 feature에 영향을 주지 않음, edition 2021 부터는 2이 기본값이다.
resolver = &quot;3&quot;: Rust 1.84+ 필수, MSRV(Minimum Supported Rust Version) 관리 개선, edition 2024 부터는 3이 기본값이다.</p>
</blockquote>
<h2 id="members">members</h2>
<p>어떤 패키지를 멤버로 사용할지 정의한다. 대괄호를 사용하여 (경로가 포함 된)디렉토리 이름을 문자열로 선언해줍니다.</p>
</br>
</br>


<p><strong>이렇게 해놓으면 root에서 <code>cargo build</code>를 수행하여도 하위 workspace들까지 모두 한번에 build가 된다.</strong></p>
<h1 id="workspace-사용해보기">Workspace 사용해보기</h1>
<h2 id="의존성-추가">의존성 추가</h2>
<p><img src="https://velog.velcdn.com/images/charlie_moon/post/1d0a6d5c-b651-4c6f-81ab-f94a12f80435/image.png" alt=""></p>
<p><code>main.rs</code> 를 <code>lib.rs</code> 로 변경한다. 그리고 <code>fn main</code>을 다른 함수로 작성한다. <code>main.rs</code>를<code>lib.rs</code>로 만드는 이유는 <strong>이 프로젝트를 실행 가능한 프로그램이 아닌 재사용 가능한 라이브러리로 전환한다는 의미이다.</strong></p>
<p><img src="https://velog.velcdn.com/images/charlie_moon/post/2a497434-1a9f-496f-bd34-a3989814c147/image.png" alt=""></p>
<p>root <code>Cargo.toml</code>의 depentancies 테이블에 의존성을 등록해준다.</p>
<p><img src="https://velog.velcdn.com/images/charlie_moon/post/e6d3452c-d0ea-47de-b10e-6d94095cae9c/image.png" alt=""></p>
<p>root의 <code>main.rs</code>에 하위 워크스페이스의 함수를 호출하는 코드를 작성한다.</p>
<p><img src="https://velog.velcdn.com/images/charlie_moon/post/9bf8ea4b-875a-4fee-8cb8-997935e12a2f/image.png" alt=""></p>
<p>실행을 시키면 잘 동작한다.</p>
<h1 id="그래서-workspace를-사용하면-뭐가-좋은가">그래서 Workspace를 사용하면 뭐가 좋은가?</h1>
<h2 id="빌드-시간-단축">빌드 시간 단축</h2>
<h3 id="독립적-컴파일-증분-빌드">독립적 컴파일, 증분 빌드</h3>
<p>모노리스 프로젝트로 관리하게 되면 파일 하나만 변경하여도 전체를 다시 컴파일 해야 할 수 도 있지만 워크스페이스를 사용하여 여러 크레이트(패키지)로 관리하면 변경되지 않은 크레이트의 컴파일 결과물을 재사용하게 되어 시간 단축이 있다.</p>
<h2 id="의존성-관리-효율화-및-일관성">의존성 관리 효율화 및 일관성</h2>
<h3 id="단일화">단일화</h3>
<p>워크스페이스 내의 모든 크레이트는 하나의 Cargo.lock 파일을 공유하게 된다.</p>
<h3 id="버전-통일">버전 통일</h3>
<p>단일 Cargo.lock 파일을 통해 모든 크레이트가 동일한 버전의 의존성을 사용하도록 보장하고, target 폴더를 공유하여 중복 빌드를 방지한다.</p>
<h2 id="코드-구조화-및-모듈화">코드 구조화 및 모듈화</h2>
<h3 id="논리적-분리">논리적 분리</h3>
<p>애플리케이션의 핵심 로직, CLI 도구, API 서버 등 분리하여 관리 할 수 있다.</p>
<h3 id="코드-재사용">코드 재사용</h3>
<p>공통으로 사용하는 유틸리티나 데이터 모델을 별도의 라이브러리로 만들어 다른 크레이트에서 쉽게 재사용을 할 수 있다.</p>
<h3 id="관심사-분리">관심사 분리</h3>
<p>각 크레이트가 자신만의 책임을 갖게 되어 코드 베이스가 깔끔해지고 유지보수가 용이해 진다.</p>
<h2 id="개발-워크플로우-최적화">개발 워크플로우 최적화</h2>
<h3 id="한번에-빌드테스트">한번에 빌드/테스트</h3>
<p><code>cargo &lt;command&gt; --workspace</code> 명령을 사용해서 root에서 모든 크레이트를 한번에 빌드하거나 테스트 할 수 있다.</p>
<h1 id="언제-사용해야-하나">언제 사용해야 하나</h1>
<ul>
<li>프로젝트가 커져서 빌드 시간이 답답하게 느껴질 때</li>
<li>하나의 프로젝트 안에 여러 개의 실행 파일(Binary)이나 라이브러리가 공존할 때</li>
<li>공통 코드를 여러 곳에서 공유해야 할 때</li>
</ul>
<hr>
<h3 id="cargo-book"><a href="https://doc.rust-lang.org/cargo/index.html">Cargo Book</a></h3>
]]></description>
        </item>
        <item>
            <title><![CDATA[Rust New Project 만들기]]></title>
            <link>https://velog.io/@charlie_moon/Rust-New-Project-%EB%A7%8C%EB%93%A4%EA%B8%B0</link>
            <guid>https://velog.io/@charlie_moon/Rust-New-Project-%EB%A7%8C%EB%93%A4%EA%B8%B0</guid>
            <pubDate>Sat, 24 Jan 2026 16:51:55 GMT</pubDate>
            <description><![CDATA[<p>러스트를 설치하면 자연스럽게 <code>cargo</code> 라는 빌드 시스템 및 패키지 매니저를 하는 도구가 설치된다. 이걸 통해서 프로젝트를 만들 수 있다.</p>
<pre><code class="language-bash">cargo new &lt;프로젝트 이름&gt;</code></pre>
<p><img src="https://velog.velcdn.com/images/charlie_moon/post/b5891192-4c87-4003-aa8b-f496699941f6/image.png" alt=""></p>
<p>프로젝트 이름은 <code>Rust</code> 언어가 사용하고 있는 예약 키워드로 프로젝트 이름을 만들 수는 없다. 그렇게 하고 싶다면 예약 키워드가 아닌 다른 이름으로 프로젝트를 만든 뒤 <code>Cargo.toml</code>에서 <code>name</code>을 변경해야 한다.</p>
<p><img src="https://velog.velcdn.com/images/charlie_moon/post/7fd8f3f4-62b8-4e18-b8f2-40c8f18b39ec/image.png" alt=""></p>
<p>프로젝트가 생성되었다.
코드 편집기를 이용해서 프로젝트를 열어보자</p>
<p><img src="https://velog.velcdn.com/images/charlie_moon/post/1f244b1b-6052-42c2-86d8-eb9c22c99209/image.png" alt=""></p>
<p>프로젝트를 생성하면 이런 구조가 만들어진다.</p>
<pre><code class="language-bash">EXAMPLE
|   .gitignore    # git에서 추적을 무시해야하는 파일 목록 파일
|   Cargo.toml    # Cargo 설정 파일 
\---src
        main.rs    # 러스트 소스코드</code></pre>
<h1 id="mainrs">main.rs</h1>
<p><img src="https://velog.velcdn.com/images/charlie_moon/post/cc56cc1b-da61-4a51-b44c-a10b28cfb373/image.png" alt=""></p>
<p><code>main.rs</code> 파일을 열어보면 <code>Hello, world!</code> 를 출력하는 기본 코드가 작성되어 있다.</p>
<p><img src="https://velog.velcdn.com/images/charlie_moon/post/53865173-52fb-41aa-ad81-0441dd0f399e/image.png" alt=""></p>
<p>해당 경로로 터미널을 열어서 <code>cargo build</code> 를 해준다.</p>
<p><img src="https://velog.velcdn.com/images/charlie_moon/post/2749c5c2-bfd8-4c9a-b6cb-267a9a809663/image.png" alt=""></p>
<p><code>cargo run</code> 으로 실행을 해주면 Hello world! 가 출력된다.</p>
<p><code>cargo build</code>를 안하고 바고 <code>cargo run</code>을 해주어도 된다. <code>cargo run</code>을 하면 build를 수행하고 실행한다.</p>
<p><img src="https://velog.velcdn.com/images/charlie_moon/post/f4ac99c5-821b-4256-847b-f69947d5b9ea/image.png" alt=""></p>
<p>실행 할때 나오는 빌드 관련 출력이 보고 싶지 않다면 <code>-q</code> 옵션(quiet) 로 실행하면 빌드 관련된 출력이 없이 프로그램 출력만 나온다.</p>
<h1 id="cargotoml">Cargo.toml</h1>
<p><img src="https://velog.velcdn.com/images/charlie_moon/post/361362ea-776d-419a-828e-fbdf24ed74cf/image.png" alt=""></p>
<h2 id="package">package</h2>
<p>소스 파일과 패키지를 설명하는 매니패스트 파일 모음집이다.</p>
<h3 id="name">name</h3>
<p><strong>패키지 이름은 패키지를 참조하는 데 사용되는 식별자</strong>이다 이는 다른 패키지의 종속성으로 나열될 때 사용되며 유추된 lib 및 bin 대상의 기본 이름으로 사용된다.
이름은 영문과숫자만 사용 할 수 있으며 <code>-</code>나<code>_</code>로 구분자를 줄 수 있다.</p>
<p><img src="https://velog.velcdn.com/images/charlie_moon/post/c4e5396c-9744-479e-a5ca-18aac8e2ba32/image.png" alt=""></p>
<p>한글을 섞었을때 실패</p>
<p><img src="https://velog.velcdn.com/images/charlie_moon/post/d3af3175-8a20-4671-8988-dcda89cd25f6/image.png" alt=""></p>
<p>이모지를 섞었을때 실패</p>
<p><img src="https://velog.velcdn.com/images/charlie_moon/post/29085043-04a6-4f7a-adbe-176d1bce07b3/image.png" alt=""></p>
<p>영문과 <code>_</code>, 숫자를 섞었을때 성공</p>
<h3 id="version">version</h3>
<p><a href="https://semver.org/">SemVer</a> 사양에 따라 형식이 지정된다.
버전에는 <strong>주 버전, 부 버전, 패치 버전</strong>의 세 가지 숫자 부분이 있어야 한다.</p>
<p><img src="https://velog.velcdn.com/images/charlie_moon/post/cb6ee95d-df0d-4b84-a95a-36141fc5f0ec/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/charlie_moon/post/b7f71049-6753-4206-8c7f-b5caaf561763/image.png" alt=""></p>
<p>주 버전, 부 버전, 패치 버전 구성을 지키지 않았을때</p>
<p><img src="https://velog.velcdn.com/images/charlie_moon/post/a752866e-76c0-4feb-8ada-ddf61d6554b9/image.png" alt=""></p>
<p>뒤에 <code>-</code>를 붙여서 알파/베타 버전용으로 만들 수 있다.</p>
<p><img src="https://velog.velcdn.com/images/charlie_moon/post/ebe0fb6f-f6bb-4b83-b0f9-a983bf3e776b/image.png" alt=""></p>
<p><code>+</code>를 붙여서 메타데이터를 추가 할 수 있다. 정보 제공 목적이고 Cargo에서 무시된다고 한다.</p>
<h3 id="edition">edition</h3>
<p><code>edition</code> 키는 패키지가 컴파일되는 Rust 에디션에 영향을 미치는 선택적 키이다.
테스트 스위트, 벤치마크, 바이너리, 예제 등을 포함한 패키지의 모든 대상/크레이트에 영향을 미친다.
에디션 필드를 입력하지 않으면 자동으로 2015 에디션으로 동작하게 된다. </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[WindowsOS Rust Install ]]></title>
            <link>https://velog.io/@charlie_moon/WindowsOS-Rust-Install</link>
            <guid>https://velog.io/@charlie_moon/WindowsOS-Rust-Install</guid>
            <pubDate>Sat, 24 Jan 2026 16:23:51 GMT</pubDate>
            <description><![CDATA[<h1 id="installer-download">Installer Download</h1>
<h2 id="rust"><a href="https://rust-lang.org/tools/install/">Rust</a></h2>
<p><img src="https://velog.velcdn.com/images/charlie_moon/post/33cf469c-b825-489d-b309-ba2e1eeb38de/image.png" alt=""></p>
<h1 id="설치">설치</h1>
<p><img src="https://velog.velcdn.com/images/charlie_moon/post/7b09cad2-f4d7-4b6a-bfff-3a5c0bb564aa/image.png" alt=""></p>
<p>Y 입력</p>
<p><img src="https://velog.velcdn.com/images/charlie_moon/post/4fde799c-3fc5-49ec-b84d-8d60aa15fe76/image.png" alt=""></p>
<p>원하는 설치 타입선택 1번 기본설치 (그냥 엔터누르면 1번으로 설치됨)</p>
<p><img src="https://velog.velcdn.com/images/charlie_moon/post/104a71a2-fde4-448d-b8df-e19acc661754/image.png" alt=""></p>
<p>설치완료 (하단에 나온 메시지 대로 환경 변수 편집에서 bin 경로 등록)</p>
<h1 id="환경변수-설정">환경변수 설정</h1>
<p><img src="https://velog.velcdn.com/images/charlie_moon/post/7dbd0a63-e541-4c8f-b7b2-b2354e8e2c6d/image.png" alt=""></p>
<p><strong>시스템 환경변수 편집</strong>에 들어간다.</p>
<p><img src="https://velog.velcdn.com/images/charlie_moon/post/cba55d2f-9bff-493f-a873-8b0f4fc45645/image.png" alt=""></p>
<p><strong>환경 변수(N)...</strong> 클릭</p>
<p><img src="https://velog.velcdn.com/images/charlie_moon/post/fa6b99ab-b258-4005-92a4-b8371d3e1fc2/image.png" alt=""></p>
<p>상단에 Path 더블클릭</p>
<p><img src="https://velog.velcdn.com/images/charlie_moon/post/2ba6bfce-8afc-4102-9280-0046db2b4dd5/image.png" alt=""></p>
<p>여러 값들이 있는데 
&lt;메인드라이버&gt;:\Users&lt;유저이름&gt;.cargo\bin 가 있는지 확인
없다면 새로만들기 해서 등록해주면 된다.</p>
<p><img src="https://velog.velcdn.com/images/charlie_moon/post/434da697-5c26-4f24-87fa-6e1f538b4666/image.png" alt=""></p>
<p>터미널 켜서 <code>cargo --version</code> 입력하여 버전이 출력된다면 설치가 완료 된것이다.</p>
]]></description>
        </item>
    </channel>
</rss>