<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>꼭대기에 대한 상상</title>
    <link>https://rapsealk.tistory.com/</link>
    <description></description>
    <language>ko</language>
    <pubDate>Mon, 8 Jun 2026 02:32:26 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>rapsealk</managingEditor>
    <item>
      <title>bitsandbytes 이슈 삽질기</title>
      <link>https://rapsealk.tistory.com/25</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;원문: &lt;a href=&quot;https://www.backend.ai/ko/blog/2023-07-bitsandbytes-issue&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.backend.ai/ko/blog/2023-07-bitsandbytes-issue&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1769005550715&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;bitsandbytes 이슈 삽질기&quot; data-og-description=&quot;Backend.AI 팀은 고객들에게 항상 귀를 기울이고 있습니다. 2023년, NGC Catalog1(NVIDIA GPU Cloud)에서 제공하는 컨테이너 환경에서 특정 패키지를 실행할 때 에러가 발생한다는 이슈가 개발팀에 전달되었&quot; data-og-host=&quot;www.backend.ai&quot; data-og-source-url=&quot;https://www.backend.ai/ko/blog/2023-07-bitsandbytes-issue&quot; data-og-url=&quot;https://www.backend.ai/ko/blog/2023-07-bitsandbytes-issue&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/dxrCjj/dJMb9eTJFy5/gOUQpxS0JlKcTEHh8cykG1/img.jpg?width=960&amp;amp;height=720&amp;amp;face=0_0_960_720,https://scrap.kakaocdn.net/dn/tU6sp/dJMb9cBCatd/YMUkqdzTJBNjKT0jFrkF80/img.jpg?width=960&amp;amp;height=720&amp;amp;face=0_0_960_720&quot;&gt;&lt;a href=&quot;https://www.backend.ai/ko/blog/2023-07-bitsandbytes-issue&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.backend.ai/ko/blog/2023-07-bitsandbytes-issue&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/dxrCjj/dJMb9eTJFy5/gOUQpxS0JlKcTEHh8cykG1/img.jpg?width=960&amp;amp;height=720&amp;amp;face=0_0_960_720,https://scrap.kakaocdn.net/dn/tU6sp/dJMb9cBCatd/YMUkqdzTJBNjKT0jFrkF80/img.jpg?width=960&amp;amp;height=720&amp;amp;face=0_0_960_720');&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;bitsandbytes 이슈 삽질기&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Backend.AI 팀은 고객들에게 항상 귀를 기울이고 있습니다. 2023년, NGC Catalog1(NVIDIA GPU Cloud)에서 제공하는 컨테이너 환경에서 특정 패키지를 실행할 때 에러가 발생한다는 이슈가 개발팀에 전달되었&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.backend.ai&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>기타</category>
      <category>bitsandbytes</category>
      <author>rapsealk</author>
      <guid isPermaLink="true">https://rapsealk.tistory.com/25</guid>
      <comments>https://rapsealk.tistory.com/25#entry25comment</comments>
      <pubDate>Mon, 4 Sep 2023 08:46:32 +0900</pubDate>
    </item>
    <item>
      <title>2022년을 돌아보는 회고록</title>
      <link>https://rapsealk.tistory.com/24</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;2022년 마지막 근무를 했던 12월 30일에 팀원분들과 연말을 기념하는 커피챗 미팅을 잡게 되었다. 팀 리드님께서 한 해를 되돌아보며 기억하자는 의미에서 &quot;기년회&quot;를 제안해 주셨고, 덕분에 나도 어떤 시간을 보냈었는지 돌이켜 볼 수 있는 기회가 되었다. 기년회에 대한 내용은 이 &lt;a title=&quot;망년회 대신 기년회&quot; href=&quot;http://egloos.zum.com/agile/v/4016733&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;블로그&lt;/a&gt;를 참고하시길 바란다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&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-filename=&quot;Dumbledore_Memory.webp&quot; data-origin-width=&quot;1200&quot; data-origin-height=&quot;507&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cjeoNB/btrVzY0XDyd/4TA0a5UFv494KjcpIKU4Ik/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cjeoNB/btrVzY0XDyd/4TA0a5UFv494KjcpIKU4Ik/img.webp&quot; data-alt=&quot;기억 뽑아내는 중 (출처: 해리포터와 혼혈왕자)&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cjeoNB/btrVzY0XDyd/4TA0a5UFv494KjcpIKU4Ik/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcjeoNB%2FbtrVzY0XDyd%2F4TA0a5UFv494KjcpIKU4Ik%2Fimg.webp&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;1200&quot; height=&quot;507&quot; data-filename=&quot;Dumbledore_Memory.webp&quot; data-origin-width=&quot;1200&quot; data-origin-height=&quot;507&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;&lt;b&gt;1월&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2021년 10월부터 12월까지 진행하던 프로젝트의 1차 시연을 성공적으로 마치고, 최종 배포를 위한 안정화 작업을 진행했다. 이 프로젝트는 데스크톱 환경에서 실행되는 Electron 기반 클라이언트로 아래와 같은 특징들로 인하여 그동안 개발했던 프로그램들과 결을 달리 하는데, 이에 적합한 개발 방법을 끝내 찾지 못하고 마무리하게 된 것 같아 아쉬움이 많이 남는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 사용자 PC의 시간을 강제로 변경한다. 이 기능은 관리자 권한을 필요로 하는데, 프로그램을 실행할 때 &quot;관리자 권한으로 실행&quot;을 선택할 수 있는 Windows와는 달리 macOS에서는 터미널에서 sudo 명령어로 시작해야 했다. 대상 사용자가 터미널을 하지 않는 (개발직군 외의) 일반적인 PC 사용자인 점을 생각했을 때 썩 유쾌한 방법은 아니었던 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 백그라운드에서 실행되고 있는 음성 파일이 진행됨에 따라 이벤트를 발생시켜야 한다. 문제는 이 이벤트가 웹페이지를 이동하거나 스크립트를 실행시키는 것이었는데, 매우 당연하게도 사용자의 네트워크 환경에 따라 로딩 속도에 차이가 있었다. 따라서 웹페이지의 로딩이 끝나는 시점을 알아야 했는데, 당시의 접근 방법이었던 &lt;a href=&quot;https://developer.mozilla.org/ko/docs/Web/API/Window/DOMContentLoaded_event&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;DomContentLoaded&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;그 외에도 마우스 커서를 일시적으로 변경하거나 Electron WebView에서 내부 DOM에 접근하는 스크립트를 실행하는 등 매우 도전적인 이슈들이 많았다. 당시에 작성했던 &lt;a href=&quot;https://rapsealk.tistory.com/20&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;글&lt;/a&gt;이 하나 있는데, 지금 돌이켜보면 나름 재밌는 이슈였던 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2월&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;첫 커리어를 시작했던 직장에서 퇴사했다. 당시 사내의 소프트웨어 개발 업무를 전담하여 진행하는 과정에서 많은 고민들이 생겼었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 개발 능력에 대한 자신감과 생산력이 떨어졌다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 업무적으로나 일상적으로나 사람을 만날 일이 없으니 갈수록 외로움이 커졌다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러던 중 커뮤니티를 통해 한 시니어와 깊은 대화(라기보다는 검증의 시간)를 할 기회가 생겼는데, 여기에서 큰 충격을 받게 되었다. 그 결과 조금 갑작스럽지만 퇴사를 결정하게 되었고, 7개월 간의 여정을 마치고 집으로 돌아오게 되었다.&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;3월&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Back to the basic이라는 마음가짐으로 나를 검증하는 시간을 가지기로 했다. 지금까지 알고 있다고 생각했던 내용들을 다시 확인하는 과정을 거쳤으며, 조금 더 나은 개발 방법을 찾기 위하여 새로운 사이드 프로젝트를 진행하였다. 어차피 백수였기 때문에 시간은 많았으므로 매일매일 조금씩이라도 꾸준히 진행하려고 했다. 소위 말하는 &quot;잔디심기&quot;를 신경 쓰는 편은 아니지만, 이 기간 동안만큼은 내가 어떻게 진행했는지를 나타내는 하나의 지표가 되어 줄 수는 있을 것 같다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;174&quot; data-origin-height=&quot;118&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bQD0N3/btrVDiRFVSn/PgTWCXsyFwZj0qA3DkxdK0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bQD0N3/btrVDiRFVSn/PgTWCXsyFwZj0qA3DkxdK0/img.png&quot; data-alt=&quot;3월 14일부터 5월 6일까지&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bQD0N3/btrVDiRFVSn/PgTWCXsyFwZj0qA3DkxdK0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbQD0N3%2FbtrVDiRFVSn%2FPgTWCXsyFwZj0qA3DkxdK0%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;174&quot; height=&quot;118&quot; data-origin-width=&quot;174&quot; data-origin-height=&quot;118&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;3월 14일부터 5월 6일까지&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;4월&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한 달간의 수련을 끝마치고 다시 이력서를 작성하고 구직 활동을 시작했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;5월&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5월 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;b&gt;6월&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;6월 14일부터 전문연구요원으로서 병역을 시작하게 되었다.&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;7월&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Raft 합의 알고리즘 공부를 시작했다. 이 게시물의 끝을 지어보려 한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;821&quot; data-origin-height=&quot;239&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dAUymy/btrVzKhBiaG/SCWWMtqdL607rIORHsvXdk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dAUymy/btrVzKhBiaG/SCWWMtqdL607rIORHsvXdk/img.png&quot; data-alt=&quot;Raft 합의 알고리즘&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dAUymy/btrVzKhBiaG/SCWWMtqdL607rIORHsvXdk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdAUymy%2FbtrVzKhBiaG%2FSCWWMtqdL607rIORHsvXdk%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;821&quot; height=&quot;239&quot; data-origin-width=&quot;821&quot; data-origin-height=&quot;239&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Raft 합의 알고리즘&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;8월&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;b&gt;9월&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;새로운 프로젝트인 Backend.AI FastTrack 개발에 참여하게 되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://blog.lablup.com/posts/2022/11/29/introduce-fasttrack&quot;&gt;Backend.AI MLOps 플랫폼 FastTrack을 소개합니다. | Lablup Blog&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1673105613209&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;Backend.AI MLOps 플랫폼 FastTrack을 소개합니다. | Lablup Blog&quot; data-og-description=&quot;이번 글에서는 Backend.AI의 MLOps 플랫폼인 FastTrack을 소개합니다.&quot; data-og-host=&quot;blog.lablup.com&quot; data-og-source-url=&quot;https://blog.lablup.com/posts/2022/11/29/introduce-fasttrack&quot; data-og-url=&quot;https://blog.lablup.com/posts/2022/11/29/introduce-fasttrack&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/damp3X/hyRcMh184t/YDtHP4gmNuuHKCiNli7YeK/img.png?width=1300&amp;amp;height=474&amp;amp;face=0_0_1300_474,https://scrap.kakaocdn.net/dn/zO28z/hyRcCGskhJ/OaoknMHDzaOqmS2q0vc0S1/img.png?width=740&amp;amp;height=634&amp;amp;face=0_0_740_634,https://scrap.kakaocdn.net/dn/buWqVU/hyRcGhO5DU/1olKXf3bKxUKsUJ2unoQK0/img.png?width=340&amp;amp;height=694&amp;amp;face=0_0_340_694&quot;&gt;&lt;a href=&quot;https://blog.lablup.com/posts/2022/11/29/introduce-fasttrack&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://blog.lablup.com/posts/2022/11/29/introduce-fasttrack&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/damp3X/hyRcMh184t/YDtHP4gmNuuHKCiNli7YeK/img.png?width=1300&amp;amp;height=474&amp;amp;face=0_0_1300_474,https://scrap.kakaocdn.net/dn/zO28z/hyRcCGskhJ/OaoknMHDzaOqmS2q0vc0S1/img.png?width=740&amp;amp;height=634&amp;amp;face=0_0_740_634,https://scrap.kakaocdn.net/dn/buWqVU/hyRcGhO5DU/1olKXf3bKxUKsUJ2unoQK0/img.png?width=340&amp;amp;height=694&amp;amp;face=0_0_340_694');&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;Backend.AI MLOps 플랫폼 FastTrack을 소개합니다. | Lablup Blog&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;이번 글에서는 Backend.AI의 MLOps 플랫폼인 FastTrack을 소개합니다.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;blog.lablup.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;&lt;b&gt;10월&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&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;&lt;b&gt;11월&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;12월&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>사람다운 삶</category>
      <category>회고록</category>
      <author>rapsealk</author>
      <guid isPermaLink="true">https://rapsealk.tistory.com/24</guid>
      <comments>https://rapsealk.tistory.com/24#entry24comment</comments>
      <pubDate>Sat, 7 Jan 2023 22:59:36 +0900</pubDate>
    </item>
    <item>
      <title>Go언어와 CUDA Runtime API(cudart)</title>
      <link>https://rapsealk.tistory.com/21</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;기존에 &lt;b&gt;Python&lt;/b&gt;으로 작성했던 프로젝트를 &lt;b&gt;Go&lt;/b&gt;로 다시 작성하는 과정에서 &lt;b&gt;CUDA&lt;/b&gt;와 관련하여 문제가 발생했다. Python의 경우 &lt;a href=&quot;https://developer.nvidia.com/cuda-python&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;cuda-python&lt;/a&gt;이라는 &lt;a href=&quot;https://pypi.org/project/cuda-python/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;패키지&lt;/a&gt;가 공식적으로 지원되는 데 반해, 아직 Go에는 그런 것이 존재하지 않았다. Go에서 CUDA의 기능을 이용하기 위한 방법들을 찾아보다가, &lt;b&gt;&lt;a href=&quot;https://go.dev/blog/cgo&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;cgo&lt;/a&gt;&lt;/b&gt;라는 것을 이용하여 C 코드를 실행할 수 있다는 것을 알 수 있었다. &lt;a href=&quot;https://go.dev/blog/cgo&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;cgo&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://go.dev/blog/cgo&quot;&gt;C? Go? Cgo! - The Go Programming Language&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1650784803421&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;C? Go? Cgo! - The Go Programming Language&quot; data-og-description=&quot;C? Go? Cgo! Andrew Gerrand 17 March 2011 Introduction Cgo lets Go packages call C code. Given a Go source file written with some special features, cgo outputs Go and C files that can be combined into a single Go package. To lead with an example, here&amp;rsquo;s a&quot; data-og-host=&quot;go.dev&quot; data-og-source-url=&quot;https://go.dev/blog/cgo&quot; data-og-url=&quot;https://go.dev/blog/cgo&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bwZPFX/hyN8CcLZJe/d0R46Y8dABFZmGnoPaJ2SK/img.jpg?width=299&amp;amp;height=281&amp;amp;face=0_0_299_281&quot;&gt;&lt;a href=&quot;https://go.dev/blog/cgo&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://go.dev/blog/cgo&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bwZPFX/hyN8CcLZJe/d0R46Y8dABFZmGnoPaJ2SK/img.jpg?width=299&amp;amp;height=281&amp;amp;face=0_0_299_281');&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;C? Go? Cgo! - The Go Programming Language&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;C? Go? Cgo! Andrew Gerrand 17 March 2011 Introduction Cgo lets Go packages call C code. Given a Go source file written with some special features, cgo outputs Go and C files that can be combined into a single Go package. To lead with an example, here&amp;rsquo;s a&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;go.dev&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;cgo를 사용하기 위해서는 import &quot;C&quot; 구문 바로 이전에 주석의 형태로 C 코드를 작성하면 되는데, 이것을 preamble이라고 부른다. 이렇게 작성된 코드는 Go 런타임에서 C 패키지를 통해 접근이 가능해진다. 또한 #cgo 지시자를 통해 컴파일러에 옵션을 전달할 수 있다. 이 글에서는 gcc를 사용하였으며, CUDA Runtime API를 사용하기 위하여 아래와 같은 형태로 작성하였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1650785298369&quot; class=&quot;go&quot; data-ke-language=&quot;go&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// #cgo CFLAGS: -I/usr/local/cuda/include
