<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>DataScience</title>
    <link>https://data-science.tistory.com/</link>
    <description>Computer Vision Engineer</description>
    <language>ko</language>
    <pubDate>Sun, 14 Jun 2026 18:43:56 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>Ninestar</managingEditor>
    <image>
      <title>DataScience</title>
      <url>https://tistory1.daumcdn.net/tistory/5833672/attach/8541a041b63446f7b45598967bf16955</url>
      <link>https://data-science.tistory.com</link>
    </image>
    <item>
      <title>SK 통신사 모뎀 + iptime 공유기 환경에서 외부 VPN 접속 구축기 (WireGuard)</title>
      <link>https://data-science.tistory.com/737</link>
      <description>&lt;p&gt;그지같은 TAPO 스마트 도어벨(tp-link TAPO D230s1)이 같은 wifi망이 아니면 벨-통화나 녹화 이벤트 영상재생이 안되어 외부에서 도저히 확인이 불가능했습니다. 외부에서도 도어벨이 연결되어있는 공유기 접속하여 위 기능이 정상 동작하도록 하였습니다.&lt;br&gt;TAPO 스마트 도어벨 사지마세요. 절대 사지마세요.&lt;/p&gt;
&lt;h2&gt;환경&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;인터넷 → SK 통신사 모뎀 (NAT) → iptime 공유기 (NAT) → 내부 장치들&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;SK 모뎀&lt;/strong&gt;: 브리지 모드 미사용 (이중 NAT 상태)&lt;ul&gt;
&lt;li&gt;관리 페이지: &lt;code&gt;192.168.xxx.1&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;WAN IP: 공인 유동 IP (이하 &lt;code&gt;xxx.xxx.xxx.xxx&lt;/code&gt;로 표기)&lt;/li&gt;
&lt;li&gt;LAN 대역: &lt;code&gt;192.168.xxx.0/24&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;iptime 공유기&lt;/strong&gt;:&lt;ul&gt;
&lt;li&gt;WAN IP: &lt;code&gt;192.168.xxx.yy&lt;/code&gt; (SK 모뎀이 할당한 사설 IP)&lt;/li&gt;
&lt;li&gt;관리 페이지 (LAN 게이트웨이): &lt;code&gt;192.168.0.zzz&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;LAN 대역: &lt;code&gt;192.168.0.0/24&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;클라이언트&lt;/strong&gt;: Android 16 스마트폰&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;DDNS&lt;/strong&gt;: No-IP (&lt;code&gt;사용자도메인.ddns.net&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;p&gt;  본문에서 &lt;code&gt;xxx.xxx.xxx.xxx&lt;/code&gt; 같은 표기는 본인 환경의 실제 값으로 대체해서 사용하세요.&lt;/p&gt;
&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;h2&gt;전체 구조&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;[외부 핸드폰 (LTE/5G)]
        ↓
사용자도메인.ddns.net (No-IP DDNS)
        ↓
xxx.xxx.xxx.xxx (SK 모뎀 공인 IP)
        ↓
SK 모뎀 포트포워딩 (UDP 임의포트)
        ↓
192.168.xxx.yy (iptime WAN)
        ↓
iptime WireGuard 서버
        ↓
192.168.0.0/24 내부망 접근 가능&lt;/code&gt;&lt;/pre&gt;&lt;hr&gt;
&lt;h2&gt;시도 1: L2TP/IPSec — 실패한 접근&lt;/h2&gt;
&lt;p&gt;처음에는 표준 VPN인 L2TP/IPSec으로 시도했지만 두 가지 벽에 부딪혔습니다.&lt;/p&gt;
&lt;h3&gt;문제 1: SK 통신사가 IPSec 표준 포트(500, 4500) 차단&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;yougetsignal.com&lt;/code&gt;에서 외부 포트 검사 시 UDP 500, 4500이 모두 &lt;code&gt;closed&lt;/code&gt;로 나왔습니다. SK 모뎀 포트포워딩과 DMZ 설정을 둘 다 시도해도 동일했습니다. SK 통신사 ISP 단에서 차단하는 것으로 추정됩니다.&lt;/p&gt;
&lt;h3&gt;문제 2: Android 14+ 의 L2TP/IPSec PSK 지원 제거&lt;/h3&gt;
&lt;p&gt;Google이 Android 12부터 L2TP/IPSec PSK를 단계적으로 제거했고, &lt;strong&gt;Android 14 이상에서는 사실상 동작 불가&lt;/strong&gt;입니다. Android 16에서는 인증 단계에 도달하지도 못한 채 IPSec 협상에서 바로 끊겼습니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;p&gt;결론: &lt;strong&gt;2026년 현재 안드로이드에서 L2TP/IPSec은 사용하지 마세요.&lt;/strong&gt;&lt;/p&gt;
&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;hr&gt;
&lt;h2&gt;시도 2: WireGuard — 성공한 방법&lt;/h2&gt;
&lt;p&gt;iptime은 OpenVPN 서버를 지원하지 않지만 &lt;strong&gt;WireGuard 서버&lt;/strong&gt;를 지원합니다. WireGuard는 모던하고 빠르며 안드로이드 호환성도 완벽합니다.&lt;/p&gt;
&lt;h3&gt;1단계: No-IP DDNS 설정&lt;/h3&gt;
&lt;p&gt;iptime 자체 DDNS(&lt;code&gt;*.iptime.org&lt;/code&gt;)는 iptime의 WAN IP(사설 대역)를 등록하는데, 이게 SK 모뎀이 할당한 사설 IP라서 외부에서 접근 불가합니다. 따라서 &lt;strong&gt;SK 모뎀의 공인 IP를 직접 등록할 No-IP&lt;/strong&gt;를 사용합니다.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.noip.com&quot;&gt;https://www.noip.com&lt;/a&gt; 로그인 후 호스트네임 추가:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;항목&lt;/th&gt;
&lt;th&gt;값&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Hostname&lt;/td&gt;
&lt;td&gt;&lt;code&gt;사용자도메인&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Domain&lt;/td&gt;
&lt;td&gt;&lt;code&gt;ddns.net&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Type&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;DNS Host (A)&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;IPv4 Address&lt;/td&gt;
&lt;td&gt;&lt;code&gt;xxx.xxx.xxx.xxx&lt;/code&gt; (SK 모뎀 공인 IP)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Wildcard&lt;/td&gt;
&lt;td&gt;비활성&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Enable Dynamic DNS&lt;/td&gt;
&lt;td&gt;비활성 (수동 입력 시)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;확인:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;nslookup 사용자도메인.ddns.net
# Address가 SK 모뎀 공인 IP와 일치해야 정상&lt;/code&gt;&lt;/pre&gt;&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;p&gt;  SK 모뎀 공인 IP는 유동이라 변경될 수 있습니다. 자동화하려면 항상 켜져있는 PC/NAS에 &lt;strong&gt;No-IP DUC(Dynamic Update Client)&lt;/strong&gt; 설치를 권장합니다. (이중 NAT 환경에서는 iptime의 DDNS 클라이언트가 사설 IP를 보고하므로 사용 불가)&lt;/p&gt;
&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;h3&gt;2단계: iptime WireGuard 서버 설정&lt;/h3&gt;
&lt;p&gt;iptime 관리 페이지(&lt;code&gt;192.168.0.zzz&lt;/code&gt;) → &lt;strong&gt;고급 설정 → VPN 서버 → WireGuard 서버&lt;/strong&gt;&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;항목&lt;/th&gt;
&lt;th&gt;값&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;서버 활성화&lt;/td&gt;
&lt;td&gt;켜짐&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;인터페이스 주소&lt;/td&gt;
&lt;td&gt;&lt;code&gt;10.x.x.1/24&lt;/code&gt; (VPN 가상 네트워크 대역, 임의 설정)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;서버 포트&lt;/td&gt;
&lt;td&gt;임의의 5자리 UDP 포트 (기본 51820 대신 권장)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;VPN 내부 통신 NAT&lt;/td&gt;
&lt;td&gt;꺼짐 (내부망 직접 접근하려면 꺼짐)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;저장 후 &lt;strong&gt;공개키(Public Key)&lt;/strong&gt; 가 자동 생성됩니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;p&gt;  서버 포트는 본인이 정한 값으로 사용하세요. 본문에서는 &lt;code&gt;&amp;lt;서버포트&amp;gt;&lt;/code&gt; 로 표기합니다.&lt;/p&gt;
&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;h3&gt;3단계: 클라이언트(피어) 추가&lt;/h3&gt;
&lt;p&gt;WireGuard 서버 페이지 하단 &lt;strong&gt;피어 목록&lt;/strong&gt;에서 &lt;strong&gt;피어 추가&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;이름: &lt;code&gt;phone&lt;/code&gt; (식별용)&lt;/li&gt;
&lt;li&gt;자동으로 키페어 생성됨&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;QR 코드 표시&lt;/strong&gt; 클릭&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;이 QR 코드를 핸드폰에서 바로 스캔하면 됩니다.&lt;/p&gt;
&lt;h3&gt;4단계: SK 모뎀 포트포워딩&lt;/h3&gt;
&lt;p&gt;SK 모뎀 관리 페이지(&lt;code&gt;192.168.xxx.1&lt;/code&gt;) → &lt;strong&gt;NAT → 포트포워딩&lt;/strong&gt;:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;프로토콜&lt;/th&gt;
&lt;th&gt;외부 포트 시작&lt;/th&gt;
&lt;th&gt;외부 포트 끝&lt;/th&gt;
&lt;th&gt;내부 IP&lt;/th&gt;
&lt;th&gt;내부 포트 시작&lt;/th&gt;
&lt;th&gt;내부 포트 끝&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;UDP&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;서버포트&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;서버포트&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;192.168.xxx.yy&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;서버포트&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;서버포트&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;p&gt;⚠️ 기존 L2TP용 UDP 500, 4500 규칙은 사용하지 않으니 삭제해도 됩니다.&lt;/p&gt;
&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;h3&gt;5단계: iptime WAN IP 고정&lt;/h3&gt;
&lt;p&gt;iptime의 WAN IP는 SK 모뎀이 DHCP로 준 IP이므로, iptime 재부팅 시 바뀔 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;SK 모뎀 → DHCP 설정&lt;/strong&gt;에서 iptime의 WAN MAC 주소로 IP 고정 할당해두세요.&lt;/p&gt;
&lt;h3&gt;6단계: 핸드폰에 WireGuard 앱 설치&lt;/h3&gt;
&lt;p&gt;Play Store → &lt;strong&gt;WireGuard&lt;/strong&gt; (공식 앱, 용 모양 아이콘  )&lt;/p&gt;
&lt;p&gt;앱에서:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;+&lt;/code&gt; 버튼 → &lt;strong&gt;QR 코드로 스캔&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;iptime 관리 페이지의 피어 QR 코드 스캔&lt;/li&gt;
&lt;li&gt;프로필 자동 생성됨&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;7단계: 엔드포인트를 도메인으로 변경 (중요)&lt;/h3&gt;
&lt;p&gt;QR로 가져온 프로필의 엔드포인트는 보통 IP로 되어 있습니다. SK 모뎀 공인 IP는 유동이므로 &lt;strong&gt;도메인으로 변경&lt;/strong&gt;해두면 IP가 바뀌어도 자동 대응됩니다.&lt;/p&gt;
&lt;p&gt;WireGuard 앱 → 해당 터널 → 우측 상단 &lt;strong&gt;연필(편집)&lt;/strong&gt; 아이콘 → &lt;strong&gt;피어&lt;/strong&gt; 섹션:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;엔드포인트: xxx.xxx.xxx.xxx:&amp;lt;서버포트&amp;gt;
            ↓ 변경
엔드포인트: 사용자도메인.ddns.net:&amp;lt;서버포트&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;저장.&lt;/p&gt;
&lt;h3&gt;8단계: 연결 테스트&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;p&gt;  &lt;strong&gt;반드시 핸드폰을 LTE/5G로 전환하세요.&lt;/strong&gt; WiFi 켜져있으면 외부 접속 테스트가 의미 없습니다.&lt;/p&gt;
&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;pre&gt;&lt;code&gt;설정 → WiFi → 끄기
모바일 데이터 → 켜기&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;WireGuard 앱에서 토글 ON.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;연결 확인 방법&lt;/h2&gt;
&lt;h3&gt;A. WireGuard 앱에서 트래픽 확인&lt;/h3&gt;
&lt;p&gt;피어 상세 화면에서 &lt;strong&gt;전송/수신 바이트&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;수신 바이트가 0이 아니면&lt;/strong&gt; → 서버 응답 정상 → ✅ 연결 성공&lt;/li&gt;
&lt;li&gt;전송만 증가하고 수신 0 → 패킷이 서버까지 안 닿음&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;B. iptime 관리 페이지에서 핸드셰이크 확인&lt;/h3&gt;
&lt;p&gt;iptime → VPN 서버 → WireGuard → 피어 목록 → &lt;strong&gt;최근 핸드셰이크 시간&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&amp;quot;몇 초 전&amp;quot; 으로 갱신되면 연결 성공.&lt;/p&gt;
&lt;h3&gt;C. 내부망 접근 테스트&lt;/h3&gt;
&lt;p&gt;VPN 연결된 상태에서 핸드폰 브라우저로:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;http://192.168.0.zzz  → iptime 관리 페이지 표시&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;뜨면 외부에서 내부망 진입 완료.&lt;/p&gt;
&lt;h3&gt;D. 외부 IP 확인 (보너스)&lt;/h3&gt;
&lt;p&gt;핸드폰 브라우저에서 &lt;a href=&quot;https://myip.com&quot;&gt;https://myip.com&lt;/a&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;VPN OFF: 통신사 IP&lt;/li&gt;
&lt;li&gt;VPN ON: 집 공인 IP&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;같으면 모든 트래픽이 집 회선으로 흐르는 풀 터널 상태.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;트러블슈팅 체크리스트&lt;/h2&gt;
&lt;p&gt;문제 발생 시 단계별 확인:&lt;/p&gt;
&lt;h3&gt;DNS 확인&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;nslookup 사용자도메인.ddns.net
# 결과가 SK 모뎀 공인 IP와 일치해야 함&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;다르면 → No-IP에서 IP 다시 등록.&lt;/p&gt;
&lt;h3&gt;포트 열림 확인&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://www.yougetsignal.com/tools/open-ports/&quot;&gt;https://www.yougetsignal.com/tools/open-ports/&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Host: &lt;code&gt;사용자도메인.ddns.net&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Port: &lt;code&gt;&amp;lt;서버포트&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;p&gt;참고: UDP는 TCP보다 검사 정확도가 낮아 closed로 나와도 실제 열려있을 수 있습니다. WireGuard 핸드셰이크가 잘 되면 무시해도 됩니다.&lt;/p&gt;
&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;h3&gt;iptime WAN IP가 사설 대역인지 확인&lt;/h3&gt;
&lt;p&gt;iptime 관리 페이지 → 상태 → WAN IP&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;192.168.x.x&lt;/code&gt; → SK 모뎀이 사설 IP 할당 (이중 NAT)&lt;/li&gt;
&lt;li&gt;이 경우 SK 모뎀에서 포트포워딩 필수&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;안 될 때 흔한 원인&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;iptime DDNS(&lt;code&gt;*.iptime.org&lt;/code&gt;) 사용&lt;/strong&gt; → ❌ 사설 IP 등록되므로 외부 접근 불가, No-IP 같은 외부 DDNS 사용&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;SK 모뎀 포트포워딩 누락&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;iptime WAN IP 변동&lt;/strong&gt; → SK 모뎀에서 DHCP 고정 할당 필요&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;핸드폰이 WiFi에 연결된 상태&lt;/strong&gt; → LTE/5G로 전환&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;WireGuard 엔드포인트가 IP로 되어 있고 공인 IP가 변경됨&lt;/strong&gt; → 도메인으로 변경&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;SK 모뎀 공인 IP가 바뀌는 시점&lt;/h2&gt;
&lt;p&gt;가정용 SK 회선의 공인 IP는 유동이며 다음 시점에 변경될 수 있습니다:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;모뎀 재부팅 시 (가장 흔함)&lt;/li&gt;
&lt;li&gt;정전 후 복구 시&lt;/li&gt;
&lt;li&gt;모뎀 펌웨어 자동 업데이트 시&lt;/li&gt;
&lt;li&gt;DHCP 임대 시간 만료 시 (수일~수주)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;평소엔 잘 안 바뀌지만, 한 번 바뀌면 외부 접속이 끊깁니다. 따라서 &lt;strong&gt;DDNS 자동 갱신을 권장&lt;/strong&gt;합니다.&lt;/p&gt;
&lt;h3&gt;DDNS 자동 갱신 - No-IP DUC 설치 (Linux)&lt;/h3&gt;
&lt;p&gt;24시간 켜둘 PC/서버가 있다면 거기에 설치하는 게 가장 안정적입니다.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;cd /tmp
wget https://www.noip.com/client/linux/noip-duc-linux.tar.gz
tar xzf noip-duc-linux.tar.gz
cd noip-*
sudo make
sudo make install
# 설치 중 No-IP 계정/PW 입력

# 실행
sudo /usr/local/bin/noip2&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;systemd 서비스로 등록해두면 부팅 시 자동 시작됩니다.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;정리: SK + iptime 환경에서 VPN 베스트 프랙티스&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;항목&lt;/th&gt;
&lt;th&gt;권장&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;VPN 프로토콜&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;WireGuard&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;L2TP/IPSec&lt;/td&gt;
&lt;td&gt;❌ 사용 금지 (SK 차단 + Android 호환성 문제)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;포트&lt;/td&gt;
&lt;td&gt;51820 외 임의 5자리 포트&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DDNS&lt;/td&gt;
&lt;td&gt;No-IP 등 외부 서비스 (iptime DDNS 비추천)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;WAN IP 고정&lt;/td&gt;
&lt;td&gt;SK 모뎀에서 iptime MAC으로 DHCP 고정 할당&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;모뎀 모드&lt;/td&gt;
&lt;td&gt;브리지 모드가 최선 (이중 NAT 회피), 안 되면 포트포워딩&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;엔드포인트 표기&lt;/td&gt;
&lt;td&gt;IP가 아니라 도메인으로&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;WireGuard는 한 번 설정하면 연결 1~2초, 배터리 소모 적음, 안정성 좋음 — 모든 면에서 L2TP/IPSec보다 우월합니다. 2026년 현재 가정용 VPN의 사실상 표준입니다.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;참고 명령어 모음&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;# DNS 조회
nslookup 사용자도메인.ddns.net

# 현재 PC의 IP 확인 (Windows)
ipconfig

# 현재 외부 IP 확인 (브라우저)
# https://myip.com&lt;/code&gt;&lt;/pre&gt;&lt;pre&gt;&lt;code&gt;# 포트 열림 테스트 사이트
https://www.yougetsignal.com/tools/open-ports/

# DNS 전파 확인
https://dnschecker.org&lt;/code&gt;&lt;/pre&gt;&lt;hr&gt;
&lt;h2&gt;마치며&lt;/h2&gt;
&lt;p&gt;같은 SK + iptime 환경에서 VPN을 구축하시는 분들께 이 글이 시행착오를 줄여주길 바랍니다.&lt;/p&gt;
&lt;p&gt;그리고 다시 한번 말씀드리지만 TAPO D230s1 사지마세요. 스트레스로 흰머리 100개 늘어났습니다.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;일주일 사용후기&lt;/h2&gt;
&lt;p&gt;처음 한두번 재생되다가 안됩니다.&lt;br&gt;여전히 안돼요. 쓰레기 TAPO, TP link&lt;br&gt;두번 다신 안삽니다.&lt;/p&gt;</description>
      <category>컴퓨터</category>
      <author>Ninestar</author>
      <guid isPermaLink="true">https://data-science.tistory.com/737</guid>
      <comments>https://data-science.tistory.com/737#entry737comment</comments>
      <pubDate>Mon, 4 May 2026 22:40:14 +0900</pubDate>
    </item>
    <item>
      <title>NPU 백엔드 설정 전체 절차</title>
      <link>https://data-science.tistory.com/736</link>
      <description>&lt;div style=&quot;background-color: #fafafd; color: #202020; text-align: start;&quot;&gt;
&lt;pre class=&quot;jboss-cli&quot;&gt;&lt;code&gt;## 1. OpenVINO 설치 및 환경 설정

```bash
echo 'source /opt/intel/openvino_2025.4.0/setupvars.sh' &amp;gt;&amp;gt; ~/.zshrc
source ~/.zshrc
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2 style=&quot;background-color: #fafafd; color: #202020; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;2. openvino.pc 버그 수정&lt;/h2&gt;
&lt;p style=&quot;background-color: #fafafd; color: #202020; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;/opt/intel/openvino_2025.4.0/runtime/lib/intel64/pkgconfig/openvino.pc&lt;/p&gt;
&lt;p style=&quot;background-color: #fafafd; color: #202020; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;Libs 줄에서 -lopenvino_jax_frontend 제거 (해당 .so 미존재로 링크 실패)&lt;/p&gt;
&lt;p style=&quot;background-color: #fafafd; color: #202020; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;수정 전:&lt;/b&gt;&lt;/p&gt;
&lt;div style=&quot;background-color: #fafafd; color: #202020; text-align: start;&quot;&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;Libs: -L${libdir} -lopenvino_jax_frontend -lopenvino_onnx_frontend ...
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p style=&quot;background-color: #fafafd; color: #202020; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;수정 후:&lt;/b&gt;&lt;/p&gt;
&lt;div style=&quot;background-color: #fafafd; color: #202020; text-align: start;&quot;&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;Libs: -L${libdir} -lopenvino_onnx_frontend ...
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2 style=&quot;background-color: #fafafd; color: #202020; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;3. Intel NPU 드라이버 설치&lt;/h2&gt;
&lt;div style=&quot;background-color: #fafafd; color: #202020; text-align: start;&quot;&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;wget https://github.com/intel/linux-npu-driver/releases/download/v1.30.0/linux-npu-driver-v1.30.0.20260311-22963593310-ubuntu2404.tar.gz
tar -xf linux-npu-driver-v1.30.0.20260311-22963593310-ubuntu2404.tar.gz
sudo dpkg -i *.deb
sudo reboot
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2 style=&quot;background-color: #fafafd; color: #202020; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;4. Level Zero ICD loader 설치&lt;/h2&gt;
&lt;div style=&quot;background-color: #fafafd; color: #202020; text-align: start;&quot;&gt;
&lt;pre class=&quot;crystal&quot;&gt;&lt;code&gt;wget -qO - https://repositories.intel.com/gpu/intel-graphics.key | sudo gpg --dearmor -o /usr/share/keyrings/intel-graphics.gpg
echo &quot;deb [arch=amd64 signed-by=/usr/share/keyrings/intel-graphics.gpg] https://repositories.intel.com/gpu/ubuntu noble unified&quot; | sudo tee /etc/apt/sources.list.d/intel-gpu-noble.list
sudo apt update &amp;amp;&amp;amp; sudo apt install level-zero
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2 style=&quot;background-color: #fafafd; color: #202020; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;5. render 그룹 권한 추가&lt;/h2&gt;
&lt;div style=&quot;background-color: #fafafd; color: #202020; text-align: start;&quot;&gt;
&lt;pre class=&quot;nginx&quot;&gt;&lt;code&gt;sudo usermod -aG render $USER
# 로그아웃 후 재로그인
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2 style=&quot;background-color: #fafafd; color: #202020; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;6. 실행&lt;/h2&gt;
&lt;div style=&quot;background-color: #fafafd; color: #202020; text-align: start;&quot;&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;BACKEND=openvino OPENVINO_DEVICE=NPU cargo run -p video -- lpr ~/Videos/lpr.mp4&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;</description>
      <category>AI</category>
      <author>Ninestar</author>
      <guid isPermaLink="true">https://data-science.tistory.com/736</guid>
      <comments>https://data-science.tistory.com/736#entry736comment</comments>
      <pubDate>Thu, 26 Mar 2026 11:03:54 +0900</pubDate>
    </item>
    <item>
      <title>GitHub 대용량 모델 파일 관리: 자동 분할 및 병합</title>
      <link>https://data-science.tistory.com/735</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;목차&lt;/h2&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#%EC%84%9C%EB%A1%A0&quot;&gt;서론&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#%EC%99%9C-%ED%8C%8C%EC%9D%BC-%EB%B6%84%ED%95%A0%EC%9D%B4-%ED%95%84%EC%9A%94%ED%95%9C%EA%B0%80&quot;&gt;왜 파일 분할이 필요한가?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EA%B5%AC%EC%A1%B0-%EB%B0%8F-%EC%A3%BC%EC%9A%94-%EA%B8%B0%EB%8A%A5&quot;&gt;스크립트 구조 및 주요 기능&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#%EC%82%AC%EC%9A%A9-%EB%B0%A9%EB%B2%95&quot;&gt;사용 방법&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#%EC%BD%94%EB%93%9C-%EB%B6%84%EC%84%9D-%EB%B0%8F-%EA%B0%9C%EC%84%A0-%EC%82%AC%ED%95%AD&quot;&gt;코드 분석 및 개선 사항&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#%EC%8B%A4%EC%A0%84-%ED%99%9C%EC%9A%A9-%EC%98%88%EC%8B%9C&quot;&gt;실전 활용 예시&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#%EB%AC%B8%EC%A0%9C-%ED%95%B4%EA%B2%B0-%EA%B0%80%EC%9D%B4%EB%93%9C&quot;&gt;문제 해결 가이드&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;서론&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;딥러닝 모델, 특히 YOLO(You Only Look Once) 계열의 객체 탐지 모델은 점점 더 커지고 있습니다. YOLOv8, YOLO11, YOLO12 등의 대형 모델(12x, 24x)은 파일 크기가 수백 MB에서 수 GB에 달하며, 이는 다음과 같은 문제를 야기합니다:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Git/GitHub 업로드 제한&lt;/b&gt;: GitHub는 100MB 이상의 단일 파일 업로드를 제한합니다&lt;/li&gt;
&lt;li&gt;&lt;b&gt;네트워크 전송 실패&lt;/b&gt;: 대용량 파일 전송 시 네트워크 오류로 인한 재시작 필요&lt;/li&gt;
&lt;li&gt;&lt;b&gt;스토리지 관리 어려움&lt;/b&gt;: 클라우드 스토리지 서비스의 파일 크기 제한&lt;/li&gt;
&lt;li&gt;&lt;b&gt;버전 관리 효율성&lt;/b&gt;: Git LFS를 사용하더라도 분할된 파일이 관리에 유리&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;본 가이드에서는 이러한 문제를 해결하기 위한 &lt;b&gt;Bash 기반 자동 파일 분할 및 병합 스크립트&lt;/b&gt;를 소개하고, 실무에 바로 적용할 수 있는 노하우를 공유합니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;왜 파일 분할이 필요한가?&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. GitHub 파일 크기 제한 우회&lt;/h3&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;문제: GitHub에서 100MB 이상 파일 push 불가능
해결: 50MB 단위로 분할하여 각각 커밋&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. 네트워크 안정성 향상&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대용량 파일을 한 번에 전송하면 네트워크 오류 시 처음부터 다시 시작해야 합니다. 분할된 파일은 개별적으로 전송 가능하여 복원력이 높습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. 병렬 처리 가능&lt;/h3&gt;
&lt;pre class=&quot;armasm&quot;&gt;&lt;code&gt;# 여러 파일을 동시에 업로드
parallel -j 4 aws s3 cp {} s3://bucket/ ::: model.part*&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4. 스토리지 효율성&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일부 클라우드 서비스는 작은 파일에 대해 더 나은 중복 제거 및 압축을 제공합니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;스크립트 구조 및 주요 기능&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;전체 스크립트 구조&lt;/h3&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;#!/bin/bash
set -e

# 1. 설정 영역
SPLIT_FILES=&quot;
    yolo12x.pt
&quot;

# 2. 유틸리티 함수 (컬러 출력)
check_fancy_output()

# 3. 핵심 기능 함수
merge_one()    # 단일 파일 병합
merge()        # 전체 파일 병합
part_one()     # 단일 파일 분할
part()         # 전체 파일 분할
help()         # 도움말

# 4. 실행 로직&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;주요 기능&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;1. 컬러 출력 지원&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;터미널 환경을 자동 감지하여 색상 출력을 결정합니다:&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;check_fancy_output() {
    TPUT=/usr/bin/tput
    EXPR=/usr/bin/expr

    if [ &quot;x$TERM&quot; != &quot;xdumb&quot; ] &amp;amp;&amp;amp; [ -x $TPUT ] &amp;amp;&amp;amp; [ -x $EXPR ] &amp;amp;&amp;amp; \
       $TPUT hpa 60 &amp;gt; /dev/null 2&amp;gt;&amp;amp;1; then
        RED=`$TPUT setaf 1`
        YELLOW=`$TPUT setaf 3`
        NORMAL=`$TPUT op`
    else
        RED=&quot;&quot;
        YELLOW=&quot;&quot;
        NORMAL=&quot;&quot;
    fi
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;핵심 포인트&lt;/b&gt;:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;code&gt;dumb&lt;/code&gt; 터미널에서는 색상 비활성화&lt;/li&gt;
&lt;li&gt;&lt;code&gt;tput&lt;/code&gt; 및 &lt;code&gt;expr&lt;/code&gt; 명령어 존재 여부 확인&lt;/li&gt;
&lt;li&gt;에러 출력을 &lt;code&gt;/dev/null&lt;/code&gt;로 리다이렉트하여 조용한 실패 처리&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2. 파일 분할 (split)&lt;/h4&gt;
&lt;pre class=&quot;awk&quot;&gt;&lt;code&gt;part_one() {
    local FILE_NAME=&quot;${1}&quot;

    if [ ! -f &quot;${FILE_NAME}&quot; ]; then
        echo &quot;file '${FILE_NAME}' doesn't exist&quot;
        exit 1
    fi

    echo_status &quot;Split '${FILE_NAME}' into multiple parts&quot;
    split --verbose -b 50M -x &quot;${FILE_NAME}&quot; &quot;${FILE_NAME}.part&quot;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;split 명령어 옵션 설명&lt;/b&gt;:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;code&gt;-b 50M&lt;/code&gt;: 50MB 단위로 분할&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-x&lt;/code&gt;: 16진수 접미사 사용 (part00, part01, part02...)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--verbose&lt;/code&gt;: 진행 상황 출력&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;출력 예시&lt;/b&gt;:&lt;/p&gt;
&lt;pre class=&quot;delphi&quot;&gt;&lt;code&gt;creating file 'model.bin.part00'
creating file 'model.bin.part01'
creating file 'model.bin.part02'&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;3. 파일 병합 (cat)&lt;/h4&gt;
&lt;pre class=&quot;bash&quot;&gt;&lt;code&gt;merge_one() {
    local FILE_NAME=&quot;${1}&quot;

    if [ -f &quot;${FILE_NAME}&quot; ]; then
        echo &quot;File '${FILE_NAME}' already exists&quot;
        return 0
    fi

    echo_status &quot;Merge multiple parts into '${FILE_NAME}'&quot;
    cat &quot;${FILE_NAME}.part&quot;* &amp;gt; &quot;${FILE_NAME}&quot;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;중요&lt;/b&gt;: &lt;code&gt;cat&lt;/code&gt; 명령어는 파일을 알파벳 순서로 연결하므로 &lt;code&gt;part00, part01, part02...&lt;/code&gt; 순서가 보장됩니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;사용 방법&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;기본 사용법&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;1. 스크립트 권한 설정&lt;/h4&gt;
&lt;pre class=&quot;css&quot;&gt;&lt;code&gt;chmod +x split_merge.sh&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2. 파일 분할&lt;/h4&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;# 설정된 모든 파일 분할
./split_merge.sh part

# 특정 파일만 분할
./split_merge.sh part yolo12x.pt&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;3. 파일 병합&lt;/h4&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;# 설정된 모든 파일 병합
./split_merge.sh merge

# 특정 파일만 병합
./split_merge.sh merge yolo12x.pt&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;코드 분석 및 개선 사항&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;원본 코드의 문제점&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;1. 함수 명명 규칙&lt;/h4&gt;
&lt;pre class=&quot;bash&quot;&gt;&lt;code&gt;# 문제: 대문자 함수명 (환경변수와 혼동)
ECHO() {
    echo &quot;${RED}###${YELLOW} ${1} ...&quot;
}

# 개선: 소문자 함수명 사용
echo_status() {
    echo &quot;${RED}###${YELLOW} ${1} ...${NORMAL}&quot;
}&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2. 타이포 수정&lt;/h4&gt;
&lt;pre class=&quot;bash&quot;&gt;&lt;code&gt;# 원본
echo &quot;file '${FILE_NAME}' dosen't exist&quot;

# 수정
echo &quot;file '${FILE_NAME}' doesn't exist&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;3. exit vs return&lt;/h4&gt;
&lt;pre class=&quot;awk&quot;&gt;&lt;code&gt;# 문제: 서브쉘이 아닌 함수에서 exit 사용
merge_one() {
    if [ -f &quot;${FILE_NAME}&quot; ]; then
        exit 0  # 전체 스크립트 종료!
    fi
}

# 개선: return 사용
merge_one() {
    if [ -f &quot;${FILE_NAME}&quot; ]; then
        echo &quot;File '${FILE_NAME}' already exists&quot;
        return 0  # 함수만 종료
    fi
}&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;4. 명령어 실행 구문 오류&lt;/h4&gt;
&lt;pre class=&quot;bash&quot;&gt;&lt;code&gt;# 문제: 공백 없음
hash ${COMMAND} &amp;amp;&amp;gt; /dev/null || help${COMMAND} ${@}

# 수정: 적절한 공백과 인용
hash &quot;${COMMAND}&quot; &amp;amp;&amp;gt; /dev/null || help
&quot;${COMMAND}&quot; &quot;${@}&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;개선된 최종 버전&lt;/h3&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;#!/bin/bash
set -euo pipefail  # 추가: -u (미정의 변수 에러), -o pipefail

SPLIT_FILES=&quot;
    yolo12x.pt
&quot;

# 색상 초기화
RED=&quot;&quot;
YELLOW=&quot;&quot;
NORMAL=&quot;&quot;

check_fancy_output() {
    local TPUT=/usr/bin/tput
    local EXPR=/usr/bin/expr

    if [ &quot;x$TERM&quot; != &quot;xdumb&quot; ] &amp;amp;&amp;amp; [ -x &quot;$TPUT&quot; ] &amp;amp;&amp;amp; [ -x &quot;$EXPR&quot; ] &amp;amp;&amp;amp; \
       &quot;$TPUT&quot; hpa 60 &amp;gt; /dev/null 2&amp;gt;&amp;amp;1; then
        RED=$($TPUT setaf 1)
        YELLOW=$($TPUT setaf 3)
        NORMAL=$($TPUT op)
    fi
}

check_fancy_output

echo_status() {
    echo &quot;${RED}###${YELLOW} ${1} ...${NORMAL}&quot;
}

merge_one() {
    local FILE_NAME=&quot;${1}&quot;

    if [ -f &quot;${FILE_NAME}&quot; ]; then
        echo &quot;File '${FILE_NAME}' already exists, skipping merge&quot;
        return 0
    fi

    if ! ls &quot;${FILE_NAME}.part&quot;* 1&amp;gt; /dev/null 2&amp;gt;&amp;amp;1; then
        echo &quot;No parts found for '${FILE_NAME}'&quot;
        return 1
    fi

    echo_status &quot;Merge multiple parts into '${FILE_NAME}'&quot;
    cat &quot;${FILE_NAME}.part&quot;* &amp;gt; &quot;${FILE_NAME}&quot;
    echo &quot;✓ Merged successfully&quot;
}

merge() {
    local FILE_NAME=&quot;${1:-}&quot;

    if [ -z &quot;${FILE_NAME}&quot; ]; then
        for f in ${SPLIT_FILES}; do
            merge_one &quot;${f}&quot;
        done
    else
        merge_one &quot;${FILE_NAME}&quot;
    fi
}

part_one() {
    local FILE_NAME=&quot;${1}&quot;

    if [ ! -f &quot;${FILE_NAME}&quot; ]; then
        echo &quot;Error: file '${FILE_NAME}' doesn't exist&quot;
        return 1
    fi

    echo_status &quot;Split '${FILE_NAME}' into multiple parts&quot;
    split --verbose -b 50M -x &quot;${FILE_NAME}&quot; &quot;${FILE_NAME}.part&quot;
    echo &quot;✓ Split successfully&quot;
}

part() {
    local FILE_NAME=&quot;${1:-}&quot;

    if [ -z &quot;${FILE_NAME}&quot; ]; then
        for f in ${SPLIT_FILES}; do
            part_one &quot;${f}&quot;
        done
    else
        part_one &quot;${FILE_NAME}&quot;
    fi
}

show_help() {
    local PROG
    PROG=$(basename &quot;${0}&quot;)

    echo &quot;Usage:&quot;
    echo &quot;  ${YELLOW}${PROG} ${RED}merge${NORMAL} [file]  # Merge part files&quot;
    echo &quot;  ${YELLOW}${PROG} ${RED}part${NORMAL} [file]   # Split file into parts&quot;
    echo &quot;  ${YELLOW}${PROG} ${RED}help${NORMAL}          # Show this help&quot;
    echo &quot;&quot;
    echo &quot;Examples:&quot;
    echo &quot;  ${PROG} part                              # Split all configured files&quot;
    echo &quot;  ${PROG} part model.bin                    # Split specific file&quot;
    echo &quot;  ${PROG} merge                             # Merge all configured files&quot;
    echo &quot;  ${PROG} merge model.bin                   # Merge specific file&quot;
}

# 메인 실행 로직
main() {
    if [ $# -eq 0 ]; then
        show_help
        exit 1
    fi

    local COMMAND=&quot;${1}&quot;
    shift

    case &quot;${COMMAND}&quot; in
        merge)
            merge &quot;${@}&quot;
            ;;
        part)
            part &quot;${@}&quot;
            ;;
        help|--help|-h)
            show_help
            ;;
        *)
            echo &quot;Error: Unknown command '${COMMAND}'&quot;
            show_help
            exit 1
            ;;
    esac
}

main &quot;${@}&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;개선 사항 요약&lt;/h3&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;항목&lt;/th&gt;
&lt;th&gt;원본&lt;/th&gt;
&lt;th&gt;개선&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;에러 처리&lt;/td&gt;
&lt;td&gt;&lt;code&gt;set -e&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;set -euo pipefail&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;함수명&lt;/td&gt;
&lt;td&gt;&lt;code&gt;ECHO&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;echo_status&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;종료 방식&lt;/td&gt;
&lt;td&gt;&lt;code&gt;exit 0&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;return 0&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;파일 존재 확인&lt;/td&gt;
&lt;td&gt;없음&lt;/td&gt;
&lt;td&gt;&lt;code&gt;ls&lt;/code&gt; 패턴 매칭 검증&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;성공 피드백&lt;/td&gt;
&lt;td&gt;없음&lt;/td&gt;
&lt;td&gt;&lt;code&gt;✓ Successfully&lt;/code&gt; 메시지&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;도움말&lt;/td&gt;
&lt;td&gt;기본&lt;/td&gt;
&lt;td&gt;예시 포함 상세 도움말&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;case 문&lt;/td&gt;
&lt;td&gt;&lt;code&gt;hash&lt;/code&gt; + 동적 실행&lt;/td&gt;
&lt;td&gt;명시적 &lt;code&gt;case&lt;/code&gt; 문&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;문제 해결 가이드&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Q1: &quot;command not found: split&quot; 에러&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;원인&lt;/b&gt;: &lt;code&gt;coreutils&lt;/code&gt; 패키지 미설치&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;해결&lt;/b&gt;:&lt;/p&gt;
&lt;pre class=&quot;mipsasm&quot;&gt;&lt;code&gt;# Ubuntu/Debian
sudo apt-get install coreutils

# macOS
brew install coreutils&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Q2: 병합 후 파일 크기가 다름&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;원인&lt;/b&gt;: 분할 파일 일부 누락 또는 손상&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;해결&lt;/b&gt;:&lt;/p&gt;
&lt;pre class=&quot;vala&quot;&gt;&lt;code&gt;# 모든 part 파일 확인
ls -lh model.bin.part*

# 예상 크기 계산
du -sh model.bin.part* | awk '{sum+=$1}END{print sum}'

# 재다운로드 및 재시도&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Q3: Git에서 &quot;file too large&quot; 경고&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;해결 방법&lt;/b&gt;:&lt;/p&gt;
&lt;pre class=&quot;vim&quot;&gt;&lt;code&gt;# 이미 커밋된 대용량 파일 제거
git filter-branch --force --index-filter \
  &quot;git rm --cached --ignore-unmatch experiment/model.bin&quot; \
  --prune-empty --tag-name-filter cat -- --all

# 재분할 및 커밋
./split_merge.sh part experiment/model.bin
git add experiment/*.part*
git commit -m &quot;Replace large file with split chunks&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Q4: 병합 시 &quot;Permission denied&quot;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;원인&lt;/b&gt;: 대상 디렉토리 쓰기 권한 없음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;해결&lt;/b&gt;:&lt;/p&gt;
&lt;pre class=&quot;properties&quot;&gt;&lt;code&gt;# 권한 확인
ls -ld experiment/

# 권한 부여
chmod u+w experiment/&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Q5: 분할 파일 순서가 잘못됨&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;원인&lt;/b&gt;: 알파벳 정렬 문제 (part1, part10, part2...)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;해결&lt;/b&gt;: 스크립트에서 &lt;code&gt;-x&lt;/code&gt; 옵션 사용 (이미 적용됨)&lt;/p&gt;
&lt;pre class=&quot;livecodeserver&quot;&gt;&lt;code&gt;# 16진수 접미사로 올바른 정렬 보장
split -b 50M -x file.bin file.bin.part
# 생성: part00, part01, ..., part0a, part0b, ...&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;성능 최적화 팁&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. SSD 환경에서 버퍼 크기 조정&lt;/h3&gt;
&lt;pre class=&quot;perl&quot;&gt;&lt;code&gt;# 기본 50MB 대신 100MB 블록 사용
split -b 100M -x &quot;${FILE_NAME}&quot; &quot;${FILE_NAME}.part&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. 압축과 함께 사용&lt;/h3&gt;
&lt;pre class=&quot;css&quot;&gt;&lt;code&gt;# 분할 전 압축
gzip -k model.bin  # model.bin.gz 생성
split -b 50M model.bin.gz model.bin.gz.part

# 병합 후 압축 해제
cat model.bin.gz.part* &amp;gt; model.bin.gz
gunzip model.bin.gz&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. 병렬 압축 (pigz)&lt;/h3&gt;
&lt;pre class=&quot;css&quot;&gt;&lt;code&gt;# pigz 설치
sudo apt-get install pigz

# 빠른 압축
pigz -k model.bin
split -b 50M model.bin.gz model.bin.gz.part&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;결론&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대용량 YOLO 모델 파일 관리는 딥러닝 실무에서 자주 마주치는 문제입니다. 본 가이드에서 소개한 자동 분할/병합 스크립트는:&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;✅ &lt;b&gt;GitHub 업로드 제한 우회&lt;/b&gt;&lt;br /&gt;✅ &lt;b&gt;네트워크 안정성 향상&lt;/b&gt;&lt;br /&gt;✅ &lt;b&gt;클라우드 스토리지 최적화&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 스크립트를 프로젝트에 맞게 커스터마이징하여 사용하시면, 대용량 모델 파일 관리의 어려움을 크게 줄일 수 있습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;추가 자료&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://www.gnu.org/software/coreutils/manual/html_node/split-invocation.html&quot;&gt;GNU Coreutils - split 매뉴얼&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://git-lfs.github.com/&quot;&gt;Git LFS 공식 문서&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://google.github.io/styleguide/shellguide.html&quot;&gt;Bash 스크립팅 모범 사례&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;키워드&lt;/b&gt;: YOLO, 모델 파일 분할, Bash 스크립트, Git 대용량 파일, 딥러닝 모델 관리, split 명령어, 파일 병합, GitHub 100MB 제한&lt;/p&gt;</description>
      <category>컴퓨터</category>
      <author>Ninestar</author>
      <guid isPermaLink="true">https://data-science.tistory.com/735</guid>
      <comments>https://data-science.tistory.com/735#entry735comment</comments>
      <pubDate>Fri, 6 Feb 2026 10:39:55 +0900</pubDate>
    </item>
    <item>
      <title>SAHI(Slicing Aided Hyper Inference) 작은 객체 탐지</title>
      <link>https://data-science.tistory.com/734</link>
      <description>&lt;div&gt;
&lt;style&gt;
/* 제목 자동 번호 제거 */
.contents_style {
    counter-reset: none !important;
}

.contents_style h1::before,
.contents_style h2::before,
.contents_style h3::before,
.contents_style h4::before {
    content: none !important;
    counter-increment: none !important;
}
&lt;/style&gt;
&lt;/div&gt;
&lt;h1&gt;SAHI를 활용한 작은 객체 탐지 성능 향상&lt;/h1&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;SAHI란?&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/ultralytics/assets@main/docs/sahi-sliced-inference-overview.avif&quot; alt=&quot;SAHI Sliced Inference Overview&quot; /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SAHI(Slicing Aided Hyper Inference)는 객체 탐지 모델의 추론 성능을 향상시키기 위한 경량 비전 라이브러리입니다. 특히 고해상도 이미지에서 작은 객체를 탐지할 때 뛰어난 성능을 보입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일반적인 객체 탐지 모델(YOLO, Faster R-CNN 등)은 입력 이미지를 고정된 크기(예: 640x640)로 리사이즈하여 처리합니다. 이 과정에서 작은 객체의 정보가 손실되어 탐지율이 떨어지는 문제가 발생합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SAHI는 이 문제를 &lt;b&gt;이미지 슬라이싱(Image Slicing)&lt;/b&gt; 기법으로 해결합니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;SAHI의 핵심 원리&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;슬라이스 기반 추론&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SAHI는 다음과 같은 방식으로 동작합니다:&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;이미지 분할&lt;/b&gt;: 원본 이미지를 여러 개의 작은 타일로 분할&lt;/li&gt;
&lt;li&gt;&lt;b&gt;개별 추론&lt;/b&gt;: 각 타일에 대해 독립적으로 객체 탐지 수행&lt;/li&gt;
&lt;li&gt;&lt;b&gt;결과 병합&lt;/b&gt;: 모든 타일의 탐지 결과를 원본 이미지 좌표계로 변환&lt;/li&gt;
&lt;li&gt;&lt;b&gt;중복 제거&lt;/b&gt;: NMS(Non-Maximum Suppression)를 통해 중복된 탐지 제거&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 방식을 통해 작은 객체도 큰 비율로 표현되어 더 정확하게 탐지할 수 있습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;오버랩 처리&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;타일 경계에 걸친 객체를 놓치지 않기 위해 SAHI는 &lt;b&gt;오버랩(Overlap)&lt;/b&gt; 영역을 설정합니다. 인접한 타일들이 일부 영역을 공유하여 경계 객체도 안정적으로 탐지합니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;SAHI 설치&lt;/h2&gt;
&lt;pre class=&quot;dockerfile&quot;&gt;&lt;code&gt;pip install sahi
# 또는
uv add sahi&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;YOLO 모델과 함께 사용하려면:&lt;/p&gt;
&lt;pre class=&quot;cmake&quot;&gt;&lt;code&gt;pip install ultralytics&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;기본 사용법&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;일반 추론과 SAHI 추론 비교&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;일반 YOLO 추론:&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;properties&quot;&gt;&lt;code&gt;from ultralytics import YOLO

# 모델 로드
model = YOLO('yolov8n.pt')

# 추론 실행
results = model('image.jpg')

# 결과 처리
for result in results:
    boxes = result.boxes
    for box in boxes:
        x1, y1, x2, y2 = box.xyxy[0]
        confidence = box.conf[0]
        class_id = box.cls[0]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;SAHI를 사용한 추론:&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;from sahi import AutoDetectionModel
from sahi.predict import get_sliced_prediction

# SAHI 모델 래퍼 생성
detection_model = AutoDetectionModel.from_pretrained(
    model_type='yolov8',
    model_path='yolov8n.pt',
    confidence_threshold=0.25,
    device='cuda'  # 또는 'cpu'
)

# 슬라이스 기반 추론 실행
result = get_sliced_prediction(
    'image.jpg',
    detection_model,
    slice_height=640,
    slice_width=640,
    overlap_height_ratio=0.2,
    overlap_width_ratio=0.2
)

# 결과 처리
for obj in result.object_prediction_list:
    bbox = obj.bbox  # BoundingBox 객체
    x1, y1, x2, y2 = bbox.minx, bbox.miny, bbox.maxx, bbox.maxy
    confidence = obj.score.value
    class_name = obj.category.name
    class_id = obj.category.id&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;핵심 파라미터 설정&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;슬라이스 크기 설정&lt;/h3&gt;
&lt;pre class=&quot;nix&quot;&gt;&lt;code&gt;result = get_sliced_prediction(
    image_path,
    detection_model,
    slice_height=640,      # 타일 높이
    slice_width=640,       # 타일 너비
    overlap_height_ratio=0.2,  # 세로 오버랩 비율 (20%)
    overlap_width_ratio=0.2    # 가로 오버랩 비율 (20%)
)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;파라미터 선택 가이드:&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;slice_height/width&lt;/b&gt;: 모델의 학습 해상도와 동일하게 설정 (YOLO의 경우 보통 640)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;overlap_ratio&lt;/b&gt;: 0.1~0.3 사이 권장 (높을수록 경계 객체 탐지 향상, 하지만 연산량 증가)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;후처리 설정&lt;/h3&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;result = get_sliced_prediction(
    image_path,
    detection_model,
    slice_height=640,
    slice_width=640,
    overlap_height_ratio=0.2,
    overlap_width_ratio=0.2,
    postprocess_type=&quot;NMS&quot;,           # 또는 &quot;GREEDYNMM&quot;
    postprocess_match_metric=&quot;IOS&quot;,   # 또는 &quot;IOU&quot;
    postprocess_match_threshold=0.5,  # NMS threshold
    postprocess_class_agnostic=False  # 클래스 무관 NMS 여부
)&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;실전 활용 예제&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;고해상도 이미지에서 작은 객체 탐지&lt;/h3&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;import torch
from sahi import AutoDetectionModel
from sahi.predict import get_sliced_prediction
from PIL import Image

# 디바이스 설정
device = 'cuda' if torch.cuda.is_available() else 'cpu'

# 모델 로드
detection_model = AutoDetectionModel.from_pretrained(
    model_type='yolov8',
    model_path='yolov8m.pt',
    confidence_threshold=0.3,
    device=device
)

# 고해상도 이미지 추론
image_path = 'high_resolution_image.jpg'
result = get_sliced_prediction(
    image_path,
    detection_model,
    slice_height=640,
    slice_width=640,
    overlap_height_ratio=0.2,
    overlap_width_ratio=0.2,
    verbose=0  # 로그 출력 억제
)

# 결과 시각화
result.export_visuals(export_dir='output/')

# 탐지된 객체 정보 출력
print(f&quot;총 탐지된 객체: {len(result.object_prediction_list)}개&quot;)

for i, obj in enumerate(result.object_prediction_list):
    print(f&quot;{i+1}. {obj.category.name} (신뢰도: {obj.score.value:.2f})&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;배치 처리&lt;/h3&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;from pathlib import Path
from sahi.predict import predict

# 여러 이미지 처리
image_dir = Path('images/')
output_dir = Path('results/')
output_dir.mkdir(exist_ok=True)

for img_path in image_dir.glob('*.jpg'):
    result = get_sliced_prediction(
        str(img_path),
        detection_model,
        slice_height=640,
        slice_width=640,
        overlap_height_ratio=0.2,
        overlap_width_ratio=0.2
    )

    # 결과 저장
    output_path = output_dir / f&quot;{img_path.stem}_result.jpg&quot;
    result.export_visuals(export_dir=str(output_dir))

    print(f&quot;{img_path.name}: {len(result.object_prediction_list)}개 객체 탐지&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;커스텀 후처리&lt;/h3&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;from sahi.predict import get_sliced_prediction

result = get_sliced_prediction(
    image_path,
    detection_model,
    slice_height=640,
    slice_width=640,
    overlap_height_ratio=0.2,
    overlap_width_ratio=0.2
)

# 특정 클래스만 필터링
filtered_objects = [
    obj for obj in result.object_prediction_list
    if obj.category.name in ['person', 'car']
]

# 신뢰도 기준 필터링
high_conf_objects = [
    obj for obj in result.object_prediction_list
    if obj.score.value &amp;gt; 0.5
]

# 크기 기준 필터링 (작은 객체만)
small_objects = [
    obj for obj in result.object_prediction_list
    if (obj.bbox.maxx - obj.bbox.minx) * (obj.bbox.maxy - obj.bbox.miny) &amp;lt; 10000
]

print(f&quot;필터링된 객체: {len(filtered_objects)}개&quot;)
print(f&quot;고신뢰도 객체: {len(high_conf_objects)}개&quot;)
print(f&quot;작은 객체: {len(small_objects)}개&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;성능 최적화 팁&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;GPU 메모리 관리&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대용량 이미지를 처리할 때 GPU 메모리 부족 문제가 발생할 수 있습니다:&lt;/p&gt;
&lt;pre class=&quot;properties&quot;&gt;&lt;code&gt;# 슬라이스 크기 줄이기
result = get_sliced_prediction(
    image_path,
    detection_model,
    slice_height=512,  # 640 &amp;rarr; 512
    slice_width=512,
    overlap_height_ratio=0.15
)

# 배치 처리 시 메모리 정리
import gc
import torch

for img_path in image_list:
    result = get_sliced_prediction(img_path, detection_model, ...)
    # 결과 처리

    # 메모리 정리
    del result
    gc.collect()
    if torch.cuda.is_available():
        torch.cuda.empty_cache()&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;처리 속도 향상&lt;/h3&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;# 오버랩 비율 줄이기 (정확도 약간 감소, 속도 향상)
result = get_sliced_prediction(
    image_path,
    detection_model,
    slice_height=640,
    slice_width=640,
    overlap_height_ratio=0.1,  # 0.2 &amp;rarr; 0.1
    overlap_width_ratio=0.1
)

# 슬라이스 크기 키우기 (타일 개수 감소)
result = get_sliced_prediction(
    image_path,
    detection_model,
    slice_height=800,  # 640 &amp;rarr; 800
    slice_width=800
)&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;SAHI vs 일반 추론 성능 비교&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실제 프로젝트에서 측정한 결과:&lt;/p&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;방식&lt;/th&gt;
&lt;th&gt;작은 객체 탐지율&lt;/th&gt;
&lt;th&gt;처리 시간&lt;/th&gt;
&lt;th&gt;메모리 사용량&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;일반 YOLO&lt;/td&gt;
&lt;td&gt;65%&lt;/td&gt;
&lt;td&gt;0.2초&lt;/td&gt;
&lt;td&gt;2GB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SAHI (640x640, 0.2 overlap)&lt;/td&gt;
&lt;td&gt;89%&lt;/td&gt;
&lt;td&gt;1.5초&lt;/td&gt;
&lt;td&gt;3GB&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;사용 권장 시나리오:&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;✅ 고해상도 이미지 (1920x1080 이상)&lt;/li&gt;
&lt;li&gt;✅ 작은 객체 탐지가 중요한 경우&lt;/li&gt;
&lt;li&gt;✅ 정확도가 속도보다 우선시되는 경우&lt;/li&gt;
&lt;li&gt;❌ 실시간 처리가 필요한 경우 (FPS 중요)&lt;/li&gt;
&lt;li&gt;❌ 저해상도 이미지&lt;/li&gt;
&lt;li&gt;❌ 큰 객체만 탐지하는 경우&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;다양한 모델 지원&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SAHI는 YOLO 외에도 다양한 객체 탐지 모델을 지원합니다:&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;# YOLOv8
model = AutoDetectionModel.from_pretrained(
    model_type='yolov8',
    model_path='yolov8n.pt'
)

# YOLOv5
model = AutoDetectionModel.from_pretrained(
    model_type='yolov5',
    model_path='yolov5s.pt'
)

# MMDetection (Faster R-CNN, Cascade R-CNN 등)
model = AutoDetectionModel.from_pretrained(
    model_type='mmdet',
    model_path='faster_rcnn_r50_fpn_1x_coco.py',
    config_path='faster_rcnn_r50_fpn_1x_coco.py',
    model_path='faster_rcnn_r50_fpn_1x_coco.pth'
)

# Detectron2
model = AutoDetectionModel.from_pretrained(
    model_type='detectron2',
    model_path='COCO-Detection/faster_rcnn_R_50_FPN_3x.yaml',
    config_path='COCO-Detection/faster_rcnn_R_50_FPN_3x.yaml'
)&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;결과 내보내기&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;이미지로 저장&lt;/h3&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;from sahi.predict import get_sliced_prediction

result = get_sliced_prediction(image_path, detection_model, ...)

# 시각화된 결과 저장
result.export_visuals(
    export_dir='output/',
    file_name='result',
    rect_th=2,  # 박스 두께
    text_size=0.5,  # 텍스트 크기
    text_th=2  # 텍스트 두께
)&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;COCO 형식으로 저장&lt;/h3&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;# COCO JSON 형식으로 결과 저장
from sahi.utils.coco import Coco

coco = Coco()
coco.add_image(image_path)

for obj in result.object_prediction_list:
    coco.add_annotation(obj, image_id=0)

coco.save('result.json')&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;CSV로 저장&lt;/h3&gt;
&lt;pre class=&quot;livecodeserver&quot;&gt;&lt;code&gt;import csv

# 탐지 결과를 CSV로 저장
with open('detections.csv', 'w', newline='') as f:
    writer = csv.writer(f)
    writer.writerow(['이미지', '클래스', '신뢰도', 'x1', 'y1', 'x2', 'y2'])

    for obj in result.object_prediction_list:
        writer.writerow([
            'image.jpg',
            obj.category.name,
            f&quot;{obj.score.value:.4f}&quot;,
            obj.bbox.minx,
            obj.bbox.miny,
            obj.bbox.maxx,
            obj.bbox.maxy
        ])&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;실제 프로젝트 적용 사례&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;YOLO 데이터셋 레이블 편집기에 SAHI를 통합한 예제:&lt;/p&gt;
&lt;pre class=&quot;python&quot;&gt;&lt;code&gt;import torch
from ultralytics import YOLO
from sahi import AutoDetectionModel
from sahi.predict import get_sliced_prediction

class LabelEditor:
    def __init__(self):
        self.model = None
        self.device = 'cuda' if torch.cuda.is_available() else 'cpu'

    def load_model(self, model_path):
        &quot;&quot;&quot;YOLO 모델 로드&quot;&quot;&quot;
        self.model = YOLO(model_path)
        self.model.to(self.device)
        print(f&quot;모델 로드 완료: {model_path} (디바이스: {self.device})&quot;)

    def run_sahi_inference(self, image_path):
        &quot;&quot;&quot;SAHI를 사용한 정밀 추론&quot;&quot;&quot;
        if not self.model:
            raise ValueError(&quot;모델이 로드되지 않았습니다.&quot;)

        # SAHI 모델 래퍼 생성
        detection_model = AutoDetectionModel.from_pretrained(
            model_type='yolov8',
            model_path=str(self.model.ckpt_path),
            confidence_threshold=0.25,
            device=self.device
        )

        # 슬라이스 기반 추론
        result = get_sliced_prediction(
            image_path,
            detection_model,
            slice_height=640,
            slice_width=640,
            overlap_height_ratio=0.2,
            overlap_width_ratio=0.2,
            verbose=0
        )

        # 결과를 YOLO 형식으로 변환
        boxes = []
        for obj in result.object_prediction_list:
            box = {
                'x1': obj.bbox.minx,
                'y1': obj.bbox.miny,
                'x2': obj.bbox.maxx,
                'y2': obj.bbox.maxy,
                'confidence': obj.score.value,
                'class_id': obj.category.id,
                'class_name': obj.category.name
            }
            boxes.append(box)

        print(f&quot;SAHI 추론 완료: {len(boxes)}개 객체 탐지&quot;)
        return boxes

# 사용 예
editor = LabelEditor()
editor.load_model('yolov8m.pt')
boxes = editor.run_sahi_inference('test_image.jpg')

for i, box in enumerate(boxes):
    print(f&quot;{i+1}. {box['class_name']} ({box['confidence']:.2f}): &quot;
          f&quot;[{box['x1']:.0f}, {box['y1']:.0f}, {box['x2']:.0f}, {box['y2']:.0f}]&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;마무리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SAHI는 간단한 설치와 사용법으로 객체 탐지 성능을 크게 향상시킬 수 있는 강력한 도구입니다. 특히 고해상도 이미지에서 작은 객체를 탐지해야 하는 프로젝트에서는 필수적으로 고려해볼 만한 기술입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이미지 슬라이싱이라는 간단한 아이디어로 탐지율을 20% 이상 향상시킬 수 있으며, 기존 YOLO 모델을 그대로 사용할 수 있다는 점에서 매우 실용적입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;주요 장점 요약:&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;✅ 작은 객체 탐지 성능 대폭 향상&lt;/li&gt;
&lt;li&gt;✅ 기존 모델 그대로 사용 가능&lt;/li&gt;
&lt;li&gt;✅ 간단한 API로 쉬운 통합&lt;/li&gt;
&lt;li&gt;✅ 다양한 객체 탐지 모델 지원&lt;/li&gt;
&lt;li&gt;✅ 후처리 옵션 풍부&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;참고 자료:&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;SAHI GitHub: &lt;a href=&quot;https://github.com/obss/sahi&quot;&gt;https://github.com/obss/sahi&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;공식 문서: &lt;a href=&quot;https://docs.sahi.ai/&quot;&gt;https://docs.sahi.ai/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;논문: &lt;a href=&quot;https://arxiv.org/abs/2202.06934&quot;&gt;https://arxiv.org/abs/2202.06934&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>영상처리/Object Detection</category>
      <author>Ninestar</author>
      <guid isPermaLink="true">https://data-science.tistory.com/734</guid>
      <comments>https://data-science.tistory.com/734#entry734comment</comments>
      <pubDate>Wed, 4 Feb 2026 10:36:08 +0900</pubDate>
    </item>
    <item>
      <title>로컬 AI로 만드는 우리 회사 전용 매뉴얼 챗봇-RAG와 한국어 AI로 똑똑하게</title>
      <link>https://data-science.tistory.com/733</link>
      <description>&lt;h1&gt;RAG 기반 OO제품 매뉴얼 챗봇 구축&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한국어 특화 RAG 챗봇 구축 (KURE-v1 + Ollama + ChromaDB)&lt;br /&gt;&quot;RAG 파이프라인 완벽 구현: PDF &amp;rarr; 임베딩 &amp;rarr; 검색 &amp;rarr; 생성&quot;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;프로젝트 개요&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;로컬 LLM(Ollama)과 한국어 특화 임베딩을 사용하여 OO제품 매뉴얼 PDF를 학습하고 질문에 답변하는 RAG 챗봇을 구축했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;핵심 기술 스택&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;임베딩&lt;/b&gt;: KURE-v1 (고려대 한국어 특화)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;벡터 DB&lt;/b&gt;: ChromaDB&lt;/li&gt;
&lt;li&gt;&lt;b&gt;LLM&lt;/b&gt;: Qwen2.5-Coder 32B (Ollama)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;PDF 처리&lt;/b&gt;: PyMuPDF&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;시스템 아키텍처&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;전체 흐름도&lt;/h3&gt;
&lt;pre class=&quot;gcode&quot;&gt;&lt;code&gt;PDF 매뉴얼
    &amp;darr; (텍스트/이미지 추출)
청킹 (1000자, 200 오버랩)
    &amp;darr; (KURE 임베딩)
ChromaDB 벡터 저장
    &amp;darr;
사용자 질문
    &amp;darr; (질문 임베딩)
벡터 검색 (Top 5)
    &amp;darr; (컨텍스트 구성)
LLM 답변 생성
    &amp;darr;
답변 + 참고자료 + 관련 이미지&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;핵심 모듈 구조&lt;/h3&gt;
&lt;pre class=&quot;1c&quot;&gt;&lt;code&gt;manual-chatbot/
├── src/
│   ├── pdf_processor.py     # PDF &amp;rarr; 텍스트/이미지 추출 &amp;rarr; 청킹
│   ├── embedder_kure.py     # KURE 한국어 임베딩
│   ├── vector_store.py      # ChromaDB 벡터 저장/검색
│   ├── rag_pipeline.py      # RAG 로직 (검색 &amp;rarr; 생성)
│   └── chatbot.py           # 대화형 인터페이스
└── main.py                  # CLI 진입점&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;핵심 구현 코드&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;PDF 처리 및 청킹&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PDF에서 텍스트와 이미지를 추출하고, 의미있는 단위로 분할합니다.&lt;/p&gt;
&lt;pre class=&quot;python&quot;&gt;&lt;code&gt;class PDFProcessor:
    &quot;&quot;&quot;PDF에서 텍스트와 이미지를 추출&quot;&quot;&quot;

    def extract_content(self, pdf_path: str) -&amp;gt; List[Dict]:
        &quot;&quot;&quot;페이지별 텍스트와 이미지 추출&quot;&quot;&quot;
        doc = fitz.open(pdf_path)
        pages_content = []

        for page_num in range(len(doc)):
            page = doc.load_page(page_num)
            text = page.get_text()

            # 의미있는 이미지만 필터링
            page_images = []
            for img in page.get_images(full=True):
                if self._is_valid_image(image_bytes, width, height):
                    page_images.append(image_path)

            pages_content.append({
                &quot;page&quot;: page_num + 1,
                &quot;text&quot;: text.strip(),
                &quot;images&quot;: page_images,
                &quot;pdf_name&quot;: pdf_name
            })

        return pages_content

    def chunk_content(self, pages_content, chunk_size=1000, overlap=200):
        &quot;&quot;&quot;텍스트를 오버랩이 있는 청크로 분할&quot;&quot;&quot;
        chunks = []
        for page_data in pages_content:
            text = page_data[&quot;text&quot;]
            start = 0

            while start &amp;lt; len(text):
                end = start + chunk_size
                chunk_text = text[start:end]

                chunks.append({
                    &quot;text&quot;: chunk_text,
                    &quot;metadata&quot;: {
                        &quot;page&quot;: page_data[&quot;page&quot;],
                        &quot;pdf_name&quot;: page_data[&quot;pdf_name&quot;],
                        &quot;images&quot;: page_data[&quot;images&quot;]
                    }
                })

                start = end - overlap  # 오버랩 적용

        return chunks&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;핵심 포인트&lt;/b&gt;:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이미지 필터링: 너무 작거나 중복된 이미지 제거 (아이콘, 로고 등)&lt;/li&gt;
&lt;li&gt;청킹 오버랩: 문맥 유지를 위해 200자 중첩&lt;/li&gt;
&lt;li&gt;메타데이터 보존: 원본 페이지 번호, 이미지 경로 등 추적&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;KURE 한국어 임베딩&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한국어에 특화된 KURE 모델로 텍스트를 1024차원 벡터로 변환합니다.&lt;/p&gt;
&lt;pre class=&quot;python&quot;&gt;&lt;code&gt;class KUREEmbedder:
    &quot;&quot;&quot;KURE 모델을 사용한 한국어 특화 임베딩&quot;&quot;&quot;

    def __init__(self, model_name=&quot;nlpai-lab/KURE-v1&quot;):
        from sentence_transformers import SentenceTransformer
        self.model = SentenceTransformer(model_name)

    def embed_text(self, text: str) -&amp;gt; List[float]:
        &quot;&quot;&quot;단일 텍스트 임베딩&quot;&quot;&quot;
        embedding = self.model.encode(text, convert_to_numpy=True)
        return embedding.tolist()

    def embed_batch(self, texts: List[str], batch_size=32) -&amp;gt; List[List[float]]:
        &quot;&quot;&quot;배치 임베딩 (성능 최적화)&quot;&quot;&quot;
        embeddings = self.model.encode(
            texts,
            batch_size=batch_size,
            show_progress_bar=True,
            normalize_embeddings=True  # 코사인 유사도 최적화
        )
        return embeddings.tolist()&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;KURE 선택 이유&lt;/b&gt;:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;한국어 처리 성능 우수&lt;/li&gt;
&lt;li&gt;1024차원 고밀도 벡터&lt;/li&gt;
&lt;li&gt;코사인 유사도 85%+ 달성&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;ChromaDB 벡터 저장소&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;벡터 임베딩을 저장하고 빠르게 검색합니다.&lt;/p&gt;
&lt;pre class=&quot;python&quot;&gt;&lt;code&gt;class VectorStore:
    &quot;&quot;&quot;ChromaDB 벡터 저장소&quot;&quot;&quot;

    def __init__(self, persist_directory=&quot;data/vectordb&quot;):
        import chromadb
        self.client = chromadb.PersistentClient(path=persist_directory)
        self.collection = self.client.get_or_create_collection(
            name=&quot;manual&quot;,
            metadata={&quot;hnsw:space&quot;: &quot;cosine&quot;}
        )

    def add_documents(self, texts, embeddings, metadatas):
        &quot;&quot;&quot;문서와 임베딩 추가&quot;&quot;&quot;
        ids = [f&quot;doc_{i}&quot; for i in range(len(texts))]

        self.collection.add(
            embeddings=embeddings,
            documents=texts,
            metadatas=metadatas,
            ids=ids
        )

    def search(self, query_embedding, top_k=5):
        &quot;&quot;&quot;유사도 기반 검색&quot;&quot;&quot;
        results = self.collection.query(
            query_embeddings=[query_embedding],
            n_results=top_k,
            include=['documents', 'metadatas', 'distances']
        )

        return {
            'documents': results['documents'][0],
            'metadatas': results['metadatas'][0],
            'distances': results['distances'][0]
        }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;핵심 기능&lt;/b&gt;:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;코사인 유사도 기반 검색&lt;/li&gt;
&lt;li&gt;영속성 저장 (디스크 저장)&lt;/li&gt;
&lt;li&gt;Top-K 검색 (기본 5개)&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;RAG 파이프라인&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;검색과 생성을 통합한 RAG 로직의 핵심입니다.&lt;/p&gt;
&lt;pre class=&quot;python&quot;&gt;&lt;code&gt;class RAGPipeline:
    &quot;&quot;&quot;RAG 파이프라인: 검색 &amp;rarr; 컨텍스트 생성 &amp;rarr; LLM 응답&quot;&quot;&quot;

    def __init__(self, vector_store, embedder, llm, top_k=5):
        self.vector_store = vector_store
        self.embedder = embedder
        self.llm = llm
        self.top_k = top_k

        self.system_prompt = &quot;&quot;&quot;당신은 OO제품 매뉴얼 전문가입니다.
매뉴얼 내용을 바탕으로 정확하고 친절하게 답변하세요.
확실하지 않으면 &quot;매뉴얼에서 해당 정보를 찾을 수 없습니다&quot;라고 말하세요.&quot;&quot;&quot;

    def query(self, question: str) -&amp;gt; Dict:
        &quot;&quot;&quot;질문에 대한 답변 생성&quot;&quot;&quot;
        # 1. 질문 임베딩
        query_embedding = self.embedder.embed_text(question)

        # 2. 유사 문서 검색
        search_results = self.vector_store.search(
            query_embedding=query_embedding,
            top_k=self.top_k
        )

        # 3. 컨텍스트 생성
        context = self._build_context(search_results)

        # 4. 프롬프트 생성
        prompt = f&quot;&quot;&quot;다음은 OO제품 매뉴얼에서 검색된 관련 내용입니다:

{context}

위 매뉴얼 내용을 바탕으로 다음 질문에 답변해주세요:

질문: {question}

답변:&quot;&quot;&quot;

        # 5. LLM 답변 생성
        answer = self.llm.generate(
            prompt=prompt,
            system=self.system_prompt
        )

        # 6. 관련 이미지 수집
        images = self._collect_images(search_results)

        return {
            &quot;answer&quot;: answer,
            &quot;images&quot;: images,
            &quot;sources&quot;: self._format_sources(search_results)
        }

    def _build_context(self, search_results):
        &quot;&quot;&quot;검색 결과를 컨텍스트로 변환&quot;&quot;&quot;
        context_parts = []

        for doc, metadata in zip(search_results['documents'],
                                search_results['metadatas']):
            pdf_name = metadata.get('pdf_name', 'Unknown')
            page = metadata.get('page', 'Unknown')

            context_item = f&quot;[출처: {pdf_name} - 페이지 {page}]\n{doc}&quot;
            context_parts.append(context_item)

        return &quot;\n\n---\n\n&quot;.join(context_parts)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;RAG 5단계&lt;/b&gt;:&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;질문 임베딩 생성&lt;/li&gt;
&lt;li&gt;벡터 DB에서 유사 문서 검색&lt;/li&gt;
&lt;li&gt;검색 결과를 컨텍스트로 변환&lt;/li&gt;
&lt;li&gt;시스템 프롬프트 + 컨텍스트 + 질문 조합&lt;/li&gt;
&lt;li&gt;LLM으로 답변 생성&lt;/li&gt;
&lt;/ol&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;대화 히스토리 관리&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이전 대화를 기억하는 ConversationRAG로 확장합니다.&lt;/p&gt;
&lt;pre class=&quot;python&quot;&gt;&lt;code&gt;class ConversationRAG(RAGPipeline):
    &quot;&quot;&quot;대화 히스토리를 관리하는 RAG 파이프라인&quot;&quot;&quot;

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.conversation_history = []

    def _is_follow_up_question(self, question: str) -&amp;gt; bool:
        &quot;&quot;&quot;후속 질문인지 LLM으로 판단&quot;&quot;&quot;
        if not self.conversation_history:
            return False

        last_qa = self.conversation_history[-1]

        prompt = f&quot;&quot;&quot;다음 두 질문이 관련이 있는지 판단해주세요.

이전 질문: {last_qa['question']}
현재 질문: {question}

후속 질문이면 &quot;예&quot;, 새로운 주제면 &quot;아니오&quot;라고만 답변하세요.&quot;&quot;&quot;

        response = self.llm.generate(prompt=prompt)
        return &quot;예&quot; in response.strip()

    def query(self, question: str, use_history=True):
        &quot;&quot;&quot;대화 히스토리를 고려한 답변 생성&quot;&quot;&quot;
        is_follow_up = False
        if use_history:
            is_follow_up = self._is_follow_up_question(question)

        # 벡터 검색 (항상 원본 질문 사용)
        query_embedding = self.embedder.embed_text(question)
        search_results = self.vector_store.search(query_embedding, self.top_k)
        context = self._build_context(search_results)

        # 후속 질문인 경우 히스토리 포함
        if is_follow_up and self.conversation_history:
            recent_history = self.conversation_history[-2:]
            history_text = &quot;\n&quot;.join([
                f&quot;Q: {h['question']}\nA: {h['answer']}&quot;
                for h in recent_history
            ])
            prompt = f&quot;&quot;&quot;이전 대화:
{history_text}

---

매뉴얼 내용:
{context}

질문: {question}
답변:&quot;&quot;&quot;
        else:
            prompt = self._build_prompt(question, context)

        answer = self.llm.generate(prompt=prompt, system=self.system_prompt)

        # 히스토리에 추가
        self.conversation_history.append({
            &quot;question&quot;: question,
            &quot;answer&quot;: answer
        })

        return {&quot;answer&quot;: answer, ...}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;스마트 히스토리 관리&lt;/b&gt;:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;LLM으로 후속 질문 자동 감지&lt;/li&gt;
&lt;li&gt;관련 있을 때만 히스토리 컨텍스트 추가&lt;/li&gt;
&lt;li&gt;최근 2개 대화만 사용 (토큰 절약)&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;성능 최적화 기법&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;배치 임베딩&lt;/h3&gt;
&lt;pre class=&quot;ini&quot;&gt;&lt;code&gt;# 나쁜 예: 루프로 하나씩 처리
embeddings = [embedder.embed_text(text) for text in texts]

# 좋은 예: 배치로 한번에 처리
embeddings = embedder.embed_batch(texts, batch_size=32)&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;컨텍스트 길이 제한&lt;/h3&gt;
&lt;pre class=&quot;python&quot;&gt;&lt;code&gt;def _build_context(self, search_results):
    context_parts = []
    total_length = 0
    max_context_length = 4000  # 토큰 제한

    for doc, metadata in zip(...):
        context_item = f&quot;[출처: {pdf_name}]\n{doc}&quot;

        if total_length + len(context_item) &amp;gt; max_context_length:
            break  # 길이 초과 시 중단

        context_parts.append(context_item)
        total_length += len(context_item)

    return &quot;\n\n---\n\n&quot;.join(context_parts)&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;이미지 중복 제거&lt;/h3&gt;
&lt;pre class=&quot;ruby&quot;&gt;&lt;code&gt;def _is_valid_image(self, image_bytes, width, height):
    # 해시 기반 중복 체크
    image_hash = hashlib.md5(image_bytes).hexdigest()
    if image_hash in self.image_hashes:
        return False, &quot;duplicate&quot;

    self.image_hashes.add(image_hash)
    return True, &quot;valid&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;실행 예시&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;데이터 수집 (최초 1회)&lt;/h3&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;python main.py ingest --manual-dir ~/manual

# 출력:
#   Processing PDF: OO제품_사용자매뉴얼 (127 pages)
# ✓ Extracted 127 pages with content
#   Image Statistics:
#    Total images found: 234
#    Valid images saved: 89
#    Filtered images: 145
# ✓ Created 147 chunks from content
#   KURE로 147개 텍스트 임베딩 생성 중...
# ✓ 완료: 147개 임베딩 생성&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;대화형 챗봇 실행&lt;/h3&gt;
&lt;pre class=&quot;vala&quot;&gt;&lt;code&gt;python main.py chat

# 출력:
#   OO제품 Manual Chatbot
# Type your question or '/help' for commands
#
# You: OO제품 비밀번호를 재설정하는 방법은?
#
#   Searching relevant documents...
#   Generating answer...
#
# Assistant: OO제품 비밀번호를 재설정하는 방법은 다음과 같습니다:
#
# 1. 설정 메뉴 진입
# 2. 시스템 &amp;gt; 사용자 관리 선택
# 3. 해당 사용자 선택 후 '비밀번호 변경' 클릭
# 4. 기존 비밀번호와 새 비밀번호 입력
#
#   관련 자료:
#   1. OO제품_사용자매뉴얼 (Page 45) [유사도: 89%]
#   2. OO제품_간편매뉴얼 (Page 12) [유사도: 76%]
#
#   관련 이미지 (2개):
#   - data/raw/images/OO제품_사용자매뉴얼_page045_img1.png&lt;/code&gt;&lt;/pre&gt;
&lt;iframe src=&quot;https://www.youtube.com/embed/7HmpKHPV7Q0?autoplay=1&amp;mute=1&quot;
        width=&quot;800&quot; height=&quot;1200&quot;
        frameborder=&quot;0&quot;
        allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture&quot;
        allowfullscreen&gt;
&lt;/iframe&gt;

&lt;p&gt;&lt;figure class=&quot;fileblock&quot; data-ke-align=&quot;alignCenter&quot;&gt;&lt;a href=&quot;https://blog.kakaocdn.net/dn/kJO1t/dJMcaaKMzFn/MckUMCHnCPlqtKl3sfBDhk/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%BA%90%EC%8A%A4%ED%8A%B8%202026-01-09%2016-08-29.mp4?attach=1&amp;amp;knm=tfile.mp4&quot; class=&quot;&quot;&gt;
    &lt;div class=&quot;image&quot;&gt;&lt;/div&gt;
    &lt;div class=&quot;desc&quot;&gt;&lt;div class=&quot;filename&quot;&gt;&lt;span class=&quot;name&quot;&gt;스크린캐스트 2026-01-09 16-08-29.mp4&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;size&quot;&gt;11.78MB&lt;/div&gt;
&lt;/div&gt;
  &lt;/a&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;성능 지표&lt;/h2&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;항목&lt;/th&gt;
&lt;th&gt;수치&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;PDF 문서&lt;/td&gt;
&lt;td&gt;4개 (총 200페이지)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;추출 이미지&lt;/td&gt;
&lt;td&gt;89개 (필터링 후)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;청크 개수&lt;/td&gt;
&lt;td&gt;147개&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;임베딩 차원&lt;/td&gt;
&lt;td&gt;1024-dim&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;데이터 수집 시간&lt;/td&gt;
&lt;td&gt;~35초&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;질의 응답 시간&lt;/td&gt;
&lt;td&gt;~3-6초&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;평균 유사도&lt;/td&gt;
&lt;td&gt;85%+&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;메모리 사용량&lt;/td&gt;
&lt;td&gt;~650MB&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;핵심 설계 원칙&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;모듈화&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각 레이어가 독립적으로 작동하여 유지보수가 쉽습니다.&lt;/p&gt;
&lt;pre class=&quot;gauss&quot;&gt;&lt;code&gt;PDF Processor &amp;rarr; Embedder &amp;rarr; Vector Store &amp;rarr; RAG Pipeline &amp;rarr; Chatbot&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;한국어 최적화&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;KURE-v1: 한국어 특화 임베딩&lt;/li&gt;
&lt;li&gt;Qwen2.5-Coder: 한국어 생성 우수&lt;/li&gt;
&lt;li&gt;85%+ 유사도 정확도 달성&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;컨텍스트 보존&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;청킹 오버랩 200자&lt;/li&gt;
&lt;li&gt;출처 정보 메타데이터 보존&lt;/li&gt;
&lt;li&gt;이미지 경로 추적&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;사용자 경험&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;실시간 진행 상황 표시&lt;/li&gt;
&lt;li&gt;상세한 출처 정보 제공&lt;/li&gt;
&lt;li&gt;관련 이미지 자동 연결&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;결론&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;로컬 LLM과 한국어 특화 임베딩을 활용하여 실용적인 RAG 챗봇을 구축했습니다. 핵심은:&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;PDF 처리&lt;/b&gt;: 텍스트/이미지 추출 &amp;rarr; 청킹 &amp;rarr; 메타데이터 보존&lt;/li&gt;
&lt;li&gt;&lt;b&gt;임베딩&lt;/b&gt;: KURE 한국어 특화 모델로 85%+ 정확도&lt;/li&gt;
&lt;li&gt;&lt;b&gt;검색&lt;/b&gt;: ChromaDB 코사인 유사도 Top-5 검색&lt;/li&gt;
&lt;li&gt;&lt;b&gt;생성&lt;/b&gt;: 컨텍스트 기반 LLM 답변 생성&lt;/li&gt;
&lt;li&gt;&lt;b&gt;대화&lt;/b&gt;: 스마트 히스토리 관리로 자연스러운 대화&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 시스템은 OO제품 매뉴얼뿐만 아니라 모든 PDF 기반 문서에 적용 가능하며, 완전히 로컬에서 실행되어 데이터 프라이버시가 보장됩니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;기술 스택&lt;/b&gt;: Python, KURE, ChromaDB, Ollama, PyMuPDF, FastAPI, RAG, LLM&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&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://blog.yakkomajuri.com/blog/local-rag&quot;&gt;로컬 RAG를 구축하고 싶으신가요?&lt;/a&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://news.hada.io/topic?id=24712&quot;&gt;https://news.hada.io/topic?id=24712&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;KURE(Korea University Retrieval Embedding model) 고려대 한국어 임베딩 모델&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://yjoonjang.medium.com/koe5-%EC%B5%9C%EC%B4%88%EC%9D%98-%ED%95%9C%EA%B5%AD%EC%96%B4-%EC%9E%84%EB%B2%A0%EB%94%A9-%EB%AA%A8%EB%8D%B8-multilingual-e5-finetune-22fa7e56d220&quot;&gt;https://yjoonjang.medium.com/koe5-%EC%B5%9C%EC%B4%88%EC%9D%98-%ED%95%9C%EA%B5%AD%EC%96%B4-%EC%9E%84%EB%B2%A0%EB%94%A9-%EB%AA%A8%EB%8D%B8-multilingual-e5-finetune-22fa7e56d220&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/nlpai-lab/KURE&quot;&gt;https://github.com/nlpai-lab/KURE&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;RAG 도입기 챗봇을 만들다 (medium)&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://medium.com/spoontech/rag-%EB%8F%84%EC%9E%85%EA%B8%B0-%EC%B1%97%EB%B4%87%EC%9D%84-%EB%A7%8C%EB%93%A4%EB%8B%A4-%EC%A1%B0%EC%9A%A9%ED%9E%88-%EA%B7%B8%EB%A6%AC%EA%B3%A0-%EB%82%AD%EB%A7%8C%EC%A0%81%EC%9C%BC%EB%A1%9C-e96841c87979&quot;&gt;https://medium.com/spoontech/rag-%EB%8F%84%EC%9E%85%EA%B8%B0-%EC%B1%97%EB%B4%87%EC%9D%84-%EB%A7%8C%EB%93%A4%EB%8B%A4-%EC%A1%B0%EC%9A%A9%ED%9E%88-%EA%B7%B8%EB%A6%AC%EA%B3%A0-%EB%82%AD%EB%A7%8C%EC%A0%81%EC%9C%BC%EB%A1%9C-e96841c87979&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>AI</category>
      <author>Ninestar</author>
      <guid isPermaLink="true">https://data-science.tistory.com/733</guid>
      <comments>https://data-science.tistory.com/733#entry733comment</comments>
      <pubDate>Tue, 13 Jan 2026 11:07:05 +0900</pubDate>
    </item>
    <item>
      <title>Ollama를 이용한 로컬 코딩 어시스턴트 모델 (qwen2.5)</title>
      <link>https://data-science.tistory.com/732</link>
      <description>&lt;p data-ke-size=&quot;size18&quot;&gt;OS: Ubuntu24.04&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;CPU: Intel(R) Core(TM) Ultra 9 285K&lt;br /&gt;GPU: rtx5090 2장&lt;br /&gt;Memory: DDR5 128GB&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Ollama 설치&lt;/h2&gt;
&lt;pre class=&quot;vim&quot;&gt;&lt;code&gt;curl -fsSL https://ollama.com/install.sh | sh&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;설치 확인:&lt;/p&gt;
&lt;pre class=&quot;ada&quot;&gt;&lt;code&gt;ollama --version&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;모델 다운로드&lt;/h2&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;ollama pull qwen2.5-coder:32b-instruct-q8_0&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다운로드 완료 후 테스트:&lt;/p&gt;
&lt;pre class=&quot;dockerfile&quot;&gt;&lt;code&gt;ollama run qwen2.5-coder:32b-instruct-q8_0 &quot;hello&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Ollama 서버 외부 접속 허용&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본적으로 localhost만 허용이라 설정 변경 필요:&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;sudo systemctl edit ollama&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;에디터가 열리면 아래 내용 입력:&lt;/p&gt;
&lt;pre class=&quot;ini&quot;&gt;&lt;code&gt;[Service]
Environment=&quot;OLLAMA_HOST=0.0.0.0&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저장 후 재시작:&lt;/p&gt;
&lt;pre class=&quot;properties&quot;&gt;&lt;code&gt;sudo systemctl daemon-reload
sudo systemctl restart ollama&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;확인:&lt;/p&gt;
&lt;pre class=&quot;awk&quot;&gt;&lt;code&gt;curl http://localhost:11434/api/tags&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_1767759873695&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sudo netstat -tlnp | grep 11434

tcp6       0      0 :::11434                :::*                    LISTEN      132019/ollama&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;아래와 같이 여전히 127.0.0.1 로컬 호스트가 나온다면 적용이 안된겁니다. 다시 에디터로 수정하거나 아래와 같이 직접 파일을 만들어 수정합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1767759890138&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;tcp        0      0 127.0.0.1:11434         0.0.0.0:*               LISTEN      130535/ollama&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_1767759930380&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sudo mkdir -p /etc/systemd/system/ollama.service.d

sudo tee /etc/systemd/system/ollama.service.d/override.conf &amp;lt;&amp;lt; EOF
[Service]
Environment=&quot;OLLAMA_HOST=0.0.0.0&quot;
EOF

sudo systemctl daemon-reload
sudo systemctl restart ollama&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;br /&gt;VS Code에 Continue 확장 설치&lt;/h2&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;VS Code 열기&lt;/li&gt;
&lt;li&gt;확장(Extensions) 탭에서 &lt;code&gt;Continue&lt;/code&gt; 검색&lt;/li&gt;
&lt;li&gt;설치&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Continue 설정&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;VS Code에서 &lt;code&gt;Ctrl+Shift+P&lt;/code&gt; &amp;rarr; &lt;code&gt;Continue: Open Config&lt;/code&gt; 또는 직접 파일 열기:&lt;/p&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;# 설정 파일 위치
~/.continue/config.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래 내용으로 수정:&lt;/p&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;name: My Assistant
version: 1.0.0

models:
  - name: Qwen2.5 Coder 32B
    provider: ollama
    model: qwen2.5-coder:32b-instruct-q8_0
    apiBase: http://5090서버IP:11434

tabAutocompleteModel:
  name: Qwen2.5 Coder 32B
  provider: ollama
  model: qwen2.5-coder:32b-instruct-q8_0
  apiBase: http://5090서버IP:11434&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;사용법&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;code&gt;Ctrl+L&lt;/code&gt;: 채팅창 열기 (코드 질문, 설명 요청)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Ctrl+I&lt;/code&gt;: 인라인 편집 (선택한 코드 수정)&lt;/li&gt;
&lt;li&gt;자동완성: 코딩 중 자동으로 제안&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;</description>
      <category>AI</category>
      <author>Ninestar</author>
      <guid isPermaLink="true">https://data-science.tistory.com/732</guid>
      <comments>https://data-science.tistory.com/732#entry732comment</comments>
      <pubDate>Wed, 7 Jan 2026 12:52:56 +0900</pubDate>
    </item>
    <item>
      <title>리눅스 터미널 환경 구성</title>
      <link>https://data-science.tistory.com/731</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. 터미네이터 설치&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1750294296757&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sudo apt-get install terminator&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;b&gt;2. zsh 설치&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1750294311990&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sudo apt-get install zsh&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1750294327000&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;chsh -s $(which zsh)
echo $SHELL&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;b&gt;3. ohMyZsh 설치(쉘 설정 쉽게 해줌)&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1750294431029&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sh -c &quot;$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)&quot;

또는

sh -c &quot;$(wget -O- https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)&quot;&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;&lt;b&gt;플러그인(zsh-autosuggestions)-자동완성&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1750294492688&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/zsh-users/zsh-autosuggestions ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-autosuggestions&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; .zshrc 파일을 수정합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1750294534459&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;plugins=(git zsh-autosuggestions)&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;797&quot; data-origin-height=&quot;278&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/4Uyjq/btsOGnGwISk/OvLEs1t48kEGPLhkbpFRc0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/4Uyjq/btsOGnGwISk/OvLEs1t48kEGPLhkbpFRc0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/4Uyjq/btsOGnGwISk/OvLEs1t48kEGPLhkbpFRc0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F4Uyjq%2FbtsOGnGwISk%2FOvLEs1t48kEGPLhkbpFRc0%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;797&quot; height=&quot;278&quot; data-origin-width=&quot;797&quot; data-origin-height=&quot;278&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 Ctrl+E 나 End키로 자동완성이 가능합니다.&lt;/p&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;&lt;b&gt;플러그인(syntax Highlighting)- 구문강조&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1750294622092&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/zsh-users/zsh-syntax-highlighting.git ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-syntax-highlighting&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_1750294637602&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;plugins=(git zsh-autosuggestions zsh-syntax-highlighting)&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;b&gt;4. ohMyZsh&amp;nbsp; 테마 수정&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;.zshrc 파일을 수정합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1750294713059&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;ZSH_THEME=&quot;dpoggi&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_1750294752653&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;source ~/.zshrc&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;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/ohmyzsh/ohmyzsh/wiki/themes&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://github.com/ohmyzsh/ohmyzsh/wiki/themes&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>컴퓨터</category>
      <author>Ninestar</author>
      <guid isPermaLink="true">https://data-science.tistory.com/731</guid>
      <comments>https://data-science.tistory.com/731#entry731comment</comments>
      <pubDate>Thu, 19 Jun 2025 10:22:50 +0900</pubDate>
    </item>
    <item>
      <title>라온제나 강남, 웨딩홀 계약 후기</title>
      <link>https://data-science.tistory.com/730</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div id=&quot;SE-a8ad23e2-b7fd-4bf5-8220-fc0249a690b5&quot; data-a11y-title=&quot;사진&quot; data-compid=&quot;SE-a8ad23e2-b7fd-4bf5-8220-fc0249a690b5&quot;&gt;
&lt;div&gt;
&lt;div data-direction=&quot;top&quot; data-compid=&quot;SE-a8ad23e2-b7fd-4bf5-8220-fc0249a690b5&quot; data-unitid=&quot;&quot;&gt;
&lt;div&gt;
&lt;div id=&quot;SE-a8ad23e2-b7fd-4bf5-8220-fc0249a690b5&quot;&gt;
&lt;div data-direction=&quot;top&quot; data-compid=&quot;&quot; data-unitid=&quot;SE-a8ad23e2-b7fd-4bf5-8220-fc0249a690b5&quot;&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;936&quot; data-origin-height=&quot;691&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bYVYv9/btsFM0d1eo3/M92vLPNRqeLJEK5EscVAak/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bYVYv9/btsFM0d1eo3/M92vLPNRqeLJEK5EscVAak/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bYVYv9/btsFM0d1eo3/M92vLPNRqeLJEK5EscVAak/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbYVYv9%2FbtsFM0d1eo3%2FM92vLPNRqeLJEK5EscVAak%2Fimg.jpg&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;886&quot; height=&quot;691&quot; data-origin-width=&quot;936&quot; data-origin-height=&quot;691&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-eef002ea-16a4-451a-b36b-e8377a9ace2f&quot; data-a11y-title=&quot;본문&quot; data-compid=&quot;SE-eef002ea-16a4-451a-b36b-e8377a9ace2f&quot;&gt;
&lt;div&gt;
&lt;div data-direction=&quot;top&quot; data-compid=&quot;SE-eef002ea-16a4-451a-b36b-e8377a9ace2f&quot; data-unitid=&quot;&quot;&gt;
&lt;div&gt;
&lt;div id=&quot;SE-d8c9d87e-41a6-4f8c-8423-1e431ddfcad2&quot;&gt;
&lt;p id=&quot;SE-6a4d7732-7b74-4bfe-9def-55c0b797529b&quot; style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p id=&quot;SE-2fc04fb4-1fab-436a-a895-1f0b8fb571df&quot; style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;강남구청역 도보 3분 거리에 있는 라온제나 웨딩홀에 방문해서 계약을 진행하고 왔어요&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-f80f25d9-6cec-4ac8-b1dd-b17f499a2265&quot; style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;홀이 총 2개였는데 8층 플로렌스홀과 9층 야외 아뜰리에홀이 있었어요&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-a7cd81df-2e65-4ca6-bad6-f9f1faab1e1e&quot; style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;저희는 실내에서 하길 원했고 8층으로 예약을 진행 했답니다&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-9df0bd12-f3e3-42fc-af84-7672b54df1ac&quot; style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;엘리베이터에서 내리자마다 보이는 넓은 로비 라운지는 넓은 통창이 있어서 쾌적하며 단정한 느낌을 주었어요&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-df719366-cc13-45e7-8fa2-1fa7974e40bc&quot; style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p id=&quot;SE-0e98307f-aa42-4bad-88ae-a2140cdf1bf9&quot; style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-360d35ce-03db-448b-88e5-b9ae3048e9bc&quot; data-a11y-title=&quot;사진&quot; data-compid=&quot;SE-360d35ce-03db-448b-88e5-b9ae3048e9bc&quot;&gt;
&lt;div&gt;
&lt;div data-direction=&quot;top&quot; data-compid=&quot;SE-360d35ce-03db-448b-88e5-b9ae3048e9bc&quot; data-unitid=&quot;&quot;&gt;
&lt;div&gt;
&lt;div id=&quot;SE-360d35ce-03db-448b-88e5-b9ae3048e9bc&quot;&gt;
&lt;div data-direction=&quot;top&quot; data-compid=&quot;&quot; data-unitid=&quot;SE-360d35ce-03db-448b-88e5-b9ae3048e9bc&quot;&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;936&quot; data-origin-height=&quot;653&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/OeDEC/btsFJ9cGtto/yjkskrHgOKPE70kxoT4w20/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/OeDEC/btsFJ9cGtto/yjkskrHgOKPE70kxoT4w20/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/OeDEC/btsFJ9cGtto/yjkskrHgOKPE70kxoT4w20/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FOeDEC%2FbtsFJ9cGtto%2FyjkskrHgOKPE70kxoT4w20%2Fimg.jpg&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;886&quot; height=&quot;653&quot; data-origin-width=&quot;936&quot; data-origin-height=&quot;653&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-730f6f90-d9a0-460f-b91d-0bcc68170ff2&quot; data-a11y-title=&quot;본문&quot; data-compid=&quot;SE-730f6f90-d9a0-460f-b91d-0bcc68170ff2&quot;&gt;
&lt;div&gt;
&lt;div data-direction=&quot;top&quot; data-compid=&quot;SE-730f6f90-d9a0-460f-b91d-0bcc68170ff2&quot; data-unitid=&quot;&quot;&gt;
&lt;div&gt;
&lt;div id=&quot;SE-f1b444de-86c7-4889-a809-e11e46265d60&quot;&gt;
&lt;p id=&quot;SE-7feeee11-953c-4629-90ef-e64721ed9b1e&quot; style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p id=&quot;SE-4c0c2042-b5a9-4908-817b-ef58880f59df&quot; style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;신부대기실 앞에 생화 꽃장식도 너무 아름다웠고&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-2cb98f58-9eeb-4d60-bd57-94691ec554df&quot; style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;tv도 설치되어 있어서 예식 진행 사항을 볼 수 있었답니다&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-a2c6e20c-becd-4ac9-9649-80520ce688ff&quot; style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p id=&quot;SE-d542c387-887d-4b90-9e2a-3e2a0811bf59&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-b8db1d1f-7a4d-4b54-b030-a293479bbb14&quot; data-a11y-title=&quot;사진&quot; data-compid=&quot;SE-b8db1d1f-7a4d-4b54-b030-a293479bbb14&quot;&gt;
&lt;div&gt;
&lt;div data-direction=&quot;top&quot; data-compid=&quot;SE-b8db1d1f-7a4d-4b54-b030-a293479bbb14&quot; data-unitid=&quot;&quot;&gt;
&lt;div&gt;
&lt;div id=&quot;SE-b8db1d1f-7a4d-4b54-b030-a293479bbb14&quot;&gt;
&lt;div data-direction=&quot;top&quot; data-compid=&quot;&quot; data-unitid=&quot;SE-b8db1d1f-7a4d-4b54-b030-a293479bbb14&quot;&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;936&quot; data-origin-height=&quot;671&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bQe5Yi/btsFNyar8qw/tpu8OUZQNnhKROes61HSD1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bQe5Yi/btsFNyar8qw/tpu8OUZQNnhKROes61HSD1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bQe5Yi/btsFNyar8qw/tpu8OUZQNnhKROes61HSD1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbQe5Yi%2FbtsFNyar8qw%2Ftpu8OUZQNnhKROes61HSD1%2Fimg.jpg&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;886&quot; height=&quot;671&quot; data-origin-width=&quot;936&quot; data-origin-height=&quot;671&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-508e46e4-d333-452a-8d1d-540f4ab784d9&quot; data-a11y-title=&quot;본문&quot; data-compid=&quot;SE-508e46e4-d333-452a-8d1d-540f4ab784d9&quot;&gt;
&lt;div&gt;
&lt;div data-direction=&quot;top&quot; data-compid=&quot;SE-508e46e4-d333-452a-8d1d-540f4ab784d9&quot; data-unitid=&quot;&quot;&gt;
&lt;div&gt;
&lt;div id=&quot;SE-fad745f3-7cb4-4d45-92f8-815c074c61f3&quot;&gt;
&lt;p id=&quot;SE-64e67e57-cadc-44b6-be7b-1423d20894e6&quot; style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;전체적인 색감과 인테리어가 단정하고 차분한 분위기여서 더 좋았던 거 같아요&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-fc3e66df-47b9-404f-b30c-2e1a65e62051&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;img style=&quot;text-align: center; caret-color: transparent; letter-spacing: 0px;&quot; src=&quot;https://blog.kakaocdn.net/dn/buOR8i/btsFLP5pcbw/Hde2xhltdWJkc5DfL0lvaK/img.jpg&quot; width=&quot;886&quot; data-origin-width=&quot;936&quot; data-origin-height=&quot;709&quot; data-is-animation=&quot;false&quot; /&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-e6faa161-ed16-4e0d-ad52-e3ed10f47efb&quot; data-a11y-title=&quot;본문&quot; data-compid=&quot;SE-e6faa161-ed16-4e0d-ad52-e3ed10f47efb&quot;&gt;
&lt;div&gt;
&lt;div data-direction=&quot;top&quot; data-compid=&quot;SE-e6faa161-ed16-4e0d-ad52-e3ed10f47efb&quot; data-unitid=&quot;&quot;&gt;
&lt;div&gt;
&lt;div id=&quot;SE-dfbd0ea9-5231-40d9-846a-1f10db769ef1&quot;&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p id=&quot;SE-ac0e646f-9b64-4460-85dc-d202155baed0&quot; style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;신부대기실도 화사하니 너무 예뻤고&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-901c5d2b-a4fc-4fa4-aca7-9e87a8ac1345&quot; style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;마카롱이나 음료 등 간단하게 먹을 수 있는 간식들이 구비되어 있어서 만족했어요&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-b9270594-f2a6-4c72-b27d-138e4842d5d6&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-e00b6064-74af-416f-a42f-5d7259d64018&quot; data-a11y-title=&quot;사진&quot; data-compid=&quot;SE-e00b6064-74af-416f-a42f-5d7259d64018&quot;&gt;
&lt;div&gt;
&lt;div data-direction=&quot;top&quot; data-compid=&quot;SE-e00b6064-74af-416f-a42f-5d7259d64018&quot; data-unitid=&quot;&quot;&gt;
&lt;div&gt;
&lt;div id=&quot;SE-e00b6064-74af-416f-a42f-5d7259d64018&quot;&gt;
&lt;div data-direction=&quot;top&quot; data-compid=&quot;&quot; data-unitid=&quot;SE-e00b6064-74af-416f-a42f-5d7259d64018&quot;&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;936&quot; data-origin-height=&quot;695&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/GYyCF/btsFLo1jXPR/VlAydikaPzj4xOINXMtbUk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/GYyCF/btsFLo1jXPR/VlAydikaPzj4xOINXMtbUk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/GYyCF/btsFLo1jXPR/VlAydikaPzj4xOINXMtbUk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FGYyCF%2FbtsFLo1jXPR%2FVlAydikaPzj4xOINXMtbUk%2Fimg.jpg&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;886&quot; height=&quot;695&quot; data-origin-width=&quot;936&quot; data-origin-height=&quot;695&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-ed512896-c6c2-4025-be4b-c84c7e65bdc3&quot; data-a11y-title=&quot;본문&quot; data-compid=&quot;SE-ed512896-c6c2-4025-be4b-c84c7e65bdc3&quot;&gt;
&lt;div&gt;
&lt;div data-direction=&quot;top&quot; data-compid=&quot;SE-ed512896-c6c2-4025-be4b-c84c7e65bdc3&quot; data-unitid=&quot;&quot;&gt;
&lt;div&gt;
&lt;div id=&quot;SE-9c4eda88-654f-42ef-a4a4-2508d5edd477&quot;&gt;
&lt;p id=&quot;SE-51e1d938-19b9-49f2-9188-e528e857dc10&quot; style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;고급스러운 꽃장식의 홀 사진이에요&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-ecd4815a-6221-45ea-a071-8237c1963b26&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-a523f0e8-de33-4596-93eb-4dfc5c2b4634&quot; data-a11y-title=&quot;사진&quot; data-compid=&quot;SE-a523f0e8-de33-4596-93eb-4dfc5c2b4634&quot;&gt;
&lt;div&gt;
&lt;div data-direction=&quot;top&quot; data-compid=&quot;SE-a523f0e8-de33-4596-93eb-4dfc5c2b4634&quot; data-unitid=&quot;&quot;&gt;
&lt;div&gt;
&lt;div id=&quot;SE-a523f0e8-de33-4596-93eb-4dfc5c2b4634&quot;&gt;
&lt;div data-direction=&quot;top&quot; data-compid=&quot;&quot; data-unitid=&quot;SE-a523f0e8-de33-4596-93eb-4dfc5c2b4634&quot;&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;936&quot; data-origin-height=&quot;702&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/zUGSG/btsFKOziDgx/b4mv2jvRRkAizVqZD80I00/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/zUGSG/btsFKOziDgx/b4mv2jvRRkAizVqZD80I00/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/zUGSG/btsFKOziDgx/b4mv2jvRRkAizVqZD80I00/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FzUGSG%2FbtsFKOziDgx%2Fb4mv2jvRRkAizVqZD80I00%2Fimg.jpg&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;886&quot; height=&quot;702&quot; data-origin-width=&quot;936&quot; data-origin-height=&quot;702&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-34aba556-6f47-4435-9d2d-4949deb54879&quot; data-a11y-title=&quot;사진&quot; data-compid=&quot;SE-34aba556-6f47-4435-9d2d-4949deb54879&quot;&gt;
&lt;div&gt;
&lt;div data-direction=&quot;top&quot; data-compid=&quot;SE-34aba556-6f47-4435-9d2d-4949deb54879&quot; data-unitid=&quot;&quot;&gt;
&lt;div&gt;
&lt;div id=&quot;SE-34aba556-6f47-4435-9d2d-4949deb54879&quot;&gt;
&lt;div data-direction=&quot;top&quot; data-compid=&quot;&quot; data-unitid=&quot;SE-34aba556-6f47-4435-9d2d-4949deb54879&quot;&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;936&quot; data-origin-height=&quot;663&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b2S42S/btsFJ9DL3oK/pp3Y8PjQJxYeK2KfwH8Zt0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b2S42S/btsFJ9DL3oK/pp3Y8PjQJxYeK2KfwH8Zt0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b2S42S/btsFJ9DL3oK/pp3Y8PjQJxYeK2KfwH8Zt0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb2S42S%2FbtsFJ9DL3oK%2Fpp3Y8PjQJxYeK2KfwH8Zt0%2Fimg.jpg&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;886&quot; height=&quot;663&quot; data-origin-width=&quot;936&quot; data-origin-height=&quot;663&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-e6d8a207-625f-4111-ab1c-3aa55d8ba76d&quot; data-a11y-title=&quot;사진&quot; data-compid=&quot;SE-e6d8a207-625f-4111-ab1c-3aa55d8ba76d&quot;&gt;
&lt;div&gt;
&lt;div data-direction=&quot;top&quot; data-compid=&quot;SE-e6d8a207-625f-4111-ab1c-3aa55d8ba76d&quot; data-unitid=&quot;&quot;&gt;
&lt;div&gt;
&lt;div id=&quot;SE-e6d8a207-625f-4111-ab1c-3aa55d8ba76d&quot;&gt;
&lt;div data-direction=&quot;top&quot; data-compid=&quot;&quot; data-unitid=&quot;SE-e6d8a207-625f-4111-ab1c-3aa55d8ba76d&quot;&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;936&quot; data-origin-height=&quot;680&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cnvaM1/btsFKLJmIvU/8764dO7GjdRaY1ilQthmBk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cnvaM1/btsFKLJmIvU/8764dO7GjdRaY1ilQthmBk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cnvaM1/btsFKLJmIvU/8764dO7GjdRaY1ilQthmBk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcnvaM1%2FbtsFKLJmIvU%2F8764dO7GjdRaY1ilQthmBk%2Fimg.jpg&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;886&quot; height=&quot;680&quot; data-origin-width=&quot;936&quot; data-origin-height=&quot;680&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-11e8eedb-3a94-4dd9-a76d-6f3b7743797d&quot; data-a11y-title=&quot;본문&quot; data-compid=&quot;SE-11e8eedb-3a94-4dd9-a76d-6f3b7743797d&quot;&gt;
&lt;div&gt;
&lt;div data-direction=&quot;top&quot; data-compid=&quot;SE-11e8eedb-3a94-4dd9-a76d-6f3b7743797d&quot; data-unitid=&quot;&quot;&gt;
&lt;div&gt;
&lt;div id=&quot;SE-8cee5f06-b03f-4cd1-96e3-b5c8ea7ebd55&quot;&gt;
&lt;p id=&quot;SE-14074fbe-0c8b-4fe7-9de1-27b682dacba7&quot; style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;홀이 엄청 넓은건 아니지만 180명이 앉을 수 있는 의자가 구비되어 있었고&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-2e8ef0b9-a697-4958-86cf-8276b8d224f2&quot; style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;생화장식도 아름답게 꾸며져있어서 심플하니 괜찮았어요&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-749fcfad-3a57-48f6-9cb3-4754897aea56&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-1cad11ed-107e-44b0-af35-d0f88f969c89&quot; data-a11y-title=&quot;사진&quot; data-compid=&quot;SE-1cad11ed-107e-44b0-af35-d0f88f969c89&quot;&gt;
&lt;div&gt;
&lt;div data-direction=&quot;top&quot; data-compid=&quot;SE-1cad11ed-107e-44b0-af35-d0f88f969c89&quot; data-unitid=&quot;&quot;&gt;
&lt;div&gt;
&lt;div id=&quot;SE-1cad11ed-107e-44b0-af35-d0f88f969c89&quot;&gt;
&lt;div data-direction=&quot;top&quot; data-compid=&quot;&quot; data-unitid=&quot;SE-1cad11ed-107e-44b0-af35-d0f88f969c89&quot;&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;936&quot; data-origin-height=&quot;654&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/zHGyz/btsFLVxJiHQ/1MyYYcG1TbGijBoIS37KR1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/zHGyz/btsFLVxJiHQ/1MyYYcG1TbGijBoIS37KR1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/zHGyz/btsFLVxJiHQ/1MyYYcG1TbGijBoIS37KR1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FzHGyz%2FbtsFLVxJiHQ%2F1MyYYcG1TbGijBoIS37KR1%2Fimg.jpg&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;886&quot; height=&quot;654&quot; data-origin-width=&quot;936&quot; data-origin-height=&quot;654&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;SE-8089b810-220f-4b0d-b341-0cf85830054b&quot; data-a11y-title=&quot;본문&quot; data-compid=&quot;SE-8089b810-220f-4b0d-b341-0cf85830054b&quot;&gt;
&lt;div&gt;
&lt;div data-direction=&quot;top&quot; data-compid=&quot;SE-8089b810-220f-4b0d-b341-0cf85830054b&quot; data-unitid=&quot;&quot;&gt;
&lt;div&gt;
&lt;div id=&quot;SE-34d392a8-a00f-4afb-9e0f-5b2bcd83c77d&quot;&gt;
&lt;p id=&quot;SE-d35d8fe5-b03e-448f-876a-9a340e6a7b40&quot; style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;마지막으로 혼주 메이크업실 이랍니다&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-d44b479e-fb95-4eb3-994c-d8e18e20ec20&quot; style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;지하철역과 가깝고 주차공간이 많다는 점&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-cc53221e-87a8-4a8d-ab25-ce05288dd7f8&quot; style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;인테리어가 올드하지 않고 단정하고 깔끔한 느낌이 인상적이었으며&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-52ebc609-1e8f-4599-ab27-2bf367097293&quot; style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;전체적으로 홀도 만족스러워서 계약을 진행하게 되었답니다&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>문화,맛집</category>
      <author>Ninestar</author>
      <guid isPermaLink="true">https://data-science.tistory.com/730</guid>
      <comments>https://data-science.tistory.com/730#entry730comment</comments>
      <pubDate>Thu, 14 Mar 2024 00:02:00 +0900</pubDate>
    </item>
    <item>
      <title>[종로 명가대남 예사랑 한복] 혼주 한복 대여 후기</title>
      <link>https://data-science.tistory.com/729</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1000&quot; data-origin-height=&quot;542&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/5op8Q/btsFGI6t3oy/aW1zW67reyo3HcNj32sPXk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/5op8Q/btsFGI6t3oy/aW1zW67reyo3HcNj32sPXk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/5op8Q/btsFGI6t3oy/aW1zW67reyo3HcNj32sPXk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F5op8Q%2FbtsFGI6t3oy%2FaW1zW67reyo3HcNj32sPXk%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;1000&quot; height=&quot;542&quot; data-origin-width=&quot;1000&quot; data-origin-height=&quot;542&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;주말에 혼주 한복 대여를 위해 종로에 있는 효성주얼리시티건물 명가대남 예사랑 한복집에 다녀왔습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&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-origin-width=&quot;1000&quot; data-origin-height=&quot;755&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bSedxG/btsFF4oD39A/ZtAVEjmCCyUk7TAmczzoUk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bSedxG/btsFF4oD39A/ZtAVEjmCCyUk7TAmczzoUk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bSedxG/btsFF4oD39A/ZtAVEjmCCyUk7TAmczzoUk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbSedxG%2FbtsFF4oD39A%2FZtAVEjmCCyUk7TAmczzoUk%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;1000&quot; height=&quot;755&quot; data-origin-width=&quot;1000&quot; data-origin-height=&quot;755&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;예쁘고 고운 색의 한복들이 시선을 사로잡았고&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;구경하면서도 &quot;너무 예쁘다~&quot;라는 말이 절로 나왔습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&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-origin-width=&quot;1000&quot; data-origin-height=&quot;750&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/GHhTA/btsFGSVJ3RM/CHcPVJRTAcMJmrYpfHKYw1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/GHhTA/btsFGSVJ3RM/CHcPVJRTAcMJmrYpfHKYw1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/GHhTA/btsFGSVJ3RM/CHcPVJRTAcMJmrYpfHKYw1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FGHhTA%2FbtsFGSVJ3RM%2FCHcPVJRTAcMJmrYpfHKYw1%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;1000&quot; height=&quot;750&quot; data-origin-width=&quot;1000&quot; data-origin-height=&quot;750&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;주로 여자쪽은 홍색, 남자쪽은 청색을 많이 하신다고 합니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;화사하면서도 고운 한복의 자태가 아름다웠습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&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-origin-width=&quot;1000&quot; data-origin-height=&quot;708&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bh8RSW/btsFGM8TlJg/NHxEvrEas2B6NnrFcCcxw0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bh8RSW/btsFGM8TlJg/NHxEvrEas2B6NnrFcCcxw0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bh8RSW/btsFGM8TlJg/NHxEvrEas2B6NnrFcCcxw0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbh8RSW%2FbtsFGM8TlJg%2FNHxEvrEas2B6NnrFcCcxw0%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;1000&quot; height=&quot;708&quot; data-origin-width=&quot;1000&quot; data-origin-height=&quot;708&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;나중에 아이 돌잔치 할 때도 한복 맞춰서 입으면 예쁠 것 같습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&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-origin-width=&quot;1000&quot; data-origin-height=&quot;629&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/sLHYR/btsFFNAKsOp/kw3zv7hYK5bKwWuvPOYPF0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/sLHYR/btsFFNAKsOp/kw3zv7hYK5bKwWuvPOYPF0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/sLHYR/btsFFNAKsOp/kw3zv7hYK5bKwWuvPOYPF0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FsLHYR%2FbtsFFNAKsOp%2Fkw3zv7hYK5bKwWuvPOYPF0%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;1000&quot; height=&quot;629&quot; data-origin-width=&quot;1000&quot; data-origin-height=&quot;629&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;치수랑 사이즈 다 맞게 측정해주셨고&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;저고리랑 치마 색도 원하는 디자인으로 선택, 변경이 가능했습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&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-origin-width=&quot;600&quot; data-origin-height=&quot;694&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rPDNx/btsFGSg95ti/7XtkDCQPe0BEa9NMSQYL1k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rPDNx/btsFGSg95ti/7XtkDCQPe0BEa9NMSQYL1k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rPDNx/btsFGSg95ti/7XtkDCQPe0BEa9NMSQYL1k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FrPDNx%2FbtsFGSg95ti%2F7XtkDCQPe0BEa9NMSQYL1k%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;600&quot; height=&quot;694&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;694&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;혼주 한복 대여 시 가방, 노리개, 신발, 자수, 뒤꽂이까지&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;무료로 대여가 가능하다는 점이 좋았습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;3벌을 입어보셨는데 다 너무 잘 어울리시고&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;예븐 한복으로 선택할 수 있었습니다.&lt;/p&gt;</description>
      <category>문화,맛집</category>
      <author>Ninestar</author>
      <guid isPermaLink="true">https://data-science.tistory.com/729</guid>
      <comments>https://data-science.tistory.com/729#entry729comment</comments>
      <pubDate>Mon, 11 Mar 2024 20:23:39 +0900</pubDate>
    </item>
    <item>
      <title>[Rust] mut 변수</title>
      <link>https://data-science.tistory.com/707</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #202124; text-align: left;&quot;&gt;Rust 프로그래밍 언어에서 모든 변수는 &quot;디폴트로&quot; 불변성(Immutability)의 성질을 갖습니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #202124; text-align: left;&quot;&gt;불변성(Immutability)이란&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;변수에 값이 한번 지정된 후에는 그 값을 변경할 수 없는 특성&lt;/b&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;span style=&quot;color: #202124;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;반면에 mut는 변수의 값을 변경할 수 있는 변수입니다.&amp;nbsp;&lt;/span&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;span style=&quot;color: #202124;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;다음은 쓰레드나 프로세스 내부에서 mut변수를 선언하고 값을 변경합니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1707800634561&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;let mut a = json!({...}); 
	a.insert(...);
	...
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #202124;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;하지만 외부에서 접근하여 해당 변수의 값을 변경하고자 한다면 해당 변수값은 쉽게 바뀝니다.&lt;/span&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;span style=&quot;color: #202124;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;이는 Rust 스럽지 않은 코드입니다.&lt;/span&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;span style=&quot;color: #202124;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;이를 해결하기 위해 다음과 같이 immutable 변수로 감싸줍니다&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1707801543945&quot; class=&quot;bash&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;let a = {
	let mut a = json!({...});
	a.insert(...);
    
	a
};&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;</description>
      <category>Rust</category>
      <author>Ninestar</author>
      <guid isPermaLink="true">https://data-science.tistory.com/707</guid>
      <comments>https://data-science.tistory.com/707#entry707comment</comments>
      <pubDate>Thu, 15 Feb 2024 15:24:01 +0900</pubDate>
    </item>
    <item>
      <title>[Arch Linux] 크롬 원격 데스크톱</title>
      <link>https://data-science.tistory.com/706</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;yay에 chrome-remote-desktop이 등록되어있는지 확인합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1707797387053&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;yimstar9@archlinux:~ &amp;raquo; yay -Ss chrome-remote
aur/chrome-remote-desktop-bin 1.0.1-5 (+0 0.00) 
    A simple Desktop application for Chrome Remote Desktop, built using Electron.js
aur/chrome-remote-desktop 118.0.5993.9-1 (+122 0.14) 
    Access other computers or allow another user to access your computer securely over the Internet&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;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_1707797464029&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;yay -S chrome-remote-desktop&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_1707797496734&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;crd --setup&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1707797525559&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;사용자 yimstar9을(를) chrome-remote-desktop 그룹에 등록 중
Checking that working directory and session file are present
That would be /home/yimstar9/.config/chrome-remote-desktop and
/home/yimstar9/.chrome-remote-desktop-session

Now entering the editor to make the appropriate changes to your session file.
Press any key to continue...&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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음은 데스크탑 환경을 선택하고 저장합니다. (본인의 사용하는 DE을 선택해 주석을 해제합니다.)&lt;/p&gt;
&lt;pre id=&quot;code_1707797597403&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# You will have to uncomment one of the following lines for CRD to work
# Remove the # and save the file.
#
export $(dbus-launch)
exec /usr/bin/gnome-session
#exec /usr/bin/gnome-session
#exec classic gnome-session
#exec classic gnome-session&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;다음은 해상도 조절입니다. 기본값 1360x768과 다른 해상도를 사용하려면 새 해상도를 입력하면 됩니다. 그리고 저장후 빠져나옵니다.&lt;/p&gt;
&lt;pre id=&quot;code_1707797650735&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;If you want to set a default size for all clients, please add a
value with format [width]x[height] (e.g 1360x768) in file
/home/yimstar9/.config/chrome-remote-desktop/Size.
Remember that this will affect all clients you use.
If you dont want a default size please leave it blank.
Now entering the editor to make the appropriate changes to
your Size file. Do not enter any comments to this file.
Press any key to continue...&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1707797712227&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;5120x1440&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;pre id=&quot;code_1707797796917&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;This completes the setup.

Please remember that you will need to allow Chrome or Chromium
to act as a server for this to work at all.

To do that, open https://remotedesktop.google.com/ in your chrome or chromium browser
and follow the instructions. Clicking the computer will open
it in the browser window in default resolution.
For a more pleasant chromoting experience, just issue the command: crd --restart

Happy chromoting! :)&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://remotedesktop.google.com/access&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://remotedesktop.google.com/access&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1677&quot; data-origin-height=&quot;898&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/SGtYQ/btsEJa3zJvv/LzsdaVJEHFjspmHyLoIRpK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/SGtYQ/btsEJa3zJvv/LzsdaVJEHFjspmHyLoIRpK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/SGtYQ/btsEJa3zJvv/LzsdaVJEHFjspmHyLoIRpK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FSGtYQ%2FbtsEJa3zJvv%2FLzsdaVJEHFjspmHyLoIRpK%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;1677&quot; height=&quot;898&quot; data-origin-width=&quot;1677&quot; data-origin-height=&quot;898&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;외부에서 동일 구글 아이디로 로그인한 크롬에서 &lt;a href=&quot;https://remotedesktop.google.com/access&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://remotedesktop.google.com/access&lt;/a&gt; 로 접속하고 해당 기기로 접속하면 됩니다.&lt;/p&gt;</description>
      <category>리눅스</category>
      <author>Ninestar</author>
      <guid isPermaLink="true">https://data-science.tistory.com/706</guid>
      <comments>https://data-science.tistory.com/706#entry706comment</comments>
      <pubDate>Tue, 13 Feb 2024 13:20:07 +0900</pubDate>
    </item>
    <item>
      <title>[C] #ifndef~ #endif</title>
      <link>https://data-science.tistory.com/703</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;400&quot; data-origin-height=&quot;308&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dvWO7f/btsEu5vpYN9/CKkce1blPzLGCfgqx6P2e0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dvWO7f/btsEu5vpYN9/CKkce1blPzLGCfgqx6P2e0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dvWO7f/btsEu5vpYN9/CKkce1blPzLGCfgqx6P2e0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdvWO7f%2FbtsEu5vpYN9%2FCKkce1blPzLGCfgqx6P2e0%2Fimg.jpg&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;400&quot; height=&quot;308&quot; data-origin-width=&quot;400&quot; data-origin-height=&quot;308&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;point.h를 pointOperation.h, main.c 두군데서 포함합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;main.c에서는 point.h와 pointOperation.h를 포함합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;그러면 point.h는 main.c에서 두번 포함이 됩니다.&amp;nbsp;&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;중복 포함이 되면 컴파일시 문제가 발생하고 에러메시지를 발생시킵니다.&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;#ifndef ~ #endif&lt;/b&gt;를 사용합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;320&quot; data-origin-height=&quot;235&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cnUoVo/btsEvyxoGLQ/0e7EOmNt56yVXzMAoPLJt0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cnUoVo/btsEvyxoGLQ/0e7EOmNt56yVXzMAoPLJt0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cnUoVo/btsEvyxoGLQ/0e7EOmNt56yVXzMAoPLJt0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcnUoVo%2FbtsEvyxoGLQ%2F0e7EOmNt56yVXzMAoPLJt0%2Fimg.jpg&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;320&quot; height=&quot;235&quot; data-origin-width=&quot;320&quot; data-origin-height=&quot;235&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;#ifndef는 if not defined의 약자로 ~를 정의하지 않았으면 #endif까지 실행해라입니다.&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;모든 헤더 파일에 매크로 #ifndef~ #endif를 사용하는것이 좋습니다.&lt;/p&gt;</description>
      <category>C++</category>
      <author>Ninestar</author>
      <guid isPermaLink="true">https://data-science.tistory.com/703</guid>
      <comments>https://data-science.tistory.com/703#entry703comment</comments>
      <pubDate>Wed, 7 Feb 2024 10:49:12 +0900</pubDate>
    </item>
    <item>
      <title>ARCH Linux VNCserver</title>
      <link>https://data-science.tistory.com/690</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;초기 설정&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;tigervncviewer를 설치합니다.&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;password 설정&lt;/p&gt;
&lt;pre id=&quot;code_1706240961001&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;vncpasswd&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;원하는 암호 입력하고 (6자리)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;~/.vnc/passwd permission을 0600으로 설정합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;background-color: #ffffff; color: #222222; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;서버 키는 방법&lt;/h2&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #222222; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;Running x0vncserver to directly control the local display (직접 서버 키는방법)&lt;/span&gt;&lt;/h3&gt;
&lt;pre class=&quot;elixir&quot; style=&quot;background-color: #ebf1f5; color: #222222; text-align: start;&quot;&gt;&lt;code&gt;$ x0vncserver -rfbauth ~/.vnc/passwd
&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 style=&quot;background-color: #ffffff; color: #222222; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;With xprofile&lt;/span&gt;&lt;/h3&gt;
&lt;pre class=&quot;haml&quot; style=&quot;background-color: #ebf1f5; color: #222222; text-align: start;&quot;&gt;&lt;code&gt;~/.xprofile&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;jboss-cli&quot; style=&quot;background-color: #ebf1f5; color: #222222; text-align: start;&quot;&gt;&lt;code&gt;...
x0vncserver -rfbauth ~/.vnc/passwd &amp;amp;
&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;background-color: #ffffff; color: #222222; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #222222; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;With systemd (system service로 키는 방법)&lt;/span&gt;&lt;/h3&gt;
&lt;h4 style=&quot;background-color: #ffffff; color: #222222; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span&gt;With a system service&lt;/span&gt;&lt;/h4&gt;
&lt;pre class=&quot;awk&quot; style=&quot;background-color: #ebf1f5; color: #222222; text-align: start;&quot;&gt;&lt;code&gt;/etc/systemd/system/x0vncserver.service&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;background-color: #ebf1f5; color: #222222; text-align: start;&quot;&gt;&lt;code&gt;[Unit]
Description=Remote desktop service (VNC) for :0 display
Requires=display-manager.service
After=network-online.target
After=display-manager.service

[Service]
Type=simple
Environment=HOME=/root
Environment=XAUTHORITY=/var/run/lightdm/root/:0
ExecStart=x0vncserver -display :0 -rfbauth ~/.vnc/passwd
Restart=on-failure
RestartSec=500ms

[Install]
WantedBy=multi-user.target&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;background-color: #ffffff; color: #202122; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1706240931565&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;systemctl start x0vncserver.service

systemctl enable x0vncserver.service&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;h2 data-ke-size=&quot;size26&quot;&gt;실행&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;vcnviewer ip주소&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1980&quot; data-origin-height=&quot;1308&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bONuoV/btsD0FpnzEL/VK8d6miwqoEy75JPgafOOK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bONuoV/btsD0FpnzEL/VK8d6miwqoEy75JPgafOOK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bONuoV/btsD0FpnzEL/VK8d6miwqoEy75JPgafOOK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbONuoV%2FbtsD0FpnzEL%2FVK8d6miwqoEy75JPgafOOK%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;1980&quot; height=&quot;1308&quot; data-origin-width=&quot;1980&quot; data-origin-height=&quot;1308&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;</description>
      <category>리눅스</category>
      <author>Ninestar</author>
      <guid isPermaLink="true">https://data-science.tistory.com/690</guid>
      <comments>https://data-science.tistory.com/690#entry690comment</comments>
      <pubDate>Fri, 26 Jan 2024 12:53:04 +0900</pubDate>
    </item>
    <item>
      <title>01월 26일 띠별 오늘의 운세</title>
      <link>https://data-science.tistory.com/689</link>
      <description>&lt;p&gt;&lt;img src=https://dimg.donga.com/wps/NEWS/IMAGE/2024/01/26/123239239.2.jpg&gt;&lt;/p&gt;</description>
      <category>운세</category>
      <category>오늘의 운세</category>
      <author>Ninestar</author>
      <guid isPermaLink="true">https://data-science.tistory.com/689</guid>
      <comments>https://data-science.tistory.com/689#entry689comment</comments>
      <pubDate>Fri, 26 Jan 2024 03:20:13 +0900</pubDate>
    </item>
    <item>
      <title>selenium ChromeDriver PermissionError</title>
      <link>https://data-science.tistory.com/673</link>
      <description>&lt;div style=&quot;background-color: #ffffff; color: #080808;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;잘 되던 셀레니움 크롬드라이버가 갑자기 permission 에러가 발생합니다.&lt;/p&gt;
&lt;pre class=&quot;python&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-language=&quot;python&quot;&gt;&lt;code&gt;chrome_options = Options()
chrome_options.add_argument('headless')
driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()),options=chrome_options)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PermissionError:&amp;nbsp;[Errno&amp;nbsp;13]&amp;nbsp;Permission&amp;nbsp;denied:&amp;nbsp;'C:\\Users\\ninestar\\.wdm\\drivers\\chromedriver\\win64\\120.0.6099.109\\chromedriver-win32\\chromedriver.exe'&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;stackoverflow에서 해결방법을 찾았습니다.&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;버전의&amp;nbsp;셀레늄을&amp;nbsp;사용&amp;nbsp;중인지&amp;nbsp;잘&amp;nbsp;모르겠습니다.&amp;nbsp;최신&amp;nbsp;버전인&amp;nbsp;셀레늄&amp;nbsp;v4.6.0&amp;nbsp;이상을&amp;nbsp;사용&amp;nbsp;중이라면&amp;nbsp;브라우저&amp;nbsp;드라이버를&amp;nbsp;처리하기&amp;nbsp;위해&amp;nbsp;WebDriverManager와&amp;nbsp;같은&amp;nbsp;타사&amp;nbsp;라이브러리를&amp;nbsp;사용할&amp;nbsp;필요가&amp;nbsp;없습니다.&amp;nbsp;다음과&amp;nbsp;같이&amp;nbsp;코드를&amp;nbsp;간소화할&amp;nbsp;수&amp;nbsp;있습니다:&lt;/p&gt;
&lt;pre id=&quot;code_1704850214676&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;chrome_options = Options()
chrome_options.add_argument('headless')
driver = webdriver.Chrome(options=chrome_options)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;webdriver.Chrome함수에 service arg를 빼니 실행이 잘 됩니다.&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://stackoverflow.com/questions/76727774/selenium-webdriver-chrome-115-stopped-working&quot;&gt;https://stackoverflow.com/questions/76727774/selenium-webdriver-chrome-115-stopped-working&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1704850313753&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/khnC7/hyU2tFTN31/RkmhZNGzvBk1mgXuilN4R1/img.png?width=316&amp;amp;height=316&amp;amp;face=0_0_316_316&quot; data-og-url=&quot;https://stackoverflow.com/questions/76727774/selenium-webdriver-chrome-115-stopped-working&quot; data-og-source-url=&quot;https://stackoverflow.com/questions/76727774/selenium-webdriver-chrome-115-stopped-working&quot; data-og-host=&quot;stackoverflow.com&quot; data-og-description=&quot;I have Chrome 115.0.5790.99 installed on Windows, and I use Selenium 4.10.0. In my Python code, I call service = Service(ChromeDriverManager().install()) and it returns the error: ValueError: Ther...&quot; data-og-title=&quot;Selenium WebDriver Chrome 115 stopped working&quot; data-og-type=&quot;website&quot; data-ke-align=&quot;alignCenter&quot; data-ke-type=&quot;opengraph&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://stackoverflow.com/questions/76727774/selenium-webdriver-chrome-115-stopped-working&quot; data-source-url=&quot;https://stackoverflow.com/questions/76727774/selenium-webdriver-chrome-115-stopped-working&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/khnC7/hyU2tFTN31/RkmhZNGzvBk1mgXuilN4R1/img.png?width=316&amp;amp;height=316&amp;amp;face=0_0_316_316');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; style=&quot;color: #000000;&quot; data-ke-size=&quot;size16&quot;&gt;Selenium WebDriver Chrome 115 stopped working&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; style=&quot;color: #909090;&quot; data-ke-size=&quot;size16&quot;&gt;I have Chrome 115.0.5790.99 installed on Windows, and I use Selenium 4.10.0. In my Python code, I call service = Service(ChromeDriverManager().install()) and it returns the error: ValueError: Ther...&lt;/p&gt;
&lt;p class=&quot;og-host&quot; style=&quot;color: #909090;&quot; data-ke-size=&quot;size16&quot;&gt;stackoverflow.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;figure id=&quot;og_1704850313753&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Selenium WebDriver Chrome 115 stopped working&quot; data-og-description=&quot;I have Chrome 115.0.5790.99 installed on Windows, and I use Selenium 4.10.0. In my Python code, I call service = Service(ChromeDriverManager().install()) and it returns the error: ValueError: Ther...&quot; data-og-host=&quot;stackoverflow.com&quot; data-og-source-url=&quot;https://stackoverflow.com/questions/76727774/selenium-webdriver-chrome-115-stopped-working&quot; data-og-url=&quot;https://stackoverflow.com/questions/76727774/selenium-webdriver-chrome-115-stopped-working&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/khnC7/hyU2tFTN31/RkmhZNGzvBk1mgXuilN4R1/img.png?width=316&amp;amp;height=316&amp;amp;face=0_0_316_316&quot;&gt;&lt;/figure&gt;</description>
      <category>파이썬/파이썬 에러</category>
      <author>Ninestar</author>
      <guid isPermaLink="true">https://data-science.tistory.com/673</guid>
      <comments>https://data-science.tistory.com/673#entry673comment</comments>
      <pubDate>Wed, 10 Jan 2024 10:33:06 +0900</pubDate>
    </item>
    <item>
      <title>UnicodeEncodeError: 'locale' codec can't encode character '\uc6d4' in position 2: encoding error</title>
      <link>https://data-science.tistory.com/667</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;파이썬에서 날짜 형식을 지정하는 함수 strftime을 사용하면 아래와 같이 출력이 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre class=&quot;cos&quot; style=&quot;background-color: #f2f2f2; color: #242424; text-align: start;&quot;&gt;&lt;code&gt;print(today.strftime('%Y. %m. %d.'))#실행결과
2019. 03. 06.&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;applescript&quot; style=&quot;background-color: #f2f2f2; color: #242424; text-align: start;&quot;&gt;&lt;code&gt;print(today.strftime('year: %Y month: %m day : %d'))#실행결과
year: 2019 month: 03 day : 06&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;하지만 형식에 한글이 들어가면 아래와 같이 에러가 발생합니다.&lt;/p&gt;
&lt;pre class=&quot;vim&quot; style=&quot;background-color: #f2f2f2; color: #242424; text-align: start;&quot;&gt;&lt;code&gt;$ print(today.strftime('%Y년 %m월 %d일'))#실행결과
Traceback (most recent call last):
  File &quot;c:\Users\jeakwon\Desktop\workspace_docx\docx\take_in_request_form.py&quot;, line 7, in &amp;lt;module&amp;gt;
    print(datetime.datetime.now().date().strftime('%Y년 %m월 %d일'))
UnicodeEncodeError: 'locale' codec can't encode character '\ub144' in position 2: encoding error&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;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li id=&quot;40ab&quot; style=&quot;list-style-type: decimal; color: #242424;&quot; data-selectable-paragraph=&quot;&quot;&gt;strftime 인풋 string을&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;유니코드 인코딩&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;후 디코딩
&lt;pre id=&quot;code_1704674313540&quot; class=&quot;cos&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;python&quot;&gt;&lt;code&gt;&amp;lsquo;%Y년 %m월 %d일&amp;rsquo;.encode(&amp;lsquo;unicode-escape&amp;rsquo;).decode()​&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li style=&quot;list-style-type: decimal; color: #242424;&quot; data-selectable-paragraph=&quot;&quot;&gt;strftime 아웃풋 string 을 인코딩 후&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;&lt;b&gt;유니코드 디코딩&lt;br /&gt;&lt;/b&gt;&lt;/b&gt;
&lt;pre id=&quot;code_1704674347063&quot; class=&quot;erlang&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;python&quot;&gt;&lt;code&gt;strftime( ~ ).encode().decode(&amp;lsquo;unicode-escape&amp;rsquo;))&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre class=&quot;pgsql&quot; style=&quot;background-color: #f2f2f2; color: #242424; text-align: start;&quot;&gt;&lt;code&gt;print(
    today.strftime(
        '%Y년 %m월 %d일'.encode('unicode-escape').decode()
    ).encode().decode('unicode-escape')
)#실행결과
2019년 03월 06일&lt;/code&gt;&lt;/pre&gt;</description>
      <category>파이썬/파이썬 에러</category>
      <author>Ninestar</author>
      <guid isPermaLink="true">https://data-science.tistory.com/667</guid>
      <comments>https://data-science.tistory.com/667#entry667comment</comments>
      <pubDate>Mon, 8 Jan 2024 09:39:31 +0900</pubDate>
    </item>
    <item>
      <title>i9-13900k 언더볼팅 ASRock</title>
      <link>https://data-science.tistory.com/634</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;657&quot; data-origin-height=&quot;500&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bN5Jfx/btsBlaTR45Z/fmKOLRqmF9GtCLItYahh6K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bN5Jfx/btsBlaTR45Z/fmKOLRqmF9GtCLItYahh6K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bN5Jfx/btsBlaTR45Z/fmKOLRqmF9GtCLItYahh6K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbN5Jfx%2FbtsBlaTR45Z%2FfmKOLRqmF9GtCLItYahh6K%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;657&quot; height=&quot;500&quot; data-origin-width=&quot;657&quot; data-origin-height=&quot;500&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;직접 조립을 했는데 바이오스상에서 CPU IDLE 온도가 100도가 찍히는겁니다.&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;인터넷 검색해보니 13900k의 IDLE온도는 30~40도 정도가 정상입니다.&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;그래서 쿨러를 재장착 해보았으나 60도 밑으로 안떨어집니다. CPU를 다시 껴봐도 마찬가지입니다.&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;바이오스에 진입합니다. overclocking탭과 advanced탭에서 아래와 같이 각각 변경하면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;Overclocking&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;- &lt;b&gt;CPU configuration&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Intel Turbo Boost Max Technology 3.0&lt;/b&gt; : Enabled -&amp;gt; Disabled&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Intel Thermal Velocity Boost Voltage Optimizations&lt;/b&gt;&amp;nbsp;: Enabled -&amp;gt; Disabled&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Enhanced Thermal Velocity Boost&lt;/b&gt; : &amp;nbsp;Enabled -&amp;gt; Disabled&lt;/li&gt;
&lt;li&gt;&lt;b&gt;CPU Tj Max&lt;/b&gt; : 115&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Long Duration Power Limit&lt;/b&gt; : 최대치(9999999999)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Long Duration Maintained&lt;/b&gt; : 최대치(224s)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Short Duration Power Limit&lt;/b&gt; : 최대치(9999999999)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;CPU Core Unlimited Current Limit&lt;/b&gt; : Auto -&amp;gt; Enabled&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;b&gt;Voltage Configurations&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Voltage Mode&lt;/b&gt; : OC Mode&lt;/li&gt;
&lt;li&gt;&lt;b&gt;CPU Core/Cache Voltage&lt;/b&gt; : Fixed Mode&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Fixed Voltage(V)&lt;/b&gt; : 1.20~1.35&lt;/li&gt;
&lt;li&gt;&lt;b&gt;CPU Core/Cache Load-Line Calibration&lt;/b&gt; : Level 1&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Advanced&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;-&lt;b&gt; CPU Thermal Throttling&lt;/b&gt; : Enabled -&amp;gt; Disabled&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;Fixed Voltage값을 1.20부터 차례대로 올리면서 테스트를 해봅니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저는 1.20에서 부팅이 안됐고 1.28정도로 놓고 사용중입니다.&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;언더볼팅을 한 뒤 CPU온도는 아래와 같습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;670&quot; data-origin-height=&quot;990&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/APtDP/btsBj8ILXFy/6ZcdHyGamUkbKW7vDDtQy1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/APtDP/btsBj8ILXFy/6ZcdHyGamUkbKW7vDDtQy1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/APtDP/btsBj8ILXFy/6ZcdHyGamUkbKW7vDDtQy1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FAPtDP%2FbtsBj8ILXFy%2F6ZcdHyGamUkbKW7vDDtQy1%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;670&quot; height=&quot;990&quot; data-origin-width=&quot;670&quot; data-origin-height=&quot;990&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;온도가 30~40도로 착해졌습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;성능 테스트는 안해봤기에 얼마나 성능이 떨어졌는지는 모르겠지만 13900k의 성능을 100% 쓸일이 거의 없을 것 같으므로 그냥 사용하려 합니다.&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;b&gt;언더볼팅 만세!&lt;/b&gt;&lt;/p&gt;</description>
      <category>컴퓨터</category>
      <author>Ninestar</author>
      <guid isPermaLink="true">https://data-science.tistory.com/634</guid>
      <comments>https://data-science.tistory.com/634#entry634comment</comments>
      <pubDate>Tue, 5 Dec 2023 09:48:48 +0900</pubDate>
    </item>
    <item>
      <title>[키보드] Monsgeek m3w 풀알루 3모드 텐키리스 키보드</title>
      <link>https://data-science.tistory.com/601</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;18만원주고 산 75% 배열 키보드가 D&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;el, Home, PgUp, PgDn때문에&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;불편해도 꾹 참고 썼지만, 도저히 적응이 되지 않아 텐키리스 키보드를 하나 다시 구매하기로 마음먹었습니다. 하지만 풀알루미늄, 커스텀, 가스켓, 핫스왑, 3모드, 텐키리스 배열 키보드가 없더군요ㅠ&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개월을 존버하던중 monsgeek에서 제가 딱원하던 키보드를 출시한다 해서 바로 사전예약 해버렸습니다. 출시후 배송까지는 약 일주정도 걸렸습니다. 가격도 사전예약 특가로 9만원대에 샀습니다.&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;그동안 써봤던 키보드 종류 약 10가지 중 노뿌 무접점 키보드가 인생 키보드 였는데 오늘부로 바뀌었습니다.&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;유툽 타건음 듣고 크게 기대하지 않았는데 전혀 다른 키감입니다.&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;keyboard.jpg&quot; data-origin-width=&quot;4000&quot; data-origin-height=&quot;2425&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b2oefz/btszLneQ4bw/nnJV1Qz8kmHimML8GtTUyK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b2oefz/btszLneQ4bw/nnJV1Qz8kmHimML8GtTUyK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b2oefz/btszLneQ4bw/nnJV1Qz8kmHimML8GtTUyK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb2oefz%2FbtszLneQ4bw%2FnnJV1Qz8kmHimML8GtTUyK%2Fimg.jpg&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;4000&quot; height=&quot;2425&quot; data-filename=&quot;keyboard.jpg&quot; data-origin-width=&quot;4000&quot; data-origin-height=&quot;2425&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;20231103_161726.jpg&quot; data-origin-width=&quot;4000&quot; data-origin-height=&quot;3000&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cR7pBp/btszLrheMOs/0QezsTMykkoaqtSnLoPgOk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cR7pBp/btszLrheMOs/0QezsTMykkoaqtSnLoPgOk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cR7pBp/btszLrheMOs/0QezsTMykkoaqtSnLoPgOk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcR7pBp%2FbtszLrheMOs%2F0QezsTMykkoaqtSnLoPgOk%2Fimg.jpg&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;4000&quot; height=&quot;3000&quot; data-filename=&quot;20231103_161726.jpg&quot; data-origin-width=&quot;4000&quot; data-origin-height=&quot;3000&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;size18&quot;&gt;&lt;b&gt;무선 연결 방법&lt;/b&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;1963&quot; data-origin-height=&quot;1678&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bKrpOg/btszKJDNAVP/60PvBlaUOVuETGrrJFtzv0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bKrpOg/btszKJDNAVP/60PvBlaUOVuETGrrJFtzv0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bKrpOg/btszKJDNAVP/60PvBlaUOVuETGrrJFtzv0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbKrpOg%2FbtszKJDNAVP%2F60PvBlaUOVuETGrrJFtzv0%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;1963&quot; height=&quot;1678&quot; data-origin-width=&quot;1963&quot; data-origin-height=&quot;1678&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1923&quot; data-origin-height=&quot;313&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bukhra/btszK7dnq7q/KB1zSOo99rmWjIWmkWuoJ1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bukhra/btszK7dnq7q/KB1zSOo99rmWjIWmkWuoJ1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bukhra/btszK7dnq7q/KB1zSOo99rmWjIWmkWuoJ1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbukhra%2FbtszK7dnq7q%2FKB1zSOo99rmWjIWmkWuoJ1%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;1923&quot; height=&quot;313&quot; data-origin-width=&quot;1923&quot; data-origin-height=&quot;313&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;3000&quot; data-origin-height=&quot;4000&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mrRQt/btszJY2zXa3/P5XY1ODxo4gFF6izb58Dik/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mrRQt/btszJY2zXa3/P5XY1ODxo4gFF6izb58Dik/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mrRQt/btszJY2zXa3/P5XY1ODxo4gFF6izb58Dik/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmrRQt%2FbtszJY2zXa3%2FP5XY1ODxo4gFF6izb58Dik%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;3000&quot; height=&quot;4000&quot; data-origin-width=&quot;3000&quot; data-origin-height=&quot;4000&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Caps Lock 밑에 스위치를 Win(아래), Mac(위) 맞게 선택합니다. 기본값은 중앙에 있어서 유선으로 밖에 사용을 못합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;FN+E/R/T/Y로 블루투스123, 2.4G모드를 선택해서 사용하면 됩니다.&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;b&gt;배터리 잔량 확인 방법&lt;/b&gt;은 FN+Space를 누르면 1~0번까지 불이 켜집니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2503&quot; data-origin-height=&quot;973&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/y7F3U/btszJHzDv4y/TkkC92jkTkjpH85YFdDGI1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/y7F3U/btszJHzDv4y/TkkC92jkTkjpH85YFdDGI1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/y7F3U/btszJHzDv4y/TkkC92jkTkjpH85YFdDGI1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fy7F3U%2FbtszJHzDv4y%2FTkkC92jkTkjpH85YFdDGI1%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;2503&quot; height=&quot;973&quot; data-origin-width=&quot;2503&quot; data-origin-height=&quot;973&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;size18&quot;&gt;&lt;b&gt;사용자 매뉴얼&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;4000&quot; data-origin-height=&quot;3000&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/LGanX/btszONdUM0N/akvduzaIqARHG2Kzsfbkyk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/LGanX/btszONdUM0N/akvduzaIqARHG2Kzsfbkyk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/LGanX/btszONdUM0N/akvduzaIqARHG2Kzsfbkyk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FLGanX%2FbtszONdUM0N%2FakvduzaIqARHG2Kzsfbkyk%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;4000&quot; height=&quot;3000&quot; data-origin-width=&quot;4000&quot; data-origin-height=&quot;3000&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;4000&quot; data-origin-height=&quot;3000&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/o4Cn2/btszRTrnrgc/W33FQLOGLvvPM7rCrrdrJk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/o4Cn2/btszRTrnrgc/W33FQLOGLvvPM7rCrrdrJk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/o4Cn2/btszRTrnrgc/W33FQLOGLvvPM7rCrrdrJk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fo4Cn2%2FbtszRTrnrgc%2FW33FQLOGLvvPM7rCrrdrJk%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;4000&quot; height=&quot;3000&quot; data-origin-width=&quot;4000&quot; data-origin-height=&quot;3000&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;4000&quot; data-origin-height=&quot;3000&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bhJX5M/btszK9ChhMW/wIHk9CCH7JHZ55SoaHLsM0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bhJX5M/btszK9ChhMW/wIHk9CCH7JHZ55SoaHLsM0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bhJX5M/btszK9ChhMW/wIHk9CCH7JHZ55SoaHLsM0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbhJX5M%2FbtszK9ChhMW%2FwIHk9CCH7JHZ55SoaHLsM0%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;4000&quot; height=&quot;3000&quot; data-origin-width=&quot;4000&quot; data-origin-height=&quot;3000&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>컴퓨터</category>
      <author>Ninestar</author>
      <guid isPermaLink="true">https://data-science.tistory.com/601</guid>
      <comments>https://data-science.tistory.com/601#entry601comment</comments>
      <pubDate>Mon, 6 Nov 2023 09:50:37 +0900</pubDate>
    </item>
    <item>
      <title>[디즈니+] 멤버십 환불 신청하기</title>
      <link>https://data-science.tistory.com/598</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;디즈니+를 1년 프로모션으로 이용하고 10월30일부로 멤버십이 끝났습니다. 그런데 구독 취소를 신청하지 않아 한달 멤버십(9900원)이 자동결제 되었습니다. 고객센터에 연락하여 환불을 진행했습니다.&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://help.disneyplus.com/ko/&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://help.disneyplus.com/ko/&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1698809593421&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;https://help.disneyplus.com/ko/&quot; data-og-description=&quot;&quot; data-og-host=&quot;help.disneyplus.com&quot; data-og-source-url=&quot;https://help.disneyplus.com/ko/&quot; data-og-url=&quot;https://help.disneyplus.com/ko/&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://help.disneyplus.com/ko/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://help.disneyplus.com/ko/&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;https://help.disneyplus.com/ko/&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;help.disneyplus.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&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;602&quot; data-origin-height=&quot;207&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xWRvb/btszw9v05Rv/TPEMwkRt0ikq4IR62R0L61/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xWRvb/btszw9v05Rv/TPEMwkRt0ikq4IR62R0L61/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xWRvb/btszw9v05Rv/TPEMwkRt0ikq4IR62R0L61/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxWRvb%2Fbtszw9v05Rv%2FTPEMwkRt0ikq4IR62R0L61%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;602&quot; height=&quot;207&quot; data-origin-width=&quot;602&quot; data-origin-height=&quot;207&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1075&quot; data-origin-height=&quot;423&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bPFUqc/btszCheKtth/ofwvteKuky3F0j6C7APTi0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bPFUqc/btszCheKtth/ofwvteKuky3F0j6C7APTi0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bPFUqc/btszCheKtth/ofwvteKuky3F0j6C7APTi0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbPFUqc%2FbtszCheKtth%2FofwvteKuky3F0j6C7APTi0%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;1075&quot; height=&quot;423&quot; data-origin-width=&quot;1075&quot; data-origin-height=&quot;423&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1142&quot; data-origin-height=&quot;636&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/o7PCJ/btszwczMeaB/tGo1YGy3e3XtkKXhJJVRu0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/o7PCJ/btszwczMeaB/tGo1YGy3e3XtkKXhJJVRu0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/o7PCJ/btszwczMeaB/tGo1YGy3e3XtkKXhJJVRu0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fo7PCJ%2FbtszwczMeaB%2FtGo1YGy3e3XtkKXhJJVRu0%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;1142&quot; height=&quot;636&quot; data-origin-width=&quot;1142&quot; data-origin-height=&quot;636&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;479&quot; data-origin-height=&quot;1370&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/duWg3A/btszvGOnRoE/pBCrcQpCAYQrLB1P760zHK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/duWg3A/btszvGOnRoE/pBCrcQpCAYQrLB1P760zHK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/duWg3A/btszvGOnRoE/pBCrcQpCAYQrLB1P760zHK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FduWg3A%2FbtszvGOnRoE%2FpBCrcQpCAYQrLB1P760zHK%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;479&quot; height=&quot;1370&quot; data-origin-width=&quot;479&quot; data-origin-height=&quot;1370&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;446&quot; data-origin-height=&quot;1103&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cUJHLo/btszy5l4zGl/fkaqP3SdkmAcakhqkg8Ig1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cUJHLo/btszy5l4zGl/fkaqP3SdkmAcakhqkg8Ig1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cUJHLo/btszy5l4zGl/fkaqP3SdkmAcakhqkg8Ig1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcUJHLo%2Fbtszy5l4zGl%2FfkaqP3SdkmAcakhqkg8Ig1%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;446&quot; height=&quot;1103&quot; data-origin-width=&quot;446&quot; data-origin-height=&quot;1103&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;자동 결제되고 날짜가 지났어도 시청기록이 없으면 100% 환불해주네요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저 처럼 원치않은 자동결제 되신분들 환불 받으세요.&lt;/p&gt;</description>
      <category>컴퓨터</category>
      <author>Ninestar</author>
      <guid isPermaLink="true">https://data-science.tistory.com/598</guid>
      <comments>https://data-science.tistory.com/598#entry598comment</comments>
      <pubDate>Wed, 1 Nov 2023 12:38:30 +0900</pubDate>
    </item>
    <item>
      <title>[KVM] 여러대의 PC를 하나의 키보드, 마우스로 쓰기, 윈도우-리눅스 지원</title>
      <link>https://data-science.tistory.com/592</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;하드웨어&lt;/b&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;KVM 스위치&amp;nbsp;&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;217&quot; data-origin-height=&quot;250&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/MWav2/btszjCRNi3I/xVUtwdnIgtkEsDSZ1GCL3K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/MWav2/btszjCRNi3I/xVUtwdnIgtkEsDSZ1GCL3K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/MWav2/btszjCRNi3I/xVUtwdnIgtkEsDSZ1GCL3K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FMWav2%2FbtszjCRNi3I%2FxVUtwdnIgtkEsDSZ1GCL3K%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;217&quot; height=&quot;250&quot; data-origin-width=&quot;217&quot; data-origin-height=&quot;250&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;K(키보드), V(비디오 모니터), M(마우스)를 한 셋트로 하여 여러 대의 컴퓨터를 사용할 수 있도록 해주는 장치입니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1144&quot; data-origin-height=&quot;903&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ZnNBa/btszfKcAagG/dxrBJLloTxxQ9aKbrCC7ok/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ZnNBa/btszfKcAagG/dxrBJLloTxxQ9aKbrCC7ok/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ZnNBa/btszfKcAagG/dxrBJLloTxxQ9aKbrCC7ok/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FZnNBa%2FbtszfKcAagG%2FdxrBJLloTxxQ9aKbrCC7ok%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;1144&quot; height=&quot;903&quot; data-origin-width=&quot;1144&quot; data-origin-height=&quot;903&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;물리적으로 버튼을 눌러서 원하는 PC에 순차적으로 연결할 수 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;소프트웨어&lt;/b&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Mouse Without Borders &lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;같은 네트워크에 연결된 윈도우PC들을 하나의 키보드, 마우스로 자유롭게 사용할 수 있는 프로그램입니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;a href=&quot;https://www.microsoft.com/en-us/download/details.aspx?id=35460&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.microsoft.com/en-us/download/details.aspx?id=35460&lt;/a&gt; 여기서 다운로드 받을 수 있습니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;사용하려는 PC에 전부 설치하시고 실행하면 아래와 같은 창이 뜹니다.&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;536&quot; data-origin-height=&quot;412&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Iql6k/btszgAN38NJ/KnTWK9bfd2WvhIPZohjekk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Iql6k/btszgAN38NJ/KnTWK9bfd2WvhIPZohjekk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Iql6k/btszgAN38NJ/KnTWK9bfd2WvhIPZohjekk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FIql6k%2FbtszgAN38NJ%2FKnTWK9bfd2WvhIPZohjekk%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;536&quot; height=&quot;412&quot; data-origin-width=&quot;536&quot; data-origin-height=&quot;412&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;맨처음 설치한 상황이면 NO를 클릭합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;544&quot; data-origin-height=&quot;420&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cEb6b0/btszgmbqKV7/MF2IoqogSZodBE7nkzIsRK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cEb6b0/btszgmbqKV7/MF2IoqogSZodBE7nkzIsRK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cEb6b0/btszgmbqKV7/MF2IoqogSZodBE7nkzIsRK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcEb6b0%2FbtszgmbqKV7%2FMF2IoqogSZodBE7nkzIsRK%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;544&quot; height=&quot;420&quot; data-origin-width=&quot;544&quot; data-origin-height=&quot;420&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;233&quot; data-origin-height=&quot;186&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/KsekQ/btszhozQ0nQ/R0U6wkkw7UCoyURqZdtHnK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/KsekQ/btszhozQ0nQ/R0U6wkkw7UCoyURqZdtHnK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/KsekQ/btszhozQ0nQ/R0U6wkkw7UCoyURqZdtHnK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FKsekQ%2FbtszhozQ0nQ%2FR0U6wkkw7UCoyURqZdtHnK%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;233&quot; height=&quot;186&quot; data-origin-width=&quot;233&quot; data-origin-height=&quot;186&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드들을 다음 설치한 PC에 입력합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;257&quot; data-origin-height=&quot;207&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dtbrOF/btszjEPF0HH/gK3XRo2LlGnJNkDSdOUd4K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dtbrOF/btszjEPF0HH/gK3XRo2LlGnJNkDSdOUd4K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dtbrOF/btszjEPF0HH/gK3XRo2LlGnJNkDSdOUd4K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdtbrOF%2FbtszjEPF0HH%2FgK3XRo2LlGnJNkDSdOUd4K%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;257&quot; height=&quot;207&quot; data-origin-width=&quot;257&quot; data-origin-height=&quot;207&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러면 연결 성공했다는 메시지가 뜨고 설정이 완료됩니다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;듀얼모니터 쓰듯이 화면 가장자리로 커서가 넘어가면 다음 PC로 입력장치 제어가 넘어갑니다. 클립보드 공유와 파일 복사 도 가능합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Barrier&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;제가 이글에서 추천드리고자 하는 프로그램입니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Barrier는 같은 네트워크상에 있는&amp;nbsp;&lt;b&gt;리눅스PC-윈도우PC&lt;/b&gt; 공유가 가능합니다. 설정방법은 Mouse Without Borders와 비슷하고 제어권 넘어가는 형식, 클립보드공유도 똑같습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/debauchee/barrier/releases&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://github.com/debauchee/barrier/releases&lt;/a&gt; 여기서 다운받을 수 있습니다. open source입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;windows에는 exe파일을 받아 설치합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1325&quot; data-origin-height=&quot;360&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/pAYc2/btszf0sX6vU/KSQBh1c0iL7GJCT63zI5T0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/pAYc2/btszf0sX6vU/KSQBh1c0iL7GJCT63zI5T0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/pAYc2/btszf0sX6vU/KSQBh1c0iL7GJCT63zI5T0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FpAYc2%2Fbtszf0sX6vU%2FKSQBh1c0iL7GJCT63zI5T0%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;1325&quot; height=&quot;360&quot; data-origin-width=&quot;1325&quot; data-origin-height=&quot;360&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Linux에서는 터미널 명령어로 직접 받을 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1698393229956&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sudo apt install barrier&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저는 Arch Linux를 쓰기에 아래 명령어로 설치했습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1698393263016&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sudo Pacman -S barrier&lt;/code&gt;&lt;/pre&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;392&quot; data-origin-height=&quot;381&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Iuvtb/btszkmuhs2H/rUHQIBW7YICKeTIKzdf850/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Iuvtb/btszkmuhs2H/rUHQIBW7YICKeTIKzdf850/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Iuvtb/btszkmuhs2H/rUHQIBW7YICKeTIKzdf850/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FIuvtb%2Fbtszkmuhs2H%2FrUHQIBW7YICKeTIKzdf850%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;392&quot; height=&quot;381&quot; data-origin-width=&quot;392&quot; data-origin-height=&quot;381&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Server에 체크하고 서버설정을 누르면 아래와 같은 창이 뜹니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1382&quot; data-origin-height=&quot;553&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cbxBBm/btszf5ARwgF/QxQe8d4RcQ7h4QsivGNCCk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cbxBBm/btszf5ARwgF/QxQe8d4RcQ7h4QsivGNCCk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cbxBBm/btszf5ARwgF/QxQe8d4RcQ7h4QsivGNCCk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcbxBBm%2Fbtszf5ARwgF%2FQxQe8d4RcQ7h4QsivGNCCk%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;1382&quot; height=&quot;553&quot; data-origin-width=&quot;1382&quot; data-origin-height=&quot;553&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Grid를 더블클릭해서 아래와 같이 연결할PC(client)의 화면이름을 넣고 OK버튼을 누릅니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;431&quot; data-origin-height=&quot;467&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bQRjkS/btszjsofq09/cUgSkyL3gQRXFojKciSRf1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bQRjkS/btszjsofq09/cUgSkyL3gQRXFojKciSRf1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bQRjkS/btszjsofq09/cUgSkyL3gQRXFojKciSRf1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbQRjkS%2Fbtszjsofq09%2FcUgSkyL3gQRXFojKciSRf1%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;431&quot; height=&quot;467&quot; data-origin-width=&quot;431&quot; data-origin-height=&quot;467&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&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;1386&quot; data-origin-height=&quot;560&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/RyxF4/btszjsIFTvR/OQLgCHrjQ8Knethhsw0vc0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/RyxF4/btszjsIFTvR/OQLgCHrjQ8Knethhsw0vc0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/RyxF4/btszjsIFTvR/OQLgCHrjQ8Knethhsw0vc0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FRyxF4%2FbtszjsIFTvR%2FOQLgCHrjQ8Knethhsw0vc0%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;1386&quot; height=&quot;560&quot; data-origin-width=&quot;1386&quot; data-origin-height=&quot;560&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;373&quot; data-origin-height=&quot;515&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bEqMDg/btszk2I9ED2/sm3f4k4lbA9bjNZJdu3wWK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bEqMDg/btszk2I9ED2/sm3f4k4lbA9bjNZJdu3wWK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bEqMDg/btszk2I9ED2/sm3f4k4lbA9bjNZJdu3wWK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbEqMDg%2Fbtszk2I9ED2%2Fsm3f4k4lbA9bjNZJdu3wWK%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;373&quot; height=&quot;515&quot; data-origin-width=&quot;373&quot; data-origin-height=&quot;515&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;설정을 마친후 아래와 같이 설정이 됐으면 OK버튼을 누릅니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1383&quot; data-origin-height=&quot;557&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bj7l3X/btszf16sEl8/ejZnvvJOGmkvoH9D3DEG50/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bj7l3X/btszf16sEl8/ejZnvvJOGmkvoH9D3DEG50/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bj7l3X/btszf16sEl8/ejZnvvJOGmkvoH9D3DEG50/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbj7l3X%2Fbtszf16sEl8%2FejZnvvJOGmkvoH9D3DEG50%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;1383&quot; height=&quot;557&quot; data-origin-width=&quot;1383&quot; data-origin-height=&quot;557&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&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;373&quot; data-origin-height=&quot;377&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/uzjz0/btszgAgkip1/kjL2rfkS8hvhigSJlIc8dk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/uzjz0/btszgAgkip1/kjL2rfkS8hvhigSJlIc8dk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/uzjz0/btszgAgkip1/kjL2rfkS8hvhigSJlIc8dk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fuzjz0%2FbtszgAgkip1%2FkjL2rfkS8hvhigSJlIc8dk%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;373&quot; height=&quot;377&quot; data-origin-width=&quot;373&quot; data-origin-height=&quot;377&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;연결하고 싶은 PC에 설치를 하고 실행하면 Client에 체크를 합니다.&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;513&quot; data-origin-height=&quot;567&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cJHK37/btszhvTk9SB/SRHWQkl9duC7CFLuMjpoIK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cJHK37/btszhvTk9SB/SRHWQkl9duC7CFLuMjpoIK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cJHK37/btszhvTk9SB/SRHWQkl9duC7CFLuMjpoIK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcJHK37%2FbtszhvTk9SB%2FSRHWQkl9duC7CFLuMjpoIK%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;513&quot; height=&quot;567&quot; data-origin-width=&quot;513&quot; data-origin-height=&quot;567&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;화면이름을 서버에서 제대로 적었으면 Auto config로도 바로 연결되지만 연결되지 않을경우에는 체크를 풀고 직접 IP주소를 써넣으면 됩니다. 그리고 시작을 누르면 서버와 클라이언트 서로 연결됩니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;797&quot; data-origin-height=&quot;396&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b0wvID/btszgzaCM0n/kDtylwul3uopaMv84rcd71/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b0wvID/btszgzaCM0n/kDtylwul3uopaMv84rcd71/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b0wvID/btszgzaCM0n/kDtylwul3uopaMv84rcd71/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb0wvID%2FbtszgzaCM0n%2FkDtylwul3uopaMv84rcd71%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;797&quot; height=&quot;396&quot; data-origin-width=&quot;797&quot; data-origin-height=&quot;396&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Log창은 F2키를 누르면 볼수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;trouble shooting&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;Log창에 SSL관련 에러가 발생하면서 연결이 안되는 상황&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서버에 SSL인증서가 없기 때문입니다.&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서버가 Windows일 경우 Powershell에 아래 명령어 그대로 입력해주면 됩니다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1698394477732&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$cert = New-SelfSignedCertificate -DnsName Barrier -KeyExportPolicy Exportable

# Public key to Base64
$CertBase64 = [System.Convert]::ToBase64String($cert.RawData, 'InsertLineBreaks')

# Private key to Base64
$RSACng = [System.Security.Cryptography.X509Certificates.RSACertificateExtensions]::GetRSAPrivateKey($cert)
$KeyBytes = $RSACng.Key.Export([System.Security.Cryptography.CngKeyBlobFormat]::Pkcs8PrivateBlob)
$KeyBase64 = [System.Convert]::ToBase64String($KeyBytes, [System.Base64FormattingOptions]::InsertLineBreaks)

# Put it all together
$Pem = @&quot;
-----BEGIN PRIVATE KEY-----
$KeyBase64
-----END PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
$CertBase64
-----END CERTIFICATE-----
&quot;@

# Output to file
$Pem | Out-File -FilePath $env:LOCALAPPDATA\Barrier\SSL\Barrier.pem -Encoding Ascii&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;855&quot; data-origin-height=&quot;372&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/buYZOx/btszkntfyhd/f2T8UIP87cForQsteUQpeK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/buYZOx/btszkntfyhd/f2T8UIP87cForQsteUQpeK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/buYZOx/btszkntfyhd/f2T8UIP87cForQsteUQpeK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbuYZOx%2Fbtszkntfyhd%2Ff2T8UIP87cForQsteUQpeK%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;855&quot; height=&quot;372&quot; data-origin-width=&quot;855&quot; data-origin-height=&quot;372&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서버가 Linux일 경우 터미널에 아래 명령어를 입력하세요.&lt;/p&gt;
&lt;pre id=&quot;code_1698394528250&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;cd ~/.local/share/barrier/SSL
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:4096 -out Barrier.cert
openssl req -key Barrier.cert -x509 -new -out Barrier.pem
cat Barrier.cert &amp;gt;&amp;gt; Barrier.pem&lt;/code&gt;&lt;/pre&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;size18&quot;&gt;&lt;b&gt;리눅스가 클라이언트인 경우 마우스 커서가 안보이는 상황&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;연결은 정상적으로 됐으나 제어권이 넘어가도 리눅스 화면에서 마우스 커서가 보이지 않습니다. 제 아치 리눅스 바탕화면은 GNOME을 이용하는데 GNOME이 마우스를 감지 못하면 기본적으로 터치스크린 모드로 설정되고 커서가 숨겨진다고 합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래 명령어로 실행을 활성화 하세요&lt;/p&gt;
&lt;pre id=&quot;code_1698394699898&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;dconf write /org/gnome/settings-daemon/plugins/cursor/active false&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;b&gt;여전히 마우스 커서가 안보이면 Xorg와 Wayland환경이 혼합되서 발생한 문제일 수 도 있습니다&lt;/b&gt;. GNOME을 Xorg로 시작하면 해결이 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Xorg시작 방법은 사용자 로그인시 비번입력 할때 우측아래에 톱니모양을 누르고 GNOME on Xorg를 선택하시면 됩니다.&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;b&gt;윈도우 서버의 디스플레이 비율이 100%가 아닌경우에도 이 상황이 발생합니다&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/debauchee/barrier/issues/1894&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://github.com/debauchee/barrier/issues/1894&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1699861954770&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;Windows 11 desktop scaling issue &amp;middot; Issue #1894 &amp;middot; debauchee/barrier&quot; data-og-description=&quot;What happened? Mouse gets stuck on an invisible line whose location changes based on scaling, at normal scale it has no issue. This issue was resolved when i uninstalled barrier. Version v2.3.4 Git...&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/debauchee/barrier/issues/1894&quot; data-og-url=&quot;https://github.com/debauchee/barrier/issues/1894&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/MO08P/hyUuZFxOZE/zvjqZtDN00B2t8BKPPhFB1/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/debauchee/barrier/issues/1894&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/debauchee/barrier/issues/1894&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/MO08P/hyUuZFxOZE/zvjqZtDN00B2t8BKPPhFB1/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;Windows 11 desktop scaling issue &amp;middot; Issue #1894 &amp;middot; debauchee/barrier&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;What happened? Mouse gets stuck on an invisible line whose location changes based on scaling, at normal scale it has no issue. This issue was resolved when i uninstalled barrier. Version v2.3.4 Git...&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;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #000000;&quot;&gt;위 글을 참조하면 디스플레이 비율을 100%로 변경하거나 2.3.4 버전을 쓰는게 해결방법 같습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #ee2323;&quot;&gt;&lt;b&gt;더이상 여러대의 컴퓨터를 사용할때 여러대의 키보드, 마우스를 사용하지 마세요.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;</description>
      <category>컴퓨터</category>
      <category>Barrier</category>
      <category>kvm</category>
      <category>mouse without borders</category>
      <category>공유</category>
      <category>공유프로그램</category>
      <category>키마 공유</category>
      <category>키보드마우스 공유</category>
      <author>Ninestar</author>
      <guid isPermaLink="true">https://data-science.tistory.com/592</guid>
      <comments>https://data-science.tistory.com/592#entry592comment</comments>
      <pubDate>Tue, 31 Oct 2023 09:46:53 +0900</pubDate>
    </item>
    <item>
      <title>[Arch Linux] ibus 1.5.29 build &amp;amp; install</title>
      <link>https://data-science.tistory.com/582</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;arch linux에서 wine 카카오톡, pycharm을 쓰다보면 갑자기 한글이 안써지는 경우가 생깁니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시스템 로그를 보니 ibus-x11이 코어 덤프가 발생합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1697593768638&quot; class=&quot;angelscript&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;9월 20 10:33:53 emstone 카카오톡.desktop[9502]: 0178:fixme:win:NtUserFlashWindowEx 0x436e480 - semi-stub
 9월 20 10:33:53 emstone 카카오톡.desktop[9502]: 0178:fixme:wincodecs:jpeg_decoder_get_metadata_blocks stub
 9월 20 10:34:03 emstone 카카오톡.desktop[9502]: 0178:fixme:wincodecs:jpeg_decoder_get_metadata_blocks stub
 9월 20 10:34:10 emstone 카카오톡.desktop[9502]: 0178:fixme:win:NtUserFlashWindowEx 0x436f5b0 - semi-stub
 9월 20 10:34:23 emstone NetworkManager[582]: &amp;lt;info&amp;gt;  [1695173663.9792] dhcp4 (enp0s20f0u2): state changed new lease, address=192.168.91.94
 9월 20 10:34:23 emstone dbus-daemon[571]: [system] Activating via systemd: service name='org.freedesktop.nm_dispatcher' unit='dbus-org.freedesktop.nm-dispatcher.service' requested by ':1.5' (uid=0 pid=582 comm=&quot;/usr/bin/NetworkManager --no-daemon&quot;)
 9월 20 10:34:24 emstone systemd[1]: Starting Network Manager Script Dispatcher Service...
 9월 20 10:34:24 emstone dbus-daemon[571]: [system] Successfully activated service 'org.freedesktop.nm_dispatcher'
 9월 20 10:34:24 emstone systemd[1]: Started Network Manager Script Dispatcher Service.
 9월 20 10:34:34 emstone systemd[1]: NetworkManager-dispatcher.service: Deactivated successfully.
 9월 20 10:35:06 emstone gsd-xsettings[2243]: double free or corruption (fasttop)
 9월 20 10:35:06 emstone systemd[1]: Started Process Core Dump (PID 125485/UID 0).
 9월 20 10:35:06 emstone systemd-coredump[125486]: [ ] Process 2243 (ibus-x11) of user 1000 dumped core.
                                                    
                                                    Stack trace of thread 2243:
                                                    #0  0x00007fc681e8e83c n/a (libc.so.6 + 0x8e83c)
                                                    #1  0x00007fc681e3e668 raise (libc.so.6 + 0x3e668)
                                                    #2  0x00007fc681e264b8 abort (libc.so.6 + 0x264b8)
                                                    #3  0x00007fc681e27390 n/a (libc.so.6 + 0x27390)
                                                    #4  0x00007fc681e987b7 n/a (libc.so.6 + 0x987b7)
                                                    #5  0x00007fc681e9aa1a n/a (libc.so.6 + 0x9aa1a)
                                                    #6  0x00007fc681e9d353 free (libc.so.6 + 0x9d353)
                                                    #7  0x00007fc6820bab9e XFree (libX11.so.6 + 0x42b9e)
                                                    #8  0x000055dd09f21041 n/a (ibus-x11 + 0xe041)
                                                    #9  0x000055dd09f22eca n/a (ibus-x11 + 0xfeca)
                                                    #10 0x00007fc68239284b n/a (libgdk-3.so.0 + 0x8b84b)
                                                    #11 0x00007fc682337fb9 gdk_display_get_event (libgdk-3.so.0 + 0x30fb9)
                                                    #12 0x00007fc682392d28 n/a (libgdk-3.so.0 + 0x8bd28)
                                                    #13 0x00007fc682214f19 n/a (libglib-2.0.so.0 + 0x59f19)
                                                    #14 0x00007fc6822732b7 n/a (libglib-2.0.so.0 + 0xb82b7)
                                                    #15 0x00007fc682215b47 g_main_loop_run (libglib-2.0.so.0 + 0x5ab47)
                                                    #16 0x00007fc682cac032 ibus_main (libibus-1.0.so.5 + 0x42032)
                                                    #17 0x000055dd09f16505 n/a (ibus-x11 + 0x3505)
                                                    #18 0x00007fc681e27cd0 n/a (libc.so.6 + 0x27cd0)
                                                    #19 0x00007fc681e27d8a __libc_start_main (libc.so.6 + 0x27d8a)
                                                    #20 0x000055dd09f166f5 n/a (ibus-x11 + 0x36f5)
                                                    
                                                    Stack trace of thread 2246:
                                                    #0  0x00007fc681f0ed6d syscall (libc.so.6 + 0x10ed6d)
                                                    #1  0x00007fc68226e247 g_cond_wait (libglib-2.0.so.0 + 0xb3247)
                                                    #2  0x00007fc6821e01b4 n/a (libglib-2.0.so.0 + 0x251b4)
                                                    #3  0x00007fc682248a2e n/a (libglib-2.0.so.0 + 0x8da2e)
                                                    #4  0x00007fc6822469a5 n/a (libglib-2.0.so.0 + 0x8b9a5)
                                                    #5  0x00007fc681e8c9eb n/a (libc.so.6 + 0x8c9eb)
                                                    #6  0x00007fc681f10dfc n/a (libc.so.6 + 0x110dfc)
                                                    
                                                    Stack trace of thread 2247:
                                                    #0  0x00007fc681f0359f __poll (libc.so.6 + 0x10359f)
                                                    #1  0x00007fc682273206 n/a (libglib-2.0.so.0 + 0xb8206)
                                                    #2  0x00007fc682213112 g_main_context_iteration (libglib-2.0.so.0 + 0x58112)
                                                    #3  0x00007fc682213162 n/a (libglib-2.0.so.0 + 0x58162)
                                                    #4  0x00007fc6822469a5 n/a (libglib-2.0.so.0 + 0x8b9a5)
                                                    #5  0x00007fc681e8c9eb n/a (libc.so.6 + 0x8c9eb)
                                                    #6  0x00007fc681f10dfc n/a (libc.so.6 + 0x110dfc)
                                                    
                                                    Stack trace of thread 2248:
                                                    #0  0x00007fc681f0359f __poll (libc.so.6 + 0x10359f)
                                                    #1  0x00007fc682273206 n/a (libglib-2.0.so.0 + 0xb8206)
                                                    #2  0x00007fc682215b47 g_main_loop_run (libglib-2.0.so.0 + 0x5ab47)
                                                    #3  0x00007fc681d390bc n/a (libgio-2.0.so.0 + 0x1120bc)
                                                    #4  0x00007fc6822469a5 n/a (libglib-2.0.so.0 + 0x8b9a5)
                                                    #5  0x00007fc681e8c9eb n/a (libc.so.6 + 0x8c9eb)
                                                    #6  0x00007fc681f10dfc n/a (libc.so.6 + 0x110dfc)
                                                    ELF object binary architecture: AMD x86-64
 9월 20 10:35:06 emstone systemd[1]: systemd-coredump@1-125485-0.service: Deactivated successfully.
 9월 20 10:35:23 emstone gnome-shell[1396]: Could not create transient scope for PID 125527: GDBus.Error:org.freedesktop.DBus.Error.InvalidArgs: Invalid unit name or type.
 9월 20 10:35:24 emstone 카카오톡.desktop[125527]: 0558:fixme:exec:SHELL_execute flags ignored: 0x00004000
 9월 20 10:35:24 emstone 카카오톡.desktop[125539]: 056c:err:winediag:process_attach Failed to load libgnutls, secure connections will not be available.
 9월 20 10:35:24 emstone 카카오톡.desktop[125539]: 056c:err:secur32:SECUR32_initSchannelSP no schannel support, expect problems
 9월 20 10:35:24 emstone 카카오톡.desktop[125539]: 056c:err:winediag:ntlm_check_version ntlm_auth was not found. Make sure that ntlm_auth &amp;gt;= 3.0.25 is in your path. Usually, you can find it in the winbind package of your distribution.
 9월 20 10:35:24 emstone 카카오톡.desktop[125539]: 056c:err:ntlm:ntlm_LsaApInitializePackage no NTLM support, expect problems
 9월 20 10:35:24 emstone 카카오톡.desktop[125539]: 056c:err:winediag:gnutls_process_attach failed to load libgnutls, no support for encryption
 9월 20 10:35:24 emstone 카카오톡.desktop[125539]: 056c:fixme:toolhelp:CreateToolhelp32Snapshot Unimplemented: heap list snapshot
 9월 20 10:35:24 emstone 카카오톡.desktop[125539]: 056c:fixme:toolhelp:CreateToolhelp32Snapshot Unimplemented: heap list snapshot
 9월 20 10:35:25 emstone 카카오톡.desktop[125539]: 056c:err:winediag:process_attach failed to load libgnutls, no support for pfx import/export
 9월 20 10:35:25 emstone 카카오톡.desktop[125539]: 056c:fixme:toolhelp:CreateToolhelp32Snapshot Unimplemented: heap list snapshot
 9월 20 10:35:26 emstone 카카오톡.desktop[125539]: 056c:fixme:nls:RtlGetThreadPreferredUILanguages 00000038, 0436FB24, 0436FB34 0436FB28
 9월 20 10:35:26 emstone 카카오톡.desktop[125539]: 056c:fixme:nls:get_dummy_preferred_ui_language (0x38 0x412 0436FB24 0436FB34 0436FB28) returning a dummy value (current locale)
 9월 20 10:35:26 emstone 카카오톡.desktop[125539]: 056c:fixme:process:RegisterApplicationRestart (L&quot; /RestartByRestartManager:104AC301-3B21-4bc1-910B-7EE1C5A6BA9D&quot;,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;구글링해보니 archwiki, ibus 이슈에도 비슷한 문제가 있었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://bbs.archlinux.org/viewtopic.php?id=287701&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://bbs.archlinux.org/viewtopic.php?id=287701&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1697593911034&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;ibus-x11 dumped core, causing emacs to crash. / Newbie Corner / Arch Linux Forums&quot; data-og-description=&quot;My emacs has been freezing and crashing randomly. I haven't been able to reliably reproduce the problem, but the last two times it's happened, I found the following log message. This makes me think the issue is with X, though as far as I've seen, no progra&quot; data-og-host=&quot;bbs.archlinux.org&quot; data-og-source-url=&quot;https://bbs.archlinux.org/viewtopic.php?id=287701&quot; data-og-url=&quot;https://bbs.archlinux.org/viewtopic.php?id=287701&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://bbs.archlinux.org/viewtopic.php?id=287701&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://bbs.archlinux.org/viewtopic.php?id=287701&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;ibus-x11 dumped core, causing emacs to crash. / Newbie Corner / Arch Linux Forums&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;My emacs has been freezing and crashing randomly. I haven't been able to reliably reproduce the problem, but the last two times it's happened, I found the following log message. This makes me think the issue is with X, though as far as I've seen, no progra&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;bbs.archlinux.org&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;&lt;a href=&quot;https://github.com/ibus/ibus/issues/2480&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://github.com/ibus/ibus/issues/2480&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1697594376078&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;(Regression) TrackMania Nations Forever under Wine does not always register key releases under IBus 1.5.28 &amp;middot; Issue #2480 &amp;middot; ibu&quot; data-og-description=&quot;Which distribution and version?: Arch Linux (updated as of 2023-02-25) Which desktop environment and version?: Sway 1.8.1 Which session type?: Wayland Which application and version?: Wine 8.2, Trac...&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/ibus/ibus/issues/2480&quot; data-og-url=&quot;https://github.com/ibus/ibus/issues/2480&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/93Kva/hyUgS6CAwy/EcXscqQa8hwr6mxMQxTKSk/img.png?width=1200&amp;amp;height=600&amp;amp;face=982_131_1042_196&quot;&gt;&lt;a href=&quot;https://github.com/ibus/ibus/issues/2480&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/ibus/ibus/issues/2480&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/93Kva/hyUgS6CAwy/EcXscqQa8hwr6mxMQxTKSk/img.png?width=1200&amp;amp;height=600&amp;amp;face=982_131_1042_196');&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;(Regression) TrackMania Nations Forever under Wine does not always register key releases under IBus 1.5.28 &amp;middot; Issue #2480 &amp;middot; ibu&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Which distribution and version?: Arch Linux (updated as of 2023-02-25) Which desktop environment and version?: Sway 1.8.1 Which session type?: Wayland Which application and version?: Wine 8.2, Trac...&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;ibus 1.5.29 버전에서 해결됐다고 하니 1.5.29버전을 설치합니다.&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/ibus/ibus/releases&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://github.com/ibus/ibus/releases&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;소스코드를 다운받고 압축을 풉니다.&lt;/p&gt;
&lt;pre id=&quot;code_1697594812915&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt; $ zcat ibus-1.5.29-rc1.tar.gz | tar xfv -
 $ cd ibus-1.5.29-rc1&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또는 github에서 소스를 가져올수도 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1697594861754&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/ibus/ibus.git ibus
 $ cd ibus&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_1697594897436&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt; $ ./autogen.sh --prefix='/usr' --sysconfdir='/etc' --libdir='/usr/lib' --enable-gtk-doc
 $ make
 $ sudo make install&lt;/code&gt;&lt;/pre&gt;</description>
      <category>리눅스</category>
      <author>Ninestar</author>
      <guid isPermaLink="true">https://data-science.tistory.com/582</guid>
      <comments>https://data-science.tistory.com/582#entry582comment</comments>
      <pubDate>Wed, 18 Oct 2023 11:19:41 +0900</pubDate>
    </item>
    <item>
      <title>삼성페이로 주민등본 떼기(전자증명서 서비스)</title>
      <link>https://data-science.tistory.com/568</link>
      <description>&lt;p data-ke-size=&quot;size16&quot; style=&quot;text-align: left;&quot;&gt;&lt;b&gt;주민등록등본 등 정부24 전자증명서 11종 발급 가능&lt;br&gt;최초 발급 후 90일 간 보관…삼성페이로 간편 공유도&lt;/b&gt;&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;647&quot; data-origin-height=&quot;719&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bysQSN/btsw8jGmjdz/7AKKT2vpKUnkK6fKlJPc00/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bysQSN/btsw8jGmjdz/7AKKT2vpKUnkK6fKlJPc00/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bysQSN/btsw8jGmjdz/7AKKT2vpKUnkK6fKlJPc00/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbysQSN%2Fbtsw8jGmjdz%2F7AKKT2vpKUnkK6fKlJPc00%2Fimg.jpg&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;647&quot; height=&quot;719&quot; data-origin-width=&quot;647&quot; data-origin-height=&quot;719&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot; style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;color: #303038;&quot;&gt;오늘부터 모바일 월렛(지갑) 서비스 '삼성페이'를 통해 정부가 발행하는 전자증명서의 서비스 지원을 시작한다고 합니다.&amp;nbsp;&lt;/span&gt;&lt;br&gt;&amp;nbsp;&lt;br&gt;&lt;span style=&quot;color: #303038;&quot;&gt;삼성페이 전자증명서 서비스는 정부24에서 발급하는 증명서들을 삼성페이에서 발급, 조회, 공유, 제출 등을 할 수 있는 기능입니다. 발급 가능한 전자증명서는 주민등록표등본(초본), 건강보험료 납부확인서, 예방접종증명서, 운전경력증명서 등 총 11종 입니다. 전자 증명서는 최초발급일 후 90일간 유효합니다.&lt;/span&gt;&lt;br&gt;&amp;nbsp;&lt;br&gt;&lt;span style=&quot;color: #303038;&quot;&gt;삼성페이 전자증명서 서비스를 통해 발급된 전자증명서는 정부24를 통해 제공되는 전자증명서와 동일한 법적 효력을 가지며, 사용처 또한 동일합니다&lt;/span&gt;&lt;br&gt;&amp;nbsp;&lt;br&gt;&lt;span style=&quot;color: #303038;&quot;&gt;앞으로 삼성페이 사용자는 정부가 발행하는 '주민등록표등본' 등 전자증명서를 보다 빠르고 간편하게 발급 받을 수 있게 됩니다.&lt;/span&gt;&lt;br&gt;&amp;nbsp;&lt;br&gt;&lt;span style=&quot;color: #303038;&quot;&gt;최근에 알뜰교통카드도 삼성페이에 등록가능하게 바꼈는데 삼성페이가 점점 편해지고 있습니다. 지갑, 카드 안들고 다닌지 꽤 됐네요. 이젠 삼성페이가 없으면 불편해서 못살 것 같네요.&lt;/span&gt;&lt;/p&gt;</description>
      <category>이슈</category>
      <author>Ninestar</author>
      <guid isPermaLink="true">https://data-science.tistory.com/568</guid>
      <comments>https://data-science.tistory.com/568#entry568comment</comments>
      <pubDate>Thu, 5 Oct 2023 10:16:45 +0900</pubDate>
    </item>
    <item>
      <title>지하철 냉난방 민원신고 방법</title>
      <link>https://data-science.tistory.com/561</link>
      <description>&lt;p data-ke-size=&quot;size16&quot; style=&quot;text-align: left;&quot;&gt;출퇴근하면서 약냉방,약난방칸을 피해도 덥거나 추웠던적이 많았는데요.&amp;nbsp;&amp;nbsp;그럴때마다 쉽게 해결하는 방법이 있습니다.&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;886&quot; data-origin-height=&quot;390&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bMjzY9/btsv8eAd2M3/KtOhCbB6ttODoWyMoOwKu0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bMjzY9/btsv8eAd2M3/KtOhCbB6ttODoWyMoOwKu0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bMjzY9/btsv8eAd2M3/KtOhCbB6ttODoWyMoOwKu0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbMjzY9%2Fbtsv8eAd2M3%2FKtOhCbB6ttODoWyMoOwKu0%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;886&quot; height=&quot;390&quot; data-origin-width=&quot;886&quot; data-origin-height=&quot;390&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot; style=&quot;text-align: left;&quot;&gt;&lt;br&gt;서울 지하철 호선별 약냉방칸은 다음과 같습니다&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1650&quot; data-origin-height=&quot;804&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/J6Yc7/btswasR7Uwt/HVKQlrDkZkEsl7p5N8GQcK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/J6Yc7/btswasR7Uwt/HVKQlrDkZkEsl7p5N8GQcK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/J6Yc7/btswasR7Uwt/HVKQlrDkZkEsl7p5N8GQcK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FJ6Yc7%2FbtswasR7Uwt%2FHVKQlrDkZkEsl7p5N8GQcK%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;1650&quot; height=&quot;804&quot; data-origin-width=&quot;1650&quot; data-origin-height=&quot;804&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot; style=&quot;text-align: left;&quot;&gt;2호선은 혼잡하기 때문에 약냉방칸을 운영하지 않는다고 합니다.&lt;br&gt;&lt;br&gt;&lt;br&gt;약난방칸은 다음과 같습니다&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1058&quot; data-origin-height=&quot;346&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xPea3/btswbF4MWdL/RiZeoweVbkCxYGobKX2u40/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xPea3/btswbF4MWdL/RiZeoweVbkCxYGobKX2u40/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xPea3/btswbF4MWdL/RiZeoweVbkCxYGobKX2u40/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxPea3%2FbtswbF4MWdL%2FRiZeoweVbkCxYGobKX2u40%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;1058&quot; height=&quot;346&quot; data-origin-width=&quot;1058&quot; data-origin-height=&quot;346&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot; style=&quot;text-align: left;&quot;&gt;&lt;br&gt;&lt;/p&gt;&lt;h2 style=&quot;text-align: left;&quot; data-ke-size=&quot;size26&quot;&gt;어플을 이용한 지하철 민원 신고방법&lt;/h2&gt;&lt;p data-ke-size=&quot;size16&quot; style=&quot;text-align: left;&quot;&gt;또타지하철 앱을 이용하면 쉽게 민원을 넣을수 있습니다.&lt;br&gt;플레이스토어나 앱스토어에서 또타지하철앱을 설치하시고 실행하시면 아래와 같은 화면을 볼 수 있습니다.&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;2933&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bk9gm9/btsv7i35hnJ/9MSH0iXzGNAcCtuKzuTWqK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bk9gm9/btsv7i35hnJ/9MSH0iXzGNAcCtuKzuTWqK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bk9gm9/btsv7i35hnJ/9MSH0iXzGNAcCtuKzuTWqK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbk9gm9%2Fbtsv7i35hnJ%2F9MSH0iXzGNAcCtuKzuTWqK%2Fimg.jpg&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;1440&quot; height=&quot;2933&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;2933&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot; style=&quot;text-align: left;&quot;&gt;위 화면에서 민원신고를 누릅니다.&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;3088&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xabNv/btswkmKqKjT/tdgy5ypKGk2vkbzJGaVpVK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xabNv/btswkmKqKjT/tdgy5ypKGk2vkbzJGaVpVK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xabNv/btswkmKqKjT/tdgy5ypKGk2vkbzJGaVpVK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxabNv%2FbtswkmKqKjT%2Ftdgy5ypKGk2vkbzJGaVpVK%2Fimg.jpg&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;1440&quot; height=&quot;3088&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;3088&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot; style=&quot;text-align: left;&quot;&gt;민원 종류는 온도조절 입니다&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;3088&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/HChON/btsv7lmcWij/yYIX7YWSCRoWLhJV6vKKC0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/HChON/btsv7lmcWij/yYIX7YWSCRoWLhJV6vKKC0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/HChON/btsv7lmcWij/yYIX7YWSCRoWLhJV6vKKC0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FHChON%2Fbtsv7lmcWij%2FyYIX7YWSCRoWLhJV6vKKC0%2Fimg.jpg&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;1440&quot; height=&quot;3088&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;3088&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot; style=&quot;text-align: left;&quot;&gt; 현재 탑승하고있는 지하철정보가 자동으로 잡히고&lt;br&gt;덥가,춥다를 선택해 민원신고를 하시면 됩니다.&lt;br&gt;&lt;br&gt;&lt;br&gt;내민원메뉴에서는 신고한 민원목록을 볼 수 있습니다.&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;3088&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dA5fun/btswbgjKyqe/4iVV3exV6lrjHDQQ66pY8K/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dA5fun/btswbgjKyqe/4iVV3exV6lrjHDQQ66pY8K/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dA5fun/btswbgjKyqe/4iVV3exV6lrjHDQQ66pY8K/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdA5fun%2FbtswbgjKyqe%2F4iVV3exV6lrjHDQQ66pY8K%2Fimg.jpg&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;1440&quot; height=&quot;3088&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;3088&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot; style=&quot;text-align: left;&quot;&gt;&lt;/p&gt;</description>
      <category>이슈</category>
      <author>Ninestar</author>
      <guid isPermaLink="true">https://data-science.tistory.com/561</guid>
      <comments>https://data-science.tistory.com/561#entry561comment</comments>
      <pubDate>Fri, 29 Sep 2023 09:17:47 +0900</pubDate>
    </item>
    <item>
      <title>git@github.com: Permission denied (publickey) 에러</title>
      <link>https://data-science.tistory.com/543</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #242424; text-align: start;&quot;&gt;git push 또는 git pull 시 에러가 발생합니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1694613904681&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;git@github.com: Permission denied (publickey).
fatal: Could not read from remote repository.
Please make sure you have the correct access rights
and the repository exists.&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;github에 연결된 ssh key가 설정되어 있지 않기 때문입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해결방법은 ssk key를 만들고 gihub의 본인 계정에 등록해주면 됩니다.&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. ssh key를 생성합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1694614009982&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;ssh-keygen -t rsa -C &quot;본인 github 로그인 계정 이메일&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ssh key를 생성하면 어디에 저장할건지 패스워드를 지정할건지 물어보는데 엔터를 치면 기본값으로 설정합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #242424; text-align: start;&quot;&gt;이제 ~/.ssh/id_rsa.pub에 키가 생성되었습니다.&lt;/span&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;background-color: #ffffff; color: #242424; text-align: start;&quot;&gt;2. 생성된 key를 github에 등록합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #242424;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;cat ~&lt;span style=&quot;background-color: #ffffff; color: #242424; text-align: start;&quot;&gt;/.ssh/id_rsa.pub를 입력하고 나온 내용을 복사해서&lt;/span&gt;&lt;/span&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;span style=&quot;color: #242424;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #242424; text-align: start;&quot;&gt;github계정 settings- SSH and GPG keys에서 new ssh key을 누릅니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #242424;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #242424; text-align: start;&quot;&gt;제목은 원하는거 아무거나 입력하시고&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #242424;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #242424; text-align: start;&quot;&gt;key부분에 복사한 값을 붙여넣습니다. &lt;/span&gt;&lt;/span&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;span style=&quot;color: #242424;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #242424; text-align: start;&quot;&gt;3. 이제 git pull이나 git push를 하면 에러없이 진행되는 것을 볼 수 있습니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;</description>
      <category>컴퓨터</category>
      <author>Ninestar</author>
      <guid isPermaLink="true">https://data-science.tistory.com/543</guid>
      <comments>https://data-science.tistory.com/543#entry543comment</comments>
      <pubDate>Thu, 14 Sep 2023 10:10:04 +0900</pubDate>
    </item>
    <item>
      <title>학습 데이터 형식이 다른 라벨들 원하는 형식으로 변경하기</title>
      <link>https://data-science.tistory.com/542</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;YOLOv8모델을 학습시키기 위해 다양한 데이터셋을 찾았으나 형식이 전부 달라 사용할 수 없거나 강제로 변환을 했었습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;폴더 구조를 변경하고, Json을 txt파일 형식으로 강제로 변경합니다&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;Json형식의 파일 구조는 아래와 같습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1694585833801&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;`── data
    │── crowdpose
        │-- annotations
        │   │-- mmpose_crowdpose_train.json
        │   │-- mmpose_crowdpose_val.json
        │   │-- mmpose_crowdpose_trainval.json
        │   │-- mmpose_crowdpose_test.json
        │   │-- det_for_crowd_test_0.1_0.5.json
        │-- images
            │-- 100000.jpg
            │-- 100001.jpg
            │-- 100002.jpg
            │-- ...&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;YOLO모델의 txt형식의 파일 구조는 아래와 같습니다&lt;/p&gt;
&lt;pre id=&quot;code_1694585839837&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Dataset
 ├── images
 │     ├── train
 │     │    └── 00036.jpg
 │     │    └── 00049.jpg
 │     │    └──....
 │     └── val
 │          └── 00091.jpg
 │          └── 00095.jpg
 │          └──....
 └── label
        ├── train
        │   └── 00036.txt
        │   └── 00049.txt
        │   └──....
        └── val
            └── 00091.txt
            └── 00095.txt
            └──....&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;Json내용은 아래와 같습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1694585473111&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;{
&amp;ldquo;info&amp;rdquo;:{ 
      &amp;ldquo;description&amp;rdquo;: &amp;ldquo;coco .. &amp;rdquo;,
      &amp;rdquo;url&amp;rdquo;:&amp;rdquo;http://..&amp;rdquo;,
      &amp;rdquo;version&amp;rdquo;:&amp;rdquo;1.0&amp;rdquo;,
      &amp;rsquo;year&amp;rdquo;:2017,
      &amp;rdquo;contributor&amp;rdquo;:&amp;rdquo;coco..&amp;rdquo;,
      date_created&amp;rdquo;:&amp;rdquo;2017/09/01&amp;rdquo;
      },
&amp;ldquo;license&amp;ldquo;:[{
      &amp;ldquo;url&amp;rdquo;:&amp;rdquo;http://&amp;rdquo;,
      &amp;rdquo;id&amp;rdquo;:1,
      &amp;rdquo;name&amp;rdquo;:&amp;rdquo;&amp;rdquo;
      },..],
&amp;ldquo;images&amp;rdquo;:[{
      &amp;ldquo;license&amp;rdquo;:4,
      &amp;rdquo;file_name&amp;rdquo;:00000397133.jpg&amp;rdquo;,
      &amp;rdquo;coco_url&amp;rdquo;:&amp;rdquo;http://images.coco&amp;hellip;&amp;rdquo;,
      &amp;rdquo;height&amp;rdquo;:427,
      &amp;rdquo;width&amp;rdquo;:640, 
      &amp;ldquo;date_captured&amp;rdquo;:&amp;rdquo;2013-11-14 17:02:52&amp;rdquo;,
      &quot;flickr_url&quot;: &quot;http://farm9.st&amp;hellip;..jpg&quot;,
      &quot;id&quot;: 37777
      },...],
annotations&quot;: [{
      &quot;segmentation&quot;: [[125.12,539.69,140.94,522.43,100.67,496.54,84.85,469.21,73.35,450.52,104.99,342.65,168.27,290.88,179.78,288,189.84,286.56,191.28,260.67,202.79,240.54,221.48,237.66,248.81,243.42,257.44,256.36,253.12,262.11,253.12,275.06,299.15,233.35,329.35,207.46,355.24,206.02,363.87,206.02,365.3,210.34,373.93,221.84,363.87,226.16,363.87,237.66,350.92,237.66,332.22,234.79,314.97,249.17,271.82,313.89,253.12,326.83,227.24,352.72,214.29,357.03,212.85,372.85,208.54,395.87,228.67,414.56,245.93,421.75,266.07,424.63,276.13,437.57,266.07,450.52,284.76,464.9,286.2,479.28,291.96,489.35,310.65,512.36,284.76,549.75,244.49,522.43,215.73,546.88,199.91,558.38,204.22,565.57,189.84,568.45,184.09,575.64,172.58,578.52,145.26,567.01,117.93,551.19,133.75,532.49]],
      &quot;num_keypoints&quot;: 10,
      &quot;area&quot;: 47803.27955,
      &quot;iscrowd&quot;: 0,
      &quot;keypoints&quot;: [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,142,309,1,177,320,2,191,398,2,237,317,2,233,426,2,306,233,2,92,452,2,123,468,2,0,0,0,251,469,2,0,0,0,162,551,2],
      &quot;image_id&quot;: 425226,
      &quot;bbox&quot;: [73.35,206.02,300.58,372.5],
      &quot;category_id&quot;: 1,
      &quot;id&quot;: 183126
      },...}],
&quot;categories&quot;: [{
      &quot;supercategory&quot;: &quot;person&quot;,
      &quot;id&quot;: 1,
      &quot;name&quot;: &quot;person&quot;,
      &quot;keypoints&quot;: [&quot;nose&quot;,&quot;left_eye&quot;,&quot;right_eye&quot;,&quot;left_ear&quot;,&quot;right_ear&quot;,&quot;left_shoulder&quot;,&quot;right_shoulder&quot;,&quot;left_elbow&quot;,&quot;right_elbow&quot;,&quot;left_wrist&quot;,&quot;right_wrist&quot;,&quot;left_hip&quot;,&quot;right_hip&quot;,&quot;left_knee&quot;,&quot;right_knee&quot;,&quot;left_ankle&quot;,&quot;right_ankle&quot;
      ],
      &quot;skeleton&quot;: [[16,14],[14,12],[17,15],[15,13],[12,13],[6,12],[7,13],[6,7],[6,8],[7,9],[8,10],[9,11],[2,3],[1,2],[1,3],[2,4],[3,5],[4,6],[5,7]]}]
}&lt;/code&gt;&lt;/pre&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;txt파일의 내용은 아래와 같습니다&lt;/p&gt;
&lt;pre id=&quot;code_1694585514734&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;ClassID,
Bbox : (x,y,w,h) 중심좌표, 박스 가로길이, 세로길이
Keypoint : (x,y,visible) [nose, l_eye, r_eye, l_ear, l_ear, l_shoulder, r_shoulder, l_elbow, r_elbow, l_wrist, r_wrist,l _hip, r_hip, l_knee, r_knee, l_ankle, r_ankle]
x, y 각 포인트는 이미지의 w,h으로 나눠서 최대 1로 스케일링 된 상태입니다.&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 Json에서 필요한부분만 추출해서 txt파일로 각각 파일명으로 저장해야 합니다.&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://roboflow.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://roboflow.com/&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1694585877832&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;Roboflow: Give your software the power to see objects in images and video&quot; data-og-description=&quot;With just a few dozen example images, you can train a working, state-of-the-art computer vision model in less than 24 hours.&quot; data-og-host=&quot;roboflow.com&quot; data-og-source-url=&quot;https://roboflow.com/&quot; data-og-url=&quot;https://roboflow.com/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/dVmVYo/hyTVZyj7hU/cqpLoEAUBzi8ZQuKjqzuMk/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/bCBBiE/hyTV3nckyX/Lvip4q5b58GHgu45wzBhm1/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/dVIYm7/hyTSAtrfCX/BPeuh0asxm2Y1eyAhLxPZK/img.png?width=1024&amp;amp;height=768&amp;amp;face=0_0_1024_768&quot;&gt;&lt;a href=&quot;https://roboflow.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://roboflow.com/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/dVmVYo/hyTVZyj7hU/cqpLoEAUBzi8ZQuKjqzuMk/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/bCBBiE/hyTV3nckyX/Lvip4q5b58GHgu45wzBhm1/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/dVIYm7/hyTSAtrfCX/BPeuh0asxm2Y1eyAhLxPZK/img.png?width=1024&amp;amp;height=768&amp;amp;face=0_0_1024_768');&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;Roboflow: Give your software the power to see objects in images and video&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;With just a few dozen example images, you can train a working, state-of-the-art computer vision model in less than 24 hours.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;roboflow.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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;846&quot; data-origin-height=&quot;731&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dMVhmb/btstSlg6MFl/bRzFI5UKauYkMSn8GQ0x61/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dMVhmb/btstSlg6MFl/bRzFI5UKauYkMSn8GQ0x61/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dMVhmb/btstSlg6MFl/bRzFI5UKauYkMSn8GQ0x61/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdMVhmb%2FbtstSlg6MFl%2FbRzFI5UKauYkMSn8GQ0x61%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;846&quot; height=&quot;731&quot; data-origin-width=&quot;846&quot; data-origin-height=&quot;731&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;회원가입 후에 workspace를 만듭니다.&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;1878&quot; data-origin-height=&quot;663&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qMPnA/btstRt00ldg/NMHZTgzeEUM1UlKP7FaXI0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qMPnA/btstRt00ldg/NMHZTgzeEUM1UlKP7FaXI0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qMPnA/btstRt00ldg/NMHZTgzeEUM1UlKP7FaXI0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqMPnA%2FbtstRt00ldg%2FNMHZTgzeEUM1UlKP7FaXI0%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;1878&quot; height=&quot;663&quot; data-origin-width=&quot;1878&quot; data-origin-height=&quot;663&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;846&quot; data-origin-height=&quot;738&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dgrnd1/btstShMAL4d/ZfxmMKmMtRXbbMhvBVbz4K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dgrnd1/btstShMAL4d/ZfxmMKmMtRXbbMhvBVbz4K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dgrnd1/btstShMAL4d/ZfxmMKmMtRXbbMhvBVbz4K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdgrnd1%2FbtstShMAL4d%2FZfxmMKmMtRXbbMhvBVbz4K%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;846&quot; height=&quot;738&quot; data-origin-width=&quot;846&quot; data-origin-height=&quot;738&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;create new project를 클릭합니다&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;1452&quot; data-origin-height=&quot;1018&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cjbIw7/btstX814Kzc/7d7kQMIljrBzn7B94pXV7K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cjbIw7/btstX814Kzc/7d7kQMIljrBzn7B94pXV7K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cjbIw7/btstX814Kzc/7d7kQMIljrBzn7B94pXV7K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcjbIw7%2FbtstX814Kzc%2F7d7kQMIljrBzn7B94pXV7K%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;1452&quot; height=&quot;1018&quot; data-origin-width=&quot;1452&quot; data-origin-height=&quot;1018&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;저는 이미지 파일과 json, xml파일을 넣고 상단에 save and continue를 클릭합니다.&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;635&quot; data-origin-height=&quot;417&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bvVHeN/btstNA7fBAP/YkDIuhTKeGD7iTHprThzQ1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bvVHeN/btstNA7fBAP/YkDIuhTKeGD7iTHprThzQ1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bvVHeN/btstNA7fBAP/YkDIuhTKeGD7iTHprThzQ1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbvVHeN%2FbtstNA7fBAP%2FYkDIuhTKeGD7iTHprThzQ1%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;635&quot; height=&quot;417&quot; data-origin-width=&quot;635&quot; data-origin-height=&quot;417&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;train과 valid,test폴더 비율을 설정합니다.&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;그후에 argumentation과 몇개의 이미지를 만들지 옵션을 정해주고 생성버튼을 누릅니다.&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;1496&quot; data-origin-height=&quot;1271&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/VHUZf/btstVgGpk2p/zq0MKbX7GZPOUtpohgmDp1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/VHUZf/btstVgGpk2p/zq0MKbX7GZPOUtpohgmDp1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/VHUZf/btstVgGpk2p/zq0MKbX7GZPOUtpohgmDp1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FVHUZf%2FbtstVgGpk2p%2Fzq0MKbX7GZPOUtpohgmDp1%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;1496&quot; height=&quot;1271&quot; data-origin-width=&quot;1496&quot; data-origin-height=&quot;1271&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;Export dataset을 누르면&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;642&quot; data-origin-height=&quot;678&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cSSHrp/btstSBdd3Up/GEqyL7CnBzNnarytmw5zB0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cSSHrp/btstSBdd3Up/GEqyL7CnBzNnarytmw5zB0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cSSHrp/btstSBdd3Up/GEqyL7CnBzNnarytmw5zB0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcSSHrp%2FbtstSBdd3Up%2FGEqyL7CnBzNnarytmw5zB0%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;642&quot; height=&quot;678&quot; data-origin-width=&quot;642&quot; data-origin-height=&quot;678&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;</description>
      <category>영상처리/Object Detection</category>
      <author>Ninestar</author>
      <guid isPermaLink="true">https://data-science.tistory.com/542</guid>
      <comments>https://data-science.tistory.com/542#entry542comment</comments>
      <pubDate>Wed, 13 Sep 2023 15:53:35 +0900</pubDate>
    </item>
    <item>
      <title>PC에서 에어팟(무선이어폰)으로 연결 및 디스코드 음질 해결</title>
      <link>https://data-science.tistory.com/538</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;PC 메인보드는 대부분 무선모듈이 없기 때문에 USB동글을 따로 구매해 연결하면 무선 블루투스를 사용할 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;857&quot; data-origin-height=&quot;678&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/TCEMi/btstr2QV268/R1bt8cr1tcO9QOXBQnB7F0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/TCEMi/btstr2QV268/R1bt8cr1tcO9QOXBQnB7F0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/TCEMi/btstr2QV268/R1bt8cr1tcO9QOXBQnB7F0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FTCEMi%2Fbtstr2QV268%2FR1bt8cr1tcO9QOXBQnB7F0%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;526&quot; height=&quot;416&quot; data-origin-width=&quot;857&quot; data-origin-height=&quot;678&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&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;406&quot; data-origin-height=&quot;196&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/paKVe/btstxlhx81S/Drn07xHvwMG7YB3knPDKK0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/paKVe/btstxlhx81S/Drn07xHvwMG7YB3knPDKK0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/paKVe/btstxlhx81S/Drn07xHvwMG7YB3knPDKK0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FpaKVe%2Fbtstxlhx81S%2FDrn07xHvwMG7YB3knPDKK0%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;406&quot; height=&quot;196&quot; data-origin-width=&quot;406&quot; data-origin-height=&quot;196&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아이콘을 더블클릭하면 bluetooth 및 기타 장치 창이 뜹니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1194&quot; data-origin-height=&quot;910&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bNOY6W/btstyw3ZH4a/CnbA7qkl1eWFim2cnSvqk0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bNOY6W/btstyw3ZH4a/CnbA7qkl1eWFim2cnSvqk0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bNOY6W/btstyw3ZH4a/CnbA7qkl1eWFim2cnSvqk0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbNOY6W%2Fbtstyw3ZH4a%2FCnbA7qkl1eWFim2cnSvqk0%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;751&quot; height=&quot;572&quot; data-origin-width=&quot;1194&quot; data-origin-height=&quot;910&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1번 장치 추가해서 PC와 무선이어폰 페어링을 합니다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2번 페어링후 연결버튼을 눌러서 PC와 무선이어폰 연결합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기까지하면 PC에서 무선이어폰으로 소리를 들을 수 있습니다.&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;460&quot; data-origin-height=&quot;513&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/27Fgn/btstxjD04Mb/jIvmlTVeyTDjfmvPc2bdG1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/27Fgn/btstxjD04Mb/jIvmlTVeyTDjfmvPc2bdG1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/27Fgn/btstxjD04Mb/jIvmlTVeyTDjfmvPc2bdG1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F27Fgn%2FbtstxjD04Mb%2FjIvmlTVeyTDjfmvPc2bdG1%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;460&quot; height=&quot;513&quot; data-origin-width=&quot;460&quot; data-origin-height=&quot;513&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;핸즈프리모드로 하면 에어팟하나로 마이크와 음성듣기를 동시에 가능하지만 음질이 떨어집니다. 마치 통화하는 것 같은 음질입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 저는 핸즈프리모드를 끄고 일반 이어폰모드로만 이용합니다. 그런데 이때 문제가 발생합니다. 게임소리, 일반pc사운드는 다 들리는데 디스코드 소리만 안들립니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;핸즈프리모드로 디코하자니 음질이 안좋고 음질좋은 이어폰모드로 하자니 디스코드 소리는 안들리는ㅠ&lt;/b&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;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;해결방법&lt;/b&gt;&lt;/span&gt;&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;462&quot; data-origin-height=&quot;515&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bWAO94/btstCYliTow/4VY0PtfuXcCZeKl9n7SJu1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bWAO94/btstCYliTow/4VY0PtfuXcCZeKl9n7SJu1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bWAO94/btstCYliTow/4VY0PtfuXcCZeKl9n7SJu1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbWAO94%2FbtstCYliTow%2F4VY0PtfuXcCZeKl9n7SJu1%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;462&quot; height=&quot;515&quot; data-origin-width=&quot;462&quot; data-origin-height=&quot;515&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;녹음탭에서 에어팟 핸즈프리를 사용안함으로 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;462&quot; data-origin-height=&quot;517&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eCRx0j/btstzxhhk8n/yvl5hkbSHhd2e8nv9KQOik/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eCRx0j/btstzxhhk8n/yvl5hkbSHhd2e8nv9KQOik/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eCRx0j/btstzxhhk8n/yvl5hkbSHhd2e8nv9KQOik/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FeCRx0j%2Fbtstzxhhk8n%2Fyvl5hkbSHhd2e8nv9KQOik%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;462&quot; height=&quot;517&quot; data-origin-width=&quot;462&quot; data-origin-height=&quot;517&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;950&quot; data-origin-height=&quot;928&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/csWJV4/btstG6KaQGu/mNAYdcfIBlaKZcTkv57MhK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/csWJV4/btstG6KaQGu/mNAYdcfIBlaKZcTkv57MhK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/csWJV4/btstG6KaQGu/mNAYdcfIBlaKZcTkv57MhK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcsWJV4%2FbtstG6KaQGu%2FmNAYdcfIBlaKZcTkv57MhK%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;950&quot; height=&quot;928&quot; data-origin-width=&quot;950&quot; data-origin-height=&quot;928&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;</description>
      <category>컴퓨터</category>
      <author>Ninestar</author>
      <guid isPermaLink="true">https://data-science.tistory.com/538</guid>
      <comments>https://data-science.tistory.com/538#entry538comment</comments>
      <pubDate>Mon, 11 Sep 2023 10:16:01 +0900</pubDate>
    </item>
    <item>
      <title>갤럭시 카메라 셔터음 무음으로 설정하기(루팅없이)</title>
      <link>https://data-science.tistory.com/520</link>
      <description>&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;저는 갤럭시 울트라 22를 사용중이고&lt;/b&gt;&lt;br /&gt;&lt;b&gt;기본 카메라 어플에서 진동, 무음모드일때 카메라 셔터음을 무음으로 설정해 보았습니다.&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;구글 플레이 스토어에서 셋에디트 어플을 받습니다. 핸드폰의 database를 수정하는 어플입니다.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;3088&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c0UEHZ/btsr5hfYa4P/TH5NtpNzeLj7WmA9qCWYLK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c0UEHZ/btsr5hfYa4P/TH5NtpNzeLj7WmA9qCWYLK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c0UEHZ/btsr5hfYa4P/TH5NtpNzeLj7WmA9qCWYLK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc0UEHZ%2Fbtsr5hfYa4P%2FTH5NtpNzeLj7WmA9qCWYLK%2Fimg.jpg&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;1440&quot; height=&quot;3088&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;3088&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br /&gt;&lt;b&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;설치 후 &lt;/span&gt;&lt;/b&gt;&lt;b&gt;실행하면 &lt;/b&gt;&lt;b&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&amp;nbsp;경고 문구와 &lt;/span&gt;&lt;/b&gt;&lt;b&gt;이런 화면이 뜹니다. &lt;span style=&quot;color: #666666;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;경고문구는 확인을 눌러 넘어가도록 합니다.&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;421&quot; data-origin-height=&quot;222&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b31np0/btsr641viZ4/LjaaAAqMnG5BCD6olxHZfK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b31np0/btsr641viZ4/LjaaAAqMnG5BCD6olxHZfK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b31np0/btsr641viZ4/LjaaAAqMnG5BCD6olxHZfK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb31np0%2Fbtsr641viZ4%2FLjaaAAqMnG5BCD6olxHZfK%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;421&quot; height=&quot;222&quot; data-origin-width=&quot;421&quot; data-origin-height=&quot;222&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;3088&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/LMdCc/btsrZwdWLSe/Yiqn8iI6aNCZEn4gramrSK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/LMdCc/btsrZwdWLSe/Yiqn8iI6aNCZEn4gramrSK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/LMdCc/btsrZwdWLSe/Yiqn8iI6aNCZEn4gramrSK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FLMdCc%2FbtsrZwdWLSe%2FYiqn8iI6aNCZEn4gramrSK%2Fimg.jpg&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;1440&quot; height=&quot;3088&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;3088&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br /&gt;&lt;b&gt;스크롤을 쭉 내려서&amp;nbsp; csc_perf_camera_forced_shuttersound_key를 찾습니다. csc_perf_camera_forced_shuttersound_key를 터치하면 메뉴가 뜨는데 Edit Value를 누릅니다.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;845&quot; data-origin-height=&quot;883&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dctqNx/btsrTn97RSf/P4rYumn1XFPLFQXWixpulk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dctqNx/btsrTn97RSf/P4rYumn1XFPLFQXWixpulk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dctqNx/btsrTn97RSf/P4rYumn1XFPLFQXWixpulk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdctqNx%2FbtsrTn97RSf%2FP4rYumn1XFPLFQXWixpulk%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;845&quot; height=&quot;883&quot; data-origin-width=&quot;845&quot; data-origin-height=&quot;883&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;3088&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bysRpf/btsrUt3lCcV/b2FHyyfHgUzr7kPMPkjN91/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bysRpf/btsrUt3lCcV/b2FHyyfHgUzr7kPMPkjN91/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bysRpf/btsrUt3lCcV/b2FHyyfHgUzr7kPMPkjN91/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbysRpf%2FbtsrUt3lCcV%2Fb2FHyyfHgUzr7kPMPkjN91%2Fimg.jpg&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;1440&quot; height=&quot;3088&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;3088&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br /&gt;&lt;b&gt;Edit Setting에서 처음에 1이였던 값을 0으로 변경합니다.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;3088&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bP5BDV/btsr0siiMkz/6XcX1LrMyXHsusWUyPCRN1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bP5BDV/btsr0siiMkz/6XcX1LrMyXHsusWUyPCRN1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bP5BDV/btsr0siiMkz/6XcX1LrMyXHsusWUyPCRN1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbP5BDV%2Fbtsr0siiMkz%2F6XcX1LrMyXHsusWUyPCRN1%2Fimg.jpg&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;1440&quot; height=&quot;3088&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;3088&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br /&gt;&lt;b&gt;이제 set edit어플을 닫고 카메라 어플을 실행시켜 진동,무음모드일때 카메라 셔터음이 무음인지 확인합니다.&lt;br /&gt;&lt;br /&gt;추가로 위 설정을 해도 소리모드 사용중에는 셔터음이 나는데 빅스비 루틴으로 아래처럼 카메라 실행시 소리모드를 진동 또는 무음모드로 바꿔주면 소리모드 사용중에도 카메라 셔터음을 없앨 수 있습니다&lt;br /&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;3088&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b12MqI/btsrVtvw0ZK/Okm7q6YmbfGAYxt9VswKKK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b12MqI/btsrVtvw0ZK/Okm7q6YmbfGAYxt9VswKKK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b12MqI/btsrVtvw0ZK/Okm7q6YmbfGAYxt9VswKKK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb12MqI%2FbtsrVtvw0ZK%2FOkm7q6YmbfGAYxt9VswKKK%2Fimg.jpg&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;1440&quot; height=&quot;3088&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;3088&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;※ 저는 카메라를 사용하면 조금 민망한 상황에 사용하려 설치를 했습니다. (e.g. 회의시간, 강의시간, 조용한 공간)&lt;br /&gt;부적절한 카메라 사용으로 인한 발생하는 문제에 대해 주의하세요.&lt;/p&gt;</description>
      <category>컴퓨터</category>
      <author>Ninestar</author>
      <guid isPermaLink="true">https://data-science.tistory.com/520</guid>
      <comments>https://data-science.tistory.com/520#entry520comment</comments>
      <pubDate>Thu, 24 Aug 2023 09:47:51 +0900</pubDate>
    </item>
    <item>
      <title>멜론해지, 유튜브 뮤직(Youtube Music) PC프로그램(Desktop App)</title>
      <link>https://data-science.tistory.com/507</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;멜론은 그동안 등급 날리는게 아까워 유지를 하고있었지만 MVIP 헤택이 진짜 하나도 없고 노래도 많이 듣는편도 아니여서 해지해버렸습니다. 78개월을 썼네요. ㅎㅎ&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;1528&quot; data-origin-height=&quot;1452&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ugNiR/btsq7bOCUGA/OuE28FXzDALa2DGgKpN2t0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ugNiR/btsq7bOCUGA/OuE28FXzDALa2DGgKpN2t0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ugNiR/btsq7bOCUGA/OuE28FXzDALa2DGgKpN2t0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FugNiR%2Fbtsq7bOCUGA%2FOuE28FXzDALa2DGgKpN2t0%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;1528&quot; height=&quot;1452&quot; data-origin-width=&quot;1528&quot; data-origin-height=&quot;1452&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;그리고 유튜브 프리미엄을 이용하게 됐습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데&amp;nbsp; 멜론처럼 전용프로그램이 없어 크롬이나 엣지에서 음악을 듣는게 불편했습니다. 유튭은 전용프로그램이 없을까? 하고 프로그램을 찾아봤습니다.&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;Download&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://ytmdesktop.app/#download&quot;&gt;https://ytmdesktop.app/#download&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1691820209345&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;YouTube Music Desktop App&quot; data-og-description=&quot;Free cross platform Desktop Player for YouTube Music&quot; data-og-host=&quot;ytmdesktop.app&quot; data-og-source-url=&quot;https://ytmdesktop.app/#download&quot; data-og-url=&quot;https://ytmdesktop.app/#download&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/BJmId/hyTCE2KAij/5B5BAmIQiOs64wleXHOIy0/img.png?width=512&amp;amp;height=512&amp;amp;face=0_0_512_512,https://scrap.kakaocdn.net/dn/er6p0C/hyTCDW5z1y/vOdI1bFKjk7ehCvHbKzea1/img.png?width=1797&amp;amp;height=939&amp;amp;face=0_0_1797_939,https://scrap.kakaocdn.net/dn/Y11JP/hyTCxCw29D/CNlkyK6sfXb1JsqNb2YZH0/img.png?width=702&amp;amp;height=802&amp;amp;face=0_0_702_802&quot;&gt;&lt;a href=&quot;https://ytmdesktop.app/#download&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://ytmdesktop.app/#download&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/BJmId/hyTCE2KAij/5B5BAmIQiOs64wleXHOIy0/img.png?width=512&amp;amp;height=512&amp;amp;face=0_0_512_512,https://scrap.kakaocdn.net/dn/er6p0C/hyTCDW5z1y/vOdI1bFKjk7ehCvHbKzea1/img.png?width=1797&amp;amp;height=939&amp;amp;face=0_0_1797_939,https://scrap.kakaocdn.net/dn/Y11JP/hyTCxCw29D/CNlkyK6sfXb1JsqNb2YZH0/img.png?width=702&amp;amp;height=802&amp;amp;face=0_0_702_802');&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;YouTube Music Desktop App&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Free cross platform Desktop Player for YouTube Music&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;ytmdesktop.app&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;github&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/ytmdesktop/ytmdesktop&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://github.com/ytmdesktop/ytmdesktop&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1691820223882&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 - ytmdesktop/ytmdesktop: A Desktop App for YouTube Music&quot; data-og-description=&quot;A Desktop App for YouTube Music. Contribute to ytmdesktop/ytmdesktop development by creating an account on GitHub.&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/ytmdesktop/ytmdesktop&quot; data-og-url=&quot;https://github.com/ytmdesktop/ytmdesktop&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/cK9V42/hyTCBZerAO/6SZIFykMQKkqaFoL3two6K/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/ytmdesktop/ytmdesktop&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/ytmdesktop/ytmdesktop&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/cK9V42/hyTCBZerAO/6SZIFykMQKkqaFoL3two6K/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 - ytmdesktop/ytmdesktop: A Desktop App for YouTube Music&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;A Desktop App for YouTube Music. Contribute to ytmdesktop/ytmdesktop 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;</description>
      <category>컴퓨터</category>
      <author>Ninestar</author>
      <guid isPermaLink="true">https://data-science.tistory.com/507</guid>
      <comments>https://data-science.tistory.com/507#entry507comment</comments>
      <pubDate>Mon, 14 Aug 2023 10:08:17 +0900</pubDate>
    </item>
    <item>
      <title>[RUST]  `static</title>
      <link>https://data-science.tistory.com/496</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;데이터의 라이프타임(lifetime)을 나타내는 특별한 키워드입니다. `'static`은 프로그램 전체 수명 동안 지속되는 정적(static) 데이터를 표현합니다. `'static`은 라이프타임이 가장 긴 수명을 갖는 것으로 간주됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;`'static`은 다음과 상황에서 사용될 수 있습니다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 리터럴 데이터: 문자열 리터럴과 정수형 리터럴 같은 리터럴 값은 `'static` 라이프타임을 갖습니다. 이는 프로그램 실행 동안 변하지 않고 메모리에 상주하는 데이터입니다.&lt;/p&gt;
&lt;pre id=&quot;code_1691122583768&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;let static_string: &amp;amp;'static str = &quot;Hello, world!&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;2. 정적 변수: `static` 키워드로 선언된 정적 변수는 `'static` 라이프타임을 가집니다. 이러한 변수는 프로그램 전체에서 사용 가능하며, 프로그램이 실행되는 동안 메모리에 유지됩니다.&lt;/p&gt;
&lt;pre id=&quot;code_1691122590458&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;static STATIC_VALUE: i32 = 42;&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. 글로벌 상수: `const` 키워드로 선언된 글로벌 상수는 `'static` 라이프타임을 가집니다. 이러한 상수는 프로그램 전체에서 사용 가능하며, 프로그램이 실행되는 동안 메모리에 상주합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1691122597969&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const PI: f64 = 3.14159;&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;`'static` 라이프타임은 프로그램 전체에서 사용되는 데이터의 수명을 나타내므로, 해당 데이터는 프로그램 실행 동안 메모리에 유지됩니다. Rust는 `'static` 데이터에 대한 안전한 접근을 보장하고 메모리 안정성을 유지하기 위해 관련 규칙과 보호 기능을 제공합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;br /&gt;&lt;br /&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Rust에서 `&amp;amp;'static`은 `'static` 라이프타임을 갖는 참조(reference)를 나타냅니다. `'static` 라이프타임은 프로그램의 전체 수명 동안 유지되는 정적(static) 데이터를 가리킵니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;`'static`은 Rust의 라이프타임 시스템에서 가장 긴 수명을 갖는 라이프타임으로, 해당 데이터가 프로그램 실행 동안 유지되는 것을 의미합니다. `'static` 라이프타임은 특히 리터럴 문자열, 정적 변수, 글로벌 상수 등과 관련됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;`&amp;amp;'static` 참조는 `'static` 라이프타임 데이터에 대한 불변 참조(immutable reference)를 나타냅니다. `'static` 데이터에 대한 불변 참조는 프로그램 전체에서 안전하게 사용될 수 있으며, 수명 관리 및 대여 규칙에 따라 해당 데이터에 대한 접근을 제한합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어, 다음은 `'static` 라이프타임을 갖는 문자열에 대한 불변 참조를 나타내는 예입니다:&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1691122614560&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;fn main() {

    let static_string: &amp;amp;'static str = &quot;Hello, world!&quot;;

    

    // 'static 라이프타임 데이터에 대한 불변 참조

    println!(&quot;{}&quot;, static_string);

}&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;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 예제에서 `static_string` 변수는 `'static` 라이프타임을 갖는 문자열에 대한 `&amp;amp;'static str` 타입의 참조를 가지고 있습니다. 이 참조는 프로그램 전체 수명 동안 유효하며, 해당 문자열에 대한 불변 참조를 제공합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Rust</category>
      <author>Ninestar</author>
      <guid isPermaLink="true">https://data-science.tistory.com/496</guid>
      <comments>https://data-science.tistory.com/496#entry496comment</comments>
      <pubDate>Sun, 13 Aug 2023 14:17:10 +0900</pubDate>
    </item>
    <item>
      <title>[RUST] &amp;amp;  *   `   ' ' 다양한 기호</title>
      <link>https://data-science.tistory.com/495</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;1. `&amp;amp;`:&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;- `&amp;amp;`는 참조(reference) 연산자로 사용됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;- 변수 또는 값 앞에 `&amp;amp;`를 붙여 해당 값에 대한 참조를 생성합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;- 참조는 값에 대한 불변 참조(immutable reference)를 생성하며, 해당 값에 대한 소유권을 이전하지 않고도 값을 참조할 수 있게 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. `*`:&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;- `*`은 역참조(dereference) 연산자로 사용됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;- 포인터를 역참조하여 해당 메모리 위치에 저장된 값을 얻습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;- `*`는 포인터가 가리키는 값을 읽거나 수정할 때 사용됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. `backtick`(`) 또는 `백틱`:&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;- `backtick`은 Rust에서 일반적으로 사용되지 않는 문자입니다. 대신, 문자열 리터럴에는 역따옴표(`)가 사용됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. `'` (작은 따옴표):&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;- `'`는 문자 리터럴을 나타내는 데 사용됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;- `'`는 단일 문자를 표현하는 Unicode 스칼라 값을 나타냅니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;- 예를 들어, `'A'`, `'b'`, `'1'`, `'!'`과 같이 작은 따옴표 안에 하나의 문자를 넣어 문자 리터럴을 표현할 수 있습니다.&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;</description>
      <category>Rust</category>
      <author>Ninestar</author>
      <guid isPermaLink="true">https://data-science.tistory.com/495</guid>
      <comments>https://data-science.tistory.com/495#entry495comment</comments>
      <pubDate>Sat, 12 Aug 2023 14:15:02 +0900</pubDate>
    </item>
    <item>
      <title>[RUST] match</title>
      <link>https://data-science.tistory.com/494</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;switch case문과 비슷합니다.&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;match는 패턴 매칭을 사용하여 다양한 경우의 수에 대한 코드 블록을 처리하는 구문입니다. `match`는 값이 여러 가지 가능한 경우에 대해 일치하는 패턴을 찾고 해당하는 코드를 실행합니다.&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;`match` 구문을 사용하는 이유&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 모든 경우 다루기: `match`는 모든 가능한 경우에 대해 명시적으로 처리할 수 있습니다. `match`를 사용하면 모든 열거형 변형(variant)이나 다양한 패턴에 대해 분기 처리를 작성할 수 있습니다. 이는 프로그램의 완전성을 보장하고 예기치 않은 경우를 방지하는 데 도움을 줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 코드 가독성: `match`는 패턴 매칭을 사용하므로 코드의 의도를 명확하게 표현할 수 있습니다. `match`를 사용하여 코드를 작성하면 어떤 값을 기준으로 처리하는지 명시적으로 나타낼 수 있으며, 패턴을 통해 구조를 분해하거나 특정 값을 추출할 수 있습니다. 이는 코드의 가독성을 높이고, 유지보수를 용이하게 만들어줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 패턴 활용: `match`는 다양한 패턴을 활용할 수 있는 강력한 기능을 제공합니다. 변수 바인딩, 값의 일부 추출, 구조 분해, 열거형 변형 매칭 등 다양한 패턴을 사용하여 값을 검사하고 원하는 동작을 수행할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. 타입 안정성: `match`는 패턴 매칭을 통해 타입 안정성을 제공합니다. Rust는 패턴 매칭을 사용하여 값의 타입이 맞는지 컴파일 시점에 검사하므로, 타입 오류를 런타임에서 발생시키는 것을 방지할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5. Exhaustiveness 체크: `match`는 패턴 매칭을 사용하여 모든 가능한 경우를 다루는지 확인할 수 있습니다. 컴파일러는 `match` 구문이 모든 패턴을 다루지 않거나 패턴이 누락되어 있을 때 경고를 표시하므로, 완전성을 보장할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러한 이유로 `match`는 Rust에서 값의 다양한 경우에 대해 명확하고 안전하게 처리할 수 있는 강력한 구문입니다. `match`를 사용하여 코드를 작성하면 코드의 의도를 명확하게 표현하고, 예외적인 경우를 다루고, 타입 안정성을 유지할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;`match`와 `if` 비교&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Rust에서 조건 분기를 다루는 두 가지 다른 구문입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. `match`:&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;- 패턴 매칭을 사용하여 값이 여러 가지 경우 중 하나에 맞는지 확인합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;- `match`는 모든 가능한 경우를 다룰 수 있도록 명시적으로 작성해야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;- 각 패턴에 대해 실행될 코드 블록을 작성할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;- 예시:&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1691122372299&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;     match value {

         Pattern1 =&amp;gt; {

             // Pattern1에 맞는 경우 실행될 코드

         },

         Pattern2 =&amp;gt; {

             // Pattern2에 맞는 경우 실행될 코드

         },

         _ =&amp;gt; {

             // 나머지 모든 경우에 대한 처리

         }

     }&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. `if`:&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;- 조건식을 평가하여 불리언(true/false) 값을 확인하고, 해당 조건이 참일 때 코드 블록을 실행합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;- `if`는 단일 조건을 다룰 때 사용됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;- 예시:&lt;/p&gt;
&lt;pre id=&quot;code_1691122389872&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;     if condition {

         // condition이 참인 경우 실행될 코드

     } else {

         // condition이 거짓인 경우 실행될 코드

     }&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;`match`는 여러 가지 경우에 대해 패턴 매칭을 통해 다양한 동작을 수행할 수 있고, 모든 경우를 명시적으로 다루어야 합니다. &lt;span style=&quot;letter-spacing: 0px;&quot;&gt;`if`는 단일 조건에 대해 불리언 값을 사용하여 실행 여부를 결정합니다. 각 구문은 다른 상황에 더 적합하게 사용됩니다. 이를테면, `match`는 열거형 변형이나 복잡한 패턴 매칭을 다룰 때 유용하며, `if`는 단순한 불리언 조건을 다룰 때 유용합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용할 구문은 상황에 따라 달라집니다. 패턴 매칭이 필요하거나 여러 경우를 다루어야 한다면 `match`를 사용하고, 단순한 조건을 다룰 때는 `if`를 사용하면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Rust</category>
      <author>Ninestar</author>
      <guid isPermaLink="true">https://data-science.tistory.com/494</guid>
      <comments>https://data-science.tistory.com/494#entry494comment</comments>
      <pubDate>Thu, 10 Aug 2023 14:10:43 +0900</pubDate>
    </item>
    <item>
      <title>[RUST] if let</title>
      <link>https://data-science.tistory.com/493</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;패턴 매칭을 사용하여 `Option`, `Result`, `enum` 등과 같은 대안적인 값을 다룰 때 편리하게 사용되는 구문입니다. `if let`을 사용하면 해당 값이 특정 패턴과 일치하는지 확인하고, 일치하는 경우에만 해당 블록의 코드를 실행할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;`if let`을 사용하는 이유&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 대안적인 값 처리: `Option`이나 `Result`와 같은 대안적인 값을 다룰 때, `if let`은 해당 값이 실제로 존재하는지 확인하고 그 값을 사용할 수 있게 해줍니다. 예를 들어, `Option` 값이 `Some`인 경우에만 해당 값을 사용하고, `None`인 경우에는 특정 동작을 수행할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 코드 가독성: `if let`은 패턴 매칭을 사용하므로 코드의 의도를 더 명확하게 표현할 수 있습니다. 이는 코드의 가독성을 높이고, 에러를 방지하고, 코드를 이해하기 쉽게 만들어줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 패턴 활용: `if let`은 패턴 매칭을 사용하므로 다양한 패턴을 활용할 수 있습니다. 변수 바인딩, 값의 일부 추출, 구조 분해, 열거형 변형 매칭 등 다양한 패턴을 활용하여 특정 조건에 따라 다른 동작을 수행할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. 에러 처리: `Result` 타입에서 `Ok`와 `Err` 결과를 처리할 때 `if let`을 사용하면 편리합니다. `Result` 값을 확인하고 `Ok`인 경우에는 해당 값을 사용하고, `Err`인 경우에는 에러 처리를 수행할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러한 이유로 `if let`은 Rust에서 대안적인 값을 처리하고, 패턴 매칭을 활용하여 코드를 더욱 명확하고 유연하게 작성할 수 있는 유용한 구문입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Rust</category>
      <author>Ninestar</author>
      <guid isPermaLink="true">https://data-science.tistory.com/493</guid>
      <comments>https://data-science.tistory.com/493#entry493comment</comments>
      <pubDate>Wed, 9 Aug 2023 14:09:00 +0900</pubDate>
    </item>
    <item>
      <title>[RUST] unwrap과 '?'</title>
      <link>https://data-science.tistory.com/492</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;두 연산자는 에러 처리와 결과 값의 추출을 간편하게 수행하기 위해 사용됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. `unwrap`:&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;- `Option` 또는 `Result` 타입에서 값을 안전하게 추출합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;- `unwrap`은 `Option` 타입에서 `Some` 값을 추출하거나, `Result` 타입에서 `Ok` 값을 추출합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;- `unwrap`은 값의 존재 여부를 검사하지 않고, 값을 강제로 추출합니다. 따라서, 값이 없는 경우(`None` 또는 `Err`)에는 패닉을 일으킬 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;- 주로 디버깅이나 간단한 예제 코드 작성 시 사용되며, 실제 상용 코드에서는 에러 처리를 명시적으로 수행하는 것이 권장됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. `?` (Question Mark Operator):&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;- `?` 연산자는 함수나 메서드 내에서 `Result`를 반환하는 표현식에서 사용됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;- `?`은 결과 값을 추출하여 해당 값이 `Ok`인 경우에는 값을 반환하고, `Err`인 경우에는 현재 함수를 호출한 곳으로 `Err` 값을 전파합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;- `?`은 에러 처리를 간편하게 수행할 수 있도록 도와줍니다. 코드의 가독성과 안전성을 높여줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;- `?`을 사용하려면 현재 함수가 반환하는 타입이 `Result` 타입이어야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;`unwrap`과 `?`의 사용 이유는 다음과 같습니다:&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- `unwrap`은 값이 확실히 존재할 때, 간단하게 값을 추출하기 위해 사용될 수 있습니다. 하지만 값이 없는 경우에는 패닉을 일으킬 수 있으므로 주의해야 합니다.&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;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;`unwrap`은 주의해서 사용해야 하며, 일반적으로 실제 상용 코드에서는 명시적인 에러 처리와 함께 `?`을 사용하는 것이 권장됩니다. 이를 통해 안전성과 유지보수성을 높일 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Rust</category>
      <author>Ninestar</author>
      <guid isPermaLink="true">https://data-science.tistory.com/492</guid>
      <comments>https://data-science.tistory.com/492#entry492comment</comments>
      <pubDate>Mon, 7 Aug 2023 15:07:51 +0900</pubDate>
    </item>
    <item>
      <title>[RUST] Some</title>
      <link>https://data-science.tistory.com/491</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;Some은 `Option` 열거형의 변형 중 하나로, 값이 있는 경우를 나타냅니다. `Option`은 Rust에서 값의 존재 여부를 표현하는 타입이며, `Some`은 그 값이 있는 경우를 나타냅니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;`Some`을 사용하는 이유&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 값의 존재 여부 표현: `Some`은 값이 존재하는 경우를 명시적으로 표현합니다. Rust에서는 `Option` 타입을 사용하여 값이 있을 수도 있고 없을 수도 있는 경우를 처리할 수 있습니다. `Some`은 값이 있는 경우를 나타내므로, 이를 통해 값을 정확하게 전달하고 처리할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 타입 안정성: `Option` 타입은 컴파일 시점에서 값의 존재 여부를 확인하여 타입 안정성을 제공합니다. `Option`을 사용하면 값을 명시적으로 `Some`으로 표현하거나 `None`으로 표현하여 타입 안전성을 유지할 수 있습니다. 이는 런타임에서 발생할 수 있는 예기치 않은 상황을 방지하고, 코드를 더욱 안정적으로 만들어줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 패턴 매칭과 함께 사용: `Option`은 패턴 매칭과 함께 사용되는 경우가 많습니다. `Some`을 패턴으로 사용하여 값이 있는 경우에 대한 분기 처리를 할 수 있습니다. 이를 통해 값을 안전하게 추출하거나 다양한 동작을 수행할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. 명시적인 처리: `Some`을 사용하여 값이 있는 경우를 명시적으로 처리할 수 있습니다. 이는 코드의 의도를 명확하게 전달하고 가독성을 높여줍니다. `Some`을 사용함으로써 값의 존재 여부를 확인하고 처리함으로써 코드의 명확성과 가독성을 높일 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서, Rust에서 `Some`은 값이 있는 경우를 나타내고, `Option` 타입과 함께 사용하여 값의 존재 여부를 명확하게 표현하고 타입 안정성을 유지하기 위해 사용됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Rust</category>
      <author>Ninestar</author>
      <guid isPermaLink="true">https://data-science.tistory.com/491</guid>
      <comments>https://data-science.tistory.com/491#entry491comment</comments>
      <pubDate>Sun, 6 Aug 2023 10:06:38 +0900</pubDate>
    </item>
    <item>
      <title>TTS 응용 사례</title>
      <link>https://data-science.tistory.com/490</link>
      <description>&lt;h3 style=&quot;background-color: #ffffff;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #1f2328;&quot;&gt;교육&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;텍스트를 읽기 어려운 경우, 음성으로 듣고 학습할 수 있도록 도와줍니다. 또한, 외국어 학습에도 활용될 수 있습니다. 텍스트를 입력하여 음성으로 듣고 발음을 연습할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;h3 style=&quot;background-color: #ffffff;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #1f2328;&quot;&gt;음성 컨텐츠&amp;nbsp;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;게임에서 NPC의 목소리를 생성하거나, 영화에서 배경음과 대사를 더빙하는 데 사용할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;&lt;span style=&quot;color: #1155cc;&quot;&gt;&lt;/span&gt;&lt;a href=&quot;https://search.bilibili.com/all?vt=34305959&amp;amp;keyword=vits&amp;amp;from_source=webtop_search&amp;amp;spm_id_from=333.788&amp;amp;search_source=5&quot;&gt;https://search.bilibili.com/all?vt=34305959&amp;amp;keyword=vits&amp;amp;from_source=webtop_search&amp;amp;spm_id_from=333.788&amp;amp;search_source=5&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;h3 style=&quot;background-color: #ffffff;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #1f2328;&quot;&gt;음성 인터페이스&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;스마트폰, 스마트 홈 장치와 같은 음성 인터페이스 기술에 사용되어, 사용자들이 음성으로 기기와 상호작용할 수 있도록 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;&lt;span style=&quot;color: #1155cc;&quot;&gt;&lt;/span&gt;&lt;a href=&quot;https://www.youtube.com/shorts/Ykxhz4BrTVs&quot;&gt;https://www.youtube.com/shorts/Ykxhz4BrTVs&lt;/a&gt;&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;&lt;span style=&quot;color: #1155cc;&quot;&gt;&lt;/span&gt;&lt;a href=&quot;https://youtu.be/PzzMSQLwabE?t=61&quot;&gt;https://youtu.be/PzzMSQLwabE?t=61&lt;/a&gt;&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;&lt;span style=&quot;color: #1155cc;&quot;&gt;&lt;/span&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=XhfuKhb_9Wo&amp;amp;ab_channel=KBSNews&quot;&gt;https://www.youtube.com/watch?v=XhfuKhb_9Wo&amp;amp;ab_channel=KBSNews&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;br /&gt;&lt;br /&gt;&lt;/b&gt;&lt;/p&gt;
&lt;h3 style=&quot;background-color: #ffffff;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #1f2328;&quot;&gt;음성 안내 시스템&amp;nbsp;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;공공 장소나 규모 있는 시설에서 TTS를 이용하여 안내를 제공할 수 있습니다. 공항, 박물관, 상점, 대중 교통 등에서 사용할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;&lt;span style=&quot;color: #1155cc;&quot;&gt;&lt;/span&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=5v6pCOIQhLw&amp;amp;ab_channel=%EB%B2%84%EC%B2%A0%EC%9D%B4&quot;&gt;https://www.youtube.com/watch?v=5v6pCOIQhLw&amp;amp;ab_channel=%EB%B2%84%EC%B2%A0%EC%9D%B4&lt;/a&gt;&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;&lt;span style=&quot;color: #1155cc;&quot;&gt;&lt;/span&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=NTFjGGB3eAc&amp;amp;ab_channel=%EB%B2%84%EC%B2%A0%EC%9D%B4&quot;&gt;https://www.youtube.com/watch?v=NTFjGGB3eAc&amp;amp;ab_channel=%EB%B2%84%EC%B2%A0%EC%9D%B4&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;h3 style=&quot;background-color: #ffffff;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #1f2328;&quot;&gt;Voice Cloning&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;사람의 목소리를 복제하는 기술입니다.&amp;nbsp; 아직 개발 초기단계입니다. 사기를 치거나, 정치적인 목적으로 사람의 목소리를 조작하는 등의 윤리적인 문제가 발생할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;&lt;span style=&quot;color: #1155cc;&quot;&gt;&lt;/span&gt;&lt;a href=&quot;https://youtu.be/w0v45Zahik0?t=20&quot;&gt;https://youtu.be/w0v45Zahik0?t=20&lt;/a&gt;&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #1155cc;&quot;&gt;&lt;/span&gt;&lt;a href=&quot;https://youtu.be/-O_hYhToKoA?t=9&quot;&gt;https://youtu.be/-O_hYhToKoA?t=9&lt;/a&gt;&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;&lt;span style=&quot;color: #1155cc;&quot;&gt;&lt;/span&gt;&lt;a href=&quot;https://youtu.be/nb3R30b-uhc?t=169&quot;&gt;https://youtu.be/nb3R30b-uhc?t=169&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/b&gt;&lt;/p&gt;
&lt;h2 style=&quot;background-color: #ffffff;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #1f2328;&quot;&gt;활용&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;실시간통역(STT-TTS)&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;&lt;span style=&quot;color: #1155cc;&quot;&gt;&lt;/span&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=5WXfDyS_T5k&amp;amp;ab_channel=%EC%9D%B8%EA%B3%B5%EC%A7%80%EB%8A%A5%ED%8C%A9%ED%86%A0%EB%A6%AC%28AIFactory%29&quot;&gt;https://www.youtube.com/watch?v=5WXfDyS_T5k&amp;amp;ab_channel=%EC%9D%B8%EA%B3%B5%EC%A7%80%EB%8A%A5%ED%8C%A9%ED%86%A0%EB%A6%AC%28AIFactory%29&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;SCE-TTS: 내 목소리로 TTS 만들기&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;&lt;span style=&quot;color: #1155cc;&quot;&gt;&lt;/span&gt;&lt;a href=&quot;https://github.com/sce-tts/sce-tts.github.io&quot;&gt;https://github.com/sce-tts/sce-tts.github.io&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;FastSpeech2: 내 목소리로 TTS 만들기&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;&lt;span style=&quot;color: #1155cc;&quot;&gt;&lt;/span&gt;&lt;a href=&quot;https://pyrasis.com/tts/2023/02/05/FastSpeech2-My-Voice-TTS&quot;&gt;https://pyrasis.com/tts/2023/02/05/FastSpeech2-My-Voice-TTS&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Bark: 오픈소스 TTS 한국어 + 보이스 클로닝&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;&lt;span style=&quot;color: #1155cc;&quot;&gt;&lt;/span&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=hK8_wmy3t24&amp;amp;ab_channel=%EB%AF%B9%EC%8A%A4%EC%9D%98%EC%9D%B8%EA%B3%B5%EC%A7%80%EB%8A%A5&quot;&gt;https://www.youtube.com/watch?v=hK8_wmy3t24&amp;amp;ab_channel=%EB%AF%B9%EC%8A%A4%EC%9D%98%EC%9D%B8%EA%B3%B5%EC%A7%80%EB%8A%A5&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;coqui-ai TTS framework&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;&lt;span style=&quot;color: #1155cc;&quot;&gt;&lt;/span&gt;&lt;a href=&quot;https://github.com/coqui-ai/TTS&quot;&gt;https://github.com/coqui-ai/TTS&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>음성 합성</category>
      <author>Ninestar</author>
      <guid isPermaLink="true">https://data-science.tistory.com/490</guid>
      <comments>https://data-science.tistory.com/490#entry490comment</comments>
      <pubDate>Sat, 5 Aug 2023 14:04:48 +0900</pubDate>
    </item>
    <item>
      <title>Text to Speech (TTS) 각종 모델</title>
      <link>https://data-science.tistory.com/470</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;717&quot; data-origin-height=&quot;62&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Y8xU7/btsovslLJcJ/ee5GWKxMrbjnINYDth7AF0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Y8xU7/btsovslLJcJ/ee5GWKxMrbjnINYDth7AF0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Y8xU7/btsovslLJcJ/ee5GWKxMrbjnINYDth7AF0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FY8xU7%2FbtsovslLJcJ%2Fee5GWKxMrbjnINYDth7AF0%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;602&quot; height=&quot;52&quot; data-origin-width=&quot;717&quot; data-origin-height=&quot;62&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h1&gt;Text Analysis&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문자 텍스트를 언어학적 특징을 추출합니다. 딥러닝 기반 음성합성에서는 이부분이 많이 간편해 졌고 text analysis부분을 별도로 취급하지 않고 간단한 전처리 정도로 생각합니다.&lt;br /&gt;&lt;b&gt;1. Text Normalization&lt;/b&gt;&lt;br /&gt;약자나 숫자로 되어 있는 부분을 발음나는대로 바꿔줍니다.&lt;br /&gt;&lt;b&gt;2. Word Segmentation&lt;/b&gt;&lt;br /&gt;중국어나 한국어 같은 문자 기반 언어에 필요한 기술입니다. 가방을 하나의 단어로 볼것인지 아니면 가, 방 이라고 볼것인지 문맥을 보고 결정합니다.&lt;br /&gt;&lt;b&gt;3. Part of Speech Tagging&lt;/b&gt;&lt;br /&gt;동사,명사,전치사, 조사 등 품사를 분석하는 기술,&lt;br /&gt;&lt;b&gt;4. Prosody Prediction&lt;/b&gt;&lt;br /&gt;텍스트를 보고 강세, 톤, 길이를 예측합니다.&lt;br /&gt;&lt;b&gt;5. Grapheme to Phoneme&lt;/b&gt;&lt;br /&gt;글자를 기반으로 단어의 발음을 생성합니다. 같은 단어일지라도 발음이 다른경우 존재. 영어(Chae18), 중국어(Park20), 한국어(Kim21d)등 open source.&lt;/p&gt;
&lt;h1&gt;Acoustic Model&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Character나 Phoneme를 입력으로 받아서 acoustic feature를 추출하는 모델입니다. 기존에는 HMM기반 모델이였지만 현재는 신경망 기반 모델들이 대세입니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Seq2seq based&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;DeepVoice3 : 바이두, CNN기반, 추후 Clarinet, ParaNet으로 발전.&lt;/li&gt;
&lt;li&gt;Tacotron2 : 구글, Mel-Spectrogram(사람의 청각의 특징을 좀 더 고려하여 FFT의 결과를 변형한 방식)을 중간 표현형으로 사용, style token을 학습하여 스타일이 컨트롤 되는 TTS&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Transformer based&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;TransformerTTS : Tacotron2의 RNN부분을 transformer로 바꾼모델, 병렬처리 가능-&amp;gt;속도 증가&lt;/li&gt;
&lt;li&gt;FastSpeech2 : 복잡한 어텐션 방식이 Speech에서는 단점. 어텐션대신 length regulator이용, 빠른속도로 Mel-Spectrogram을 생성&lt;/li&gt;
&lt;li&gt;Lightspeech : FastSpeech의 구조 최적화, 속도 향상&lt;/li&gt;
&lt;li&gt;MultiSpeech : 단점 극복을 위해 여러가지 테크닉 적용&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Flow based&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Flowtron : Tacotron개선, IAF(Inverse Autoregressive Flow)적용하여 Mel-Spectrogram생성&lt;/li&gt;
&lt;li&gt;Glow-TTS : 카카오, 텍스트와 Mel-Spectrogram간 매칭을 위해 다이나믹프로그래밍 이용&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;GAN based&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Multi-SpectroGAN : 적대적 훈련방법으로 Speech 스타일 훈련&lt;/li&gt;
&lt;li&gt;GANSpeech&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Diffusion based&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(Diffusion model은 data로부터 noise를 조금씩 더해가면서 data를 완전한 noise로 만드는 forward process(diffusion process)와 이와 반대로 noise로부터 조금씩 복원해가면서 data를 만들어내는 reverse process를 활용.)&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Diff-TTS : Diffusion 모델을 이용&lt;/li&gt;
&lt;li&gt;PriorGrad : 데이터의 통계량을 활용하여 prior분포 생성&lt;/li&gt;
&lt;li&gt;DiffGAN-TTS : Diffusion decoder를 사용, 적대적 훈련방법 사용&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Vocoder&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Acoustic Model에서 추출한 feature를 이용하여 waveform으로 바꿔주는 부분입니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;a href=&quot;https://blog.kakaocdn.net/dn/cmmygq/btqNllP4fri/2rEKUlPWrhB69ZB5cINXY0/img.gif&quot;&gt;Autoregressive&lt;/a&gt; Vocoders&lt;/h2&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;wavenet : 자연스러운 음성 파형을 직접 생성, 다양한 특징적인 음성을 생성&lt;/li&gt;
&lt;li&gt;sampleRNN : RNN방식으로 샘플을 하나씩 생성,&lt;/li&gt;
&lt;li&gt;FFTNet : WaveNet의 Dilated Convolution의 모양이 FFT와 유사한점 착안.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Flow based&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;IAF(Inverse Autoregressive Flow) : 훈련시간 오래걸리지만 생성속도 빠름.&lt;/li&gt;
&lt;li&gt;WaveGlow : affine coupling layer이용&lt;/li&gt;
&lt;li&gt;FloWaveNet : affine coupling layer이용&lt;/li&gt;
&lt;li&gt;WaveFlow : 여러 생성방식의 통합&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;GAN based&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;GAN-TTS : 랜덤 윈도우 여러개로 waveform feature를 캡쳐하는 판별기&lt;/li&gt;
&lt;li&gt;VocoGAN : 여러 해상도 판별기&lt;/li&gt;
&lt;li&gt;Parallel WaveGAN(non-autoregressive) : 네이버/라인, 가우시안 노이즈도 입력받음&lt;/li&gt;
&lt;li&gt;MelGAN&lt;/li&gt;
&lt;li&gt;BigVGAN : 서울대/NVIDIA, 다양한 녹음환경&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Diffusion based&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Diffusion 방식은 복잡한 데이터 분포를 학습할 수 있어 높은 품질의 결과를 낼 수 있습니다. 하지만 생성시간이 오래 걸립니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;FastDiff : time-aware location-variation convolution 제안&lt;/li&gt;
&lt;li&gt;BDDM : Forward Process에 schedule network, Reverse Process에 score network 사용, 생성속도 크게 향상&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Source-filter based&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;음파(source)가 구강구조를 거쳐(filtering) 우리가 듣는 목소리로 변한다고 생각하는 모델입니다. filter부분이 가장 중요한 부분입니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Neural Source filter : filter부분을 신경망 모델로 만듭니다. Non Autoregressive 방식, 속도 빠름&lt;/li&gt;
&lt;li&gt;ExcitNet : Speech의 f0(피치) 부분/ 그외 (excitation)을 나누어 처리,&lt;/li&gt;
&lt;li&gt;LPCNet : waveRNN에 Linear Prediction을 더한 모델.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Vocoder는 Autoregressive(품질은 좋지만 느린) 방식에서 Non-Autoregressive(빠르지만 품질은 조금 떨어진)방식으로 발전하고 있습니다. NAR 성능도 점점 AR수준에 다다르고 있습니다.&lt;/p&gt;
&lt;h1&gt;Fully End-to-End TTS&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Acoustic Model과 Vocoder를 함께 학습하여 텍스트나 음소(phoneme)를 waverform 오디오로 바로 만들어주는 한번에 전부 하는 모델. 훈련단계를 구분할 필요도 없고 에러도 줄어듭니다. Acoustic model에 Text Analysis, Vocoder를 붙여서 End-to-End 방식이라고 부릅니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/ming024/FastSpeech2&quot;&gt;FastSpeech 2&lt;/a&gt; : FastSpeech2(Acoustic model) + WaveNet(vocoder), 훈련의 어려움때문에 미리 만들어놓은 mel encoder를 활용&lt;/li&gt;
&lt;li&gt;Wave-Tacotron : Tacotron+WaveNet, flow방식&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/jaywalnut310/vits&quot;&gt;VITS&lt;/a&gt; : 카카오팀, Glow-TTS + HiFI-GAN, VAE이용, 적대적훈련 방식&lt;/li&gt;
&lt;li&gt;LiteTTS : 연세대/네이버, Feed Forward Transformer+HiFi GAN&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/imdanboy/jets&quot;&gt;JETS&lt;/a&gt; : 카카오, FastSpeec2 + HiFi-GAN&lt;/li&gt;
&lt;li&gt;DelightfulTTS 2 : Microsoft&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;아래부터는 실용적으로 사용되기 위해 고려해야할 사항, 연구, 발전중&lt;/b&gt;&lt;/p&gt;
&lt;h1&gt;Low-Resource TTS&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;TTS는 {텍스트-해당 스피치} 두가지가 쌍으로 있는 가공된 데이터가 많이 필요합니다. 가공되지 않은 데이터로 Semi-Supervised, Unsupervised 로 발전중.&lt;/p&gt;
&lt;h1&gt;Expressive TTS&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사람처럼 자연스러운 스피치를 만들어내기 위해 감정을 추가합니다.&lt;/p&gt;
&lt;h1&gt;Adaptative TTS&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;임의의 타겟 스피커의 목소리로 TTS를 만들어내는 기술입니다.(voice adaptation, voice cloning, custom voice)&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;AdaSpeech3 : Microsoft, 텍스트 없이 현실적인 스피치 데이터로만 학습&lt;/li&gt;
&lt;li&gt;Guided-TTS2: 서울대, speaker-conditional DDPM을 훈련후 약간의 데이터로 fine-tuning&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://speechresearch.github.io/adaspeech4/&quot;&gt;AdaSpeech&lt;/a&gt; 4 : zero-shot adaptation 성능 향상&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/Rongjiehuang/GenerSpeech&quot;&gt;GenerSpeech&lt;/a&gt;: zero-shot adaptation, 여러 레벨의 style adaptor로 캡쳐, mix-style layer normalization으로 분리&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;few-shot adaptation&lt;/b&gt; : 가능하면 적은 양의 스피치 데이터를 주고 이를 이용하여 모델을 다시 훈련하는 방식(fine-tuning). 최소 몇분(minutes)의 타겟 스피커의 스피치 데이터가 필요.&lt;br /&gt;&lt;b&gt;zero-shot adaptation&lt;/b&gt;: 아주 짧은 스피치 데이터에서 스타일을 추출후 바로 적용하게 하는 것&lt;/p&gt;</description>
      <category>음성 합성</category>
      <author>Ninestar</author>
      <guid isPermaLink="true">https://data-science.tistory.com/470</guid>
      <comments>https://data-science.tistory.com/470#entry470comment</comments>
      <pubDate>Fri, 21 Jul 2023 16:02:37 +0900</pubDate>
    </item>
    <item>
      <title>음성합성 Text-to-Speech(TTS) 역사</title>
      <link>https://data-science.tistory.com/468</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;글을 입력하면 텍스트를 목소리로 읽어주는 기술로 보편적으로 음성합성(text to speech)의 약자인 TTS로 불립니다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;최근에는 딥러닝 기반의 음성 합성 기술이 발전하면서 딥러닝 모델을 사용하여 자연스러운 음성을 생성할 수 있습니다.&lt;/p&gt;
&lt;h2 style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;TTS의 역사&lt;/h2&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. Articulatory Synthesis (조음 합성)&lt;/b&gt;&lt;br /&gt;&amp;nbsp; 인간의 성대 모델(입술, 혀, 성대)과 그 안에서 일어나는 조음 과정을 기반으로 음성을 합성하는 컴퓨터 기술, 혀, 턱, 입술과 같은 음성 조음기의 위치를 수정하는 것으로 공기의 흐름을 디지털 방식으로 시뮬레이션하여 만들어집니다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. formant Synthesis (포만트 합성)&lt;/b&gt;&lt;br /&gt;&amp;nbsp; 음성 샘플을 사용하지 않고 주파수 변조나 Physical Modelling과 같은 기술을 이용하여 소리를 생성하는 기술입니다. 사람의 소리는 음성 기관에서 소리를 필터링 해서 만들어내는데, 여러 필터의 조합을 사용하여 합성 음성을 얻을 수 있습니다. 자연스러운 사람의 목소리라기보다는 인공적이고 로봇처럼 들리는 소리를 만들어 냅니다. 이 기술은 자연스러움보다는 매우 빠른 속도로 음성을 합성하여 전달하는데 장점이 있습니다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3. Concatenative Synthesis (연결 합성)&lt;/b&gt;&lt;br /&gt;&amp;nbsp; 스피치 조각을 만들어놓고 연결해서 음성을 합성해 내는 기술입니다. 예를들어 0~9까지 각 숫자의 목소리를 녹음해놓으면 전화번호를 녹음된 목소리를 연결하여 불러줄 수 있습니다. 단점으로는 자연스러운 소리를 합성하기 위해 엄청난 용량의 DB가 확보되어야 하고, 다양한 목소리를 만들기 위해서는 그만큼 많은 시간이 소요됩니다. 비용과 용량에 비해 단어와 단어 간의 자연스러운 연결에서 아직까지는 한계가 명확한 상태입니다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;4. Statistical Parametric Speech Synthesis (통계 파라미터 합성)&lt;/b&gt;&lt;br /&gt;&amp;nbsp; Hidden Markov Model (HMM) 기반 합성은, 통계 파라미터 합성이라고도 불립니다. 음성의 주파수 스펙트럼, 기본 주파수, 지속시간 등이 HMM에 의해 동시에 모델링 되어 '최대우도 추정법'로 파라미터를 추측하여 음성을 생성해내는 기술이라고 합니다. text analysis(입력 텍스트를 언어학적 특징 추출), acoustic model(음향특징 추출), vocoder(음향특징-&amp;gt;음성으로 변경) 크게 3가지로 나눌 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;116&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bNlXDj/btsog1PsLXV/eEwi2xB6qrgOL2MbLACKYK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bNlXDj/btsog1PsLXV/eEwi2xB6qrgOL2MbLACKYK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bNlXDj/btsog1PsLXV/eEwi2xB6qrgOL2MbLACKYK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbNlXDj%2Fbtsog1PsLXV%2FeEwi2xB6qrgOL2MbLACKYK%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;1280&quot; height=&quot;116&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;116&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;5. Neural TTS&lt;/b&gt;&lt;br /&gt;&amp;nbsp; 녹음된 음성을 인공지능으로 학습시킨후 가장 자연스러운 인간의 목소리를 합성해 내는 기술입니다. 신경망기반 모델들은 HMM을 대체하여 'acoustic model' 부분에 쓰이게 됩니다. SPSS의 3가지 부분을 단순화 시키는 방향으로 발전중입니다. 아래 그림 0-&amp;gt;4로 발전중이라고 보시면 됩니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;392&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/k2fFR/btsog0CYx5z/Xs1DuQjSYZO0LCTrCnS9X1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/k2fFR/btsog0CYx5z/Xs1DuQjSYZO0LCTrCnS9X1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/k2fFR/btsog0CYx5z/Xs1DuQjSYZO0LCTrCnS9X1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fk2fFR%2Fbtsog0CYx5z%2FXs1DuQjSYZO0LCTrCnS9X1%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;1280&quot; height=&quot;392&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;392&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #1f2328; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Acoustic Model&lt;/b&gt;: 입력으로 character(텍스트)혹은 phoneme(음소; 발음단위)을 받아서 어떠한 acoustic feature를 추출하는 모델. acoustic feature는 mel-spectrogram을 의미합니다&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Vocoder&lt;/b&gt;: 입력으로 mel-spectrogram 및 유사한 스펙트로그램을 받아서 실제 오디오를 생성하는 모델.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Fully End-to-End TTS Model&lt;/b&gt;: 입력으로 character혹은 phoneme을 받아서 오디오를 바로 생성하는 모델.&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>음성 합성</category>
      <author>Ninestar</author>
      <guid isPermaLink="true">https://data-science.tistory.com/468</guid>
      <comments>https://data-science.tistory.com/468#entry468comment</comments>
      <pubDate>Thu, 20 Jul 2023 13:28:11 +0900</pubDate>
    </item>
    <item>
      <title>[Rust] mod와 파일 시스템</title>
      <link>https://data-science.tistory.com/450</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://data-science.tistory.com/341&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://data-science.tistory.com/341&lt;/a&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;러스트로 프로그램을 작성하기 시작했을때 코드는 오로지 main함수 안에만 있을지도 모릅니다. 코드가 커짐에 따라서, 재사용 및 더 나은 조직화를 위하여 결국 어떤 기능을 다른 함수로 이동시킬 것입니다. 코드를 더 작은 덩어리로 쪼갬으로서, 각각의 덩어리들은 개별적으로 이해하기 더 수월해집니다. 러스트는 조직화된 방식으로 코드의 재사용을 할 수 있게 해주는 모듈(module) 시스템을 갖추고 있습니다.&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;cargo를 이용해서 새로운 프로젝트를 만드는 것으로 모듈 예제를 시작하려고 하는데, 바이너리 크레이트( crate)를 만드는 대신에 라이브러리 크레이트를 만들 것입니다.(라이브러리 크레이트란 다른 사람들이 자신들의 프로젝트에 dependency)로 추가할 수 있는 프로젝트를 말합니다.)&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;몇가지 일반적인 네트워크 기능을 제공하는 라이브러리의 뼈대를 만듭니다. 여기서는 모듈들과 함수들의 조직화에 집중할 것이고, 함수의 본체에 어떤 코드가 들어가야 하는지는 신경쓰지 않겠습니다. 이 라이브러리를 communicator라고 할것입니다. 라이브러리를 만들기 위해서는 --bin대신 --lib 옵션을 사용하면 됩니다.&lt;/p&gt;
&lt;pre id=&quot;code_1689049136355&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ cargo new communicator --lib
$ cd communicator&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;cargo가&lt;span&gt;&amp;nbsp;&lt;/span&gt;src/main.rs&lt;span&gt;&amp;nbsp;&lt;/span&gt;대신&lt;span&gt;&amp;nbsp;&lt;/span&gt;src/lib.rs을 생성했음을 주목하세요.&lt;span&gt;&amp;nbsp;&lt;/span&gt;src/lib.rs&lt;span&gt;&amp;nbsp;&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;&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&gt;Filename: src/lib.rs&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;rust&quot;&gt;&lt;code&gt;#[cfg(test)]
mod tests {
    #[test]
    fn it_works() {
    }
}
&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;cargo는 우리가 만든 라이브러리의 작성 시작을 돕기 위해 빈 테스트를 만드는데, 이는&lt;span&gt;&amp;nbsp;&lt;/span&gt;--bin&lt;span&gt;&amp;nbsp;&lt;/span&gt;옵션을 사용했을때 &amp;ldquo;Hello, world!&amp;rdquo; 바이너리를 만들어준 것과 다릅니다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;src/main.rs&lt;span&gt;&amp;nbsp;&lt;/span&gt;파일이 없기 때문에,&lt;span&gt;&amp;nbsp;&lt;/span&gt;cargo run&lt;span&gt;&amp;nbsp;&lt;/span&gt;커맨드로 카고가 실행할 것이 없습니다. 따라서, 여기서는 라이브러리 크레이트의 코드를 컴파일하기 위해&lt;span&gt;&amp;nbsp;&lt;/span&gt;cargo build를 사용할 것입니다.&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 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;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;communicator&lt;span&gt;&amp;nbsp;&lt;/span&gt;네트워크 라이브러리를 위해서, 먼저&lt;span&gt;&amp;nbsp;&lt;/span&gt;connect라는 이름의 함수가 정의되어 있는&lt;span&gt;&amp;nbsp;&lt;/span&gt;network라는 이름의 모듈을 정의하겠습니다. 러스트 내 모듈 정의는 모두&lt;span&gt;&amp;nbsp;&lt;/span&gt;mod로 시작됩니다. 이 코드를&lt;span&gt;&amp;nbsp;&lt;/span&gt;src/lib.rs의 시작 부분, 즉 테스트 코드의 윗 쪽에 추가해봅시다.&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;&lt;span&gt;Filename: src/lib.rs&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1689049957346&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;mod network {
    fn connect() {
    }
}&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;mod&lt;span&gt;&amp;nbsp;&lt;/span&gt;키워드 뒤에, 모듈의 이름&lt;span&gt;&amp;nbsp;&lt;/span&gt;network가 쓰여지고 중괄호 안에 코드 블록이 옵니다. 이 블록 안의 모든 것은 이름공간&lt;span&gt;&amp;nbsp;&lt;/span&gt;network&lt;span&gt;&amp;nbsp;&lt;/span&gt;안에 있습니다. 위의 경우&lt;span&gt;&amp;nbsp;&lt;/span&gt;connect라는 이름의 함수 하나가 있습니다. 이 함수를&lt;span&gt;&amp;nbsp;&lt;/span&gt;network&lt;span&gt;&amp;nbsp;&lt;/span&gt;모듈 바깥의 스크립트에서 호출하고자 한다면, 우리는 모듈을 특정할 필요가 있으므로 이름공간 문법&lt;span&gt;&amp;nbsp;&lt;/span&gt;::를 이용해야 합니다:&lt;span&gt;&amp;nbsp;&lt;/span&gt;connect()&lt;span&gt;&amp;nbsp;&lt;/span&gt;이렇게만 하지 않고&lt;span&gt;&amp;nbsp;&lt;/span&gt;network::connect()&lt;span&gt;&amp;nbsp;&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&gt;&amp;nbsp;&lt;/span&gt;src/lib.rs&lt;span&gt;&amp;nbsp;&lt;/span&gt;파일 내에 여러 개의 모듈을 나란히 정의할 수도 있습니다. 예를 들어,&lt;span&gt;&amp;nbsp;&lt;/span&gt;connect라는 이름의 함수를 갖고 있는&lt;span&gt;&amp;nbsp;&lt;/span&gt;client&lt;span&gt;&amp;nbsp;&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;&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&gt;Filename: src/lib.rs&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1689050073045&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;mod network {
    fn connect() {
    }
}

mod client {
    fn connect() {
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Rust</category>
      <author>Ninestar</author>
      <guid isPermaLink="true">https://data-science.tistory.com/450</guid>
      <comments>https://data-science.tistory.com/450#entry450comment</comments>
      <pubDate>Sat, 15 Jul 2023 14:37:07 +0900</pubDate>
    </item>
    <item>
      <title>[Rust] 주석</title>
      <link>https://data-science.tistory.com/449</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;유용한 문서화 주석&amp;nbsp;&lt;/h2&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&gt;Filename: src/lib.rs&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;cpp&quot; style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;/// Adds one to the number given.
///
/// # Examples
///
/// ```
/// let five = 5;
///
/// assert_eq!(6, my_crate::add_one(5));
/// ```
pub fn add_one(x: i32) -&amp;gt; i32 {
    x + 1
}&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;cargo doc --open&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;을 실행시키면 현재 크레이트의 문서에 대해 (심지어 크레이트가 가진 모든 디펜던시의 문서까지) HTML 을 생성하고 웹 브라우저에 띄워줍니다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1578&quot; data-origin-height=&quot;911&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/biXJX2/btsm8KaIoDk/h98dDUX9kg74QTMTJrxu50/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/biXJX2/btsm8KaIoDk/h98dDUX9kg74QTMTJrxu50/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/biXJX2/btsm8KaIoDk/h98dDUX9kg74QTMTJrxu50/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbiXJX2%2Fbtsm8KaIoDk%2Fh98dDUX9kg74QTMTJrxu50%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;1578&quot; height=&quot;911&quot; data-origin-width=&quot;1578&quot; data-origin-height=&quot;911&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;h3 data-ke-size=&quot;size23&quot;&gt;자주 사용되는 구절&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Panics : 문서화된 기능이 패닉을 일으킬 수 있는 시나리오 입니다. 함수를 호출하는 사람들에게 &quot;프로그램이 패닉을 일으키지 않게 하려면 이러한 상황에서는 이 함수를 호출하지 않아야 합니다&quot; 라는 내용을 알려줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Error : 해당 함수가 Result를 반환할 경우에는 발생할 수 있는 에러의 종류와 해당 에러들이 발생하는 조건을 설명해 주어서 호출하는 사람이 여러 에러를 여러 방법으로 처리할 수 있도록 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- safety : 함수가 안전하지 않을(unsafe)의 경우에 왜 이 함수가 안전하지 않은지와 이 함수가 호출하는 사람에게 지키길 기대하는 불변성에 대해 알려주는 구절이 있어야 합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 id=&quot;주석을-포함하는-항목을-문서화-하기&quot; style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;주석을 포함하는 항목을 문서화 하기&lt;/h2&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;문서화 주석의 또 다른 스타일로&lt;span&gt;&amp;nbsp;&lt;/span&gt;//!&lt;span&gt;&amp;nbsp;&lt;/span&gt;가 있습니다. 이는 주석 뒤에 오는 항목을 문서화 하는게 아닌 주석을 포함하는 항목을 문서화 합니다. 일반적으로 크레이트의 루트 파일 (관례적으로&lt;span&gt;&amp;nbsp;&lt;/span&gt;src/lib.rs&lt;span&gt;&amp;nbsp;&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&gt;&amp;nbsp;&lt;/span&gt;add_one&lt;span&gt;&amp;nbsp;&lt;/span&gt;함수를 포함한&lt;span&gt;&amp;nbsp;&lt;/span&gt;my_crate&lt;span&gt;&amp;nbsp;&lt;/span&gt;크레이트를 설명하기 위한 목적으로 문서화를 진행한다면, src/lib.rs&lt;span&gt;&amp;nbsp;&lt;/span&gt;에&lt;span&gt;&amp;nbsp;&lt;/span&gt;//!&lt;span&gt;&amp;nbsp;&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&gt;Filename: src/lib.rs&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;1c&quot; style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;&lt;code&gt;//! # My Crate
//!
//! `my_crate` is a collection of utilities to make performing certain
//! calculations more convenient.

/// Adds one to the number given.
// --snip--&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;//!&lt;span&gt;&amp;nbsp;&lt;/span&gt;로 시작하는 줄 중 마지막 줄에 코드가 뒤따르지 않는다는 점을 주목하세요. 우린 주석 뒤에 따라오는 항목이 아닌, 주석을 포함하는 항목을 문서화 할 것이기에&lt;span&gt;&amp;nbsp;&lt;/span&gt;///&lt;span&gt;&amp;nbsp;&lt;/span&gt;가 아니라&lt;span&gt;&amp;nbsp;&lt;/span&gt;//!&lt;span&gt;&amp;nbsp;&lt;/span&gt;로 시작하는 주석을 사용했습니다. 이 경우, 주석을 포함하는 항목은 크레이트의 루트 파일인&lt;span&gt;&amp;nbsp;&lt;/span&gt;src/lib.rs&lt;span&gt;&amp;nbsp;&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;cargo doc --open&lt;span&gt;&amp;nbsp;&lt;/span&gt;을 실행하면, my_crate&lt;span&gt;&amp;nbsp;&lt;/span&gt;문서 첫 페이지 내용 중 크레이트의 공개 아이템들 상단에 이 주석의 내용이 표시될 것입니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2473&quot; data-origin-height=&quot;1096&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/6ly2C/btsm8XVcclW/34IVIaBJrYQMSWYpJEr8K1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/6ly2C/btsm8XVcclW/34IVIaBJrYQMSWYpJEr8K1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/6ly2C/btsm8XVcclW/34IVIaBJrYQMSWYpJEr8K1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F6ly2C%2Fbtsm8XVcclW%2F34IVIaBJrYQMSWYpJEr8K1%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;2473&quot; height=&quot;1096&quot; data-origin-width=&quot;2473&quot; data-origin-height=&quot;1096&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;</description>
      <category>Rust</category>
      <author>Ninestar</author>
      <guid isPermaLink="true">https://data-science.tistory.com/449</guid>
      <comments>https://data-science.tistory.com/449#entry449comment</comments>
      <pubDate>Thu, 13 Jul 2023 13:26:47 +0900</pubDate>
    </item>
    <item>
      <title>노르웨이 멘사테스트</title>
      <link>https://data-science.tistory.com/453</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;아버지께서 인터넷으로 IQ검사 하는데 유료라고 하셔서 무료 검사 찾아보다가 노르웨이, 스웨덴, 덴마크, 헝가리 멘사 샘플이 있다는것을 알게 됐고 그중 노르웨이 멘사 테스를 찾은김에 점심시간에 잠 깰겸 해봤습니다.&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://test.mensa.no/&quot;&gt;https://test.mensa.no/&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1689135373035&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;IQ Test Made by Mensa Norway - Mensa Norway&quot; data-og-description=&quot;You are anonymous! We collect anonymised IQ test data for use in statistics. However, we do not collect any personally identifiable information (PII), nor do we use tracking. The only exception is that we calculate and store technical fingerprints for the &quot; data-og-host=&quot;test.mensa.no&quot; data-og-source-url=&quot;https://test.mensa.no/&quot; data-og-url=&quot;https://test.mensa.no/&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://test.mensa.no/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://test.mensa.no/&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;IQ Test Made by Mensa Norway - Mensa Norway&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;You are anonymous! We collect anonymised IQ test data for use in statistics. However, we do not collect any personally identifiable information (PII), nor do we use tracking. The only exception is that we calculate and store technical fingerprints for the&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;test.mensa.no&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: justify;&quot;&gt;멘사 노르웨이의 테스트입니다. &lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: justify;&quot;&gt;이 테스트의 결과값은 표준편차 15로 나옵니다. 이 결과값으로는 130이 멘사 커트라인입니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;총 35문제이고 25분의 시간이 주어집니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&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-origin-width=&quot;1287&quot; data-origin-height=&quot;724&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/HL6ms/btsng7pK3uo/KQRRogJimC316q9XThFAck/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/HL6ms/btsng7pK3uo/KQRRogJimC316q9XThFAck/img.png&quot; data-alt=&quot;나이를 선택하세요&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/HL6ms/btsng7pK3uo/KQRRogJimC316q9XThFAck/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FHL6ms%2Fbtsng7pK3uo%2FKQRRogJimC316q9XThFAck%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;1287&quot; height=&quot;724&quot; data-origin-width=&quot;1287&quot; data-origin-height=&quot;724&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;나이를 선택하세요&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1279&quot; data-origin-height=&quot;1152&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/3hGmO/btsngNE54v2/9E30jlTFzJCk0o7HeJ0fkk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/3hGmO/btsngNE54v2/9E30jlTFzJCk0o7HeJ0fkk/img.png&quot; data-alt=&quot;Start the test로 검사를 시작하세요&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/3hGmO/btsngNE54v2/9E30jlTFzJCk0o7HeJ0fkk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F3hGmO%2FbtsngNE54v2%2F9E30jlTFzJCk0o7HeJ0fkk%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;1279&quot; height=&quot;1152&quot; data-origin-width=&quot;1279&quot; data-origin-height=&quot;1152&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Start the test로 검사를 시작하세요&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1430&quot; data-origin-height=&quot;1039&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/PwpLD/btsngs8WDWB/feYRK2syKEnh1kpD1AGyKK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/PwpLD/btsngs8WDWB/feYRK2syKEnh1kpD1AGyKK/img.png&quot; data-alt=&quot;보기에서 정답이라고 생각되는것을 클릭하면 다음 문제로 자동으로 넘어갑니다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/PwpLD/btsngs8WDWB/feYRK2syKEnh1kpD1AGyKK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FPwpLD%2Fbtsngs8WDWB%2FfeYRK2syKEnh1kpD1AGyKK%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;1430&quot; height=&quot;1039&quot; data-origin-width=&quot;1430&quot; data-origin-height=&quot;1039&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1378&quot; data-origin-height=&quot;456&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/byOl7c/btsnnUbvb6i/6kvX8xJ9nDKMB4biN21RWk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/byOl7c/btsnnUbvb6i/6kvX8xJ9nDKMB4biN21RWk/img.png&quot; data-alt=&quot;35문제 다 풀면 결과가 나오는데 엉망으로 풀면 측정 범위를 벗어났다고 뜹니다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/byOl7c/btsnnUbvb6i/6kvX8xJ9nDKMB4biN21RWk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbyOl7c%2FbtsnnUbvb6i%2F6kvX8xJ9nDKMB4biN21RWk%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;1378&quot; height=&quot;456&quot; data-origin-width=&quot;1378&quot; data-origin-height=&quot;456&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;35문제 다 풀면 결과가 나오는데 엉망으로 풀면 측정 범위를 벗어났다고 뜹니다.&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1052&quot; data-origin-height=&quot;1103&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dJNsio/btsnhdcA1Zv/eXkJsexkdwk5s7sKqDaxwK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dJNsio/btsnhdcA1Zv/eXkJsexkdwk5s7sKqDaxwK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dJNsio/btsnhdcA1Zv/eXkJsexkdwk5s7sKqDaxwK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdJNsio%2FbtsnhdcA1Zv%2FeXkJsexkdwk5s7sKqDaxwK%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;1052&quot; height=&quot;1103&quot; data-origin-width=&quot;1052&quot; data-origin-height=&quot;1103&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시간이 촉박해서 마지막 몇문제는 찍었습니다ㅠ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;20년전 학교에서 정식으로 검사했던거랑 비슷하게 나오는거 보니 정확도가 높은편 같습니다.&lt;/p&gt;</description>
      <category>이슈</category>
      <author>Ninestar</author>
      <guid isPermaLink="true">https://data-science.tistory.com/453</guid>
      <comments>https://data-science.tistory.com/453#entry453comment</comments>
      <pubDate>Wed, 12 Jul 2023 13:31:29 +0900</pubDate>
    </item>
    <item>
      <title>부산 대중교통 요금 4.5만 초과 환급(동백패스)</title>
      <link>https://data-science.tistory.com/451</link>
      <description>&lt;p style=&quot;text-align: right;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://v.daum.net/v/20230710180135880&quot;&gt;https://v.daum.net/v/20230710180135880&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;660&quot; data-origin-height=&quot;800&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cysakW/btsngs7RcQW/5XlvMe7vYSXUhiOfDXHjP0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cysakW/btsngs7RcQW/5XlvMe7vYSXUhiOfDXHjP0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cysakW/btsngs7RcQW/5XlvMe7vYSXUhiOfDXHjP0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcysakW%2Fbtsngs7RcQW%2F5XlvMe7vYSXUhiOfDXHjP0%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;660&quot; height=&quot;800&quot; data-origin-width=&quot;660&quot; data-origin-height=&quot;800&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;720&quot; data-origin-height=&quot;2065&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/FDKNN/btsngvXONvr/rb437Gnxi7zEd6ThslZEM0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/FDKNN/btsngvXONvr/rb437Gnxi7zEd6ThslZEM0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/FDKNN/btsngvXONvr/rb437Gnxi7zEd6ThslZEM0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FFDKNN%2FbtsngvXONvr%2Frb437Gnxi7zEd6ThslZEM0%2Fimg.jpg&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;720&quot; height=&quot;2065&quot; data-origin-width=&quot;720&quot; data-origin-height=&quot;2065&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;954&quot; data-origin-height=&quot;314&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/yWuAy/btsngraf8u2/kHNKeNB7EbpWr7umNRXUH1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/yWuAy/btsngraf8u2/kHNKeNB7EbpWr7umNRXUH1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/yWuAy/btsngraf8u2/kHNKeNB7EbpWr7umNRXUH1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FyWuAy%2Fbtsngraf8u2%2FkHNKeNB7EbpWr7umNRXUH1%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;954&quot; height=&quot;314&quot; data-origin-width=&quot;954&quot; data-origin-height=&quot;314&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4.5만 초과시 최대 9만원까지 환급을 해주네요&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를들어 이번달에 대중교통 8만원을사용했으면 3만5천원을 환급해준대요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;환승시 추가요금 발생하는 김해경전철, 동해선도 포함이랍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;부산은행 동백전은 8월부터 시행하고 하나은행, 농협은 10월부터 서비스 예정이라네요.&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 style=&quot;text-align: right;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>이슈</category>
      <category>동백패스</category>
      <category>부산 대중교통</category>
      <author>Ninestar</author>
      <guid isPermaLink="true">https://data-science.tistory.com/451</guid>
      <comments>https://data-science.tistory.com/451#entry451comment</comments>
      <pubDate>Tue, 11 Jul 2023 15:45:11 +0900</pubDate>
    </item>
    <item>
      <title>[C++] 동영상 YOLOv8 detection ONNX모델 추론(openCV)</title>
      <link>https://data-science.tistory.com/439</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/ultralytics/ultralytics/blob/8a11eda4a9a8cf94b17f7cae4c58099d538926a4/examples/YOLOv8-CPP-Inference/main.cpp&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://github.com/ultralytics/ultralytics/blob/8a11eda4a9a8cf94b17f7cae4c58099d538926a4/examples/YOLOv8-CPP-Inference/main.cpp&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1688469169391&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 - ultralytics/ultralytics: NEW - YOLOv8   in PyTorch &amp;gt; ONNX &amp;gt; CoreML &amp;gt; TFLite&quot; data-og-description=&quot;NEW - YOLOv8   in PyTorch &amp;gt; ONNX &amp;gt; CoreML &amp;gt; TFLite - GitHub - ultralytics/ultralytics: NEW - YOLOv8   in PyTorch &amp;gt; ONNX &amp;gt; CoreML &amp;gt; TFLite&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/ultralytics/ultralytics/blob/8a11eda4a9a8cf94b17f7cae4c58099d538926a4/examples/YOLOv8-CPP-Inference/main.cpp&quot; data-og-url=&quot;https://github.com/ultralytics/ultralytics&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/nzG9g/hyTcEpB7TF/ilXCi6C1tdzebGcUIZ9RVK/img.png?width=1920&amp;amp;height=540&amp;amp;face=0_0_1920_540&quot;&gt;&lt;a href=&quot;https://github.com/ultralytics/ultralytics/blob/8a11eda4a9a8cf94b17f7cae4c58099d538926a4/examples/YOLOv8-CPP-Inference/main.cpp&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/ultralytics/ultralytics/blob/8a11eda4a9a8cf94b17f7cae4c58099d538926a4/examples/YOLOv8-CPP-Inference/main.cpp&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/nzG9g/hyTcEpB7TF/ilXCi6C1tdzebGcUIZ9RVK/img.png?width=1920&amp;amp;height=540&amp;amp;face=0_0_1920_540');&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 - ultralytics/ultralytics: NEW - YOLOv8   in PyTorch &amp;gt; ONNX &amp;gt; CoreML &amp;gt; TFLite&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;NEW - YOLOv8   in PyTorch &amp;gt; ONNX &amp;gt; CoreML &amp;gt; TFLite - GitHub - ultralytics/ultralytics: NEW - YOLOv8   in PyTorch &amp;gt; ONNX &amp;gt; CoreML &amp;gt; TFLite&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;YOLOv8 github참조해서 동영상 파일에서 객체 검출을 진행합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컴파일 전에 opencv라이브러리를 설치합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;동영상 파일을 decode하여 프레임마다 onnx모델추론을 진행합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;onnxruntime 라이브러리를 따로 안쓰고 opencv의&amp;nbsp; cv::dnn::readNetFromONNX 함수를 사용합니다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1688469153322&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 컴파일 명령어
// g++ main.cpp -o test `pkg-config opencv4 --cflags --libs`

// pt,onnx 모델 다운로드 opset 12로 해야 에러가 안납니다.
// yolo export model=yolov8n.pt imgsz=480,640 format=onnx opset=12

#include &amp;lt;iostream&amp;gt;
#include &amp;lt;vector&amp;gt;
#include &amp;lt;getopt.h&amp;gt;
#include &amp;lt;ctime&amp;gt;
#include &amp;lt;opencv2/opencv.hpp&amp;gt;
#include &quot;inference.h&quot;

using namespace std;
using namespace cv;
clock_t input_start, input_end, run_start, run_end, output_start, output_end, draw_start, draw_end, total_start, total_end;
double input_duration, run_duration, output_duration, draw_duration, total_duration;
Inference::Inference(const std::string &amp;amp;onnxModelPath, const cv::Size &amp;amp;modelInputShape, const std::string &amp;amp;classesTxtFile, const bool &amp;amp;runWithCuda)
{
    modelPath = onnxModelPath;
    modelShape = modelInputShape;
    classesPath = classesTxtFile;
    cudaEnabled = runWithCuda;

    loadOnnxNetwork();
    // loadClassesFromFile(); The classes are hard-coded for this example
}

std::vector&amp;lt;Detection&amp;gt; Inference::runInference(const cv::Mat &amp;amp;input)
{
    cv::Mat modelInput = input;
    if (letterBoxForSquare &amp;amp;&amp;amp; modelShape.width == modelShape.height)
        modelInput = formatToSquare(modelInput);

    // prepare input data 시간 체크
    cv::Mat blob;
    input_start = clock();
    cv::dnn::blobFromImage(modelInput, blob, 1.0 / 255.0, modelShape, cv::Scalar(), true, false);
    input_end = clock();
    input_duration = (double)(input_end - input_start) / CLOCKS_PER_SEC;
    cout &amp;lt;&amp;lt; &quot;input time:&quot; &amp;lt;&amp;lt; input_duration &amp;lt;&amp;lt; &quot;초&quot; &amp;lt;&amp;lt; endl;

    // model run 시간체크
    run_start = clock();
    net.setInput(blob);
    std::vector&amp;lt;cv::Mat&amp;gt; outputs;
    net.forward(outputs, net.getUnconnectedOutLayersNames());

    int rows = outputs[0].size[1];
    int dimensions = outputs[0].size[2];
    run_end = clock();
    run_duration = (double)(run_end - run_start) / CLOCKS_PER_SEC;
    cout &amp;lt;&amp;lt; &quot;run time:&quot; &amp;lt;&amp;lt; run_duration &amp;lt;&amp;lt; &quot;초&quot; &amp;lt;&amp;lt; endl;

    // output 시간체크
    output_start = clock();
    bool yolov8 = false;
    // yolov5 has an output of shape (batchSize, 25200, 85) (Num classes + box[x,y,w,h] + confidence[c])
    // yolov8 has an output of shape (batchSize, 84,  8400) (Num classes + box[x,y,w,h])
    if (dimensions &amp;gt; rows) // Check if the shape[2] is more than shape[1] (yolov8)
    {
        yolov8 = true;
        rows = outputs[0].size[2];
        dimensions = outputs[0].size[1];

        outputs[0] = outputs[0].reshape(1, dimensions);
        cv::transpose(outputs[0], outputs[0]);
    }
    float *data = (float *)outputs[0].data;

    float x_factor = modelInput.cols / modelShape.width;
    float y_factor = modelInput.rows / modelShape.height;

    std::vector&amp;lt;int&amp;gt; class_ids;
    std::vector&amp;lt;float&amp;gt; confidences;
    std::vector&amp;lt;cv::Rect&amp;gt; boxes;

    for (int i = 0; i &amp;lt; rows; ++i)
    {
        if (yolov8)
        {
            float *classes_scores = data + 4;

            cv::Mat scores(1, classes.size(), CV_32FC1, classes_scores);
            cv::Point class_id;
            double maxClassScore;

            minMaxLoc(scores, 0, &amp;amp;maxClassScore, 0, &amp;amp;class_id);

            if (class_id.x == 0)
            {
                if (maxClassScore &amp;gt; modelScoreThreshold)
                {
                    confidences.push_back(maxClassScore);
                    class_ids.push_back(class_id.x);

                    float x = data[0];
                    float y = data[1];
                    float w = data[2];
                    float h = data[3];

                    int left = int((x - 0.5 * w) * x_factor);
                    int top = int((y - 0.5 * h) * y_factor);

                    int width = int(w * x_factor);
                    int height = int(h * y_factor);

                    boxes.push_back(cv::Rect(left, top, width, height));
                }
            }
        }
        else // yolov5
        {
            float confidence = data[4];

            if (confidence &amp;gt;= modelConfidenceThreshold)
            {
                float *classes_scores = data + 5;

                cv::Mat scores(1, classes.size(), CV_32FC1, classes_scores);
                cv::Point class_id;
                double max_class_score;

                minMaxLoc(scores, 0, &amp;amp;max_class_score, 0, &amp;amp;class_id);

                if (max_class_score &amp;gt; modelScoreThreshold)
                {
                    confidences.push_back(confidence);
                    class_ids.push_back(class_id.x);

                    float x = data[0];
                    float y = data[1];
                    float w = data[2];
                    float h = data[3];

                    int left = int((x - 0.5 * w) * x_factor);
                    int top = int((y - 0.5 * h) * y_factor);

                    int width = int(w * x_factor);
                    int height = int(h * y_factor);

                    boxes.push_back(cv::Rect(left, top, width, height));
                }
            }
        }

        data += dimensions;
    }

    std::vector&amp;lt;int&amp;gt; nms_result;
    cv::dnn::NMSBoxes(boxes, confidences, modelScoreThreshold, modelNMSThreshold, nms_result);

    std::vector&amp;lt;Detection&amp;gt; detections{};
    for (unsigned long i = 0; i &amp;lt; nms_result.size(); ++i)
    {
        int idx = nms_result[i];

        Detection result;
        result.class_id = class_ids[idx];
        result.confidence = confidences[idx];

        std::random_device rd;
        std::mt19937 gen(rd());
        std::uniform_int_distribution&amp;lt;int&amp;gt; dis(100, 255);
        result.color = cv::Scalar(dis(gen),
                                  dis(gen),
                                  dis(gen));

        result.className = classes[result.class_id];
        result.box = boxes[idx];

        detections.push_back(result);
    }
    output_end = clock();
    output_duration = (double)(output_end - output_start) / CLOCKS_PER_SEC;
    cout &amp;lt;&amp;lt; &quot;output time:&quot; &amp;lt;&amp;lt; output_duration &amp;lt;&amp;lt; &quot;초&quot; &amp;lt;&amp;lt; endl;
    return detections;
}

void Inference::loadClassesFromFile()
{
    std::ifstream inputFile(classesPath);
    if (inputFile.is_open())
    {
        std::string classLine;
        while (std::getline(inputFile, classLine))
            classes.push_back(classLine);
        inputFile.close();
    }
}

void Inference::loadOnnxNetwork()
{
    net = cv::dnn::readNetFromONNX(modelPath);
    if (cudaEnabled)
    {
        std::cout &amp;lt;&amp;lt; &quot;\nRunning on CUDA&quot; &amp;lt;&amp;lt; std::endl;
        net.setPreferableBackend(cv::dnn::DNN_BACKEND_CUDA);
        net.setPreferableTarget(cv::dnn::DNN_TARGET_CUDA);
    }
    else
    {
        std::cout &amp;lt;&amp;lt; &quot;\nRunning on CPU&quot; &amp;lt;&amp;lt; std::endl;
        net.setPreferableBackend(cv::dnn::DNN_BACKEND_OPENCV);
        net.setPreferableTarget(cv::dnn::DNN_TARGET_CPU);
    }
}

cv::Mat Inference::formatToSquare(const cv::Mat &amp;amp;source)
{
    int col = source.cols;
    int row = source.rows;
    int _max = MAX(col, row);
    cv::Mat result = cv::Mat::zeros(_max, _max, CV_8UC3);
    source.copyTo(result(cv::Rect(0, 0, col, row)));
    return result;
}

int main(int argc, char **argv)
{
    int count = 0;
    bool runOnGPU = true;
    std::string projectBasePath = &quot;/home/yimstar9/github/ObjectTracking&quot;; // Set your ultralytics base path
    std::string videoPath = &quot;../../data/crowd.mp4&quot;;
    Inference inf(&quot;yolov8n.onnx&quot;, cv::Size(640, 640), &quot;classes.txt&quot;, runOnGPU);

    cv::VideoCapture cap(videoPath);
    if (!cap.isOpened())
    {
        std::cout &amp;lt;&amp;lt; &quot;동영상 파일을 열 수 없습니다.&quot; &amp;lt;&amp;lt; std::endl;
        return -1;
    }
    total_start = clock();

    // 동영상 파일에서 첫 번째 프레임 가져오기
    cv::Mat frame;
    cap.read(frame);
    // cv::namedWindow(&quot;Video&quot;, cv::WINDOW_NORMAL);
    // cv::resizeWindow(&quot;Video&quot;, frame.cols, frame.rows);

    // 동영상 프레임 표시 반복
    while (true)
    {
        count += 1;
        std::cout &amp;lt;&amp;lt; &quot;frame: &quot; &amp;lt;&amp;lt; count &amp;lt;&amp;lt; std::endl;
        // Inference starts here...
        std::vector&amp;lt;Detection&amp;gt; output = inf.runInference(frame);

        int detections = output.size();

        // 그리기 시간 체크
        draw_start = clock();
        for (int i = 0; i &amp;lt; detections; ++i)
        {
            Detection detection = output[i];
            cv::Rect box = detection.box;
            cv::Scalar color = detection.color;

            // Detection box
            cv::rectangle(frame, box, color, 2);

            // Detection box text
            std::string classString = detection.className + ' ' + std::to_string(detection.confidence).substr(0, 4);
            cv::Size textSize = cv::getTextSize(classString, cv::FONT_HERSHEY_DUPLEX, 1, 2, 0);
            cv::Rect textBox(box.x, box.y - 40, textSize.width + 10, textSize.height + 20);

            cv::rectangle(frame, textBox, color, cv::FILLED);
            cv::putText(frame, classString, cv::Point(box.x + 5, box.y - 10), cv::FONT_HERSHEY_DUPLEX, 1, cv::Scalar(0, 0, 0), 2, 0);
        }
        // 현재 프레임 표시
        cv::imshow(&quot;Video&quot;, frame);
        draw_end = clock();
        draw_duration = (double)(draw_end - draw_start) / CLOCKS_PER_SEC;
        cout &amp;lt;&amp;lt; &quot;draw time:&quot; &amp;lt;&amp;lt; draw_duration &amp;lt;&amp;lt; &quot;초&quot; &amp;lt;&amp;lt; endl;

        // 다음 프레임 가져오기
        cap.read(frame);

        // 동영상 재생 완료 시 반복 종료
        if (frame.empty())
        {
            break;
        }

        // 키 입력 대기 (30ms)
        if (cv::waitKey(30) == 27)
        { // ESC 키를 누르면 종료
            break;
        }
    }

    total_end = clock();
    total_duration = (double)(total_end - total_start) / CLOCKS_PER_SEC;
    cout &amp;lt;&amp;lt; &quot;total time:&quot; &amp;lt;&amp;lt; total_duration &amp;lt;&amp;lt; &quot;초&quot; &amp;lt;&amp;lt; endl;
    // 창 닫기
    // cv::destroyAllWindows();

    return 0;
}&lt;/code&gt;&lt;/pre&gt;</description>
      <category>C++</category>
      <author>Ninestar</author>
      <guid isPermaLink="true">https://data-science.tistory.com/439</guid>
      <comments>https://data-science.tistory.com/439#entry439comment</comments>
      <pubDate>Tue, 11 Jul 2023 11:16:31 +0900</pubDate>
    </item>
    <item>
      <title>[C++] Visual Studio Code에서 C++환경 만들기 (Linux)</title>
      <link>https://data-science.tistory.com/438</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;석사 초반에 C++잠깐 건드려 보고 처음 해보는 C++입니다. 그때 당시에도 되게 불편했었는데 오늘 또 한번 느끼네요. 최근에 파이썬과 러스트만 다뤘는데 파이썬이 얼마나 편한 언어인지, 초보자도 쉽게 배울수 있는 언어라는걸 다시한번 깨닫게 되네요.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;C++컴파일러 설치&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;build-essential 패키지를 설치하면 gcc, g++ 등 컴파일에 필요한 패키지들이 설치됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1688467412653&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ sudo apt-get install  build-essential&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;background-color: #ffffff; color: #444444; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Visual Studio Code 설치&lt;/span&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;curl을 설치해줍니다. 이미 설치되어 있다고 메시지가 보일 수도 있습니다.&amp;nbsp;&lt;/span&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1688467497170&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ sudo apt-get install curl&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;마이크로소프트 GPG 키를 다운로드하여 /etc/apt/trusted.gpg.d/ 경로에 복사해줍니다.&lt;/span&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1688467528291&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ sudo sh -c 'curl https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor &amp;gt; /etc/apt/trusted.gpg.d/microsoft.gpg'&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Visual Studio Code를 다운로드 받기 위한 저장소를 추가합니다.&lt;/span&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1688467537132&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ sudo sh -c 'echo &quot;deb [arch=amd64] https://packages.microsoft.com/repos/vscode stable main&quot; &amp;gt; /etc/apt/sources.list.d/vscode.list'&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;br /&gt;&lt;br /&gt;&lt;/b&gt;&lt;/p&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;추가한 저장소로부터 패키지 목록을 가져옵니다.&lt;/span&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1688467542783&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ sudo apt update&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Visual Studio Code를 설치합니다.&lt;/span&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1688467553659&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ sudo apt install code&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;프로젝트 생성 및 파일 생성&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;새프로젝트를 생성하고 새파일을 추가하여 OO.cpp파일명을 입력합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;cpp파일에 아래 내용을 입력합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;언어 처음 배우거나 실행할땐 항상 hello world죠 ㅎ&lt;/p&gt;
&lt;pre id=&quot;code_1688467737068&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;iostream&amp;gt;

using namespace std;

int main()
{
    cout &amp;lt;&amp;lt; &quot;Hello, World!&quot; &amp;lt;&amp;lt; endl;

    return 0;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;C++언어 확장 지원 설치&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Ctrl + Shift + X를 누르고 C++을 입력합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;검색된 리스트에서&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;C/C++&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;Extension Pack&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;항목에 있는 파란색&amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;설치&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;를 클릭합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;401&quot; data-origin-height=&quot;352&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dTZ8sL/btsmrBL4Bxl/nzwOd4WXj41FVdiOizCt41/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dTZ8sL/btsmrBL4Bxl/nzwOd4WXj41FVdiOizCt41/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dTZ8sL/btsmrBL4Bxl/nzwOd4WXj41FVdiOizCt41/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdTZ8sL%2FbtsmrBL4Bxl%2FnzwOd4WXj41FVdiOizCt41%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;401&quot; height=&quot;352&quot; data-origin-width=&quot;401&quot; data-origin-height=&quot;352&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Ctrl+Shift+P를 눌러 C/C++을 입력한후 &lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;&amp;ldquo;C/C++: Select a Configuration...&amp;rdquo;을 선택합니다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;865&quot; data-origin-height=&quot;517&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/buCih0/btsmr3adS0D/Ki1itkez8BcmFLZvkGVdCk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/buCih0/btsmr3adS0D/Ki1itkez8BcmFLZvkGVdCk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/buCih0/btsmr3adS0D/Ki1itkez8BcmFLZvkGVdCk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbuCih0%2Fbtsmr3adS0D%2FKi1itkez8BcmFLZvkGVdCk%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;865&quot; height=&quot;517&quot; data-origin-width=&quot;865&quot; data-origin-height=&quot;517&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;Edit Configuration(UI)를 선택합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;865&quot; data-origin-height=&quot;156&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bW4NWQ/btsmscdEV98/KTsKIGDVuSEQK8XltIGTO1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bW4NWQ/btsmscdEV98/KTsKIGDVuSEQK8XltIGTO1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bW4NWQ/btsmscdEV98/KTsKIGDVuSEQK8XltIGTO1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbW4NWQ%2FbtsmscdEV98%2FKTsKIGDVuSEQK8XltIGTO1%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;865&quot; height=&quot;156&quot; data-origin-width=&quot;865&quot; data-origin-height=&quot;156&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;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;헤더파일 인식하여 작성한 코드에 유용한 정보를 제공하기 위해 필요한 작업입니다.&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;g++을 선택해주세요.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1191&quot; data-origin-height=&quot;186&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Jh0XO/btsmsztbgD2/1xOBYq587jyfEM64w6UoiK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Jh0XO/btsmsztbgD2/1xOBYq587jyfEM64w6UoiK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Jh0XO/btsmsztbgD2/1xOBYq587jyfEM64w6UoiK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FJh0XO%2FbtsmsztbgD2%2F1xOBYq587jyfEM64w6UoiK%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;1191&quot; height=&quot;186&quot; data-origin-width=&quot;1191&quot; data-origin-height=&quot;186&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;IntelliSense 모드로 사용하는 운영체제에 따라서&amp;nbsp; linux-gcc-x64를 선택하세요.&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1178&quot; data-origin-height=&quot;272&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nGKWP/btsmsQBqlNb/pRxUrG1Z3WmZ6r4Q6s3aQ0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nGKWP/btsmsQBqlNb/pRxUrG1Z3WmZ6r4Q6s3aQ0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nGKWP/btsmsQBqlNb/pRxUrG1Z3WmZ6r4Q6s3aQ0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FnGKWP%2FbtsmsQBqlNb%2FpRxUrG1Z3WmZ6r4Q6s3aQ0%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;1178&quot; height=&quot;272&quot; data-origin-width=&quot;1178&quot; data-origin-height=&quot;272&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;추가로 사용할 헤더파일의 경로를 추가합니다.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1181&quot; data-origin-height=&quot;339&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/7gMvJ/btsmtNRZ0SL/QTchWn9m08A8DL2ATTk2Zk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/7gMvJ/btsmtNRZ0SL/QTchWn9m08A8DL2ATTk2Zk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/7gMvJ/btsmtNRZ0SL/QTchWn9m08A8DL2ATTk2Zk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F7gMvJ%2FbtsmtNRZ0SL%2FQTchWn9m08A8DL2ATTk2Zk%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;1181&quot; height=&quot;339&quot; data-origin-width=&quot;1181&quot; data-origin-height=&quot;339&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;사용할 C 및 C++ 표준을 지정할 수 있습니다.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1181&quot; data-origin-height=&quot;339&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/HQjvT/btsmsR1oetN/AilUeRhTRkT3qTwdhWU4tk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/HQjvT/btsmsR1oetN/AilUeRhTRkT3qTwdhWU4tk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/HQjvT/btsmsR1oetN/AilUeRhTRkT3qTwdhWU4tk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FHQjvT%2FbtsmsR1oetN%2FAilUeRhTRkT3qTwdhWU4tk%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;1181&quot; height=&quot;339&quot; data-origin-width=&quot;1181&quot; data-origin-height=&quot;339&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;b&gt;UI에서 설정을 마치고 탭을 닫으면 .vscode폴더에 c_cpp_properties.json파일이&amp;nbsp;추가되어&amp;nbsp;있습니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;코드 컴파일 및 실행&lt;/b&gt;&lt;/h2&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; Termianl&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt; &amp;gt; Configure Tasks&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;을 선택합니다.&lt;/span&gt;&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;create tasks.json file from template을 선택합니다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;876&quot; data-origin-height=&quot;206&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/CYjLR/btsmr3H4cNd/NwJg18PPPZYKzqgGpVjC9K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/CYjLR/btsmr3H4cNd/NwJg18PPPZYKzqgGpVjC9K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/CYjLR/btsmr3H4cNd/NwJg18PPPZYKzqgGpVjC9K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FCYjLR%2Fbtsmr3H4cNd%2FNwJg18PPPZYKzqgGpVjC9K%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;876&quot; height=&quot;206&quot; data-origin-width=&quot;876&quot; data-origin-height=&quot;206&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Others를 선택합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;876&quot; data-origin-height=&quot;206&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dU7unI/btsmmPYrrt2/WiXgQsrhWW3dVkdmRPB9NK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dU7unI/btsmmPYrrt2/WiXgQsrhWW3dVkdmRPB9NK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dU7unI/btsmmPYrrt2/WiXgQsrhWW3dVkdmRPB9NK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdU7unI%2FbtsmmPYrrt2%2FWiXgQsrhWW3dVkdmRPB9NK%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;876&quot; height=&quot;206&quot; data-origin-width=&quot;876&quot; data-origin-height=&quot;206&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;.vscode폴더에 tasks.json파일이 추가가 됩니다.&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;tasks.json 내용을 다음으로 교체하고 Ctrl + S를 눌러서 저장합니다&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1688468572951&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;{
    &quot;version&quot;: &quot;2.0.0&quot;,
    &quot;runner&quot;: &quot;terminal&quot;,
    &quot;type&quot;: &quot;shell&quot;,
    &quot;echoCommand&quot;: true,
    &quot;presentation&quot; : { &quot;reveal&quot;: &quot;always&quot; },
    &quot;tasks&quot;: [
          //C++ 컴파일
          {
            &quot;label&quot;: &quot;save and compile for C++&quot;,
            &quot;command&quot;: &quot;g++&quot;,
            &quot;args&quot;: [
                &quot;${file}&quot;,
                &quot;-o&quot;,
                &quot;${fileDirname}/${fileBasenameNoExtension}&quot;
            ],
            &quot;group&quot;: &quot;build&quot;,

            //컴파일시 에러를 편집기에 반영
            //참고:   https://code.visualstudio.com/docs/editor/tasks#_defining-a-problem-matcher

            &quot;problemMatcher&quot;: {
                &quot;fileLocation&quot;: [
                    &quot;relative&quot;,
                    &quot;${workspaceRoot}&quot;
                ],
                &quot;pattern&quot;: {
                    // The regular expression.
                  //Example to match: helloWorld.c:5:3: warning: implicit declaration of function 'prinft'
                    &quot;regexp&quot;: &quot;^(.*):(\\d+):(\\d+):\\s+(warning error):\\s+(.*)$&quot;,
                    &quot;file&quot;: 1,
                    &quot;line&quot;: 2,
                    &quot;column&quot;: 3,
                    &quot;severity&quot;: 4,
                    &quot;message&quot;: 5
                }
            }
        },
        //C 컴파일
        {
            &quot;label&quot;: &quot;save and compile for C&quot;,
            &quot;command&quot;: &quot;gcc&quot;,
            &quot;args&quot;: [
                &quot;${file}&quot;,
                &quot;-o&quot;,
                &quot;${fileDirname}/${fileBasenameNoExtension}&quot;
            ],
            &quot;group&quot;: &quot;build&quot;,

            //컴파일시 에러를 편집기에 반영
            //참고:   https://code.visualstudio.com/docs/editor/tasks#_defining-a-problem-matcher

            &quot;problemMatcher&quot;: {
                &quot;fileLocation&quot;: [
                    &quot;relative&quot;,
                    &quot;${workspaceRoot}&quot;
                ],
                &quot;pattern&quot;: {
                    // The regular expression.
                  //Example to match: helloWorld.c:5:3: warning: implicit declaration of function 'prinft'
                    &quot;regexp&quot;: &quot;^(.*):(\\d+):(\\d+):\\s+(warning error):\\s+(.*)$&quot;,
                    &quot;file&quot;: 1,
                    &quot;line&quot;: 2,
                    &quot;column&quot;: 3,
                    &quot;severity&quot;: 4,
                    &quot;message&quot;: 5
                }
            }
        },
        // 바이너리 실행(Ubuntu)
        {
             &quot;label&quot;: &quot;execute&quot;,
             &quot;command&quot;: &quot;${fileDirname}/${fileBasenameNoExtension}&quot;,
             &quot;group&quot;: &quot;test&quot;
        }
        // 바이너리 실행(Windows)
        //{
        //    &quot;label&quot;: &quot;execute&quot;,
        //    &quot;command&quot;: &quot;cmd&quot;,
        //    &quot;group&quot;: &quot;test&quot;,
        //    &quot;args&quot;: [
        //        &quot;/C&quot;, &quot;${fileDirname}\\${fileBasenameNoExtension}&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;컴파일, 실행 단축키를 지정합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메뉴에서 Preferences-&amp;gt;keyboard shortcut을 선택합니다.&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;사용자 정의로 바로 가기 키를 추가해야 합니다. 캡처화면에 빨간색 사각형으로 표시한 아이콘을 클릭합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;910&quot; data-origin-height=&quot;113&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nv43B/btsmrWhSkgZ/Ho8FxFNRx8aTJqK2QgAWK0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nv43B/btsmrWhSkgZ/Ho8FxFNRx8aTJqK2QgAWK0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nv43B/btsmrWhSkgZ/Ho8FxFNRx8aTJqK2QgAWK0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fnv43B%2FbtsmrWhSkgZ%2FHo8FxFNRx8aTJqK2QgAWK0%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;910&quot; height=&quot;113&quot; data-origin-width=&quot;910&quot; data-origin-height=&quot;113&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래 내용을 입력하고 저장을 합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1688468728458&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 키 바인딩을 이 파일에 넣어서 기본값을 덮어씁니다.
[
    //컴파일
    { &quot;key&quot;: &quot;ctrl+alt+c&quot;, &quot;command&quot;: &quot;workbench.action.tasks.build&quot; },
   
    //실행
    { &quot;key&quot;: &quot;ctrl+alt+r&quot;, &quot;command&quot;: &quot;workbench.action.tasks.test&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;vscode내 파일 탐색기에서 OO.cpp를 선택하고 Ctrl+Alt+C를 누르면 항목에서 save and compile for C++을 선택합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;870&quot; data-origin-height=&quot;512&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bsE34N/btsmsbTnd08/Co4IyV9IKO0OkY1d9kx3u0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bsE34N/btsmsbTnd08/Co4IyV9IKO0OkY1d9kx3u0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bsE34N/btsmsbTnd08/Co4IyV9IKO0OkY1d9kx3u0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbsE34N%2FbtsmsbTnd08%2FCo4IyV9IKO0OkY1d9kx3u0%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;870&quot; height=&quot;512&quot; data-origin-width=&quot;870&quot; data-origin-height=&quot;512&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컴파일이 완료 되면 탐색기에 실행파일이 생성됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실행파일을 선택후 Ctrl + Alt + R을 누르면 터미널에서 실행되는것을 볼 수 있습니다.&lt;/p&gt;</description>
      <category>C++</category>
      <author>Ninestar</author>
      <guid isPermaLink="true">https://data-science.tistory.com/438</guid>
      <comments>https://data-science.tistory.com/438#entry438comment</comments>
      <pubDate>Mon, 10 Jul 2023 10:09:26 +0900</pubDate>
    </item>
    <item>
      <title>[numba] Python을 C++보다 빠르게</title>
      <link>https://data-science.tistory.com/437</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;Python은&amp;nbsp;매우&amp;nbsp;다재다능한&amp;nbsp;프로그래밍&amp;nbsp;언어입니다.&amp;nbsp;파이썬은&amp;nbsp;라이브러리와&amp;nbsp;고수준&amp;nbsp;언어&amp;nbsp;덕분에&amp;nbsp;머신러닝&amp;nbsp;문제&amp;nbsp;해결에&amp;nbsp;가장&amp;nbsp;많이&amp;nbsp;사용되지만,&amp;nbsp;다른&amp;nbsp;언어에&amp;nbsp;비해&amp;nbsp;속도가&amp;nbsp;느린&amp;nbsp;것으로&amp;nbsp;알려져&amp;nbsp;있습니다.&amp;nbsp;이러한&amp;nbsp;평판&amp;nbsp;때문에&amp;nbsp;많은&amp;nbsp;사람들이&amp;nbsp;이&amp;nbsp;언어를&amp;nbsp;포기하고&amp;nbsp;프로그램&amp;nbsp;해결을&amp;nbsp;위해&amp;nbsp;C++와&amp;nbsp;같은&amp;nbsp;다른&amp;nbsp;옵션을&amp;nbsp;선택하기도&amp;nbsp;합니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;br /&gt;기본&amp;nbsp;속도&amp;nbsp;테스트&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;파이썬과&amp;nbsp;C++의&amp;nbsp;일반적인&amp;nbsp;속도&amp;nbsp;차이를&amp;nbsp;테스트하기&amp;nbsp;위해&amp;nbsp;소수&amp;nbsp;생성&amp;nbsp;알고리즘의&amp;nbsp;실행&amp;nbsp;시간을&amp;nbsp;테스트해&amp;nbsp;보겠습니다.&amp;nbsp;두&amp;nbsp;언어&amp;nbsp;모두에서&amp;nbsp;명확한&amp;nbsp;짧은&amp;nbsp;단계가&amp;nbsp;있는&amp;nbsp;간단한&amp;nbsp;알고리즘입니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;br /&gt;소수&amp;nbsp;생성&amp;nbsp;순서도&lt;br /&gt;&lt;br /&gt;&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;767&quot; data-origin-height=&quot;785&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bWIIq7/btsmlmt9IMs/tBVGyJJ7kKhA0oGWtYecbK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bWIIq7/btsmlmt9IMs/tBVGyJJ7kKhA0oGWtYecbK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bWIIq7/btsmlmt9IMs/tBVGyJJ7kKhA0oGWtYecbK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbWIIq7%2Fbtsmlmt9IMs%2FtBVGyJJ7kKhA0oGWtYecbK%2Fimg.jpg&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;767&quot; height=&quot;785&quot; data-origin-width=&quot;767&quot; data-origin-height=&quot;785&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 id=&quot;768b&quot; style=&quot;background-color: #ffffff; color: #292929; text-align: start;&quot; data-selectable-paragraph=&quot;&quot; data-ke-size=&quot;size26&quot;&gt;Python 실행&lt;/h2&gt;
&lt;pre class=&quot;fortran&quot; style=&quot;background-color: #f2f2f2; color: #292929; text-align: start;&quot;&gt;&lt;code&gt;import math
from time import per_counter def is_prime(num):
  if num == 2:
     return True;
  if num &amp;lt;= 1 or not num % 2:
     return False
  for div in range(3,int(math.sqrt(num)+1),2):
     if not num % div:
        return False
 return Truedef run program(N):
   for i in range(N):
      is_prime(i)if __name__ == &amp;lsquo;__main__&amp;rsquo;:
   N = 10000000
   start = perf_counter()
   run_program(N)
   end = perf_counter()
   print (end &amp;mdash; start)&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;442f&quot; style=&quot;background-color: #ffffff; color: #292929; text-align: start;&quot; data-selectable-paragraph=&quot;&quot; data-ke-size=&quot;size26&quot;&gt;C++ 실행&lt;/h2&gt;
&lt;pre class=&quot;arduino&quot; style=&quot;background-color: #f2f2f2; color: #292929; text-align: start;&quot;&gt;&lt;code&gt;#include &amp;lt;iostream&amp;gt;
#include &amp;lt;cmath&amp;gt;
#include &amp;lt;time.h&amp;gt;using namespace std;bool isPrime(int num)
{
 if (num == 2) return true; 
 if (num &amp;lt;= 1 || num % 2 == 0) return false;
 double sqrt_num = sqrt(double(num));
 for (int div = 3; div &amp;lt;= sqrt_num; div +=2){
    if (num % div == 0) return false;
 }
 return true;}int main() 
{
 int N = 10000000;
 clock_t start,end;
 start = clock();
 for (int i; i &amp;lt; N; i++) isPrime(i);
 end = clock();
 cout &amp;lt;&amp;lt; (end &amp;mdash; start) / ((double) CLOCKS_PER_SEC);
 return 0;}&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;ec8f&quot; style=&quot;background-color: #ffffff; color: #292929; text-align: start;&quot; data-selectable-paragraph=&quot;&quot; data-ke-size=&quot;size26&quot;&gt;결과&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li id=&quot;12e8&quot; style=&quot;list-style-type: disc; color: #292929;&quot; data-selectable-paragraph=&quot;&quot;&gt;&lt;b&gt;Python&lt;/b&gt;: 80.137 초&lt;/li&gt;
&lt;li id=&quot;7f5e&quot; style=&quot;list-style-type: disc; color: #292929;&quot; data-selectable-paragraph=&quot;&quot;&gt;&lt;b&gt;C++&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;: 3.174 초&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예상대로 기본 테스트에서 C++는 Python보다 25배 더 빨랐습니다.&amp;nbsp;&lt;br /&gt;&lt;br /&gt;Python은&amp;nbsp;C++와&amp;nbsp;달리&amp;nbsp;동적&amp;nbsp;언어입니다.&lt;br /&gt;GIL(&lt;span style=&quot;background-color: #ffffff; color: #292929; text-align: left;&quot;&gt;Python Global Interpreter&lt;/span&gt;)은 병렬 프로그래밍을 허용하지 않습니다.&lt;br /&gt;Numba를 사용하면 속도 문제를 해결할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Numba&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Numba는 Python 및 NumPy 코드의 하위 집합을 빠른 머신 코드로 변환하는 오픈 소스 JIT 컴파일러입니다. ~ 위키백과&lt;br /&gt;&lt;br /&gt;간단히&amp;nbsp;말해,&amp;nbsp;Numba는&amp;nbsp;파이썬을&amp;nbsp;빠르게&amp;nbsp;만드는&amp;nbsp;라이브러리입니다.&amp;nbsp;사용하기&amp;nbsp;매우&amp;nbsp;쉬우며&amp;nbsp;코드&amp;nbsp;속도를&amp;nbsp;획기적으로&amp;nbsp;바꿔줍니다.&amp;nbsp;Numba를&amp;nbsp;사용하려면&amp;nbsp;콘솔을&amp;nbsp;사용하여&amp;nbsp;설치하세요.&lt;/p&gt;
&lt;pre class=&quot;cmake&quot; style=&quot;background-color: #f2f2f2; color: #292929; text-align: start;&quot;&gt;&lt;code&gt;pip install numba&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;fe63&quot; style=&quot;background-color: #ffffff; color: #292929; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;numba설치후 Python 실행&lt;/h4&gt;
&lt;pre class=&quot;python&quot; style=&quot;background-color: #f2f2f2; color: #292929; text-align: start;&quot;&gt;&lt;code&gt;import math
from time import per_counter 
from numba import njit, prange@njit(fastmath=True, cache=True)
def is_prime(num):
   if num == 2:
      return True;
   if num &amp;lt;= 1 or not num % 2:
      return False
   for div in range(3,int(math.sqrt(num)+1),2):
      if not num % div:
        return False
   return True@njit(fastmath=True, cache=True,parallel=True)
def run program(N):
   for i in prange(N):
      is_prime(i)if __name__ == &amp;lsquo;__main__&amp;rsquo;:
  N = 10000000
  start = perf_counter()
  run_program(N)
  end = perf_counter()
  print (end &amp;mdash; start)&lt;/code&gt;&lt;/pre&gt;
&lt;p id=&quot;16e5&quot; style=&quot;background-color: #ffffff; color: #292929; text-align: start;&quot; data-selectable-paragraph=&quot;&quot; data-ke-size=&quot;size16&quot;&gt;결과&lt;/p&gt;
&lt;p id=&quot;2832&quot; style=&quot;background-color: #ffffff; color: #292929; text-align: start;&quot; data-selectable-paragraph=&quot;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Python&lt;/b&gt;: 1.401 초&lt;br /&gt;&lt;b&gt;C++&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;: 3.174 초&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #292929; text-align: start;&quot; data-selectable-paragraph=&quot;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #292929; text-align: start;&quot; data-selectable-paragraph=&quot;&quot; data-ke-size=&quot;size16&quot;&gt;파이썬이 C++보다 빠릅니다. 파이썬에서 알고리즘의 속도를 C++보다 빠르게 할 수 있습니다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #292929; text-align: start;&quot; data-selectable-paragraph=&quot;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #292929; text-align: right;&quot; data-selectable-paragraph=&quot;&quot; data-ke-size=&quot;size16&quot;&gt;출처: &lt;a href=&quot;https://medium.com/swlh/python-can-be-faster-than-c-2372c627068&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://medium.com/swlh/python-can-be-faster-than-c-2372c627068&lt;/a&gt;&lt;/p&gt;</description>
      <category>파이썬</category>
      <author>Ninestar</author>
      <guid isPermaLink="true">https://data-science.tistory.com/437</guid>
      <comments>https://data-science.tistory.com/437#entry437comment</comments>
      <pubDate>Sat, 8 Jul 2023 12:06:46 +0900</pubDate>
    </item>
    <item>
      <title>[Rust] model inference with CUDA (ONNXRUNTIME,ort)</title>
      <link>https://data-science.tistory.com/431</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://crates.io/crates/ort에&quot;&gt;https://crates.io/crates/ort에&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;따르면 cuda를 사용할수 있습니다.(cuda는 이미 설치되어있다고 가정합니다.)&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;cargo.toml에 ort를 추가할때 feature로 load-dynamic이나 cuda가 있으면 cuda를 사용 할 수 있는것 같습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1688100712642&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#[cfg(any(feature = &quot;load-dynamic&quot;, feature = &quot;cuda&quot;))]&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;cargo.toml에 아래 코드를 추가합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1688100746617&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;ort = {version=&quot;1.14.6&quot;, features = [&quot;cuda&quot;]}&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;그리고&lt;span&gt;&amp;nbsp;&lt;/span&gt;main.rs에&lt;span&gt;&amp;nbsp;&lt;/span&gt;use ort::ExecutionProvider&lt;span&gt;&amp;nbsp;&lt;/span&gt;추가하고&lt;br /&gt;main()함수 에서&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1688100764934&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;ExecutionProvider::cuda().is_available()&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;로 확인할수 있습니다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;builder 환경 설정할때&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;.with_execution_providers([ExecutionProvider::cuda()])옵션을 추가합니다.&lt;br /&gt;위 옵션이 있을때 available 결과가 False로 나오면 providers는 자동으로 CPU로 설정되는것 같습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1688100809826&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;let env = Arc::new(
    Environment::builder()
        .with_name(&quot;YOLOv8&quot;)
        .with_execution_providers([ExecutionProvider::cuda()])
        .build()
        .unwrap(),
);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1688100909598&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;watch -d nvidia-smi&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1212&quot; data-origin-height=&quot;513&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bzcRJZ/btslZvj8wSL/k07dElq2kGtKGrD1IhEWb1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bzcRJZ/btslZvj8wSL/k07dElq2kGtKGrD1IhEWb1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bzcRJZ/btslZvj8wSL/k07dElq2kGtKGrD1IhEWb1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbzcRJZ%2FbtslZvj8wSL%2Fk07dElq2kGtKGrD1IhEWb1%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;1212&quot; height=&quot;513&quot; data-origin-width=&quot;1212&quot; data-origin-height=&quot;513&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;</description>
      <category>Rust</category>
      <author>Ninestar</author>
      <guid isPermaLink="true">https://data-science.tistory.com/431</guid>
      <comments>https://data-science.tistory.com/431#entry431comment</comments>
      <pubDate>Fri, 7 Jul 2023 14:56:36 +0900</pubDate>
    </item>
    <item>
      <title>[Rust] Object Tracking in RUST with YOLOv8n ONNX model</title>
      <link>https://data-science.tistory.com/430</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;각 프레임마다 onnx모델 Run을 하여 bbox 좌표를 얻습니다.&lt;br /&gt;onnx모델의 입력값은 정규화,표준화된 픽셀값이며 크기는 [1,3,640,640] 형식은 텐서입니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #1f2328; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/pykeio/ort/blob/a92e4d1e6d99674dc1d04ed22743c3dd1bc59186/tests/onnx.rs#L16&quot;&gt;https://github.com/pykeio/ort/blob/a92e4d1e6d99674dc1d04ed22743c3dd1bc59186/tests/onnx.rs#L16&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://dev.to/andreygermanov/how-to-create-yolov8-based-object-detection-web-service-using-python-julia-nodejs-javascript-go-and-rust-4o8e#rust&quot;&gt;https://dev.to/andreygermanov/how-to-create-yolov8-based-object-detection-web-service-using-python-julia-nodejs-javascript-go-and-rust-4o8e#rust&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;cpp&quot; style=&quot;background-color: #000000; color: #1f2328; text-align: start;&quot; data-ke-language=&quot;rust&quot;&gt;&lt;code&gt;use std::{sync::Arc,
    path::PathBuf,
    any::type_name,
    time::SystemTime,
};
use image::{imageops::{FilterType,resize},
    RgbImage, Rgb
};
use ndarray::{Array, IxDyn, s, Axis,Array3};
use video_rs::{self, Decoder,Locator,Encoder, EncoderSettings, Time};
use ort::{SessionBuilder,    
    environment::Environment,
    tensor::InputTensor, Session,
};
use imageproc::{drawing::draw_hollow_rect,
        rect::Rect
};

// Array of YOLOv8 class labels
const YOLO_CLASSES:[&amp;amp;str;80] = [
&quot;person&quot;, &quot;bicycle&quot;, &quot;car&quot;, &quot;motorcycle&quot;, &quot;airplane&quot;, &quot;bus&quot;, &quot;train&quot;, &quot;truck&quot;, &quot;boat&quot;,
&quot;traffic light&quot;, &quot;fire hydrant&quot;, &quot;stop sign&quot;, &quot;parking meter&quot;, &quot;bench&quot;, &quot;bird&quot;, &quot;cat&quot;, &quot;dog&quot;, &quot;horse&quot;,
&quot;sheep&quot;, &quot;cow&quot;, &quot;elephant&quot;, &quot;bear&quot;, &quot;zebra&quot;, &quot;giraffe&quot;, &quot;backpack&quot;, &quot;umbrella&quot;, &quot;handbag&quot;, &quot;tie&quot;,
&quot;suitcase&quot;, &quot;frisbee&quot;, &quot;skis&quot;, &quot;snowboard&quot;, &quot;sports ball&quot;, &quot;kite&quot;, &quot;baseball bat&quot;, &quot;baseball glove&quot;,
&quot;skateboard&quot;, &quot;surfboard&quot;, &quot;tennis racket&quot;, &quot;bottle&quot;, &quot;wine glass&quot;, &quot;cup&quot;, &quot;fork&quot;, &quot;knife&quot;, &quot;spoon&quot;,
&quot;bowl&quot;, &quot;banana&quot;, &quot;apple&quot;, &quot;sandwich&quot;, &quot;orange&quot;, &quot;broccoli&quot;, &quot;carrot&quot;, &quot;hot dog&quot;, &quot;pizza&quot;, &quot;donut&quot;,
&quot;cake&quot;, &quot;chair&quot;, &quot;couch&quot;, &quot;potted plant&quot;, &quot;bed&quot;, &quot;dining table&quot;, &quot;toilet&quot;, &quot;tv&quot;, &quot;laptop&quot;, &quot;mouse&quot;,
&quot;remote&quot;, &quot;keyboard&quot;, &quot;cell phone&quot;, &quot;microwave&quot;, &quot;oven&quot;, &quot;toaster&quot;, &quot;sink&quot;, &quot;refrigerator&quot;, &quot;book&quot;,
&quot;clock&quot;, &quot;vase&quot;, &quot;scissors&quot;, &quot;teddy bear&quot;, &quot;hair drier&quot;, &quot;toothbrush&quot;
];

fn detect_objects_on_image(model: &amp;amp;Session, buf: RgbImage) -&amp;gt; Vec&amp;lt;(f32,f32,f32,f32,&amp;amp;'static str,f32)&amp;gt; {
    let (input,img_width,img_height) = prepare_input(buf);
    let output = run_model(&amp;amp;model,input);
    return process_output(output, img_width, img_height);
}

fn prepare_input(buf: RgbImage) -&amp;gt; (Array&amp;lt;f32,IxDyn&amp;gt;, u32, u32) {
    let resizeimg = resize(img,640,640,FilterType::Nearest);
    let mut input = Array::zeros((1, 3, 640, 640)).into_dyn();
    for pixel in resizeimg.enumerate_pixels() {
    let x = pixel.0 as usize;
    let y = pixel.1 as usize;
    let [r,g,b] = pixel.2.0;
    input[[0, 0, y, x]] = (r as f32) / 255.0;
    input[[0, 1, y, x]] = (g as f32) / 255.0;
    input[[0, 2, y, x]] = (b as f32) / 255.0;
    };
    return (input, img_width, img_height);
}

fn run_model(model:&amp;amp;Session, input:Array&amp;lt;f32,IxDyn&amp;gt;) -&amp;gt; Array&amp;lt;f32,IxDyn&amp;gt; {
    let input = InputTensor::FloatTensor(input);
    let outputs = model.run([input]).unwrap();
    let output = outputs.get(0).unwrap().try_extract::&amp;lt;f32&amp;gt;().unwrap().view().t().into_owned();
    return output;
}

fn process_output(output:Array&amp;lt;f32,IxDyn&amp;gt;,img_width: u32, img_height: u32) -&amp;gt; Ve
    let mut boxes = Vec::new();
    let output = output.slice(s![..,..,0]);
    for row in output.axis_iter(Axis(0)) {
    let row:Vec&amp;lt;_&amp;gt; = row.iter().map(|x| *x).collect();
    let (class_id, prob) = row.iter().skip(4).enumerate()
        .map(|(index,value)| (index,*value))
        .reduce(|accum, row| if row.1&amp;gt;accum.1 { row } else {accum}).unwrap();
    if class_id != 0 {
        continue
    }
    if prob &amp;lt; 0.5 {
        continue
    }
    let label = YOLO_CLASSES[class_id];
    let xc = row[0]/640.0*(img_width as f32);
    let yc = row[1]/640.0*(img_height as f32);
    let w = row[2]/640.0*(img_width as f32);
    let h = row[3]/640.0*(img_height as f32);
    let x1 = xc - w/2.0;
    let x2 = xc + w/2.0;
    let y1 = yc - h/2.0;
    let y2 = yc + h/2.0;
    boxes.push((x1,y1,x2,y2,label,prob));
}

boxes.sort_by(|box1,box2| box2.5.total_cmp(&amp;amp;box1.5));
    let mut result = Vec::new();
    while boxes.len()&amp;gt;0 {
    result.push(boxes[0]);
    boxes = boxes.iter().filter(|box1| iou(&amp;amp;boxes[0],box1) &amp;lt; 0.7).map(|x| *x).collect()
    }
    return result;
}

fn array_to_image(arr: Array3&amp;lt;u8&amp;gt;) -&amp;gt; RgbImage {
    let raw = arr.into_raw_vec();

    (RgbImage::from_raw(width as u32, height as u32, raw))
    .expect(&quot;container should have the right size for the image dimensions&quot;)
}  
fn image_to_array(buf:RgbImage)-&amp;gt;Array3&amp;lt;u8&amp;gt;{
    let img = &amp;amp;buf;
fn image_to_array(buf:RgbImage)-&amp;gt;Array3&amp;lt;u8&amp;gt;{
    return input;  
}
fn main(){
    let env = Arc::new(Environment::builder().with_name(&quot;YOLOv8&quot;).build().unwrap());
    let model = SessionBuilder::new(&amp;amp;env).unwrap().with_model_from_file(&quot;yolov8n.onnx&quot;).unwrap();

    video_rs::init().unwrap();
    let mut decoder = Decoder::new(&amp;amp;PathBuf::from(&quot;/home/yimstar9/github/ObjectTracking/data/crowd.mp4&quot;).into()).unwrap();
    let mut count = 0; 
 fn main(){
    //시간체크용 타이머
    let start = SystemTime::now();
    for frame in decoder.decode_iter() {
    if let Ok((_, frame)) = frame {
        //frame(array)를 RgbImage형식으로 변환
        let mut image = array_to_image(frame);
        //객체 box 좌표 -&amp;gt; boxes 
                // let detect_start = SystemTime::now();
                let boxes = detect_objects_on_image(&amp;amp;model,image.clone());
                // let detect_end = SystemTime::now();
                // let detect_time = detect_end.duration_since(detect_start);
                // println!(&quot;detect run time: {:?}&quot;, detect_time);
        //image에 box좌표로 사각형 그림
        for bbox in boxes.iter(){
            let rect = Rect::at(bbox.0 as i32, bbox.1 as i32).of_size((bbox.2-bbox.0) as u32,(bbox.3 - bbox.1) as u32 );
            image = draw_hollow_rect(&amp;amp;image, rect, Rgb([255, 0, 0]));
        }
    //인코딩용 프레임 변환
    let frm= image_to_array(image);
    //인코딩
    encoder
        .encode(&amp;amp;frm,&amp;amp;position)
        .expect(&quot;failed to encode frame&quot;);
    position = position.aligned_with(&amp;amp;duration).add();
    } else {
        break;
    }
    count = count +1;
    println!(&quot;{}&quot;,count);
    }
    //시간체크용 타이머
    let end = SystemTime::now();
    let elapsed_time = end.duration_since(start);
    println!(&quot;Elapsed time: {:?}&quot;, elapsed_time);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1060&quot; data-origin-height=&quot;1339&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qYo1Y/btslXnNBC9A/UHCouYNfvVQId72Kg3fxU0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qYo1Y/btslXnNBC9A/UHCouYNfvVQId72Kg3fxU0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qYo1Y/btslXnNBC9A/UHCouYNfvVQId72Kg3fxU0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqYo1Y%2FbtslXnNBC9A%2FUHCouYNfvVQId72Kg3fxU0%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;1060&quot; height=&quot;1339&quot; data-origin-width=&quot;1060&quot; data-origin-height=&quot;1339&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&gt;&lt;iframe src=&quot;https://www.youtube.com/embed/rMsLKsjJMy4&quot; width=&quot;560&quot; height=&quot;315&quot; frameborder=&quot;&quot; allowfullscreen=&quot;true&quot;&gt;&lt;/iframe&gt;&lt;/p&gt;</description>
      <category>Rust</category>
      <author>Ninestar</author>
      <guid isPermaLink="true">https://data-science.tistory.com/430</guid>
      <comments>https://data-science.tistory.com/430#entry430comment</comments>
      <pubDate>Thu, 6 Jul 2023 14:48:47 +0900</pubDate>
    </item>
    <item>
      <title>[OpenCV] DNN failing to load an ONNX file: computeShapeByReshapeMask</title>
      <link>https://data-science.tistory.com/442</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;[ERROR:0@0.058]&amp;nbsp;global&amp;nbsp;onnx_importer.cpp:1054&amp;nbsp;cv::dnn::dnn4_v20221220::ONNXImporter::handleNode&amp;nbsp;DNN/ONNX:&amp;nbsp;ERROR&amp;nbsp;during&amp;nbsp;processing&amp;nbsp;node&amp;nbsp;with&amp;nbsp;2&amp;nbsp;inputs&amp;nbsp;and&amp;nbsp;1&amp;nbsp;outputs:&amp;nbsp;[Reshape]:(onnx_node!/model.22/dfl/Reshape)&amp;nbsp;from&amp;nbsp;domain='ai.onnx'&lt;br /&gt;Traceback&amp;nbsp;(most&amp;nbsp;recent&amp;nbsp;call&amp;nbsp;last):&lt;/p&gt;
&lt;pre id=&quot;code_1688542075134&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;[ERROR:0@0.058] global onnx_importer.cpp:1054 cv::dnn::dnn4_v20221220::ONNXImporter::handleNode DNN/ONNX: ERROR during processing node with 2 inputs and 1 outputs: [Reshape]:(onnx_node!/model.22/dfl/Reshape) from domain='ai.onnx'
Traceback (most recent call last):
  File &quot;.\run.py&quot;, line 12, in &amp;lt;module&amp;gt;
    opencv_net = cv2.dnn.readNetFromONNX(onnx_model_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;[Reshape] 관련 에러 메시지가 뜨면 onnx모델을 opset=12 옵션을 적용해야 합니다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래 명령어를 입력하여 onnx모델을 새로 다운로드 합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1688542337522&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;pip install ultralytics
yolo export model=yolov8n.pt imgsz=640 format=onnx opset=12&lt;/code&gt;&lt;/pre&gt;</description>
      <category>Rust</category>
      <author>Ninestar</author>
      <guid isPermaLink="true">https://data-science.tistory.com/442</guid>
      <comments>https://data-science.tistory.com/442#entry442comment</comments>
      <pubDate>Wed, 5 Jul 2023 16:32:41 +0900</pubDate>
    </item>
    <item>
      <title>[RUST]OpenCV : 'limits' file not found</title>
      <link>https://data-science.tistory.com/441</link>
      <description>&lt;pre id=&quot;code_1688534857722&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;===    /usr/local/include/opencv4/opencv2/core/cvdef.h:185:10: fatal error: 'limits' file not found
  thread 'main' panicked at '=== Errors during header parsing', /home/yimstar9/.cargo/registry/src/github.com-1ecc6299db9ec823/opencv-binding-generator-0.66.0/src/generator.rs:501:17
  note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
  === WARNING: 1 diagnostic messages
  ===    /usr/local/include/opencv4/opencv2/core/cvdef.h:185:10: fatal error: 'limits' file not found
  thread 'main' panicked at '=== Errors during header parsing', /home/yimstar9/.cargo/registry/src/github.com-1ecc6299db9ec823/opencv-binding-generator-0.66.0/src/generator.rs:501:17
  note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
  === WARNING: 1 diagnostic messages
  ===    /usr/local/include/opencv4/opencv2/core/cvdef.h:185:10: fatal error: 'limits' file not found
  thread 'main' panicked at '=== Errors during header parsing', /home/yimstar9/.cargo/registry/src/github.com-1ecc6299db9ec823/opencv-binding-generator-0.66.0/src/generator.rs:501:17
  note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
  === WARNING: 1 diagnostic messages
  ===    /usr/local/include/opencv4/opencv2/core/cvdef.h:185:10: fatal error: 'limits' file not found
  thread 'main' panicked at '=== Errors during header parsing', /home/yimstar9/.cargo/registry/src/github.com-1ecc6299db9ec823/opencv-binding-generator-0.66.0/src/generator.rs:501:17
  note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
  === WARNING: 1 diagnostic messages
  ===    /usr/local/include/opencv4/opencv2/core/cvdef.h:185:10: fatal error: 'limits' file not found
  thread 'main' panicked at '=== Errors during header parsing', /home/yimstar9/.cargo/registry/src/github.com-1ecc6299db9ec823/opencv-binding-generator-0.66.0/src/generator.rs:501:17
  note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;libstdc++-12-dev을 다시 설치하면 됩니다.&lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&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;&lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot;&gt;Ubuntu&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;apt install libstdc++-12-dev&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/twistedfall/opencv-rust/issues/322&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://github.com/twistedfall/opencv-rust/issues/322&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;a href=&quot;https://github.com/twistedfall/opencv-rust/issues/419&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://github.com/twistedfall/opencv-rust/issues/419&lt;/a&gt;&lt;/p&gt;</description>
      <category>Rust</category>
      <author>Ninestar</author>
      <guid isPermaLink="true">https://data-science.tistory.com/441</guid>
      <comments>https://data-science.tistory.com/441#entry441comment</comments>
      <pubDate>Wed, 5 Jul 2023 14:28:23 +0900</pubDate>
    </item>
    <item>
      <title>[Rust] 동영상에 Box 그리기</title>
      <link>https://data-science.tistory.com/429</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;decode :&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://crates.io/crates/video-rs/0.4.0&quot;&gt;video-rs&lt;/a&gt;&lt;br /&gt;imageprocess :&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://crates.io/crates/imageproc&quot;&gt;imageproc&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;video-rs를 이용하여 영상을 decode후 decode_iter()로 frame별 픽셀 값을 추출합니다.&lt;br /&gt;추출한 frame에&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://docs.rs/imageproc/latest/imageproc/drawing/fn.draw_hollow_rect.html&quot;&gt;imageproc::drawing::draw_hollow_rect&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;함수를 이용하여 사각형을 그립니다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1688098912178&quot; class=&quot;go&quot; data-ke-language=&quot;go&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;pub fn draw_hollow_rect&amp;lt;I&amp;gt;(
    image: &amp;amp;I, 
    rect: Rect, 
    color: I::Pixel
) -&amp;gt; Image&amp;lt;I::Pixel&amp;gt; 
where
    I: GenericImage,&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;함수에서 입력받는 이미지 형식이&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://docs.rs/image/0.24.1/image/trait.GenericImage.html&quot;&gt;GenericImage&lt;/a&gt;입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;형 변환 방법&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #1f2328; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;imagebuffer에 for문으로 픽셀값 넣어주는 방법&lt;/li&gt;
&lt;li&gt;ndarray to image trait으로 generic image 변환후 사각형 그리는방법&lt;/li&gt;
&lt;li&gt;픽셀값을 직접 수정해서 사각형만 그려주는 방법&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;형변환: imagebuffer에 for문으로 픽셀값 넣어주는 방법&lt;/h3&gt;
&lt;pre id=&quot;code_1688099036782&quot; class=&quot;go&quot; data-ke-language=&quot;go&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;fn main() {
    video_rs::init().unwrap();
    let mut decoder = Decoder::new(&amp;amp;PathBuf::from(&quot;/home/yimstar9/ObjectTracking/videors/crowd.mp4&quot;).into()).unwrap();

    //사각형 설정
    let rect = Rect::at(300, 300).of_size(50, 30);

    //시간체크용 타이머
    let start = SystemTime::now();
   
    for frame in decoder.decode_iter() {
        if let Ok((_, frame)) = frame {

            // decoder의 결과값(frame)을 image trait의 imagebuffer형식으로 바꿔야 합니다. 
            // frame에서 픽셀값을 for문으로 imagebuffer에 하나씩 넣어줍니다.
            let mut img = RgbImage::new(720,1280);
            for x in 0..720 {
                for y in 0..1280 {
                    // https://crates.io/crates/video-rs/0.4.0 frame에서 x,y위치의 픽셀값 추출
                    let rgb = frame
                    .slice(ndarray::s![x as i32, y as i32, ..])
                    .to_slice()
                    .unwrap();
                    
                    img.put_pixel(x, y, Rgb([rgb[0],rgb[1],rgb[2]]));
                }
            }
            // https://docs.rs/imageproc/latest/imageproc/drawing/fn.draw_hollow_rect.html 이미지에 사각형 그립니다.
            let mut rect = draw_hollow_rect(&amp;amp;img, rect, Rgb([255, 0, 0]));
        } else {
            break;
        }
    }
    //시간체크용 타이머
    let end = SystemTime::now();
    let elapsed_time = end.duration_since(start);
    println!(&quot;Elapsed time: {:?}&quot;, elapsed_time);
    
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;형변환: array to image&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot;&gt;image::RgbImage::from_raw 함수를 이용합니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1688099131756&quot; class=&quot;go&quot; data-ke-language=&quot;go&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;use image::RgbImage;
use ndarray::Array3;
use std::path::PathBuf;
use video_rs::{self, Decoder, Locator};
use std::time::SystemTime;

fn array_to_image(arr: Array3&amp;lt;u8&amp;gt;) -&amp;gt; RgbImage {
    assert!(arr.is_standard_layout());

    let (height, width, _) = arr.dim();
    let raw = arr.into_raw_vec();

    RgbImage::from_raw(width as u32, height as u32, raw)
        .expect(&quot;container should have the right size for the image dimensions&quot;)
}


fn main(){
    video_rs::init().unwrap();
    let mut decoder = Decoder::new(&amp;amp;PathBuf::from(&quot;/home/yimstar9/github/ObjectTracking/data/crowd.mp4&quot;).into()).unwrap();
    //시간체크용 타이머
    let start = SystemTime::now();
    for frame in decoder.decode_iter() {
        if let Ok((_, frame)) = frame {
            let image = array_to_image(frame);
     
        } else {
            break;
        }
    }
    //시간체크용 타이머
    let end = SystemTime::now();
    let elapsed_time = end.duration_since(start);
    println!(&quot;Elapsed time: {:?}&quot;, elapsed_time);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Rust</category>
      <author>Ninestar</author>
      <guid isPermaLink="true">https://data-science.tistory.com/429</guid>
      <comments>https://data-science.tistory.com/429#entry429comment</comments>
      <pubDate>Wed, 5 Jul 2023 13:28:14 +0900</pubDate>
    </item>
    <item>
      <title>[Rust] asser_eq!</title>
      <link>https://data-science.tistory.com/428</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #333333;&quot;&gt;assert!(식) 매크로는 &quot;식&quot;에 있는 값이 true이면 테스트가 성공한 것으로 여기고, false 이면 에러인 것으로 취급합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #333333;&quot;&gt;assert_eq!() 혹은 assert_ne!() 매크로는 2개의 파라미터를 받아들여 에러가 난 경우 두 파라미터의 값이 어떻게 다른지 출력해 줍니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1688098510010&quot; class=&quot;go&quot; data-ke-language=&quot;go&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;assert_eq!(rect.left(), 4);
assert_eq!(rect.top(), 5);
assert!(rect.contains(rect.left(), rect.top()));&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: #333333; text-align: start;&quot;&gt; assert_eq!() 매크로는 실패하면 아래와 같이 좌, 우 파라미터가 어떻게 다른지 자세하게 출력하게 됩니다. Rust의 assert 매크로는 (다른 test framework과 달리) expected vs actual 의 구분이 없이, 그냥 두 파라미터를 비교합니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1688098609885&quot; class=&quot;go&quot; data-ke-language=&quot;go&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#[cfg(test)]
mod tests {
    #[test]
    fn mul_test() {
        assert_eq!(2 * 3, 5);  // 에러
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;crystal&quot; style=&quot;background-color: #f5f5f5; color: #333333; text-align: start;&quot;&gt;&lt;code&gt;test tests::mul_test ... FAILED
    
    failures:
    
    ---- tests::mul_test stdout ----
    thread 'tests::mul_test' panicked at 'assertion failed: `(left == right)`
    left: `6`,
    right: `5`', src\lib.rs:48:9
    note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace&lt;/code&gt;&lt;/pre&gt;</description>
      <category>Rust</category>
      <author>Ninestar</author>
      <guid isPermaLink="true">https://data-science.tistory.com/428</guid>
      <comments>https://data-science.tistory.com/428#entry428comment</comments>
      <pubDate>Wed, 5 Jul 2023 12:17:25 +0900</pubDate>
    </item>
  </channel>
</rss>