// #cgo LDFLAGS: -L/usr/local/cuda/lib64 -lcudart
// #include &amp;lt;cuda_runtime_api.h&amp;gt;
import &quot;C&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;이제 Go에서 CUDA Runtime API를 사용할 수 있게 되었다. 코드를 작성하기에 앞서, 아래의 문서를 통해 CUDA Runtime API의 명세를 확인할 수 있다.(본 글에서는 cudaGetDeviceCount, cudaGetDeviceProperties 등 Device Management 관련 API만을 사용한다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://docs.nvidia.com/cuda/cuda-runtime-api/group__CUDART__DEVICE.html&quot;&gt;CUDA Runtime API :: CUDA Toolkit Documentation (nvidia.com)&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1650785516798&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;CUDA Runtime API :: CUDA Toolkit Documentation&quot; data-og-description=&quot;Destroy all allocations and reset all state on the current device in the current process. Explicitly destroys and cleans up all resources associated with the current device in the current process. It is the caller's responsibility to ensure that the resour&quot; data-og-host=&quot;docs.nvidia.com&quot; data-og-source-url=&quot;https://docs.nvidia.com/cuda/cuda-runtime-api/group__CUDART__DEVICE.html&quot; data-og-url=&quot;https://docs.nvidia.com/cuda/cuda-runtime-api/group__CUDART__DEVICE.html&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://docs.nvidia.com/cuda/cuda-runtime-api/group__CUDART__DEVICE.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://docs.nvidia.com/cuda/cuda-runtime-api/group__CUDART__DEVICE.html&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;CUDA Runtime API :: CUDA Toolkit Documentation&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Destroy all allocations and reset all state on the current device in the current process. Explicitly destroys and cleans up all resources associated with the current device in the current process. It is the caller's responsibility to ensure that the resour&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;docs.nvidia.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;이제 본격적으로 Go 코드를 작성해 보도록 하겠다.&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. cudaGetDeviceCount&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;cudaGetDeviceCount는 사용 가능한 CUDA Device의 갯수를 읽어오는 함수로, 그 명세는 아래와 같다.&lt;/p&gt;
&lt;pre id=&quot;code_1650785946842&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;__host____device__cudaError_t cudaGetDeviceCount ( int* count )&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;함수에 전달한 int형 주소값인 count를 역참조하여 CUDA Device의 갯수 정보를 입력하고, 함수의 반환값으로는 에러의 유무를 전달하여 정상적으로 처리되었는지를 알 수 있게 한다. 이 API를 Go로 사용하기 위하여 아래와 같이 작성할 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1650786224113&quot; class=&quot;go&quot; data-ke-language=&quot;go&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import &quot;errors&quot;

var ErrCUDAInvalidValue = errors.New(&quot;This indicates that one or more..&quot;)

func CUDAGetDeviceCount() (int32, error) {
    var deviceCount C.int
    if C.cudaGetDeviceCount(&amp;amp;deviceCount) != 0 {
        return 0, ErrCUDAInvalidValue
    }
    return int32(deviceCount), nil
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이때 C 함수에는 *C.int 자료형을 전달하고, Go 함수에서 반환할 때는 int32 자료형으로 변환했음에 유의하자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. cudaGetDeviceProperties&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;cudaGetDeviceProperties는 n번째 CUDA Device의 정보를 읽어오는 함수로, 그 명세는 아래와 같다.&lt;/p&gt;
&lt;pre id=&quot;code_1650786394254&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;__host__cudaError_t cudaGetDeviceProperties ( cudaDeviceProp* prop, int  device )&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마찬가지로 함수에 전달한 cudaDeviceProp형 주소값인 prop을 역참조하여 device 번째에 해당하는 CUDA Device의 정보를 입력하고, 함수의 반환값으로는 에러의 유무를 전달한다. 이 API를 Go로 사용하기 위하여 아래와 같이 작성할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1650786737342&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import (
    &quot;encoding/hex&quot;
    &quot;fmt&quot;
)

func CUDAGetDeviceProperties(device int32) (C.struct_cudaDeviceProp, error) {
    var prop C.struct_cudaDeviceProp
    if C.cudaGetDeviceProperties(&amp;amp;prop, C.int(device)) != 0 {
        return prop, ErrCUDAInvalidValue
    }
    c_uuid := []byte(C.GoString(&amp;amp;prop.uuid.bytes[0]))
    uuid := make([]byte, hex.EncodedLen(len(c_uuid)))
    hex.Encode(uuid, c_uuid)
    fmt.Println(&quot;Name:&quot;, C.GoString(&amp;amp;prop.name[0]))
    fmt.Println(&quot;UUID:&quot;, string(uuid))
    fmt.Println(&quot;Total Global Memory:&quot;, prop.totalGlobalMem)
    return prop, nil
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이때 C에서 정의된 struct cudaDeviceProp {...}과 같은 구조체는 C.struct_cudaDeviceProp과 같은 형태로 접근할 수 있다. 또한 C.GoString은 *_Ctype_char을 인자로 받기 때문에, []_Ctype_char 자료형인 prop.name을 &amp;amp;prop.name[0]의 형태로 참조하였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1650787281668&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Hello, MLRD!
GPU Device count: 1
Name: NVIDIA GeForce GTX 1660 Ti
UUID: cfd68e3d1d6d95b3e8240890188f0536
Total Global Memory: 6441992192&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;a href=&quot;https://github.com/rapsealk/go-cuda&quot;&gt;https://github.com/rapsealk/go-cuda&lt;/a&gt;&lt;/p&gt;</description>
      <category>CUDA</category>
      <category>go</category>
      <author>rapsealk</author>
      <guid isPermaLink="true">https://rapsealk.tistory.com/21</guid>
      <comments>https://rapsealk.tistory.com/21#entry21comment</comments>
      <pubDate>Sun, 24 Apr 2022 17:05:10 +0900</pubDate>
    </item>
    <item>
      <title>[Web] Drop Event 발생시키기</title>
      <link>https://rapsealk.tistory.com/20</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;* 이 글에서 나오는 프로그램은 웹사이트를 돌아다니며 미술관에서 작품을 안내하는 &lt;b&gt;도슨트&lt;/b&gt;처럼 각 사이트의 내용을 설명해주는 기능을 한다. 사용자는 프로그램에 내장된 WebView를 통해 일정 시간마다 각 사이트로 이동하게 되고, 매 사이트에 도착할 때마다 그곳을 설명하는 나레이션이 실행된다.&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://musiclab.chromeexperiments.com/Spectrogram/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://musiclab.chromeexperiments.com/Spectrogram/&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1639496170017&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;Chrome Music Lab&quot; data-og-description=&quot;Music is for everyone. Play with simple experiments that let anyone, of any age, explore how music works.&quot; data-og-host=&quot;musiclab.chromeexperiments.com&quot; data-og-source-url=&quot;https://musiclab.chromeexperiments.com/Spectrogram/&quot; data-og-url=&quot;https://musiclab.chromeexperiments.com&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/xNvAw/hyMH3nF7VQ/qQhmg7XmAkdg0p9u6AkSTk/img.jpg?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/ekg6qk/hyMGZNZzs5/IJRjz65Ari80zUkygHfME1/img.jpg?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630&quot;&gt;&lt;a href=&quot;https://musiclab.chromeexperiments.com/Spectrogram/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://musiclab.chromeexperiments.com/Spectrogram/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/xNvAw/hyMH3nF7VQ/qQhmg7XmAkdg0p9u6AkSTk/img.jpg?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/ekg6qk/hyMGZNZzs5/IJRjz65Ari80zUkygHfME1/img.jpg?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630');&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;Chrome Music Lab&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Music is for everyone. Play with simple experiments that let anyone, of any age, explore how music works.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;musiclab.chromeexperiments.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이 사이트는 다양한 소리의 스펙트로그램을 시각화하여 보여주는 기능을 제공한다. 플룻, 하프, 휘파람 등의 샘플 소리들을 기본적으로 제공해주며, 마이크를 통해 입력된 소리를 이용할 수도 있다. 또한 드래그 앤 드롭을 통해 midi 이외의 오디오 파일의 실행도 지원해준다.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;978&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dR3868/btrnQk4gtSg/TMPD4ykoE1ypVy6ma2HP80/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dR3868/btrnQk4gtSg/TMPD4ykoE1ypVy6ma2HP80/img.png&quot; data-alt=&quot;Chrome Music Lab의 Spectrogram 서비스&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dR3868/btrnQk4gtSg/TMPD4ykoE1ypVy6ma2HP80/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdR3868%2FbtrnQk4gtSg%2FTMPD4ykoE1ypVy6ma2HP80%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;1920&quot; height=&quot;978&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;978&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Chrome Music Lab의 Spectrogram 서비스&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;이 재미난 사이트에서 주어진 요구사항은 아래와 같다.&lt;/div&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;현재 실행되고 있는 나레이션의 스펙트로그램을 보여주도록 한다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;이 요구사항을 충족하기 위해 밟아온 단계들을 차례로 정리하고자 한다.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;0. 가상 Element 파헤치기&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;사용자의 마이크 입력을 전달받기 위해서는 아래에 있는 여러 버튼들 중 가장 왼쪽에 있는 버튼을 클릭해야 한다. 이 과정을 자바스크립트로 구현하는 과정에서 버튼의 클래스 이름을 알아내고 아래와 같은 방식으로 접근했다.&lt;/div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1639497213996&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;document.getElementsByClassName('music-box__buttons__button');&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;하지만 결과는 텅 빈 HTMLCollection[]가 돌아올 뿐이었다. 몇 번의 시행착오를 통해 해당 요소가 iframe을 통해 불러온 것이며, 가상 Element로 이루어졌음을 확인할 수 있었다. 가상 Element는 사용자의 입력이 발생하기 전에는 Element에 접근이 되지 않는 것 같다. 아래와 같은 iframe 태그를 찾을 수 있었고, 실제 기능을 수행하는 페이지의 주소를 알아낼 수 있었다.&lt;/div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1639496973531&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;iframe id=&quot;experimentFrame&quot;&amp;gt;&amp;lt;/iframe&amp;gt;​&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #6a9955;&quot;&gt;&lt;a href=&quot;https://musiclab.chromeexperiments.com/spectrogram-service/?ln=ko&quot;&gt;https://musiclab.chromeexperiments.com/spectrogram-service/?ln=ko&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;
&lt;figure id=&quot;og_1639496186762&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;3D Spectrogram&quot; data-og-description=&quot;&quot; data-og-host=&quot;musiclab.chromeexperiments.com&quot; data-og-source-url=&quot;https://musiclab.chromeexperiments.com/spectrogram-service/?ln=ko&quot; data-og-url=&quot;https://musiclab.chromeexperiments.com/spectrogram-service/?ln=ko&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://musiclab.chromeexperiments.com/spectrogram-service/?ln=ko&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://musiclab.chromeexperiments.com/spectrogram-service/?ln=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;3D Spectrogram&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;musiclab.chromeexperiments.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div&gt;1. StereoMix&lt;/div&gt;
&lt;div&gt;첫 번째로 사용한 방법은 StereoMix를 이용한 방법이다. 정확히는 Chrome Music Lab의 마이크 기능을 이용하기 위하여 StereoMix를 통해 소리를 전달하도록 하였다.&lt;/div&gt;
&lt;div&gt;StereoMix는 현재 스피커에 출력되고 있는 소리를 녹음할 수 있도록 해주는 가상 오디오 입력 장치다. 오디오 입력 장치를 StereoMix로 설정한 후 마이크 버튼을 누르면 실행 중인 소리를 그대로 입력으로 전달할 수 있다.&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;465&quot; data-origin-height=&quot;518&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cvyskU/btrnVx8TFoa/B9sHJfqdl9CLZHOwwp9N71/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cvyskU/btrnVx8TFoa/B9sHJfqdl9CLZHOwwp9N71/img.png&quot; data-alt=&quot;Stereo Mix 오디오 장치 (Windows)&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cvyskU/btrnVx8TFoa/B9sHJfqdl9CLZHOwwp9N71/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcvyskU%2FbtrnVx8TFoa%2FB9sHJfqdl9CLZHOwwp9N71%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;465&quot; height=&quot;518&quot; data-origin-width=&quot;465&quot; data-origin-height=&quot;518&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Stereo Mix 오디오 장치 (Windows)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;StereoMix의 설정 방법은 아래와 같다.&lt;/div&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;https://www.intel.com/content/www/us/en/download/19336/realtek-high-definition-audio-driver-for-windows-10-64-bit-for-nuc8i7be-nuc8i5be-nuc8i3be.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Realtek High Definition Audio (SST) 드라이버&lt;/a&gt;를 설치한다.&lt;/li&gt;
&lt;li&gt;제어판 &amp;gt; 하드웨어 및 소리 &amp;gt; 소리로 이동한 후, 녹음 장치를 스테레오 믹스로 설정한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 설정한 후 정상적으로 기능이 작동함을 확인할 수 있었다. 하지만 이런 방법에는 아래와 같은 문제점이 있었다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;실행 PC에 Realtek 드라이버가 설치되었음을 보장할 수 없다.&lt;/li&gt;
&lt;li&gt;오디오 입력 장치를 임의로 설정/변경하는 방법을 찾지 못했다. (레지스트리로 접근했지만..)&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;따라서 별도의 설정이 필요하지 않은 드래그 앤 드롭 기능을 이용하는 방법으로 변경하기로 했다.&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div&gt;2. Drop Event&lt;/div&gt;
&lt;div&gt;드래그 앤 드롭 기능을 이용하기 위해서는 'drop' 이벤트를 어떻게 처리하는지 확인할 필요가 있었다. 따라서 해당 페이지에서 동작하는 자바스크립트 코드를 분석하기로 했다. 그렇게 지옥문이 열렸다.&lt;/div&gt;
&lt;div&gt;&lt;a href=&quot;https://musiclab.chromeexperiments.com/js/app.js&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://musiclab.chromeexperiments.com/js/app.js&lt;/a&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2-1. 어떤 Element가 이벤트를 처리하는가?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아름다운 minify가 적용되어 덤으로 난독화까지 적용된 모습이었다. 우선 'drop' 이벤트에 대한 처리 방식을 찾아야 했기 때문에, 'drop' 단어를 검색해봤다. 그 결과 아래와 같은 처리 함수가 등록되었음을 확인할 수 있었다.&lt;/p&gt;
&lt;pre id=&quot;code_1639498273682&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function (n) {
	n.preventDefault(), n.stopPropagation(), e.addClass(&quot;pointer-events&quot;), i();
	var s = n.originalEvent.dataTransfer;
	s &amp;amp;&amp;amp; s.files.length &amp;amp;&amp;amp; s.items[0] &amp;amp;&amp;amp; &quot;audio/midi&quot; !== s.items[0].type
		? $.each(s.files, function (n, i) {
			i.type.indexOf(&quot;audio&quot;) &amp;gt; -1
				? ($(&quot;#loadingMessage&quot;).text(i.name), $(&quot;#loadingSound&quot;).show(0), r(i), e.removeClass(&quot;active&quot;), e.removeClass(&quot;pointer-events&quot;))
					: t.text(&quot;Only sound files will work here.&quot;);
		})
		: t.text(&quot;Only sound files will work here.&quot;);
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 저 처리 함수가 어떤 Element에 등록되었는지 확인해야 했다. 이것을 확인하기 위하여 사용자가 파일을 드롭하는 영역에 'drop' 이벤트 리스너를 추가하였고, 파일을 드랍했을 때 실제로 반응하는 Element가 무엇인지 확인했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2-2. 어떻게 파일을 전달할 것인가?&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;위의 이벤트 처리 함수를 보면 dataTransfer에 담긴 파일을 처리하는 방식임을 알 수 있었다. 그렇다면 이제 audio/mp3 파일을 dataTransfer에 담아서 전달해주기만 하면 될 것 같다. dataTransfer에 대한 내용은 아래에서 확인할 수 있었다.&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://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API/Drag_operations&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API/Drag_operations&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1639498582679&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;Drag Operations - Web APIs | MDN&quot; data-og-description=&quot;The following describes the steps that occur during a drag and drop operation.&quot; data-og-host=&quot;developer.mozilla.org&quot; data-og-source-url=&quot;https://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API/Drag_operations&quot; data-og-url=&quot;https://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API/Drag_operations&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/gMZnj/hyMH7KpiOF/HkLDu6XykVLnXhgHciEQSK/img.png?width=1920&amp;amp;height=1080&amp;amp;face=0_0_1920_1080&quot;&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API/Drag_operations&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API/Drag_operations&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/gMZnj/hyMH7KpiOF/HkLDu6XykVLnXhgHciEQSK/img.png?width=1920&amp;amp;height=1080&amp;amp;face=0_0_1920_1080');&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;Drag Operations - Web APIs | MDN&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;The following describes the steps that occur during a drag and drop operation.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;developer.mozilla.org&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://developer.mozilla.org/ko/docs/Web/API/DataTransfer&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://developer.mozilla.org/ko/docs/Web/API/DataTransfer&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1639498593458&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;DataTransfer - Web API | MDN&quot; data-og-description=&quot;The DataTransfer object is used to hold the data that is being dragged during a drag and drop operation. It may hold one or more data items, each of one or more data types. For more information about drag and drop, see HTML Drag and Drop API.&quot; data-og-host=&quot;developer.mozilla.org&quot; data-og-source-url=&quot;https://developer.mozilla.org/ko/docs/Web/API/DataTransfer&quot; data-og-url=&quot;https://developer.mozilla.org/ko/docs/Web/API/DataTransfer&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/vyazp/hyMG3CRPx9/KlCn0J5w1dfF4AAvUZQ9hK/img.png?width=1920&amp;amp;height=1080&amp;amp;face=0_0_1920_1080&quot;&gt;&lt;a href=&quot;https://developer.mozilla.org/ko/docs/Web/API/DataTransfer&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://developer.mozilla.org/ko/docs/Web/API/DataTransfer&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/vyazp/hyMG3CRPx9/KlCn0J5w1dfF4AAvUZQ9hK/img.png?width=1920&amp;amp;height=1080&amp;amp;face=0_0_1920_1080');&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;DataTransfer - Web API | MDN&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;The DataTransfer object is used to hold the data that is being dragged during a drag and drop operation. It may hold one or more data items, each of one or more data types. For more information about drag and drop, see HTML Drag and Drop API.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;developer.mozilla.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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2-3. 아뿔싸! originalEvent가 무엇인가?&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;jQuery에서는 DOM Event 객체를 jQuery.Event 객체로 래핑하여 사용함을 알 수 있었다.&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://api.jquery.com/category/events/event-object/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://api.jquery.com/category/events/event-object/&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1639498650510&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;Event Object | jQuery API Documentation&quot; data-og-description=&quot;The current DOM element within the event bubbling phase. An optional object of data passed to an event method when the current executing handler is bound. The element where the currently-called jQuery event handler was attached. Returns whether event.preve&quot; data-og-host=&quot;api.jquery.com&quot; data-og-source-url=&quot;https://api.jquery.com/category/events/event-object/&quot; data-og-url=&quot;https://api.jquery.com/category/events/event-object/&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://api.jquery.com/category/events/event-object/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://api.jquery.com/category/events/event-object/&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;Event Object | jQuery API Documentation&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;The current DOM element within the event bubbling phase. An optional object of data passed to an event method when the current executing handler is bound. The element where the currently-called jQuery event handler was attached. Returns whether event.preve&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;api.jquery.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Drag</category>
      <category>drop</category>
      <category>JavaScript</category>
      <category>jquery</category>
      <category>web</category>
      <author>rapsealk</author>
      <guid isPermaLink="true">https://rapsealk.tistory.com/20</guid>
      <comments>https://rapsealk.tistory.com/20#entry20comment</comments>
      <pubDate>Wed, 15 Dec 2021 01:17:52 +0900</pubDate>
    </item>
    <item>
      <title>Visual Studio Code와 Docker를 이용한 원격 코딩</title>
      <link>https://rapsealk.tistory.com/19</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;필자는 2019년 다음과 같은 글을 작성하였다. (&lt;/span&gt;&lt;a style=&quot;letter-spacing: 0px;&quot; href=&quot;https://rapsealk.tistory.com/10&quot;&gt;https://rapsealk.tistory.com/10&lt;/a&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&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;하지만 시간은 흐르고, 이제는 Linux 환경을 넘어 Docker를 다룰 줄 아는 것이 기본 소양인 시대가 되었다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;650&quot; data-origin-height=&quot;530&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bNvnNn/btrg8ETFsP9/h2FmRaoZWIFUYPzSPXZcq1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bNvnNn/btrg8ETFsP9/h2FmRaoZWIFUYPzSPXZcq1/img.png&quot; data-alt=&quot;Docker&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bNvnNn/btrg8ETFsP9/h2FmRaoZWIFUYPzSPXZcq1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbNvnNn%2Fbtrg8ETFsP9%2Fh2FmRaoZWIFUYPzSPXZcq1%2Fimg.png&quot; data-origin-width=&quot;650&quot; data-origin-height=&quot;530&quot; data-ke-mobilestyle=&quot;widthOrigin&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;/&gt;&lt;/span&gt;&lt;figcaption&gt;Docker&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;준비사항: Visual Studio Code, Docker가 실행 중인 (원격) 서버&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참고: &lt;a href=&quot;https://code.visualstudio.com/docs/containers/ssh&quot;&gt;https://code.visualstudio.com/docs/containers/ssh&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1633590668953&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;Connect to Docker engine running on a remote machine&quot; data-og-description=&quot;Connect via SSH to Docker engine running on a remote machine and use the remote machine as a development environment for Visual Studio Code.&quot; data-og-host=&quot;code.visualstudio.com&quot; data-og-source-url=&quot;https://code.visualstudio.com/docs/containers/ssh&quot; data-og-url=&quot;https://code.visualstudio.com/docs/containers/ssh&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/eR5rX/hyLStuv7kB/iWSOEJrskhQueDUCSv8Eu0/img.png?width=1012&amp;amp;height=506&amp;amp;face=0_0_1012_506&quot;&gt;&lt;a href=&quot;https://code.visualstudio.com/docs/containers/ssh&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://code.visualstudio.com/docs/containers/ssh&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/eR5rX/hyLStuv7kB/iWSOEJrskhQueDUCSv8Eu0/img.png?width=1012&amp;amp;height=506&amp;amp;face=0_0_1012_506');&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;Connect to Docker engine running on a remote machine&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Connect via SSH to Docker engine running on a remote machine and use the remote machine as a development environment for Visual Studio Code.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;code.visualstudio.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;[0] 현재 PC에 접속할 서버에 대한 fingerprint가 저장된 상태인지 확인한다. 처음 접속하는 경우라면, 아래의 명령어를 통해 서버에 접속하기 위한 fingerprint를 생성 및 저장할 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1633590820262&quot; class=&quot;shell&quot; style=&quot;margin: 20px auto 0px; display: block; overflow: auto; padding: 20px; color: #383a42; background: #f8f8f8; font-size: 14px; font-family: 'SF Mono', Menlo, Consolas, Monaco, monospace; border: 1px solid #ebebeb; line-height: 1.71; cursor: default; z-index: 1; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;gt; ssh &amp;lt;USER&amp;gt;@&amp;lt;HOSTNAME&amp;gt;[:&amp;lt;PORT&amp;gt;]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[1] Visual Studio Code에서 필요로 하는 Extension을 설치해 준다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;494&quot; data-origin-height=&quot;184&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bp8NVs/btrg1GszavQ/yC5HNEgAmkknp4vfi3EDQ1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bp8NVs/btrg1GszavQ/yC5HNEgAmkknp4vfi3EDQ1/img.png&quot; data-alt=&quot;VSCode: Docker&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bp8NVs/btrg1GszavQ/yC5HNEgAmkknp4vfi3EDQ1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbp8NVs%2Fbtrg1GszavQ%2FyC5HNEgAmkknp4vfi3EDQ1%2Fimg.png&quot; data-origin-width=&quot;494&quot; data-origin-height=&quot;184&quot; data-ke-mobilestyle=&quot;widthOrigin&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;/&gt;&lt;/span&gt;&lt;figcaption&gt;VSCode: Docker&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;546&quot; data-origin-height=&quot;170&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cGjpUP/btrg2MlzfI1/XOkVk2rZdz8p8WOklOFIB1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cGjpUP/btrg2MlzfI1/XOkVk2rZdz8p8WOklOFIB1/img.png&quot; data-alt=&quot;VSCode: Remote - Container&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cGjpUP/btrg2MlzfI1/XOkVk2rZdz8p8WOklOFIB1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcGjpUP%2Fbtrg2MlzfI1%2FXOkVk2rZdz8p8WOklOFIB1%2Fimg.png&quot; data-origin-width=&quot;546&quot; data-origin-height=&quot;170&quot; data-ke-mobilestyle=&quot;widthOrigin&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;/&gt;&lt;/span&gt;&lt;figcaption&gt;VSCode: Remote - Container&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;492&quot; data-origin-height=&quot;170&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Oifvg/btrg8D8iEEW/GXGYtH02eBG87DYWoOX0BK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Oifvg/btrg8D8iEEW/GXGYtH02eBG87DYWoOX0BK/img.png&quot; data-alt=&quot;VSCode: Remote - SSH&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Oifvg/btrg8D8iEEW/GXGYtH02eBG87DYWoOX0BK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FOifvg%2Fbtrg8D8iEEW%2FGXGYtH02eBG87DYWoOX0BK%2Fimg.png&quot; data-origin-width=&quot;492&quot; data-origin-height=&quot;170&quot; data-ke-mobilestyle=&quot;widthOrigin&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;/&gt;&lt;/span&gt;&lt;figcaption&gt;VSCode: Remote - SSH&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;[2] File &amp;gt; Preferences &amp;gt; Settings에 들어간 후 docker.host 항목에 접속할 ssh 서버 주소를 입력한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[3] Ctrl+Shift+P를 누른 후, Remote-Containers: Attach to Running Container...를 선택한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;626&quot; data-origin-height=&quot;342&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bcKTTl/btrg8gyESMW/Kib0OC4bsTmcmJcfUaVHjk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bcKTTl/btrg8gyESMW/Kib0OC4bsTmcmJcfUaVHjk/img.png&quot; data-alt=&quot;Attach to Running Container...&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bcKTTl/btrg8gyESMW/Kib0OC4bsTmcmJcfUaVHjk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbcKTTl%2Fbtrg8gyESMW%2FKib0OC4bsTmcmJcfUaVHjk%2Fimg.png&quot; data-origin-width=&quot;626&quot; data-origin-height=&quot;342&quot; data-ke-mobilestyle=&quot;widthOrigin&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;/&gt;&lt;/span&gt;&lt;figcaption&gt;Attach to Running Container...&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>docker</category>
      <category>Visual Studio Code</category>
      <author>rapsealk</author>
      <guid isPermaLink="true">https://rapsealk.tistory.com/19</guid>
      <comments>https://rapsealk.tistory.com/19#entry19comment</comments>
      <pubDate>Thu, 7 Oct 2021 16:25:24 +0900</pubDate>
    </item>
    <item>
      <title>오픈 소스 컨트리뷰션 도전기</title>
      <link>https://rapsealk.tistory.com/18</link>
      <description>&lt;p&gt;1. 해당 소프트웨어를 사용하는 유저들의 니즈를 파악할 수 있다.&lt;/p&gt;
&lt;p&gt;2. 소프트웨어 프로젝트의 운영 방식과 소통 방법을 이해하고 경험할 수 있다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;발견한 이슈:&lt;/p&gt;
&lt;p&gt;- &lt;a href=&quot;https://github.com/microsoft/AirSim/issues/1711&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;github.com/microsoft/AirSim/issues/1711&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1618894891975&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-og-type=&quot;object&quot; data-og-title=&quot;Is it possible to manually specify the communication port? &amp;middot; Issue #1711 &amp;middot; microsoft/AirSim&quot; data-og-description=&quot;Is it possible to manually specify the communication port between the server and the python client? I want to do this so that I can start multiple instances of the environment and have multiple pyt...&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/microsoft/AirSim/issues/1711&quot; data-og-url=&quot;https://github.com/microsoft/AirSim/issues/1711&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/BqJCa/hyJWvum2pq/aZi7uNQqDMmrtV074hire1/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/microsoft/AirSim/issues/1711&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/microsoft/AirSim/issues/1711&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/BqJCa/hyJWvum2pq/aZi7uNQqDMmrtV074hire1/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;&gt;Is it possible to manually specify the communication port? &amp;middot; Issue #1711 &amp;middot; microsoft/AirSim&lt;/p&gt;
&lt;p class=&quot;og-desc&quot;&gt;Is it possible to manually specify the communication port between the server and the python client? I want to do this so that I can start multiple instances of the environment and have multiple pyt...&lt;/p&gt;
&lt;p class=&quot;og-host&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;커밋 목록:&lt;/p&gt;
&lt;p&gt;-&amp;nbsp;&lt;a href=&quot;https://github.com/microsoft/AirSim/commit/c88ffafffa7b272fceb1728376660b2074852eac&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;github.com/microsoft/AirSim/commit/c88ffafffa7b272fceb1728376660b2074852eac&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1618894816425&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-og-type=&quot;object&quot; data-og-title=&quot;Added RpcLibPort to change rpc port easily (#1711) &amp;middot; microsoft/AirSim@c88ffaf&quot; data-og-description=&quot;Permalink This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository. Browse files Added RpcLibPort to change rpc port easily (#1711) Loading branch information Showing 7 changed files with 44 additions&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/microsoft/AirSim/commit/c88ffafffa7b272fceb1728376660b2074852eac&quot; data-og-url=&quot;https://github.com/microsoft/AirSim/commit/c88ffafffa7b272fceb1728376660b2074852eac&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/drujLW/hyJWGbAq2q/U5FfoYgyJJkBdDkN6vmp8k/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/microsoft/AirSim/commit/c88ffafffa7b272fceb1728376660b2074852eac&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/microsoft/AirSim/commit/c88ffafffa7b272fceb1728376660b2074852eac&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/drujLW/hyJWGbAq2q/U5FfoYgyJJkBdDkN6vmp8k/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;&gt;Added RpcLibPort to change rpc port easily (#1711) &amp;middot; microsoft/AirSim@c88ffaf&lt;/p&gt;
&lt;p class=&quot;og-desc&quot;&gt;Permalink This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository. Browse files Added RpcLibPort to change rpc port easily (#1711) Loading branch information Showing 7 changed files with 44 additions&lt;/p&gt;
&lt;p class=&quot;og-host&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p&gt;- &lt;a href=&quot;https://github.com/microsoft/AirSim/commit/ed12bf75624df553dff06a30a149363c6c040535&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;github.com/microsoft/AirSim/commit/ed12bf75624df553dff06a30a149363c6c040535&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1618894819552&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-og-type=&quot;object&quot; data-og-title=&quot;fixed RpcLibPort following advice (#1981) &amp;middot; microsoft/AirSim@ed12bf7&quot; data-og-description=&quot;Permalink This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository. Browse files fixed RpcLibPort following advice (#1981) Loading branch information Showing 3 changed files with 2 additions and 16 de&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/microsoft/AirSim/commit/ed12bf75624df553dff06a30a149363c6c040535&quot; data-og-url=&quot;https://github.com/microsoft/AirSim/commit/ed12bf75624df553dff06a30a149363c6c040535&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/clF0KH/hyJWySaKBz/K8ObiPEeCNYX6TxcJ0oONk/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/microsoft/AirSim/commit/ed12bf75624df553dff06a30a149363c6c040535&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/microsoft/AirSim/commit/ed12bf75624df553dff06a30a149363c6c040535&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/clF0KH/hyJWySaKBz/K8ObiPEeCNYX6TxcJ0oONk/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;&gt;fixed RpcLibPort following advice (#1981) &amp;middot; microsoft/AirSim@ed12bf7&lt;/p&gt;
&lt;p class=&quot;og-desc&quot;&gt;Permalink This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository. Browse files fixed RpcLibPort following advice (#1981) Loading branch information Showing 3 changed files with 2 additions and 16 de&lt;/p&gt;
&lt;p class=&quot;og-host&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;최종 PR(Pull Request):&lt;/p&gt;
&lt;p&gt;-&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a href=&quot;https://github.com/microsoft/AirSim/pull/1981&quot;&gt;github.com/microsoft/AirSim/pull/1981&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1618894933784&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-og-type=&quot;object&quot; data-og-title=&quot;Added RpcLibPort to change rpc port easily (#1711) by rapsealk &amp;middot; Pull Request #1981 &amp;middot; microsoft/AirSim&quot; data-og-description=&quot;I found issue number #1711 while I was trying to change default rpc port, and thought it might be handy if there is a variable with common value. Thank you!&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/microsoft/AirSim/pull/1981&quot; data-og-url=&quot;https://github.com/microsoft/AirSim/pull/1981&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/dj05bQ/hyJWDzbDI4/DrLEbJyJUnIBjue1Kqh3U0/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/microsoft/AirSim/pull/1981&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/microsoft/AirSim/pull/1981&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/dj05bQ/hyJWDzbDI4/DrLEbJyJUnIBjue1Kqh3U0/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;&gt;Added RpcLibPort to change rpc port easily (#1711) by rapsealk &amp;middot; Pull Request #1981 &amp;middot; microsoft/AirSim&lt;/p&gt;
&lt;p class=&quot;og-desc&quot;&gt;I found issue number #1711 while I was trying to change default rpc port, and thought it might be handy if there is a variable with common value. Thank you!&lt;/p&gt;
&lt;p class=&quot;og-host&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>기타</category>
      <author>rapsealk</author>
      <guid isPermaLink="true">https://rapsealk.tistory.com/18</guid>
      <comments>https://rapsealk.tistory.com/18#entry18comment</comments>
      <pubDate>Tue, 20 Apr 2021 14:02:38 +0900</pubDate>
    </item>
    <item>
      <title>Windows 환경에서 virtualenv 사용하기</title>
      <link>https://rapsealk.tistory.com/17</link>
      <description>&lt;p&gt;Python 프로젝트를 운용할 경우, 모듈들이 중복되거나 꼬이는 현상을 막기 위하여 독립된 공간이 필요할 때가 있다. 이럴 때 사용할 수 있는 것이 바로 virtualenv(이하 venv)다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #333333;&quot;&gt;Windows 환경에서 virtualenv를 사용하기 위해서는 PowerShell을 &quot;관리자 권한으로 실행&quot;한 후 아래의 명령어를 실행시켜야 한다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1616494892851&quot; class=&quot;cs&quot; data-ke-language=&quot;cs&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Set-ExecutionPolicy Unrestricted -Force&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;이후 여느 환경과 동일하게 사용하면 된다.&lt;/p&gt;
&lt;pre id=&quot;code_1616494994293&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;source venv/Scripts/activate&lt;/code&gt;&lt;/pre&gt;</description>
      <category>venv</category>
      <category>virtualenv</category>
      <category>Windows</category>
      <author>rapsealk</author>
      <guid isPermaLink="true">https://rapsealk.tistory.com/17</guid>
      <comments>https://rapsealk.tistory.com/17#entry17comment</comments>
      <pubDate>Tue, 23 Mar 2021 19:23:39 +0900</pubDate>
    </item>
    <item>
      <title>PTR</title>
      <link>https://rapsealk.tistory.com/16</link>
      <description>&lt;p&gt;기록을 남긴다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;* (Deep) Reinforcement Learning&lt;/p&gt;
&lt;p&gt;- Playing Atari with Deep Reinforcement Learning, 2013&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;gt; 키워드: Deep Q Network&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;gt; 링크: &lt;a href=&quot;https://arxiv.org/abs/1312.5602&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;arxiv&lt;/a&gt;&lt;/p&gt;</description>
      <category>논문</category>
      <author>rapsealk</author>
      <guid isPermaLink="true">https://rapsealk.tistory.com/16</guid>
      <comments>https://rapsealk.tistory.com/16#entry16comment</comments>
      <pubDate>Tue, 24 Nov 2020 22:27:25 +0900</pubDate>
    </item>
    <item>
      <title>개인정보처리방침</title>
      <link>https://rapsealk.tistory.com/15</link>
      <description>&lt;p&gt;이 앱은 아래와 같은 이유로 안드로이드 권한을 필요로 합니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;- android.permission.CAMERA : 기기의 전면 카메라를 이용하여 사용자의 얼굴을 인식하기 위함.&lt;/span&gt;&lt;/p&gt;</description>
      <category>기타</category>
      <category>Android</category>
      <author>rapsealk</author>
      <guid isPermaLink="true">https://rapsealk.tistory.com/15</guid>
      <comments>https://rapsealk.tistory.com/15#entry15comment</comments>
      <pubDate>Wed, 26 Feb 2020 21:05:45 +0900</pubDate>
    </item>
    <item>
      <title>Kotlin 키워드 정리</title>
      <link>https://rapsealk.tistory.com/14</link>
      <description>&lt;p&gt;Java에서 사용하던 키워드 중 Kotlin에서 대응되는 키워드 목록을 (&lt;b&gt;&lt;span style=&quot;color: #953b34;&quot;&gt;Java&lt;/span&gt;&lt;/b&gt; -&amp;gt; &lt;b&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;Kotlin&lt;/span&gt;&lt;/b&gt;) 형태로 나열해보려 한다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;* &lt;b&gt;&lt;span style=&quot;color: #953b34;&quot;&gt;native&lt;/span&gt;&lt;/b&gt; -&amp;gt; &lt;b&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;external&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Java에서는 JNI(Java Native Interface)를 이용하여 C++로 작성된 함수를 실행할 때 &lt;span style=&quot;color: #953b34;&quot;&gt;&lt;b&gt;native&lt;/b&gt;&lt;/span&gt; 키워드를 이용해서 함수를 선언해준다.&lt;/p&gt;
&lt;pre id=&quot;code_1579858462741&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public native void print_hello();&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Kotlin에서는 &lt;b&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;external&lt;/span&gt;&lt;/b&gt; 키워드를 이용하여 아래와 같이 선언할 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1579858487777&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public external fun print_hello()&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;...&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Java</category>
      <category>kotlin</category>
      <category>native</category>
      <category>키워드</category>
      <author>rapsealk</author>
      <guid isPermaLink="true">https://rapsealk.tistory.com/14</guid>
      <comments>https://rapsealk.tistory.com/14#entry14comment</comments>
      <pubDate>Fri, 24 Jan 2020 18:35:07 +0900</pubDate>
    </item>
  </channel>
</rss>