<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>LuckyGg</title>
    <link>https://luckygg.tistory.com/</link>
    <description>LuckyGg의 블로그에 오신 것을 환영합니다 :)</description>
    <language>ko</language>
    <pubDate>Tue, 14 Apr 2026 12:33:30 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>　❤ </managingEditor>
    <image>
      <title>LuckyGg</title>
      <url>https://tistory1.daumcdn.net/tistory/2587971/attach/0bf2e88d709a4ef684910ed407303915</url>
      <link>https://luckygg.tistory.com</link>
    </image>
    <item>
      <title>[레드마인 플러그인] Redmine CKEditor pastebase64 (with Redmine 4.2.9)</title>
      <link>https://luckygg.tistory.com/404</link>
      <description>&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;소개&lt;/h2&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;CKEditor의 pastebase 플러그인은 &lt;b&gt;사용자가 클립보드에 복사한 이미지를 CKEditor 본문에 붙여 넣을 수 있도록 지원하는 플러그인&lt;/b&gt;입니다. CKEditor에서는 그림 첨부 형태로 이미지를 넣을 수 있는데요. PasteBase 플러그인을 설치하면 ctrl+v로 쉽게 이미지를 첨부할 수 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;설치 따라 하기&lt;/h2&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div style=&quot;color: #333333;&quot;&gt;&lt;span style=&quot;color: #000000; font-size: 1.44em; letter-spacing: -1px;&quot;&gt;1. 플러그인 파일 다운로드하기&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;p style=&quot;color: #333333;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;아래 링크에서 파일을 다운로드 하거나, 첨부된 파일을 사용합니다.&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;https://ckeditor.com/cke4/addon/pastebase64&lt;/blockquote&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/9xeP9/dJMb88lsMHJ/T4RYJGViLX5VwIbtTKOUl0/pastebase64_1.0.zip?attach=1&amp;amp;knm=tfile.zip&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;pastebase64_1.0.zip&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;size&quot;&gt;0.00MB&lt;/div&gt;
&lt;/div&gt;
  &lt;/a&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;2. 파일 복사하기&lt;/h3&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;Redmine Plugin 경로를 매핑했다면, 아래와 같이 업로드합니다.&lt;/p&gt;
&lt;blockquote style=&quot;background-color: #fcfcfc; color: #666666; text-align: left;&quot; data-ke-style=&quot;style3&quot;&gt;redmine/plugins/redmine_ckeditor/assets/ckeditor-contrib/plugins&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1050&quot; data-origin-height=&quot;698&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c7jfqw/btsP5njobc4/xGmMiLmrxrusgdt9BN0wwK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c7jfqw/btsP5njobc4/xGmMiLmrxrusgdt9BN0wwK/img.png&quot; data-alt=&quot;매핑된 경로에 복사하기&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c7jfqw/btsP5njobc4/xGmMiLmrxrusgdt9BN0wwK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc7jfqw%2FbtsP5njobc4%2FxGmMiLmrxrusgdt9BN0wwK%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;700&quot; height=&quot;465&quot; data-origin-width=&quot;1050&quot; data-origin-height=&quot;698&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;매핑된 경로에 복사하기&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;3. config.js 수정하기&lt;/h3&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;아래와 같이 config.js 파일을 수정합니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;redmine/plugins/redmine_ckeditor/assets/ckeditor/config.js&lt;/blockquote&gt;
&lt;blockquote style=&quot;background-color: #fcfcfc; color: #666666; text-align: left;&quot; data-ke-style=&quot;style3&quot;&gt;config.extraPlugins = 'pastebase64,base64image';&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1049&quot; data-origin-height=&quot;620&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bDPcRM/btsP2IQafqa/iydKZrJXDpX0FUKafkkaf1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bDPcRM/btsP2IQafqa/iydKZrJXDpX0FUKafkkaf1/img.png&quot; data-alt=&quot;config.js 수정하기&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bDPcRM/btsP2IQafqa/iydKZrJXDpX0FUKafkkaf1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbDPcRM%2FbtsP2IQafqa%2FiydKZrJXDpX0FUKafkkaf1%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;700&quot; height=&quot;414&quot; data-origin-width=&quot;1049&quot; data-origin-height=&quot;620&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;config.js 수정하기&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;4. init.rb 수정하기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래와 같이 init.rb 파일을 수정합니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;redmine/plugins/redmine_ckeditor&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;Loofah::HTML5::WhiteList::ALLOWED_PROTOCOLS.add('data')&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1049&quot; data-origin-height=&quot;620&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/6hGfp/btsP3yGhRcF/hFp7DtCX1C1ySnQ314gRHK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/6hGfp/btsP3yGhRcF/hFp7DtCX1C1ySnQ314gRHK/img.png&quot; data-alt=&quot;init.rb 수정하기&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/6hGfp/btsP3yGhRcF/hFp7DtCX1C1ySnQ314gRHK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F6hGfp%2FbtsP3yGhRcF%2FhFp7DtCX1C1ySnQ314gRHK%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;700&quot; height=&quot;414&quot; data-origin-width=&quot;1049&quot; data-origin-height=&quot;620&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;init.rb 수정하기&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;5. 레드마인 재시작&lt;/h3&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;따로 설치 명령어 없이 레드마인을 재시작하면 적용됩니다.&lt;/p&gt;</description>
      <category>Redmine/Plugin</category>
      <category>레드마인</category>
      <author>❤ </author>
      <guid isPermaLink="true">https://luckygg.tistory.com/404</guid>
      <comments>https://luckygg.tistory.com/404#entry404comment</comments>
      <pubDate>Fri, 5 Sep 2025 23:14:37 +0900</pubDate>
    </item>
    <item>
      <title>[레드마인 플러그인] Redmine CKEditor Codesnippet (with Redmine 4.2.9)</title>
      <link>https://luckygg.tistory.com/403</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;소개&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CKEditor의 Codesnippet 플러그인은 에디터에 작성한 &lt;b&gt;코드 블록을 보기 좋게 표시해 주는 플러그인&lt;/b&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;800&quot; data-origin-height=&quot;311&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b5xykx/btsP273gOBL/iSwqOzym06QuvAn1qI3QY0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b5xykx/btsP273gOBL/iSwqOzym06QuvAn1qI3QY0/img.png&quot; data-alt=&quot;codesnippet 적용 모습&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b5xykx/btsP273gOBL/iSwqOzym06QuvAn1qI3QY0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb5xykx%2FbtsP273gOBL%2FiSwqOzym06QuvAn1qI3QY0%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;800&quot; height=&quot;311&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;311&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;codesnippet 적용 모습&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;설치 따라 하기&lt;/h2&gt;
&lt;div class=&quot;rgyInfo&quot;&gt;
&lt;div class=&quot;rgyInfo-circle&quot;&gt;
&lt;div class=&quot;topDiv&quot;&gt;주의&lt;/div&gt;
&lt;div class=&quot;bottomDiv&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;bottomDiv2&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;rgyInfo-text&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CKEditor 공식 홈페이지에서 제공하는 codesnippet 플러그인 파일을 사용하면 오류가 발생합니다. 본문에 첨부된 파일을 사용하면 설치 및 사용에 문제는 없습니다.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. 플러그인 파일 다운로드하기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;적어도 아래의 파일은 Redmine 4.2.9와 CKEditor 1.2.3 버전에서 문제가 없습니다.&lt;/p&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/N9xY8/dJMb8WrNuSG/ZQuQ69WEALxTPHDM66RPE1/codesnippet.zip?attach=1&amp;amp;knm=tfile.zip&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;codesnippet.zip&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;size&quot;&gt;0.12MB&lt;/div&gt;
&lt;/div&gt;
  &lt;/a&gt;&lt;/figure&gt;
&lt;figure class=&quot;fileblock&quot; data-ke-align=&quot;alignCenter&quot;&gt;&lt;a href=&quot;https://blog.kakaocdn.net/dn/FV16L/dJMb9VzDB9K/kRcBrkUuFASx9w21frG291/lineutils.zip?attach=1&amp;amp;knm=tfile.zip&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;lineutils.zip&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;size&quot;&gt;0.01MB&lt;/div&gt;
&lt;/div&gt;
  &lt;/a&gt;&lt;/figure&gt;
&lt;figure class=&quot;fileblock&quot; data-ke-align=&quot;alignCenter&quot;&gt;&lt;a href=&quot;https://blog.kakaocdn.net/dn/dwOBVF/dJMb8Z9TxCD/2ockHIGxyOkFAXUJX0xxeK/widget.zip?attach=1&amp;amp;knm=tfile.zip&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;widget.zip&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;size&quot;&gt;0.08MB&lt;/div&gt;
&lt;/div&gt;
  &lt;/a&gt;&lt;/figure&gt;
&lt;figure class=&quot;fileblock&quot; data-ke-align=&quot;alignCenter&quot;&gt;&lt;a href=&quot;https://blog.kakaocdn.net/dn/bkI5IB/dJMb85bcFJz/WCKT4Zfb3FYPR9zeBXKKd0/widgetselection.zip?attach=1&amp;amp;knm=tfile.zip&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;widgetselection.zip&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;size&quot;&gt;0.00MB&lt;/div&gt;
&lt;/div&gt;
  &lt;/a&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. 파일 복사하기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Redmine Plugin 경로를 매핑했다면, 아래와 같이 업로드합니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;redmine\plugins\redmine_ckeditor\assets\ckeditor-contrib\plugins&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1595&quot; data-origin-height=&quot;894&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bHpryi/btsP3fmDNMO/iRahgkk8KLWJk16Kjw20w1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bHpryi/btsP3fmDNMO/iRahgkk8KLWJk16Kjw20w1/img.png&quot; data-alt=&quot;매핑된 경로에 복사하기&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bHpryi/btsP3fmDNMO/iRahgkk8KLWJk16Kjw20w1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbHpryi%2FbtsP3fmDNMO%2FiRahgkk8KLWJk16Kjw20w1%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;700&quot; height=&quot;392&quot; data-origin-width=&quot;1595&quot; data-origin-height=&quot;894&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;매핑된 경로에 복사하기&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. config.js 수정하기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래와 같이 config.js 파일을 수정합니다.&lt;/p&gt;
&lt;blockquote style=&quot;background-color: #fcfcfc; color: #666666; text-align: left;&quot; data-ke-style=&quot;style3&quot;&gt;redmine/plugins/redmine_ckeditor/assets/ckeditor/config.js&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;config.extraPlugins = 'widgetselection'; &lt;br /&gt;config.extraPlugins = 'lineutils'; &lt;br /&gt;config.extraPlugins = 'widget'; &lt;br /&gt;config.extraPlugins = 'codesnippet';&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1049&quot; data-origin-height=&quot;620&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/6ds1g/btsP5q1wU7c/JDtr72YKJNTly5yvLkGgBk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/6ds1g/btsP5q1wU7c/JDtr72YKJNTly5yvLkGgBk/img.png&quot; data-alt=&quot;config.js 수정하기&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/6ds1g/btsP5q1wU7c/JDtr72YKJNTly5yvLkGgBk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F6ds1g%2FbtsP5q1wU7c%2FJDtr72YKJNTly5yvLkGgBk%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;700&quot; height=&quot;414&quot; data-origin-width=&quot;1049&quot; data-origin-height=&quot;620&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;config.js 수정하기&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4. 레드마인 재시작&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따로 설치 명령어 없이 레드마인을 재시작하면 적용됩니다.&lt;/p&gt;</description>
      <category>Redmine/Plugin</category>
      <category>레드마인</category>
      <author>❤ </author>
      <guid isPermaLink="true">https://luckygg.tistory.com/403</guid>
      <comments>https://luckygg.tistory.com/403#entry403comment</comments>
      <pubDate>Fri, 29 Aug 2025 23:01:56 +0900</pubDate>
    </item>
    <item>
      <title>[레드마인 플러그인] Redmine CKEditor (with Redmine 4.2.9)</title>
      <link>https://luckygg.tistory.com/402</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;소개&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CKEditor는 글을 작성할 때 글자의 폰트, 색상, 스타일, 정렬, 그림 첨부, 코드 스니핏 등의 기능을 제공하는 에디터 툴이라고 생각하시면 됩니다. 레드마인은 기본적으로 마크다운을 제공하지만, 더 풍부한 기능을 사용하기 위해서는 CKEditor를 별도로 설치해야 합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1015&quot; data-origin-height=&quot;910&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dLPYCa/btsOA0LzBPN/nj0DTsSYJPtlCdjcaoAZT0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dLPYCa/btsOA0LzBPN/nj0DTsSYJPtlCdjcaoAZT0/img.png&quot; data-alt=&quot;CKEditor 편집 화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dLPYCa/btsOA0LzBPN/nj0DTsSYJPtlCdjcaoAZT0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdLPYCa%2FbtsOA0LzBPN%2Fnj0DTsSYJPtlCdjcaoAZT0%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;800&quot; height=&quot;717&quot; data-origin-width=&quot;1015&quot; data-origin-height=&quot;910&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;CKEditor 편집 화면&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;설치 따라 하기&lt;/h2&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;1. 저장소에서 최신 버전 다운로드하기&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;git clone -b 1.2.3 https://github.com/a-ono/redmine_ckeditor&lt;/blockquote&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. 파일 복사하기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Redmine Plugin 경로를 매핑했다면, 아래와 같이 업로드합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1593&quot; data-origin-height=&quot;896&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bh5gGs/btsP4mZOIe4/40DKrV9BpuDyyKZdqkGwq1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bh5gGs/btsP4mZOIe4/40DKrV9BpuDyyKZdqkGwq1/img.png&quot; data-alt=&quot;Plugin 경로에 파일 업로드하기&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bh5gGs/btsP4mZOIe4/40DKrV9BpuDyyKZdqkGwq1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbh5gGs%2FbtsP4mZOIe4%2F40DKrV9BpuDyyKZdqkGwq1%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;700&quot; height=&quot;394&quot; data-origin-width=&quot;1593&quot; data-origin-height=&quot;896&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Plugin 경로에 파일 업로드하기&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약, 매핑을 안 했다면 직접 다운로드한 파일을 Redmine plugin 경로로 복사해야 하는 번거로움이 있습니다. 차라리 셋업 과정에서 매핑을 해놓고 시작하는 게 좋습니다. 매핑 관련해서는 아래 게시물을 참고하세요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://luckygg.tistory.com/400&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;[Container Manager] MariaDB와 레드마인 구축하는 방법, 쉽게 따라하기&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1755951642634&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;[Container Manager] MariaDB와 레드마인 구축하는 방법, 쉽게 따라하기&quot; data-og-description=&quot;이제 Docker 대신 Container Manager  시놀로지 패키지 센터에서는 도커(Docker)와 레드마인(Redmine) 패키지를 제공하는데요. 이 패키지 설치를 통해 쉽고 편하게 레드마인을 구축할 수 있습니다. 하지만&quot; data-og-host=&quot;luckygg.tistory.com&quot; data-og-source-url=&quot;https://luckygg.tistory.com/400&quot; data-og-url=&quot;https://luckygg.tistory.com/400&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/Sy8WM/hyZzGheQB2/4tVpqSKdwN2VaV1VbVZVK0/img.png?width=800&amp;amp;height=431&amp;amp;face=0_0_800_431,https://scrap.kakaocdn.net/dn/AUhz2/hyZDMtj5Y4/WmNbhFK2ahY1bsERUmRN81/img.png?width=800&amp;amp;height=431&amp;amp;face=0_0_800_431,https://scrap.kakaocdn.net/dn/gn1rt/hyZzyKiWON/MSfxCsVc4b8mh6hV3UbdmK/img.png?width=1210&amp;amp;height=772&amp;amp;face=0_0_1210_772&quot;&gt;&lt;a href=&quot;https://luckygg.tistory.com/400&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://luckygg.tistory.com/400&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/Sy8WM/hyZzGheQB2/4tVpqSKdwN2VaV1VbVZVK0/img.png?width=800&amp;amp;height=431&amp;amp;face=0_0_800_431,https://scrap.kakaocdn.net/dn/AUhz2/hyZDMtj5Y4/WmNbhFK2ahY1bsERUmRN81/img.png?width=800&amp;amp;height=431&amp;amp;face=0_0_800_431,https://scrap.kakaocdn.net/dn/gn1rt/hyZzyKiWON/MSfxCsVc4b8mh6hV3UbdmK/img.png?width=1210&amp;amp;height=772&amp;amp;face=0_0_1210_772');&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;[Container Manager] MariaDB와 레드마인 구축하는 방법, 쉽게 따라하기&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;이제 Docker 대신 Container Manager  시놀로지 패키지 센터에서는 도커(Docker)와 레드마인(Redmine) 패키지를 제공하는데요. 이 패키지 설치를 통해 쉽고 편하게 레드마인을 구축할 수 있습니다. 하지만&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;luckygg.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;3. Redmine Plugin 경로에 파일 확인 후 설치하기&lt;/h3&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;아래 명령어로 플러그인 경로에 접근합니다.&lt;/p&gt;
&lt;blockquote style=&quot;background-color: #fcfcfc; color: #666666; text-align: left;&quot; data-ke-style=&quot;style3&quot;&gt;cd /home/redmine/redmine/plugins/&lt;/blockquote&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;그리고 아래 명령어로 파일 목록을 조회합니다.&lt;/p&gt;
&lt;blockquote style=&quot;background-color: #fcfcfc; color: #666666; text-align: left;&quot; data-ke-style=&quot;style3&quot;&gt;ls -l&lt;/blockquote&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;정상적으로 파일을 복사했다면 Redmine Plugin 경로에 아래와 같이 redmine_ckeditor 폴더가 있어야 합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1049&quot; data-origin-height=&quot;670&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/DvkZX/btsP25RRphT/9onw2xAOZizfkyfNKMQOGk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/DvkZX/btsP25RRphT/9onw2xAOZizfkyfNKMQOGk/img.png&quot; data-alt=&quot;플러그인 경로에 복사한 플러그인 확인하기&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/DvkZX/btsP25RRphT/9onw2xAOZizfkyfNKMQOGk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FDvkZX%2FbtsP25RRphT%2F9onw2xAOZizfkyfNKMQOGk%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;800&quot; height=&quot;511&quot; data-origin-width=&quot;1049&quot; data-origin-height=&quot;670&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;플러그인 경로에 복사한 플러그인 확인하기&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;설치를 위해 다시 레드마인 루트 경로로 이동합니다.&lt;/p&gt;
&lt;blockquote style=&quot;background-color: #fcfcfc; color: #666666; text-align: left;&quot; data-ke-style=&quot;style3&quot;&gt;cd /home/redmine/redmine&lt;/blockquote&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;아래 명령어를 실행합니다.&lt;/p&gt;
&lt;blockquote style=&quot;background-color: #fcfcfc; color: #666666; text-align: left;&quot; data-ke-style=&quot;style3&quot;&gt;bundle install --without development test&lt;br /&gt;&lt;br /&gt;bundle exec rails redmine:plugins:migrate RAILS_ENV=production&lt;/blockquote&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;설치에 문제가 없었다면 레드마인을 재시작합니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;만약, 위 설치 과정에서 여러 오류가 발생한다면, 아래 '&lt;b&gt;오류에 따른 조치 방법&lt;/b&gt;'을 참고하세요. 그리고 다시 위의 설치 명령어를 입력하여 재시도하시기 바랍니다.&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;참고로, 아래 조치 사항은 여러 시도 끝에 해결된 방법입니다. 불필요한 명령어가 있거나 순서가 틀릴 수 있지만, 제 상황에서는 문제가 해결되었습니다.&lt;/p&gt;
&lt;h3 style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;※ 오류에 따른 조치 방법&lt;/h3&gt;
&lt;h4 style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;mysql2 오류&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1049&quot; data-origin-height=&quot;670&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bE0UqQ/btsP4l7FC9q/4ZBfk4X0S69h67eNUdEnX0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bE0UqQ/btsP4l7FC9q/4ZBfk4X0S69h67eNUdEnX0/img.png&quot; data-alt=&quot;mysql2 에러&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bE0UqQ/btsP4l7FC9q/4ZBfk4X0S69h67eNUdEnX0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbE0UqQ%2FbtsP4l7FC9q%2F4ZBfk4X0S69h67eNUdEnX0%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;800&quot; height=&quot;511&quot; data-origin-width=&quot;1049&quot; data-origin-height=&quot;670&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;mysql2 에러&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 이미지처럼, mysql2 오류가 있다면 아래의 순서대로 진행해 보세요.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;sudo apt-get install -y build-essential libmysqlclient-dev&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약, 위 명령어를 실행해도 오류가 있다면 아래 명령어를 실행하세요.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;sudo apt-get update&lt;br /&gt;&lt;br /&gt;sudo apt-get install -y default-libmysqlclient-dev&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후 아래의 명령어를 실행하세요.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;gem install mysql2 -v '0.5.6'&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마지막으로 아래의 명령어를 실행합니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;bundle install&lt;/blockquote&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;ruby 2.7.0 오류&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1049&quot; data-origin-height=&quot;670&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cAeUQL/btsP2vDtqiV/uKjPzQeWAS0Ml660WrPko0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cAeUQL/btsP2vDtqiV/uKjPzQeWAS0Ml660WrPko0/img.png&quot; data-alt=&quot;ruby 2.7.0 오류&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cAeUQL/btsP2vDtqiV/uKjPzQeWAS0Ml660WrPko0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcAeUQL%2FbtsP2vDtqiV%2FuKjPzQeWAS0Ml660WrPko0%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;800&quot; height=&quot;511&quot; data-origin-width=&quot;1049&quot; data-origin-height=&quot;670&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;ruby 2.7.0 오류&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 이미지처럼, ruby 2.7.0 오류가 있다면 아래의 순서대로 진행해 보세요.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;bundle install --no-deployment&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약, sqlite3 에러가 발생한다면 아래 명령어를 실행하세요.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1049&quot; data-origin-height=&quot;620&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/t35MZ/btsP4jB2R6t/BFTzPyHqihpKwwhcmOkkmK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/t35MZ/btsP4jB2R6t/BFTzPyHqihpKwwhcmOkkmK/img.png&quot; data-alt=&quot;sqlite3 오류&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/t35MZ/btsP4jB2R6t/BFTzPyHqihpKwwhcmOkkmK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Ft35MZ%2FbtsP4jB2R6t%2FBFTzPyHqihpKwwhcmOkkmK%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;800&quot; height=&quot;473&quot; data-origin-width=&quot;1049&quot; data-origin-height=&quot;620&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;sqlite3 오류&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;sudo apt-get update&lt;br /&gt;&lt;br /&gt;sudo apt-get install -y sqlite3 libsqlite3-dev&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 아래의 명령어를 실행합니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;gem install sqlite3 -v '1.4.4'&lt;/blockquote&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;마지막으로 아래의 명령어를 실행합니다.&lt;/p&gt;
&lt;blockquote style=&quot;background-color: #fcfcfc; color: #666666; text-align: left;&quot; data-ke-style=&quot;style3&quot;&gt;bundle install&lt;/blockquote&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;pg 오류&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1049&quot; data-origin-height=&quot;620&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cJT8A7/btsP3dPX0tu/kyGDwhKzoWwTiSKuQlHOuk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cJT8A7/btsP3dPX0tu/kyGDwhKzoWwTiSKuQlHOuk/img.png&quot; data-alt=&quot;pg 오류&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cJT8A7/btsP3dPX0tu/kyGDwhKzoWwTiSKuQlHOuk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcJT8A7%2FbtsP3dPX0tu%2FkyGDwhKzoWwTiSKuQlHOuk%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;800&quot; height=&quot;473&quot; data-origin-width=&quot;1049&quot; data-origin-height=&quot;620&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;pg 오류&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 이미지처럼, pg 오류가 있다면 아래의 순서대로 진행해 보세요.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;sudo apt-get update&lt;br /&gt;&lt;br /&gt;sudo apt-get install -y postgresql postgresql-contrib libpq-dev&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 아래의 명령어를 실행합니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;gem install pg -v '1.2.3'&lt;/blockquote&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;마지막으로 아래의 명령어를 실행합니다.&lt;/p&gt;
&lt;blockquote style=&quot;background-color: #fcfcfc; color: #666666; text-align: left;&quot; data-ke-style=&quot;style3&quot;&gt;bundle install&lt;/blockquote&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4. rich_files 연동하기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CKEditor에서 이미지를 업로드하면 rich_files 폴더에 이미지가 보관됩니다. 혹시 이미 보유하고 있는 rich_files가 있다면, 아래의 경로에 복사합니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;/home/redmine/redmine/public/system/rich/rich_files/rich_files&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또는 아래와 같이 레드마인 컨테이너 설정에서 폴더를 매핑하여 file station에서 옮기는 것도 가능합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1891&quot; data-origin-height=&quot;1014&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bLl7BJ/btsP2HX28mr/JqYGO6b6h3CKgwihUG1fu0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bLl7BJ/btsP2HX28mr/JqYGO6b6h3CKgwihUG1fu0/img.png&quot; data-alt=&quot;rich_files 경로 매핑하기&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bLl7BJ/btsP2HX28mr/JqYGO6b6h3CKgwihUG1fu0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbLl7BJ%2FbtsP2HX28mr%2FJqYGO6b6h3CKgwihUG1fu0%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;700&quot; height=&quot;375&quot; data-origin-width=&quot;1891&quot; data-origin-height=&quot;1014&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;rich_files 경로 매핑하기&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;5. CKEditor 활성화하기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 모든 설치가 완료되었으니, 레드마인의 본문 형식을 CKEditor로 변경하여 저장합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1341&quot; data-origin-height=&quot;1142&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cUESV8/btsP2JIjGgs/cJ0TeFdfKCefE1Nf9zo6N0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cUESV8/btsP2JIjGgs/cJ0TeFdfKCefE1Nf9zo6N0/img.png&quot; data-alt=&quot;레드마인 본문 형식을 변경하는 방법&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cUESV8/btsP2JIjGgs/cJ0TeFdfKCefE1Nf9zo6N0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcUESV8%2FbtsP2JIjGgs%2FcJ0TeFdfKCefE1Nf9zo6N0%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;700&quot; height=&quot;596&quot; data-origin-width=&quot;1341&quot; data-origin-height=&quot;1142&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;레드마인 본문 형식을 변경하는 방법&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>Redmine/Plugin</category>
      <category>레드마인</category>
      <author>❤ </author>
      <guid isPermaLink="true">https://luckygg.tistory.com/402</guid>
      <comments>https://luckygg.tistory.com/402#entry402comment</comments>
      <pubDate>Sat, 23 Aug 2025 21:42:51 +0900</pubDate>
    </item>
    <item>
      <title>[레드마인 플러그인] Redmine Issue Template (with Redmine 4.2.9)</title>
      <link>https://luckygg.tistory.com/401</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;소개&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/akiko-pusu/redmine_issue_templates/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;이슈 템플릿(Issue Template)&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;807&quot; data-origin-height=&quot;584&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bKmPmk/btsOAHrKoMY/99q07W8kVqLRk9NXKQr3Pk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bKmPmk/btsOAHrKoMY/99q07W8kVqLRk9NXKQr3Pk/img.png&quot; data-alt=&quot;템플릿 작성 예시&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bKmPmk/btsOAHrKoMY/99q07W8kVqLRk9NXKQr3Pk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbKmPmk%2FbtsOAHrKoMY%2F99q07W8kVqLRk9NXKQr3Pk%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;800&quot; height=&quot;579&quot; data-origin-width=&quot;807&quot; data-origin-height=&quot;584&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;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;830&quot; data-origin-height=&quot;740&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cBlaBm/btsOB89zLgg/rGtZCWnWI2Azp4hoYFjWEk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cBlaBm/btsOB89zLgg/rGtZCWnWI2Azp4hoYFjWEk/img.png&quot; data-alt=&quot;템플릿 사용 예시&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cBlaBm/btsOB89zLgg/rGtZCWnWI2Azp4hoYFjWEk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcBlaBm%2FbtsOB89zLgg%2FrGtZCWnWI2Azp4hoYFjWEk%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;800&quot; height=&quot;713&quot; data-origin-width=&quot;830&quot; data-origin-height=&quot;740&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;&lt;b&gt;참고로, 해당 플러그인은 2021년 1월 23일에 보관 처리되어 더 이상 업데이트 되지 않습니다.&lt;/b&gt;&lt;/i&gt;&lt;/p&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;blockquote data-ke-style=&quot;style3&quot;&gt;git clone -b 1.1.0 https://github.com/akiko-pusu/redmine_issue_templates/&lt;/blockquote&gt;
&lt;div class=&quot;rgyInfo&quot;&gt;
&lt;div class=&quot;rgyInfo-circle&quot;&gt;
&lt;div class=&quot;topDiv&quot;&gt;주의&lt;/div&gt;
&lt;div class=&quot;bottomDiv&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;bottomDiv2&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;rgyInfo-text&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저는 저장소의 최신 버전인 1.1.0을 그대로 사용하면 설치 과정 중 오류가 발생했습니다. 그래서 오류가 발생하지 않도록 &lt;b&gt;init.rb&lt;/b&gt; 파일을 수정했고, 정상적으로 설치되었습니다. 아래에 수정된 &lt;b&gt;init.rb&lt;/b&gt; 파일을 첨부했습니다.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&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/AuEWJ/btsOBEVafat/A6K1AIaveFTczm93oXpjA0/redmine_issue_templates%20%28init.rb%20%EC%88%98%EC%A0%95%EB%B3%B8%29.zip?attach=1&amp;amp;knm=tfile.zip&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;redmine_issue_templates (init.rb 수정본).zip&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;size&quot;&gt;0.20MB&lt;/div&gt;
&lt;/div&gt;
  &lt;/a&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저장소에서 다운로드하면 3번 과정으로, 위의 첨부된 파일을 다운로드하면 2번 과정으로 진행합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. 파일 복사하기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Redmine Plugin 경로를 매핑했다면, 아래와 같이 업로드합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1120&quot; data-origin-height=&quot;636&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/U5Z7A/btsODmTnh3E/c8XsW3OkolRQ9Vlw1dTBTk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/U5Z7A/btsODmTnh3E/c8XsW3OkolRQ9Vlw1dTBTk/img.png&quot; data-alt=&quot;Plugin 경로에 파일 업로드하기&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/U5Z7A/btsODmTnh3E/c8XsW3OkolRQ9Vlw1dTBTk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FU5Z7A%2FbtsODmTnh3E%2Fc8XsW3OkolRQ9Vlw1dTBTk%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;694&quot; height=&quot;394&quot; data-origin-width=&quot;1120&quot; data-origin-height=&quot;636&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Plugin 경로에 파일 업로드하기&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약, 매핑을 안 했다면 직접 다운로드한 파일을 Redmine plugin 경로로 복사해야 하는 번거로움이 있습니다. 차라리 셋업 과정에서 매핑을 해놓고 시작하는 게 좋습니다. 매핑 관련해서는 아래 게시물을 참고하세요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://luckygg.tistory.com/400&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;[Container Manager] MariaDB와 레드마인 구축하는 방법, 쉽게 따라 하기&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1749973444140&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;[Container Manager] MariaDB와 레드마인 구축하는 방법, 쉽게 따라하기&quot; data-og-description=&quot;이제 Docker 대신 Container Manager  시놀로지 패키지 센터에서는 도커(Docker)와 레드마인(Redmine) 패키지를 제공하는데요. 이 패키지 설치를 통해 쉽고 편하게 레드마인을 구축할 수 있습니다. 하지만&quot; data-og-host=&quot;luckygg.tistory.com&quot; data-og-source-url=&quot;https://luckygg.tistory.com/400&quot; data-og-url=&quot;https://luckygg.tistory.com/400&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/o11BW/hyY80eRGtX/A8poIXKKhWczMNdHsslWh1/img.png?width=800&amp;amp;height=431&amp;amp;face=0_0_800_431,https://scrap.kakaocdn.net/dn/b4sdTy/hyY8UFGEYq/WfK70DYOaMqfPeerMY8wxk/img.png?width=800&amp;amp;height=431&amp;amp;face=0_0_800_431,https://scrap.kakaocdn.net/dn/cMsSXA/hyY71d2ndi/pRSJuaQ6OtNHjcGUnWDHz1/img.png?width=1210&amp;amp;height=772&amp;amp;face=0_0_1210_772&quot;&gt;&lt;a href=&quot;https://luckygg.tistory.com/400&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://luckygg.tistory.com/400&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/o11BW/hyY80eRGtX/A8poIXKKhWczMNdHsslWh1/img.png?width=800&amp;amp;height=431&amp;amp;face=0_0_800_431,https://scrap.kakaocdn.net/dn/b4sdTy/hyY8UFGEYq/WfK70DYOaMqfPeerMY8wxk/img.png?width=800&amp;amp;height=431&amp;amp;face=0_0_800_431,https://scrap.kakaocdn.net/dn/cMsSXA/hyY71d2ndi/pRSJuaQ6OtNHjcGUnWDHz1/img.png?width=1210&amp;amp;height=772&amp;amp;face=0_0_1210_772');&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;[Container Manager] MariaDB와 레드마인 구축하는 방법, 쉽게 따라하기&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;이제 Docker 대신 Container Manager  시놀로지 패키지 센터에서는 도커(Docker)와 레드마인(Redmine) 패키지를 제공하는데요. 이 패키지 설치를 통해 쉽고 편하게 레드마인을 구축할 수 있습니다. 하지만&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;luckygg.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. Redmine Plugin 경로에 파일 확인 후 설치하기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래 명령어로 플러그인 경로에 접근합니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;cd /home/redmine/redmine/plugins/&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 아래 명령어로 파일 목록을 조회합니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;ls -l&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정상적으로 파일을 복사했다면 Redmine Plugin 경로에 아래와 같이 redmine_issue_templates 폴더가 있어야 합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1049&quot; data-origin-height=&quot;670&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/MMxqa/btsOCNwTD6w/SlnUBGeBHIpJta7yx2DvJk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/MMxqa/btsOCNwTD6w/SlnUBGeBHIpJta7yx2DvJk/img.png&quot; data-alt=&quot;플러그인 경로에 복사한 플러그인 확인하기&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/MMxqa/btsOCNwTD6w/SlnUBGeBHIpJta7yx2DvJk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FMMxqa%2FbtsOCNwTD6w%2FSlnUBGeBHIpJta7yx2DvJk%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;800&quot; height=&quot;511&quot; data-origin-width=&quot;1049&quot; data-origin-height=&quot;670&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;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;cd /home/redmine/redmine&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래 명령어를 실행합니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;bundle exec rails redmine:plugins:migrate RAILS_ENV=production&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약, 위 명령어 실행 후 오류가 발생하거나, 위 명령어 실행 후 오류는 없지만 레드마인 재시작 후 오류가 발생하면 추가로 아래의 명령어를 실행합니다. 아니면, 처음부터 아래의 명령어를 실행해도 상관은 없을 듯합니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;bundle exec rake db:migrate RAILS_ENV=production&lt;/blockquote&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;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1049&quot; data-origin-height=&quot;670&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/YTKz1/btsODkOMtYb/dKKFHplFCJktUt8I9x78o0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/YTKz1/btsODkOMtYb/dKKFHplFCJktUt8I9x78o0/img.png&quot; data-alt=&quot;설치가 완료된 모습&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/YTKz1/btsODkOMtYb/dKKFHplFCJktUt8I9x78o0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FYTKz1%2FbtsODkOMtYb%2FdKKFHplFCJktUt8I9x78o0%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;800&quot; height=&quot;511&quot; data-origin-width=&quot;1049&quot; data-origin-height=&quot;670&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;gt; 플러그인' 메뉴를 클릭하면 아래와 같이 표시되면 정상적으로 설치가 완료된 것입니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;959&quot; data-origin-height=&quot;79&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/beJ9Zm/btsOA74ERnZ/gGRr4IaW0N4D6mKVgyOdNK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/beJ9Zm/btsOA74ERnZ/gGRr4IaW0N4D6mKVgyOdNK/img.png&quot; data-alt=&quot;플러그인이 정상적으로 설치된 모습&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/beJ9Zm/btsOA74ERnZ/gGRr4IaW0N4D6mKVgyOdNK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbeJ9Zm%2FbtsOA74ERnZ%2FgGRr4IaW0N4D6mKVgyOdNK%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;800&quot; height=&quot;66&quot; data-origin-width=&quot;959&quot; data-origin-height=&quot;79&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;플러그인이 정상적으로 설치된 모습&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>Redmine/Plugin</category>
      <category>레드마인</category>
      <author>❤ </author>
      <guid isPermaLink="true">https://luckygg.tistory.com/401</guid>
      <comments>https://luckygg.tistory.com/401#entry401comment</comments>
      <pubDate>Sun, 15 Jun 2025 16:56:06 +0900</pubDate>
    </item>
    <item>
      <title>[AI] OpenAI API를 사용하기 위한 기초 가이드 (노코딩 테스트 포함)</title>
      <link>https://luckygg.tistory.com/399</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;OpenAI API란?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제는 생성형 인공 지능 서비스인 ChatGPT를 모르시는 분들이 거의 없을 텐데요. OpenAI의 ChatGPT 사이트에서 채팅하는 방법 뿐만 아니라, OpenAI에서 제공하는 GPT 모델을 API로 호출하여 사용하는 방법도 있습니다. 이 방식은 무료는 아니지만 직접 모델을 구축하는 것에 비해 훨씬 효율적입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참고로, OpenAI API는 유료 서비스인 ChatGPT Plus 구독과는 다른 것입니다. GPT Plus는 월 결제 방식으로, 새로운 GPT 모델과 빠른 응답속도, 더 긴 대화를 할 수 있는 장점이 있는데요. API는 말 그대로 프로그래밍을 통해 메시지를 서버로 보내면 응답을 받는 형태로, 다양한 애플리케이션 구현이 가능해집니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;OpenAI API에서 제공하는 기능&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;API는 다양한 기능을 제공하며, 개발자가 알맞은 기능을 선택하여 다양한 애플리케이션 구현이 가능합니다. 간단하게 정리하면 다음과 같습니다.&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;Text Generation(텍스트 생성)&lt;/b&gt;: 사용자의 질문에 자연스러운 답변을 생성하는 기능으로, 일반적으로 사용하는 ChatGPT의 채팅 기능.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Image Generation(이미지 생성)&lt;/b&gt;: 사용자의 프롬프트에 따라 이미지를 생성하는 기능.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Vision&lt;/b&gt;: 사용자의 이미지를 이해하고 분석하는 기능.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Vector Embbeddings&lt;/b&gt;: 사용자의 데이터를 벡터 공간으로 변환하여 수치화하고, 수치의 유사성으로 결과를 활용하는 기능.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;TTS(Text To Speech)&lt;/b&gt;: 텍스트를 음성으로 변환하는 기능.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;STT(Speech To Text)&lt;/b&gt;: 음성을 텍스트로 변환하는 기능.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Moderation&lt;/b&gt;: 텍스트에 유해하거나 부적절한 내용이 있는지 판단하는 기능.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Reasoning&lt;/b&gt;: 복잡한 문제에 대해 더 정확하고 깊이있는 대답을 생성하는 기능.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서론이 많이 길었습니다. 이제 본문에서는 Text Generation을 기준으로 API 준비 과정과 노코딩 테스트 방법 소개하겠습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;따라하기&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. API Key 발급 받기&lt;/h3&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://platform.openai.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://platform.openai.com/&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 &lt;b&gt;Settings &amp;gt; API Keys&lt;/b&gt; 또는 &lt;b&gt;Dashboard &amp;gt; API Keys &lt;/b&gt;메뉴를 눌러 API Keys 페이지로 이동합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;API Keys 화면.webp&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;834&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bBGxqH/btsMUlPEoJX/Hd0XSKlYap36LRlHRKz3T0/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bBGxqH/btsMUlPEoJX/Hd0XSKlYap36LRlHRKz3T0/img.webp&quot; data-alt=&quot;API Keys 화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bBGxqH/btsMUlPEoJX/Hd0XSKlYap36LRlHRKz3T0/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbBGxqH%2FbtsMUlPEoJX%2FHd0XSKlYap36LRlHRKz3T0%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; alt=&quot;API Keys 화면&quot; loading=&quot;lazy&quot; width=&quot;600&quot; height=&quot;626&quot; data-filename=&quot;API Keys 화면.webp&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;834&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;API Keys 화면&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우측 상단의 &lt;b&gt;Create new secret key&lt;/b&gt; 버튼을 클릭하면 아래의 화면이 표시됩니다. 이름과 프로젝트, 권한을 지정하고 생성 버튼을 클릭합니다. '프로젝트'는 애플리케이션마다 생성하여 API 키를 관리할 때 지정하면 되겠습니다. 일단 테스트를 위해 Default를 선택하세요. 이름과 권한은 나중에라도 변경할 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Key 생성 화면.webp&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;842&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/CkBsp/btsMSVEEa8R/Vy6ObXUbACuy9qGDJkFGn0/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/CkBsp/btsMSVEEa8R/Vy6ObXUbACuy9qGDJkFGn0/img.webp&quot; data-alt=&quot;Key 생성 화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/CkBsp/btsMSVEEa8R/Vy6ObXUbACuy9qGDJkFGn0/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FCkBsp%2FbtsMSVEEa8R%2FVy6ObXUbACuy9qGDJkFGn0%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; alt=&quot;Key 생성 화면&quot; loading=&quot;lazy&quot; width=&quot;600&quot; height=&quot;632&quot; data-filename=&quot;Key 생성 화면.webp&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;842&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Key 생성 화면&lt;/figcaption&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-filename=&quot;키가 생성된 화면.webp&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;842&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/thQVI/btsMT3hptcx/Hk2GmbKHWJAzXYYGY2wV6k/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/thQVI/btsMT3hptcx/Hk2GmbKHWJAzXYYGY2wV6k/img.webp&quot; data-alt=&quot;키가 생성된 화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/thQVI/btsMT3hptcx/Hk2GmbKHWJAzXYYGY2wV6k/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FthQVI%2FbtsMT3hptcx%2FHk2GmbKHWJAzXYYGY2wV6k%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; alt=&quot;키가 생성된 화면&quot; loading=&quot;lazy&quot; width=&quot;600&quot; height=&quot;632&quot; data-filename=&quot;키가 생성된 화면.webp&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;842&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;키가 생성된 화면&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. 크레딧 및 결제 정보 추가하기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참고로, 최초에 가입하면 무료 크레딧을 일정 금액 제공했었습니다(지금은 모르겠네요). 앞으로 API를 호출하면 크레딧이 소진하게 됩니다. 당연하지만, 크레딧이 없으면 API 호출은 불가능합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;청구 페이지.webp&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;840&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/S9gxz/btsMUvScOWN/umWdSJlKKJ4MXKI8IBdFVk/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/S9gxz/btsMUvScOWN/umWdSJlKKJ4MXKI8IBdFVk/img.webp&quot; data-alt=&quot;청구 페이지&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/S9gxz/btsMUvScOWN/umWdSJlKKJ4MXKI8IBdFVk/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FS9gxz%2FbtsMUvScOWN%2FumWdSJlKKJ4MXKI8IBdFVk%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; alt=&quot;청구 페이지&quot; loading=&quot;lazy&quot; width=&quot;600&quot; height=&quot;630&quot; data-filename=&quot;청구 페이지.webp&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;840&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;Billing &amp;gt; Payment methods&lt;/b&gt; 메뉴를 클릭합니다. 그리고 카드 정보를 입력하고 추가 버튼을 클릭하면 쉽게 완료할 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;결제 정보 입력 화면.webp&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;793&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/x2K8h/btsMSCrUGKp/tLolYRhFdybnuuuKoti4z1/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/x2K8h/btsMSCrUGKp/tLolYRhFdybnuuuKoti4z1/img.webp&quot; data-alt=&quot;결제 정보 입력 화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/x2K8h/btsMSCrUGKp/tLolYRhFdybnuuuKoti4z1/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fx2K8h%2FbtsMSCrUGKp%2FtLolYRhFdybnuuuKoti4z1%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; alt=&quot;결제 정보 입력 화면&quot; loading=&quot;lazy&quot; width=&quot;600&quot; height=&quot;595&quot; data-filename=&quot;결제 정보 입력 화면.webp&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;793&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;저는 처음 테스트를 위해 $5를 결제했는데요. 호출 토큰 양이 많지 않은 이상, API 테스트를 하기에는 충분하다고 생각합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;결제 후 화면.webp&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;843&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/TBfv9/btsMTf3Tl21/iMi7edZtuuLXL22xlKpUe0/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/TBfv9/btsMTf3Tl21/iMi7edZtuuLXL22xlKpUe0/img.webp&quot; data-alt=&quot;결제 후 화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/TBfv9/btsMTf3Tl21/iMi7edZtuuLXL22xlKpUe0/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FTBfv9%2FbtsMTf3Tl21%2FiMi7edZtuuLXL22xlKpUe0%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; alt=&quot;결제 후 화면&quot; loading=&quot;lazy&quot; width=&quot;600&quot; height=&quot;632&quot; data-filename=&quot;결제 후 화면.webp&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;843&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;Add to credit balance&lt;/b&gt; 버튼을 클릭해 충전하시면 됩니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;크레딧 충전 화면.webp&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;793&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bIRypP/btsMUpYOKKT/7nC5v68ef7tKeiCegDku9K/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bIRypP/btsMUpYOKKT/7nC5v68ef7tKeiCegDku9K/img.webp&quot; data-alt=&quot;크레딧 충전 화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bIRypP/btsMUpYOKKT/7nC5v68ef7tKeiCegDku9K/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbIRypP%2FbtsMUpYOKKT%2F7nC5v68ef7tKeiCegDku9K%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; alt=&quot;크레딧 충전 화면&quot; loading=&quot;lazy&quot; width=&quot;600&quot; height=&quot;595&quot; data-filename=&quot;크레딧 충전 화면.webp&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;793&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;크레딧 충전 화면&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. Talend API Tester에서 간단하게 테스트하기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;크롬 확장 프로그램인 &lt;b&gt;Talend API Tester&lt;/b&gt;에서 간단하게 API 테스트를 할 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;API 요청 화면.webp&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;372&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/IRAkE/btsMUjxwV5l/skaIIjwogtocI4c6O1EQb0/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/IRAkE/btsMUjxwV5l/skaIIjwogtocI4c6O1EQb0/img.webp&quot; data-alt=&quot;API 요청 화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/IRAkE/btsMUjxwV5l/skaIIjwogtocI4c6O1EQb0/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FIRAkE%2FbtsMUjxwV5l%2FskaIIjwogtocI4c6O1EQb0%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; alt=&quot;API 요청 화면&quot; loading=&quot;lazy&quot; width=&quot;600&quot; height=&quot;279&quot; data-filename=&quot;API 요청 화면.webp&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;372&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;API 요청 화면&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;POST 메소드를 선택하고, API 요청 주소는 &lt;a href=&quot;https://api.openai.com/v1/chat/completions&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://api.openai.com/v1/chat/completions&lt;/a&gt; 을 입력합니다. 그리고 헤더에는 아래의 정보를 입력합니다.&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 68px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style12&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 33.3333%; height: 17px; text-align: center;&quot;&gt;항목&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 17px; text-align: center;&quot;&gt;값&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 33.3333%; height: 17px; text-align: center;&quot;&gt;Content-Type&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 17px; text-align: center;&quot;&gt;application/json&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 33.3333%; height: 17px; text-align: center;&quot;&gt;Authorization&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 17px; text-align: center;&quot;&gt;Bearer [API Key]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 33.3333%; height: 17px; text-align: center;&quot;&gt;OpenAI-Beta&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 17px; text-align: center;&quot;&gt;assistants=v2&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 BODY에는 아래의 정보를 예시로 입력합니다. 모델과 메시지는 자유롭게 선택해도 좋습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1742628179366&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;{
  &quot;model&quot;: &quot;gpt-3.5-turbo&quot;,
  &quot;messages&quot;: [
    {&quot;role&quot;: &quot;user&quot;, &quot;content&quot;: &quot;Hello, how are you?&quot;}
  ]
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Send&lt;/b&gt; 버튼을 클릭하면, 아래와 같은 응답을 받게 됩니다. BODY의 content에 응답한 메시지가 포함되어 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;응답 화면.webp&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;748&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/k118E/btsMTi7mLAl/ilm1OtBPqFqMjPX9uJZkq1/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/k118E/btsMTi7mLAl/ilm1OtBPqFqMjPX9uJZkq1/img.webp&quot; data-alt=&quot;응답 화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/k118E/btsMTi7mLAl/ilm1OtBPqFqMjPX9uJZkq1/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fk118E%2FbtsMTi7mLAl%2Film1OtBPqFqMjPX9uJZkq1%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; alt=&quot;응답 화면&quot; loading=&quot;lazy&quot; width=&quot;600&quot; height=&quot;561&quot; data-filename=&quot;응답 화면.webp&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;748&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;Dashboard &amp;gt; Usage&lt;/b&gt; 메뉴에 들어가 보면, 방금 호출한 API에 얼마의 크레딧이 소진되었는지 확인할 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;크레딧 사용량 화면.webp&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;434&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Rtv3x/btsMUN6d11s/l0bjG6DFp7nzlotlWmEME0/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Rtv3x/btsMUN6d11s/l0bjG6DFp7nzlotlWmEME0/img.webp&quot; data-alt=&quot;크레딧 사용량 화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Rtv3x/btsMUN6d11s/l0bjG6DFp7nzlotlWmEME0/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FRtv3x%2FbtsMUN6d11s%2Fl0bjG6DFp7nzlotlWmEME0%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; alt=&quot;크레딧 사용량 화면&quot; loading=&quot;lazy&quot; width=&quot;600&quot; height=&quot;326&quot; data-filename=&quot;크레딧 사용량 화면.webp&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;434&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://platform.openai.com/docs/pricing&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://platform.openai.com/docs/pricing&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;모델 가격 표.webp&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;742&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cl7HnC/btsMUvxTgPS/HktOSZb3lnpxmnqOVm0xO1/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cl7HnC/btsMUvxTgPS/HktOSZb3lnpxmnqOVm0xO1/img.webp&quot; data-alt=&quot;모델 가격 표&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cl7HnC/btsMUvxTgPS/HktOSZb3lnpxmnqOVm0xO1/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcl7HnC%2FbtsMUvxTgPS%2FHktOSZb3lnpxmnqOVm0xO1%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; alt=&quot;모델 가격 표&quot; loading=&quot;lazy&quot; width=&quot;600&quot; height=&quot;557&quot; data-filename=&quot;모델 가격 표.webp&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;742&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;모델 가격 표&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>Programming/AI</category>
      <category>Ai</category>
      <author>❤ </author>
      <guid isPermaLink="true">https://luckygg.tistory.com/399</guid>
      <comments>https://luckygg.tistory.com/399#entry399comment</comments>
      <pubDate>Sat, 22 Mar 2025 17:04:36 +0900</pubDate>
    </item>
    <item>
      <title>[Container Manager] MariaDB와 레드마인 구축하는 방법, 쉽게 따라하기</title>
      <link>https://luckygg.tistory.com/400</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;이제 Docker 대신 Container Manager  &lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시놀로지 패키지 센터에서는 &lt;u&gt;도커(Docker)&lt;/u&gt;와 &lt;u&gt;레드마인(Redmine)&lt;/u&gt; 패키지를 제공하는데요. 이 패키지 설치를 통해 쉽고 편하게 레드마인을 구축할 수 있습니다. 하지만, 앞으로 시놀로지 &lt;b&gt;DSM 7.2&lt;/b&gt; 버전부터는 이 패키지를 제공하지 않습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이전 버전인 DSM 6.2까지는 도커와 레드마인을 제공했지만, DSM 7.2에서는 &lt;u&gt;컨테이너 매니저(Container Manager)&lt;/u&gt;만 제공합니다. 즉, 레드마인을 설치하려면 컨테이너 매니저를 통해 직접 설치와 DB를 연동하여 환경을 구축해야 한다는 것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;직접 구축한다는 것에 부담이 있겠지만, 막상 시도해 보면 그다지 어렵지 않습니다. 본문에서는 레드마인 설치와 MariaDB 연동하는 방법을 상세히 설명하는데요. 한 단계씩 따라 하면 큰 어려움 없이 모두 설치하실 수 있을 것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참고로, 본문에서는 레드마인 4.2.9 버전을 설치하는데요. 최신 버전인 6.x 버전을 선택해도 상관은 없습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;MariaDB 설치 따라 하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기존 도커의 레드마인은 MariaDB 10 패키지와 연동되어 데이터가 관리됐습니다. DSM 7.2의 패키지 센터에도 MariaDB 10 패키지가 있으나, 이상하게도 컨테이너 매니저의 레드마인에서 MariaDB 10 패키지와 연동이 제대로 안되더군요. 그래서 이를 사용하지 않고, 컨테이너 매니저에서 직접 MariaDB를 설치한 후 연동하는 방식으로 진행합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컨테이너 매니저를 실행한 후 레지스트리 메뉴에서 &lt;b&gt;MariaDB&lt;/b&gt;를 검색합니다. 그리고 검색 결과의 mariadb를 선택한 후 다운로드를 클릭하면 태그 선택 창이 표시됩니다. 특정 버전을 선택하거나 &lt;b&gt;최신 버전(latest)&lt;/b&gt;을 선택하면 됩니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;컨테이너 매니저의 레지스트리 메뉴 화면.png&quot; data-origin-width=&quot;1232&quot; data-origin-height=&quot;664&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ckdgca/btsL4YOlvLY/Z29kigsfqJdJtCcOwKnzI1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ckdgca/btsL4YOlvLY/Z29kigsfqJdJtCcOwKnzI1/img.png&quot; data-alt=&quot;컨테이너 매니저의 레지스트리 메뉴 화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ckdgca/btsL4YOlvLY/Z29kigsfqJdJtCcOwKnzI1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fckdgca%2FbtsL4YOlvLY%2FZ29kigsfqJdJtCcOwKnzI1%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; alt=&quot;컨테이너 매니저의 레지스트리 메뉴 화면&quot; loading=&quot;lazy&quot; width=&quot;700&quot; height=&quot;377&quot; data-filename=&quot;컨테이너 매니저의 레지스트리 메뉴 화면.png&quot; data-origin-width=&quot;1232&quot; data-origin-height=&quot;664&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-filename=&quot;mariadb의 버전 선택 화면.png&quot; data-origin-width=&quot;1234&quot; data-origin-height=&quot;664&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/FkvGa/btsL2zW8Bku/WUiOwCcjAXUioqKcskhw7K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/FkvGa/btsL2zW8Bku/WUiOwCcjAXUioqKcskhw7K/img.png&quot; data-alt=&quot;mariadb의 버전 선택 화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/FkvGa/btsL2zW8Bku/WUiOwCcjAXUioqKcskhw7K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FFkvGa%2FbtsL2zW8Bku%2FWUiOwCcjAXUioqKcskhw7K%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; alt=&quot;mariadb의 버전 선택 화면&quot; loading=&quot;lazy&quot; width=&quot;700&quot; height=&quot;377&quot; data-filename=&quot;mariadb의 버전 선택 화면.png&quot; data-origin-width=&quot;1234&quot; data-origin-height=&quot;664&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;mariadb의 버전 선택 화면&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컨테이너 이름은 기본 값을 사용하거나 사용자 마음대로 변경해도 상관없습니다. 저는 &lt;b&gt;mariadb&lt;/b&gt;라는 이름으로 진행했습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;컨테이너 이름 설정.png&quot; data-origin-width=&quot;1239&quot; data-origin-height=&quot;664&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/QXzos/btsL4YHyQeo/iknwcz2M0J5gsmGVMVgk2K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/QXzos/btsL4YHyQeo/iknwcz2M0J5gsmGVMVgk2K/img.png&quot; data-alt=&quot;컨테이너 이름 설정&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/QXzos/btsL4YHyQeo/iknwcz2M0J5gsmGVMVgk2K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FQXzos%2FbtsL4YHyQeo%2Fiknwcz2M0J5gsmGVMVgk2K%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; alt=&quot;컨테이너 이름 설정&quot; loading=&quot;lazy&quot; width=&quot;700&quot; height=&quot;375&quot; data-filename=&quot;컨테이너 이름 설정.png&quot; data-origin-width=&quot;1239&quot; data-origin-height=&quot;664&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;3306&lt;/b&gt;으로 설정합니다. 볼륨 설정에서는 파일 스테이션의 공유 폴더와 mariadb의 특정 경로를 매핑합니다. 이렇게 매핑하면 공유 폴더에 mariadb의 정보가 동기화됩니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;포트 및 볼륨 설정.png&quot; data-origin-width=&quot;1235&quot; data-origin-height=&quot;664&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nR1mb/btsL2IfCwMB/GYkIKs4fINmBBcYfMAauGK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nR1mb/btsL2IfCwMB/GYkIKs4fINmBBcYfMAauGK/img.png&quot; data-alt=&quot;포트 및 볼륨 설정&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nR1mb/btsL2IfCwMB/GYkIKs4fINmBBcYfMAauGK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FnR1mb%2FbtsL2IfCwMB%2FGYkIKs4fINmBBcYfMAauGK%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; alt=&quot;포트 및 볼륨 설정&quot; loading=&quot;lazy&quot; width=&quot;700&quot; height=&quot;376&quot; data-filename=&quot;포트 및 볼륨 설정.png&quot; data-origin-width=&quot;1235&quot; data-origin-height=&quot;664&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;포트 및 볼륨 설정&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style12&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;항목&lt;/td&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;값&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;/docker/mariadb&lt;/td&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;/var/lib/mysql&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&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;환경 변수 설정.png&quot; data-origin-width=&quot;1237&quot; data-origin-height=&quot;664&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/z5IY6/btsL4GmZD9N/alImDr1f2onTtmujjtK9bK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/z5IY6/btsL4GmZD9N/alImDr1f2onTtmujjtK9bK/img.png&quot; data-alt=&quot;환경 변수 설정&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/z5IY6/btsL4GmZD9N/alImDr1f2onTtmujjtK9bK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fz5IY6%2FbtsL4GmZD9N%2FalImDr1f2onTtmujjtK9bK%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; alt=&quot;환경 변수 설정&quot; loading=&quot;lazy&quot; width=&quot;700&quot; height=&quot;376&quot; data-filename=&quot;환경 변수 설정.png&quot; data-origin-width=&quot;1237&quot; data-origin-height=&quot;664&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;환경 변수 설정&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style12&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;항목&lt;/td&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;값&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;TZ&lt;/td&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;Asia/Seoul&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;MYSQL_ROOT_PASSWORD&lt;/td&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;초기 비밀번호 입력&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&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;1230&quot; data-origin-height=&quot;654&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qTDaJ/btsL2n3Gzzi/fj1gJmcvWVOUDW77OnVH61/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qTDaJ/btsL2n3Gzzi/fj1gJmcvWVOUDW77OnVH61/img.png&quot; data-alt=&quot;설치 화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qTDaJ/btsL2n3Gzzi/fj1gJmcvWVOUDW77OnVH61/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqTDaJ%2FbtsL2n3Gzzi%2Ffj1gJmcvWVOUDW77OnVH61%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;700&quot; height=&quot;372&quot; data-origin-width=&quot;1230&quot; data-origin-height=&quot;654&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;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1232&quot; data-origin-height=&quot;664&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/byiRW5/btsL4q5Ew8l/Tjk0JUKbuhgzl03QeAR5Bk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/byiRW5/btsL4q5Ew8l/Tjk0JUKbuhgzl03QeAR5Bk/img.png&quot; data-alt=&quot;MariaDB가 정상적으로 설치되어 실행되는 모습&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/byiRW5/btsL4q5Ew8l/Tjk0JUKbuhgzl03QeAR5Bk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbyiRW5%2FbtsL4q5Ew8l%2FTjk0JUKbuhgzl03QeAR5Bk%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; alt=&quot;MariaDB가 정상적으로 설치되어 실행되는 모습&quot; loading=&quot;lazy&quot; width=&quot;700&quot; height=&quot;377&quot; data-origin-width=&quot;1232&quot; data-origin-height=&quot;664&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;MariaDB가 정상적으로 설치되어 실행되는 모습&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Redmine DB 환경 설정 따라 하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 레드마인이 MariaDB에 접근하여 읽고 쓰기가 가능하도록 계정을 만들고 권한을 설정해야 합니다. 이를 위해 &lt;b&gt;HeidiSQL&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;a href=&quot;https://www.heidisql.com/download.php&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.heidisql.com/download.php&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1738303563707&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;Download HeidiSQL&quot; data-og-description=&quot;Download HeidiSQL 12.10, released on 21 Jan 2025 Installer, 64 bit ≃ Portable version (zipped): 32 bit ≃ 64 bit ≃ Stable link to latest portable version: 32 bit 64 bit Sourcecode Previous releases v12.10 (revision 7000) from 21 Jan 2025: Installer, 6&quot; data-og-host=&quot;www.heidisql.com&quot; data-og-source-url=&quot;https://www.heidisql.com/download.php&quot; data-og-url=&quot;https://www.heidisql.com/download.php&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://www.heidisql.com/download.php&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.heidisql.com/download.php&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;Download HeidiSQL&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Download HeidiSQL 12.10, released on 21 Jan 2025 Installer, 64 bit ≃ Portable version (zipped): 32 bit ≃ 64 bit ≃ Stable link to latest portable version: 32 bit 64 bit Sourcecode Previous releases v12.10 (revision 7000) from 21 Jan 2025: Installer, 6&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.heidisql.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래 화면에서 Installer를 클릭하여 설치 파일을 받습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;805&quot; data-origin-height=&quot;945&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/oX5WS/btsL3lcZw0o/kstEh1M1iWgkREFnLMnCH1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/oX5WS/btsL3lcZw0o/kstEh1M1iWgkREFnLMnCH1/img.png&quot; data-alt=&quot;HeidiSQL 홈페이지 화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/oX5WS/btsL3lcZw0o/kstEh1M1iWgkREFnLMnCH1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FoX5WS%2FbtsL3lcZw0o%2FkstEh1M1iWgkREFnLMnCH1%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;700&quot; height=&quot;822&quot; data-origin-width=&quot;805&quot; data-origin-height=&quot;945&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;HeidiSQL 홈페이지 화면&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;설치 과정에는 따로 설정할 것이 없습니다. 설치가 완료되면 HeidiSQL 프로그램을 실행합니다. 그리고 시놀로지 서버의 IP 주소와 사용자 아이디, 비밀번호, 포트 번호를 입력한 후 열기 버튼을 클릭합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1089&quot; data-origin-height=&quot;772&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b3PaI0/btsL2S9UNGG/alRiszOQBrycEkcdDhjJKk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b3PaI0/btsL2S9UNGG/alRiszOQBrycEkcdDhjJKk/img.png&quot; data-alt=&quot;HeidiSQL로 MariaDB 접속하기&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b3PaI0/btsL2S9UNGG/alRiszOQBrycEkcdDhjJKk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb3PaI0%2FbtsL2S9UNGG%2FalRiszOQBrycEkcdDhjJKk%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; alt=&quot;HeidiSQL로 MariaDB 접속하기&quot; loading=&quot;lazy&quot; width=&quot;800&quot; height=&quot;567&quot; data-origin-width=&quot;1089&quot; data-origin-height=&quot;772&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;HeidiSQL로 MariaDB 접속하기&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style12&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;항목&lt;/td&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;값&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;호스트명 / IP&lt;/td&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;시놀로지 서버 주소&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;사용자&lt;/td&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;root&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;암호&lt;/td&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;MariaDB 설치 시 환경 변수에 입력한 비밀번호&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;포트&lt;/td&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;MariaDB 설치 시 포트 번호에 입력한 번호&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;연결이 되면 아래와 같이 기본적인 DB 4가지가 보입니다. 이제 &lt;b&gt;도구 &amp;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;1210&quot; data-origin-height=&quot;772&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/sSd53/btsL4zBu1MM/egCRMmRAzY0qEGJF5zWVd1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/sSd53/btsL4zBu1MM/egCRMmRAzY0qEGJF5zWVd1/img.png&quot; data-alt=&quot;사용자 관리자 메뉴 클릭&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/sSd53/btsL4zBu1MM/egCRMmRAzY0qEGJF5zWVd1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FsSd53%2FbtsL4zBu1MM%2FegCRMmRAzY0qEGJF5zWVd1%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; alt=&quot;사용자 관리자 메뉴 클릭&quot; loading=&quot;lazy&quot; width=&quot;700&quot; height=&quot;447&quot; data-origin-width=&quot;1210&quot; data-origin-height=&quot;772&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;추가&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;777&quot; data-origin-height=&quot;632&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/7L1od/btsL3QX8U5q/jkLC2NaxzKEyDxRyBTJdP0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/7L1od/btsL3QX8U5q/jkLC2NaxzKEyDxRyBTJdP0/img.png&quot; data-alt=&quot;사용자 추가하기&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/7L1od/btsL3QX8U5q/jkLC2NaxzKEyDxRyBTJdP0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F7L1od%2FbtsL3QX8U5q%2FjkLC2NaxzKEyDxRyBTJdP0%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; alt=&quot;사용자 추가하기&quot; loading=&quot;lazy&quot; width=&quot;500&quot; height=&quot;407&quot; data-origin-width=&quot;777&quot; data-origin-height=&quot;632&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;사용자 추가하기&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style12&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;항목&lt;/td&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;값&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;사용자 이름&lt;/td&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;사용자 이름 입력&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;호스트에서&lt;/td&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;암호&lt;/td&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;암호 입력&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;접근 허용&lt;/td&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;전체 권한 체크&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참고로, 사용자 이름과 암호는 추후 레드마인 설치 과정 중 환경 변수로 사용됩니다. 여기까지가 MariaDB 환경 구성의 전부입니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Redmine 설치 따라 하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컨테이너 매니저의 레지스트리 메뉴에서 redmine을 검색합니다. 그리고 설치하고 싶은 버전을 선택합니다. 저는 특정 플러그인의 호환성 때문에 4.2.9 버전을 채택했습니다. 참고로, 4.2.9 버전은 4.x의 가장 마지막 버전입니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1199&quot; data-origin-height=&quot;646&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/efApG5/btsL4XPnXUH/SwPHZ87jSNdzAuDpTYKIz0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/efApG5/btsL4XPnXUH/SwPHZ87jSNdzAuDpTYKIz0/img.png&quot; data-alt=&quot;레드마인 버전 선택 화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/efApG5/btsL4XPnXUH/SwPHZ87jSNdzAuDpTYKIz0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FefApG5%2FbtsL4XPnXUH%2FSwPHZ87jSNdzAuDpTYKIz0%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; alt=&quot;레드마인 버전 선택 화면&quot; loading=&quot;lazy&quot; width=&quot;700&quot; height=&quot;377&quot; data-origin-width=&quot;1199&quot; data-origin-height=&quot;646&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;723&quot; data-origin-height=&quot;468&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cCcX7u/btsL2S9YfKO/Qde2j3hyRwOc0QGElDLk90/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cCcX7u/btsL2S9YfKO/Qde2j3hyRwOc0QGElDLk90/img.png&quot; data-alt=&quot;레드마인 버전 목록&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cCcX7u/btsL2S9YfKO/Qde2j3hyRwOc0QGElDLk90/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcCcX7u%2FbtsL2S9YfKO%2FQde2j3hyRwOc0QGElDLk90%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; alt=&quot;레드마인 버전 목록&quot; loading=&quot;lazy&quot; width=&quot;500&quot; height=&quot;324&quot; data-origin-width=&quot;723&quot; data-origin-height=&quot;468&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;b&gt;sameersbn-redmine&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;1198&quot; data-origin-height=&quot;646&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/IrYuV/btsL4XaNMcd/ZxxAqXLDg9JQFJK5aKky2k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/IrYuV/btsL4XaNMcd/ZxxAqXLDg9JQFJK5aKky2k/img.png&quot; data-alt=&quot;컨테이너 이름 설정하기&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/IrYuV/btsL4XaNMcd/ZxxAqXLDg9JQFJK5aKky2k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FIrYuV%2FbtsL4XaNMcd%2FZxxAqXLDg9JQFJK5aKky2k%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; alt=&quot;컨테이너 이름 설정하기&quot; loading=&quot;lazy&quot; width=&quot;700&quot; height=&quot;377&quot; data-origin-width=&quot;1198&quot; data-origin-height=&quot;646&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;포트 설정은 자유롭게 지정&lt;/b&gt;합니다. 저는 테스트로 7777을 입력했습니다. 그리고 아래 표와 같이 폴더 매핑을 지정합니다. 아래와 같이 폴더를 매핑하면, 파일 스테이션의 공유 폴더와 레드마인의 폴더가 매핑되어 &lt;b&gt;동기화&lt;/b&gt;가 됩니다. 플러그인을 설치하기 위해 폴더를 가져다 옮기거나, CKEditor를 사용할 경우 첨부 파일을 백업할 때 매우 용이합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1173&quot; data-origin-height=&quot;616&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/pYvO4/btsL36sUylx/jnyvZSeJ565IGChGsWs0DK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/pYvO4/btsL36sUylx/jnyvZSeJ565IGChGsWs0DK/img.png&quot; data-alt=&quot;폴더 매핑 설정&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/pYvO4/btsL36sUylx/jnyvZSeJ565IGChGsWs0DK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FpYvO4%2FbtsL36sUylx%2FjnyvZSeJ565IGChGsWs0DK%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; alt=&quot;폴더 매핑 설정&quot; loading=&quot;lazy&quot; width=&quot;700&quot; height=&quot;368&quot; data-origin-width=&quot;1173&quot; data-origin-height=&quot;616&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;폴더 매핑 설정&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style12&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;항목&lt;/td&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;값&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;/docker/redmine&lt;/td&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;/home/redmine/data&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;/docker/redmine/plugins&lt;/td&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;/home/redmine/redmine/plugins&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;div class=&quot;rgyInfo&quot;&gt;
&lt;div class=&quot;rgyInfo-circle&quot;&gt;
&lt;div class=&quot;topDiv&quot;&gt;주의&lt;/div&gt;
&lt;div class=&quot;bottomDiv&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;bottomDiv2&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;rgyInfo-text&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이미 레드마인을 운영하고 있는 상태에서 폴더 매핑을 지정하면 안 됩니다. 제가 알기로는, 매핑은 단방향 동기화라서 레드마인의 지정된 폴더 데이터가 공유 폴더를 따라갑니다. 즉, 공유 폴더에 새 폴더(비어있는 상태)를 생성한 후 레드마인과 매핑하면, 레드마인의 매핑된 경로가 모두 비어집니다. 어떻게 아냐고요? 기존 서버를 그렇게 했다가 모두 지워졌거든요...&lt;/p&gt;
&lt;/div&gt;
&lt;/div&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;1091&quot; data-origin-height=&quot;646&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/z72dO/btsL2cgMsye/Kr88aFzdrBpLHNRhClzmAK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/z72dO/btsL2cgMsye/Kr88aFzdrBpLHNRhClzmAK/img.png&quot; data-alt=&quot;환경 변수 설정&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/z72dO/btsL2cgMsye/Kr88aFzdrBpLHNRhClzmAK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fz72dO%2FbtsL2cgMsye%2FKr88aFzdrBpLHNRhClzmAK%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; alt=&quot;환경 변수 설정&quot; loading=&quot;lazy&quot; width=&quot;700&quot; height=&quot;414&quot; data-origin-width=&quot;1091&quot; data-origin-height=&quot;646&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;환경 변수 설정&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style12&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;항목&lt;/td&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;값&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;DB_ADAPTER&lt;/td&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;mysql2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;DB_HOST&lt;/td&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;MariaDB 컨테이너 이름&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;DB_NAME&lt;/td&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;redmine&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;DB_USER&lt;/td&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;redmine DB 사용자 이름&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;DB_PASS&lt;/td&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;redmine DB 사용자 비밀번호&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;DB_PORT&lt;/td&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;MariaDB 포트 번호&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;TZ&lt;/td&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;Asia/Seoul&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 링크 설정에서 MariaDB 컨테이너를 선택합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1098&quot; data-origin-height=&quot;645&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/X4jNo/btsL4pMwIzt/XTIZAiksYJkCi5wOi14Je1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/X4jNo/btsL4pMwIzt/XTIZAiksYJkCi5wOi14Je1/img.png&quot; data-alt=&quot;컨테이너 링크 설정&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/X4jNo/btsL4pMwIzt/XTIZAiksYJkCi5wOi14Je1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FX4jNo%2FbtsL4pMwIzt%2FXTIZAiksYJkCi5wOi14Je1%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; alt=&quot;컨테이너 링크 설정&quot; loading=&quot;lazy&quot; width=&quot;700&quot; height=&quot;411&quot; data-origin-width=&quot;1098&quot; data-origin-height=&quot;645&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;이제 컨테이너 상태를 보면 MariaDB와 레드마인이 정상적으로 동작하는 것을 확인할 수 있습니다. (정상 동작 중인 모습을 캡처하지 못했네요... 정상 동작하면 상태에 초록색이 표시됩니다.)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1198&quot; data-origin-height=&quot;646&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/tYuBR/btsL4nBdxhQ/zLJkeira8weuQaNpVSrHfk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/tYuBR/btsL4nBdxhQ/zLJkeira8weuQaNpVSrHfk/img.png&quot; data-alt=&quot;컨테이너 동작 상태&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/tYuBR/btsL4nBdxhQ/zLJkeira8weuQaNpVSrHfk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FtYuBR%2FbtsL4nBdxhQ%2FzLJkeira8weuQaNpVSrHfk%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; alt=&quot;컨테이너 동작 상태&quot; loading=&quot;lazy&quot; width=&quot;700&quot; height=&quot;377&quot; data-origin-width=&quot;1198&quot; data-origin-height=&quot;646&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;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1236&quot; data-origin-height=&quot;504&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dzp4Je/btsL3ogw12A/moaW8kHBjX4GdZ5cB5X8Yk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dzp4Je/btsL3ogw12A/moaW8kHBjX4GdZ5cB5X8Yk/img.png&quot; data-alt=&quot;레드마인 초기 화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dzp4Je/btsL3ogw12A/moaW8kHBjX4GdZ5cB5X8Yk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdzp4Je%2FbtsL3ogw12A%2FmoaW8kHBjX4GdZ5cB5X8Yk%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; alt=&quot;레드마인 초기 화면&quot; loading=&quot;lazy&quot; width=&quot;700&quot; height=&quot;285&quot; data-origin-width=&quot;1236&quot; data-origin-height=&quot;504&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;admin/admin&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;1236&quot; data-origin-height=&quot;554&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/1wLae/btsL2kMJS1U/cnusBCwJPZ4qpHu4x9w5M0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/1wLae/btsL2kMJS1U/cnusBCwJPZ4qpHu4x9w5M0/img.png&quot; data-alt=&quot;초기 비밀번호 변경&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/1wLae/btsL2kMJS1U/cnusBCwJPZ4qpHu4x9w5M0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F1wLae%2FbtsL2kMJS1U%2FcnusBCwJPZ4qpHu4x9w5M0%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; alt=&quot;초기 비밀번호 변경&quot; loading=&quot;lazy&quot; width=&quot;700&quot; height=&quot;314&quot; data-origin-width=&quot;1236&quot; data-origin-height=&quot;554&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;초기 비밀번호 변경&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;정리하며&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음에는 익숙하지 않아 어렵게 느껴지지만, 막상 몇 번 반복하다 보면 어렵지 않게 구축할 수 있습니다. 그리고 레드마인 버전이 높다고 무조건 다 좋은 것은 아닙니다. 레드마인과 함께 사용할 플러그인의 호환성이 매우 중요하며, 설치 중 문제가 생기면 지웠다 설치하기를 반복 시도하여 최적의 조건을 찾아야 합니다. 레드마인 자체의 큰 문제가 없다면 플러그인 호환성에 맞춰 버전을 선택하는 것을 권장합니다.&lt;/p&gt;</description>
      <category>Redmine/Windows &amp;amp; NAS &amp;amp; Docker</category>
      <category>레드마인</category>
      <author>❤ </author>
      <guid isPermaLink="true">https://luckygg.tistory.com/400</guid>
      <comments>https://luckygg.tistory.com/400#entry400comment</comments>
      <pubDate>Fri, 31 Jan 2025 16:39:27 +0900</pubDate>
    </item>
    <item>
      <title>[.Net] 생성형 AI, C#에서 대규모 언어 모델(LLM) LLaMaSharp 사용하기(예제 포함)</title>
      <link>https://luckygg.tistory.com/397</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;생성형(Generative) AI란?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터를 기반으로 &lt;b&gt;새로운 콘텐츠를 생성하는 기술&lt;/b&gt;로, 이미 존재하는 데이터를 학습하여 새로운 이미지, 텍스트, 음악 등 &lt;b&gt;다양한 형태의 콘텐츠를 만들어내는 인공지능&lt;/b&gt;입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;'정의'만 들어보면 잘 와닿지 않을 텐데요. OpenAI의 &lt;b&gt;ChatGPT&lt;/b&gt;는 잘 아실 겁니다. 이 ChatGPT는 텍스트 생성에 초점을 맞춘 생성형 AI로, 방대한 양의 데이터를 학습하여 사용자와 자연스러운 대화를 나눌 수 있는 기술을 제공합니다. 조심해야 할 부분은, ChatGPT의 답변은 100% 정답이 아니며 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;허상 데이터(Hallucination)&lt;/span&gt;&lt;/code&gt;를 구분할 줄 알아야 한다는 점입니다. 즉, 맹신하기보다는 의심하는 자세를 취하고 사용해야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;요즘은 대기업뿐만 아니라 스타트업 기업에서도 생성형 AI를 탑재한 서비스를 내놓고 있습니다. 저는 특히, 최근 3D 제품 제조사에서 자신들의 기술과 매뉴얼을 기반으로 생성형 AI 서비스를 출시하여, 사용자로 하여금 기술 지원 빈도를 줄이고, 원하는 답변을 매뉴얼 정보로 표시해 신뢰성을 높인 부분이 대단하다고 생각합니다. 이제 단순히 정형화된 대답만 하는 챗봇을 마주치면 싱거운 기분이 듭니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자, 이번 본문에서는 C# 기반인 LLaMaSharp 라이브러리를 이용하여 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;대규모 언어 모델(LLM)&lt;/span&gt;&lt;/code&gt;을 사용해 질문하고 답변을 얻어보려고 합니다. (사실, 나만의 LLM을 특정 데이터를 기반으로 학습시켜보고 싶지만, 깊은 지식과 고성능 하드웨어가 부족하여 도전하지 못하고 있어 아쉽네요.)&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;LLaMaSharp 소개&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;LLaMaSharp은 Meta에서 개발한 LLaMA 모델 기반의 크로스 플랫폼 라이브러리입니다. 데이터 모델과 CPU 또는 GPU를 선택하여 다양한 동작 성능을 확인할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/SciSharp/LLamaSharp&quot;&gt;GitHub - SciSharp/LLamaSharp: A C#/.NET library to run LLM ( LLaMA/LLaVA) on your local device efficiently.&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1723555829459&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 - SciSharp/LLamaSharp: A C#/.NET library to run LLM ( LLaMA/LLaVA) on your local device efficiently.&quot; data-og-description=&quot;A C#/.NET library to run LLM ( LLaMA/LLaVA) on your local device efficiently. - SciSharp/LLamaSharp&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/SciSharp/LLamaSharp&quot; data-og-url=&quot;https://github.com/SciSharp/LLamaSharp&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://github.com/SciSharp/LLamaSharp&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/SciSharp/LLamaSharp&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;GitHub - SciSharp/LLamaSharp: A C#/.NET library to run LLM ( LLaMA/LLaVA) on your local device efficiently.&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;A C#/.NET library to run LLM ( LLaMA/LLaVA) on your local device efficiently. - SciSharp/LLamaSharp&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;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;console_demo.gif&quot; data-origin-width=&quot;1971&quot; data-origin-height=&quot;1078&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Jf6QR/btsI3gS7vgQ/qkPsa0QvMd5IUTQ25XLSFk/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Jf6QR/btsI3gS7vgQ/qkPsa0QvMd5IUTQ25XLSFk/img.gif&quot; data-alt=&quot;LLaMa 데모&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Jf6QR/btsI3gS7vgQ/qkPsa0QvMd5IUTQ25XLSFk/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/Jf6QR/btsI3gS7vgQ/qkPsa0QvMd5IUTQ25XLSFk/img.gif&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; alt=&quot;LLaMa-데모&quot; loading=&quot;lazy&quot; width=&quot;600&quot; height=&quot;328&quot; data-filename=&quot;console_demo.gif&quot; data-origin-width=&quot;1971&quot; data-origin-height=&quot;1078&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;LLaMa 데모&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래는 시각적 정보를 제공하는 LLaVa의 동작 데모 영상입니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;llava_demo.gif&quot; data-origin-width=&quot;2595&quot; data-origin-height=&quot;1809&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/be28up/btsI4cWOQgf/jOholuqTqJfKO1HaGyEa0K/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/be28up/btsI4cWOQgf/jOholuqTqJfKO1HaGyEa0K/img.gif&quot; data-alt=&quot;LLaVa 데모&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/be28up/btsI4cWOQgf/jOholuqTqJfKO1HaGyEa0K/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/be28up/btsI4cWOQgf/jOholuqTqJfKO1HaGyEa0K/img.gif&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; alt=&quot;LLaVa-데모&quot; loading=&quot;lazy&quot; width=&quot;600&quot; height=&quot;418&quot; data-filename=&quot;llava_demo.gif&quot; data-origin-width=&quot;2595&quot; data-origin-height=&quot;1809&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;LLaVa 데모&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;따라 하기&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. CUDA 12 SDK 설치하기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;LLaMaSharp을 사용하기 위해서 CUDA를 사용한다면 CUDA 11 또는 CUDA 12 SDK가 필요합니다. 저는 CUDA Toolkit 12.4를 설치했습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;CUDA Toolkit 12.4 설치된 모습.webp&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;255&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bPPS6u/btsI5gzmtQd/f5G3k6b4rfItKydrc4SLQk/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bPPS6u/btsI5gzmtQd/f5G3k6b4rfItKydrc4SLQk/img.webp&quot; data-alt=&quot;CUDA Toolkit 12.4 설치된 모습&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bPPS6u/btsI5gzmtQd/f5G3k6b4rfItKydrc4SLQk/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbPPS6u%2FbtsI5gzmtQd%2Ff5G3k6b4rfItKydrc4SLQk%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;600&quot; height=&quot;191&quot; data-filename=&quot;CUDA Toolkit 12.4 설치된 모습.webp&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;255&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;CUDA Toolkit 12.4 설치된 모습&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;2. 프로젝트 생성하기&lt;/h3&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;저는 Visual Studio 2022를 사용하여 콘솔(.Net Core 8.0) 프로젝트를 생성했습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Visual Studio 2022 .Net 8.0 프로젝트 생성 화면.webp&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;535&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lhPmu/btsI5AxGXDD/Kj4hLKlOPYUXkursyxidok/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lhPmu/btsI5AxGXDD/Kj4hLKlOPYUXkursyxidok/img.webp&quot; data-alt=&quot;Visual Studio 2022 .Net 8.0 프로젝트 생성 화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lhPmu/btsI5AxGXDD/Kj4hLKlOPYUXkursyxidok/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlhPmu%2FbtsI5AxGXDD%2FKj4hLKlOPYUXkursyxidok%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;600&quot; height=&quot;401&quot; data-filename=&quot;Visual Studio 2022 .Net 8.0 프로젝트 생성 화면.webp&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;535&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Visual Studio 2022 .Net 8.0 프로젝트 생성 화면&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. Nuget 설치하기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Nuget 패키지 관리에서 LLaMaSharp을 검색하고, 다음의 항목을 설치합니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;LLaMaSharp&lt;/li&gt;
&lt;li&gt;LLaMaSharp.Backend.Cpu (CPU 사용 시)&lt;/li&gt;
&lt;li&gt;LLaMaSharp.Backend.Cuda11 or 12 (GPU, CUDA 11 또는 12 사용에 따라 선택)&lt;/li&gt;
&lt;li&gt;Spectre.Console&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;LLaMaSharp Nuget 검색 화면.webp&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;480&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cJvQtM/btsI6ucqMAO/Cm7wcPkCUns7z2KkyZcGd0/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cJvQtM/btsI6ucqMAO/Cm7wcPkCUns7z2KkyZcGd0/img.webp&quot; data-alt=&quot;LLaMaSharp Nuget 검색 화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cJvQtM/btsI6ucqMAO/Cm7wcPkCUns7z2KkyZcGd0/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcJvQtM%2FbtsI6ucqMAO%2FCm7wcPkCUns7z2KkyZcGd0%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;600&quot; height=&quot;360&quot; data-filename=&quot;LLaMaSharp Nuget 검색 화면.webp&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;480&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;LLaMaSharp Nuget 검색 화면&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Spectre Nuget 검색 화면.webp&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;480&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/FLD26/btsI7hQTNpS/K11vGCUaZTNKXYuzQEZFx0/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/FLD26/btsI7hQTNpS/K11vGCUaZTNKXYuzQEZFx0/img.webp&quot; data-alt=&quot;Spectre Nuget 검색 화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/FLD26/btsI7hQTNpS/K11vGCUaZTNKXYuzQEZFx0/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FFLD26%2FbtsI7hQTNpS%2FK11vGCUaZTNKXYuzQEZFx0%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;600&quot; height=&quot;360&quot; data-filename=&quot;Spectre Nuget 검색 화면.webp&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;480&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Spectre Nuget 검색 화면&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4. 모델 파일 준비하기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;LLM의 모델 파일에는 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;PyTorch 형식(.pth)&lt;/span&gt;&lt;/code&gt;과 &lt;code&gt;&lt;span class=&quot;token function&quot;&gt;Huggingface 형식(.bin)&lt;/span&gt;&lt;/code&gt;이 많이 사용됩니다. LLamaSharp는 GGUF 형식 파일을 사용하는데, 이 두 형식에서 변환하여 사용할 수 있습니다. 다음은 GGUF 파일을 얻기 위한 방법을 설명합니다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;4-1. Hugging Face에서 얻기&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;허깅 페이스(Hugging Face)는 다양한 인공지능 모델을 오픈 소스로 제공하는 사이트입니다. 이 사이트에서 '모델이름 + GGUF'로 검색하여 다운로드할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://huggingface.co/&quot;&gt;Hugging Face &amp;ndash; The AI community building the future.&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1723557057187&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;Hugging Face &amp;ndash; The AI community building the future.&quot; data-og-description=&quot;The Home of Machine Learning Create, discover and collaborate on ML better. We provide paid Compute and Enterprise solutions. We are building the foundation of ML tooling with the community.&quot; data-og-host=&quot;huggingface.co&quot; data-og-source-url=&quot;https://huggingface.co/&quot; data-og-url=&quot;https://huggingface.co/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/6lsqv/hyWOe0VvyX/Q1bIv2ndIgs8poI7whwXF1/img.png?width=1200&amp;amp;height=648&amp;amp;face=0_0_1200_648,https://scrap.kakaocdn.net/dn/cq2Q3y/hyWOca0n5k/xxJdAeGiJd9ATCeUeIkkp0/img.png?width=1200&amp;amp;height=648&amp;amp;face=0_0_1200_648&quot;&gt;&lt;a href=&quot;https://huggingface.co/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://huggingface.co/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/6lsqv/hyWOe0VvyX/Q1bIv2ndIgs8poI7whwXF1/img.png?width=1200&amp;amp;height=648&amp;amp;face=0_0_1200_648,https://scrap.kakaocdn.net/dn/cq2Q3y/hyWOca0n5k/xxJdAeGiJd9ATCeUeIkkp0/img.png?width=1200&amp;amp;height=648&amp;amp;face=0_0_1200_648');&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;Hugging Face &amp;ndash; The AI community building the future.&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;The Home of Machine Learning Create, discover and collaborate on ML better. We provide paid Compute and Enterprise solutions. We are building the foundation of ML tooling with the community.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;huggingface.co&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;허깅페이스의 Blossom 8B 소개 화면.webp&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;452&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bgDpmA/btsI5P865ik/w8QjTKMKpsF83yh2ZhkNsK/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bgDpmA/btsI5P865ik/w8QjTKMKpsF83yh2ZhkNsK/img.webp&quot; data-alt=&quot;허깅페이스의 Blossom 8B 소개 화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bgDpmA/btsI5P865ik/w8QjTKMKpsF83yh2ZhkNsK/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbgDpmA%2FbtsI5P865ik%2Fw8QjTKMKpsF83yh2ZhkNsK%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;600&quot; height=&quot;339&quot; data-filename=&quot;허깅페이스의 Blossom 8B 소개 화면.webp&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;452&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;허깅페이스의 Blossom 8B 소개 화면&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;4-2. 직접 변환하기&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PyTorch 또는 Huggingface 형식의 모델 파일을 직접 GGUF 형식으로 변환하여 사용할 수 있습니다. 아래 링크의 가이드에 따라 파이썬 스크립트로 변환이 가능합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/ggerganov/llama.cpp?tab=readme-ov-file#prepare-and-quantize&quot;&gt;GitHub - ggerganov/llama.cpp: LLM inference in C/C++&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1723557259165&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 - ggerganov/llama.cpp: LLM inference in C/C++&quot; data-og-description=&quot;LLM inference in C/C++. Contribute to ggerganov/llama.cpp development by creating an account on GitHub.&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/ggerganov/llama.cpp?tab=readme-ov-file#prepare-and-quantize&quot; data-og-url=&quot;https://github.com/ggerganov/llama.cpp&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/CUgW8/hyWOcWmzdo/7qqgaBKGv4D4qMdbjvkhzk/img.png?width=1280&amp;amp;height=640&amp;amp;face=0_0_1280_640&quot;&gt;&lt;a href=&quot;https://github.com/ggerganov/llama.cpp?tab=readme-ov-file#prepare-and-quantize&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/ggerganov/llama.cpp?tab=readme-ov-file#prepare-and-quantize&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/CUgW8/hyWOcWmzdo/7qqgaBKGv4D4qMdbjvkhzk/img.png?width=1280&amp;amp;height=640&amp;amp;face=0_0_1280_640');&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 - ggerganov/llama.cpp: LLM inference in C/C++&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;LLM inference in C/C++. Contribute to ggerganov/llama.cpp 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;하지만 이러한 변환 과정이 저처럼 익숙치 않으시다면, 아쉽지만 허깅 페이스에서 제공하는 것만 찾아 쓸 수밖에 없습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;5. 코드 작성하기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;LLaMaSharp에서 제공하는 기본 예제 코드를 참고하여 아래의 메인 코드를 준비했습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1723788256707&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;using LLama;
using LLama.Common;
using LLama.Examples;

public class ChatSessionWithRoleName
{
    public static async Task Main()
    {
        string modelPath = UserSettings.GetModelPath();

        var parameters = new ModelParams(modelPath)
        {
            ContextSize = 1024,
            GpuLayerCount = 10,
            MainGpu = 0
        };
        using var model = LLamaWeights.LoadFromFile(parameters);
        using var context = model.CreateContext(parameters);
        var executor = new InteractiveExecutor(context);

        ChatSession session = new(executor);

        InferenceParams inferenceParams = new InferenceParams()
        {
            AntiPrompts = new List&amp;lt;string&amp;gt; { &quot;User:&quot; }
        };

        Console.ForegroundColor = ConsoleColor.Yellow;
        Console.WriteLine(&quot;The chat session has started.&quot;);

        // show the prompt
        Console.ForegroundColor = ConsoleColor.Green;
        string userInput = Console.ReadLine() ?? &quot;&quot;;

        while (userInput != &quot;exit&quot;)
        {
            await foreach (
                var text
                in session.ChatAsync(
                    new ChatHistory.Message(AuthorRole.User, userInput),
                    inferenceParams))
            {
                Console.ForegroundColor = ConsoleColor.White;
                Console.Write(text);
            }

            Console.ForegroundColor = ConsoleColor.Green;
            userInput = Console.ReadLine() ?? &quot;&quot;;

            Console.ForegroundColor = ConsoleColor.White;
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ContextSize, GpuLayerCount 등의 파라미터 튜닝이 가능하나, 자세히 다룰 줄 몰라 기본 값으로 적용했습니다. 전체 코드는 아래 첨부된 프로젝트 파일을 참고하세요.&lt;/p&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/k3Gu4/btsI6PAAlDG/Zt5UkfgKRBdfMyamhNd821/ExamLLaMaSharp.zip?attach=1&amp;amp;knm=tfile.zip&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;ExamLLaMaSharp.zip&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;size&quot;&gt;0.00MB&lt;/div&gt;
&lt;/div&gt;
  &lt;/a&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;동작 화면&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저는 허깅페이스에서 &lt;b&gt;llama-3-Korean-Bllossom-8B-Q4_K_M.gguf&lt;/b&gt; 모델을 다운로드하여 대화를 시도해 보았습니다. 축구 경기의 규칙을 설명해 달라고 했는데, 그럴싸한 답변을 주다가 어느 순간부터는 이상한 답변을 주기 시작합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;llamasharp.gif&quot; data-origin-width=&quot;1734&quot; data-origin-height=&quot;927&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ckZzfE/btsI5vpsnuS/i5hKhYVuMrUMkm0dIMEWo0/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ckZzfE/btsI5vpsnuS/i5hKhYVuMrUMkm0dIMEWo0/img.gif&quot; data-alt=&quot;동작 화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ckZzfE/btsI5vpsnuS/i5hKhYVuMrUMkm0dIMEWo0/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/ckZzfE/btsI5vpsnuS/i5hKhYVuMrUMkm0dIMEWo0/img.gif&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; alt=&quot;동작-화면&quot; loading=&quot;lazy&quot; width=&quot;600&quot; height=&quot;321&quot; data-filename=&quot;llamasharp.gif&quot; data-origin-width=&quot;1734&quot; data-origin-height=&quot;927&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;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;정리하며&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;로컬 PC 기반의 LLM 사용은 어떤가 살펴보았는데요. 여러 모델을 다운로드하여 테스트해 보았지만, 하드웨어 사양 부족, 튜닝 숙지 등의 문제로 원하는 성능을 얻지는 못했습니다. 어째서인지, 답변이 끝나지 않고 이상한 내용만 주더군요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개인적으로 만들어 보고 싶은 것이 있는데, 이에 적합한 모델을 찾는 것부터 파라미터 튜닝, 하드웨어 준비 등 생각해야 할 것들이 너무 많은 것 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음에는 OpenAI API와 같은 서비스를 이용하여 조금 더 쉽고 빠르게 접근이 가능한지 알아보려고 합니다.&lt;/p&gt;</description>
      <category>Programming/.Net</category>
      <category>.net</category>
      <category>LLM</category>
      <author>❤ </author>
      <guid isPermaLink="true">https://luckygg.tistory.com/397</guid>
      <comments>https://luckygg.tistory.com/397#entry397comment</comments>
      <pubDate>Fri, 16 Aug 2024 15:45:28 +0900</pubDate>
    </item>
    <item>
      <title>[.Net] XML 파일 읽기와 쓰기, 그리고 직렬화(Serialization)로 객체와 연동하는 방법(예제 포함)</title>
      <link>https://luckygg.tistory.com/396</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;XML이란?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;XML은 e&lt;b&gt;X&lt;/b&gt;tensible &lt;b&gt;M&lt;/b&gt;arkup &lt;b&gt;L&lt;/b&gt;anguage약자로, 말 그대로 '&lt;i&gt;확장 가능한 마크업 언어'&lt;/i&gt;를 뜻하는데, 좀 더 의미를 풀자면 '&lt;u&gt;&lt;i&gt;데이터를 정의하는 규칙을 제공하는 마크업 언어&lt;/i&gt;&lt;/u&gt;'입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;XML을 몰랐을 때에는 프로그램의 설정 파일로 &lt;b&gt;INI 포맷&lt;/b&gt;을 사용했었으나, XML을 접한 이후로는 줄곧 XML 파일만 사용하고 있습니다. 배열 형태로 나열이 가능하고, 데이터의 깊이도 자유롭게 설정이 가능하기 때문입니다. 또한, 가장 중요한 점은 &lt;b&gt;직렬화&lt;/b&gt;(Serialization)를 사용하여 객체와 연동이 쉬워 읽고 쓰기가 아주 편리하다는 점입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼, 본문에서는 XML 파일의 구조와 C#으로 어떻게 읽고 쓰는지를 보여주고, Serialization을 사용해 어떻게 객체화하는지 설명하겠습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;XML 구조&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;XML은 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;트리(Tree)&lt;/span&gt;&lt;/code&gt; 구조입니다. 하나의 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;노드(Node)&lt;/span&gt;&lt;/code&gt;를 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;요소(Element)&lt;/span&gt;&lt;/code&gt;라고 부르고, &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;루트(Root)&lt;/span&gt;&lt;/code&gt;부터 시작하여 하위요소가 이어집니다. 하위 요소 입장에서 상위 요소를 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;부모(Parent)&lt;/span&gt;&lt;/code&gt; 요소라고 부르고, 반대로는 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;자식(Child)&lt;/span&gt;&lt;/code&gt; 요소라고 부릅니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;XML 트리 구조.webp&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;558&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/n4IIA/btsHo6c2EMV/rZAucEBe0RKWIqC1P8IKq1/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/n4IIA/btsHo6c2EMV/rZAucEBe0RKWIqC1P8IKq1/img.webp&quot; data-alt=&quot;XML 트리 구조&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/n4IIA/btsHo6c2EMV/rZAucEBe0RKWIqC1P8IKq1/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fn4IIA%2FbtsHo6c2EMV%2FrZAucEBe0RKWIqC1P8IKq1%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;600&quot; height=&quot;419&quot; data-filename=&quot;XML 트리 구조.webp&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;558&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;XML 트리 구조&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 각 요소는 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;속성(Attribute)&lt;/span&gt;&lt;/code&gt;을 가질 수 있습니다. 아래 이미지는 Product 노드 이름에 'index'라는 속성과 '0'이라는 값이 포함된 모습입니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;노드에 속성이 포함된 모습.webp&quot; data-origin-width=&quot;602&quot; data-origin-height=&quot;368&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/LVlBz/btsHnI5ai9B/xGVUyZPfyVmbKpiWURx3fK/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/LVlBz/btsHnI5ai9B/xGVUyZPfyVmbKpiWURx3fK/img.webp&quot; data-alt=&quot;노드에 속성이 포함된 모습&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/LVlBz/btsHnI5ai9B/xGVUyZPfyVmbKpiWURx3fK/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FLVlBz%2FbtsHnI5ai9B%2FxGVUyZPfyVmbKpiWURx3fK%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;400&quot; height=&quot;245&quot; data-filename=&quot;노드에 속성이 포함된 모습.webp&quot; data-origin-width=&quot;602&quot; data-origin-height=&quot;368&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;span style=&quot;background-color: #ffffff; color: #222222; text-align: start;&quot;&gt;그럼 간단하게 반 별로 학생들의 개인 정보가 담긴 XML을 예시로 보겠습니다. A와 B라는 이름의 Class가 있고, Class 별로 몇 명의 학생이 포함되어 있습니다. 그리고 각 학생의 정보에는 이름과 핸드폰 번호가 담겨 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1715491009129&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;?xml version=&quot;1.0&quot;?&amp;gt;
&amp;lt;Root xmlns:xsd=&quot;http://www.w3.org/2001/XMLSchema&quot; xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;&amp;gt;
  &amp;lt;Class Name=&quot;A&quot;&amp;gt;
	&amp;lt;Student Index=&quot;0&quot;&amp;gt;
	  &amp;lt;Name&amp;gt;철수&amp;lt;/Name&amp;gt;
	  &amp;lt;Phone&amp;gt;010-xxxx-xxxx&amp;lt;/Phone&amp;gt;
	&amp;lt;/Student&amp;gt;  
	&amp;lt;Student Index=&quot;1&quot;&amp;gt;
	  &amp;lt;Name&amp;gt;영희&amp;lt;/Name&amp;gt;
	  &amp;lt;Phone&amp;gt;010-yyyy-yyyy&amp;lt;/Phone&amp;gt;
	&amp;lt;/Student&amp;gt;  
  &amp;lt;/Class&amp;gt;
  &amp;lt;Class Name=&quot;B&quot;&amp;gt;
	&amp;lt;Student Index=&quot;0&quot;&amp;gt;
	  &amp;lt;Name&amp;gt;짱구&amp;lt;/Name&amp;gt;
	  &amp;lt;Phone&amp;gt;010-zzzz-zzzz&amp;lt;/Phone&amp;gt;
	&amp;lt;/Student&amp;gt;  
	&amp;lt;Student Index=&quot;1&quot;&amp;gt;
	  &amp;lt;Name&amp;gt;맹구&amp;lt;/Name&amp;gt;
	  &amp;lt;Phone&amp;gt;010-xxxx-yyyy&amp;lt;/Phone&amp;gt;
	&amp;lt;/Student&amp;gt;  
	&amp;lt;Student Index=&quot;2&quot;&amp;gt;
	  &amp;lt;Name&amp;gt;기영&amp;lt;/Name&amp;gt;
	  &amp;lt;Phone&amp;gt;010-xxxx-zzzz&amp;lt;/Phone&amp;gt;
	&amp;lt;/Student&amp;gt;  
  &amp;lt;/Class&amp;gt;
&amp;lt;/Root&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #222222; text-align: start;&quot;&gt;사실 굳이 'Index' 속성을 붙일 필요가 없습니다. 그리고 Name과 Phone 노드도 속성으로 넣으면 더욱 심플해지죠. 그럼 위 파일을 코드로 어떻게 불러올 수 있는지, 어떻게 노드의 값에 접근하는지 보겠습니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1715491032163&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;using System.Xml;
 
private void btnOpen_Click(object sender, EventArgs e)
{
    try
    {
        OpenFileDialog dlg = new OpenFileDialog();
        if (dlg.ShowDialog() == DialogResult.OK )
        {
            XmlDocument doc = new XmlDocument();
            doc.Load(dlg.FileName);
 
            XmlNodeList nodes = doc.SelectNodes(@&quot;/Root/Class&quot;);
            var classes = nodes.Count; //반환 값: 2
            
            nodes = doc.SelectNodes(@&quot;/Root/Class[@Name='B']/Student&quot;);
            var students = nodes.Count; //반환 값: 3
 
            var node = doc.SelectSingleNode(@&quot;/Root/Class[@Name='B']/Student[@Index='1']/Name&quot;);
            var name = node.InnerText; //반환 값: 맹구
        }
    }
    catch(Exception exc)
    {
        MessageBox.Show(exc.Message);
    }
}&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;노드에 접근하기 위해서는 올바른 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;XPath(XML Path) 식&lt;/span&gt;&lt;/code&gt;을 사용해야 합니다. 위 예시처럼, 절대 경로 또는 상대 경로를 입력해야 하며, 속성에 접근하기 위해서는 노드에 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;[@속성='값']&lt;/span&gt;&lt;/code&gt; 키워드를 추가해야 합니다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #222222; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;만약, 불러오는 것뿐만 아니라 노드 삽입, 삭제, 값 변경 등의 편집도 원한다면 &lt;code&gt;&lt;span class=&quot;token function-name&quot;&gt;CreateElement&lt;/span&gt;&lt;/code&gt;, &lt;code&gt;&lt;span class=&quot;token function-name&quot;&gt;RemoveChild&lt;/span&gt;&lt;/code&gt;, &lt;code&gt;&lt;span class=&quot;token function-name&quot;&gt;AppendChild&lt;/span&gt;&lt;/code&gt;, &lt;code&gt;&lt;span class=&quot;token function-name&quot;&gt;CreateAttribute&lt;/span&gt;&lt;/code&gt; 등의 함수를 사용합니다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #222222; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;XMLDocument의 자세한 사용법은 아래 링크를 참고하세요.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #222222; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://learn.microsoft.com/ko-kr/dotnet/api/system.xml.xmldocument?view=netframework-4.8&quot;&gt;https://learn.microsoft.com/ko-kr/dotnet/api/system.xml.xmldocument?view=netframework-4.8&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1715491044069&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;XmlDocument 클래스 (System.Xml)&quot; data-og-description=&quot;XML 문서를 나타냅니다. 이 클래스를 사용하여 문서에서 XML 로드, 유효성 검사, 편집, 추가 및 위치 지정을 수행할 수 있습니다.&quot; data-og-host=&quot;learn.microsoft.com&quot; data-og-source-url=&quot;https://learn.microsoft.com/ko-kr/dotnet/api/system.xml.xmldocument?view=netframework-4.8&quot; data-og-url=&quot;https://learn.microsoft.com/ko-kr/dotnet/api/system.xml.xmldocument?view=net-8.0&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/wA1Pd/hyV2w21vdp/ZUUNxEax73VHRziyD4wGLk/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630&quot;&gt;&lt;a href=&quot;https://learn.microsoft.com/ko-kr/dotnet/api/system.xml.xmldocument?view=netframework-4.8&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://learn.microsoft.com/ko-kr/dotnet/api/system.xml.xmldocument?view=netframework-4.8&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/wA1Pd/hyV2w21vdp/ZUUNxEax73VHRziyD4wGLk/img.png?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;XmlDocument 클래스 (System.Xml)&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;XML 문서를 나타냅니다. 이 클래스를 사용하여 문서에서 XML 로드, 유효성 검사, 편집, 추가 및 위치 지정을 수행할 수 있습니다.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;learn.microsoft.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;background-color: #ffffff; color: #222222; text-align: start;&quot;&gt;프로그램 운영 중 XML을 편집하길 원한다면 사용하기 쉽게 Wrapper Class를 만드는 것을 추천합니다.&lt;/span&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #222222;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;XML 직렬화&lt;/span&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #222222;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;직렬화(Serialize)&lt;/span&gt;&lt;/code&gt;란, 데이터를 저장이나 전송을 위해 연속적인 바이트 단위의 데이터로 가공하는 것을 의미합니다. 이렇게 직렬화된 데이터는 반대로 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;역직렬화(Deserialize)&lt;/span&gt;&lt;/code&gt;를 통해 다시 원래의 데이터로 되돌릴 수 있습니다. XML&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #222222;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt; 직렬화는 어떤 객체를 XML 데이터로 직렬화하여 저장(또는 전송)하고, 다시 직렬화된 데이터를 객체로 되돌리는 데 사용될 수 있습니다. 위에서&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #222222;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt; 예시로 보여줬던 학생 정보가 담긴 XML 구조를 객체로 표현하면 다음과 같습니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1715510597070&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;using System.Xml.Serialization;

namespace ExamXML
{
    [Serializable]
    [XmlRoot(&quot;Root&quot;)]
    public class School
    {
        [XmlElement(&quot;Class&quot;)]
        public List&amp;lt;Class&amp;gt; Classes { get; set; }
    }

    [Serializable]
    public class Class
    {
        [XmlAttribute(&quot;Name&quot;)]
        public string Name { get; set; }

        [XmlElement(&quot;Student&quot;)]
        public List&amp;lt;Student&amp;gt; Students { get; set; }
    }

    [Serializable]
    public class Student
    {
        [XmlAttribute(&quot;Index&quot;)]
        public int Index { get; set; }

        [XmlElement(&quot;Name&quot;)]
        public string Name { get; set; }

        [XmlElement(&quot;Phone&quot;)]
        public string Phone { get; set; }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;Serializable&lt;/span&gt;&lt;/code&gt; 키워드는 객체가 직렬화할 수 있다는 의미이고, &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;XmlRoot&lt;/span&gt;&lt;/code&gt;와 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;XmlElement&lt;/span&gt;&lt;/code&gt;는 노드의 이름, 그리고 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;XmlAttrinute&lt;/span&gt;&lt;/code&gt;는 속성을 의미합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;객체를 XML 직렬화하기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;학생 정보가 담긴 School 객체를 Xml 직렬화하는 코드는 다음과 같습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1715512316575&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;private void btnSeiralize_Click(object sender, EventArgs e)
{
    try
    {
        var school = new School
        {
            Classes = new List&amp;lt;Class&amp;gt;
            {
                new Class
                {
                    Name = &quot;A&quot;,
                    Students = new List&amp;lt;Student&amp;gt;
                    {
                        new Student { Index = 0, Name = &quot;철수&quot;, Phone = &quot;010-xxxx-xxxx&quot; },
                        new Student { Index = 1, Name = &quot;영희&quot;, Phone = &quot;010-yyyy-yyyy&quot; }
                    }
                },
                new Class
                {
                    Name = &quot;B&quot;,
                    Students = new List&amp;lt;Student&amp;gt;
                    {
                        new Student { Index = 0, Name = &quot;짱구&quot;, Phone = &quot;010-zzzz-zzzz&quot; },
                        new Student { Index = 1, Name = &quot;맹구&quot;, Phone = &quot;010-xxxx-yyyy&quot; },
                        new Student { Index = 2, Name = &quot;기영&quot;, Phone = &quot;010-xxxx-zzzz&quot; }
                    }
                }
            }
        };

        SaveFileDialog dlg = new SaveFileDialog();
        if (dlg.ShowDialog() == DialogResult.OK)
        {
            XmlSerializer serializer = new XmlSerializer(typeof(School));
            using (FileStream fileStream = new FileStream(dlg.FileName, FileMode.Create))
            {
                serializer.Serialize(fileStream, school);
            }
        }
    }
    catch (Exception exc)
    {
        MessageBox.Show(exc.Message);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;객체를 XML 구조로 직렬화할 것이니, 확장자는 XML로 지정합니다. 저장된 파일을 열어보면 처음에 제시한 XML 파일과 동일합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;XML 파일을 객체로 역직렬화하기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번엔 반대로, XML 파일을 불러오면 School 객체로 변환이 가능합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1715512431620&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;private void btnDeserialize_Click(object sender, EventArgs e)
{
    try
    {
        OpenFileDialog dlg = new OpenFileDialog();
        if (dlg.ShowDialog() == DialogResult.OK)
        {
            XmlSerializer serializer = new XmlSerializer(typeof(School));
            using (FileStream fileStream = new FileStream(dlg.FileName, FileMode.Open))
            {
                School school = (School)serializer.Deserialize(fileStream);
            }
        }
    }
    catch (Exception exc)
    {
        MessageBox.Show(exc.Message);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 코드를 사용해 XML 파일을 불러오면, 아래와 같이 객체를 얻을 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;XML 파일로부터 객체로 역직렬화한 결과.webp&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;740&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bmvoRG/btsHnieMeRX/1Rkpl2kMCBGH4qzykF6Cj1/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bmvoRG/btsHnieMeRX/1Rkpl2kMCBGH4qzykF6Cj1/img.webp&quot; data-alt=&quot;XML 파일로부터 객체로 역직렬화한 결과&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bmvoRG/btsHnieMeRX/1Rkpl2kMCBGH4qzykF6Cj1/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbmvoRG%2FbtsHnieMeRX%2F1Rkpl2kMCBGH4qzykF6Cj1%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;600&quot; height=&quot;555&quot; data-filename=&quot;XML 파일로부터 객체로 역직렬화한 결과.webp&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;740&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;XML 파일로부터 객체로 역직렬화한 결과&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;정리하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개인적으로 XML은 주로 프로그램의 시스템 설정 값을 관리하는 용도로 사용합니다. INI보다 사용하기 편하고 직렬화를 통해 객체 관리가 더 용이한 것 같습니다. 참고로,&amp;nbsp;직렬화는 XML만 가능한 것은 아니고 어떤 객체든 직렬화/역직렬화가 가능합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;게다가 PropertyGrid 컨트롤과 XML 객체를 연동하면 XML 편집이 더욱 용이하고 활용성이 높아지는 장점이 있습니다. 한번 사용해 보세요.&lt;/p&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/G9ls6/btsHmtgh6Ti/DNpBFOh89OScKkEbIde6Ok/ExamXML.zip?attach=1&amp;amp;knm=tfile.zip&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;ExamXML.zip&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;size&quot;&gt;0.01MB&lt;/div&gt;
&lt;/div&gt;
  &lt;/a&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>Programming/.Net</category>
      <category>.net</category>
      <author>❤ </author>
      <guid isPermaLink="true">https://luckygg.tistory.com/396</guid>
      <comments>https://luckygg.tistory.com/396#entry396comment</comments>
      <pubDate>Mon, 13 May 2024 20:31:52 +0900</pubDate>
    </item>
    <item>
      <title>[.Net] WinForm UI 컨트롤 데이터 바인딩(Data Binding) 파헤치기(예제 포함)</title>
      <link>https://luckygg.tistory.com/395</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;데이터 바인딩(Data Binding)이란?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;혹시 WinForm UI 컨트롤 중 DataGridView나 ListBox에서 DataBinding 항목을 본 적이 있나요? 데이터 바인딩은 UI 컨트롤과 데이터를 연결하는 것을 의미합니다. 데이터와 UI 컨트롤이 연결되어 있으면, 데이터가 변경될 때 UI 컨트롤이 자동으로 갱신되게 됩니다. 즉, 데이터가 변경됐을 때 사용자가 일일이 UI 컨트롤을 수정할 필요가 없는 것이죠.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;DataGridView 속성 화면.webp&quot; data-origin-width=&quot;537&quot; data-origin-height=&quot;374&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/IaGdo/btsF0EXWGMo/TARTV1QKDvWSnWNQL1SXpK/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/IaGdo/btsF0EXWGMo/TARTV1QKDvWSnWNQL1SXpK/img.webp&quot; data-alt=&quot;DataGridView 속성 화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/IaGdo/btsF0EXWGMo/TARTV1QKDvWSnWNQL1SXpK/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FIaGdo%2FbtsF0EXWGMo%2FTARTV1QKDvWSnWNQL1SXpK%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;400&quot; height=&quot;279&quot; data-filename=&quot;DataGridView 속성 화면.webp&quot; data-origin-width=&quot;537&quot; data-origin-height=&quot;374&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;DataGridView 속성 화면&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터 바인딩을 사용할 때 또 하나의 장점이 있습니다. 대량의 데이터를 UI 컨트롤에 반영할 때 반응 속도가 빠르다는 것이죠.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;본문에서 데이터 바인딩을 사용하지 않았을 때 문제점, 데이터 바인딩을 적용하면 어떤 효과를 볼 수 있는지 자세히 다뤄보도록 하겠습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;DataGridView 컨트롤&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DataGridView는 흔히 엑셀에서 셀을 표시하는 것과 유사합니다. 제일 첫 번째 행에는 헤더 행(Header row)이 있고, 그 아래로는 데이터 행(Data row)이 추가됩니다. 그리고 제일 마지막 행에는 데이터 입력이 가능합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;DataGridView 컨트롤의 동작 화면.webp&quot; data-origin-width=&quot;672&quot; data-origin-height=&quot;426&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qGRDJ/btsF1Agl89l/IUqHG1TJkOCptuAAJtJsu1/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qGRDJ/btsF1Agl89l/IUqHG1TJkOCptuAAJtJsu1/img.webp&quot; data-alt=&quot;DataGridView 컨트롤의 동작 화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qGRDJ/btsF1Agl89l/IUqHG1TJkOCptuAAJtJsu1/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqGRDJ%2FbtsF1Agl89l%2FIUqHG1TJkOCptuAAJtJsu1%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;500&quot; height=&quot;317&quot; data-filename=&quot;DataGridView 컨트롤의 동작 화면.webp&quot; data-origin-width=&quot;672&quot; data-origin-height=&quot;426&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;DataGridView 컨트롤의 동작 화면&lt;/figcaption&gt;
&lt;/figure&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;아래 코드는 버튼을 클릭하면 '이름'과 '나이' 헤더에 두 개의 데이터를 추가하는 동작입니다.&lt;/p&gt;
&lt;pre id=&quot;code_1710677925624&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;private void btnCreateData_Click(object sender, EventArgs e)
{
    dataGridView1.Columns.Add(&quot;Column1&quot;, &quot;이름&quot;);
    dataGridView1.Columns.Add(&quot;Column2&quot;, &quot;나이&quot;);

    dataGridView1.Rows.Add(&quot;짱구&quot;, &quot;22&quot;);
    dataGridView1.Rows.Add(&quot;철수&quot;, &quot;33&quot;);
}&lt;/code&gt;&lt;/pre&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;코드 동작 결과.webp&quot; data-origin-width=&quot;677&quot; data-origin-height=&quot;430&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Db3XK/btsF4AZ5i6G/73tCsWCt7aCO7IuEQktTO0/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Db3XK/btsF4AZ5i6G/73tCsWCt7aCO7IuEQktTO0/img.webp&quot; data-alt=&quot;코드 동작 결과&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Db3XK/btsF4AZ5i6G/73tCsWCt7aCO7IuEQktTO0/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FDb3XK%2FbtsF4AZ5i6G%2F73tCsWCt7aCO7IuEQktTO0%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;500&quot; height=&quot;318&quot; data-filename=&quot;코드 동작 결과.webp&quot; data-origin-width=&quot;677&quot; data-origin-height=&quot;430&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;그럼 이번에는 훨씬 더 많은 5천 개의 데이터 행(Row)을 추가해 보겠습니다. 데이터 행을 추가하는 함수로 &lt;code&gt;&lt;span class=&quot;token function-name&quot;&gt;Add()&lt;/span&gt;&lt;/code&gt;가 사용됐습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1710678279534&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;private void btnCreateData_Click(object sender, EventArgs e)
{
    dataGridView1.Columns.Add(&quot;Column1&quot;, &quot;이름&quot;);
    dataGridView1.Columns.Add(&quot;Column2&quot;, &quot;나이&quot;);

    for (int i = 0; i &amp;lt; 5000; i++)
    {
        dataGridView1.Rows.Add($&quot;Name{i}&quot;, $&quot;Age{i}&quot;);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 동작 결과는 아래와 같습니다. 버튼을 클릭하고 약 1~2초 정도의 지연 후 컨트롤에 5천 개의 데이터가 추가됐습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;datagridview1.gif&quot; data-origin-width=&quot;770&quot; data-origin-height=&quot;457&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/GuZE6/btsFTd46yiw/JhNS2lt6kCXYkGNr9kuKR1/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/GuZE6/btsFTd46yiw/JhNS2lt6kCXYkGNr9kuKR1/img.gif&quot; data-alt=&quot;Add 함수로 데이터 추가한 결과&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/GuZE6/btsFTd46yiw/JhNS2lt6kCXYkGNr9kuKR1/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/GuZE6/btsFTd46yiw/JhNS2lt6kCXYkGNr9kuKR1/img.gif&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; alt=&quot;Add-함수로-데이터-추가한-결과&quot; loading=&quot;lazy&quot; width=&quot;500&quot; height=&quot;297&quot; data-filename=&quot;datagridview1.gif&quot; data-origin-width=&quot;770&quot; data-origin-height=&quot;457&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Add 함수로 데이터 추가한 결과&lt;/figcaption&gt;
&lt;/figure&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;이번에는 데이터 바인딩을 사용하여 데이터를 연결해 보겠습니다. &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;DataTable&lt;/span&gt;&lt;/code&gt;을 사용하여 Column을 추가하고, 이후 Rows에 데이터를 추가하면 됩니다.&lt;/p&gt;
&lt;pre id=&quot;code_1710678454173&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;private void btnDataBinding_Click(object sender, EventArgs e)
{
    DataTable dt = new DataTable();

    dt.Columns.Add(&quot;Column1&quot;);
    dt.Columns.Add(&quot;Column2&quot;);

    for (int i = 0; i &amp;lt; 5000; i++)
    {
        dt.Rows.Add($&quot;Name{i}&quot;, $&quot;Age{i}&quot;);
    }

    dataGridView1.DataSource = dt;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결과를 보면, 버튼을 클릭하자마자 데이터가 바로 보입니다. &lt;code&gt;&lt;span class=&quot;token function-name&quot;&gt;Add()&lt;/span&gt;&lt;/code&gt; 함수를 사용할 때 와는 다른 속도입니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;datagridview2.gif&quot; data-origin-width=&quot;770&quot; data-origin-height=&quot;457&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ci5Qsd/btsFOFbJX1L/BC1t8ZERhP6IZnhjYn1UKK/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ci5Qsd/btsFOFbJX1L/BC1t8ZERhP6IZnhjYn1UKK/img.gif&quot; data-alt=&quot;데이터 바인딩으로 추가한 결과&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ci5Qsd/btsFOFbJX1L/BC1t8ZERhP6IZnhjYn1UKK/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/ci5Qsd/btsFOFbJX1L/BC1t8ZERhP6IZnhjYn1UKK/img.gif&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; alt=&quot;데이터-바인딩으로-추가한-결과&quot; loading=&quot;lazy&quot; width=&quot;500&quot; height=&quot;297&quot; data-filename=&quot;datagridview2.gif&quot; data-origin-width=&quot;770&quot; data-origin-height=&quot;457&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한, 데이터 바인딩을 사용하면 데이터를 추가하고 삭제할 때 자동으로 컨트롤이 갱신됩니다. 아래 코드는 맨 마지막 행에 데이터를 추가하고, 맨 처음 행의 데이터를 삭제하는 동작입니다.&lt;/p&gt;
&lt;pre id=&quot;code_1710679127732&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;private void btnAdd_Click(object sender, EventArgs e)
{
    DataTable dt = (DataTable)dataGridView1.DataSource;
    dt.Rows.Add($&quot;Name{dt.Rows.Count}&quot;, $&quot;Age{dt.Rows.Count}&quot;);
}

private void btnDelete_Click(object sender, EventArgs e)
{
    DataTable dt = (DataTable)dataGridView1.DataSource;
    dt.Rows.RemoveAt(0);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;datagridview3.gif&quot; data-origin-width=&quot;834&quot; data-origin-height=&quot;457&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bbJUay/btsFRisDeoj/THr72x2Ufwtn5JBX0I2iC0/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bbJUay/btsFRisDeoj/THr72x2Ufwtn5JBX0I2iC0/img.gif&quot; data-alt=&quot;데이터 추가, 삭제 동작&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bbJUay/btsFRisDeoj/THr72x2Ufwtn5JBX0I2iC0/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/bbJUay/btsFRisDeoj/THr72x2Ufwtn5JBX0I2iC0/img.gif&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; alt=&quot;데이터-추가&amp;amp;#44;-삭제-동작&quot; loading=&quot;lazy&quot; width=&quot;500&quot; height=&quot;274&quot; data-filename=&quot;datagridview3.gif&quot; data-origin-width=&quot;834&quot; data-origin-height=&quot;457&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;데이터 추가, 삭제 동작&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;주의 사항&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터 행을 추가하는 &lt;code&gt;&lt;span class=&quot;token function-name&quot;&gt;Add()&lt;/span&gt;&lt;/code&gt; 그리고 제거하는 &lt;code&gt;&lt;span class=&quot;token function-name&quot;&gt;Remove()&lt;/span&gt;&lt;/code&gt;를 사용하는 일반적인 방식과 데이터 바인딩 방식은 같이 사용될 수 없습니다. 만약, 데이터 바인딩 이후 &lt;code&gt;&lt;span class=&quot;token function-name&quot;&gt;Add()&lt;/span&gt;&lt;/code&gt;나 &lt;code&gt;&lt;span class=&quot;token function-name&quot;&gt;Remove()&lt;/span&gt;&lt;/code&gt;를 호출하게 되면 다음의 메시지가 발생합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1711198799463&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;private void btnMixed_Click(object sender, EventArgs e)
{
    try
    {
        DataTable dt = new DataTable();
        dataGridView1.DataSource = dt;

        dataGridView1.Rows.Add($&quot;Name&quot;, $&quot;Age&quot;);
    }
    catch(Exception exc)
    {
        MessageBox.Show(exc.Message);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;오류.webp&quot; data-origin-width=&quot;500&quot; data-origin-height=&quot;180&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Q8UgT/btsF3f9WOqe/OrwLuZ6qha7I3gbRzZsed0/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Q8UgT/btsF3f9WOqe/OrwLuZ6qha7I3gbRzZsed0/img.webp&quot; data-alt=&quot;오류&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Q8UgT/btsF3f9WOqe/OrwLuZ6qha7I3gbRzZsed0/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FQ8UgT%2FbtsF3f9WOqe%2FOrwLuZ6qha7I3gbRzZsed0%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;400&quot; height=&quot;144&quot; data-filename=&quot;오류.webp&quot; data-origin-width=&quot;500&quot; data-origin-height=&quot;180&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;오류&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;컨트롤이 데이터 바인딩된 경우에는 DataGridView의 행 컬렉션에 프로그래밍 방식으로 행을 추가할 수 없습니다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서, 처음부터 데이터 바인딩을 사용할 것인지 아니면 프로그래밍 방식을 사용할 것인지 미리 선택한 후 개발해야 합니다.&lt;/p&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/MFzbm/btsF3XOv7Uv/ti2wtRen7DS2iASsEtrKak/TestDataBinding.zip?attach=1&amp;amp;knm=tfile.zip&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;TestDataBinding.zip&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;size&quot;&gt;0.02MB&lt;/div&gt;
&lt;/div&gt;
  &lt;/a&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>Programming/.Net</category>
      <category>.net</category>
      <author>❤ </author>
      <guid isPermaLink="true">https://luckygg.tistory.com/395</guid>
      <comments>https://luckygg.tistory.com/395#entry395comment</comments>
      <pubDate>Sun, 24 Mar 2024 18:09:18 +0900</pubDate>
    </item>
    <item>
      <title>[AI] ChatGPT 유료 버전 Custom 챗봇 생성 방법과 사용 후기</title>
      <link>https://luckygg.tistory.com/394</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;맞춤형 데이터 기반의 AI 챗봇&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OpenAI의 챗GPT(ChatGPT)는 정말 혁신적이죠. 작성일 기준, 챗GPT를 사용하면 2023년 4월까지의 학습된 정보를 기반으로 질문에 대한 답변을 받을 수 있습니다. 게다가 플러그인을 사용하면 웹 브라우저 검색으로 최신 데이터도 얻을 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;챗GPT를 사용하다가 문득 든 생각이, '현재 내가 갖고 있는 데이터를 기반으로 챗GPT와 같은 AI 챗봇을 만들 수 있을까?'였습니다. 회사의 업무 데이터를 기반으로 챗봇으로 만든다면, 사소하고 반복되는 업무나 과거 데이터를 찾을 때, 그리고 장기간 이어진 이슈를 요약할 때 유용하지 않을까 생각했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 생각과 다르게 현실의 벽은 너무 높았습니다. 인공지능 모델에 학습하기 위한 데이터 세트를 어떻게 준비해야 할 지, 그리고 방대한 양의 데이터를 혼자서 어떻게 편집할지, 게다가 인공지능 학습에 관한 개발 환경은 어떻게 준비해야 할지 등 고민해야 할 부분이 너무 많았습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러던 와중에 ChatGPT에 &lt;i&gt;&lt;b&gt;Custom ChatGPT&lt;/b&gt;&lt;/i&gt; 기능이 있다는 것을 접했습니다. 이는, 사용자 데이터를 기반으로 맞춤형 챗봇을 만드는 것인데요. 다행스럽게도 프로그래밍을 할 줄 몰라도 손쉽게 만들 수 있었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 포스팅을 통해 어떻게 Custom ChatGPT를 만드는 지, 성능은 어떤지 알아보겠습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;목표&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저는 특정 pdf 파일을 준비했으며, 이 내용 기반으로 챗봇을 제작하고자 합니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;준비물&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OpenAI ChatGPT 유료 버전을 구독해야 합니다. 작성일 기준, 한 달에 20$입니다. 그리고 학습할 데이터를 준비합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;484&quot; data-origin-height=&quot;542&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cu7Sb9/btsBJdOXFen/dTTWqTBKeNcxbxbqJraXCk/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cu7Sb9/btsBJdOXFen/dTTWqTBKeNcxbxbqJraXCk/img.webp&quot; data-alt=&quot;챗GPT 구독&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cu7Sb9/btsBJdOXFen/dTTWqTBKeNcxbxbqJraXCk/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcu7Sb9%2FbtsBJdOXFen%2FdTTWqTBKeNcxbxbqJraXCk%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; alt=&quot;챗GPT-구독&quot; loading=&quot;lazy&quot; width=&quot;484&quot; height=&quot;542&quot; data-origin-width=&quot;484&quot; data-origin-height=&quot;542&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;챗GPT 구독&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;따라 하기&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. GPT 생성하기(자동/수동)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ChatGPT 사이트에 접속한 후 좌측 상단의 아래 화면을 확인합니다. 그리고 &lt;i&gt;&lt;b&gt;Explore&lt;/b&gt;&lt;/i&gt; 메뉴를 클릭합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;413&quot; data-origin-height=&quot;173&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/csGxld/btsBGviwGbB/pftJUyzenNKVNcx2E2ljm1/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/csGxld/btsBGviwGbB/pftJUyzenNKVNcx2E2ljm1/img.webp&quot; data-alt=&quot;Explore 메뉴 클릭하기&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/csGxld/btsBGviwGbB/pftJUyzenNKVNcx2E2ljm1/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcsGxld%2FbtsBGviwGbB%2FpftJUyzenNKVNcx2E2ljm1%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; alt=&quot;Explore-메뉴-클릭하기&quot; loading=&quot;lazy&quot; width=&quot;279&quot; height=&quot;117&quot; data-origin-width=&quot;413&quot; data-origin-height=&quot;173&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Explore 메뉴 클릭하기&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래의 화면이 표시되면, &lt;i&gt;&lt;b&gt;Create a GPT&lt;/b&gt;&lt;/i&gt; 메뉴를 클릭합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;438&quot; data-origin-height=&quot;134&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/wKd7j/btsBFKAnyGF/2Daq3nuH2WWXvDvlozpRKK/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/wKd7j/btsBFKAnyGF/2Daq3nuH2WWXvDvlozpRKK/img.webp&quot; data-alt=&quot;Create a GPT 메뉴 클릭하기&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/wKd7j/btsBFKAnyGF/2Daq3nuH2WWXvDvlozpRKK/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FwKd7j%2FbtsBFKAnyGF%2F2Daq3nuH2WWXvDvlozpRKK%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; alt=&quot;Create-a-GPT-메뉴-클릭하기&quot; loading=&quot;lazy&quot; width=&quot;438&quot; height=&quot;134&quot; data-origin-width=&quot;438&quot; data-origin-height=&quot;134&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Create a GPT 메뉴 클릭하기&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 맞춤형 GPT를 만들기 위한 첫 단계입니다. 왼쪽은 GPT를 생성하기 위한 설정 화면이고, 오른쪽은 생성된 챗GPT를 평가하는 화면입니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;783&quot; data-origin-height=&quot;779&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ctHmwn/btsBDSseyEB/WnlZg8x2utC8iJLUEJbdQ0/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ctHmwn/btsBDSseyEB/WnlZg8x2utC8iJLUEJbdQ0/img.webp&quot; data-alt=&quot;GPT 생성 및 미리보기 화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ctHmwn/btsBDSseyEB/WnlZg8x2utC8iJLUEJbdQ0/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FctHmwn%2FbtsBDSseyEB%2FWnlZg8x2utC8iJLUEJbdQ0%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; alt=&quot;GPT-생성-및-미리보기-화면&quot; loading=&quot;lazy&quot; width=&quot;783&quot; height=&quot;779&quot; data-origin-width=&quot;783&quot; data-origin-height=&quot;779&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;GPT 생성 및 미리보기 화면&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;왼쪽화면의 상단에 &lt;i&gt;&lt;b&gt;Create&lt;/b&gt;&lt;/i&gt;와 &lt;i&gt;&lt;b&gt;Configure&lt;/b&gt; &lt;/i&gt;메뉴가 보이는데요. Create 메뉴는 GPT Builder와 대화하면서 이름과 프로필, 업로드 파일 등을 설정하게 됩니다. 뭐가 뭔지 모르겠으면 챗GPT를 사용하듯이 GPT Builder와 질문하면서 진행해 나가면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약, 능숙하게 사용할 줄 안다면 Configure 메뉴를 클릭해서 모든 설정을 직접 해서 GPT를 생성하면 됩니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;505&quot; data-origin-height=&quot;715&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bvGddV/btsBCokPi7j/KMyW1ms3IJKTWTAmWmKyl1/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bvGddV/btsBCokPi7j/KMyW1ms3IJKTWTAmWmKyl1/img.webp&quot; data-alt=&quot;Configure 메뉴 화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bvGddV/btsBCokPi7j/KMyW1ms3IJKTWTAmWmKyl1/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbvGddV%2FbtsBCokPi7j%2FKMyW1ms3IJKTWTAmWmKyl1%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; alt=&quot;Configure-메뉴-화면&quot; loading=&quot;lazy&quot; width=&quot;505&quot; height=&quot;715&quot; data-origin-width=&quot;505&quot; data-origin-height=&quot;715&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Configure 메뉴 화면&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. GPT 설정하기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;GPT Builder와 대화를 시작합니다. GPT를 어떤 목적으로 사용할 것인지 대답하면 이름과 프로필 사진을 제안해 줍니다. 만약, 영어가 답답하면 한국어로 대답해 달라고 얘기하면 됩니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;799&quot; data-origin-height=&quot;798&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bVs9DX/btsBKe73ZWV/CxqxwfDnL2kUaHj5CPrEZk/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bVs9DX/btsBKe73ZWV/CxqxwfDnL2kUaHj5CPrEZk/img.webp&quot; data-alt=&quot;GPT Builder와 대화하면서 설정하기&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bVs9DX/btsBKe73ZWV/CxqxwfDnL2kUaHj5CPrEZk/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbVs9DX%2FbtsBKe73ZWV%2FCxqxwfDnL2kUaHj5CPrEZk%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; alt=&quot;GPT-Builder와-대화하면서-설정하기&quot; loading=&quot;lazy&quot; width=&quot;799&quot; height=&quot;798&quot; data-origin-width=&quot;799&quot; data-origin-height=&quot;798&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;GPT Builder와 대화하면서 설정하기&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 준비된 자료를 Knowledge에 첨부합니다. 테스트한 결과 약 30개 정도 첨부하면 더 이상 업로드가 되지 않더군요. 여러 파일을 많이 올리기보다는 하나로 합쳐 업로드하는 게 더 효율적인 것 같습니다. 저는 다수의 PDF 파일이 있었는데 한 개의 PDF로 합쳐서 업로드했습니다. 이렇게 해도 원하는 답변을 얻는데 문제는 없었습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;587&quot; data-origin-height=&quot;246&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bgFlBM/btsBGk9iXla/DF4VUN51KSt6EAsYIOB49k/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bgFlBM/btsBGk9iXla/DF4VUN51KSt6EAsYIOB49k/img.webp&quot; data-alt=&quot;Knowledge에 파일 첨부하기&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bgFlBM/btsBGk9iXla/DF4VUN51KSt6EAsYIOB49k/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbgFlBM%2FbtsBGk9iXla%2FDF4VUN51KSt6EAsYIOB49k%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; alt=&quot;Knowledge에-파일-첨부하기&quot; loading=&quot;lazy&quot; width=&quot;587&quot; height=&quot;246&quot; data-origin-width=&quot;587&quot; data-origin-height=&quot;246&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Knowledge에 파일 첨부하기&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. GPT 테스트 및 저장, 완료하기&lt;/h3&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;799&quot; data-origin-height=&quot;799&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/4ToES/btsBF1BX3XN/Xx4uqxCnWgqqWe5MyqG10K/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/4ToES/btsBF1BX3XN/Xx4uqxCnWgqqWe5MyqG10K/img.webp&quot; data-alt=&quot;GPT 학습 결과 테스트하는 화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/4ToES/btsBF1BX3XN/Xx4uqxCnWgqqWe5MyqG10K/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F4ToES%2FbtsBF1BX3XN%2FXx4uqxCnWgqqWe5MyqG10K%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; alt=&quot;GPT-학습-결과-테스트하는-화면&quot; loading=&quot;lazy&quot; width=&quot;799&quot; height=&quot;799&quot; data-origin-width=&quot;799&quot; data-origin-height=&quot;799&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;GPT 학습 결과 테스트하는 화면&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;더이상 설정할 내용이 없다면 우측 상단의 &lt;i&gt;&lt;b&gt;Save&lt;/b&gt;&lt;/i&gt; 버튼을 클릭하여 저장합니다. 이렇게 만든 GPT를 다른 사람에게 공유할 순 있지만, 상대방도 Plus 구독자여야 사용이 가능합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;268&quot; data-origin-height=&quot;250&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/p6BKb/btsBKe73ZXl/wttDUDnFVspJG9Vahugon0/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/p6BKb/btsBKe73ZXl/wttDUDnFVspJG9Vahugon0/img.webp&quot; data-alt=&quot;GPT 저장하기&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/p6BKb/btsBKe73ZXl/wttDUDnFVspJG9Vahugon0/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fp6BKb%2FbtsBKe73ZXl%2FwttDUDnFVspJG9Vahugon0%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; alt=&quot;GPT-저장하기&quot; loading=&quot;lazy&quot; width=&quot;268&quot; height=&quot;250&quot; data-origin-width=&quot;268&quot; data-origin-height=&quot;250&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;GPT 저장하기&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;GPT 생성이 완료됐습니다. ChatGPT 사이트 메인으로 이동하면 아래와 같이 생성한 Custom ChatGPT가 보이게 됩니다. ChatGPT를 사용하듯이 대화를 걸면 원하는 답변을 얻을 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;460&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cHPC6K/btsBKmkIv7O/8KpyZaCAZ13oBptNy48YE1/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cHPC6K/btsBKmkIv7O/8KpyZaCAZ13oBptNy48YE1/img.webp&quot; data-alt=&quot;Custom GPT가 생성된 모습&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cHPC6K/btsBKmkIv7O/8KpyZaCAZ13oBptNy48YE1/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcHPC6K%2FbtsBKmkIv7O%2F8KpyZaCAZ13oBptNy48YE1%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; alt=&quot;Custom-GPT가-생성된-모습&quot; loading=&quot;lazy&quot; width=&quot;800&quot; height=&quot;460&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;460&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Custom GPT가 생성된 모습&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Custom ChatGPT 사용 후기&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. 레드마인 티켓 학습&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음 Custom ChatGPT에 학습한 파일은 레드마인 티켓이었습니다. 처음에는 레드마인 DB를 학습해야 하나 싶었는데, 티켓을 PDF로 저장하고 학습해도 가능한 것을 확인했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 티켓이 1만 개가 넘다 보니, 1만 개의 PDF를 업로드하는 것은 사실상 불가능했습니다. 그래서 이를 하나의 PDF로 합치고 학습하는 것으로 방법을 바꾸었습니다. 그래도 1만 개는 너무 많으니 100개 정도로 테스트를 진행했는데요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어떤 이슈를 얘기하면 과거에 어떻게 진행했었는지, 티켓 번호는 무엇인지 원하는 답변을 얻을 수 있었습니다. 하지만, 항상 100% 원하는 답변은 아니었고, 일부는 없는 답변을 주기도 했습니다. 전체 티켓을 학습한다고 해도 티켓마다 내용이 거의 다르니 Custom GPT 믿고 가기에는 조금은 불안한 느낌이 들었습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. 기술 자료&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번에는 기술 자료로 테스트를 해봤습니다. 레드마인 티켓은 시간의 흐름에 따라 어떤 일들이 있었는지 구구절절 이력이 남아있는 것에 반해, 기술 자료는 '무엇을 하려면 어떻게 해야 한다'라는 내용이 명확하게 기록되어 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 자료 기반으로 생성된 GPT는 상당히 만족스러운 결과를 얻을 수 있었습니다. 어떤 질문을 하면 학습된 내용 기반으로 거의 완벽한 답변을 얻을 수 있었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아무래도 깔끔하게 정리가 된 자료 기반으로 학습하는 것이 답변 퀄리티가 높은 것 같습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. 도서 및 논문&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인터넷에 오픈되어 있는 샘플 도서 PDF 및 논문 자료를 사용하여 학습해 보았습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PDF 전체 내용을 요약하거나 특정 주제를 찾을 때, 그리고 그 내용을 구체적으로 설명을 원할 때 사용하면 아주 유용합니다. PDF가 수백 페이지가 넘어가면 특정 내용을 찾기도 어렵지만 정리하기도 힘든데요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Custom ChatGPT로 학습하면 요약, 내용 분석, 쉬운 설명이 가능해집니다. 사실 몰랐던 부분인데, 챗GPT 말고도 PDF를 요약해주는 서비스가 여럿 있더군요.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;정리&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저에게는 굳이 Custom ChatGPT를 사용하기 위해 유로 서비스를 구독할 필요는 없을 것 같습니다. 누군가와 공유를 하기 위해 서비스를 만드는 게 아니라면, Knowledge를 사용한 챗GPT를 사용할 일은 없을 것 같기 때문입니다. 그저, '유료를 사용하던 와중에 이런 기능이 있어서 사용한다'라는 접근이 낫지 않을까 싶습니다.&lt;/p&gt;</description>
      <category>Programming/AI</category>
      <category>ChatGPT</category>
      <author>❤ </author>
      <guid isPermaLink="true">https://luckygg.tistory.com/394</guid>
      <comments>https://luckygg.tistory.com/394#entry394comment</comments>
      <pubDate>Sat, 9 Dec 2023 18:42:23 +0900</pubDate>
    </item>
    <item>
      <title>[셀레니움/Selenium, C#] ChromeDriver 버전 자동 업데이트 적용 방법</title>
      <link>https://luckygg.tistory.com/393</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;크롬 드라이버 업데이트&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;크롬 브라우저 기반으로 크롤링 프로그램 개발 시 현재 시스템에 설치되어 있는 크롬 브라우저의 버전과, 실행되는 프로그램의 버전을 맞추는 작업이 참 귀찮았습니다.&lt;/p&gt;
&lt;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://luckygg.tistory.com/323&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;[셀레니움/Selenium, C#] ChromeDriver 버전 에러 해결 방법&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1700657072765&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;[셀레니움/Selenium, C#] ChromeDriver 버전 에러 해결 방법&quot; data-og-description=&quot;크롬 드라이버 버전 오류 현상 크롬 드라이버를 이용한 크롤링 프로그램 제작 시 아래의 메시지는 한 번쯤은 봤을 것입니다. session not created: This version of ChromeDriver only supports Chrome version 85 (Session&quot; data-og-host=&quot;luckygg.tistory.com&quot; data-og-source-url=&quot;https://luckygg.tistory.com/323&quot; data-og-url=&quot;https://luckygg.tistory.com/323&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/dNpODZ/hyUCehr3y1/xqXZl9OMnzNdyKsdakKmNk/img.png?width=800&amp;amp;height=603&amp;amp;face=0_0_800_603,https://scrap.kakaocdn.net/dn/wrl0h/hyUCcRsNSD/WUhwSP3rGhrV74RkWzGp5k/img.png?width=800&amp;amp;height=603&amp;amp;face=0_0_800_603,https://scrap.kakaocdn.net/dn/b7hZwL/hyUytAzCZX/J37b9EOTafOsISKkakOP01/img.png?width=960&amp;amp;height=724&amp;amp;face=0_0_960_724&quot;&gt;&lt;a href=&quot;https://luckygg.tistory.com/323&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://luckygg.tistory.com/323&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/dNpODZ/hyUCehr3y1/xqXZl9OMnzNdyKsdakKmNk/img.png?width=800&amp;amp;height=603&amp;amp;face=0_0_800_603,https://scrap.kakaocdn.net/dn/wrl0h/hyUCcRsNSD/WUhwSP3rGhrV74RkWzGp5k/img.png?width=800&amp;amp;height=603&amp;amp;face=0_0_800_603,https://scrap.kakaocdn.net/dn/b7hZwL/hyUytAzCZX/J37b9EOTafOsISKkakOP01/img.png?width=960&amp;amp;height=724&amp;amp;face=0_0_960_724');&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;[셀레니움/Selenium, C#] ChromeDriver 버전 에러 해결 방법&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;크롬 드라이버 버전 오류 현상 크롬 드라이버를 이용한 크롤링 프로그램 제작 시 아래의 메시지는 한 번쯤은 봤을 것입니다. session not created: This version of ChromeDriver only supports Chrome version 85 (Session&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;luckygg.tistory.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 data-ke-size=&quot;size16&quot;&gt;사실, 이보다 더 간편한 방법이 있습니다. 프로그램 실행 시 자동으로 크롬 드라이버를 업데이트하는 방법입니다. 그럼 더 이상 귀찮게 직접 다운로드할 필요가 없지요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;본문에서 차근차근 설명하겠습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;따라 하기&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. C# 프로젝트 생성하기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;콘솔이든 WinForm이든 상관 없습니다. 사용하기 편한 프로젝트를 생성합니다. 저는 WinForm 프로젝트를 생성했습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. NuGet에서 Selenium 패키지 설치하기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로젝트 생성 후 Visual Studio 상단 메뉴 중 &lt;i&gt;&lt;b&gt;도구 &amp;gt; NuGet 패키지 관리자 &amp;gt; 솔루션용 NuGet 패키지 관리&lt;/b&gt;&lt;/i&gt; 메뉴를 클릭합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;426&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cmQH01/btsAJzHoG29/lj90L1a9EXjX9ShIikIaZ0/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cmQH01/btsAJzHoG29/lj90L1a9EXjX9ShIikIaZ0/img.webp&quot; data-alt=&quot;NuGet 패키지 관리 메뉴&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cmQH01/btsAJzHoG29/lj90L1a9EXjX9ShIikIaZ0/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcmQH01%2FbtsAJzHoG29%2Flj90L1a9EXjX9ShIikIaZ0%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; alt=&quot;NuGet-패키지-관리-메뉴&quot; loading=&quot;lazy&quot; width=&quot;426&quot; data-origin-width=&quot;426&quot; data-origin-height=&quot;0&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;NuGet 패키지 관리 메뉴&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;&lt;b&gt;찾아보기&lt;/b&gt;&lt;/i&gt; 탭에서 검색란에 &lt;i&gt;&lt;b&gt;selenium&lt;/b&gt;&lt;/i&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;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lxP36/btsAMVBSvw4/kjIumklGPxPaR9eVFSsKXk/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lxP36/btsAMVBSvw4/kjIumklGPxPaR9eVFSsKXk/img.webp&quot; data-alt=&quot;selenium 패키지 검색&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lxP36/btsAMVBSvw4/kjIumklGPxPaR9eVFSsKXk/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlxP36%2FbtsAMVBSvw4%2FkjIumklGPxPaR9eVFSsKXk%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; alt=&quot;selenium-패키지-검색&quot; loading=&quot;lazy&quot; width=&quot;401&quot; data-origin-width=&quot;401&quot; data-origin-height=&quot;0&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;selenium 패키지 검색&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;검색 결과에서 &lt;i&gt;&lt;b&gt;Selenium.WebDriver&lt;/b&gt;&lt;/i&gt;와 &lt;i&gt;&lt;b&gt;Selenium.Support&lt;/b&gt; &lt;/i&gt;패키지를 프로젝트에 설치합니다. 그리고 다시 검색 란에 &lt;i&gt;&lt;b&gt;web driver manager&lt;/b&gt;&lt;/i&gt;를 검색합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;369&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/on8mx/btsAJztLODs/BOZyoAQnUu36SsCy57iIp0/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/on8mx/btsAJztLODs/BOZyoAQnUu36SsCy57iIp0/img.webp&quot; data-alt=&quot;web driver manager 패키지 검색&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/on8mx/btsAJztLODs/BOZyoAQnUu36SsCy57iIp0/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fon8mx%2FbtsAJztLODs%2FBOZyoAQnUu36SsCy57iIp0%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; alt=&quot;web-driver-manager-패키지-검색&quot; loading=&quot;lazy&quot; width=&quot;369&quot; data-origin-width=&quot;369&quot; data-origin-height=&quot;0&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;web driver manager 패키지 검색&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;&lt;b&gt;WebDriverManager&lt;/b&gt;&lt;/i&gt; 패키지를 프로젝트에 설치합니다.&lt;/p&gt;
&lt;div class=&quot;rgyInfo&quot;&gt;
&lt;div class=&quot;rgyInfo-circle&quot;&gt;
&lt;div class=&quot;topDiv&quot;&gt;주의&lt;/div&gt;
&lt;div class=&quot;bottomDiv&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;bottomDiv2&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;rgyInfo-text&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약, &lt;i&gt;&lt;b&gt;Selenium.WeDriver.ChromeDriver&lt;/b&gt;&lt;/i&gt; 패키지를 같이 설치하면 드라이버 충돌이 발생해 크롬 드라이버가 일치하지 않는다는 오류가 계속해서 발생합니다.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3. 코드 구현&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본적인 코드 사용 방법은 아래와 같습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1700658612216&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//기본 namespace 생략
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using OpenQA.Selenium.Support.UI;
using WebDriverManager;
using WebDriverManager.Helpers;
using WebDriverManager.DriverConfigs.Impl;

namespace ExamSelenium
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();

            try
            {
                ChromeDriverService driverService = null;
                ChromeOptions options = null;
                ChromeDriver driver = null;

                //크롬 드라이버 자동 업데이트
                new DriverManager().SetUpDriver(new ChromeConfig(), VersionResolveStrategy.MatchingBrowser);

                driverService = ChromeDriverService.CreateDefaultService();
                driverService.HideCommandPromptWindow = true;

                options = new ChromeOptions();
                options.AddArgument(&quot;disable-gpu&quot;);

                driver = new ChromeDriver(driverService, options);

                driver.Navigate().GoToUrl(&quot;https://www.naver.com&quot;);
            }
            catch(Exception exc)
            {
                MessageBox.Show(exc.Message);
            }
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Chrome 관련 객체는 예전에 설명한 내용과 동일하고, 24번째 라인의 &lt;code&gt;&lt;span class=&quot;token function-name&quot;&gt;DriverManager()&lt;/span&gt;&lt;/code&gt; 부분이 핵심입니다. 이 코드가 실행되면 현재 시스템에 설치되어 있는 브라우저와 일치하는 크롬 드라이버가 자동으로 준비됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;크롬 드라이버 업데이트 방법은 다음과 같이 여러 방법이 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1700658810459&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//특정 버전
new DriverManager().SetUpDriver(new ChromeConfig(), &quot;2.25&quot;)

//특정 아키텍처
new DriverManager().SetUpDriver(new ChromeConfig(), &quot;Latest&quot;, Architecture.X32)

//특정 버전 및 특정 아키텍처
new DriverManager().SetUpDriver(new ChromeConfig(), &quot;2.25&quot;, Architecture.X64)

//브라우저와 일치하는 버전(Chrome, Edge, Firefox, Internet Explorer만 해당):
new DriverManager().SetUpDriver(new ChromeConfig(), VersionResolveStrategy.MatchingBrowser);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 외 WebDriverManager에 대해 더 궁금하다면 아래 GitHub 페이지를 참고하세요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/rosolko/WebDriverManager.Net&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;https://github.com/rosolko/WebDriverManager.Net&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1700658973413&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 - rosolko/WebDriverManager.Net: Automatic Selenium Webdriver binaries management for .Net&quot; data-og-description=&quot;Automatic Selenium Webdriver binaries management for .Net - GitHub - rosolko/WebDriverManager.Net: Automatic Selenium Webdriver binaries management for .Net&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/rosolko/WebDriverManager.Net&quot; data-og-url=&quot;https://github.com/rosolko/WebDriverManager.Net&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/u8mI9/hyUCf1I1zQ/lDEKWYiWVzw84247C3notK/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/rosolko/WebDriverManager.Net&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/rosolko/WebDriverManager.Net&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/u8mI9/hyUCf1I1zQ/lDEKWYiWVzw84247C3notK/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 - rosolko/WebDriverManager.Net: Automatic Selenium Webdriver binaries management for .Net&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Automatic Selenium Webdriver binaries management for .Net - GitHub - rosolko/WebDriverManager.Net: Automatic Selenium Webdriver binaries management for .Net&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;</description>
      <category>Programming/Selenium</category>
      <category>.net</category>
      <category>셀레니움</category>
      <author>❤ </author>
      <guid isPermaLink="true">https://luckygg.tistory.com/393</guid>
      <comments>https://luckygg.tistory.com/393#entry393comment</comments>
      <pubDate>Wed, 22 Nov 2023 22:18:29 +0900</pubDate>
    </item>
    <item>
      <title>[.Net] ML.NET을 이용한 딥 러닝 모델 생성하기 - 이미지 분류</title>
      <link>https://luckygg.tistory.com/392</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;인공 지능&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;인공 지능(AI)&lt;/b&gt;이라는 키워드가 어딜 가나 빠지지 않습니다. 학습 도구는 물론이고 자동차, CCTV, 검색 엔진, 챗봇, 글자 인식(OCR) 등 다양한 분야에서 인공 지능 기술이 많이 접목되었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인공 지능의 역사는 1950년대 까지 거슬러 올라간다고 하는데요. 지금까지 여러 암흑기를 거치고 지속적인 발전을 통해 오늘날 챗GPT까지 오게 됐습니다. 그 결과, AI 기술은 우리 생활과 밀접하게 연결되었고, AI 기술을 얼마나 활용하냐에 따라 업무 효율성이 달라질 정도입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;본 포스팅은 머신 러닝(인공 지능 분야의 하위 집합, 분야)에 대한 깊은 지식이 없더라도, C# 언어를 사용하여 간단하게 머신 러닝 라이브러리를 사용할 수 있는 방법을 소개하고자 합니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;ML.NET&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ML.NET은 마이크로소프트에서 만든 머신 러닝 프레임워크로, 무료 오픈 소스 플랫폼입니다. 앞서 얘기한 것처럼, 머신 러닝에 대한 지식이 없어도 가이드대로 라이브러리를 사용하면 원하는 결과를 얻을 수 있습니다. 주요 특징을 나열하면 다음과 같습니다.&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;C# 및 F# 지원&lt;/li&gt;
&lt;li&gt;.NET Core 2.0 이상, .NET Framework 4.6.1 이상 지원&lt;/li&gt;
&lt;li&gt;Windows, Linux, macOS 지원&lt;/li&gt;
&lt;li&gt;데이터/이미지/문자열 분류, 값 예측, 개체 감지 등 지원&lt;/li&gt;
&lt;li&gt;Visual Studio 2019, 2022&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;공식 홈페이지: &lt;a href=&quot;https://dotnet.microsoft.com/ko-kr/learn/ml-dotnet/what-is-mldotnet&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://dotnet.microsoft.com/ko-kr/learn/ml-dotnet/what-is-mldotnet&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1696339346995&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;ML.NET란? 오픈 소스 기계 학습 프레임워크.&quot; data-og-description=&quot;ML.NET은 .NET 개발자 플랫폼을 위해 Microsoft에서 만든 무료 오픈 소스 플랫폼 간 기계 학습 프레임워크입니다.&quot; data-og-host=&quot;dotnet.microsoft.com&quot; data-og-source-url=&quot;https://dotnet.microsoft.com/ko-kr/learn/ml-dotnet/what-is-mldotnet&quot; data-og-url=&quot;https://dotnet.microsoft.com/ko-kr/learn/ml-dotnet/what-is-mldotnet&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/cn41aV/hyT56RY35N/wJHpq9CQYbFEk22eo3mE0k/img.png?width=238&amp;amp;height=238&amp;amp;face=0_0_238_238,https://scrap.kakaocdn.net/dn/g69gx/hyT5ZedSpT/zL7jNYrteqErXCFzVhmFeK/img.png?width=459&amp;amp;height=238&amp;amp;face=0_0_459_238&quot;&gt;&lt;a href=&quot;https://dotnet.microsoft.com/ko-kr/learn/ml-dotnet/what-is-mldotnet&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://dotnet.microsoft.com/ko-kr/learn/ml-dotnet/what-is-mldotnet&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/cn41aV/hyT56RY35N/wJHpq9CQYbFEk22eo3mE0k/img.png?width=238&amp;amp;height=238&amp;amp;face=0_0_238_238,https://scrap.kakaocdn.net/dn/g69gx/hyT5ZedSpT/zL7jNYrteqErXCFzVhmFeK/img.png?width=459&amp;amp;height=238&amp;amp;face=0_0_459_238');&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;ML.NET란? 오픈 소스 기계 학습 프레임워크.&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;ML.NET은 .NET 개발자 플랫폼을 위해 Microsoft에서 만든 무료 오픈 소스 플랫폼 간 기계 학습 프레임워크입니다.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;dotnet.microsoft.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;시나리오&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ML.NET에서는 시나리오에 따라 모델 학습이 달라집니다. 지원하는 시나리오는 아래 그림과 같습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;654&quot; data-origin-height=&quot;687&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/brONgz/btsytgoVXWL/MOx8TmeGFNbDl4WS0dDDXk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/brONgz/btsytgoVXWL/MOx8TmeGFNbDl4WS0dDDXk/img.png&quot; data-alt=&quot;시나리오 종류&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/brONgz/btsytgoVXWL/MOx8TmeGFNbDl4WS0dDDXk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbrONgz%2FbtsytgoVXWL%2FMOx8TmeGFNbDl4WS0dDDXk%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;654&quot; height=&quot;687&quot; data-origin-width=&quot;654&quot; data-origin-height=&quot;687&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;본문에서는 강아지와 고양이를 구분하는 이미지 분류 시나리오를 선택하여 성능 및 결과를 살펴보겠습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;따라 하기&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. ML.NET Model Builder 설치하기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Visual Studio 구성에서 아래 그림과 같이 ML.NET Model Builder가 설치되어 있는지 확인합니다. 없다면, 체크한 후 설치를 진행합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;945&quot; data-origin-height=&quot;532&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bNXf3j/btswgWspXzT/jjUC2NIUitSTXzuHSUKKE1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bNXf3j/btswgWspXzT/jjUC2NIUitSTXzuHSUKKE1/img.png&quot; data-alt=&quot;ML.NET Model Builder 설치하기&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bNXf3j/btswgWspXzT/jjUC2NIUitSTXzuHSUKKE1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbNXf3j%2FbtswgWspXzT%2FjjUC2NIUitSTXzuHSUKKE1%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;945&quot; height=&quot;532&quot; data-origin-width=&quot;945&quot; data-origin-height=&quot;532&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;ML.NET Model Builder 설치하기&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. ML.NET Model Builder 업데이트하기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Visual Studio를 실행하고 &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;241&quot; data-origin-height=&quot;129&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/vhytf/btsysJMaxZ9/0KvkcUTJ95QNMwghIJkOwK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/vhytf/btsysJMaxZ9/0KvkcUTJ95QNMwghIJkOwK/img.png&quot; data-alt=&quot;확장 관리 메뉴&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/vhytf/btsysJMaxZ9/0KvkcUTJ95QNMwghIJkOwK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fvhytf%2FbtsysJMaxZ9%2F0KvkcUTJ95QNMwghIJkOwK%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;241&quot; height=&quot;129&quot; data-origin-width=&quot;241&quot; data-origin-height=&quot;129&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;ML.NET Model Builder&lt;/b&gt;가 있는지 확인합니다. Model Builder를 방금 설치했어도 업데이트가 안되어 있을 수 있습니다. 버전이 낮으면 학습 단계에서 문제가 생길 수 있으므로 반드시 업데이트합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;733&quot; data-origin-height=&quot;509&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xu3RF/btsyujS1zPE/6PmUM2whPKXKwVw3Fu5gKk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xu3RF/btsyujS1zPE/6PmUM2whPKXKwVw3Fu5gKk/img.png&quot; data-alt=&quot;Model Builder 업데이트&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xu3RF/btsyujS1zPE/6PmUM2whPKXKwVw3Fu5gKk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fxu3RF%2FbtsyujS1zPE%2F6PmUM2whPKXKwVw3Fu5gKk%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;733&quot; height=&quot;509&quot; data-origin-width=&quot;733&quot; data-origin-height=&quot;509&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Model Builder 업데이트&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. 프로젝트 생성 및 기계 학습 모델 추가&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;콘솔 앱(.NET Framework) 프로젝트를 생성합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;801&quot; data-origin-height=&quot;532&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/KsYDb/btsyspNpq5c/kRtwtp503QZuuifkGV6h8k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/KsYDb/btsyspNpq5c/kRtwtp503QZuuifkGV6h8k/img.png&quot; data-alt=&quot;프로젝트 생성&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/KsYDb/btsyspNpq5c/kRtwtp503QZuuifkGV6h8k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FKsYDb%2FbtsyspNpq5c%2FkRtwtp503QZuuifkGV6h8k%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;801&quot; height=&quot;532&quot; data-origin-width=&quot;801&quot; data-origin-height=&quot;532&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;기계 학습 모델&lt;/b&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;760&quot; data-origin-height=&quot;734&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mWJT7/btsyrAvajAE/rZWJ4rZ35PZB9TgSermT11/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mWJT7/btsyrAvajAE/rZWJ4rZ35PZB9TgSermT11/img.png&quot; data-alt=&quot;기계 학습 모델&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mWJT7/btsyrAvajAE/rZWJ4rZ35PZB9TgSermT11/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmWJT7%2FbtsyrAvajAE%2FrZWJ4rZ35PZB9TgSermT11%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;760&quot; height=&quot;734&quot; data-origin-width=&quot;760&quot; data-origin-height=&quot;734&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;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;851&quot; data-origin-height=&quot;590&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ehsVhq/btsysJld73K/CKFAAtnNfjkRGG1dqikrw1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ehsVhq/btsysJld73K/CKFAAtnNfjkRGG1dqikrw1/img.png&quot; data-alt=&quot;Machine Learning Model 추가&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ehsVhq/btsysJld73K/CKFAAtnNfjkRGG1dqikrw1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FehsVhq%2FbtsysJld73K%2FCKFAAtnNfjkRGG1dqikrw1%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;851&quot; height=&quot;590&quot; data-origin-width=&quot;851&quot; data-origin-height=&quot;590&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Machine Learning Model 추가&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4. 기계 학습 모델 설정&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시나리오를 선택합니다. 앞에서 얘기한 대로, 본문에서는 이미지를 구분하는 것이 목표이므로 &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;654&quot; data-origin-height=&quot;687&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dPMB2J/btsyulDjSaX/t0lDTyLszgnmrWKGiFQk40/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dPMB2J/btsyulDjSaX/t0lDTyLszgnmrWKGiFQk40/img.png&quot; data-alt=&quot;시나리오 선택&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dPMB2J/btsyulDjSaX/t0lDTyLszgnmrWKGiFQk40/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdPMB2J%2FbtsyulDjSaX%2Ft0lDTyLszgnmrWKGiFQk40%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;654&quot; height=&quot;687&quot; data-origin-width=&quot;654&quot; data-origin-height=&quot;687&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;학습 환경으로는 되도록이면 GPU를 선택합니다. CPU를 선택하면 시간이 오래 걸리기 때문에 GPU를 선택하는 것을 권장합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;841&quot; data-origin-height=&quot;392&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mMLfk/btsytugtBVI/ClRu995t9mUnaxwNLkIk30/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mMLfk/btsytugtBVI/ClRu995t9mUnaxwNLkIk30/img.png&quot; data-alt=&quot;GPU 선택 화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mMLfk/btsytugtBVI/ClRu995t9mUnaxwNLkIk30/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmMLfk%2FbtsytugtBVI%2FClRu995t9mUnaxwNLkIk30%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;841&quot; height=&quot;392&quot; data-origin-width=&quot;841&quot; data-origin-height=&quot;392&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;GPU 선택 화면&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약, GPU 호환성에 모두 초록색 표시가 아니라면 아래의 내용대로 조치해 보세요.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;4-1. GPU 확장&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;GPU 확장이 없습니다&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;263&quot; data-origin-height=&quot;181&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/p9C0P/btsys9p3F1N/Lqp7tJtef1KWK9N22lK2N0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/p9C0P/btsys9p3F1N/Lqp7tJtef1KWK9N22lK2N0/img.png&quot; data-alt=&quot;GPU 인식 오류&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/p9C0P/btsys9p3F1N/Lqp7tJtef1KWK9N22lK2N0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fp9C0P%2Fbtsys9p3F1N%2FLqp7tJtef1KWK9N22lK2N0%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;263&quot; height=&quot;181&quot; data-origin-width=&quot;263&quot; data-origin-height=&quot;181&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;GPU 인식 오류&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;① NVIDIA 그래픽 카드 드라이버 업데이트 확인.&lt;br /&gt;② Visual Studio 확장 메뉴에서 Model Builder 업데이트 확인.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;4-2. CUDA 및 cuDNN&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2023년 10월 15일 자 기준, &lt;a title=&quot;CUDA 다운로드 링크&quot; href=&quot;https://developer.nvidia.com/cuda-10.1-download-archive-update2&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;CUDA v10.1&lt;/a&gt;과 &lt;a title=&quot;cuDNN 다운로드 링크&quot; href=&quot;https://developer.nvidia.com/rdp/cudnn-download&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;cuDNN v7.6.4 for CUDA 10.1&lt;/a&gt;을 준비해야 합니다. cuDNN의 경우, 다운로드한 파일 중 &lt;i&gt;&lt;b&gt;bin\cudnn64_7.dll&lt;/b&gt;&lt;/i&gt; 파일을 &lt;i&gt;&lt;b&gt;Program Files\NVIDIA GPU Computing Toolkit\CUDA\v10.1\bin&lt;/b&gt;&lt;/i&gt;에 복사합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;5. 데이터 추가&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 학습할 데이터를 추가해야 하는데요. 저는 kaggle에서 &lt;a title=&quot;강아지와 고양이 학습 이미지&quot; href=&quot;https://www.kaggle.com/datasets/shaunthesheep/microsoft-catsvsdogs-dataset/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Cats-vs-Dogs&lt;/a&gt; 주제의 이미지를 사용했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.kaggle.com/datasets/shaunthesheep/microsoft-catsvsdogs-dataset/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://www.kaggle.com/datasets/shaunthesheep/microsoft-catsvsdogs-dataset/&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1697337594453&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;Cats-vs-Dogs&quot; data-og-description=&quot;image dataset for binary classification.&quot; data-og-host=&quot;www.kaggle.com&quot; data-og-source-url=&quot;https://www.kaggle.com/datasets/shaunthesheep/microsoft-catsvsdogs-dataset/&quot; data-og-url=&quot;https://www.kaggle.com/datasets/shaunthesheep/microsoft-catsvsdogs-dataset&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/m8o6b/hyUdRmNPBS/QM5NP7MGGi4qY6cqN1U2oK/img.jpg?width=1200&amp;amp;height=1200&amp;amp;face=54_856_132_942&quot;&gt;&lt;a href=&quot;https://www.kaggle.com/datasets/shaunthesheep/microsoft-catsvsdogs-dataset/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.kaggle.com/datasets/shaunthesheep/microsoft-catsvsdogs-dataset/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/m8o6b/hyUdRmNPBS/QM5NP7MGGi4qY6cqN1U2oK/img.jpg?width=1200&amp;amp;height=1200&amp;amp;face=54_856_132_942');&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;Cats-vs-Dogs&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;image dataset for binary classification.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.kaggle.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다운로드한 후 동물 별로 &lt;b&gt;학습용(Training)&lt;/b&gt; 이미지와 &lt;b&gt;검사용(Inference)&lt;/b&gt; 이미지를 분류했습니다. 주의 사항으로, 폴더 이름이 레이블(Label)이 되므로, 폴더 이름으로 이미지가 확실히 분류되어 있어야 합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;696&quot; data-origin-height=&quot;303&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/v8ULz/btsyyqcN00M/q04Q5PozkXQjhxIY7kL8s0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/v8ULz/btsyyqcN00M/q04Q5PozkXQjhxIY7kL8s0/img.png&quot; data-alt=&quot;폴더 구조&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/v8ULz/btsyyqcN00M/q04Q5PozkXQjhxIY7kL8s0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fv8ULz%2FbtsyyqcN00M%2Fq04Q5PozkXQjhxIY7kL8s0%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;696&quot; height=&quot;303&quot; data-origin-width=&quot;696&quot; data-origin-height=&quot;303&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;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;904&quot; data-origin-height=&quot;683&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/XgoXQ/btsyrAotm0i/J2Ux1Z8FKbkdf6ErFEaHbK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/XgoXQ/btsyrAotm0i/J2Ux1Z8FKbkdf6ErFEaHbK/img.png&quot; data-alt=&quot;데이터가 추가된 모습&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/XgoXQ/btsyrAotm0i/J2Ux1Z8FKbkdf6ErFEaHbK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FXgoXQ%2FbtsyrAotm0i%2FJ2Ux1Z8FKbkdf6ErFEaHbK%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;904&quot; height=&quot;683&quot; data-origin-width=&quot;904&quot; data-origin-height=&quot;683&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;데이터가 추가된 모습&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;6. 학습&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&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;780&quot; data-origin-height=&quot;213&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/L3JBW/btsywjSx4rK/iE0zjQwzrHU0yi6SPMiOH0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/L3JBW/btsywjSx4rK/iE0zjQwzrHU0yi6SPMiOH0/img.png&quot; data-alt=&quot;학습&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/L3JBW/btsywjSx4rK/iE0zjQwzrHU0yi6SPMiOH0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FL3JBW%2FbtsywjSx4rK%2FiE0zjQwzrHU0yi6SPMiOH0%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;780&quot; height=&quot;213&quot; data-origin-width=&quot;780&quot; data-origin-height=&quot;213&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;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;748&quot; data-origin-height=&quot;366&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/EHYs5/btsyuEQbgHx/tWDbFtwbWVVoM246ujtz1K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/EHYs5/btsyuEQbgHx/tWDbFtwbWVVoM246ujtz1K/img.png&quot; data-alt=&quot;고급 학습 옵&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/EHYs5/btsyuEQbgHx/tWDbFtwbWVVoM246ujtz1K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FEHYs5%2FbtsyuEQbgHx%2FtWDbFtwbWVVoM246ujtz1K%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;748&quot; height=&quot;366&quot; data-origin-width=&quot;748&quot; data-origin-height=&quot;366&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;고급 학습 옵&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;7. 평가&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;약 23분 만에 학습이 완료됐습니다. 그런데 정확도가 0.4732밖에 되지 않는군요.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;746&quot; data-origin-height=&quot;442&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bEsIIc/btsyqvNY0GW/17q0rcCsNktbDhINlDxG51/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bEsIIc/btsyqvNY0GW/17q0rcCsNktbDhINlDxG51/img.png&quot; data-alt=&quot;학습 결과&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bEsIIc/btsyqvNY0GW/17q0rcCsNktbDhINlDxG51/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbEsIIc%2FbtsyqvNY0GW%2F17q0rcCsNktbDhINlDxG51%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;746&quot; height=&quot;442&quot; data-origin-width=&quot;746&quot; data-origin-height=&quot;442&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;평가 메뉴에서 Inference용 이미지를 불러와 결과를 확인할 수 있습니다. 강아지 이미지를 불러오면 52% Dog 레이블이고, 고양이 이미지를 불러오면 51% Cat 레이블입니다. 학습 결과가 좋지 않습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;896&quot; data-origin-height=&quot;409&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/9NHN6/btsys7TjVbM/bPa5pvYCmyosCcrPJiXkok/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/9NHN6/btsys7TjVbM/bPa5pvYCmyosCcrPJiXkok/img.png&quot; data-alt=&quot;평가 결과&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/9NHN6/btsys7TjVbM/bPa5pvYCmyosCcrPJiXkok/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F9NHN6%2Fbtsys7TjVbM%2FbPa5pvYCmyosCcrPJiXkok%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;896&quot; height=&quot;409&quot; data-origin-width=&quot;896&quot; data-origin-height=&quot;409&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;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;8. 코드 사용&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 &lt;b&gt;사용&lt;/b&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;922&quot; data-origin-height=&quot;548&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/sAHBh/btsytZgjl9d/LCbfooZGTXpnKHtjLlzdK1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/sAHBh/btsytZgjl9d/LCbfooZGTXpnKHtjLlzdK1/img.png&quot; data-alt=&quot;코드 사용을 위한 프로젝트 추가&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/sAHBh/btsytZgjl9d/LCbfooZGTXpnKHtjLlzdK1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FsAHBh%2FbtsytZgjl9d%2FLCbfooZGTXpnKHtjLlzdK1%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;922&quot; height=&quot;548&quot; data-origin-width=&quot;922&quot; data-origin-height=&quot;548&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;예제 코드와 함께 프로젝트가 생성됩니다. 파일 경로에 Inference 이미지가 있는 경로로 변경하고 실행합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;899&quot; data-origin-height=&quot;602&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dNo1hh/btsyynNZRqd/z82mZ24SiGc0ApgRXw34aK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dNo1hh/btsyynNZRqd/z82mZ24SiGc0ApgRXw34aK/img.png&quot; data-alt=&quot;모델 사용을 위한 콘솔 프로젝트&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dNo1hh/btsyynNZRqd/z82mZ24SiGc0ApgRXw34aK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdNo1hh%2FbtsyynNZRqd%2Fz82mZ24SiGc0ApgRXw34aK%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;899&quot; height=&quot;602&quot; data-origin-width=&quot;899&quot; data-origin-height=&quot;602&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;고양이 이미지를 테스트했더니 Cat 레이블 0.52%의 결과를 얻을 수 있었습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1030&quot; data-origin-height=&quot;580&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Zmhkb/btsywilR3yn/DkynHSIVIWPVksN8TScJB1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Zmhkb/btsywilR3yn/DkynHSIVIWPVksN8TScJB1/img.png&quot; data-alt=&quot;Inference 결과&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Zmhkb/btsywilR3yn/DkynHSIVIWPVksN8TScJB1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FZmhkb%2FbtsywilR3yn%2FDkynHSIVIWPVksN8TScJB1%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;1030&quot; height=&quot;580&quot; data-origin-width=&quot;1030&quot; data-origin-height=&quot;580&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Inference 결과&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;평가 메뉴에서 테스트한 것처럼 결과가 그다지 좋진 않습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;상용 라이브러리와 비교&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다른 고급 옵션 설정을 변경하여 재시도 해봤지만 여전히 결과가 좋지 않더군요. 고급 옵션 외에 별다른 설정이 없어 성능을 더 높일 수 있는 방법을 찾지 못했습니다. 이 점이 너무 아쉽습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;추가로, ML.NET 모델의 한계인지 궁금하여 상용 라이브러리로 테스트를 진행해 보았습니다. 상용 라이브러리는 Euresys의 Open eVision 23.08을 사용했는데요. 여기서 제공하는 Deep Learning Studio는 무료로 사용이 가능하여 쉽게 검토가 가능합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;물론, 머신 비전에 적합한 모델이 적용되어 있겠지만 간단한 분류는 가능하지 않을까 시도해 봤습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;동일한 이미지로 학습을 진행했더니 약 10시간 넘게 예상 시간이 표시됐습니다. 그래서 2시간 반 정도 학습한 후 중지시키고 테스트를 해봤습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;452&quot; data-origin-height=&quot;220&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/belTiI/btsyujyOZ9D/qRsHDbdXROdoOZvrqYDgW1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/belTiI/btsyujyOZ9D/qRsHDbdXROdoOZvrqYDgW1/img.png&quot; data-alt=&quot;학습 예상 시간&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/belTiI/btsyujyOZ9D/qRsHDbdXROdoOZvrqYDgW1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbelTiI%2FbtsyujyOZ9D%2FqRsHDbdXROdoOZvrqYDgW1%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;452&quot; height=&quot;220&quot; data-origin-width=&quot;452&quot; data-origin-height=&quot;220&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;고양이 사진은 99%, 강아지 사진은 99%로 분류가 됐습니다. 상용 라이브러리로 매우 정확하게 분류할 수 있었습니다.&lt;/p&gt;
&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;1138&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bmgCWJ/btsyn0U19UA/4506NblKc4tOSLI5qbYTv1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bmgCWJ/btsyn0U19UA/4506NblKc4tOSLI5qbYTv1/img.png&quot; data-alt=&quot;상용 라이브러리 분류 결과&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bmgCWJ/btsyn0U19UA/4506NblKc4tOSLI5qbYTv1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbmgCWJ%2Fbtsyn0U19UA%2F4506NblKc4tOSLI5qbYTv1%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;1138&quot; data-origin-width=&quot;886&quot; data-origin-height=&quot;1138&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;또한, 아래처럼 Heatmap 이미지를 제공하여 모델이 어디에 집중했는지도 보여줍니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;465&quot; data-origin-height=&quot;352&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c4yRK8/btsytRvJbjS/ny8XA78gKq0KRaVPAlOhLK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c4yRK8/btsytRvJbjS/ny8XA78gKq0KRaVPAlOhLK/img.png&quot; data-alt=&quot;히트 맵 이미지&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c4yRK8/btsytRvJbjS/ny8XA78gKq0KRaVPAlOhLK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc4yRK8%2FbtsytRvJbjS%2Fny8XA78gKq0KRaVPAlOhLK%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;352&quot; data-origin-width=&quot;465&quot; data-origin-height=&quot;352&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;그리고 모델을 검증하던 중 Confusion Matrix에 제대로 예상하지 못한 결과가 있었습니다. 항목을 보니, Dog 폴더에 고양이와 글자, 일러스트와 같은 이미지들이 섞여 있더군요. Cat 폴더에도 마찬가지였습니다. 사람 사진도 섞여있는 것이, 아마도 ML.NET에서는 학습에 안 좋은 영향을 주지 않았나 싶습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;481&quot; data-origin-height=&quot;690&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dz4bAP/btsys2LB61H/hkNyifhTbUpGByTsD5bddk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dz4bAP/btsys2LB61H/hkNyifhTbUpGByTsD5bddk/img.png&quot; data-alt=&quot;Confusion Matix 결과&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dz4bAP/btsys2LB61H/hkNyifhTbUpGByTsD5bddk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdz4bAP%2Fbtsys2LB61H%2FhkNyifhTbUpGByTsD5bddk%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;350&quot; height=&quot;502&quot; data-origin-width=&quot;481&quot; data-origin-height=&quot;690&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Confusion Matix 결과&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>Programming/.Net</category>
      <author>❤ </author>
      <guid isPermaLink="true">https://luckygg.tistory.com/392</guid>
      <comments>https://luckygg.tistory.com/392#entry392comment</comments>
      <pubDate>Sun, 15 Oct 2023 16:36:34 +0900</pubDate>
    </item>
    <item>
      <title>[Flutter] 윈도우(Windows)에 플러터(Flutter) 환경 구축하는 방법</title>
      <link>https://luckygg.tistory.com/390</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. 윈도우 용 Android Studio 설치하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Android Studio를 다운로드하기 위해 아래 사이트에 접속합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://developer.android.com/studio&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://developer.android.com/studio&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1692529229697&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;Download Android Studio &amp;amp; App Tools - Android Developers&quot; data-og-description=&quot;Android Studio provides app builders with an integrated development environment (IDE) optimized for Android apps. Download Android Studio today.&quot; data-og-host=&quot;developer.android.com&quot; data-og-source-url=&quot;https://developer.android.com/studio&quot; data-og-url=&quot;https://developer.android.com/studio&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/b2ny7c/hyTFfpceRq/4PMcEJHpVe33RFv3ZYekqK/img.png?width=1201&amp;amp;height=676&amp;amp;face=0_0_1201_676,https://scrap.kakaocdn.net/dn/6QZcq/hyTIDop4K0/w9fTrqUx0bDU2f1t0d1Lf1/img.png?width=1832&amp;amp;height=1082&amp;amp;face=0_0_1832_1082,https://scrap.kakaocdn.net/dn/ziuBO/hyTFdEVhL0/Faksc03eHwdPXLnGDdCou1/img.png?width=1480&amp;amp;height=772&amp;amp;face=0_0_1480_772&quot;&gt;&lt;a href=&quot;https://developer.android.com/studio&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://developer.android.com/studio&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/b2ny7c/hyTFfpceRq/4PMcEJHpVe33RFv3ZYekqK/img.png?width=1201&amp;amp;height=676&amp;amp;face=0_0_1201_676,https://scrap.kakaocdn.net/dn/6QZcq/hyTIDop4K0/w9fTrqUx0bDU2f1t0d1Lf1/img.png?width=1832&amp;amp;height=1082&amp;amp;face=0_0_1832_1082,https://scrap.kakaocdn.net/dn/ziuBO/hyTFdEVhL0/Faksc03eHwdPXLnGDdCou1/img.png?width=1480&amp;amp;height=772&amp;amp;face=0_0_1480_772');&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;Download Android Studio &amp;amp; App Tools - Android Developers&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Android Studio provides app builders with an integrated development environment (IDE) optimized for Android apps. Download Android Studio today.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;developer.android.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 홈페이지에 접속하면 아래와 같이 Download Android Studio Giraffe 버튼이 보입니다. 클릭하면 라이선스 동의 화면이 보이고, 동의하면 다운로드가 진행됩니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;410&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rIZYA/btsrIa2jTdW/dXzrVzGz7KOklU8DPnBRr1/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rIZYA/btsrIa2jTdW/dXzrVzGz7KOklU8DPnBRr1/img.webp&quot; data-alt=&quot;Android Studio 홈페이지&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rIZYA/btsrIa2jTdW/dXzrVzGz7KOklU8DPnBRr1/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FrIZYA%2FbtsrIa2jTdW%2FdXzrVzGz7KOklU8DPnBRr1%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; alt=&quot;Android-Studio-홈페이지&quot; loading=&quot;lazy&quot; width=&quot;800&quot; height=&quot;410&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;410&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Android Studio 홈페이지&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;설치 파일을 실행하여 설치 마법사를 진행합니다. 설치 과정 중 'Android Virtual Device'는 선택하여 설치합니다. 그 외, 별다른 설정 없이 Next만 클릭하면 설치가 완료됩니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;799&quot; data-origin-height=&quot;415&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bG2HFQ/btsrypNL4XC/ytKsdcc9FUVfztoPtfMqx1/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bG2HFQ/btsrypNL4XC/ytKsdcc9FUVfztoPtfMqx1/img.webp&quot; data-alt=&quot;설치 과정&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bG2HFQ/btsrypNL4XC/ytKsdcc9FUVfztoPtfMqx1/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbG2HFQ%2FbtsrypNL4XC%2FytKsdcc9FUVfztoPtfMqx1%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; alt=&quot;설치-과정&quot; loading=&quot;lazy&quot; width=&quot;799&quot; height=&quot;415&quot; data-origin-width=&quot;799&quot; data-origin-height=&quot;415&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;설치가 완료되면, 아래와 같이 Android Studio가 실행됩니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;768&quot; data-origin-height=&quot;629&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/clQNr4/btsrNntvZpM/Iutt8eMqcdZQt6a7GkK5Dk/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/clQNr4/btsrNntvZpM/Iutt8eMqcdZQt6a7GkK5Dk/img.webp&quot; data-alt=&quot;Android Studio 실행 모습&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/clQNr4/btsrNntvZpM/Iutt8eMqcdZQt6a7GkK5Dk/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FclQNr4%2FbtsrNntvZpM%2FIutt8eMqcdZQt6a7GkK5Dk%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; alt=&quot;Android-Studio-실행-모습&quot; loading=&quot;lazy&quot; width=&quot;768&quot; height=&quot;629&quot; data-origin-width=&quot;768&quot; data-origin-height=&quot;629&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Android Studio 실행 모습&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2. Flutter SDK 설치하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 Android Studio에서 사용할 Flutter SDK를 설치해야 합니다. Flutter 공식 홈페이지에 접속합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://docs.flutter.dev/release/archive?tab=windows&quot;&gt;https://docs.flutter.dev/release/archive?tab=windows&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1692529909084&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;Flutter SDK archive&quot; data-og-description=&quot;All current Flutter SDK releases: stable, beta, and master.&quot; data-og-host=&quot;docs.flutter.dev&quot; data-og-source-url=&quot;https://docs.flutter.dev/release/archive?tab=windows&quot; data-og-url=&quot;https://docs.flutter.dev/release/archive&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/be5ARP/hyTIFs1s3s/n9zBZ0Rk9KltKiKc32atxk/img.png?width=937&amp;amp;height=461&amp;amp;face=0_0_937_461&quot;&gt;&lt;a href=&quot;https://docs.flutter.dev/release/archive?tab=windows&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://docs.flutter.dev/release/archive?tab=windows&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/be5ARP/hyTIFs1s3s/n9zBZ0Rk9KltKiKc32atxk/img.png?width=937&amp;amp;height=461&amp;amp;face=0_0_937_461');&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;Flutter SDK archive&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;All current Flutter SDK releases: stable, beta, and master.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;docs.flutter.dev&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Stable channel (Windows) 중 최신 버전 또는 원하는 버전의 파일을 다운로드합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;660&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dlNOiT/btsrNy9DPlZ/FyiRUnKRi2gC4YkEjKzBW0/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dlNOiT/btsrNy9DPlZ/FyiRUnKRi2gC4YkEjKzBW0/img.webp&quot; data-alt=&quot;Flutter SDK 다운로드 화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dlNOiT/btsrNy9DPlZ/FyiRUnKRi2gC4YkEjKzBW0/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdlNOiT%2FbtsrNy9DPlZ%2FFyiRUnKRi2gC4YkEjKzBW0%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; alt=&quot;Flutter-SDK-다운로드-화면&quot; loading=&quot;lazy&quot; width=&quot;800&quot; height=&quot;660&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;660&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Flutter SDK 다운로드 화면&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다운로드한 파일은 설치 파일이 아닌 압축 파일(*.zip)입니다. 압축을 풀고, &lt;i&gt;&lt;b&gt;C:\flutter&lt;/b&gt;&lt;/i&gt; 또는 &lt;i&gt;&lt;b&gt;D:\flutter&lt;/b&gt;&lt;/i&gt;과 같이 원하는 경로에 옮겨 놓습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;624&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b0JbFY/btsrCuOg8Ow/DjxOYU1Bn4vheh0KhuTeek/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b0JbFY/btsrCuOg8Ow/DjxOYU1Bn4vheh0KhuTeek/img.webp&quot; data-alt=&quot;flutter 압축을 푼 모습&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b0JbFY/btsrCuOg8Ow/DjxOYU1Bn4vheh0KhuTeek/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb0JbFY%2FbtsrCuOg8Ow%2FDjxOYU1Bn4vheh0KhuTeek%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; alt=&quot;flutter-압축을-푼-모습&quot; loading=&quot;lazy&quot; width=&quot;800&quot; height=&quot;624&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;624&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;flutter 압축을 푼 모습&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 윈도우 환경 변수에 &lt;i&gt;&lt;b&gt;flutter\bin&lt;/b&gt;&lt;/i&gt; 폴더 경로를 추가합니다. 저는 &lt;i&gt;&lt;b&gt;C:\flutter\bin&lt;/b&gt;&lt;/i&gt; 경로를 추가했습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;279&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bLkCvT/btsrCxRLKIX/SPKTrexIkdTmd7gPHxcxCk/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bLkCvT/btsrCxRLKIX/SPKTrexIkdTmd7gPHxcxCk/img.webp&quot; data-alt=&quot;환경 변수 추가하기&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bLkCvT/btsrCxRLKIX/SPKTrexIkdTmd7gPHxcxCk/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbLkCvT%2FbtsrCxRLKIX%2FSPKTrexIkdTmd7gPHxcxCk%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; alt=&quot;환경-변수-추가하기&quot; loading=&quot;lazy&quot; width=&quot;800&quot; height=&quot;279&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;279&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;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;436&quot; data-origin-height=&quot;377&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/blIyiK/btsrDDjFksG/zzTYKDkeTNV4IkWBNJlPa0/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/blIyiK/btsrDDjFksG/zzTYKDkeTNV4IkWBNJlPa0/img.webp&quot; data-alt=&quot;명령 프롬프트 실행하기&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/blIyiK/btsrDDjFksG/zzTYKDkeTNV4IkWBNJlPa0/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FblIyiK%2FbtsrDDjFksG%2FzzTYKDkeTNV4IkWBNJlPa0%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; alt=&quot;명령-프롬프트-실행하기&quot; loading=&quot;lazy&quot; width=&quot;436&quot; height=&quot;377&quot; data-origin-width=&quot;436&quot; data-origin-height=&quot;377&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;/p&gt;
&lt;pre id=&quot;code_1692531044436&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;flutter doctor&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;명령어를 입력하면 아래와 같이 &lt;b&gt;&lt;span style=&quot;color: #f3c000;&quot;&gt;!&lt;/span&gt;&lt;/b&gt;, &lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;X&lt;/span&gt;&lt;/b&gt;, &lt;b&gt;&lt;span style=&quot;color: #009a87;&quot;&gt;V&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;799&quot; data-origin-height=&quot;421&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/depxTW/btsryr5Tcwo/qbO9rYeAdykWLWSvln2s0K/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/depxTW/btsryr5Tcwo/qbO9rYeAdykWLWSvln2s0K/img.webp&quot; data-alt=&quot;flutter doctor로 점검한 모습&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/depxTW/btsryr5Tcwo/qbO9rYeAdykWLWSvln2s0K/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdepxTW%2Fbtsryr5Tcwo%2FqbO9rYeAdykWLWSvln2s0K%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; alt=&quot;flutter-doctor로-점검한-모습&quot; loading=&quot;lazy&quot; width=&quot;799&quot; height=&quot;421&quot; data-origin-width=&quot;799&quot; data-origin-height=&quot;421&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;flutter doctor로 점검한 모습&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #f3c000;&quot;&gt;! &lt;/span&gt;&lt;/b&gt;Some Android licenses not accepted&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 메시지는 말 그대로, 라이선스 일부가 동의되지 않았다는 의미입니다. 명령 프롬프트에서 아래의 명령어를 입력합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1692531277683&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;flutter doctor --android-licenses&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약, 명령어 입력 시 에러가 발생하면 아래와 같이 &lt;i&gt;Android SDK Command-line Tools&lt;/i&gt;를 설치합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;580&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cCoJcz/btsrB5usnD8/kwJTFWtpqbEpWXrYNWKiFK/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cCoJcz/btsrB5usnD8/kwJTFWtpqbEpWXrYNWKiFK/img.webp&quot; data-alt=&quot;Command-line Tools 설치하기&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cCoJcz/btsrB5usnD8/kwJTFWtpqbEpWXrYNWKiFK/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcCoJcz%2FbtsrB5usnD8%2FkwJTFWtpqbEpWXrYNWKiFK%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; alt=&quot;Command-line-Tools-설치하기&quot; loading=&quot;lazy&quot; width=&quot;800&quot; height=&quot;580&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;580&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Command-line Tools 설치하기&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다시 명령 프롬프트에서 명령어를 입력하고, 화면에 동의 하겠느냐는 메시지가 표시될 때마다 '&lt;i&gt;&lt;b&gt;y&lt;/b&gt;&lt;/i&gt;' 키를 입력하면 간단하게 해결됩니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;X &lt;/span&gt;&lt;/b&gt;Flutter/Dart plugin not installed&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 에러 메시지는 Android Studio에 Flutter plugin이 설치되지 않았다는 의미입니다. 아래와 같이 Android Studio의 Plugins 메뉴에서 Dart와 Flutter 항목을 선택하여 설치하면 해결됩니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;654&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cGqEHv/btsrBpfEwUV/blBofRHKBLmETwjIumCdRK/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cGqEHv/btsrBpfEwUV/blBofRHKBLmETwjIumCdRK/img.webp&quot; data-alt=&quot;Dart와 Flutter를 설치한 모습&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cGqEHv/btsrBpfEwUV/blBofRHKBLmETwjIumCdRK/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcGqEHv%2FbtsrBpfEwUV%2FblBofRHKBLmETwjIumCdRK%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; alt=&quot;Dart와-Flutter를-설치한-모습&quot; loading=&quot;lazy&quot; width=&quot;800&quot; height=&quot;654&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;654&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Dart와 Flutter를 설치한 모습&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;span&gt;&lt;b&gt;&lt;span style=&quot;color: #f3c000;&quot;&gt;!&lt;/span&gt;&lt;/b&gt; &lt;/span&gt;&lt;/span&gt;&lt;/b&gt;No devices available&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용 가능한 디바이스가 없다는 메시지입니다. 앱 개발 시 물리적으로 연결된 스마트폰 또는 가상 장치에서 실행하여 확인할 수 있는데요. 처음 Android Studio를 설치하면 장치가 없기 때문에 메시지가 발생한 것입니다.&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://luckygg.tistory.com/391&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;[Flutter] 가상 디바이스(Virtual device) 추가하는 방법&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1692534187515&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;[Flutter] 가상 디바이스(Virtual device) 추가하는 방법&quot; data-og-description=&quot;Android Virtual Device(AVD) 관리하기 Android Studio에서는 물리적으로 연결된 스마트 폰에서 앱을 개발할 수도 있지만, 편리하게 가상 디바이스를 추가하여 실행하고 디버깅이 가능합니다. 가상 디바이&quot; data-og-host=&quot;luckygg.tistory.com&quot; data-og-source-url=&quot;https://luckygg.tistory.com/391&quot; data-og-url=&quot;https://luckygg.tistory.com/391&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/hYvfa/hyTIL05utD/AigNKjWKt1tKirZMbBj8Vk/img.jpg?width=652&amp;amp;height=272&amp;amp;face=0_0_652_272,https://scrap.kakaocdn.net/dn/zSCIY/hyTFmomDF8/11UCBkUi7hRKPNPKLH7KM1/img.jpg?width=652&amp;amp;height=272&amp;amp;face=0_0_652_272&quot;&gt;&lt;a href=&quot;https://luckygg.tistory.com/391&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://luckygg.tistory.com/391&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/hYvfa/hyTIL05utD/AigNKjWKt1tKirZMbBj8Vk/img.jpg?width=652&amp;amp;height=272&amp;amp;face=0_0_652_272,https://scrap.kakaocdn.net/dn/zSCIY/hyTFmomDF8/11UCBkUi7hRKPNPKLH7KM1/img.jpg?width=652&amp;amp;height=272&amp;amp;face=0_0_652_272');&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;[Flutter] 가상 디바이스(Virtual device) 추가하는 방법&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Android Virtual Device(AVD) 관리하기 Android Studio에서는 물리적으로 연결된 스마트 폰에서 앱을 개발할 수도 있지만, 편리하게 가상 디바이스를 추가하여 실행하고 디버깅이 가능합니다. 가상 디바이&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;luckygg.tistory.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;pre id=&quot;code_1692532199455&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;flutter doctor&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래와 같이 &lt;b&gt;&lt;span style=&quot;color: #009a87;&quot;&gt;V &lt;/span&gt;&lt;/b&gt;표시되고, No issues found 메시지가 보인다면 flutter를 사용하기 위한 준비가 끝난 겁니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;418&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/QjNcJ/btsrNzHttBv/ltc8sqUNzKqS2WvL7Msk1k/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/QjNcJ/btsrNzHttBv/ltc8sqUNzKqS2WvL7Msk1k/img.webp&quot; data-alt=&quot;모든 준비가 완료된 모습&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/QjNcJ/btsrNzHttBv/ltc8sqUNzKqS2WvL7Msk1k/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FQjNcJ%2FbtsrNzHttBv%2Fltc8sqUNzKqS2WvL7Msk1k%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; alt=&quot;모든-준비가-완료된-모습&quot; loading=&quot;lazy&quot; width=&quot;800&quot; height=&quot;418&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;418&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;모든 준비가 완료된 모습&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3. Flutter Project 생성하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Welcome 화면에서 &lt;i&gt;&lt;b&gt;New Flutter Project&lt;/b&gt;&lt;/i&gt;를 클릭합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;694&quot; data-origin-height=&quot;568&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Fuynn/btsrH8i648z/IT0U8IWqKQwirqNIq17Ksk/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Fuynn/btsrH8i648z/IT0U8IWqKQwirqNIq17Ksk/img.webp&quot; data-alt=&quot;Flutter Project 생성하기&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Fuynn/btsrH8i648z/IT0U8IWqKQwirqNIq17Ksk/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FFuynn%2FbtsrH8i648z%2FIT0U8IWqKQwirqNIq17Ksk%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; alt=&quot;Flutter-Project-생성하기&quot; loading=&quot;lazy&quot; width=&quot;694&quot; height=&quot;568&quot; data-origin-width=&quot;694&quot; data-origin-height=&quot;568&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Flutter Project 생성하기&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 아래 화면과 같이 &lt;i&gt;&lt;b&gt;Flutter SDK path&lt;/b&gt;&lt;/i&gt;란에 처음 옮겨놨던 flutter 경로로 설정합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;732&quot; data-origin-height=&quot;568&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ekfkch/btsrDfi1391/0sY3KKpAIJbVNxbRkQUg91/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ekfkch/btsrDfi1391/0sY3KKpAIJbVNxbRkQUg91/img.webp&quot; data-alt=&quot;flutter 경로 설정하기&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ekfkch/btsrDfi1391/0sY3KKpAIJbVNxbRkQUg91/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fekfkch%2FbtsrDfi1391%2F0sY3KKpAIJbVNxbRkQUg91%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; alt=&quot;flutter-경로-설정하기&quot; loading=&quot;lazy&quot; width=&quot;732&quot; height=&quot;568&quot; data-origin-width=&quot;732&quot; data-origin-height=&quot;568&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;flutter 경로 설정하기&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제가 없다면 아래 화면과 같이 Flutter 프로젝트가 생성됩니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;799&quot; data-origin-height=&quot;566&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bFPcHB/btsrNztWFuJ/ZtMsietDRUd1gGIz56tvi1/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bFPcHB/btsrNztWFuJ/ZtMsietDRUd1gGIz56tvi1/img.webp&quot; data-alt=&quot;Flutter 프로젝트가 생성된 모습&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bFPcHB/btsrNztWFuJ/ZtMsietDRUd1gGIz56tvi1/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbFPcHB%2FbtsrNztWFuJ%2FZtMsietDRUd1gGIz56tvi1%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; alt=&quot;Flutter-프로젝트가-생성된-모습&quot; loading=&quot;lazy&quot; width=&quot;799&quot; height=&quot;566&quot; data-origin-width=&quot;799&quot; data-origin-height=&quot;566&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Flutter 프로젝트가 생성된 모습&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>Programming/Flutter</category>
      <category>flutter</category>
      <author>❤ </author>
      <guid isPermaLink="true">https://luckygg.tistory.com/390</guid>
      <comments>https://luckygg.tistory.com/390#entry390comment</comments>
      <pubDate>Wed, 23 Aug 2023 10:23:17 +0900</pubDate>
    </item>
    <item>
      <title>[Flutter] 가상 디바이스(Virtual device) 추가하는 방법</title>
      <link>https://luckygg.tistory.com/391</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;Android Virtual Device(AVD) 관리하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Android Studio에서는 물리적으로 연결된 스마트 폰에서 앱을 개발할 수도 있지만, 편리하게 가상 디바이스를 추가하여 실행하고 디버깅이 가능합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가상 디바이스를 추가하는 방법은 아주 간단한데요. 한번 따라 해 보겠습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. Virtual Device Manager 메뉴 클릭하기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음 Welcome 화면에서 &lt;i&gt;&lt;b&gt;More Actions&lt;/b&gt;&lt;/i&gt;를 클릭하면 &lt;i&gt;&lt;b&gt;Virtual Device Manager&lt;/b&gt;&lt;/i&gt; 메뉴가 보입니다. 이 메뉴를 클릭합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;723&quot; data-origin-height=&quot;593&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/d8sgie/btsrxPlDC4e/9siSBkNBp0CjQyK9aGGvFK/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/d8sgie/btsrxPlDC4e/9siSBkNBp0CjQyK9aGGvFK/img.webp&quot; data-alt=&quot;Virtual Device Manager 클릭하기&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/d8sgie/btsrxPlDC4e/9siSBkNBp0CjQyK9aGGvFK/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fd8sgie%2FbtsrxPlDC4e%2F9siSBkNBp0CjQyK9aGGvFK%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; alt=&quot;Virtual-Device-Manager-클릭하기&quot; loading=&quot;lazy&quot; width=&quot;723&quot; height=&quot;593&quot; data-origin-width=&quot;723&quot; data-origin-height=&quot;593&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Virtual Device Manager 클릭하기&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약, 이미 생성한 프로젝트가 있어서 Welcome 화면이 보이지 않는다면, 아래와 같이 상단 메뉴의 아이콘을 클릭해도 동일한 화면을 볼 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;652&quot; data-origin-height=&quot;272&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ssEFw/btsrNxXcymW/Aa7rWBRQAdw06OXSi9Iqi1/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ssEFw/btsrNxXcymW/Aa7rWBRQAdw06OXSi9Iqi1/img.webp&quot; data-alt=&quot;프로젝트 생성 후 Virtual Device Manager 클릭하기&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ssEFw/btsrNxXcymW/Aa7rWBRQAdw06OXSi9Iqi1/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FssEFw%2FbtsrNxXcymW%2FAa7rWBRQAdw06OXSi9Iqi1%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; alt=&quot;프로젝트-생성-후-Virtual-Device-Manager-클릭하기&quot; loading=&quot;lazy&quot; width=&quot;652&quot; height=&quot;272&quot; data-origin-width=&quot;652&quot; data-origin-height=&quot;272&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;프로젝트 생성 후 Virtual Device Manager 클릭하기&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. Virtual Device 생성하기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래 화면과 같이 표시되어 있는 &lt;i&gt;&lt;b&gt;Create virtual device&lt;/b&gt;&lt;/i&gt; 또는 &lt;i&gt;&lt;b&gt;Create Device&lt;/b&gt;&lt;/i&gt; 버튼을 클릭합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;725&quot; data-origin-height=&quot;594&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/duFSGv/btsrBN8H7yZ/ztSVBm3k3t9RNqed6I2Dq1/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/duFSGv/btsrBN8H7yZ/ztSVBm3k3t9RNqed6I2Dq1/img.webp&quot; data-alt=&quot;Virtual Device 생성 버튼 클릭하&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/duFSGv/btsrBN8H7yZ/ztSVBm3k3t9RNqed6I2Dq1/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FduFSGv%2FbtsrBN8H7yZ%2FztSVBm3k3t9RNqed6I2Dq1%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; alt=&quot;Virtual-Device-생성-버튼-클릭하&quot; loading=&quot;lazy&quot; width=&quot;725&quot; height=&quot;594&quot; data-origin-width=&quot;725&quot; data-origin-height=&quot;594&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Virtual Device 생성 버튼 클릭하&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Category에서 고르거나 검색 란에 입력하여 원하는 기종을 선택할 수 있습니다. 저는 &lt;i&gt;&lt;b&gt;Galaxy Nexus&lt;/b&gt;&lt;/i&gt;를 선택했습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;520&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dqWrOT/btsrBQRSJFT/MpDSi2eQpFCvAsHOI6F8K0/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dqWrOT/btsrBQRSJFT/MpDSi2eQpFCvAsHOI6F8K0/img.webp&quot; data-alt=&quot;기종 선택하기&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dqWrOT/btsrBQRSJFT/MpDSi2eQpFCvAsHOI6F8K0/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdqWrOT%2FbtsrBQRSJFT%2FMpDSi2eQpFCvAsHOI6F8K0%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; alt=&quot;기종-선택하기&quot; loading=&quot;lazy&quot; width=&quot;800&quot; height=&quot;520&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;520&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;이번에는 Android Version을 선택하는 화면입니다. 원하는 버전을 선택합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;799&quot; data-origin-height=&quot;519&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/od1cu/btsrIeRdWGF/d65xMtUiwC6KGMgXseZHb0/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/od1cu/btsrIeRdWGF/d65xMtUiwC6KGMgXseZHb0/img.webp&quot; data-alt=&quot;Android Version 선택하기&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/od1cu/btsrIeRdWGF/d65xMtUiwC6KGMgXseZHb0/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fod1cu%2FbtsrIeRdWGF%2Fd65xMtUiwC6KGMgXseZHb0%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; alt=&quot;Android-Version-선택하기&quot; loading=&quot;lazy&quot; width=&quot;799&quot; height=&quot;519&quot; data-origin-width=&quot;799&quot; data-origin-height=&quot;519&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Android Version 선택하기&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Graphics 옵션에는 &lt;i&gt;&lt;b&gt;Hardware - GLES 2.0&lt;/b&gt;&lt;/i&gt;을 선택합니다. 가상 디바이스가 컴퓨터의 그래픽 카드를 사용하여 렌더링 속도를 향상하는 옵션입니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;799&quot; data-origin-height=&quot;519&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bDFyOH/btsrxOG25R3/OOrdQUwgnnvDJA7Kpg9yTk/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bDFyOH/btsrxOG25R3/OOrdQUwgnnvDJA7Kpg9yTk/img.webp&quot; data-alt=&quot;Graphics 옵션 선택하기&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bDFyOH/btsrxOG25R3/OOrdQUwgnnvDJA7Kpg9yTk/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbDFyOH%2FbtsrxOG25R3%2FOOrdQUwgnnvDJA7Kpg9yTk%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; alt=&quot;Graphics-옵션-선택하기&quot; loading=&quot;lazy&quot; width=&quot;799&quot; height=&quot;519&quot; data-origin-width=&quot;799&quot; data-origin-height=&quot;519&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Graphics 옵션 선택하기&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Finish 버튼을 클릭하면 가상 디바이스 생성이 완료됩니다. 아주 간단하죠?&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. Virtual Device 실행하기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래 표시한 Actions 부분의 실행 아이콘을 클릭합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;686&quot; data-origin-height=&quot;561&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bkiSqI/btsrEqj4AFm/rsY7FiDak61qN2kYU6DTBk/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bkiSqI/btsrEqj4AFm/rsY7FiDak61qN2kYU6DTBk/img.webp&quot; data-alt=&quot;실행 아이콘 클릭하기&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bkiSqI/btsrEqj4AFm/rsY7FiDak61qN2kYU6DTBk/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbkiSqI%2FbtsrEqj4AFm%2FrsY7FiDak61qN2kYU6DTBk%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; alt=&quot;실행-아이콘-클릭하기&quot; loading=&quot;lazy&quot; width=&quot;686&quot; height=&quot;561&quot; data-origin-width=&quot;686&quot; data-origin-height=&quot;561&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;Android Emulator 창이 표시되고, 스마트 폰과 같이 익숙한 UI가 보입니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;357&quot; data-origin-height=&quot;658&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qidwY/btsrDB7d43Z/f99PHWPcRExQkqpd7A8Fu0/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qidwY/btsrDB7d43Z/f99PHWPcRExQkqpd7A8Fu0/img.webp&quot; data-alt=&quot;Virtual Device가 실행된 모습&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qidwY/btsrDB7d43Z/f99PHWPcRExQkqpd7A8Fu0/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqidwY%2FbtsrDB7d43Z%2Ff99PHWPcRExQkqpd7A8Fu0%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; alt=&quot;Virtual-Device가-실행된-모습&quot; loading=&quot;lazy&quot; width=&quot;357&quot; height=&quot;658&quot; data-origin-width=&quot;357&quot; data-origin-height=&quot;658&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Virtual Device가 실행된 모습&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Virtual Device 추가하기가 모두 완료됐습니다. 정말 간단하죠?&lt;/p&gt;</description>
      <category>Programming/Flutter</category>
      <category>flutter</category>
      <author>❤ </author>
      <guid isPermaLink="true">https://luckygg.tistory.com/391</guid>
      <comments>https://luckygg.tistory.com/391#entry391comment</comments>
      <pubDate>Sun, 20 Aug 2023 21:23:12 +0900</pubDate>
    </item>
    <item>
      <title>[DirectX] .Net WinForm에서 GDI+와 SharpDX 사용하기 (예제 포함)</title>
      <link>https://luckygg.tistory.com/389</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;SharpDX vs GDI+&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지난 포스팅에서 DirectX와 GDI+의 기본적인 차이점과 SharpDX가 무엇인지 알아보았습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a style=&quot;background-color: #e6f5ff; color: #0070d1; text-align: start;&quot; href=&quot;https://luckygg.tistory.com/388&quot;&gt;[.Net] DirectX와 GDI+의 차이점, 그리고 SharpDX 이해하기&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1686030529892&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;[DirectX] DirectX와 GDI+의 차이점, 그리고 SharpDX 이해하기&quot; data-og-description=&quot;DirectX와 GDI의 차이점 SharpDX를 설명하기 전에, DirectX가 무엇인지 그리고 GDI와 무슨 차이가 있는지부터 알아보겠습니다. 우리가 흔히 알고 있는 GDI(Graphics Device Interface)는 윈도우 운영 체제의 그래&quot; data-og-host=&quot;luckygg.tistory.com&quot; data-og-source-url=&quot;https://luckygg.tistory.com/388&quot; data-og-url=&quot;https://luckygg.tistory.com/388&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bI4obz/hySTUd8qbl/Vq3hfWQCIvGSwy0PQbaevK/img.jpg?width=395&amp;amp;height=371&amp;amp;face=0_0_395_371,https://scrap.kakaocdn.net/dn/ekR0Wf/hySTLBuCDT/H6P0bG9lliPnXMuNw5KuEK/img.jpg?width=395&amp;amp;height=371&amp;amp;face=0_0_395_371&quot;&gt;&lt;a href=&quot;https://luckygg.tistory.com/388&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://luckygg.tistory.com/388&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bI4obz/hySTUd8qbl/Vq3hfWQCIvGSwy0PQbaevK/img.jpg?width=395&amp;amp;height=371&amp;amp;face=0_0_395_371,https://scrap.kakaocdn.net/dn/ekR0Wf/hySTLBuCDT/H6P0bG9lliPnXMuNw5KuEK/img.jpg?width=395&amp;amp;height=371&amp;amp;face=0_0_395_371');&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;[DirectX] DirectX와 GDI+의 차이점, 그리고 SharpDX 이해하기&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;DirectX와 GDI의 차이점 SharpDX를 설명하기 전에, DirectX가 무엇인지 그리고 GDI와 무슨 차이가 있는지부터 알아보겠습니다. 우리가 흔히 알고 있는 GDI(Graphics Device Interface)는 윈도우 운영 체제의 그래&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;luckygg.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;간단하게 요약하자면, 2D 이미지 렌더링 기준으로 &lt;b&gt;하드웨어 가속을 지원하냐의 차이점&lt;/b&gt;이 있다고 보면 되겠습니다. 이번 포스팅에서는 WinForm 프로젝트에서 &lt;u&gt;SharpDX를 어떻게 사용하는지&lt;/u&gt;, 그리고 GDI+ 대비하여 &lt;u&gt;어떤 차이가 있는지&lt;/u&gt; 알아보도록 하겠습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;따라 하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예제 코드는 &lt;b&gt;Visual Studio 2022&lt;/b&gt; 환경으로 제작했습니다. WinForm에 Picture Box를 추가했고, 선택한 방식(GDI+ 또는 DirectX)에 따라 Picture Box에 이미지를 &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;어떻게&lt;span&gt; &lt;/span&gt;&lt;/span&gt;렌더링 하는지 보여줍니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;WinForm 프로젝트 생성하기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;ExamDirectX&lt;/span&gt;&lt;/code&gt; 이름으로 &lt;b&gt;Windows Forms 앱(.NET Framework)&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;800&quot; data-origin-height=&quot;532&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c5Xyop/btsjjDl3vZj/fmhgVGEBa10PTEfiagfrm0/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c5Xyop/btsjjDl3vZj/fmhgVGEBa10PTEfiagfrm0/img.webp&quot; data-alt=&quot;WinForm 프로젝트 생성하기&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c5Xyop/btsjjDl3vZj/fmhgVGEBa10PTEfiagfrm0/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc5Xyop%2FbtsjjDl3vZj%2FfmhgVGEBa10PTEfiagfrm0%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; alt=&quot;WinForm-프로젝트-생성하기&quot; loading=&quot;lazy&quot; width=&quot;800&quot; height=&quot;532&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;532&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;WinForm 프로젝트 생성하기&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;UI Control 배치하기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래 그림처럼, UI는 Picture Box와 버튼, 라디오 버튼으로 구성했습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;465&quot; data-origin-height=&quot;573&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/tzzJk/btsjlWkw0d7/ME7qQJCs7XOMwgymxRN7yK/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/tzzJk/btsjlWkw0d7/ME7qQJCs7XOMwgymxRN7yK/img.webp&quot; data-alt=&quot;UI 배치&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/tzzJk/btsjlWkw0d7/ME7qQJCs7XOMwgymxRN7yK/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FtzzJk%2FbtsjlWkw0d7%2FME7qQJCs7XOMwgymxRN7yK%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; alt=&quot;UI-배치&quot; loading=&quot;lazy&quot; width=&quot;465&quot; height=&quot;573&quot; data-origin-width=&quot;465&quot; data-origin-height=&quot;573&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;UI 배치&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;SharpDX NuGet 패키지 설치하기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;NuGet 패키지 관리&lt;/b&gt;에서 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;SharpDX&lt;/span&gt;&lt;/code&gt;를 검색하고 아래의 패키지들을 설치합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;619&quot; data-origin-height=&quot;402&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bOzFsc/btsjnabD0ic/aYlptx3OLDzHKVfOjZ7G91/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bOzFsc/btsjnabD0ic/aYlptx3OLDzHKVfOjZ7G91/img.webp&quot; data-alt=&quot;NuGet 패키지 설치하기&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bOzFsc/btsjnabD0ic/aYlptx3OLDzHKVfOjZ7G91/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbOzFsc%2FbtsjnabD0ic%2FaYlptx3OLDzHKVfOjZ7G91%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; alt=&quot;NuGet-패키지-설치하기&quot; loading=&quot;lazy&quot; width=&quot;619&quot; height=&quot;402&quot; data-origin-width=&quot;619&quot; data-origin-height=&quot;402&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;NuGet 패키지 설치하기&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;SharpDX 구현하기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;본문 하단에 첨부된 예제 코드에는 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;MyDirectX.cs&lt;/span&gt;&lt;/code&gt; 파일이 있습니다. 이 파일에 SharpDX 라이브러리를 어떻게 초기화하고, 파일을 불러오고, 대상 컨트롤에 렌더링 하는지 코드가 구현되어 있습니다. 코드에도 주석으로 설명을 남겨 놓았지만 본문에서도 설명하겠습니다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;각 객체 별 용도&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Picture Box는 GDI+ 기반의 컨트롤입니다. DirectX 객체로 해당 컨트롤에 렌더링 하기 위해 아래의 기본 객체들이 사용됩니다.&lt;/p&gt;
&lt;pre id=&quot;code_1686032225734&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//DirectX 2D 그래픽 렌더링에 필요한 리소스를 제공
SharpDX.Direct2D1.Factory2 _factory2D = null;

//GPU 하드웨어에 접근하는 인터페이스를 제공
SharpDX.Direct3D11.Device _device = null;

//백 버퍼와 프론트 버퍼를 스왑(ex: 더블 버퍼링)해주는 기능
SharpDX.DXGI.SwapChain _swapChain = null;

//렌더링이 수행되는 타겟
SharpDX.Direct2D1.RenderTarget _renderTarget2D = null;

//DirectX 2D 비트맵
SharpDX.Direct2D1.Bitmap _bitmap = null;&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;PictureBox 컨트롤과 연동하여 초기화하기&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일반적으로 화면에 이미지를 부드럽게 렌더링 하기 위해 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;더블 버퍼링&lt;/span&gt;&lt;/code&gt;을 사용합니다. &lt;b&gt;화면에 보이는 버퍼(프런트 버퍼)&lt;/b&gt;와 &lt;b&gt;보여주기 위해 처리하는 버퍼(백 버퍼)&lt;/b&gt; 두 개를 의미합니다. &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;스왑 체인(Swap Chain)&lt;/span&gt;&lt;/code&gt;은 이 백 버퍼와 프론트 버퍼를 스왑 하여 사용자에게 부드러운 화면을 보여주도록 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래의 코드를 수행하면 _renderTarget2D는 PictureBox와 연동됩니다.&lt;/p&gt;
&lt;pre id=&quot;code_1686032670302&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public void InitializeControl(PictureBox control)
{
    //스왑 체인에 대한 설정
    var desc = new SwapChainDescription()
    {
        BufferCount = 1, //스왑 체인에 사용될 버퍼의 수
        ModeDescription = new ModeDescription(control.Width, control.Height, new Rational(60, 1), Format.R8G8B8A8_UNorm),
        //Rational: 화면 갱신 속도 1/60
        IsWindowed = true, //스왑 체인이 창 모드에서 동작하도록 설정
        OutputHandle = control.Handle, //출력이 이루어질 창의 핸들
        SampleDescription = new SampleDescription(1, 0), //멀티샘플링의 수준
        SwapEffect = SwapEffect.Discard, //스왑 체인의 스왑 효과. Discard: 스왑 이후 백 버퍼 삭제
        Usage = Usage.RenderTargetOutput //GPU가 이 자원에 그래픽 데이터를 직접 쓸 수 있음을 의미
    };

    _targetWindowSize.Left = 0;
    _targetWindowSize.Top = 0;
    _targetWindowSize.Right = control.Width;
    _targetWindowSize.Bottom = control.Height;

    SharpDX.Direct3D11.Device.CreateWithSwapChain(DriverType.Hardware, DeviceCreationFlags.BgraSupport, desc, out _device, out _swapChain);

    //DirectX 2D 그래픽 렌더링에 필요한 리소스를 만들기 위한 기능을 제공
    _factory2D = new SharpDX.Direct2D1.Factory2();

    //Surface는 그래픽 데이터를 저장하고 그리기 작업을 수행하는 데 사용되는 클래스
    var backBuffer = Surface.FromSwapChain(_swapChain, 0);
    var properties = new RenderTargetProperties(new SharpDX.Direct2D1.PixelFormat(Format.Unknown, SharpDX.Direct2D1.AlphaMode.Premultiplied));

    _renderTarget2D = new RenderTarget(_factory2D, backBuffer, properties);
}&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;파일로부터 SharpDX 비트맵 생성하기&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;WIC(windows Imaging Component)&lt;/span&gt;&lt;/code&gt;를 사용하여 이미지 파일을 불러온 후 렌더링 타깃에 사용할 수 있는 Direct2D 비트맵으로 생성합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1686055075453&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public void LoadBitmap(string filename)
{
    //Bitmap 디코더/인코더, 포맷 변경, 스케일러 등 지원
    var wicFactory = new SharpDX.WIC.ImagingFactory2();

    //파일로부터 이미지 불러오기
    var wicDecoder = new SharpDX.WIC.BitmapDecoder(wicFactory, filename, SharpDX.WIC.DecodeOptions.CacheOnDemand);

    //파일로부터 불러온 디코더의 첫 프레임 가져오기
    //이미지 파일은 하나의 프레임이지만, GIF의 경우 여러 프레임
    var wicFrame = wicDecoder.GetFrame(0);

    //포맷 컨버터 생성 및 초기화
    var converter = new SharpDX.WIC.FormatConverter(wicFactory);
    converter.Initialize(wicFrame, SharpDX.WIC.PixelFormat.Format32bppPRGBA);

    //변환된 이미지 데이터를 Direct2D 비트맵으로 변환
    _bitmap = SharpDX.Direct2D1.Bitmap.FromWicBitmap(_renderTarget2D, converter);

    //객체 소멸
    converter.Dispose();
    wicFrame.Dispose();
    wicDecoder.Dispose();
    wicFactory.Dispose();
}&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;화면에 그리기&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;화면에 그리기 위해 아래의 코드가 수행됩니다. 특히 마지막 라인의 코드가 중요한데요. &lt;code&gt;&lt;span class=&quot;token function-name&quot;&gt;Present&lt;/span&gt;&lt;/code&gt; 함수를 호출해야 화면에 보입니다. 첫 번째 인자는 &lt;b&gt;모니터의 리프레시 속도(VSync)와 동기화하는 인자&lt;/b&gt;입니다. 0은 즉시 화면에 표시하고, 1은 모니터의 갱신 속도와 동기를 맞춥니다. 두 번째 인자는 &lt;b&gt;VSync와 관련하여 동작을 설정하는 플래그&lt;/b&gt;입니다. 특정 효과를 얻고 싶다면 플래그를 설정하면 되지만 성능 저하나 오류가 발생할 수 있으니 잘 알고 사용해야 합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1686055519313&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public void Render()
{
    //렌더링 작업 시작
    _renderTarget2D.BeginDraw();

    //렌더링 화면 비우기(특정 색상 채우기 가능)
    _renderTarget2D.Clear(new SharpDX.Mathematics.Interop.RawColor4(1.0f, 1.0f, 1.0f, 1.0f));

    //1:1 비율로 그리기
    //_renderTarget2D.DrawBitmap(_bitmap, 1.0f, SharpDX.Direct2D1.BitmapInterpolationMode.Linear);

    //렌더링 타겟에 채워서 그리기
    _renderTarget2D.DrawBitmap(_bitmap, _targetWindowSize, 1.0f, SharpDX.Direct2D1.BitmapInterpolationMode.Linear);

    //렌더링 작업 종료
    _renderTarget2D.EndDraw();

    //스왑 체인의 렌더링 이미지를 화면에 표시하는 역할
    _swapChain.Present(1, PresentFlags.None);
}&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;객체 소멸&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;더 이상 사용하지 않는 객체는 소멸합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1686056880020&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public void Dispose()
{
    _renderTarget2D?.Dispose();
    _renderTarget2D = null;

    _swapChain?.Dispose();
    _swapChain = null;

    _device?.Dispose();
    _device = null;

    _factory2D?.Dispose();
    _factory2D = null;

    _bitmap?.Dispose();
    _bitmap = null;
}&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;버튼 동작&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;라디오 버튼으로 GDI+ 또는 DirectX를 선택한 후 실행 버튼을 클릭하면 각 방식 별 렌더링을 위한 스레드 함수가 동작합니다. CPU 및 GPU 사용율을 확인하기 위해 500회 반복하도록 구현했습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1686091526709&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;private void btnLoad_Click(object sender, EventArgs e)
{
    try
    {
        OpenFileDialog dlg = new OpenFileDialog();
        if(dlg.ShowDialog() == DialogResult.OK)
        {
            Thread thread = null;
            if (rbtnDirectX.Checked == true)
            {
                _directX.LoadBitmap(dlg.FileName);
                thread = new Thread(threadFuncDirectX);
            }
            else
            {
                _bitmap = new Bitmap(dlg.FileName);
                //...

                thread = new Thread(threadFuncGDI);
            }
            thread.Start();
        }
    }
    catch (Exception exc)
    {
        MessageBox.Show(exc.Message);
    }
}

private void threadFuncDirectX()
{
    for (int i = 0; i &amp;lt; 500; i++)
    {
        Thread.Sleep(30);
        _directX.Render();
    }
}

private void threadFuncGDI()
{
    for (int i = 0; i &amp;lt; 500; i++)
    {
        Thread.Sleep(30);
        _graphics.DrawImage(_bitmap, new Rectangle(0, 0, pbView.Width, pbView.Height));
    }
}&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;인터넷에서 고해상도 이미지를 다운받습니다. 저는 24MB의 &lt;a title=&quot;고해상도 이미지 다운로드&quot; href=&quot;https://www.pexels.com/search/high%20resolution/?size=large&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;GDI+로 동작하면 CPU 부하가 약 10%까지 증가합니다. GPU는 사용하지 않으므로 따로 사용량이 없습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;799&quot; data-origin-height=&quot;123&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mOI4k/btsji5Xo5uV/70B9cqHmADX0MzvYmpX7T1/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mOI4k/btsji5Xo5uV/70B9cqHmADX0MzvYmpX7T1/img.webp&quot; data-alt=&quot;GDI+ 동작 성능&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mOI4k/btsji5Xo5uV/70B9cqHmADX0MzvYmpX7T1/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmOI4k%2Fbtsji5Xo5uV%2F70B9cqHmADX0MzvYmpX7T1%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; alt=&quot;GDI+-동작-성능&quot; loading=&quot;lazy&quot; width=&quot;799&quot; height=&quot;123&quot; data-origin-width=&quot;799&quot; data-origin-height=&quot;123&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;GDI+ 동작 성능&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;반면, DirectX로 동작하면 CPU 부하가 거의 없으며 GPU 사용량이 증가합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;793&quot; data-origin-height=&quot;119&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/omOhu/btsjjBPfxL7/h4YfeNEgK7YzpwWjfgqoX0/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/omOhu/btsjjBPfxL7/h4YfeNEgK7YzpwWjfgqoX0/img.webp&quot; data-alt=&quot;DirectX 동작 성능&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/omOhu/btsjjBPfxL7/h4YfeNEgK7YzpwWjfgqoX0/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FomOhu%2FbtsjjBPfxL7%2Fh4YfeNEgK7YzpwWjfgqoX0%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; alt=&quot;DirectX-동작-성능&quot; loading=&quot;lazy&quot; width=&quot;793&quot; height=&quot;119&quot; data-origin-width=&quot;793&quot; data-origin-height=&quot;119&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;DirectX 동작 성능&lt;/figcaption&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;fileblock&quot; data-ke-align=&quot;alignCenter&quot;&gt;&lt;a href=&quot;https://blog.kakaocdn.net/dn/bcbpAX/btsiREkkdfD/TswWrWa3EexGMNoIPLoiwk/ExamDirectX.zip?attach=1&amp;amp;knm=tfile.zip&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;ExamDirectX.zip&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;size&quot;&gt;12.28MB&lt;/div&gt;
&lt;/div&gt;
  &lt;/a&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>Programming/DirectX</category>
      <category>.net</category>
      <category>DirectX</category>
      <author>❤ </author>
      <guid isPermaLink="true">https://luckygg.tistory.com/389</guid>
      <comments>https://luckygg.tistory.com/389#entry389comment</comments>
      <pubDate>Sat, 10 Jun 2023 10:11:43 +0900</pubDate>
    </item>
    <item>
      <title>[DirectX] DirectX와 GDI+의 차이점, 그리고 SharpDX 이해하기</title>
      <link>https://luckygg.tistory.com/388</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;DirectX와 GDI의 차이점&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SharpDX를 설명하기 전에, DirectX가 무엇인지 그리고 GDI와 무슨 차이가 있는지부터 알아보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우리가 흔히 알고 있는 &lt;b&gt;GDI(Graphics Device Interface)&lt;/b&gt;는 윈도우 운영 체제의 그래픽 라이브러리로, 도형(직선, 사각형, 원형 등) 또는 문자열, 이미지 등을 그릴 수 있습니다. 그리고 &lt;u&gt;이보다 더 진보된 기술&lt;/u&gt;이 &lt;b&gt;GDI+&lt;/b&gt;이며, GDI보다 더 다양한 그래픽 렌더링 기능을 지원합니다. 주요 특징으로, &lt;u&gt;GDI는 CPU에서 수행되다 보니 하드웨어 가속을 지원하지 않습니다&lt;/u&gt;.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;DirectX&lt;/b&gt;는 게임, 멀티미디어 및 그래픽 응용 프로그램에서 사용되는 라이브러리입니다. 기본적인 입력 장치(키보드, 마우스 등)와 사운드 출력, 2차원뿐만 아니라 3차원 렌더링 기능도 지원합니다. 또한 &lt;u&gt;GDI와 다르게 하드웨어 가속을 지원하여 높은 품질의 그래픽 렌더링이 가능&lt;/u&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-filename=&quot;direct2d-vs-gdi1.png&quot; data-origin-width=&quot;395&quot; data-origin-height=&quot;371&quot;&gt;&lt;a href=&quot;https://learn.microsoft.com/ko-kr/windows/win32/direct2d/comparing-direct2d-and-gdi#differences-between-direct2d-and-gdi&quot; target=&quot;_blank&quot; title=&quot;Microsoft Direct2D 및 GDI 하드웨어 가속&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/AMnAm/btsiQjgfnq4/yun3KrrWbIb8eC8V3ffLA0/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FAMnAm%2FbtsiQjgfnq4%2Fyun3KrrWbIb8eC8V3ffLA0%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; alt=&quot;GDI와-DirectX-계층&quot; loading=&quot;lazy&quot; width=&quot;395&quot; height=&quot;371&quot; data-filename=&quot;direct2d-vs-gdi1.png&quot; data-origin-width=&quot;395&quot; data-origin-height=&quot;371&quot;/&gt;&lt;/a&gt;&lt;figcaption&gt;GDI와 DirectX 계층&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;GDI는 커널 모드&lt;/b&gt;에서, &lt;b&gt;DirectX는 사용자 모드&lt;/b&gt;에서 실행됩니다. 일반적으로 커널 모드에서 실행되는 코드가 하드웨어와 직접적으로 상호작용하여 사용자 모드보다 더 빠르게 실행됩니다. 단순히 이미지 자체만 렌더링 한다면 GDI가 더 빠를 수 있지만, 특수한 조건(좀 더 복잡한 그래픽 처리)에서는 DirectX의 성능이 높을 수 있습니다. 따라서, 어떤 목적으로 그래픽을 처리할 것인가에 따라 적절한 라이브러리를 선택해야 합니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;DirectX 구성 요소&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DirectX가 여러 분야로 지원하다 보니, DirectX에는 다양한 구성 요소가 있습니다. 그중 대표적인 것 몇 개만 나열하면 다음과 같습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Direct2D: 2D 그래픽을 위한 API(기존 GDI/GDI+ 대체)&lt;/li&gt;
&lt;li&gt;Direct3D: 3D 그래픽을 위한 API&lt;/li&gt;
&lt;li&gt;DirectWrite: 텍스트 렌더링을 위한 API&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;SharpDX란?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 본론으로 왔습니다. &lt;b&gt;SharpDX&lt;/b&gt;란, &lt;u&gt;DirectX API를 .Net에 사용할 수 있도록 래핑 된 라이브러리&lt;/u&gt;입니다. 즉, C#에서 DirectX를 쉽게 사용하기 위한 라이브러리라고 이해하면 되겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;http://sharpdx.org/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;http://sharpdx.org/&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1683385907816&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;Home | SharpDX&quot; data-og-description=&quot;SharpDX is an open-source managed .NET wrapper of the DirectX API. NOTE: As of 29 Mar 2019, SharpDX is no longer being under development or maintenance SharpDX has been around for almost 9 years, the project is relatively stable and has been used by many p&quot; data-og-host=&quot;sharpdx.org&quot; data-og-source-url=&quot;http://sharpdx.org/&quot; data-og-url=&quot;http://sharpdx.org/&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;http://sharpdx.org/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;http://sharpdx.org/&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;Home | SharpDX&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;SharpDX is an open-source managed .NET wrapper of the DirectX API. NOTE: As of 29 Mar 2019, SharpDX is no longer being under development or maintenance SharpDX has been around for almost 9 years, the project is relatively stable and has been used by many p&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;sharpdx.org&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SharpDX에서 제공하는 API 종류는 다음과 같습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;3D 그래픽: Direct3D9+, Direct3D11+, Direct3D12+&lt;/li&gt;
&lt;li&gt;2D 그래픽: Direct2D1+, DirectWrite+, WIC&lt;/li&gt;
&lt;li&gt;그래픽 코어: DXGI+, MediaFoundation, DirectComposition, DirectManipulation, Animation&lt;/li&gt;
&lt;li&gt;사운드: DirectSound, XAudio, X3DAudio&lt;/li&gt;
&lt;li&gt;입력: DirectInput, RawInput, XInput&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참고로, &lt;u&gt;SharpDX는 2019년 3월 29일부로 더 이상 개발 및 유지 관리가 되지 않습니다&lt;/u&gt;. 기술 리더와 커뮤니티 참여가 부족하여 더 이상 개발되지 않는다고 하는군요. 하지만 NuGet에서는 다운로드가 가능하며, 여전히 사용하는 데에는 문제가 없습니다. 만약, 최신 버전의 DirectX를 .Net에서 사용하고 싶다면 직접 래핑하여 사용해야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음 포스팅에서는 .Net WinForm 프로젝트에서 SharpDX를 어떻게 사용하는지, 그리고 GDI+와 비교하여 얼마나 성능 차이가 나는지 알아보겠습니다.&lt;/p&gt;</description>
      <category>Programming/DirectX</category>
      <category>DirectX</category>
      <author>❤ </author>
      <guid isPermaLink="true">https://luckygg.tistory.com/388</guid>
      <comments>https://luckygg.tistory.com/388#entry388comment</comments>
      <pubDate>Tue, 6 Jun 2023 14:44:06 +0900</pubDate>
    </item>
    <item>
      <title>메모리와 CPU 부하율을 모니터링하는 Process Manager v2023.05.31, 무료 배포합니다!</title>
      <link>https://luckygg.tistory.com/350</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;프로그램을 개발하고 나면 정상적으로 동작하는지, 문제는 없는지, 에러가 발생하더라도 예외처리가 되는지 등의 검증은 꼭 필요합니다. 그리고 배포 후 문제가 발생하더라도 어느 부분이 문제였는지 추적이 가능해야 합니다. 최소한의 검증도 없이 배포하면 유지보수 시 정말 골치가 아파집니다. 그런데 메모리 누수 또는 불필요하게 CPU 부하율이 높아지지는 않는지도 점검하고 있나요?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실 저는 메모리 누수와 CPU 부하율까지 꼼꼼하게 점검하지는 않았습니다. 당연히 문제없겠지 하고 너무 간과한 부분이죠. 그런데 가끔 특정 프로그램의 메모리 누수와 CPU 부하율을 점검해야 하는 일이 있곤 합니다. 그럴 때마다 하는 방법이 작업 관리자를 열고, 특정 프로세스의 상태(메모리, CPU)를 주기적으로 캡처하는 것입니다. 또는 퇴근하기 전에, 출근한 후 캡처하여 비교하는 것이죠. 여간 귀찮은 일이 아닙니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 만든 것이 &lt;b&gt;Process Manager 프로그램&lt;/b&gt;입니다. 실행 중인 특정 프로세스의 메모리 사용 상태와 CPU 부하율을 주기적으로 확인하여 로그를 남기는 것이죠. 별거 아니지만 막상 사용해 보면 정말 편리합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;프로그램 소개.png&quot; data-origin-width=&quot;873&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dk6Hc8/btsiaD1wEZp/IJq5welc0oUlzg7THhx3G1/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dk6Hc8/btsiaD1wEZp/IJq5welc0oUlzg7THhx3G1/img.webp&quot; data-alt=&quot;프로그램 소개&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dk6Hc8/btsiaD1wEZp/IJq5welc0oUlzg7THhx3G1/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdk6Hc8%2FbtsiaD1wEZp%2FIJq5welc0oUlzg7THhx3G1%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; alt=&quot;프로그램-소개&quot; loading=&quot;lazy&quot; width=&quot;873&quot; data-filename=&quot;프로그램 소개.png&quot; data-origin-width=&quot;873&quot; data-origin-height=&quot;0&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-filename=&quot;동작.gif&quot; data-origin-width=&quot;585&quot; data-origin-height=&quot;873&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bRU9cP/btsiaAjzJ62/nnG8FfrgRqqKB1RLddb8LK/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bRU9cP/btsiaAjzJ62/nnG8FfrgRqqKB1RLddb8LK/img.gif&quot; data-alt=&quot;동작 화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bRU9cP/btsiaAjzJ62/nnG8FfrgRqqKB1RLddb8LK/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/bRU9cP/btsiaAjzJ62/nnG8FfrgRqqKB1RLddb8LK/img.gif&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; alt=&quot;동작-화면&quot; loading=&quot;lazy&quot; width=&quot;585&quot; height=&quot;873&quot; data-filename=&quot;동작.gif&quot; data-origin-width=&quot;585&quot; data-origin-height=&quot;873&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;동작 화면&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&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;/li&gt;
&lt;li&gt;모니터링이 필요한 다수의 프로세스 등록 지원&lt;/li&gt;
&lt;li&gt;등록된 프로세스의 메모리 사용량과 CPU 부하율 점검
&lt;ul style=&quot;list-style-type: circle;&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;/li&gt;
&lt;li&gt;특정 시간(2초~6시간, 또는 지정된 분 단위)을 주기로 점검&lt;/li&gt;
&lt;li&gt;CSV 및 스크린 샷 저장 지원&lt;/li&gt;
&lt;li&gt;CPU 사용량 및 메모리 사용량을 시각화하기 위한 그래프 기능 지원&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;OneDrive로 파일을 첨부했습니다. 아래 링크에서 다운로드하세요.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a title=&quot;다운로드하기&quot; href=&quot;https://1drv.ms/u/s!AhrLbATTcIfkzEZXf2AZxlWwyZ9h?e=EemASW&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;★★다운로드(OneDrive 링크)★★&lt;/a&gt;&lt;/p&gt;
&lt;center&gt;
&lt;script src=&quot;https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js&quot;&gt;&lt;/script&gt;
&lt;ins class=&quot;adsbygoogle&quot; style=&quot;display: block;&quot; data-ad-client=&quot;ca-pub-3156423405867571&quot; data-ad-slot=&quot;4203200518&quot; data-ad-format=&quot;link&quot; data-full-width-responsive=&quot;false&quot; data-ad-language=&quot;ko&quot;&gt;&lt;/ins&gt;
&lt;script&gt;
(adsbygoogle = window.adsbygoogle || []).push({});&lt;/script&gt;
&lt;/center&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;업데이트 이력&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;업데이트 이력은 아래 '&lt;b&gt;더보기&lt;/b&gt;' 버튼을 클릭하여 확인할 수 있습니다.&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;v2023.05.31&lt;/h4&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;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;v2023.03.21&lt;/h4&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;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;v2022.12.6&lt;/h4&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;CPU 사용량 체크가 안정화 됐습니다.&lt;/li&gt;
&lt;li&gt;메모리 표기가 잘못된 점을 개선했습니다.&lt;/li&gt;
&lt;li&gt;자동 스크롤 기능을 추가했습니다.&lt;/li&gt;
&lt;li&gt;모니터링 작업 중 CSV 결과를 저장할 수 있도록 수정했습니다.&lt;/li&gt;
&lt;li&gt;프로그램을 최적화 했습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;v1.3&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;모니터링 주기 10분 설정 시 프로그램 종료되는 버그 수정.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;v1.2&lt;/h4&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;li&gt;모니터링 화면을 실시간으로 캡쳐할 수 있도록 저장 옵션을 추가했습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;v1.1&lt;/h4&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;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;v1.0&lt;/h4&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;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;프로그램 사용 방법&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로그램 사용 방법은 아래 '&lt;b&gt;더보기&lt;/b&gt;' 버튼을 클릭하여 확인하세요.&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;프로세스 등록하기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특정 프로세스를 모니터링하기 위해 &lt;span style=&quot;background-color: #fafafa;&quot;&gt;프로세스&lt;span&gt; &lt;/span&gt;&lt;/span&gt;등록 과정이 필요합니다. 아래 그림처럼 프로세스 목록에서 모니터링이 필요한 프로세스의 이름을 입력합니다. 리스트에 필터링된 프로세스를 선택하고 '&lt;b&gt;등록&lt;/b&gt;' 버튼을 클릭합니다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/QooKm/btrohTQ6IeS/QbxsGaa5l7gqkUyPcEiDSk/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/QooKm/btrohTQ6IeS/QbxsGaa5l7gqkUyPcEiDSk/img.webp&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/QooKm/btrohTQ6IeS/QbxsGaa5l7gqkUyPcEiDSk/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FQooKm%2FbtrohTQ6IeS%2FQbxsGaa5l7gqkUyPcEiDSk%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; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;/&gt;&lt;/span&gt;&lt;/figure&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;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cfH6dR/btrodSL9Wkj/OPbhGXEVDZHVIka9xDTrXk/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cfH6dR/btrodSL9Wkj/OPbhGXEVDZHVIka9xDTrXk/img.webp&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cfH6dR/btrodSL9Wkj/OPbhGXEVDZHVIka9xDTrXk/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcfH6dR%2FbtrodSL9Wkj%2FOPbhGXEVDZHVIka9xDTrXk%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; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;아래 이미지와 같은 창이 표시되면 &lt;b&gt;5초~6시간&lt;/b&gt; 또는 &lt;b&gt;기타&lt;/b&gt;를 선택하여 분 단위로 입력할 수 있습니다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ZGoHd/btrogwPoFlU/kfK4j48B6J6PjKTuXyYAgK/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ZGoHd/btrogwPoFlU/kfK4j48B6J6PjKTuXyYAgK/img.webp&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ZGoHd/btrogwPoFlU/kfK4j48B6J6PjKTuXyYAgK/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FZGoHd%2FbtrogwPoFlU%2FkfK4j48B6J6PjKTuXyYAgK%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; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;h3 data-ke-size=&quot;size23&quot;&gt;모니터링 시작과 종료&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;화면 중간에 있는 '&lt;b&gt;시작&lt;/b&gt;' 버튼과 '&lt;b&gt;종료&lt;/b&gt;' 버튼을 클릭하여 모니터링을 시작, 종료할 수 있습니다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bZG9qs/btroi4SoAKK/9mqDksyuu6IBa6HNPkbkEk/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bZG9qs/btroi4SoAKK/9mqDksyuu6IBa6HNPkbkEk/img.webp&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bZG9qs/btroi4SoAKK/9mqDksyuu6IBa6HNPkbkEk/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbZG9qs%2Fbtroi4SoAKK%2F9mqDksyuu6IBa6HNPkbkEk%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; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&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;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dQrwpG/btrodS6wKlQ/zCrM2ubooABQv8HmotLi60/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dQrwpG/btrodS6wKlQ/zCrM2ubooABQv8HmotLi60/img.webp&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dQrwpG/btrodS6wKlQ/zCrM2ubooABQv8HmotLi60/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdQrwpG%2FbtrodS6wKlQ%2FzCrM2ubooABQv8HmotLi60%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; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;h3 data-ke-size=&quot;size23&quot;&gt;모니터링 결과 CSV로 저장하기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모니터링이 끝나면 화면에 보이는 결과를 CSV 파일로 저장할 수 있습니다. 아래에 표시한 '&lt;b&gt;결과 저장&lt;/b&gt;' 버튼을 클릭합니다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/drsBRu/btrodSFrDqq/ImC8Knm0MpeDoHa1NPcSeK/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/drsBRu/btrodSFrDqq/ImC8Knm0MpeDoHa1NPcSeK/img.webp&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/drsBRu/btrodSFrDqq/ImC8Knm0MpeDoHa1NPcSeK/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdrsBRu%2FbtrodSFrDqq%2FImC8Knm0MpeDoHa1NPcSeK%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; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;/&gt;&lt;/span&gt;&lt;/figure&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;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bJcfPg/btrocSMA3jZ/4IvXjoz01eZlHuyTYF2sS1/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bJcfPg/btrocSMA3jZ/4IvXjoz01eZlHuyTYF2sS1/img.webp&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bJcfPg/btrocSMA3jZ/4IvXjoz01eZlHuyTYF2sS1/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbJcfPg%2FbtrocSMA3jZ%2F4IvXjoz01eZlHuyTYF2sS1%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; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;결과는 아래와 같이 표시됩니다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;550&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/0tH2b/btsh6AEs8Sn/DRFCb99KyjFKax54WQIwK0/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/0tH2b/btsh6AEs8Sn/DRFCb99KyjFKax54WQIwK0/img.webp&quot; data-alt=&quot;CSV 저장 결과&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/0tH2b/btsh6AEs8Sn/DRFCb99KyjFKax54WQIwK0/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F0tH2b%2Fbtsh6AEs8Sn%2FDRFCb99KyjFKax54WQIwK0%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; alt=&quot;CSV-저장-결과&quot; loading=&quot;lazy&quot; width=&quot;550&quot; data-origin-width=&quot;550&quot; data-origin-height=&quot;0&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;CSV 저장 결과&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;h3 data-ke-size=&quot;size23&quot;&gt;모니터링 결과 실시간으로 저장하기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;옵션 창에서 &lt;b&gt;모니터링 기록&lt;/b&gt;의 &lt;b&gt;저장하기&lt;/b&gt;를 체크하면, 정해진 주기마다 지정된 파일이름으로 모니터링 기록이 저장됩니다. 주기는 30초부터 6시간까지 또는 사용자가 지정한 시간(분 단위)으로 설정할 수 있습니다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;364&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/elOUhe/btsicNoEd5S/fyHXJxEdkNW7B4emHXLnZ0/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/elOUhe/btsicNoEd5S/fyHXJxEdkNW7B4emHXLnZ0/img.webp&quot; data-alt=&quot;모니터링 저장 옵션&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/elOUhe/btsicNoEd5S/fyHXJxEdkNW7B4emHXLnZ0/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FelOUhe%2FbtsicNoEd5S%2FfyHXJxEdkNW7B4emHXLnZ0%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; alt=&quot;모니터링-저장-옵션&quot; loading=&quot;lazy&quot; width=&quot;364&quot; data-origin-width=&quot;364&quot; data-origin-height=&quot;0&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;모니터링 저장 옵션&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;h3 data-ke-size=&quot;size23&quot;&gt;모니터 화면을 실시간으로 저장하기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;옵션 창에서 &lt;b&gt;화면 캡처 저장&lt;/b&gt;의 &lt;b&gt;저장하기&lt;/b&gt;를 체크하면, 정해진 주기마다 프로세스 또는 전체 화면이 저장됩니다. &lt;span style=&quot;background-color: #fafafa;&quot;&gt;주기는 30초부터 6시간까지 또는 사용자가 지정한 시간(분 단위)으로 설정할 수 있습니다.&lt;br /&gt;프로세스의 경우, 모니터링 목록에 등록된 모든 프로세스가 캡처됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;364&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cADKle/btsibdVLgWM/jc40umo4THk7fhyuUKjkK0/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cADKle/btsibdVLgWM/jc40umo4THk7fhyuUKjkK0/img.webp&quot; data-alt=&quot;화면 캡쳐 저장 옵션&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cADKle/btsibdVLgWM/jc40umo4THk7fhyuUKjkK0/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcADKle%2FbtsibdVLgWM%2Fjc40umo4THk7fhyuUKjkK0%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; alt=&quot;화면-캡쳐-저장-옵션&quot; loading=&quot;lazy&quot; width=&quot;364&quot; data-origin-width=&quot;364&quot; data-origin-height=&quot;0&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;화면 캡쳐 저장 옵션&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;h3 data-ke-size=&quot;size23&quot;&gt;그래프 보기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시간이 지남에 따라 CPU 부하와 메모리 사용량이 엑셀처럼 표시됩니다. 하지만 너무 많이 쌓이면 추이를 보기가 어려운 단점이 있습니다. 이를 해결하기 위해 그래프 기능을 추가했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래와 같이 &lt;b&gt;그래프 보기&lt;/b&gt; 항목을 체크합니다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;622&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cfSS57/btsibfzePCT/j6Tz0MKys5zQJe8YnjvYWK/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cfSS57/btsibfzePCT/j6Tz0MKys5zQJe8YnjvYWK/img.webp&quot; data-alt=&quot;그래프 보기 옵션&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cfSS57/btsibfzePCT/j6Tz0MKys5zQJe8YnjvYWK/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcfSS57%2FbtsibfzePCT%2Fj6Tz0MKys5zQJe8YnjvYWK%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; alt=&quot;그래프-보기-옵션&quot; loading=&quot;lazy&quot; width=&quot;622&quot; data-origin-width=&quot;622&quot; data-origin-height=&quot;0&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;그래프 보기 옵션&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;그래프에는 시간의 흐름에 따른 데이터가 표시되어 추이를 한눈에 볼 수 있습니다. 해당 그래프는 &lt;a title=&quot;ScottPlot 홈페이지&quot; href=&quot;https://scottplot.net/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;ScottPlot&lt;/a&gt;이라는 오픈 소스 라이브러리를 사용했습니다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;881&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cBCdZe/btsiaBiufhC/E4gO9xc4R4VkBWfJmy8Nl0/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cBCdZe/btsiaBiufhC/E4gO9xc4R4VkBWfJmy8Nl0/img.webp&quot; data-alt=&quot;그래프 표시 화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cBCdZe/btsiaBiufhC/E4gO9xc4R4VkBWfJmy8Nl0/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcBCdZe%2FbtsiaBiufhC%2FE4gO9xc4R4VkBWfJmy8Nl0%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; alt=&quot;그래프-표시-화면&quot; loading=&quot;lazy&quot; width=&quot;881&quot; data-origin-width=&quot;881&quot; data-origin-height=&quot;0&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;그래프 표시 화면&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/div&gt;
&lt;/div&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;/li&gt;
&lt;li&gt;데이터 표시 부분은 1초 간격으로 갱신됩니다. 데이터 표시 부분의 스크롤 이동이나 키보드 방향 이동 시 갱신과 겹치면 버벅거리는 것처럼 느껴질 수 있습니다.&lt;/li&gt;
&lt;li&gt;그래프도 1초 간격으로 갱신됩니다. 그래프 조작(확대, 축소, 이동 등) 중 갱신이되면 첫 모습으로 돌아가기 때문에 동작이 충돌됩니다. 이 경우에는 &lt;b&gt;일시 중지&lt;/b&gt; 항목을 체크하여 업데이트를 잠시 멈추고 조작하면 되겠습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;288&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bL2hxu/btsiacQQvZV/1RxzA39kzh3IAQJJpPwl1K/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bL2hxu/btsiacQQvZV/1RxzA39kzh3IAQJJpPwl1K/img.webp&quot; data-alt=&quot;그래프 갱신 일시 중지하기&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bL2hxu/btsiacQQvZV/1RxzA39kzh3IAQJJpPwl1K/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbL2hxu%2FbtsiacQQvZV%2F1RxzA39kzh3IAQJJpPwl1K%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; alt=&quot;그래프-갱신-일시-중지하기&quot; loading=&quot;lazy&quot; width=&quot;288&quot; data-origin-width=&quot;288&quot; data-origin-height=&quot;0&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;그래프 갱신 일시 중지하기&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;버그 신고 또는 개선 사항 요청 방법&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로그램 사용 중 문제가 발생하면 &lt;b&gt;댓글&lt;/b&gt;로 신고 부탁드립니다. 또는 &lt;b&gt;개선 사항&lt;/b&gt;을 요청하셔도 좋습니다.&lt;/p&gt;</description>
      <category>Programming/프로그램 배포</category>
      <category>.net</category>
      <author>❤ </author>
      <guid isPermaLink="true">https://luckygg.tistory.com/350</guid>
      <comments>https://luckygg.tistory.com/350#entry350comment</comments>
      <pubDate>Wed, 31 May 2023 22:35:51 +0900</pubDate>
    </item>
    <item>
      <title>[OpenCV] VTK 9.0.0과 OpenCV 4.4.0으로 viz 모듈 포함하여 빌드하기!</title>
      <link>https://luckygg.tistory.com/250</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;viz 모듈이란&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OpenCV에서 제공하는 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;3D 가시화(Visualization) 라이브러리&lt;/span&gt;&lt;/code&gt;를 의미합니다. 또한, 위젯을 표시하는 데 사용되며 위젯과 상호 작용하는 여러 함수들을 제공합니다. 예를 들면, 선, 포인트, 바운딩 박스, 문자열 등을 그리는 작업이 가능합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데 OpenCV는 기본적으로 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;viz&lt;/span&gt;&lt;/code&gt;를 제공하지 않습니다. 사용자가 직접 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;VTK 라이브러리&lt;/span&gt;&lt;/code&gt;를 사용하여 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;viz&lt;/span&gt;&lt;/code&gt; 모듈이 포함된 OpenCV 라이브러리를 생성해야 합니다. 이 과정이 꽤 시간이 걸리고 복잡한데요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 포스팅을 통해 어떻게 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;viz&lt;/span&gt;&lt;/code&gt; 모듈이 포함된 OpenCV 라이브러리를 빌드하는지 소개하겠습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;준비 사항&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. VTK 8.2.0 또는 9.0.0 Source 파일을 준비합니다.&lt;br /&gt;다운로드 링크: &lt;a href=&quot;https://vtk.org/download/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;vtk.org/download/&lt;/a&gt; 또는 &lt;a href=&quot;https://github.com/Kitware/VTK/releases&quot;&gt;https://github.com/Kitware/VTK/releases&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. OpenCV 4.4.0 Source 파일을 준비합니다.&lt;br /&gt;다운로드 링크: &lt;a href=&quot;https://opencv.org/releases/&quot;&gt;https://opencv.org/releases/&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. OpenCV-contrib 4.4.0 source 파일을 준비합니다.&lt;br /&gt;다운로드 링크: &lt;a href=&quot;https://github.com/opencv/opencv_contrib/releases&quot;&gt;https://github.com/opencv/opencv_contrib/releases&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. CMake 설치 파일을 준비합니다.&lt;br /&gt;다운로드 링크: &lt;a href=&quot;https://cmake.org/download/&quot;&gt;https://cmake.org/download/&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CMake는 라이브러리 소스 파일을 빌드하여 개발 환경에 맞는 라이브러리를 생성하는 용도입니다. CMake 설치방법은 아래 글을 참고해주세요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://luckygg.tistory.com/121&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;[CMake] CMake 설치하기&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1596965617737&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[CMake] CMake 설치하기&quot; data-og-description=&quot;CMake는 사용자가 원하는 개발환경의 라이브러리 생성을 도와주는 오픈 소스 도구입니다. OpenCV나 VTK 혹은 각 제조사에서 제공하는 SDK를 개발환경에 따라 라이브러리를 새로 생성할 때 사용됩니��&quot; data-og-host=&quot;luckygg.tistory.com&quot; data-og-source-url=&quot;https://luckygg.tistory.com/121&quot; data-og-url=&quot;https://luckygg.tistory.com/121&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/dKW6kr/hyG5Aj1sEt/f9NKebFyjtEEht6KI9Mvr0/img.png?width=256&amp;amp;height=256&amp;amp;face=0_0_256_256,https://scrap.kakaocdn.net/dn/cRyEbv/hyG3Vche4m/pLTpVlal4fklzKrSuLfMT1/img.png?width=256&amp;amp;height=256&amp;amp;face=0_0_256_256,https://scrap.kakaocdn.net/dn/1atBw/hyG5vJNaBS/QMB5pOknrLUwHf4k95zxV1/img.png?width=860&amp;amp;height=547&amp;amp;face=0_0_860_547&quot;&gt;&lt;a href=&quot;https://luckygg.tistory.com/121&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://luckygg.tistory.com/121&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/dKW6kr/hyG5Aj1sEt/f9NKebFyjtEEht6KI9Mvr0/img.png?width=256&amp;amp;height=256&amp;amp;face=0_0_256_256,https://scrap.kakaocdn.net/dn/cRyEbv/hyG3Vche4m/pLTpVlal4fklzKrSuLfMT1/img.png?width=256&amp;amp;height=256&amp;amp;face=0_0_256_256,https://scrap.kakaocdn.net/dn/1atBw/hyG5vJNaBS/QMB5pOknrLUwHf4k95zxV1/img.png?width=860&amp;amp;height=547&amp;amp;face=0_0_860_547');&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;[CMake] CMake 설치하기&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;CMake는 사용자가 원하는 개발환경의 라이브러리 생성을 도와주는 오픈 소스 도구입니다. OpenCV나 VTK 혹은 각 제조사에서 제공하는 SDK를 개발환경에 따라 라이브러리를 새로 생성할 때 사용됩니��&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;luckygg.tistory.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;div class=&quot;rgyInfo&quot;&gt;
&lt;div class=&quot;rgyInfo-circle&quot;&gt;
&lt;div class=&quot;topDiv&quot;&gt;주의&lt;/div&gt;
&lt;div class=&quot;bottomDiv&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;bottomDiv2&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;rgyInfo-text&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OpenCV-contrib를 사용하여 viz 모듈을 생성할 수 있는데요. OpenCV-contrib viz 모듈은 VTK 8.90.0 까지만 호환되는 것 같습니다. 만약, 공식적인 버전으로 빌드하고 싶다면 VTK 8.2.0을, VTK 9.0.0이 괜찮다면 본문의 순서대로 따라 하면 되겠습니다.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. VTK 빌드하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;VTK 라이브러리&lt;/span&gt;&lt;/code&gt;부터 빌드를 시작합니다. &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;VTK 8.2.0&lt;/span&gt;&lt;/code&gt; 또는 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;9.0.0&lt;/span&gt;&lt;/code&gt; &lt;code&gt;&lt;span class=&quot;token function&quot;&gt;source&lt;/span&gt;&lt;/code&gt; 파일을 준비하고 압축을 해제합니다. 본문에서는 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;VTK 9.0.0&lt;/span&gt;&lt;/code&gt;을 사용했습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthContent&quot; data-filename=&quot;CMake.png&quot; data-origin-width=&quot;609&quot; data-origin-height=&quot;615&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eG1Zrz/btqGx834IWr/KnOh8xwwtCvLkcSSwznyLK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eG1Zrz/btqGx834IWr/KnOh8xwwtCvLkcSSwznyLK/img.png&quot; data-alt=&quot;CMake에서 VTK 경로 설정&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eG1Zrz/btqGx834IWr/KnOh8xwwtCvLkcSSwznyLK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FeG1Zrz%2FbtqGx834IWr%2FKnOh8xwwtCvLkcSSwznyLK%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;609&quot; height=&quot;615&quot; data-filename=&quot;CMake.png&quot; data-origin-width=&quot;609&quot; data-origin-height=&quot;615&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;CMake에서 VTK 경로 설정&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 74px;&quot; border=&quot;1&quot; data-ke-style=&quot;style12&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 18px;&quot;&gt;
&lt;td style=&quot;width: 50%; text-align: center; height: 18px;&quot;&gt;&lt;b&gt;항목&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 50%; text-align: center; height: 18px;&quot;&gt;&lt;b&gt;설명&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 18px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 18px;&quot;&gt;Where is the source code&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 18px;&quot;&gt;VTK의 소스 파일 경로를 지정합니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 38px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 38px;&quot;&gt;Where to build the binaries&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 38px;&quot;&gt;빌드 된 바이너리 파일들이 생성되는 경로를 지정합니다.&lt;br /&gt;본문에서는 &lt;b&gt;vtk_bin&lt;/b&gt;이라는 폴더를 생성해서 지정했습니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;Configure 버튼&lt;/span&gt;&lt;/code&gt;을 클릭하면 아래와 같이 개발 환경을 선택하는 창이 표시됩니다. &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;컴파일러 버전&lt;/span&gt;&lt;/code&gt;과 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;OS 비트 버전&lt;/span&gt;&lt;/code&gt;을 선택합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthContent&quot; data-filename=&quot;Configure.png&quot; data-origin-width=&quot;609&quot; data-origin-height=&quot;615&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/YD84v/btqGuypAObU/ieKpJc4Zik7O4hXSbE0CKK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/YD84v/btqGuypAObU/ieKpJc4Zik7O4hXSbE0CKK/img.png&quot; data-alt=&quot;개발 환경 선택 화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/YD84v/btqGuypAObU/ieKpJc4Zik7O4hXSbE0CKK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FYD84v%2FbtqGuypAObU%2FieKpJc4Zik7O4hXSbE0CKK%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;609&quot; height=&quot;615&quot; data-filename=&quot;Configure.png&quot; data-origin-width=&quot;609&quot; data-origin-height=&quot;615&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;code&gt;&lt;span class=&quot;token keyword&quot;&gt;Finish 버튼&lt;/span&gt;&lt;/code&gt;을 클릭하면 라이브러리 생성을 위한 준비 과정이 시작됩니다. 조금 기다리고 나면 아래와 같은 화면이 표시됩니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthContent&quot; data-filename=&quot;옵션 선택 화면.png&quot; data-origin-width=&quot;609&quot; data-origin-height=&quot;615&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/sRSrX/btqGuMumzzf/OQFF62JsJtTlhq1sPGUqMK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/sRSrX/btqGuMumzzf/OQFF62JsJtTlhq1sPGUqMK/img.png&quot; data-alt=&quot;빌드 옵션 선택 화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/sRSrX/btqGuMumzzf/OQFF62JsJtTlhq1sPGUqMK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FsRSrX%2FbtqGuMumzzf%2FOQFF62JsJtTlhq1sPGUqMK%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;609&quot; height=&quot;615&quot; data-filename=&quot;옵션 선택 화면.png&quot; data-origin-width=&quot;609&quot; data-origin-height=&quot;615&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;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-style=&quot;style12&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;&lt;b&gt;항목&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;&lt;b&gt;설명&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;VTK_BUILD_EXAMPLE&lt;/td&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;예제 프로그램 생성 선택 옵션입니다. 해제합니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;BUILD_SHARED_LIBS&lt;/td&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;공유 또는 정적 라이브러리 생성 선택 옵션입니다. 필요한대로 선택합니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;VTK_BUILD_TESTING&lt;/td&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;VTK_BUILD_EXAMPLE과 더불어 해당 옵션을 해제하면 빌드 속도가 향상됩니다. 굳이 체크하지 않아도 됩니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;Generate 버튼&lt;/span&gt;&lt;/code&gt;을 클릭하면 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;binaries 경로&lt;/span&gt;&lt;/code&gt;에 아래와 같은 파일들이 생성됩니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthContent&quot; data-filename=&quot;바이너리 파일.png&quot; data-origin-width=&quot;897&quot; data-origin-height=&quot;634&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cafzmm/btqGurw2kSy/j8Aji9xLJ5OByVTMdt4Xy0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cafzmm/btqGurw2kSy/j8Aji9xLJ5OByVTMdt4Xy0/img.png&quot; data-alt=&quot;생성된 바이너리 파일&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cafzmm/btqGurw2kSy/j8Aji9xLJ5OByVTMdt4Xy0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcafzmm%2FbtqGurw2kSy%2Fj8Aji9xLJ5OByVTMdt4Xy0%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;897&quot; height=&quot;634&quot; data-filename=&quot;바이너리 파일.png&quot; data-origin-width=&quot;897&quot; data-origin-height=&quot;634&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;s&gt;&lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;OpenCV viz 모듈&lt;/span&gt;&lt;/code&gt;을 생성하기 위해서 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;VTK&lt;/span&gt;&lt;/code&gt;는 여기까지 진행하면 됩니다. 만약, &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;VTK 라이브러리&lt;/span&gt;&lt;/code&gt;를 생성하고 싶다면 아래 링크를 참고하세요.&lt;/s&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;VTK 라이브러리도 아래를 참고하여 빌드를 완료해 주세요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://luckygg.tistory.com/125&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;[VTK] VTK 8.2 및 Visual Studio 2015 환경 구성&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1597146287472&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[VTK] VTK 8.2 및 Visual Studio 2015 환경 구성&quot; data-og-description=&quot;VTK를 사용하기 위해서는 준비 과정이 다소 길고 복잡합니다. 본 글에서는 차례차례 쉽게 따라 할 수 있도록 정리해 보았습니다. ※ 2019년 7월 3일 추가 혹시 아래 빌드 과정이 안 되는 분들을 위��&quot; data-og-host=&quot;luckygg.tistory.com&quot; data-og-source-url=&quot;https://luckygg.tistory.com/125&quot; data-og-url=&quot;https://luckygg.tistory.com/125&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bLt7xM/hyG7RMBZz4/8BBBWDTdBMlRoFtbZjtDBK/img.png?width=300&amp;amp;height=161&amp;amp;face=0_0_300_161,https://scrap.kakaocdn.net/dn/GBJcI/hyG5BScM8X/PAKGhbezh9kSOsayaOcDgK/img.png?width=300&amp;amp;height=161&amp;amp;face=0_0_300_161,https://scrap.kakaocdn.net/dn/bydSKw/hyG7T4JtIa/kzZaqUgb5HFdpWUvIi9ynk/img.png?width=860&amp;amp;height=889&amp;amp;face=0_0_860_889&quot;&gt;&lt;a href=&quot;https://luckygg.tistory.com/125&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://luckygg.tistory.com/125&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bLt7xM/hyG7RMBZz4/8BBBWDTdBMlRoFtbZjtDBK/img.png?width=300&amp;amp;height=161&amp;amp;face=0_0_300_161,https://scrap.kakaocdn.net/dn/GBJcI/hyG5BScM8X/PAKGhbezh9kSOsayaOcDgK/img.png?width=300&amp;amp;height=161&amp;amp;face=0_0_300_161,https://scrap.kakaocdn.net/dn/bydSKw/hyG7T4JtIa/kzZaqUgb5HFdpWUvIi9ynk/img.png?width=860&amp;amp;height=889&amp;amp;face=0_0_860_889');&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;[VTK] VTK 8.2 및 Visual Studio 2015 환경 구성&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;VTK를 사용하기 위해서는 준비 과정이 다소 길고 복잡합니다. 본 글에서는 차례차례 쉽게 따라 할 수 있도록 정리해 보았습니다. ※ 2019년 7월 3일 추가 혹시 아래 빌드 과정이 안 되는 분들을 위��&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;luckygg.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2. OpenCV-contrib 수정하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앞에서 얘기한대로, &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;OpenCV-contrib 4.4.0&lt;/span&gt;&lt;/code&gt;은 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;VTK 8.90.0&lt;/span&gt;&lt;/code&gt;까지 호환되는 것으로 보입니다. 그 이유로는, 아래 경로의 파일에 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;VTK 버전&lt;/span&gt;&lt;/code&gt;이 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;8.90.0&lt;/span&gt;&lt;/code&gt;으로 표기돼있습니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;opencv_contrib-4.4.0\modules\viz\CMakeList.txt&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthContent&quot; data-origin-width=&quot;652&quot; data-origin-height=&quot;296&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/coe86V/btqGuyC92t4/YafJZ6GkL6PBAY34Hq8Pak/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/coe86V/btqGuyC92t4/YafJZ6GkL6PBAY34Hq8Pak/img.png&quot; data-alt=&quot;CMakeList에 표기되어 있는 VTK 버전&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/coe86V/btqGuyC92t4/YafJZ6GkL6PBAY34Hq8Pak/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcoe86V%2FbtqGuyC92t4%2FYafJZ6GkL6PBAY34Hq8Pak%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;652&quot; height=&quot;296&quot; data-origin-width=&quot;652&quot; data-origin-height=&quot;296&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;CMakeList에 표기되어 있는 VTK 버전&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이게 정확히 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;8.90.0&lt;/span&gt;&lt;/code&gt;까지만 호환된다는 의미인지는 모르겠습니다만, 강제로 아래와 같이 변경하면 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;VTK 9.0.0&lt;/span&gt;&lt;/code&gt;으로 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;viz 모듈&lt;/span&gt;&lt;/code&gt;을 생성할 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthContent&quot; data-origin-width=&quot;631&quot; data-origin-height=&quot;291&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cKG6tE/btqGsnWvfZY/KJmr4X55PTUtGLx2zAKmeK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cKG6tE/btqGsnWvfZY/KJmr4X55PTUtGLx2zAKmeK/img.png&quot; data-alt=&quot;CMakeList에 VTK 버전을 수정&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cKG6tE/btqGsnWvfZY/KJmr4X55PTUtGLx2zAKmeK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcKG6tE%2FbtqGsnWvfZY%2FKJmr4X55PTUtGLx2zAKmeK%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;631&quot; height=&quot;291&quot; data-origin-width=&quot;631&quot; data-origin-height=&quot;291&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;CMakeList에 VTK 버전을 수정&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;같은 방법으로 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;VTK 9.0.1&lt;/span&gt;&lt;/code&gt;도 해봤으나 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;CMake&lt;/span&gt;&lt;/code&gt;에서 빌드 시 에러가 발생합니다. 여기까지 수정이 완료되면 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;OpenCV-contrib&lt;/span&gt;&lt;/code&gt; 준비도 끝납니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3. OpenCV 빌드하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 본격적으로 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;CMake&lt;/span&gt;&lt;/code&gt;에서 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;OpenCV&lt;/span&gt;&lt;/code&gt;를 빌드합니다. &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;VTK&lt;/span&gt;&lt;/code&gt;와 마찬가지로 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;OpenCV 4.4.0 source 파일&lt;/span&gt;&lt;/code&gt;을 준비하고 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;binary 파일&lt;/span&gt;&lt;/code&gt;이 생성되는 경로도 지정합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthContent&quot; data-origin-width=&quot;609&quot; data-origin-height=&quot;615&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bTL48G/btqGvc0uC65/YF1qTK1tXLhm7skQYJpk8K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bTL48G/btqGvc0uC65/YF1qTK1tXLhm7skQYJpk8K/img.png&quot; data-alt=&quot;OpenCV source 및 binary 경로 지정&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bTL48G/btqGvc0uC65/YF1qTK1tXLhm7skQYJpk8K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbTL48G%2FbtqGvc0uC65%2FYF1qTK1tXLhm7skQYJpk8K%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;609&quot; height=&quot;615&quot; data-origin-width=&quot;609&quot; data-origin-height=&quot;615&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;OpenCV source 및 binary 경로 지정&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;Configure 버튼&lt;/span&gt;&lt;/code&gt;을 클릭하여 개발 환경을 입력합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthContent&quot; data-origin-width=&quot;609&quot; data-origin-height=&quot;615&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xU2uU/btqGtd69os0/a5FNSmfflFOURle2GaEDTK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xU2uU/btqGtd69os0/a5FNSmfflFOURle2GaEDTK/img.png&quot; data-alt=&quot;개발 환경 선택 화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xU2uU/btqGtd69os0/a5FNSmfflFOURle2GaEDTK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxU2uU%2FbtqGtd69os0%2Fa5FNSmfflFOURle2GaEDTK%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;609&quot; height=&quot;615&quot; data-origin-width=&quot;609&quot; data-origin-height=&quot;615&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;span style=&quot;color: #333333;&quot;&gt;&lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;Finish 버튼&lt;/span&gt;&lt;/code&gt;을 클릭하면 라이브러리 생성을 위한 준비 과정이 시작됩니다. 조금 기다리고 나면 아래와 같은 화면이 표시됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthContent&quot; data-origin-width=&quot;609&quot; data-origin-height=&quot;615&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/oqaU8/btqGxxJNYgc/sHbAkcn3kgNOp2JrlYIKeK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/oqaU8/btqGxxJNYgc/sHbAkcn3kgNOp2JrlYIKeK/img.png&quot; data-alt=&quot;빌드 옵션 선택 화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/oqaU8/btqGxxJNYgc/sHbAkcn3kgNOp2JrlYIKeK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FoqaU8%2FbtqGxxJNYgc%2FsHbAkcn3kgNOp2JrlYIKeK%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;609&quot; height=&quot;615&quot; data-origin-width=&quot;609&quot; data-origin-height=&quot;615&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;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-style=&quot;style12&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;&lt;b&gt;항목&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;&lt;b&gt;설명&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;OPENCV_EXTRA_MODULES_PATH&lt;/td&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;opencv_contrib-4.4.0\modules 경로를 설정합니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;BUILD_SHARED_LIBS&lt;/td&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;공유 또는 정적 라이브러리 생성 선택 옵션입니다. 본문에서는 체크하여 공유 라이브러리로 생성했습니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;VTK_DIR&lt;/td&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;&lt;s&gt;VTK binary 경로를 설정합니다. 본문에서는 vtk_bin 폴더에 이미 생성했습니다.&lt;br /&gt;&lt;br /&gt;&lt;/s&gt;빌드된 VTK 라이브러리 경로를 설정합니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;WITH_VTK&lt;/td&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;체크합니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;Generate 버튼&lt;/span&gt;&lt;/code&gt;을 클릭하고 나면 아래와 같이 화면이 표시됩니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthContent&quot; data-origin-width=&quot;609&quot; data-origin-height=&quot;615&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/7wFYM/btqGuF2Vlcn/3raJnKe9VrAYraklQvwTv1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/7wFYM/btqGuF2Vlcn/3raJnKe9VrAYraklQvwTv1/img.png&quot; data-alt=&quot;Generate 이후 모습&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/7wFYM/btqGuF2Vlcn/3raJnKe9VrAYraklQvwTv1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F7wFYM%2FbtqGuF2Vlcn%2F3raJnKe9VrAYraklQvwTv1%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;609&quot; height=&quot;615&quot; data-origin-width=&quot;609&quot; data-origin-height=&quot;615&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Generate 이후 모습&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;Binary 생성 경로&lt;/span&gt;&lt;/code&gt;를 보면 아래와 같이 파일들이 생성되어 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthContent&quot; data-origin-width=&quot;897&quot; data-origin-height=&quot;634&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/BksPy/btqGyv5Q1SX/NQO0SlUsKRfMuYmatqv0c0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/BksPy/btqGyv5Q1SX/NQO0SlUsKRfMuYmatqv0c0/img.png&quot; data-alt=&quot;생성된 바이너리 파일&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/BksPy/btqGyv5Q1SX/NQO0SlUsKRfMuYmatqv0c0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FBksPy%2FbtqGyv5Q1SX%2FNQO0SlUsKRfMuYmatqv0c0%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;897&quot; height=&quot;634&quot; data-origin-width=&quot;897&quot; data-origin-height=&quot;634&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;code&gt;&lt;span class=&quot;token keyword&quot;&gt;Binary 폴더&lt;/span&gt;&lt;/code&gt;의 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;OpenCV.sln 파일&lt;/span&gt;&lt;/code&gt;을 실행합니다. 주의할 점은 반드시 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;Visual Studio를 관리자 권한으로 실행&lt;/span&gt;&lt;/code&gt;해야 합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthContent&quot; data-origin-width=&quot;697&quot; data-origin-height=&quot;701&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/zD2ni/btqGsn3gAym/jOk2XoKsP8KkLFGFFgXHRk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/zD2ni/btqGsn3gAym/jOk2XoKsP8KkLFGFFgXHRk/img.png&quot; data-alt=&quot;OpenCV.sln 실행 모습&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/zD2ni/btqGsn3gAym/jOk2XoKsP8KkLFGFFgXHRk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FzD2ni%2FbtqGsn3gAym%2FjOk2XoKsP8KkLFGFFgXHRk%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;697&quot; height=&quot;701&quot; data-origin-width=&quot;697&quot; data-origin-height=&quot;701&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;OpenCV.sln 실행 모습&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;ALL_BUILD&lt;/span&gt;&lt;/code&gt;와 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;INSTALL&lt;/span&gt;&lt;/code&gt;을 차례대로 빌드합니다. 빌드가 끝나면 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;opencv_bin/install&lt;/span&gt;&lt;/code&gt; 경로에 라이브러리 파일이 생성되어 있습니다. &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;Debug&lt;/span&gt;&lt;/code&gt; 및 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;Release&lt;/span&gt;&lt;/code&gt; 모드로 같은 방식으로 빌드합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;debug\include\opencv2&lt;/span&gt;&lt;/code&gt;에 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;viz 폴더&lt;/span&gt;&lt;/code&gt;가 있고, 그 안에 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;viz 관련 코드&lt;/span&gt;&lt;/code&gt;가 생성된 것을 확인할 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthContent&quot; data-origin-width=&quot;858&quot; data-origin-height=&quot;704&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/EA6qz/btqGvaBPFK5/JKvpd37sbJOjXR50zGGoP1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/EA6qz/btqGvaBPFK5/JKvpd37sbJOjXR50zGGoP1/img.png&quot; data-alt=&quot;생성된 viz 모듈&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/EA6qz/btqGvaBPFK5/JKvpd37sbJOjXR50zGGoP1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FEA6qz%2FbtqGvaBPFK5%2FJKvpd37sbJOjXR50zGGoP1%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;858&quot; height=&quot;704&quot; data-origin-width=&quot;858&quot; data-origin-height=&quot;704&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;생성된 viz 모듈&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;결론&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저는 처음에 며칠동안 헤매고 인터넷에서 온갖 정보를 참고하여 결국에 OpenCV viz 모듈 생성에 성공했습니다. 편하게 누군가가 제공해주면 쉽겠지만, 이렇게 시도해 본 것도 좋은 경험인 것 같습니다. 이 글이 누군가에게 도움이 되었으면 하네요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div&gt;
&lt;script src=&quot;https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js&quot;&gt;&lt;/script&gt;
&lt;ins class=&quot;adsbygoogle&quot; style=&quot;display: block;&quot; data-ad-format=&quot;autorelaxed&quot; data-ad-client=&quot;ca-pub-3156423405867571&quot; data-ad-slot=&quot;7295645329&quot;&gt;&lt;/ins&gt;
&lt;script&gt;
     (adsbygoogle = window.adsbygoogle || []).push({});
&lt;/script&gt;
&lt;/div&gt;</description>
      <category>Programming/OpenCV</category>
      <category>OpenCV</category>
      <category>VTK</category>
      <author>❤ </author>
      <guid isPermaLink="true">https://luckygg.tistory.com/250</guid>
      <comments>https://luckygg.tistory.com/250#entry250comment</comments>
      <pubDate>Sat, 15 Apr 2023 19:23:56 +0900</pubDate>
    </item>
    <item>
      <title>[.Net] 지연(Delay) 함수들의 특징과 차이점 정리</title>
      <link>https://luckygg.tistory.com/387</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;지연(Delay) 함수&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로그램을 개발하다 보면 단발성으로 실행하는 스레드 함수가 있고, 프로그램이 시작된 후 종료되기 직전까지 실행되는 스레드 함수가 있습니다. 그리고 후자의 경우에는 스레드 함수 내에 반복문을 넣어서 구현됩니다. 그런데 이 반복문에 지연(Delay) 함수를 넣지 않으면 &lt;u&gt;과도한 연산으로 인해 CPU 부하가 증가&lt;/u&gt;하게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CPU 부하를 낮추기 위해 스레드 함수의 반복문 안에는 &lt;code&gt;&lt;span class=&quot;token function&quot;&gt;Sleep()&lt;/span&gt;&lt;/code&gt; 함수를 사용하는 것이 일반적입니다. 사실 꼭 스레드 함수의 반복문에만 해당하는 것은 아닙니다. 과도한 반복문 내에는 지연 함수를 사용하지 않으면 CPU 부하가 높아지기 때문입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데 지연을 위한 함수로는 &lt;code&gt;&lt;span class=&quot;token function&quot;&gt;Sleep()&lt;/span&gt;&lt;/code&gt; 뿐만 아니라 &lt;code&gt;&lt;span class=&quot;token function&quot;&gt;AutoResetEvent.WaitOne()&lt;/span&gt;&lt;/code&gt;도 있고 &lt;code&gt;&lt;span class=&quot;token function&quot;&gt;Task.Delay()&lt;/span&gt;&lt;/code&gt;도 있습니다. 본문에서는 각 지연 함수에 따른 차이점을 정리해 보았습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;지연 함수의 종류&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. Thread.Sleep() 함수&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 많이 사용하는 함수이죠. 사용하는 방법이 정말 간단합니다. 함수 인자로 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;밀리미터 시간&lt;/span&gt;&lt;/code&gt; 또는 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;TimeSpan&lt;/span&gt;&lt;/code&gt; 시간을 입력하면 해당 시간만큼 지연됩니다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1673143102948&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public static void Sleep (int millisecondsTimeout);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용 예시는 다음과 같습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1673143335772&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;using System;
using System.Threading;

class Example
{
    static void Main()
    {
        for (int i = 0; i &amp;lt; 5; i++)
        {
            Console.WriteLine(&quot;Sleep for 2 seconds.&quot;);
            Thread.Sleep(2000);
        }

        Console.WriteLine(&quot;Main thread exits.&quot;);
    }
}

/* 예제 실행 결과:

Sleep for 2 seconds.
Sleep for 2 seconds.
Sleep for 2 seconds.
Sleep for 2 seconds.
Sleep for 2 seconds.
Main thread exits.
 */&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;MSDN 문서는 아래 링크를 참고하세요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://learn.microsoft.com/ko-kr/dotnet/api/system.threading.thread.sleep?view=net-7.0&quot;&gt;https://learn.microsoft.com/ko-kr/dotnet/api/system.threading.thread.sleep?view=net-7.0&lt;/a&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1673143086380&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;Thread.Sleep 메서드 (System.Threading)&quot; data-og-description=&quot;지정된 시간 동안 현재 스레드를 일시 중단합니다.&quot; data-og-host=&quot;learn.microsoft.com&quot; data-og-source-url=&quot;https://learn.microsoft.com/ko-kr/dotnet/api/system.threading.thread.sleep?view=net-7.0&quot; data-og-url=&quot;https://learn.microsoft.com/ko-kr/dotnet/api/system.threading.thread.sleep&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/5cmAO/hyRcCUfYVT/bzHeR2SWVvSJfdQYUgQKSk/img.png?width=400&amp;amp;height=400&amp;amp;face=0_0_400_400&quot;&gt;&lt;a href=&quot;https://learn.microsoft.com/ko-kr/dotnet/api/system.threading.thread.sleep?view=net-7.0&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://learn.microsoft.com/ko-kr/dotnet/api/system.threading.thread.sleep?view=net-7.0&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/5cmAO/hyRcCUfYVT/bzHeR2SWVvSJfdQYUgQKSk/img.png?width=400&amp;amp;height=400&amp;amp;face=0_0_400_400');&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;Thread.Sleep 메서드 (System.Threading)&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;지정된 시간 동안 현재 스레드를 일시 중단합니다.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;learn.microsoft.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. WaitHandle.WaitOne() 함수&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 함수는 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;WaitHandle&lt;/span&gt;&lt;/code&gt;이 &lt;code&gt;&lt;span class=&quot;token function&quot;&gt;Set()&lt;/span&gt;&lt;/code&gt;이 될 때까지 스레드를 차단하는 동작을 합니다. 함수 인자는 &lt;code&gt;&lt;span class=&quot;token function&quot;&gt;Sleep()&lt;/span&gt;&lt;/code&gt; 함수와 마찬가지로, &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;밀리미터 시간&lt;/span&gt;&lt;/code&gt; 또는 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;TimeSpan&lt;/span&gt;&lt;/code&gt; 시간을 입력합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 동작은 &lt;code&gt;&lt;span class=&quot;token function&quot;&gt;Sleep()&lt;/span&gt;&lt;/code&gt;과 다릅니다. 타임아웃 시간 내에 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;WaitHandle&lt;/span&gt;&lt;/code&gt;이 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;Set&lt;/span&gt;&lt;/code&gt;이 되면, 타임아웃까지 기다리지 않고 바로 다음 코드를 실행합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1673150357967&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public virtual bool WaitOne ();&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예제 코드도 보겠습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1673150648258&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;using System;
using System.Threading;

class WaitOne
{
    static AutoResetEvent autoEvent = new AutoResetEvent(false);

    static void Main()
    {
        Console.WriteLine(&quot;Main starting.&quot;);

        ThreadPool.QueueUserWorkItem(
            new WaitCallback(WorkMethod), autoEvent);

        // autoEvent가 Set이 될 때까지 기다림
        autoEvent.WaitOne();
        Console.WriteLine(&quot;Work method signaled.\nMain ending.&quot;);
    }

    static void WorkMethod(object stateInfo) 
    {
        Console.WriteLine(&quot;Work starting.&quot;);

        //랜덤한 시간 대기
        Thread.Sleep(new Random().Next(100, 2000));

        //대기 후 autoEvent를 Set 합니다
        Console.WriteLine(&quot;Work ending.&quot;);
        ((AutoResetEvent)stateInfo).Set();
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;MSDN 문서는 아래 링크를 참고하세요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://learn.microsoft.com/ko-kr/dotnet/api/system.threading.waithandle.waitone?view=net-7.0&quot;&gt;https://learn.microsoft.com/ko-kr/dotnet/api/system.threading.waithandle.waitone?view=net-7.0&lt;/a&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1673150842495&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;WaitHandle.WaitOne 메서드 (System.Threading)&quot; data-og-description=&quot;현재 WaitHandle이(가) 신호를 받을 때까지 현재 스레드를 차단합니다.&quot; data-og-host=&quot;learn.microsoft.com&quot; data-og-source-url=&quot;https://learn.microsoft.com/ko-kr/dotnet/api/system.threading.waithandle.waitone?view=net-7.0&quot; data-og-url=&quot;https://learn.microsoft.com/ko-kr/dotnet/api/system.threading.waithandle.waitone&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bcSDWG/hyRcDskz4Y/fGcDsaHj1m4TLiMcfWcli1/img.png?width=400&amp;amp;height=400&amp;amp;face=0_0_400_400&quot;&gt;&lt;a href=&quot;https://learn.microsoft.com/ko-kr/dotnet/api/system.threading.waithandle.waitone?view=net-7.0&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://learn.microsoft.com/ko-kr/dotnet/api/system.threading.waithandle.waitone?view=net-7.0&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bcSDWG/hyRcDskz4Y/fGcDsaHj1m4TLiMcfWcli1/img.png?width=400&amp;amp;height=400&amp;amp;face=0_0_400_400');&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;WaitHandle.WaitOne 메서드 (System.Threading)&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;현재 WaitHandle이(가) 신호를 받을 때까지 현재 스레드를 차단합니다.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;learn.microsoft.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. Task.Delay() 함수&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 함수는 &lt;b&gt;비동기 함수&lt;/b&gt;로, &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;Task&lt;/span&gt;&lt;/code&gt;와 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;async/await&lt;/span&gt;&lt;/code&gt; 키워드와 같이 설명하기에는 내용이 너무 많으므로, &lt;code&gt;&lt;span class=&quot;token function&quot;&gt;Delay()&lt;/span&gt;&lt;/code&gt; 함수에 대해서만 다루겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본적으로 해당 함수의 형태는 다음과 같습니다. 인자로 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;밀리미터 시간&lt;/span&gt;&lt;/code&gt;을 입력하는 것이 모두 비슷합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1673164604045&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public static System.Threading.Tasks.Task Delay (int millisecondsDelay);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드 예시는 다음과 같습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1673164644560&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine($&quot;{DateTime.Now.ToString(&quot;T&quot;)} Wait 시작!&quot;);
            Task.Delay(5000).Wait();
            Console.WriteLine($&quot;{DateTime.Now.ToString(&quot;T&quot;)} Wait 종료!&quot;);
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;&lt;span class=&quot;token function&quot;&gt;Task.Delay().Wait()&lt;/span&gt;&lt;/code&gt;를 사용하면 해당 코드 부분에서 설정된 시간만큼 지연됩니다. 해당 함수의 MSDN 문서는 아래 링크를 참고하세요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://learn.microsoft.com/ko-kr/dotnet/api/system.threading.tasks.task.delay?view=net-7.0&quot;&gt;https://learn.microsoft.com/ko-kr/dotnet/api/system.threading.tasks.task.delay?view=net-7.0&lt;/a&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1673165161733&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;Task.Delay 메서드 (System.Threading.Tasks)&quot; data-og-description=&quot;시간 지연 후 완료되는 작업을 만듭니다.&quot; data-og-host=&quot;learn.microsoft.com&quot; data-og-source-url=&quot;https://learn.microsoft.com/ko-kr/dotnet/api/system.threading.tasks.task.delay?view=net-7.0&quot; data-og-url=&quot;https://learn.microsoft.com/ko-kr/dotnet/api/system.threading.tasks.task.delay?view=net-7.0&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/ZSIeX/hyRcImZRlx/xbkbVy6XdB01pvVf7uG2v1/img.png?width=400&amp;amp;height=400&amp;amp;face=0_0_400_400&quot;&gt;&lt;a href=&quot;https://learn.microsoft.com/ko-kr/dotnet/api/system.threading.tasks.task.delay?view=net-7.0&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://learn.microsoft.com/ko-kr/dotnet/api/system.threading.tasks.task.delay?view=net-7.0&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/ZSIeX/hyRcImZRlx/xbkbVy6XdB01pvVf7uG2v1/img.png?width=400&amp;amp;height=400&amp;amp;face=0_0_400_400');&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;Task.Delay 메서드 (System.Threading.Tasks)&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;시간 지연 후 완료되는 작업을 만듭니다.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;learn.microsoft.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;정리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각 지연 함수의 인자로 밀리미터 시간을 넣어 사용한다는 측면에서는 모두 동작이 동일해 보입니다. 그럼 어느 상황에서 어떻게 사용해야 하는 걸까요?&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. 대략적인 시간으로 지연하고 싶을 때&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;&lt;span class=&quot;token function&quot;&gt;Sleep()&lt;/span&gt;&lt;/code&gt; 함수는 높은 정밀도를 갖고 있지 않습니다. 하지만 초 단위 이상으로 대략적인 지연이 필요하거나 CPU 부하를 억제하기 위함이라면 &lt;code&gt;&lt;span class=&quot;token function&quot;&gt;Sleep()&lt;/span&gt;&lt;/code&gt; 함수를 사용합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. 비동기적으로 시퀀스에 따라 지연하고 싶을 때&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;제어를 위한 시퀀스 루프 내에서 동기화를 위한 지연이 필요하다면 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;WaitHandle&lt;/span&gt;&lt;/code&gt;을 사용합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어, 외부에서 전기적 신호가 입력되면 스테이지를 이동해야 하는 상황을 가정하겠습니다. 만약, 시퀀스 루프 내에 &lt;code&gt;&lt;span class=&quot;token function&quot;&gt;Sleep()&lt;/span&gt;&lt;/code&gt;을 사용하면 지정된 시간만큼 블러킹 되어 응답이 늦어질 수 있습니다. 하지만 &lt;code&gt;&lt;span class=&quot;token function&quot;&gt;WaitHandle.WaitOne()&lt;/span&gt;&lt;/code&gt;을 사용한다면 이벤트가 Set이 되어 즉각 반응할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;물론 이 예시도 여러 조건에 따라 적합하냐는 따져봐야 하지만, 기본적으로 &lt;code&gt;&lt;span class=&quot;token function&quot;&gt;Sleep()&lt;/span&gt;&lt;/code&gt;과 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;WaitHandle&lt;/span&gt;&lt;/code&gt; 중 어느 것을 사용할 것인지 판단하는 기준이 될 수 있습니다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;참고 자료&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://blog.rogatnev.net/posts/2017/10/Sleep-well.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://blog.rogatnev.net/posts/2017/10/Sleep-well.html&lt;/a&gt;&lt;/p&gt;</description>
      <category>Programming/.Net</category>
      <category>.net</category>
      <author>❤ </author>
      <guid isPermaLink="true">https://luckygg.tistory.com/387</guid>
      <comments>https://luckygg.tistory.com/387#entry387comment</comments>
      <pubDate>Mon, 9 Jan 2023 21:30:29 +0900</pubDate>
    </item>
    <item>
      <title>[Wireshark] PcapPlusPlus로 실시간 패킷 감지하기(예제 포함)</title>
      <link>https://luckygg.tistory.com/386</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;PcapPlusPlus를 사용하기 위한 준비 단계는 아래 링크를 참고하세요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://luckygg.tistory.com/385&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;[Wireshark] Visual Studio에서 PcapPlusPlus 사용을 위한 준비 단계와 예제 코드 실행하기&lt;/a&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;예제 프로젝트 목표&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;본문의 예제 프로젝트의 목표는 다음과 같습니다. 항목 별로 차근차근 구현해 보겠습니다.&lt;/p&gt;
&lt;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;해당 패킷을 pcapng 파일로 저장하기&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. 네트워크 어댑터 목록 얻기&lt;/h3&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;643&quot; data-origin-height=&quot;331&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/o8FoW/btrVaSFywjv/fS2efNXkqkhjhTMC3e1WN0/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/o8FoW/btrVaSFywjv/fS2efNXkqkhjhTMC3e1WN0/img.webp&quot; data-alt=&quot;와이어샤크의 캡쳐 목록&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/o8FoW/btrVaSFywjv/fS2efNXkqkhjhTMC3e1WN0/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fo8FoW%2FbtrVaSFywjv%2FfS2efNXkqkhjhTMC3e1WN0%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; alt=&quot;와이어샤크의-캡쳐-목록&quot; loading=&quot;lazy&quot; width=&quot;450&quot; height=&quot;232&quot; data-origin-width=&quot;643&quot; data-origin-height=&quot;331&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;PcapPlusPlus로 네트워크 목록을 얻는 방법은 아주 쉽습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1672564670244&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;PcapLiveDevice.h&amp;gt;
#include &amp;lt;PcapLiveDeviceList.h&amp;gt;

std::cout &amp;lt;&amp;lt; &quot;===== Device List =====&quot; &amp;lt;&amp;lt; std::endl;
int index = 0;
//auto 타입은 std::vector&amp;lt;pcpp::PcapLiveDevice*&amp;gt; 입니다.	
auto list = pcpp::PcapLiveDeviceList::getInstance().getPcapLiveDevicesList();
for (const auto&amp;amp; dev : list)
{
	std::cout &amp;lt;&amp;lt; &quot;[&quot; &amp;lt;&amp;lt; index++ &amp;lt;&amp;lt; &quot;] &quot; &amp;lt;&amp;lt; dev-&amp;gt;getDesc() &amp;lt;&amp;lt; std::endl;
}&lt;/code&gt;&lt;/pre&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;631&quot; data-origin-height=&quot;228&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cy0dIL/btrU1NsfSUT/L3V0RAnpxpc6GhdJ86QcjK/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cy0dIL/btrU1NsfSUT/L3V0RAnpxpc6GhdJ86QcjK/img.webp&quot; data-alt=&quot;PcapPlusPlus로 얻어진 네트워크 목록&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cy0dIL/btrU1NsfSUT/L3V0RAnpxpc6GhdJ86QcjK/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcy0dIL%2FbtrU1NsfSUT%2FL3V0RAnpxpc6GhdJ86QcjK%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; alt=&quot;PcapPlusPlus로-얻어진-네트워크-목록&quot; loading=&quot;lazy&quot; width=&quot;631&quot; height=&quot;228&quot; data-origin-width=&quot;631&quot; data-origin-height=&quot;228&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;PcapPlusPlus로 얻어진 네트워크 목록&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. 어댑터 열고 닫기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;목록에서 얻어진 &lt;code&gt;&lt;span class=&quot;token function&quot;&gt;PcapLiveDevice&lt;/span&gt;&lt;/code&gt; 객체의 &lt;code&gt;&lt;span class=&quot;token function-name&quot;&gt;open()&lt;/span&gt;&lt;/code&gt; 함수로 어댑터를 열 수 있습니다. 만약, 타임아웃이나 버퍼 크기, 무차별모드(Promiscuous mode) 등을 설정하기 원한다면, &lt;code&gt;&lt;span class=&quot;token function&quot;&gt;DeviceConfiguration&lt;/span&gt;&lt;/code&gt;을 인자로 넘겨 설정과 동시에 열 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1672565802561&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;pcpp::PcapLiveDevice* dev;
//Select capture device
dev-&amp;gt;open();
//or
pcpp::PcapLiveDevice::DeviceConfiguration config;
config.mode = pcpp::PcapLiveDevice::DeviceMode::Promiscuous;
config.packetBufferTimeoutMs = 1000;
dev-&amp;gt;open(config);&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;code&gt;&lt;span class=&quot;token function-name&quot;&gt;close()&lt;/span&gt;&lt;/code&gt;를 호출하여 닫을 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1672566053014&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;dev-&amp;gt;close();&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. 캡처 시작하고 멈추기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어댑터를 열었다면, 패킷을 획득하기 위해 캡처 시작을 해야 합니다. 캡처를 시작하는 함수는 &lt;code&gt;&lt;span class=&quot;token function-name&quot;&gt;startCapture()&lt;/span&gt;&lt;/code&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;799&quot; data-origin-height=&quot;612&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bgGF4v/btrU36EOLjN/C3ROKVU8EqCtdPex5mYo5K/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bgGF4v/btrU36EOLjN/C3ROKVU8EqCtdPex5mYo5K/img.webp&quot; data-alt=&quot;startCapture 기본 함수&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bgGF4v/btrU36EOLjN/C3ROKVU8EqCtdPex5mYo5K/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbgGF4v%2FbtrU36EOLjN%2FC3ROKVU8EqCtdPex5mYo5K%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; alt=&quot;startCapture-기본-함수&quot; loading=&quot;lazy&quot; width=&quot;799&quot; height=&quot;612&quot; data-origin-width=&quot;799&quot; data-origin-height=&quot;612&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;startCapture 기본 함수&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;캡처를 정지하려면 간단하게 &lt;code&gt;&lt;span class=&quot;token function-name&quot;&gt;stopCapture()&lt;/span&gt;&lt;/code&gt;를 호출하면 됩니다.&lt;/p&gt;
&lt;pre id=&quot;code_1672566579799&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//어댑터에서 패킷이 획득될 때 콜백 함수가 호출됩니다.
void packetArrives(pcpp::RawPacket* rawPacket, pcpp::PcapLiveDevice* dev, void* cookie)
{
	//rawPacket에는 획득된 정보가 담겨있습니다.
}

//...
dev-&amp;gt;startCapture(packetArrives, nullptr);

//...
dev-&amp;gt;stopCapture();&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;code&gt;&lt;span class=&quot;token function&quot;&gt;RawPacket&lt;/span&gt;&lt;/code&gt;에는 와이어샤크에서 보이는 모든 정보가 동일하게 담겨있습니다. &lt;code&gt;&lt;span class=&quot;token function&quot;&gt;pcpp::Packet&lt;/span&gt;&lt;/code&gt; 객체로 변환하여 각 레이어의 정보를 얻을 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1672566780776&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;void packetArrives(pcpp::RawPacket* rawPacket, pcpp::PcapLiveDevice* dev, void* cookie)
{
    pcpp::Packet packet(rawPacket);
}&lt;/code&gt;&lt;/pre&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;패킷의 총길이&lt;/li&gt;
&lt;li&gt;프로토콜 타입&lt;/li&gt;
&lt;li&gt;Source IP, Destination IP Address 및 Port&lt;/li&gt;
&lt;li&gt;체크섬 계산&lt;/li&gt;
&lt;li&gt;Payload 데이터&lt;/li&gt;
&lt;li&gt;TCP Flag 등&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 외에 직접 데이터 편집이 필요하다면, Data Pointer를 얻어 확인할 수 있습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;5. 패킷 기록하기(Dump)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PcapPlusPlus도 와이어샤크처럼 캡처된 패킷을 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;pcap&lt;/span&gt;&lt;/code&gt; 또는 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;pcapng&lt;/span&gt;&lt;/code&gt; 파일로 저장할 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1672573014019&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;PcapFileDevice.h&amp;gt;

pcpp::PcapFileWriterDevice dumper(&quot;test.pcapng&quot;);
dumper.open();

//...
dumper.writePacket(rawPacket);
//...

dumper.close();&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약, 이미 저장된 파일을 불러와 기록된 패킷을 꺼내고 싶다면 다음의 예제 코드를 참고하세요. pcap과 pcapng 파일의 읽고 쓰기 예시입니다.&lt;/p&gt;
&lt;pre id=&quot;code_1672574846997&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//pcap 파일 불러오기
pcpp::PcapFileReaderDevice pcapReader(&quot;input.pcap&quot;);
pcapReader.open();

//pcapng 파일 생성하기
pcpp::PcapNgFileWriterDevice pcapNgWriter(&quot;output.pcapng&quot;);
pcapNgWriter.open();

//raw packet 객체
pcpp::RawPacket rawPacket;

//pcap 파일의 패킷을 읽어들인 후 pcapng 파일에 쓰기
while (pcapReader-&amp;gt;getNextPacket(rawPacket)) {
  pcapNgWriter.writePacket(rawPacket);
}

pcapNgReader.close();
pcapNgWriter.close();&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;본문의 예제 프로그램은 네트워크 어댑터에 연결한 후 100개의 패킷을 획득하고 pcapng 파일로 저장하는 동작을 보여줍니다. 용량 문제로, 첨부된 파일에는 npcap과 pcapplusplus 라이브러리 파일은 제외하고 프로젝트 파일만 있습니다.&lt;/p&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/cjUv8B/btrUYPYvPX6/VQVCzzrer0g6TkLo1Hoekk/ExamPcapPlusPlus.zip?attach=1&amp;amp;knm=tfile.zip&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;ExamPcapPlusPlus.zip&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;size&quot;&gt;0.00MB&lt;/div&gt;
&lt;/div&gt;
  &lt;/a&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;799&quot; data-origin-height=&quot;588&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cBoeTe/btrUYQQCDAC/cAgKRpDTPUhjONgoxPsEmk/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cBoeTe/btrUYQQCDAC/cAgKRpDTPUhjONgoxPsEmk/img.webp&quot; data-alt=&quot;예제 프로그램 실행 화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cBoeTe/btrUYQQCDAC/cAgKRpDTPUhjONgoxPsEmk/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcBoeTe%2FbtrUYQQCDAC%2FcAgKRpDTPUhjONgoxPsEmk%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; alt=&quot;예제-프로그램-실행-화면&quot; loading=&quot;lazy&quot; width=&quot;600&quot; height=&quot;441&quot; data-origin-width=&quot;799&quot; data-origin-height=&quot;588&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;예제 프로그램 실행 화면&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;정리하며&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;본문에서는 기본적인 사용 방법을 다뤄봤습니다. Pcap++ 라이브러리를 사용하면 패킷 캡처 라이브러리를 자세히 모르더라도 아주 쉽게 접근할 수 있다는 것을 알게 됐습니다. 필요한 기능만 잘 구현한다면 와이어샤크 못지않은 패킷 모니터링이 가능하겠죠?&lt;/p&gt;</description>
      <category>Programming/Network</category>
      <category>network</category>
      <category>wireshark</category>
      <author>❤ </author>
      <guid isPermaLink="true">https://luckygg.tistory.com/386</guid>
      <comments>https://luckygg.tistory.com/386#entry386comment</comments>
      <pubDate>Wed, 4 Jan 2023 22:29:00 +0900</pubDate>
    </item>
    <item>
      <title>[Wireshark] Visual Studio에서 PcapPlusPlus 사용을 위한 준비 단계와 예제 코드 실행하기</title>
      <link>https://luckygg.tistory.com/385</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;패킷 캡처를 위한 라이브러리인 Pcap++의 전반적인 소개는 아래 링크를 참고하세요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://luckygg.tistory.com/384&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;[Wireshark] 네트워크 패킷 모니터링은 PcapPlusPlus로 쉽게!&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1672408223292&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;[Wireshark] 네트워크 패킷 모니터링은 PcapPlusPlus로 쉽게!&quot; data-og-description=&quot;Pcap++ 라이브러리 네트워크 패킷 감지를 위한 라이브러리로는 Unix의 libpcap, Windows의 Npcap과 WinPcap이 대표적입니다. PcapPlusPlus(Pcap++)는 네트워크 패킷을 감지하고 파싱하기 위한 멀티 플랫폼 C++ 라&quot; data-og-host=&quot;luckygg.tistory.com&quot; data-og-source-url=&quot;https://luckygg.tistory.com/384&quot; data-og-url=&quot;https://luckygg.tistory.com/384&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/YjJwv/hyQ6VFabQK/uvP4lbX46jBp6mBeGzCkmK/img.jpg?width=800&amp;amp;height=418&amp;amp;face=0_0_800_418,https://scrap.kakaocdn.net/dn/sGqMA/hyQ5AvRCFN/0xKkxjywt0U7P5G5OmW6j1/img.jpg?width=800&amp;amp;height=418&amp;amp;face=0_0_800_418&quot;&gt;&lt;a href=&quot;https://luckygg.tistory.com/384&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://luckygg.tistory.com/384&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/YjJwv/hyQ6VFabQK/uvP4lbX46jBp6mBeGzCkmK/img.jpg?width=800&amp;amp;height=418&amp;amp;face=0_0_800_418,https://scrap.kakaocdn.net/dn/sGqMA/hyQ5AvRCFN/0xKkxjywt0U7P5G5OmW6j1/img.jpg?width=800&amp;amp;height=418&amp;amp;face=0_0_800_418');&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;[Wireshark] 네트워크 패킷 모니터링은 PcapPlusPlus로 쉽게!&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Pcap++ 라이브러리 네트워크 패킷 감지를 위한 라이브러리로는 Unix의 libpcap, Windows의 Npcap과 WinPcap이 대표적입니다. PcapPlusPlus(Pcap++)는 네트워크 패킷을 감지하고 파싱하기 위한 멀티 플랫폼 C++ 라&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;luckygg.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;준비 단계&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Pcap++를 사용하기 위해서는 몇 가지 준비 단계가 있습니다. 다운로드가 필요한 파일은 링크를 추가했으니 해당 링크를 참고하세요.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. Visual Studio 버전&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Pcap++는 22.11 버전 기준으로 Visual Studio 2015, 2017, 2019를 지원합니다. 이에 맞는 Visual Studio를 준비합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. WinPcap or Npcap SDK&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a title=&quot;WinPcap 다운로드 링크&quot; href=&quot;https://www.winpcap.org/devel.htm&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;WinPcap&lt;/a&gt; 또는 &lt;a title=&quot;Npcap 다운로드 링크&quot; href=&quot;https://npcap.com/#download&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Npcap&lt;/a&gt; SDK를 준비합니다. WinPcap은 지원이 끝났으므로, 본문에서는 Npcap SDK 1.13을 사용했습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. Visual Studio 2010 재배포 패키지&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a title=&quot;Visual Studio 재배포 패키지 다운로드 링크&quot; href=&quot;https://learn.microsoft.com/en-US/cpp/windows/latest-supported-vc-redist?view=msvc-170&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Microsoft Visual C++ 2010 재배포 패키지&lt;/a&gt;를 설치합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4. Pcap++ 라이브러리 및 예제 프로젝트&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a title=&quot;Pcap++ 다운로드 링크&quot; href=&quot;https://github.com/seladb/PcapPlusPlus/releases/tag/v22.11&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;PcapPlusPlus Github&lt;/a&gt;에서 Visual Studio 버전에 맞는 파일을 다운로드합니다. Release 페이지에서 스크롤을 조금 내리면 각 개발환경에 맞는 파일이 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;799&quot; data-origin-height=&quot;569&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bpO8DZ/btrU1N5NtAU/BWKjBzkBZkfz7tr7Vu51vK/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bpO8DZ/btrU1N5NtAU/BWKjBzkBZkfz7tr7Vu51vK/img.webp&quot; data-alt=&quot;PcapPlusPlus Release 화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bpO8DZ/btrU1N5NtAU/BWKjBzkBZkfz7tr7Vu51vK/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbpO8DZ%2FbtrU1N5NtAU%2FBWKjBzkBZkfz7tr7Vu51vK%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; alt=&quot;PcapPlusPlus-Release-화면&quot; loading=&quot;lazy&quot; width=&quot;799&quot; height=&quot;569&quot; data-origin-width=&quot;799&quot; data-origin-height=&quot;569&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;PcapPlusPlus Release 화면&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;799&quot; data-origin-height=&quot;493&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/FCRwy/btrUWSfXaoe/wUBKqzqiLTIabWdSgqkRuk/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/FCRwy/btrUWSfXaoe/wUBKqzqiLTIabWdSgqkRuk/img.webp&quot; data-alt=&quot;개발환경 별 라이브러리 파일&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/FCRwy/btrUWSfXaoe/wUBKqzqiLTIabWdSgqkRuk/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FFCRwy%2FbtrUWSfXaoe%2FwUBKqzqiLTIabWdSgqkRuk%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; alt=&quot;개발환경-별-라이브러리-파일&quot; loading=&quot;lazy&quot; width=&quot;799&quot; height=&quot;493&quot; data-origin-width=&quot;799&quot; data-origin-height=&quot;493&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;개발환경 별 라이브러리 파일&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;예제 프로젝트 실행하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;본문의 개발 환경은 &lt;b&gt;Windows&lt;/b&gt;와 &lt;b&gt;Visual Studio 2019&lt;/b&gt;를 사용했습니다. 위 Release 페이지에서 &lt;i&gt;pcapplusplus-22.11-windows-vs2019.zip&lt;/i&gt;을 다운로드합니다. 그리고 압축을 해제한 후 &lt;i&gt;pcapplusplus-22.11-windows-vs2019\ExampleProject&lt;/i&gt; 경로를 보면 &lt;b&gt;PcapPlusPlusPropertySheet.props&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;376&quot; data-origin-height=&quot;251&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/KORKz/btrU1N5NtDu/WwbIN1BEEczdnjqxjbS53k/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/KORKz/btrU1N5NtDu/WwbIN1BEEczdnjqxjbS53k/img.webp&quot; data-alt=&quot;예제 프로젝트 파일 구성&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/KORKz/btrU1N5NtDu/WwbIN1BEEczdnjqxjbS53k/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FKORKz%2FbtrU1N5NtDu%2FWwbIN1BEEczdnjqxjbS53k%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; alt=&quot;예제-프로젝트-파일-구성&quot; loading=&quot;lazy&quot; width=&quot;376&quot; height=&quot;251&quot; data-origin-width=&quot;376&quot; data-origin-height=&quot;251&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;예제 프로젝트 파일 구성&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p 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;799&quot; data-origin-height=&quot;474&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cMXJmp/btrUSz2FWeX/ZmkKBo3JFaRo2344mkUNgK/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cMXJmp/btrUSz2FWeX/ZmkKBo3JFaRo2344mkUNgK/img.webp&quot; data-alt=&quot;속성 시트 변경하기&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cMXJmp/btrUSz2FWeX/ZmkKBo3JFaRo2344mkUNgK/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcMXJmp%2FbtrUSz2FWeX%2FZmkKBo3JFaRo2344mkUNgK%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; alt=&quot;속성-시트-변경하기&quot; loading=&quot;lazy&quot; width=&quot;799&quot; height=&quot;474&quot; data-origin-width=&quot;799&quot; data-origin-height=&quot;474&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;속성 시트 변경하기&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 60px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style12&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 50%; text-align: center; height: 20px;&quot;&gt;&lt;b&gt;항목&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 50%; text-align: center; height: 20px;&quot;&gt;&lt;b&gt;설명&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;PcapPlusPlusHome&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;예제 코드가 위치한 경로&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;PcapSdkHome&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;준비단계 2에서 다운로드한 WinPcap 또는 Npcap SDK가 위치한 경로&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 저장한 후 ExampleProject.sln 파일을 실행하면 프로젝트가 정상적으로 로드됩니다. 만약, 경로가 다르면 빌드 중 에러가 발생하는데, 위와 같이 속성 시트를 변경하거나 직접 include, lib 경로를 수정해도 상관없습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;main.cpp&lt;/b&gt;의 예제 코드를 보면 다음과 같습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1672409197853&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;iostream&amp;gt;
#include &amp;lt;IPv4Layer.h&amp;gt;
#include &amp;lt;Packet.h&amp;gt;
#include &amp;lt;PcapFileDevice.h&amp;gt;

int main(int argc, char* argv[])
{
	// open a pcap file for reading
	pcpp::PcapFileReaderDevice reader(&quot;1_packet.pcap&quot;);
	if (!reader.open())
	{
		std::cerr &amp;lt;&amp;lt; &quot;Error opening the pcap file&quot; &amp;lt;&amp;lt; std::endl;
		return 1;
	}

	// read the first (and only) packet from the file
	pcpp::RawPacket rawPacket;
	if (!reader.getNextPacket(rawPacket))
	{
		std::cerr &amp;lt;&amp;lt; &quot;Couldn't read the first packet in the file&quot; &amp;lt;&amp;lt; std::endl;
		return 1;
	}

	// parse the raw packet into a parsed packet
	pcpp::Packet parsedPacket(&amp;amp;rawPacket);

	// verify the packet is IPv4
	if (parsedPacket.isPacketOfType(pcpp::IPv4))
	{
		// extract source and dest IPs
		pcpp::IPv4Address srcIP = parsedPacket.getLayerOfType&amp;lt;pcpp::IPv4Layer&amp;gt;()-&amp;gt;getSrcIPv4Address();
		pcpp::IPv4Address destIP = parsedPacket.getLayerOfType&amp;lt;pcpp::IPv4Layer&amp;gt;()-&amp;gt;getDstIPv4Address();

		// print source and dest IPs
		std::cout
			&amp;lt;&amp;lt; &quot;Source IP is '&quot; &amp;lt;&amp;lt; srcIP &amp;lt;&amp;lt; &quot;'; &quot;
			&amp;lt;&amp;lt; &quot;Dest IP is '&quot; &amp;lt;&amp;lt; destIP &amp;lt;&amp;lt; &quot;'&quot;
			&amp;lt;&amp;lt; std::endl;
	}

	// close the file
	reader.close();

	return 0;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드만 봐도 동작이 아주 간단합니다. &lt;i&gt;1_packet.pcap&lt;/i&gt; 파일을 불러온 후 packet을 읽어내고, IPv4 타입이라면 Source IP와 Destination IP를 출력하는 것이 다입니다. 한번 실행해 볼까요?&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;799&quot; data-origin-height=&quot;423&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bHOs3T/btrU02hQjvV/7urkGJOVNuJNgM2pUpHIM0/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bHOs3T/btrU02hQjvV/7urkGJOVNuJNgM2pUpHIM0/img.webp&quot; data-alt=&quot;동작 결과&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bHOs3T/btrU02hQjvV/7urkGJOVNuJNgM2pUpHIM0/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbHOs3T%2FbtrU02hQjvV%2F7urkGJOVNuJNgM2pUpHIM0%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; alt=&quot;동작-결과&quot; loading=&quot;lazy&quot; width=&quot;799&quot; height=&quot;423&quot; data-origin-width=&quot;799&quot; data-origin-height=&quot;423&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;i&gt;Source IP is '10.0.0.138'; Dest IP is '10.0.0.1'&lt;/i&gt;이라는 문자열이 출력되어 있습니다. 와이어샤크로 &lt;i&gt;1_packet.pcap&lt;/i&gt; 파일을 열어보면, 실제로 Source IP와 Destination IP가 일치합니다. 즉, 잘 동작했다는 것을 알 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;559&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ebxyTb/btrU15Fhm6d/H21dQNlyXMk5a9ZU53klX1/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ebxyTb/btrU15Fhm6d/H21dQNlyXMk5a9ZU53klX1/img.webp&quot; data-alt=&quot;와이어샤크로 pcap 파일을 열어본 모습&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ebxyTb/btrU15Fhm6d/H21dQNlyXMk5a9ZU53klX1/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FebxyTb%2FbtrU15Fhm6d%2FH21dQNlyXMk5a9ZU53klX1%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; alt=&quot;와이어샤크로-pcap-파일을-열어본-모습&quot; loading=&quot;lazy&quot; width=&quot;800&quot; height=&quot;559&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;559&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;와이어샤크로 pcap 파일을 열어본 모습&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>Programming/Network</category>
      <category>network</category>
      <category>wireshark</category>
      <author>❤ </author>
      <guid isPermaLink="true">https://luckygg.tistory.com/385</guid>
      <comments>https://luckygg.tistory.com/385#entry385comment</comments>
      <pubDate>Mon, 2 Jan 2023 11:12:06 +0900</pubDate>
    </item>
    <item>
      <title>[Wireshark] 네트워크 패킷 모니터링은 PcapPlusPlus로 쉽게!</title>
      <link>https://luckygg.tistory.com/384</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;Pcap++ 라이브러리&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;588&quot; data-origin-height=&quot;119&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/uLywL/btrUYQ9UaKM/yvDeHof4PK7WB9WWYkCElK/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/uLywL/btrUYQ9UaKM/yvDeHof4PK7WB9WWYkCElK/img.webp&quot; data-alt=&quot;PcapPlusPlus&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/uLywL/btrUYQ9UaKM/yvDeHof4PK7WB9WWYkCElK/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FuLywL%2FbtrUYQ9UaKM%2FyvDeHof4PK7WB9WWYkCElK%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; alt=&quot;PcapPlusPlus&quot; loading=&quot;lazy&quot; width=&quot;588&quot; height=&quot;119&quot; data-origin-width=&quot;588&quot; data-origin-height=&quot;119&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;PcapPlusPlus&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;네트워크 패킷 감지를 위한 라이브러리로&lt;/u&gt;는 Unix의 &lt;b&gt;libpcap&lt;/b&gt;, Windows의 &lt;b&gt;Npcap&lt;/b&gt;과 &lt;b&gt;WinPcap&lt;/b&gt;이 대표적입니다. &lt;span&gt;&lt;b&gt;PcapPlusPlus(Pcap++)&lt;/b&gt;는 &lt;u&gt;네트워크 패킷을 감지하고 파싱하기 위한 멀티 플랫폼 C++ 라이브러리&lt;/u&gt;이며, libpcap, Npcap과 같은 널리 사용되는 패킷 처리 엔진을 사용하기 쉽게 &lt;u&gt;C++ Wrapper&lt;/u&gt;로 제공하는 것입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;참고로, Windows의 WinPcap은 2013년을 마지막으로 더 이상 개발되지 않습니다. 이후로는 Npcap 라이브러리만 지원되며 이에 대한 내용은 아래 링크를 참고하시면 되겠습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;a href=&quot;https://npcap.com/vs-winpcap.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://npcap.com/vs-winpcap.html&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1672405785403&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;Npcap vs WinPcap&amp;quot;&quot; data-og-description=&quot;Docs Download Licensing Windows 11 WinPcap WinPcap has been the de facto standard library for packet capture and link-layer packet injection for over a decade. Many open source and commercial network tools use WinPcap for network access and filtering, but &quot; data-og-host=&quot;npcap.com&quot; data-og-source-url=&quot;https://npcap.com/vs-winpcap.html&quot; data-og-url=&quot;https://npcap.com/vs-winpcap.html&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://npcap.com/vs-winpcap.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://npcap.com/vs-winpcap.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;Npcap vs WinPcap&quot;&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Docs Download Licensing Windows 11 WinPcap WinPcap has been the de facto standard library for packet capture and link-layer packet injection for over a decade. Many open source and commercial network tools use WinPcap for network access and filtering, but&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;npcap.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;주요 특징&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Pcap++ 라이브러리의 주요 특징을 나열해 보겠습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;다양한 플랫폼 지원(Windows, Linux, Apple, FreeBSD, Android)&lt;/li&gt;
&lt;li&gt;빠른 속도와 적은 오버헤드(벤치마크 자료: &lt;a href=&quot;https://pcapplusplus.github.io/docs/benchmark&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://pcapplusplus.github.io/docs/benchmark&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;다양한 프로토콜 지원(목록: &lt;a href=&quot;https://pcapplusplus.github.io/docs/features#supported-network-protocols&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://pcapplusplus.github.io/docs/features#supported-network-protocols&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;PCAP 및 PCAPNG 파일 읽기/쓰기 지원&lt;/li&gt;
&lt;li&gt;Unlicense 라이선스&lt;/li&gt;
&lt;li&gt;Visual Studio 2015~2019 지원(지원 환경: &lt;a href=&quot;https://pcapplusplus.github.io/docs/platforms&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://pcapplusplus.github.io/docs/platforms&lt;/a&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;아래 그림은 특정 네트워크 어댑터에서 캡처되는 실시간 패킷을 보여주고 있습니다. 일반적으로는 Npcap 라이브러리를 사용하여 패킷을 직접 분석해야 하지만, Pcap++ 라이브러리를 사용하면 깊은 지식 없이 바로 패킷 분석이 가능합니다. 그만큼 개발 시간을 줄일 수 있는 장점이 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;418&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Vduhg/btrUTI58rbu/s57ju5baRB1lUiAxbaj981/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Vduhg/btrUTI58rbu/s57ju5baRB1lUiAxbaj981/img.webp&quot; data-alt=&quot;실시간 패킷 모니터링 예시&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Vduhg/btrUTI58rbu/s57ju5baRB1lUiAxbaj981/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FVduhg%2FbtrUTI58rbu%2Fs57ju5baRB1lUiAxbaj981%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; alt=&quot;실시간-패킷-모니터링-예시&quot; loading=&quot;lazy&quot; width=&quot;800&quot; height=&quot;418&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;418&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;실시간 패킷 모니터링 예시&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>Programming/Network</category>
      <category>network</category>
      <category>wireshark</category>
      <author>❤ </author>
      <guid isPermaLink="true">https://luckygg.tistory.com/384</guid>
      <comments>https://luckygg.tistory.com/384#entry384comment</comments>
      <pubDate>Fri, 30 Dec 2022 22:48:45 +0900</pubDate>
    </item>
    <item>
      <title>[C#] 솔루션 탐색기에서 Form이 사라지는 현상 해결 방법</title>
      <link>https://luckygg.tistory.com/383</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;Form이 사라지는 현상&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;C# WinForm 프로젝트를 사용하던 중 &lt;u&gt;Form이 사라지는 현상&lt;/u&gt;이 발생했습니다. 어떻게 사라진다는 건지 한번 보겠습니다. 아래 그림을 보면, &lt;u&gt;Form1.cs 왼쪽에 사각형 아이콘&lt;/u&gt;이 보입니다. 그런데 오른쪽과 같이 &lt;u&gt;C# 아이콘으로 변경&lt;/u&gt;되었습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;246&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/oK67G/btrUBaUFens/tYSe4bRHBvCCDUgPxY0mc0/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/oK67G/btrUBaUFens/tYSe4bRHBvCCDUgPxY0mc0/img.webp&quot; data-alt=&quot;솔루션 탐색기에서 아이콘이 변경된 모습&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/oK67G/btrUBaUFens/tYSe4bRHBvCCDUgPxY0mc0/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FoK67G%2FbtrUBaUFens%2FtYSe4bRHBvCCDUgPxY0mc0%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; alt=&quot;솔루션-탐색기에서-아이콘이-변경된-모습&quot; loading=&quot;lazy&quot; width=&quot;800&quot; height=&quot;246&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;246&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;이 상태에서 Form1.cs를 더블 클릭하면 디자인 탭이 보이지 않고 소스 코드만 보입니다. 심지어 이 상태에서는 소스 코드 창에서 '&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;799&quot; data-origin-height=&quot;178&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/CTesh/btrUumoHOUZ/69ycv3pOGlPzIgfnoMcfQK/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/CTesh/btrUumoHOUZ/69ycv3pOGlPzIgfnoMcfQK/img.webp&quot; data-alt=&quot;디자이너 보기 메뉴가 사라진 모습&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/CTesh/btrUumoHOUZ/69ycv3pOGlPzIgfnoMcfQK/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FCTesh%2FbtrUumoHOUZ%2F69ycv3pOGlPzIgfnoMcfQK%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; alt=&quot;디자이너-보기-메뉴가-사라진-모습&quot; loading=&quot;lazy&quot; width=&quot;799&quot; height=&quot;178&quot; data-origin-width=&quot;799&quot; data-origin-height=&quot;178&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;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;해결 방법&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제가 있는 프로젝트의 &lt;u&gt;csproj 파일을 텍스트 편집기(메모장)로 엽니다&lt;/u&gt;. 그리고 문제가 있는 파일(본문은 Form1.cs)을 찾습니다. 이 파일이 정상이라면 파일 이름 아래에 &lt;b&gt;Form 속성&lt;/b&gt;이 있어야 합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1671975192491&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;SubType&amp;gt;Form&amp;lt;/SubType&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 이 속성이 빠져있으면 본문과 같은 문제가 생기는 것입니다. 결론은, 아래와 같이 &lt;u&gt;파일 이름 아래에 Form 속성을 추가해주면 바로 해결&lt;/u&gt;됩니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;167&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dNa6YV/btrUvWpFpHd/sA92CPIhH13lkaFxvJMuFK/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dNa6YV/btrUvWpFpHd/sA92CPIhH13lkaFxvJMuFK/img.webp&quot; data-alt=&quot;Form 속성을 추가한 모습&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dNa6YV/btrUvWpFpHd/sA92CPIhH13lkaFxvJMuFK/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdNa6YV%2FbtrUvWpFpHd%2FsA92CPIhH13lkaFxvJMuFK%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; alt=&quot;Form-속성을-추가한-모습&quot; loading=&quot;lazy&quot; width=&quot;800&quot; height=&quot;167&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;167&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Form 속성을 추가한 모습&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제가 발생한 이유는 모르겠으나, 이렇게 간단하게 해결이 가능합니다. 괜한 시간 낭비하지 마세요~!&lt;/p&gt;</description>
      <category>Programming/Visual Studio</category>
      <category>.net</category>
      <category>Visual Studio</category>
      <author>❤ </author>
      <guid isPermaLink="true">https://luckygg.tistory.com/383</guid>
      <comments>https://luckygg.tistory.com/383#entry383comment</comments>
      <pubDate>Tue, 27 Dec 2022 21:36:49 +0900</pubDate>
    </item>
    <item>
      <title>손목과 어깨 통증 보호를 위한 새로운 키보드, 마우스 배치 방법</title>
      <link>https://luckygg.tistory.com/381</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;직업병 관리, 1년 동안 효과는?&lt;/h2&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://luckygg.tistory.com/347&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;개발자 직업병 거북목과 손목 통증 관리, 저만의 노하우를 공개합니다&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1670757520374&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;개발자 직업병 거북목과 손목 통증 관리, 저만의 노하우를 공개합니다&quot; data-og-description=&quot;본문 중간에 실제로 구입한 제품이 공개됩니다. 광고가 아니며 공유 차원에서 작성한 것이니 참고하세요. 본문의 건강 지식 관련 내용은 출처를 남겼으며, 자신의 건강 상태는 반드시 전문 병원&quot; data-og-host=&quot;luckygg.tistory.com&quot; data-og-source-url=&quot;https://luckygg.tistory.com/347&quot; data-og-url=&quot;https://luckygg.tistory.com/347&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bBMVBL/hyQRQK9eOl/Np1YJcSUz8afuEgHwkP3h0/img.png?width=800&amp;amp;height=299&amp;amp;face=0_0_800_299,https://scrap.kakaocdn.net/dn/dQWsm8/hyQQrlTb9L/kwZY5GGGepLCZes0Mm8RM1/img.png?width=800&amp;amp;height=299&amp;amp;face=0_0_800_299,https://scrap.kakaocdn.net/dn/c3bySC/hyQQuCW3Wf/mTVmgNty4AzhD4Nf7JGbjk/img.png?width=760&amp;amp;height=766&amp;amp;face=0_0_760_766&quot;&gt;&lt;a href=&quot;https://luckygg.tistory.com/347&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://luckygg.tistory.com/347&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bBMVBL/hyQRQK9eOl/Np1YJcSUz8afuEgHwkP3h0/img.png?width=800&amp;amp;height=299&amp;amp;face=0_0_800_299,https://scrap.kakaocdn.net/dn/dQWsm8/hyQQrlTb9L/kwZY5GGGepLCZes0Mm8RM1/img.png?width=800&amp;amp;height=299&amp;amp;face=0_0_800_299,https://scrap.kakaocdn.net/dn/c3bySC/hyQQuCW3Wf/mTVmgNty4AzhD4Nf7JGbjk/img.png?width=760&amp;amp;height=766&amp;amp;face=0_0_760_766');&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;개발자 직업병 거북목과 손목 통증 관리, 저만의 노하우를 공개합니다&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;본문 중간에 실제로 구입한 제품이 공개됩니다. 광고가 아니며 공유 차원에서 작성한 것이니 참고하세요. 본문의 건강 지식 관련 내용은 출처를 남겼으며, 자신의 건강 상태는 반드시 전문 병원&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;luckygg.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지난 1년 동안 증상은 어땠을까요? 이런저런 시도를 해봤지만 &lt;span style=&quot;color: #ee2323;&quot;&gt;결과적으로 몸 상태가 더 안 좋아졌습니다&lt;/span&gt; :)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;손목은 여전히 아프고, 이제는 가슴 근육과 견갑골까지 통증이 생겨버렸습니다. 역시나 병원에서 CT든 X-Ray든 어떤 검사를 해도 전~혀 문제가 없다고 하는군요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇다면, 결국 1년 동안 관리한 것은 모두 헛수고냐? 그건 아니라고 생각합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어쨌든 컴퓨터에 계속 앉아서 작업하는 시간은 꾸준하고, 이렇게나마 관리를 안 했으면 몸 상태는 지금보다 더 나빠지지 않았을까 생각합니다. 그래도 지난 1년 동안은 운동을 꾸준히 하고, 잦은 스트레칭과 휴식을 취하면서 관리에 힘썼습니다. 이런 노력조차 하지 않았다면 아마 지금보다 더 골병이 들지 않았을까 싶네요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아무튼, 잡설이 길었습니다. 지난 포스팅에서 언급한 키보드와 마우스를 사용하면서 단점이 확인되었고, 이번 포스팅을 통해 조금 더 개선된 방법을 공유하고자 합니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;키보드 두 개 활용 방법의 단점&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지난 포스팅에서 아래와 같이 키보드 두 개를 활용한 배치를 공유했었습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;342&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dSYb0S/btrUuYVdQrQ/5tDLeXrJCzK1KxHmt8F7Nk/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dSYb0S/btrUuYVdQrQ/5tDLeXrJCzK1KxHmt8F7Nk/img.webp&quot; data-alt=&quot;키보드 두 개를 활용한 방법&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dSYb0S/btrUuYVdQrQ/5tDLeXrJCzK1KxHmt8F7Nk/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdSYb0S%2FbtrUuYVdQrQ%2F5tDLeXrJCzK1KxHmt8F7Nk%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; alt=&quot;키보드-두-개를-활용한-방법&quot; loading=&quot;lazy&quot; width=&quot;800&quot; height=&quot;342&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;342&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;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;690&quot; data-origin-height=&quot;382&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/GRweU/btrUAbTcUyQ/SYmb7sbAHKy3V0IhJATlOk/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/GRweU/btrUAbTcUyQ/SYmb7sbAHKy3V0IhJATlOk/img.webp&quot; data-alt=&quot;어깨 너비의 양손 키보드&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/GRweU/btrUAbTcUyQ/SYmb7sbAHKy3V0IhJATlOk/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FGRweU%2FbtrUAbTcUyQ%2FSYmb7sbAHKy3V0IhJATlOk%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; alt=&quot;어깨-너비의-양손-키보드&quot; loading=&quot;lazy&quot; width=&quot;690&quot; height=&quot;382&quot; data-origin-width=&quot;690&quot; data-origin-height=&quot;382&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;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. 오른쪽 견갑골 통증&lt;/h3&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;마우스를 사용하기 위해 오른팔이 조금 더 뻗어진 채로 사용&lt;/b&gt;하다 보니, &lt;b&gt;오른쪽 견갑골이 당기는 통증&lt;/b&gt;이 생기더군요. 키보드만 사용하면 자세가 편한데, 마우스를 사용하려니 불편한 통증이 느껴집니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. 불편한 윈도우 자판 배열&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;윈도우 자판 배열을 변경하면, 사용하는 본인은 익숙해 질지 모르지만 다른 사람은 그렇지 않습니다. 즉, 개인 PC는 괜찮지만 누군가 같이 사용하는 공용 PC는 변경하면 안 되겠죠.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;회사 개인 PC는 변경했지만 집에 있는 PC는 와이프랑 같이 사용하다 보니 기본 값을 사용하고 있습니다. 게다가 회사 공용 PC까지 사용하다 보면 키보드 배열이 너무 헷갈리게 됩니다. 이도 저도 안 되는 상황이 되다 보니 결국 자판 배열은 기본 값을 사용하게 됐습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;새로운 키보드와 마우스 배치&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 단점을 겪고 난 후 키보드와 마우스를 새로 구입하여 배치를 변경했습니다. 사진을 볼까요?&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;359&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/noh0z/btrUuIx0hJN/KVFoKgkJdWkWXK9nk3fuJ0/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/noh0z/btrUuIx0hJN/KVFoKgkJdWkWXK9nk3fuJ0/img.webp&quot; data-alt=&quot;키보드 &amp;amp;amp; 마우스 배치 2.0&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/noh0z/btrUuIx0hJN/KVFoKgkJdWkWXK9nk3fuJ0/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fnoh0z%2FbtrUuIx0hJN%2FKVFoKgkJdWkWXK9nk3fuJ0%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; alt=&quot;키보드-&amp;amp;-마우스-배치-2.0&quot; loading=&quot;lazy&quot; width=&quot;800&quot; height=&quot;359&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;359&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;키보드 &amp;amp; 마우스 배치 2.0&lt;/figcaption&gt;
&lt;/figure&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;1. 분리형 키보드 Mistel MD770&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;분리형 키보드는 각 키보드가 USB 케이블로 연결됩니다. 그리고 PC로 연결되는 USB 케이블이 있습니다. 블루투스 모델도 있다고 하던데, 저는 유선 모델을 사용하고 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실, 애초에 분리형 키보드를 샀어도 되는 거지만 가격과 키보드 B의 위치 때문에 고민을 많이 했었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;웬만한 &lt;span style=&quot;color: #ee2323;&quot;&gt;분리형 키보드는 거의 20만 원으로 가격이 상당히 비싼 편&lt;/span&gt;입니다. 그런데 직장 동료가 사용하던 분리형 키보드를 저렴하게 판다기에, 좋은 금액으로 좋은 키보드를 얻게 되었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 &lt;b&gt;B 키의 위치가 상당히 걱정&lt;/b&gt;됐습니다. 제가 찾아본 분리형 키보드의 B 키는 모두 왼쪽에 있었는데요. 우리나라는 B(ㅠ) 키를 입력할 때 보통 오른손 손가락으로 타이핑을 하기 때문에, 분리형 키보드를 사용하면 계속 오른손 손가락이 저절로 책상 위를 치고 있더군요. 하지만 &lt;span style=&quot;color: #ee2323;&quot;&gt;걱정과 달리 바로 익숙해지더군요.&lt;/span&gt; 이제는 B 키를 누를 때 자연스럽게 왼손 손가락이 움직여 &lt;span style=&quot;color: #ee2323;&quot;&gt;불편함을 느끼진 못하고 있습니다&lt;/span&gt;. 혹시 B 키 때문에 분리형 키보드 구입에 고민이 된다면 괜한 고민이라고 말씀드릴 수 있겠습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. 트랙볼 마우스 켄싱턴 SlimBlade&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;트랙볼 마우스의 끝판 왕&lt;/b&gt;이라는 켄싱턴 SlimBlade입니다. 가격도 비싸고, 불편하면 끝내 적응하지 못하고 중고로 판매하게 된다고 하는군요. 다행히도, 저에게는 너무나 잘 맞아서 사용하고 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 마우스의 장점은 마우스 커서를 움직이기 위해 손가락만 사용하면 된다는 것입니다. 일반 마우스는 커서를 많이 움직일 때 팔이 같이 움직이게 되는데요. 트랙볼 마우스는 &lt;u&gt;손가락으로 트랙볼을 굴리면&lt;/u&gt; 되기 때문에 팔이 움직일 일이 없습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;게다가 &lt;u&gt;굴리는 속도에 따라 커서 속도가 결정&lt;/u&gt;되므로, 먼 거리의 커서를 움직일 때 더욱 편리합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 &lt;u&gt;트랙볼을 수평 방향으로 굴리면 화면의 스크롤을 제어&lt;/u&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;a href=&quot;https://luckygg.tistory.com/382&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;[제품 후기] 켄싱턴 트랙볼 마우스, 슬림 블레이드(Slim Blade) 사용 후기&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1671890012966&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;[제품 후기] 켄싱턴 트랙볼 마우스, 슬림 블레이드(Slim Blade) 사용 후기&quot; data-og-description=&quot;트랙볼 마우스? 볼 마우스? 트랙볼 마우스는 볼(Ball)을 굴려서 커서를 조작하는 마우스입니다. 그런데 볼을 굴린다고 해서 오래전에 사용하던 볼 마우스와는 다릅니다. 과거의 볼 마우스는 마우&quot; data-og-host=&quot;luckygg.tistory.com&quot; data-og-source-url=&quot;https://luckygg.tistory.com/382&quot; data-og-url=&quot;https://luckygg.tistory.com/382&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/LXqE3/hyQ1qFAFIh/xhFcaKMqAtGrT070dufkL1/img.png?width=346&amp;amp;height=379&amp;amp;face=0_0_346_379,https://scrap.kakaocdn.net/dn/pdbsx/hyQZJfHEef/TJd69p6bYJl6u7YK3WilS0/img.png?width=346&amp;amp;height=379&amp;amp;face=0_0_346_379,https://scrap.kakaocdn.net/dn/FyaU0/hyQ1fqxJ6J/guekPcTxKAVUxx7kTCKVQk/img.png?width=1580&amp;amp;height=536&amp;amp;face=0_0_1580_536&quot;&gt;&lt;a href=&quot;https://luckygg.tistory.com/382&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://luckygg.tistory.com/382&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/LXqE3/hyQ1qFAFIh/xhFcaKMqAtGrT070dufkL1/img.png?width=346&amp;amp;height=379&amp;amp;face=0_0_346_379,https://scrap.kakaocdn.net/dn/pdbsx/hyQZJfHEef/TJd69p6bYJl6u7YK3WilS0/img.png?width=346&amp;amp;height=379&amp;amp;face=0_0_346_379,https://scrap.kakaocdn.net/dn/FyaU0/hyQ1fqxJ6J/guekPcTxKAVUxx7kTCKVQk/img.png?width=1580&amp;amp;height=536&amp;amp;face=0_0_1580_536');&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;[제품 후기] 켄싱턴 트랙볼 마우스, 슬림 블레이드(Slim Blade) 사용 후기&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;트랙볼 마우스? 볼 마우스? 트랙볼 마우스는 볼(Ball)을 굴려서 커서를 조작하는 마우스입니다. 그런데 볼을 굴린다고 해서 오래전에 사용하던 볼 마우스와는 다릅니다. 과거의 볼 마우스는 마우&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;luckygg.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&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;h2 data-ke-size=&quot;size26&quot;&gt;정리하며&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컴퓨터를 장시간 사용한다면 아이템 투자에 아끼지 마세요. 편안한 작업 환경을 조성해야 건강하게 오래오래 일을 할 수 있습니다. 저는 부디 이번 투자로 오랫동안 사용할 수 있길 바라고 있습니다. 또 새로운 시도를 하게 되면 여러분께 공유하겠습니다.&lt;/p&gt;</description>
      <category>Life</category>
      <author>❤ </author>
      <guid isPermaLink="true">https://luckygg.tistory.com/381</guid>
      <comments>https://luckygg.tistory.com/381#entry381comment</comments>
      <pubDate>Sun, 25 Dec 2022 22:06:09 +0900</pubDate>
    </item>
    <item>
      <title>[제품 후기] 켄싱턴 트랙볼 마우스, 슬림 블레이드(Slim Blade) 사용 후기</title>
      <link>https://luckygg.tistory.com/382</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;트랙볼 마우스? 볼 마우스?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;트랙볼 마우스는 &lt;b&gt;볼(Ball)을 굴려서 커서를 조작하는 마우스&lt;/b&gt;입니다. 그런데 볼을 굴린다고 해서 오래전에 사용하던 볼 마우스와는 다릅니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;과거의 볼 마우스는 마우스 밑면에 볼이 살짝 튀어나와 있어서, 마우스를 움직이면 바닥에 닿은 볼의 움직임에 따라 커서가 조작되었습니다. 이와 달리 트랙볼 마우스는 볼이 많이 튀어나와 있고, 손가락으로 볼을 움직여 커서를 조작하는 방식입니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;트랙볼 마우스를 선택한 이유&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일반적인 마우스는 손으로 마우스를 쥐고 손목을 지탱하여 손가락만 살짝 폈다가 오므리면서 조작이 가능합니다. 그런데 마우스의 위치에 따라 팔이 펴지는 각도가 달라지고, 각도가 과하게 커지면 팔이 뻗어지게 됩니다. 이렇게 장시간 사용하다 보면 견갑골에 통증이 생기기도 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저는 그동안 마우스의 크기가 작은 것, 큰 것, 인체 공학, 유선, 무선 등 다양한 종류의 광마우스를 사용해 왔습니다. 하지만 결론은 손목은 아프지 않지만 견갑골이 너무 아프더군요. 마우스를 잡는 위치가 너무 오른쪽에 치우쳐 있어, 오랜 시간 작업을 하면 통증이 많이 느껴집니다. 그리고 마우스를 놓고 잠시 쉬면 통증이 바로 가라앉습니다. 즉, 자세에 문제가 있다는 것이 확실하더군요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 &lt;b&gt;어떻게 해야 팔을 뻗지 않고 올바른 자세를 유지&lt;/b&gt;한 채 키보드, 마우스 작업이 가능할까 고민하던 끝에 트랙볼 마우스를 선택하게 됐습니다. 트랙볼 마우스는 &lt;u&gt;마우스 자체의 이동이 필요하지 않고, 손가락으로만 볼을 굴리면 되기 때문에 불필요한 이동이 없다는 것&lt;/u&gt;이 장점입니다. 그래서 트랙볼 마우스의 끝판왕이라는 &lt;b&gt;켄싱턴 마우스&lt;/b&gt;를 선택하게 됐습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;켄싱턴 트랙볼 마우스, 슬림 블레이드&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마우스를 찾기 전까지는 몰랐지만, 켄싱턴 트랙볼 마우스는 정말 유명하더군요. &lt;b&gt;슬림 블레이드(Slim Blade)&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;346&quot; data-origin-height=&quot;379&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xRfUW/btrUuosWBm6/FfIAEkFjGs7RJne160KGkk/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xRfUW/btrUuosWBm6/FfIAEkFjGs7RJne160KGkk/img.webp&quot; data-alt=&quot;켄싱턴 트랙볼 마우스 SlimBlade&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xRfUW/btrUuosWBm6/FfIAEkFjGs7RJne160KGkk/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxRfUW%2FbtrUuosWBm6%2FFfIAEkFjGs7RJne160KGkk%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; alt=&quot;켄싱턴-트랙볼-마우스-SlimBlade&quot; loading=&quot;lazy&quot; width=&quot;346&quot; height=&quot;379&quot; data-origin-width=&quot;346&quot; data-origin-height=&quot;379&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;켄싱턴 트랙볼 마우스 SlimBlade&lt;/figcaption&gt;
&lt;/figure&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;손가락으로 볼을 살며시 밀면 마우스 커서가 부드럽게 이동합니다. 이동거리가 많으면 손가락에 힘을 줘 볼을 세게 굴리면 됩니다. 아래 동영상처럼, 두 손가락만으로도 쉽게 이동이 가능하니 &lt;u&gt;힘이 덜 들고 손의 부담이 덜해 편안&lt;/u&gt;합니다.&lt;/p&gt;
&lt;figure data-ke-type=&quot;video&quot; data-ke-style=&quot;alignCenter&quot; data-video-host=&quot;kakaotv&quot; data-video-url=&quot;https://tv.kakao.com/v/434540009&quot; data-video-thumbnail=&quot;https://scrap.kakaocdn.net/dn/bzcXWz/hyQZEyHoKx/tJPCwN8PyO68r8tAo4yMmK/img.jpg?width=1920&amp;amp;height=1080&amp;amp;face=0_0_1920_1080,https://scrap.kakaocdn.net/dn/dtwqhr/hyQ1nWmI17/kCLaoeWjyFbHRTApFdeZ50/img.jpg?width=1920&amp;amp;height=1080&amp;amp;face=0_0_1920_1080&quot; data-video-width=&quot;600&quot; data-video-height=&quot;338&quot; data-video-origin-width=&quot;860&quot; data-video-origin-height=&quot;484&quot; data-ke-mobilestyle=&quot;widthContent&quot; data-video-play-service=&quot;daum_tistory&quot;&gt;&lt;iframe src=&quot;https://play-tv.kakao.com/embed/player/cliplink/434540009?service=daum_tistory&quot; width=&quot;600&quot; height=&quot;338&quot; frameborder=&quot;0&quot; allowfullscreen=&quot;true&quot;&gt;&lt;/iframe&gt;
&lt;figcaption&gt;마우스 커서 이동하기&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음에는 미세 조정이 불편했으나, 적응되면 볼마우스가 훨씬 편안합니다. 이제는 일반 광마우스를 사용하면 광마우스가 더 불편한 느낌이 들 정도입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;충분한 4개의 버튼과 2개의 특수 버튼&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 마우스는 4개의 버튼이 2x2 배열로 배치되어 있습니다. &lt;u&gt;KensingtonWorks 소프트웨어&lt;/u&gt;를 사용하면 각 버튼에 키를 매핑하여 유용하게 사용할 수 있습니다. 위의 2개 버튼과 아래의 2개 버튼을 동시에 누르는 것도 매핑을 할 수 있습니다.&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://www.kensington.com/software/kensingtonworks/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://www.kensington.com/software/kensingtonworks/&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1671884626748&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;KensingtonWorks Customization Software&quot; data-og-description=&quot;KensingtonWorks&amp;trade; is a software for personalizing your experience with Kensington&amp;reg; trackballs, mice and presenters.&quot; data-og-host=&quot;www.kensington.com&quot; data-og-source-url=&quot;https://www.kensington.com/software/kensingtonworks/&quot; data-og-url=&quot;https://www.kensington.com/software/kensingtonworks/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bKHVzA/hyQ1fqvsvi/wL9NXCEWrlUsYH4LPhzPp1/img.jpg?width=991&amp;amp;height=600&amp;amp;face=0_0_991_600,https://scrap.kakaocdn.net/dn/nrrNs/hyQZScDzYu/4bfKRoIAYGqCIz8ePxkyYK/img.jpg?width=991&amp;amp;height=600&amp;amp;face=0_0_991_600,https://scrap.kakaocdn.net/dn/Kkip4/hyQZKTa2Om/QzWbqTG3FZP4Qrmchy3PLK/img.jpg?width=580&amp;amp;height=440&amp;amp;face=0_0_580_440&quot;&gt;&lt;a href=&quot;https://www.kensington.com/software/kensingtonworks/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.kensington.com/software/kensingtonworks/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bKHVzA/hyQ1fqvsvi/wL9NXCEWrlUsYH4LPhzPp1/img.jpg?width=991&amp;amp;height=600&amp;amp;face=0_0_991_600,https://scrap.kakaocdn.net/dn/nrrNs/hyQZScDzYu/4bfKRoIAYGqCIz8ePxkyYK/img.jpg?width=991&amp;amp;height=600&amp;amp;face=0_0_991_600,https://scrap.kakaocdn.net/dn/Kkip4/hyQZKTa2Om/QzWbqTG3FZP4Qrmchy3PLK/img.jpg?width=580&amp;amp;height=440&amp;amp;face=0_0_580_440');&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;KensingtonWorks Customization Software&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;KensingtonWorks&amp;trade; is a software for personalizing your experience with Kensington&amp;reg; trackballs, mice and presenters.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.kensington.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;525&quot; data-origin-height=&quot;544&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cEpKh4/btrUzmgfgFQ/iCgzilPPDKthqQK9GAEZk0/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cEpKh4/btrUzmgfgFQ/iCgzilPPDKthqQK9GAEZk0/img.webp&quot; data-alt=&quot;켄싱턴 키 매핑&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cEpKh4/btrUzmgfgFQ/iCgzilPPDKthqQK9GAEZk0/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcEpKh4%2FbtrUzmgfgFQ%2FiCgzilPPDKthqQK9GAEZk0%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; alt=&quot;켄싱턴-키-매핑&quot; loading=&quot;lazy&quot; width=&quot;525&quot; height=&quot;544&quot; data-origin-width=&quot;525&quot; data-origin-height=&quot;544&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;u&gt;일반적인 동작(왼쪽 클릭, 오른쪽 클릭, 뒤로 가기, 앞으로 가기)&lt;/u&gt;을 수행합니다. 저는 그보다 두 키를 동시에 누르는 기능이 특히나 마음에 듭니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래 두 키를 누르면 '&lt;b&gt;Ctrl + W&lt;/b&gt;'를 동작하도록 설정했습니다. 이는 일반적으로 '&lt;b&gt;창 닫기&lt;/b&gt;'를 수행합니다. 웹 브라우저의 탭을 닫거나 윈도우 탐색기의 창을 닫을 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 두 키를 누르면 '&lt;b&gt;Ctrl + Shift + T&lt;/b&gt;'를 동작하도록 설정했습니다. 이는 웹 브라우저의 '&lt;b&gt;닫힌 창 다시 열기&lt;/b&gt;'를 수행합니다. 실수로 창을 닫은 경우, 위 두 키를 누르면 다시 생성할 수 있어 아주 편리합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그동안 'Ctrl + W'와 'Ctrl + Shift + T' 키를 누르기 위해 왼쪽 손이 아팠는데, &lt;u&gt;손의 부담이 덜해졌습니다&lt;/u&gt;.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 아쉬운 건 버튼의 클릭감이 좋진 않습니다. 버튼을 누르면 투박한 소리가 나고, 촉감도 껍데기를 누르는 기분이 드는 단점이 있습니다.&lt;/p&gt;
&lt;figure data-ke-type=&quot;video&quot; data-ke-style=&quot;alignCenter&quot; data-video-host=&quot;kakaotv&quot; data-video-url=&quot;https://tv.kakao.com/v/434573995&quot; data-video-thumbnail=&quot;https://scrap.kakaocdn.net/dn/tdL72/hyQ1nXeUSw/FPW8Yuyo5WcuqdF4jKaA71/img.jpg?width=1920&amp;amp;height=1080&amp;amp;face=0_0_1920_1080,https://scrap.kakaocdn.net/dn/kOBi9/hyQ1dmOyfp/aO9be4EBZuxUOLg4cXRmpk/img.jpg?width=1920&amp;amp;height=1080&amp;amp;face=0_0_1920_1080&quot; data-video-width=&quot;600&quot; data-video-height=&quot;338&quot; data-video-origin-width=&quot;860&quot; data-video-origin-height=&quot;484&quot; data-ke-mobilestyle=&quot;widthContent&quot; data-video-play-service=&quot;daum_tistory&quot;&gt;&lt;iframe src=&quot;https://play-tv.kakao.com/embed/player/cliplink/434573995?service=daum_tistory&quot; width=&quot;600&quot; height=&quot;338&quot; frameborder=&quot;0&quot; allowfullscreen=&quot;true&quot;&gt;&lt;/iframe&gt;
&lt;figcaption&gt;버튼 클릭 소리&lt;/figcaption&gt;
&lt;/figure&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;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;scrolling.gif&quot; data-origin-width=&quot;400&quot; data-origin-height=&quot;400&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/YJKuL/btrUvX2LIQE/I2lNxkdvLp361ySu1FkAR1/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/YJKuL/btrUvX2LIQE/I2lNxkdvLp361ySu1FkAR1/img.gif&quot; data-alt=&quot;횡 이동으로 스크롤 수행&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/YJKuL/btrUvX2LIQE/I2lNxkdvLp361ySu1FkAR1/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/YJKuL/btrUvX2LIQE/I2lNxkdvLp361ySu1FkAR1/img.gif&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; alt=&quot;횡-이동으로-스크롤-수행&quot; loading=&quot;lazy&quot; width=&quot;400&quot; height=&quot;400&quot; data-filename=&quot;scrolling.gif&quot; data-origin-width=&quot;400&quot; data-origin-height=&quot;400&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;/p&gt;
&lt;figure data-ke-type=&quot;video&quot; data-ke-style=&quot;alignCenter&quot; data-video-host=&quot;kakaotv&quot; data-video-url=&quot;https://tv.kakao.com/v/434539935&quot; data-video-thumbnail=&quot;https://scrap.kakaocdn.net/dn/cWr20J/hyQZLkgUMo/dNoFvRRB5Ztip4JevSTwLk/img.jpg?width=1920&amp;amp;height=1080&amp;amp;face=0_0_1920_1080,https://scrap.kakaocdn.net/dn/beIsN4/hyQZNoPN8S/9mLX4OIWsVsBjdnJ09RMP1/img.jpg?width=1920&amp;amp;height=1080&amp;amp;face=0_0_1920_1080&quot; data-video-width=&quot;600&quot; data-video-height=&quot;338&quot; data-video-origin-width=&quot;860&quot; data-video-origin-height=&quot;484&quot; data-ke-mobilestyle=&quot;widthContent&quot; data-video-play-service=&quot;daum_tistory&quot;&gt;&lt;iframe src=&quot;https://play-tv.kakao.com/embed/player/cliplink/434539935?service=daum_tistory&quot; width=&quot;600&quot; height=&quot;338&quot; frameborder=&quot;0&quot; allowfullscreen=&quot;true&quot;&gt;&lt;/iframe&gt;
&lt;figcaption&gt;스크롤 동작하기&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;KensingtonWorks 소프트웨어&lt;/h3&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;options.png&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;271&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cepjfa/btrUBazQYWh/Ca1hWJLd76aBvaxXIcqJXK/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cepjfa/btrUBazQYWh/Ca1hWJLd76aBvaxXIcqJXK/img.webp&quot; data-alt=&quot;소프트웨어 옵션&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cepjfa/btrUBazQYWh/Ca1hWJLd76aBvaxXIcqJXK/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcepjfa%2FbtrUBazQYWh%2FCa1hWJLd76aBvaxXIcqJXK%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; alt=&quot;소프트웨어-옵션&quot; loading=&quot;lazy&quot; width=&quot;800&quot; height=&quot;271&quot; data-filename=&quot;options.png&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;271&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;소프트웨어 옵션&lt;/figcaption&gt;
&lt;/figure&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;볼 마우스를 사용할 때는 &lt;b&gt;관리가 필수&lt;/b&gt;입니다. &lt;u&gt;볼이 움직이면서 먼지가 쌓여 움직임이 자연스럽지 않아 지기 때문&lt;/u&gt;입니다. 아래 사진을 보면, 빨간색으로 표시한 부분에 먼지가 쌓여있습니다(왼쪽 사진). 휴지나 물티슈로 닦아내면 깔끔하게 지워집니다(오른쪽 사진).&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;hole.png&quot; data-origin-width=&quot;799&quot; data-origin-height=&quot;248&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bqMTfw/btrUyid6FXE/6D8kKP2b1EksKoKFO6Rcl1/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bqMTfw/btrUyid6FXE/6D8kKP2b1EksKoKFO6Rcl1/img.webp&quot; data-alt=&quot;청소 전, 후 모습&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bqMTfw/btrUyid6FXE/6D8kKP2b1EksKoKFO6Rcl1/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbqMTfw%2FbtrUyid6FXE%2F6D8kKP2b1EksKoKFO6Rcl1%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; alt=&quot;청소-전&amp;amp;#44;-후-모습&quot; loading=&quot;lazy&quot; width=&quot;799&quot; height=&quot;248&quot; data-filename=&quot;hole.png&quot; data-origin-width=&quot;799&quot; data-origin-height=&quot;248&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;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;결론&lt;/h2&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;참고로, 최근 켄싱턴 Pro Trackball 제품이 출시됐는데 이 제품은 무선 기능을 지원합니다. 구매하실 의향이 있다면 아래 제품 설명을 꼭 확인하세요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.kensington.com/p/products/electronic-control-solutions/trackball-products/slimblade-pro-trackball/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://www.kensington.com/p/products/electronic-control-solutions/trackball-products/slimblade-pro-trackball/&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1671889423328&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;SlimBlade&amp;trade; Pro Trackball | Trackballs | Trackball Mouse | Kensington&quot; data-og-description=&quot;Professional reviewers and ergonomists agree that finger-operated trackballs are superior to thumb-based trackballs when it comes to precision and hand comfort. At the same time, professional users prefer the convenience of wireless controllers. Kensington&quot; data-og-host=&quot;www.kensington.com&quot; data-og-source-url=&quot;https://www.kensington.com/p/products/electronic-control-solutions/trackball-products/slimblade-pro-trackball/&quot; data-og-url=&quot;https://www.kensington.com/p/products/electronic-control-solutions/trackball-products/slimblade-pro-trackball/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bnq6VT/hyQ1rEvdBi/ksK7gYdjwZg1tmhUK4EhOk/img.jpg?width=560&amp;amp;height=560&amp;amp;face=0_0_560_560,https://scrap.kakaocdn.net/dn/xWhnq/hyQ1p0YOWG/SYOk7RxOGjKTJgBmY7ZPwK/img.jpg?width=560&amp;amp;height=560&amp;amp;face=0_0_560_560&quot;&gt;&lt;a href=&quot;https://www.kensington.com/p/products/electronic-control-solutions/trackball-products/slimblade-pro-trackball/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.kensington.com/p/products/electronic-control-solutions/trackball-products/slimblade-pro-trackball/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bnq6VT/hyQ1rEvdBi/ksK7gYdjwZg1tmhUK4EhOk/img.jpg?width=560&amp;amp;height=560&amp;amp;face=0_0_560_560,https://scrap.kakaocdn.net/dn/xWhnq/hyQ1p0YOWG/SYOk7RxOGjKTJgBmY7ZPwK/img.jpg?width=560&amp;amp;height=560&amp;amp;face=0_0_560_560');&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;SlimBlade&amp;trade; Pro Trackball | Trackballs | Trackball Mouse | Kensington&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Professional reviewers and ergonomists agree that finger-operated trackballs are superior to thumb-based trackballs when it comes to precision and hand comfort. At the same time, professional users prefer the convenience of wireless controllers. Kensington&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.kensington.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>Life/제품 후기</category>
      <category>제품 후기</category>
      <author>❤ </author>
      <guid isPermaLink="true">https://luckygg.tistory.com/382</guid>
      <comments>https://luckygg.tistory.com/382#entry382comment</comments>
      <pubDate>Sat, 24 Dec 2022 22:46:37 +0900</pubDate>
    </item>
    <item>
      <title>[Wireshark] 패킷 분석의 시작, 와이어샤크! 기본 사용법 정리</title>
      <link>https://luckygg.tistory.com/379</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;와이어샤크(Wireshark)란?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;와이어샤크는 &lt;i&gt;네트워크 패킷을 감시 및 분석하는 프로그램&lt;/i&gt;으로, 이름이 가장 널리 알려진 소프트웨어입니다. 네트워크 장비뿐만 아니라 머신 비전 카메라를 사용하는 경우에도 어떠한 문제가 있다면 와이어샤크로 패킷을 분석하고 문제점을 찾는데 도움이 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한, TCP 통신으로 장치와 명령어를 주고받으면서 패킷의 데이터 형태는 어떠한지 학습하는 데에도 유용하게 사용됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;와이어샤크의 주요 특징은 다음과 같습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;GNU GPLv2 라이선스(자유 소프트웨어)&lt;/li&gt;
&lt;li&gt;크로스 플랫폼(Windows, Linux, Mac 등 지원)&lt;/li&gt;
&lt;li&gt;패킷 분석을 위한 GUI 제공&lt;/li&gt;
&lt;li&gt;무차별 모드(promiscuous mode) 지원&lt;/li&gt;
&lt;li&gt;Loopback 뿐만 아니라 시스템의 네트워크 어댑터도 분석 가능&lt;/li&gt;
&lt;li&gt;파일 형태로 기록 가능&lt;/li&gt;
&lt;/ul&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;와이어샤크 공식 홈페이지에 접속한 후 사용하는 운영체제에 맞는 파일을 다운로드합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.wireshark.org/#download&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://www.wireshark.org/#download&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1670590892915&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;Wireshark &amp;middot; Go Deep.&quot; data-og-description=&quot;What is SharkFest? SharkFest&amp;trade;, launched in 2008, is a series of annual educational conferences staged in various parts of the globe and focused on sharing knowledge, experience and best practices among the Wireshark&amp;reg; developer and user communities. Shar&quot; data-og-host=&quot;www.wireshark.org&quot; data-og-source-url=&quot;https://www.wireshark.org/#download&quot; data-og-url=&quot;https://www.wireshark.org/#download&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/dh1xiH/hyQQp1oq7e/1bZw3cBkXpnCKktXGkk3O1/img.png?width=400&amp;amp;height=400&amp;amp;face=0_0_400_400,https://scrap.kakaocdn.net/dn/Lezox/hyQPhqm0H3/3mCvGNBZZKsNurk6OPzz5K/img.png?width=300&amp;amp;height=250&amp;amp;face=0_0_300_250,https://scrap.kakaocdn.net/dn/0qyEv/hyQQyqvsnz/kLqg51ysp01QTRVg4yJZXK/img.png?width=300&amp;amp;height=250&amp;amp;face=0_0_300_250&quot;&gt;&lt;a href=&quot;https://www.wireshark.org/#download&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.wireshark.org/#download&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/dh1xiH/hyQQp1oq7e/1bZw3cBkXpnCKktXGkk3O1/img.png?width=400&amp;amp;height=400&amp;amp;face=0_0_400_400,https://scrap.kakaocdn.net/dn/Lezox/hyQPhqm0H3/3mCvGNBZZKsNurk6OPzz5K/img.png?width=300&amp;amp;height=250&amp;amp;face=0_0_300_250,https://scrap.kakaocdn.net/dn/0qyEv/hyQQyqvsnz/kLqg51ysp01QTRVg4yJZXK/img.png?width=300&amp;amp;height=250&amp;amp;face=0_0_300_250');&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;Wireshark &amp;middot; Go Deep.&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;What is SharkFest? SharkFest&amp;trade;, launched in 2008, is a series of annual educational conferences staged in various parts of the globe and focused on sharing knowledge, experience and best practices among the Wireshark&amp;reg; developer and user communities. Shar&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.wireshark.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;h2 data-ke-size=&quot;size26&quot;&gt;와이어샤크 설치하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로그램을 설치하는 과정은 아주 간단합니다. 웬만한 옵션은 건들지 말고 &lt;b&gt;Next 버튼만 클릭&lt;/b&gt;하여 설치하면 됩니다. 참고로, 설치 중간에 아래와 같이 &lt;b&gt;Npcap 드라이버 설치 과정&lt;/b&gt;이 있습니다. 해당 드라이버가 있어야 캡처가 가능하므로 반드시 체크를 해야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저는 Npcap 드라이버를 별도로 설치했으므로, 설치 과정 중에 설치가 필요 없다는 메시지가 표시됐습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;413&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Nn1WD/btrThmcm8fR/8bbT8PgzkSj58ttT5YM3qk/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Nn1WD/btrThmcm8fR/8bbT8PgzkSj58ttT5YM3qk/img.webp&quot; data-alt=&quot;Npcap 드라이버 설치하기&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Nn1WD/btrThmcm8fR/8bbT8PgzkSj58ttT5YM3qk/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FNn1WD%2FbtrThmcm8fR%2F8bbT8PgzkSj58ttT5YM3qk%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; alt=&quot;Npcap-드라이버-설치하기&quot; loading=&quot;lazy&quot; width=&quot;413&quot; data-origin-width=&quot;413&quot; data-origin-height=&quot;0&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Npcap 드라이버 설치하기&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 외에 USB 트래픽을 캡처하고 싶다면 체크 박스를 선택하고 설치를 진행합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;412&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bJ66XU/btrTkg3flTS/WXkc6oE7KkMBQNYxW4VocK/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bJ66XU/btrTkg3flTS/WXkc6oE7KkMBQNYxW4VocK/img.webp&quot; data-alt=&quot;USB 캡쳐 설치 옵션&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bJ66XU/btrTkg3flTS/WXkc6oE7KkMBQNYxW4VocK/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbJ66XU%2FbtrTkg3flTS%2FWXkc6oE7KkMBQNYxW4VocK%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; alt=&quot;USB-캡쳐-설치-옵션&quot; loading=&quot;lazy&quot; width=&quot;412&quot; data-origin-width=&quot;412&quot; data-origin-height=&quot;0&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;USB 캡쳐 설치 옵션&lt;/figcaption&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;412&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ejxpE2/btrTiwZBLU1/AtYFCudDQUJZ2Xok2Ws1ek/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ejxpE2/btrTiwZBLU1/AtYFCudDQUJZ2Xok2Ws1ek/img.webp&quot; data-alt=&quot;설치가 완료된 모습&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ejxpE2/btrTiwZBLU1/AtYFCudDQUJZ2Xok2Ws1ek/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FejxpE2%2FbtrTiwZBLU1%2FAtYFCudDQUJZ2Xok2Ws1ek%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; alt=&quot;설치가-완료된-모습&quot; loading=&quot;lazy&quot; width=&quot;412&quot; data-origin-width=&quot;412&quot; data-origin-height=&quot;0&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;h2 data-ke-size=&quot;size26&quot;&gt;와이어샤크 기본 사용 방법&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. 패킷 분석을 위한 어댑터 연결하기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;설치된 Wireshark를 실행하면, 아래와 같이 패킷 수집이 가능한 네트워크 어댑터 목록이 표시됩니다. 만약, 루프백 테스트를 하는 경우에는 'Adapter for loopback traffic capture'를 선택하면 됩니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;576&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bWik1y/btrTher5mMo/hNsJLXDKKOhNeHN4FNhFL1/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bWik1y/btrTher5mMo/hNsJLXDKKOhNeHN4FNhFL1/img.webp&quot; data-alt=&quot;네트워크 어댑터 목록&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bWik1y/btrTher5mMo/hNsJLXDKKOhNeHN4FNhFL1/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbWik1y%2FbtrTher5mMo%2FhNsJLXDKKOhNeHN4FNhFL1%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; alt=&quot;네트워크-어댑터-목록&quot; loading=&quot;lazy&quot; width=&quot;576&quot; data-origin-width=&quot;576&quot; data-origin-height=&quot;0&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;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;577&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Ox05a/btrTiyJRynE/KRBGdjqbtDoEuUjlXJLQ4K/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Ox05a/btrTiyJRynE/KRBGdjqbtDoEuUjlXJLQ4K/img.webp&quot; data-alt=&quot;패킷이 수집된 모습&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Ox05a/btrTiyJRynE/KRBGdjqbtDoEuUjlXJLQ4K/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FOx05a%2FbtrTiyJRynE%2FKRBGdjqbtDoEuUjlXJLQ4K%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; alt=&quot;패킷이-수집된-모습&quot; loading=&quot;lazy&quot; width=&quot;577&quot; data-origin-width=&quot;577&quot; data-origin-height=&quot;0&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;패킷이 수집된 모습&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. 패킷 분석 시작과 중지, 캡처된 패킷 저장하기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로그램 좌측 상단의 &lt;b&gt;중지(Stop) 버튼&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;211&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/blhhlw/btrTk2p9TjZ/O3KVqkAkMKBhPslJSQhOpK/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/blhhlw/btrTk2p9TjZ/O3KVqkAkMKBhPslJSQhOpK/img.webp&quot; data-alt=&quot;패킷 캡쳐를 중지하는 방법&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/blhhlw/btrTk2p9TjZ/O3KVqkAkMKBhPslJSQhOpK/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fblhhlw%2FbtrTk2p9TjZ%2FO3KVqkAkMKBhPslJSQhOpK%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; alt=&quot;패킷-캡쳐를-중지하는-방법&quot; loading=&quot;lazy&quot; width=&quot;211&quot; data-origin-width=&quot;211&quot; data-origin-height=&quot;0&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;시작(Start) 버튼&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;209&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/IVZjO/btrTjFvdzN8/tF8nVfxkFzH0wcQgiDJ8zk/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/IVZjO/btrTjFvdzN8/tF8nVfxkFzH0wcQgiDJ8zk/img.webp&quot; data-alt=&quot;패킷 캡쳐를 시작하는 방법&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/IVZjO/btrTjFvdzN8/tF8nVfxkFzH0wcQgiDJ8zk/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FIVZjO%2FbtrTjFvdzN8%2FtF8nVfxkFzH0wcQgiDJ8zk%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; alt=&quot;패킷-캡쳐를-시작하는-방법&quot; loading=&quot;lazy&quot; width=&quot;209&quot; data-origin-width=&quot;209&quot; data-origin-height=&quot;0&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;span&gt;시작 버튼을 클릭했을 때 저장 여부 안내 창이 표시됩니다. 저장이 필요하면 &lt;b&gt;'저장' 버튼&lt;/b&gt;을, 필요 없다면 &lt;b&gt;'Continue without Saving' 버튼&lt;/b&gt;을 클릭합니다.&lt;span&gt; &lt;/span&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;142&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bYkABU/btrToDXFUfc/lguLfYkG51MLn6TWf9wcp0/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bYkABU/btrToDXFUfc/lguLfYkG51MLn6TWf9wcp0/img.webp&quot; data-alt=&quot;패킷 저장 여부 안내 창&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bYkABU/btrToDXFUfc/lguLfYkG51MLn6TWf9wcp0/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbYkABU%2FbtrToDXFUfc%2FlguLfYkG51MLn6TWf9wcp0%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; alt=&quot;패킷-저장-여부-안내-창&quot; loading=&quot;lazy&quot; width=&quot;142&quot; data-origin-width=&quot;142&quot; data-origin-height=&quot;0&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;또는 좌측 상단의 File 메뉴 중 &lt;b&gt;Save, Save As 메뉴를 클릭&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;375&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/8igyu/btrTmX3a4d6/ToiG2nV70UkHePZpKtGpyk/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/8igyu/btrTmX3a4d6/ToiG2nV70UkHePZpKtGpyk/img.webp&quot; data-alt=&quot;패킷 저장하기 메뉴&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/8igyu/btrTmX3a4d6/ToiG2nV70UkHePZpKtGpyk/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F8igyu%2FbtrTmX3a4d6%2FToiG2nV70UkHePZpKtGpyk%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; alt=&quot;패킷-저장하기-메뉴&quot; loading=&quot;lazy&quot; width=&quot;375&quot; data-origin-width=&quot;375&quot; data-origin-height=&quot;0&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;다시 시작(Restart) 버튼&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;211&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bodmbP/btrTiywl0YJ/dIsU6ElrYQG5IYEhwBFyr1/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bodmbP/btrTiywl0YJ/dIsU6ElrYQG5IYEhwBFyr1/img.webp&quot; data-alt=&quot;패킷 캡쳐 다시 시작하기&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bodmbP/btrTiywl0YJ/dIsU6ElrYQG5IYEhwBFyr1/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbodmbP%2FbtrTiywl0YJ%2FdIsU6ElrYQG5IYEhwBFyr1%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; alt=&quot;패킷-캡쳐-다시-시작하기&quot; loading=&quot;lazy&quot; width=&quot;211&quot; data-origin-width=&quot;211&quot; data-origin-height=&quot;0&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;패킷 캡쳐 다시 시작하기&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. 필터 사용하여 원하는 패킷만 보기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;툴바 아래에 IP 주소나 포트 번호, 그 외의 조건을 설정하여 원하는 패킷만 볼 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;239&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bs9lhY/btrToCLeoK9/tkeRhZWRs3AJAKt9YdeJKk/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bs9lhY/btrToCLeoK9/tkeRhZWRs3AJAKt9YdeJKk/img.webp&quot; data-alt=&quot;필터 적용하여 원하는 패킷만 수집하기&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bs9lhY/btrToCLeoK9/tkeRhZWRs3AJAKt9YdeJKk/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbs9lhY%2FbtrToCLeoK9%2FtkeRhZWRs3AJAKt9YdeJKk%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; alt=&quot;필터-적용하여-원하는-패킷만-수집하기&quot; loading=&quot;lazy&quot; width=&quot;239&quot; data-origin-width=&quot;239&quot; data-origin-height=&quot;0&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;자주 사용하는 필터 조건은 다음과 같습니다. 주로 보내는 IP 주소와 목적지 IP 주소 정보로 주고받는 패킷만 보고 싶을 때 사용합니다. 그리고 논리 연산자를 사용하여 AND, OR와 같은 조건도 같이 사용할 수 있습니다.&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 97px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style12&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 20px; text-align: center;&quot;&gt;항목&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 20px; text-align: center;&quot;&gt;설명&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;ip.src&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;보내는 IP 주소&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;ip.dst&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;받는(목적지) IP 주소&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;tcp.srcport&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;보내는 TCP 포트 번호&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 17px;&quot;&gt;tcp.dstport&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 17px;&quot;&gt;받는(목적지) TCP 포트 번호&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;481&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bZE6LA/btrTmYgHwTu/rAddlTXeCitG6yAL5J06KK/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bZE6LA/btrTmYgHwTu/rAddlTXeCitG6yAL5J06KK/img.webp&quot; data-alt=&quot;보내는 IP 주소를 필터링한 모습&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bZE6LA/btrTmYgHwTu/rAddlTXeCitG6yAL5J06KK/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbZE6LA%2FbtrTmYgHwTu%2FrAddlTXeCitG6yAL5J06KK%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; alt=&quot;보내는-IP-주소를-필터링한-모습&quot; loading=&quot;lazy&quot; width=&quot;481&quot; data-origin-width=&quot;481&quot; data-origin-height=&quot;0&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;보내는 IP 주소를 필터링한 모습&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>Programming/Network</category>
      <category>와이어샤크</category>
      <author>❤ </author>
      <guid isPermaLink="true">https://luckygg.tistory.com/379</guid>
      <comments>https://luckygg.tistory.com/379#entry379comment</comments>
      <pubDate>Thu, 15 Dec 2022 19:21:32 +0900</pubDate>
    </item>
    <item>
      <title>[네트워크] iPerf3로 네트워크 부하 테스트 쉽게 하기</title>
      <link>https://luckygg.tistory.com/380</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;네트워크 부하&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로그램을 만들고 나면 &lt;b&gt;안정성 테스트&lt;/b&gt;가 필요합니다. 장기적인 동작에 문제가 없는지, 낮은 사양의 PC에서도 잘 동작하는지, CPU 부하가 높은 상태에서도 잘 동작하는지 등의 예시가 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;네트워크 부하도 마찬가지입니다. 네트워크 관련 프로그램을 만든다면 네트워크 부하에 따른 테스트도 필요합니다. 일반적인 상황에서는 문제가 없으나 순식간에 많은 양의 네트워크 패킷이 들어오면 프로그램이 버벅거리는 상황을 볼 수 있습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;iPerf3 특징&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기, 네트워크 부하를 테스트하기 위한 편리한 프로그램이 있습니다. 바로 &lt;b&gt;iPerf3&lt;/b&gt;입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://iperf.fr/iperf-download.php&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://iperf.fr/iperf-download.php&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1670640167663&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;iPerf - Download iPerf3 and original iPerf pre-compiled binaries&quot; data-og-description=&quot;iPerf - The ultimate speed test tool for TCP, UDP and SCTPTest the limits of your network + Internet neutrality test Table of contents : Download iPerf for Windows Download iPerf3 for Android Download iPerf3 for iPhone / iPad Download iPerf3 for Apple macO&quot; data-og-host=&quot;iperf.fr&quot; data-og-source-url=&quot;https://iperf.fr/iperf-download.php&quot; data-og-url=&quot;https://iperf.fr/iperf-download.php&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://iperf.fr/iperf-download.php&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://iperf.fr/iperf-download.php&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;iPerf - Download iPerf3 and original iPerf pre-compiled binaries&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;iPerf - The ultimate speed test tool for TCP, UDP and SCTPTest the limits of your network + Internet neutrality test Table of contents : Download iPerf for Windows Download iPerf3 for Android Download iPerf3 for iPhone / iPad Download iPerf3 for Apple macO&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;iperf.fr&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;TCP/ SCTP/ UDP 프로토콜 지원&lt;/li&gt;
&lt;li&gt;다양한 운영체제 지원(Windows, Linux, Android, MacOS 등)&lt;/li&gt;
&lt;li&gt;다수의 클라이언트, 서버 연결 가능&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;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;iPerf3 사용 방법&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다운로드 페이지에서 운영체제에 맞는 항목을 다운로드합니다. 파일은 아주 간단하게 &lt;b&gt;dll 파일과 exe 파일&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;605&quot; data-origin-height=&quot;288&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/EtmMt/btrTg4Xevoc/EMwI1mCRwFJOCea2IId9rK/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/EtmMt/btrTg4Xevoc/EMwI1mCRwFJOCea2IId9rK/img.webp&quot; data-alt=&quot;iPerf3 구성&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/EtmMt/btrTg4Xevoc/EMwI1mCRwFJOCea2IId9rK/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FEtmMt%2FbtrTg4Xevoc%2FEMwI1mCRwFJOCea2IId9rK%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; alt=&quot;iPerf3-구성&quot; loading=&quot;lazy&quot; width=&quot;400&quot; height=&quot;190&quot; data-origin-width=&quot;605&quot; data-origin-height=&quot;288&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;iPerf3 구성&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 &lt;b&gt;명령 프롬프트(cmd)&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;520&quot; data-origin-height=&quot;234&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bplRkR/btrThOTSdnb/9YFDoUnflZPbUNHmdMKyv0/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bplRkR/btrThOTSdnb/9YFDoUnflZPbUNHmdMKyv0/img.webp&quot; data-alt=&quot;명령 프롬프트 실행하기&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bplRkR/btrThOTSdnb/9YFDoUnflZPbUNHmdMKyv0/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbplRkR%2FbtrThOTSdnb%2F9YFDoUnflZPbUNHmdMKyv0%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; alt=&quot;명령-프롬프트-실행하기&quot; loading=&quot;lazy&quot; width=&quot;400&quot; height=&quot;180&quot; data-origin-width=&quot;520&quot; data-origin-height=&quot;234&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;iperf3.exe가 위치한 폴더로 이동&lt;/b&gt;합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1670640823159&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;cd C:\Users\User\Downloads\iperf-3.1.3-win64&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;서버 구동하기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래 명령어를 입력하여 &lt;b&gt;서버로 구동&lt;/b&gt;합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1670640876955&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;iperf3 -s&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;800&quot; data-origin-height=&quot;489&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bGcoaf/btrTifXXCoD/t1ClzOSow8bT0YHrf8khg1/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bGcoaf/btrTifXXCoD/t1ClzOSow8bT0YHrf8khg1/img.webp&quot; data-alt=&quot;서버로 구동된 모습&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bGcoaf/btrTifXXCoD/t1ClzOSow8bT0YHrf8khg1/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbGcoaf%2FbtrTifXXCoD%2Ft1ClzOSow8bT0YHrf8khg1%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; alt=&quot;서버로-구동된-모습&quot; loading=&quot;lazy&quot; width=&quot;860&quot; height=&quot;526&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;489&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;h3 data-ke-size=&quot;size23&quot;&gt;클라이언트 구동하기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래 명령어를 입력하여 &lt;b&gt;클라이언트로 구동&lt;/b&gt;합니다. 아래 명령어는 클라이언트(-c)이며 127.0.0.1에 접속하고, 5초 동안 전송(-t 5)한다는 의미입니다.&lt;/p&gt;
&lt;pre id=&quot;code_1670641133053&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;iperf3 -c 127.0.0.1 -t 5&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;800&quot; data-origin-height=&quot;492&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xYOEB/btrTiV55Ia9/2JclQnlpSpmF9n5K6YhEX1/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xYOEB/btrTiV55Ia9/2JclQnlpSpmF9n5K6YhEX1/img.webp&quot; data-alt=&quot;5초 동안 패킷이 전송된 모습&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xYOEB/btrTiV55Ia9/2JclQnlpSpmF9n5K6YhEX1/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxYOEB%2FbtrTiV55Ia9%2F2JclQnlpSpmF9n5K6YhEX1%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; alt=&quot;5초-동안-패킷이-전송된-모습&quot; loading=&quot;lazy&quot; width=&quot;860&quot; height=&quot;530&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;492&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;5초 동안 패킷이 전송된 모습&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또는, 1초 동안 N Byte를 전송하는 명령어도 있습니다. 아래 명령어는 1초 동안 10MB를 전송한다는 의미입니다.&lt;/p&gt;
&lt;pre id=&quot;code_1670641563358&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;iperf3 -c 127.0.0.1 -n 10M&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;800&quot; data-origin-height=&quot;450&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/pWvwG/btrThfRWeEz/uOxXkeklkpQTCyLKK7egsK/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/pWvwG/btrThfRWeEz/uOxXkeklkpQTCyLKK7egsK/img.webp&quot; data-alt=&quot;1초 동안 10MB가 전송된 모습&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/pWvwG/btrThfRWeEz/uOxXkeklkpQTCyLKK7egsK/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FpWvwG%2FbtrThfRWeEz%2FuOxXkeklkpQTCyLKK7egsK%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; alt=&quot;1초-동안-10MB가-전송된-모습&quot; loading=&quot;lazy&quot; width=&quot;860&quot; height=&quot;484&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;450&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;1초 동안 10MB가 전송된 모습&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Batch 파일로 반복하기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아쉬운 점은 -t와 -n 옵션을 같이 사용할 수 없습니다. -h 명령어를 입력하면 iperf3을 실행하기 위한 도움말이 보이는데요. -t와 -n옵션은 동시에 사용되지 않고, 서로 대체되어 사용이 가능하다고 되어 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저는 초당 10MB를 반복적으로 전송하고 싶었는데, -t와 -n을 같이 사용할 수 없으니 고민이 되더군요. 그래서 다음과 같은 배치 파일을 만들어 보았습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1670641965741&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@echo off

:1

iperf3 -c 127.0.0.1 -n 10M

timeout -t 1 /nobreak

goto 1&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아쉬운 대로, 10MB/s 전송을 1초마다 계속해서 반복하여 실행하는 것이지요. 이렇게 하면 나름 10MB/s로 데이터를 계속 전송하여 부하 테스트가 가능합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;566&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c4AoPD/btrTkfXvL39/uAbYyMgLUrWb0vbPQiUb5K/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c4AoPD/btrTkfXvL39/uAbYyMgLUrWb0vbPQiUb5K/img.webp&quot; data-alt=&quot;10MB/s가 반복 동작하는 모습&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c4AoPD/btrTkfXvL39/uAbYyMgLUrWb0vbPQiUb5K/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc4AoPD%2FbtrTkfXvL39%2FuAbYyMgLUrWb0vbPQiUb5K%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; alt=&quot;10MB/s가-반복-동작하는-모습&quot; loading=&quot;lazy&quot; width=&quot;860&quot; height=&quot;609&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;566&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;10MB/s가 반복 동작하는 모습&lt;/figcaption&gt;
&lt;/figure&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;아래의 명령어를 입력하면 iPerf3을 사용하기 위한 명령어 목록이 보입니다.&lt;/p&gt;
&lt;pre id=&quot;code_1670741391955&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;iperf3 -h&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;800&quot; data-origin-height=&quot;534&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bG74cd/btrThfdoZbj/5nUwDBbPSvEAu2k0tP2Odk/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bG74cd/btrThfdoZbj/5nUwDBbPSvEAu2k0tP2Odk/img.webp&quot; data-alt=&quot;iperf3 명령어 도움말&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bG74cd/btrThfdoZbj/5nUwDBbPSvEAu2k0tP2Odk/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbG74cd%2FbtrThfdoZbj%2F5nUwDBbPSvEAu2k0tP2Odk%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; alt=&quot;iperf3-명령어-도움말&quot; loading=&quot;lazy&quot; width=&quot;860&quot; height=&quot;575&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;534&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;iperf3 명령어 도움말&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;정리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위에서 언급한 명령어들을 편리하게 사용할 수 있는 배치 파일을 아래 파일에 업로드했습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;fileblock&quot; data-ke-align=&quot;alignCenter&quot;&gt;&lt;a href=&quot;https://blog.kakaocdn.net/dn/cIT9eC/btrTgRKxiiL/YGAe7xX5NwZEYzBfDwXJR0/iperf-3.1.3-win64%20with%20Batch%20files.zip?attach=1&amp;amp;knm=tfile.zip&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;iperf-3.1.3-win64 with Batch files.zip&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;size&quot;&gt;1.32MB&lt;/div&gt;
&lt;/div&gt;
  &lt;/a&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;필요한 조건에 맞게 메모장으로 편집하여 실행해도 됩니다. 이 외에 인터넷 웹 브라우저를 접속하거나 유튜브에 접속하여 동영상을 재생하는 방법도 있으니 참고하세요.&lt;/p&gt;</description>
      <category>Programming/Network</category>
      <category>네트워크</category>
      <author>❤ </author>
      <guid isPermaLink="true">https://luckygg.tistory.com/380</guid>
      <comments>https://luckygg.tistory.com/380#entry380comment</comments>
      <pubDate>Sun, 11 Dec 2022 16:00:28 +0900</pubDate>
    </item>
    <item>
      <title>[C#] WinForm 도구 상자에 컨트롤이 추가되지 않는 경우 해결 방법</title>
      <link>https://luckygg.tistory.com/378</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;도구 상자에 컨트롤이 추가되지 않는 문제&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;C# WinForm&lt;/b&gt;에서 기본으로 제공되는 컨트롤 외에, 내가 필요로 하는 기능의 컨트롤이 없는 경우에는 &lt;b&gt;사용자 컨트롤(Custom control)&lt;/b&gt;로 직접 만들어야 합니다. 또는 &lt;b&gt;NuGet&lt;/b&gt;이나 &lt;b&gt;누군가 만든 컨트롤 dll&lt;/b&gt;을 사용해도 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데 이렇게 외부 컨트롤을 폼(Form) 디자이너에서 사용하려면 &lt;b&gt;도구 상자(Tool box)&lt;/b&gt;에 추가되어야 하는데요. 하필이면 Visual Studio 버그인지 모르겠으나, 도구 상자에 컨트롤을 추가하다가 &lt;b&gt;Visual Studio가 종료되는 버그&lt;/b&gt;가 발생할 수도 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://luckygg.tistory.com/161&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;[Visual Studio] VS2015 도구 상자(ToolBox) 종료 현상 해결 방법&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1666692397060&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;[Visual Studio] VS2015 도구 상자(ToolBox) 종료 현상 해결 방법&quot; data-og-description=&quot;최근 Visual Studio 2015에서 C# Windows Form 작업이 있었는데요. Custom Control을 제작하여 윈 폼 프로젝트에 추가하는 과정에서 문제가 발생했습니다. 마침 여분의 PC가 더 있어서 확인해 보았는데, PC 1대&quot; data-og-host=&quot;luckygg.tistory.com&quot; data-og-source-url=&quot;https://luckygg.tistory.com/161&quot; data-og-url=&quot;https://luckygg.tistory.com/161&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/75orZ/hyQlFjgk0T/pT86vitFlPsJow7O5NU9pK/img.jpg?width=671&amp;amp;height=481&amp;amp;face=0_0_671_481,https://scrap.kakaocdn.net/dn/h8vqq/hyQhz54wII/v6xRRRBOdPcQHK9xVcrEyk/img.jpg?width=671&amp;amp;height=481&amp;amp;face=0_0_671_481,https://scrap.kakaocdn.net/dn/rH4fA/hyQhDUVMm8/9PsPXhhfOy9G86AilJSftk/img.jpg?width=671&amp;amp;height=481&amp;amp;face=0_0_671_481&quot;&gt;&lt;a href=&quot;https://luckygg.tistory.com/161&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://luckygg.tistory.com/161&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/75orZ/hyQlFjgk0T/pT86vitFlPsJow7O5NU9pK/img.jpg?width=671&amp;amp;height=481&amp;amp;face=0_0_671_481,https://scrap.kakaocdn.net/dn/h8vqq/hyQhz54wII/v6xRRRBOdPcQHK9xVcrEyk/img.jpg?width=671&amp;amp;height=481&amp;amp;face=0_0_671_481,https://scrap.kakaocdn.net/dn/rH4fA/hyQhDUVMm8/9PsPXhhfOy9G86AilJSftk/img.jpg?width=671&amp;amp;height=481&amp;amp;face=0_0_671_481');&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;[Visual Studio] VS2015 도구 상자(ToolBox) 종료 현상 해결 방법&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;최근 Visual Studio 2015에서 C# Windows Form 작업이 있었는데요. Custom Control을 제작하여 윈 폼 프로젝트에 추가하는 과정에서 문제가 발생했습니다. 마침 여분의 PC가 더 있어서 확인해 보았는데, PC 1대&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;luckygg.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데 문제는 위 링크의 조치 사항을 적용해도 여전히 Visual Studio 버전에 상관없이 종료되는 경우가 있습니다. 참 골치 아픈 문제인데요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;본문에서는 도구 상자에 컨트롤을 추가하지 않고, 직접 코드 편집으로 컨트롤을 추가하여 사용하는 방법을 알려드립니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;도구 상자 없이 컨트롤 추가하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선 추가하고자 하는 컨트롤의 dll을 참조로 추가합니다. 저는 예시로 ImageGlass.ImageBox dll을 사용했습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;779&quot; data-origin-height=&quot;736&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dPIzUw/btrPyuSgTbK/l2nBmGmy8dSKDqk5ECWakK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dPIzUw/btrPyuSgTbK/l2nBmGmy8dSKDqk5ECWakK/img.png&quot; data-alt=&quot;참조 dll 추가하기&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dPIzUw/btrPyuSgTbK/l2nBmGmy8dSKDqk5ECWakK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdPIzUw%2FbtrPyuSgTbK%2Fl2nBmGmy8dSKDqk5ECWakK%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;779&quot; height=&quot;736&quot; data-origin-width=&quot;779&quot; data-origin-height=&quot;736&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;참조 dll 추가하기&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 버튼(Button)과 같은 아무 컨트롤이나 추가합니다.&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;671&quot; data-origin-height=&quot;513&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/m8zHE/btrPz2NO6yn/cTJtwxqwZOFp6qeglMikU1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/m8zHE/btrPz2NO6yn/cTJtwxqwZOFp6qeglMikU1/img.png&quot; data-alt=&quot;Button 컨트롤이 추가된 모습&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/m8zHE/btrPz2NO6yn/cTJtwxqwZOFp6qeglMikU1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fm8zHE%2FbtrPz2NO6yn%2FcTJtwxqwZOFp6qeglMikU1%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;671&quot; height=&quot;513&quot; data-origin-width=&quot;671&quot; data-origin-height=&quot;513&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Button 컨트롤이 추가된 모습&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 Form의 디자이너인 &lt;b&gt;Form1.Designer.cs&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;1088&quot; data-origin-height=&quot;763&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/boxhQM/btrPAquiBaY/45DKTCEkD5SbKUeDxiLj5k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/boxhQM/btrPAquiBaY/45DKTCEkD5SbKUeDxiLj5k/img.png&quot; data-alt=&quot;Form1.Designer.cs 파일을 연 모습&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/boxhQM/btrPAquiBaY/45DKTCEkD5SbKUeDxiLj5k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FboxhQM%2FbtrPAquiBaY%2F45DKTCEkD5SbKUeDxiLj5k%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;1088&quot; height=&quot;763&quot; data-origin-width=&quot;1088&quot; data-origin-height=&quot;763&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Form1.Designer.cs 파일을 연 모습&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;기존 코드에서 Button과 관련된 모든 코드를 사용하고자 하는 컨트롤로 변경&lt;/u&gt;합니다. 저는 ImageGlass의 ImageBox로 모두 교체했습니다. &lt;u&gt;컨트롤에서 지원되지 않는 속성은 지우셔도 상관없습니다.&lt;/u&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;783&quot; data-origin-height=&quot;700&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/EVFFR/btrPys1bDH3/Evyyk6RtNEk3u2Rh7K9m10/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/EVFFR/btrPys1bDH3/Evyyk6RtNEk3u2Rh7K9m10/img.png&quot; data-alt=&quot;새로운 컨트롤 이름으로 모두 변경한 모습&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/EVFFR/btrPys1bDH3/Evyyk6RtNEk3u2Rh7K9m10/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FEVFFR%2FbtrPys1bDH3%2FEvyyk6RtNEk3u2Rh7K9m10%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;783&quot; height=&quot;700&quot; data-origin-width=&quot;783&quot; data-origin-height=&quot;700&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;이제 Form1.cs를 더블 클릭해서 디자이너를 보겠습니다. 처음에 있던 버튼은 사라지고 교체한 컨트롤이 존재합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;981&quot; data-origin-height=&quot;556&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mBzoA/btrPynyX460/yPTVgvsNLTiWQSLQMxP0c0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mBzoA/btrPynyX460/yPTVgvsNLTiWQSLQMxP0c0/img.png&quot; data-alt=&quot;새로 추가한 컨트롤로 교체된 모습&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mBzoA/btrPynyX460/yPTVgvsNLTiWQSLQMxP0c0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmBzoA%2FbtrPynyX460%2FyPTVgvsNLTiWQSLQMxP0c0%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;981&quot; height=&quot;556&quot; data-origin-width=&quot;981&quot; data-origin-height=&quot;556&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;u&gt;드 플랫폼이 x64인 경우에는 빌드에는 문제가 없지만 디자이너를 열면 아래와 같은 에러가 발생&lt;/u&gt;합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1190&quot; data-origin-height=&quot;270&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xWQmQ/btrPynZ2HSz/8GaJ3hkptEKkqYtE7zXRd1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xWQmQ/btrPynZ2HSz/8GaJ3hkptEKkqYtE7zXRd1/img.png&quot; data-alt=&quot;x64 디자이너 오류&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xWQmQ/btrPynZ2HSz/8GaJ3hkptEKkqYtE7zXRd1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxWQmQ%2FbtrPynZ2HSz%2F8GaJ3hkptEKkqYtE7zXRd1%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;1190&quot; height=&quot;270&quot; data-origin-width=&quot;1190&quot; data-origin-height=&quot;270&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;x64 디자이너 오류&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정확한 이유는 모르겠습니다만, &lt;u&gt;64bit에서 생성된 컨트롤은 빌드 플랫폼이 x64일 때 디자이너에서 오류가 발생&lt;/u&gt;합니다. 그래서 &lt;u&gt;AnyCPU나 x86으로 빌드하면 디자이너가 정상적으로 열립니다&lt;/u&gt;. 만약, x64용 dll만 있다면 빌드는 되지만 디자이너가 열리지 않아 난감한 상황에 직면하긴 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아무튼, 컨트롤이 도구 상자에 정상적으로 추가되지 않는다면 본문과 같이 디자이너 코드 편집으로 직접 추가하는 방법이 있다는 것을 알고 계시면 꽤 유용합니다.&lt;/p&gt;</description>
      <category>Programming/.Net</category>
      <category>.net</category>
      <category>Visual Studio</category>
      <author>❤ </author>
      <guid isPermaLink="true">https://luckygg.tistory.com/378</guid>
      <comments>https://luckygg.tistory.com/378#entry378comment</comments>
      <pubDate>Sat, 29 Oct 2022 23:49:12 +0900</pubDate>
    </item>
    <item>
      <title>[C#] WinForm의 Form 디자이너가 사라지는 문제 해결 방법</title>
      <link>https://luckygg.tistory.com/377</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;Form 디자이너가 사라지는 현상&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아주 가끔 &lt;b&gt;C# WinForm 프로젝트&lt;/b&gt;를 사용하다가 &lt;u&gt;Form 디자이너가 사라지는 현상&lt;/u&gt;이 생깁니다. 정상적이라면 아래와 같이 Form.cs 파일의 아이콘이 &lt;b&gt;폼(Form)&lt;/b&gt;이어야 합니다. 그리고 더블 클릭하면 오른쪽과 같이 UI 꾸미기가 가능한 디자이너 창이 표시되어야 하죠.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;417&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cSdfxQ/btrPymmhjrQ/7YTHrq7gMarXVh99ldbTkK/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cSdfxQ/btrPymmhjrQ/7YTHrq7gMarXVh99ldbTkK/img.webp&quot; data-alt=&quot;Form 디자이너가 정상적으로 보이는 모습&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cSdfxQ/btrPymmhjrQ/7YTHrq7gMarXVh99ldbTkK/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcSdfxQ%2FbtrPymmhjrQ%2F7YTHrq7gMarXVh99ldbTkK%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; alt=&quot;Form-디자이너가-정상적으로-보이는-모습&quot; loading=&quot;lazy&quot; width=&quot;800&quot; height=&quot;417&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;417&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Form 디자이너가 정상적으로 보이는 모습&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데 어느 순간부터 폼 아이콘이 사라지고 C# 아이콘이 생기면서 디자이너가 더 이상 보이지 않는 현상이 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;799&quot; data-origin-height=&quot;532&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bBkuQP/btrPyVO3m3V/91zgyUZSHe7TE569P1VGe1/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bBkuQP/btrPyVO3m3V/91zgyUZSHe7TE569P1VGe1/img.webp&quot; data-alt=&quot;Form 디자이너가 보이지 않는 모습&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bBkuQP/btrPyVO3m3V/91zgyUZSHe7TE569P1VGe1/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbBkuQP%2FbtrPyVO3m3V%2F91zgyUZSHe7TE569P1VGe1%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; alt=&quot;Form-디자이너가-보이지-않는-모습&quot; loading=&quot;lazy&quot; width=&quot;799&quot; height=&quot;532&quot; data-origin-width=&quot;799&quot; data-origin-height=&quot;532&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Form 디자이너가 보이지 않는 모습&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이상하다 싶어 프로젝트를 다시 열어도, PC를 재부팅해도, 이름을 바꿔도 도저히 돌아오지 않습니다. 이런 현상이 발생했을 때 아주 간단하게 조치하는 방법을 알려드리겠습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;csproj 파일을 수정하여 해결하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 문제는 프로젝트 파일을 수정하여 쉽게 해결이 가능합니다. 아래 그림처럼, &lt;u&gt;*.csproj 파일&lt;/u&gt;을 메모장과 같은 편집기로 불러옵니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;417&quot; data-origin-height=&quot;286&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cRfHdT/btrPyudjTDv/qAOtxI0VAZpofBM84VVz3k/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cRfHdT/btrPyudjTDv/qAOtxI0VAZpofBM84VVz3k/img.webp&quot; data-alt=&quot;csproj 파일&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cRfHdT/btrPyudjTDv/qAOtxI0VAZpofBM84VVz3k/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcRfHdT%2FbtrPyudjTDv%2FqAOtxI0VAZpofBM84VVz3k%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; alt=&quot;csproj-파일&quot; loading=&quot;lazy&quot; width=&quot;417&quot; height=&quot;286&quot; data-origin-width=&quot;417&quot; data-origin-height=&quot;286&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;csproj 파일&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;파일을 열어보면, 폼 디자이너가 보이지 않는 파일을 찾습니다. 본문의 예제 파일은 &lt;b&gt;Form1.cs&lt;/b&gt; 입니다. 아래 그림을 보면 Designer.cs 파일도 보이고 문제가 없어 보이는데요. 사실 정상적이지 않은 모습입니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;782&quot; data-origin-height=&quot;164&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b0KVvE/btrPyK09Kls/JhYoi1dp7k2HOJrvByYo0K/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b0KVvE/btrPyK09Kls/JhYoi1dp7k2HOJrvByYo0K/img.webp&quot; data-alt=&quot;에디터 편집기로 csproj 열기&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b0KVvE/btrPyK09Kls/JhYoi1dp7k2HOJrvByYo0K/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb0KVvE%2FbtrPyK09Kls%2FJhYoi1dp7k2HOJrvByYo0K%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; alt=&quot;에디터-편집기로-csproj-열기&quot; loading=&quot;lazy&quot; width=&quot;782&quot; height=&quot;164&quot; data-origin-width=&quot;782&quot; data-origin-height=&quot;164&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;에디터 편집기로 csproj 열기&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래와 같이 되어있다면,&lt;/p&gt;
&lt;pre id=&quot;code_1666689745703&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;Compile Include=&quot;Form1.cs&quot; /&amp;gt;
&amp;lt;Compile Include=&quot;Form1.Designer.cs&quot;&amp;gt;
  &amp;lt;DependentUpon&amp;gt;Form1.cs&amp;lt;/DependentUpon&amp;gt;
&amp;lt;/Compile&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 수정해야 합니다. 즉, SubType이 사라져 생긴 문제입니다.&lt;/p&gt;
&lt;pre id=&quot;code_1666689784840&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;Compile Include=&quot;Form1.cs&quot;&amp;gt;
	&amp;lt;SubType&amp;gt;Form&amp;lt;/SubType&amp;gt;
&amp;lt;/Compile&amp;gt;
&amp;lt;Compile Include=&quot;Form1.Designer.cs&quot;&amp;gt;
  &amp;lt;DependentUpon&amp;gt;Form1.cs&amp;lt;/DependentUpon&amp;gt;
&amp;lt;/Compile&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참고로, 수정할 때 &lt;u&gt;&amp;lt;Compile&amp;gt;~&amp;lt;/Compile&amp;gt;&lt;/u&gt;이 한 쌍이어야 합니다. 기존 내용에서 &amp;lt;Compile ... &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;/&lt;/b&gt;&lt;/span&gt;&amp;gt; '슬래시(/)'를 지웠는지 꼭 확인하세요. 슬래시가 남아있으면 계속 적용이 안됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 저장한 후 다시 프로젝트 파일을 열면 정상적으로 폼 디자이너가 보이기 시작합니다. 이게 Visual Studio 버그인지는 모르겠으나, 또 발생하면 똑같이 수정하면 해결되므로 알고 있으면 유용합니다.&lt;/p&gt;</description>
      <category>Programming/.Net</category>
      <category>.net</category>
      <category>Visual Studio</category>
      <author>❤ </author>
      <guid isPermaLink="true">https://luckygg.tistory.com/377</guid>
      <comments>https://luckygg.tistory.com/377#entry377comment</comments>
      <pubDate>Tue, 25 Oct 2022 18:30:53 +0900</pubDate>
    </item>
    <item>
      <title>[C++] C++에서 구조적 예외 처리(SEH) 사용하는 방법</title>
      <link>https://luckygg.tistory.com/375</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;구조적 예외 처리와 C++ 예외 처리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;구조적 예외 처리&lt;/b&gt;는 &lt;u&gt;Microsoft Windows의 기본 예외 처리 메커니즘&lt;/u&gt;이며, &lt;u&gt;소프트웨어와 하드웨어 예외를 처리&lt;/u&gt;할 수 있다고 설명했었습니다. 이러한 내용은 아래 링크를 참고하세요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://luckygg.tistory.com/374&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;구조적 예외 처리(SEH, Structured Exception Handling) 기초 이야기&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1661692395473&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;구조적 예외 처리(SEH, Structured Exception Handling) 기초 이야기&quot; data-og-description=&quot;구조적 예외 처리(SEH)란? 구조적 예외 처리(이하 SEH)는 하드웨어와 소프트웨어 예외를 모두 처리하는 Microsoft Windows의 기본 예외 처리 메커니즘입니다. 하드웨어 예외는 예외가 발생한 주체가 CPU&quot; data-og-host=&quot;luckygg.tistory.com&quot; data-og-source-url=&quot;https://luckygg.tistory.com/374&quot; data-og-url=&quot;https://luckygg.tistory.com/374&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/jnfJ1/hyPBVUNdOX/OUWl2iy1m2gCVPyzcjkdG0/img.png?width=512&amp;amp;height=512&amp;amp;face=0_0_512_512,https://scrap.kakaocdn.net/dn/dkubKI/hyPBTCGTgi/hJiit4F3mE2qzcfj3YwXeK/img.png?width=512&amp;amp;height=512&amp;amp;face=0_0_512_512&quot;&gt;&lt;a href=&quot;https://luckygg.tistory.com/374&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://luckygg.tistory.com/374&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/jnfJ1/hyPBVUNdOX/OUWl2iy1m2gCVPyzcjkdG0/img.png?width=512&amp;amp;height=512&amp;amp;face=0_0_512_512,https://scrap.kakaocdn.net/dn/dkubKI/hyPBTCGTgi/hJiit4F3mE2qzcfj3YwXeK/img.png?width=512&amp;amp;height=512&amp;amp;face=0_0_512_512');&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;구조적 예외 처리(SEH, Structured Exception Handling) 기초 이야기&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;구조적 예외 처리(SEH)란? 구조적 예외 처리(이하 SEH)는 하드웨어와 소프트웨어 예외를 모두 처리하는 Microsoft Windows의 기본 예외 처리 메커니즘입니다. 하드웨어 예외는 예외가 발생한 주체가 CPU&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;luckygg.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 C++ 예외 문법인 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt;&lt;/code&gt;, &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt;&lt;/code&gt;, &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt;&lt;/code&gt;는 내부적으로 &lt;b&gt;구조적 예외 처리(이하 SEH, Structured Exception Handling)&lt;/b&gt; 기능을 이용하여 구현되어 있다는 내용도 언급했습니다. 어쨌든, 특별한 이유가 없다면 &lt;u&gt;C++ 언어에서는 C++ 예외 처리 문법을, C#에서는 C# 예외 처리 문법을 사용&lt;/u&gt;하면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;본문에서는 C++ 언어에서 SEH를 사용하는 방법을 설명하겠습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;C++에서 SEH 사용하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;간단한 테스트를 위해 Visual Studio 2019에서 콘솔 앱 프로젝트를 생성합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;531&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lKlxP/btrOgxPglPx/se4QEjKKHBq9kTKAoW9cP0/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lKlxP/btrOgxPglPx/se4QEjKKHBq9kTKAoW9cP0/img.webp&quot; data-alt=&quot;C++ 콘솔 앱 프로젝트 생성하기&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lKlxP/btrOgxPglPx/se4QEjKKHBq9kTKAoW9cP0/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlKlxP%2FbtrOgxPglPx%2Fse4QEjKKHBq9kTKAoW9cP0%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; alt=&quot;C++-콘솔-앱-프로젝트-생성하기&quot; loading=&quot;lazy&quot; width=&quot;800&quot; height=&quot;531&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;531&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;C++ 콘솔 앱 프로젝트 생성하기&lt;/figcaption&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;&lt;a href=&quot;https://learn.microsoft.com/ko-kr/cpp/cpp/structured-exception-handling-c-cpp?view=msvc-170&quot;&gt;https://learn.microsoft.com/ko-kr/cpp/cpp/structured-exception-handling-c-cpp?view=msvc-170&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1664364387350&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;Structured Exception Handling (C/C++)&quot; data-og-description=&quot;Microsoft C/C++의 구조적 예외 처리 개요입니다.&quot; data-og-host=&quot;learn.microsoft.com&quot; data-og-source-url=&quot;https://learn.microsoft.com/ko-kr/cpp/cpp/structured-exception-handling-c-cpp?view=msvc-170&quot; data-og-url=&quot;https://learn.microsoft.com/ko-kr/cpp/cpp/structured-exception-handling-c-cpp&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/lV0pd/hyPXPeVxGo/SgtwgBT93z737eeCzmkBbk/img.png?width=400&amp;amp;height=400&amp;amp;face=0_0_400_400&quot;&gt;&lt;a href=&quot;https://learn.microsoft.com/ko-kr/cpp/cpp/structured-exception-handling-c-cpp?view=msvc-170&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://learn.microsoft.com/ko-kr/cpp/cpp/structured-exception-handling-c-cpp?view=msvc-170&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/lV0pd/hyPXPeVxGo/SgtwgBT93z737eeCzmkBbk/img.png?width=400&amp;amp;height=400&amp;amp;face=0_0_400_400');&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;Structured Exception Handling (C/C++)&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Microsoft C/C++의 구조적 예외 처리 개요입니다.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;learn.microsoft.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;pre id=&quot;code_1664364399125&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;Windows.h&amp;gt;
#include &amp;lt;exception&amp;gt;

class TestClass
{
public:
    ~TestClass()
    {
        printf(&quot;Destroying TestClass!\r\n&quot;);
    }
};

__declspec(noinline) void TestCPPEX()
{
#ifdef CPPEX
    printf(&quot;Throwing C++ exception\r\n&quot;);
    throw std::exception(&quot;&quot;);
#else
    printf(&quot;Triggering SEH exception\r\n&quot;);
    volatile int *pInt = 0x00000000;
    *pInt = 20;
#endif
}

__declspec(noinline) void TestExceptions()
{
    TestClass d;
    TestCPPEX();
}

int main()
{
    __try
    {
        TestExceptions();
    }
    __except(EXCEPTION_EXECUTE_HANDLER)
    {
        printf(&quot;Executing SEH __except block\r\n&quot;);
    }

    return 0;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 예제 코드를 실행하면 다음과 같은 결과가 표시됩니다.&lt;/p&gt;
&lt;pre id=&quot;code_1664364460384&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Triggering SEH exception //24번 째
Executing SEH __except block //44번 째&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로그램을 실행하면 &lt;code&gt;&lt;span class=&quot;token function&quot;&gt;CPPEX&lt;/span&gt;&lt;/code&gt;가 정의되어 있지 않아 24번째 메시지가 출력되고, &lt;u&gt;잘못된 메모리 주소에 접근을 시도&lt;/u&gt;하게 됩니다. 그리고 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;__except&lt;/span&gt;&lt;/code&gt; 필터에 의해 44번째 메시지가 출력되는 동작입니다. 여기서, TestClass 객체의 &lt;u&gt;소멸자가 정의되어 있는데 호출되지 않은 것&lt;/u&gt;을 알 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약, 프로젝트 속성의 명령줄에 &lt;code&gt;&lt;span class=&quot;token function&quot;&gt;/DCPPEX&lt;/span&gt;&lt;/code&gt;를 추가하면 결과는 달라집니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;553&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bmWMGa/btrOgzffl7w/qV1y1PmoMjLBKCyT6li7V1/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bmWMGa/btrOgzffl7w/qV1y1PmoMjLBKCyT6li7V1/img.webp&quot; data-alt=&quot;C++ 명령줄에 옵션 추가하기&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bmWMGa/btrOgzffl7w/qV1y1PmoMjLBKCyT6li7V1/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbmWMGa%2FbtrOgzffl7w%2FqV1y1PmoMjLBKCyT6li7V1%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; alt=&quot;C++-명령줄에-옵션-추가하기&quot; loading=&quot;lazy&quot; width=&quot;800&quot; height=&quot;553&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;553&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;C++ 명령줄에 옵션 추가하기&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래와 같이 14번째 줄의 메시지가 출력됩니다.&lt;/p&gt;
&lt;pre id=&quot;code_1664372440886&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Throwing C++ exception
Destroying TestClass! //14번 째
Executing SEH __except block&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;&lt;span class=&quot;token function&quot;&gt;/DCPPEX&lt;/span&gt;&lt;/code&gt; 명령줄을 추가하면 &lt;code&gt;&lt;span class=&quot;token function&quot;&gt;CPPEX&lt;/span&gt;&lt;/code&gt;가 정의되어 C++ 예외인 throw가 호출되면서 소멸자가 호출되기 때문입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마지막으로, &lt;u&gt;C++ 예외와 SEH를 같이 사용하고 싶다면&lt;/u&gt; C++ 예외 처리 가능 옵션을 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;/EHa&lt;/span&gt;&lt;/code&gt;로 변경하면 됩니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;618&quot; data-origin-height=&quot;114&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/clJdtL/btrOcgHvzXB/9O3zuRfPtcOsHsEM6WYsz1/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/clJdtL/btrOcgHvzXB/9O3zuRfPtcOsHsEM6WYsz1/img.webp&quot; data-alt=&quot;C++ 예외 처리 옵션 변경&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/clJdtL/btrOcgHvzXB/9O3zuRfPtcOsHsEM6WYsz1/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FclJdtL%2FbtrOcgHvzXB%2F9O3zuRfPtcOsHsEM6WYsz1%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; alt=&quot;C++-예외-처리-옵션-변경&quot; loading=&quot;lazy&quot; width=&quot;618&quot; height=&quot;114&quot; data-origin-width=&quot;618&quot; data-origin-height=&quot;114&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;C++ 예외 처리 옵션 변경&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 옵션을 변경하면 명령줄에 &lt;code&gt;&lt;span class=&quot;token function&quot;&gt;/DCPPEX&lt;/span&gt;&lt;/code&gt;가 있든 없든 상관없이, 소멸자가 정상적으로 호출됩니다.&lt;/p&gt;
&lt;pre id=&quot;code_1664372705755&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Throwing C++ exception
Destroying TestClass! //14번 째
Executing SEH __except block&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Programming</category>
      <category>예외처리</category>
      <author>❤ </author>
      <guid isPermaLink="true">https://luckygg.tistory.com/375</guid>
      <comments>https://luckygg.tistory.com/375#entry375comment</comments>
      <pubDate>Tue, 18 Oct 2022 21:40:59 +0900</pubDate>
    </item>
    <item>
      <title>프로그램에서 일반적인 예외 처리(Exception Handling)하는 방법</title>
      <link>https://luckygg.tistory.com/370</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;예외 처리가 왜 필요할까요?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로그램의 예외 처리는 아주 중요합니다. 내가 만든 프로그램이 &lt;u&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;모든 상황에서 항상 잘 동작할 것이라는 보장을 할 수 없기 때문&lt;/span&gt;&lt;/u&gt;이죠. 아무리 잘 만들었다고 해도, 막상 사용자가 사용하는 환경이나 조작 방법에 따라 무슨 문제가 발생할지는 알 수가 없습니다.&lt;/p&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;code&gt;&lt;span class=&quot;token keyword&quot;&gt;에러 처리(Error Handling)&lt;/span&gt;&lt;/code&gt;와 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;예외 처리(Exception Handling)&lt;/span&gt;&lt;/code&gt; 모두를 통칭하는 표현입니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;예외를 처리하는 방법&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예외(또는 오류)를 처리하는 방법은 일반적으로 다음의 세 가지가 있습니다. 앞으로 언급할 세 가지 외에도 또 다른 방법이 있을 수도 있고, 어떤 방법이 옳고 그르다기보다는 아주 보편적이다라는 의미로 소개합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. 오류 무시하기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다소 황당할 수도 있는 방법이지만, 은연중에 그렇게 사용하고 있을 수도 있습니다. 예를 들어, 문자열을 출력하는 다음 함수를 보겠습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1658628811210&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;int printf_s(
   const char *format [,
   argument]...
);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://docs.microsoft.com/ko-kr/cpp/c-runtime-library/reference/printf-s-printf-s-l-wprintf-s-wprintf-s-l?view=msvc-170&quot;&gt;https://docs.microsoft.com/ko-kr/cpp/c-runtime-library/reference/printf-s-printf-s-l-wprintf-s-wprintf-s-l?view=msvc-170&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1659257022824&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;printf_s, _printf_s_l, wprintf_s, _wprintf_s_l&quot; data-og-description=&quot;자세한 정보: printf_s, _printf_s_l, wprintf_s, _wprintf_s_l&quot; data-og-host=&quot;docs.microsoft.com&quot; data-og-source-url=&quot;https://docs.microsoft.com/ko-kr/cpp/c-runtime-library/reference/printf-s-printf-s-l-wprintf-s-wprintf-s-l?view=msvc-170&quot; data-og-url=&quot;https://docs.microsoft.com/ko-kr/cpp/c-runtime-library/reference/printf-s-printf-s-l-wprintf-s-wprintf-s-l&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bzorxX/hyPhqNUgDd/f0K43NhWoryDDk2oOF35d0/img.png?width=400&amp;amp;height=400&amp;amp;face=0_0_400_400&quot;&gt;&lt;a href=&quot;https://docs.microsoft.com/ko-kr/cpp/c-runtime-library/reference/printf-s-printf-s-l-wprintf-s-wprintf-s-l?view=msvc-170&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://docs.microsoft.com/ko-kr/cpp/c-runtime-library/reference/printf-s-printf-s-l-wprintf-s-wprintf-s-l?view=msvc-170&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bzorxX/hyPhqNUgDd/f0K43NhWoryDDk2oOF35d0/img.png?width=400&amp;amp;height=400&amp;amp;face=0_0_400_400');&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;printf_s, _printf_s_l, wprintf_s, _wprintf_s_l&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;자세한 정보: printf_s, _printf_s_l, wprintf_s, _wprintf_s_l&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;docs.microsoft.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&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;h3 data-ke-size=&quot;size23&quot;&gt;2. 에러 코드(Error Code) 반환하기 - Error Handling&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;특정 함수를 호출하면 성공 여부를 정수로 반환하는 방식&lt;/u&gt;을 많이 접해봤을 텐데요. 에러 코드 반환하기가 바로 그런 방법입니다. 함수 호출 성공 여부를 &lt;code&gt;&lt;span class=&quot;token number&quot;&gt;boolean&lt;/span&gt;&lt;/code&gt;으로 반환할 수도 있고, &lt;code&gt;&lt;span class=&quot;token number&quot;&gt;int&lt;/span&gt;&lt;/code&gt;나 에러를 정의한 &lt;code&gt;&lt;span class=&quot;token number&quot;&gt;struct&lt;/span&gt;&lt;/code&gt;로 반환하는 방법이 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만, 이러한 코드는 지저분한 코드를 야기합니다. 대부분의 서적에서도 언급하는 내용인데요. 항상 함수를 호출하고 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;if-else 문&lt;/span&gt;&lt;/code&gt;으로 에러를 확인하기 때문이죠.&lt;/p&gt;
&lt;pre id=&quot;code_1658629615678&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;int result = doSomething();
if (result == 0)
{
    //동작 성공
}
else if (result == -1)
{
    //에러1
}
else if (result == -2)
{
    //에러2
}
//...&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;물론, 보통은 다음과 같이 사용하기도 합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1658629728910&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;int result = doSomething();
if (result != 0)
{
    //오류 보고
}
//...&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 방법론의 핵심은, 매번 오류 코드를 확인해야 하는 번거로움과 반환 코드에 따라 if-else문이 많아지면 유지보수에 까다로움이 있다는 것이죠.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. 예외(Exception) 사용하기 - Exception Handling&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어느 서적이나 예외를 소개하는 파트가 있다면, 다들 &lt;u&gt;예외를 사용하라고 권장&lt;/u&gt;합니다(물론, 항상 좋은 점만 있는 것은 아니죠). &lt;u&gt;코드가 간결&lt;/u&gt;해지고, 예외가 발생했을 때 &lt;u&gt;오류를 보고하고 조치하기가 간편&lt;/u&gt;하며 &lt;u&gt;예외를 발생시킨 원인에 따라 다른 작업을 수행&lt;/u&gt;하도록 코드를 작성할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예외를 사용하기 위한 C++ 문법은 아주 간단합니다(본문에서는 문법에 대해 상세히 설명하지 않습니다).&lt;/p&gt;
&lt;pre id=&quot;code_1658642645290&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//C++
void doSomething()
{
    //...
    thorw std::exception(&quot;예외 메시지&quot;);
}

int main()
{
    try
    {
        doSomething();
    }
    catch(const std::exception &amp;amp;e)
    {
        //e.what();
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특정 함수에서 작업을 수행하다가 문제가 발생하면 예외를 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;던집(throw)&lt;/span&gt;&lt;/code&gt;니다. 던져진 예외는 가장 가까운 &lt;code&gt;&lt;span class=&quot;token function-name&quot;&gt;try-catch 블록&lt;/span&gt;&lt;/code&gt;까지 자동으로 전파되고, &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt;&lt;/code&gt;된 예외에서 오류 메시지를 확인할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특히 C#에서는 Exception 객체의 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;StackTrace&lt;/span&gt;&lt;/code&gt;를 통해 어디서 예외가 던져졌는지 확인할 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1658643287944&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;static void doSomething()
{
    throw new Exception(&quot;예외 발생!&quot;);
}

static void Main(string[] args)
{
    try
    {
        doSomething();
    }
    catch(Exception exc)
    {
        Console.WriteLine(exc.StackTrace);
        Console.WriteLine(exc.Message);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 코드를 실행하면 StackTrace를 통해 예외 메시지와 예외가 던져진 소스 코드의 위치를 알 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;381&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/zKceL/btrIy0cXxmf/nsHxXXCdQ8WtKK4Ky2lPP1/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/zKceL/btrIy0cXxmf/nsHxXXCdQ8WtKK4Ky2lPP1/img.webp&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/zKceL/btrIy0cXxmf/nsHxXXCdQ8WtKK4Ky2lPP1/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FzKceL%2FbtrIy0cXxmf%2FnsHxXXCdQ8WtKK4Ky2lPP1%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;800&quot; height=&quot;381&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;381&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;참고&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;C++ For Game Programmers - Second Edition, Michale J. Dickheiser&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Programming</category>
      <category>예외처리</category>
      <author>❤ </author>
      <guid isPermaLink="true">https://luckygg.tistory.com/370</guid>
      <comments>https://luckygg.tistory.com/370#entry370comment</comments>
      <pubDate>Sat, 15 Oct 2022 17:59:03 +0900</pubDate>
    </item>
    <item>
      <title>예외 스택 풀기(Stack Unwinding)와 프로그램 성능 영향</title>
      <link>https://luckygg.tistory.com/372</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;스택 풀기(Stack Unwinding)란?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;예외가 발생한 함수에서 예외가 처리되지 않으면, 상위 함수로 돌아가 예외가 처리되기를 시도&lt;/u&gt;합니다. 만약, 상위 함수에도 없다면 다시 그 위의 상위 함수로 돌아가며 반복하게 됩니다. 만약, 예외가 발생했는데 어느 곳에서도 &lt;code&gt;&lt;span class=&quot;token function-name&quot;&gt;try-catch 문&lt;/span&gt;&lt;/code&gt;이 없다면 &lt;u&gt;프로그램은 종료&lt;/u&gt;되고 맙니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 이전에 호출된 함수로 계속 돌아가는 것을 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;스택 풀기(Stack Unwinding)&lt;/span&gt;&lt;/code&gt;라고 합니다. 다음의 예제 코드를 보겠습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1658931760512&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;namespace ExamException
{
    class Program
    {
        static void func1()
        {
            func2();
        }

        static void func2()
        {
            func3();
        }

        static void func3()
        {
            throw new Exception(&quot;예외 발생!&quot;);
        }

        static void Main(string[] args)
        {
            func1();
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Main&lt;/b&gt; 함수에서 &lt;b&gt;func1()&lt;/b&gt;을 호출하면, &lt;b&gt;func2()&lt;/b&gt;, &lt;b&gt;func3()&lt;/b&gt;이 차례대로 호출되고, func3()에서 예외가 발생하는 코드입니다. 예외가 발생하는 지점에 &lt;b&gt;Break point&lt;/b&gt;를 지정하고, 디버깅을 실행한 후 비주얼 스튜디오의 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;호출 스택(Call Stack)&lt;/span&gt;&lt;/code&gt; 창을 열어보겠습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;119&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Cf3Wa/btrOeQH66gH/6WV6jB1ISW9BZYQdsqaDK0/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Cf3Wa/btrOeQH66gH/6WV6jB1ISW9BZYQdsqaDK0/img.webp&quot; data-alt=&quot;호출 스택 화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Cf3Wa/btrOeQH66gH/6WV6jB1ISW9BZYQdsqaDK0/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FCf3Wa%2FbtrOeQH66gH%2F6WV6jB1ISW9BZYQdsqaDK0%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; alt=&quot;호출 스택 화면&quot; loading=&quot;lazy&quot; width=&quot;119&quot; data-origin-width=&quot;119&quot; data-origin-height=&quot;0&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;호출 스택 맨 아래에 Main 함수를 시작으로, 차례대로 func1(), func2(), func3()이 기록되어 있습니다. 이것이 스택에 쌓여있는 함수의 호출 목록이며, func3()에서 예외가 발생했으니 try-catch에 도달할 때까지 func2(), func1(), Main 함수까지 돌아가는 것이죠. 이것을 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;스택 풀기&lt;/b&gt;&lt;/span&gt;라고 합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스택 풀기.png&quot; data-origin-width=&quot;577&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bGhuIy/btrOchTGRoe/QZq8L3EzjnPDvPqfKgyVQ1/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bGhuIy/btrOchTGRoe/QZq8L3EzjnPDvPqfKgyVQ1/img.webp&quot; data-alt=&quot;스택이 쌓이고 풀리는 과정&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bGhuIy/btrOchTGRoe/QZq8L3EzjnPDvPqfKgyVQ1/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbGhuIy%2FbtrOchTGRoe%2FQZq8L3EzjnPDvPqfKgyVQ1%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; alt=&quot;스택이 쌓이고 풀리는 과정&quot; loading=&quot;lazy&quot; width=&quot;400&quot; height=&quot;386&quot; data-filename=&quot;스택 풀기.png&quot; data-origin-width=&quot;577&quot; data-origin-height=&quot;0&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;h2 data-ke-size=&quot;size26&quot;&gt;예외와 프로그램 성능 영향&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위에서 언급한 대로, 스택을 푸는 과정에서 &lt;b&gt;Stack Trace&lt;/b&gt;와 같은 예외 정보를 가지다 보니, 예외가 발생하면 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;오버헤드(Overhaed)&lt;/span&gt;&lt;/code&gt;가 발생하게 됩니다. 그리고 이를 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;예외 비용(Exception cost)&lt;/span&gt;&lt;/code&gt;이라고도 부릅니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데 여기서 오해의 소지가 있는데요. 예외 처리를 사용하면 항상 오버헤드가 발생하는 것이 아닙니다. 즉, &lt;code&gt;&lt;span class=&quot;token function-name&quot;&gt;try-catch 블록&lt;/span&gt;&lt;/code&gt;을 사용한다고 항상 성능에 영향을 미치는 것이 아니라는 뜻입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실 try-catch 블록을 사용하더라도 &lt;u&gt;예외가 발생하지 않으면 성능 저하가 거의 없다&lt;/u&gt;고 볼 수 있습니다. 이에 대한 성능 검증은 구글링을 통해 쉽게 찾아볼 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://pspdfkit.com/blog/2020/performance-overhead-of-exceptions-in-cpp/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://pspdfkit.com/blog/2020/performance-overhead-of-exceptions-in-cpp/&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1665387258602&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;Investigating the Performance Overhead of C++ Exceptions | PSPDFKit&quot; data-og-description=&quot;C++ exceptions have their place, but using an alternative is recommended for general program flow control.&quot; data-og-host=&quot;pspdfkit.com&quot; data-og-source-url=&quot;https://pspdfkit.com/blog/2020/performance-overhead-of-exceptions-in-cpp/&quot; data-og-url=&quot;https://pspdfkit.com/blog/2020/performance-overhead-of-exceptions-in-cpp/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/ybUGt/hyP6wtgQeS/LM5lYUSyB9CUzKcixNSUJK/img.png?width=2000&amp;amp;height=1000&amp;amp;face=0_0_2000_1000&quot;&gt;&lt;a href=&quot;https://pspdfkit.com/blog/2020/performance-overhead-of-exceptions-in-cpp/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://pspdfkit.com/blog/2020/performance-overhead-of-exceptions-in-cpp/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/ybUGt/hyP6wtgQeS/LM5lYUSyB9CUzKcixNSUJK/img.png?width=2000&amp;amp;height=1000&amp;amp;face=0_0_2000_1000');&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;Investigating the Performance Overhead of C++ Exceptions | PSPDFKit&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;C++ exceptions have their place, but using an alternative is recommended for general program flow control.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;pspdfkit.com&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://yesarang.tistory.com/371&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://yesarang.tistory.com/371&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1658924944480&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;C++ 이야기 서른두번째: 예외가 성능에 미치는 영향&quot; data-og-description=&quot;2009/09/25 - [S/W개발/C++ 이야기] - C++ 이야기 서른한번째: 왜 예외를 쓰는 게 좋을까요? 에서 왜 예외를 쓰는 것이 좋은지에 대해 얘기를 해 봤습니다. 정리해서 말씀드리자면 결함내성 특성(fault-tol&quot; data-og-host=&quot;yesarang.tistory.com&quot; data-og-source-url=&quot;https://yesarang.tistory.com/371&quot; data-og-url=&quot;https://yesarang.tistory.com/371&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bByMia/hyPc7JzmGc/D2CsUYZNw9v6PEwCFQKv70/img.jpg?width=757&amp;amp;height=647&amp;amp;face=0_0_757_647,https://scrap.kakaocdn.net/dn/vHzmd/hyPc5E1eJr/rEqYQO5eHzuwK1ria5uo40/img.jpg?width=757&amp;amp;height=647&amp;amp;face=0_0_757_647,https://scrap.kakaocdn.net/dn/ggTlm/hyPeIuDzW8/qUPK0g8GlimrKBCkBroICk/img.jpg?width=757&amp;amp;height=647&amp;amp;face=0_0_757_647&quot;&gt;&lt;a href=&quot;https://yesarang.tistory.com/371&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://yesarang.tistory.com/371&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bByMia/hyPc7JzmGc/D2CsUYZNw9v6PEwCFQKv70/img.jpg?width=757&amp;amp;height=647&amp;amp;face=0_0_757_647,https://scrap.kakaocdn.net/dn/vHzmd/hyPc5E1eJr/rEqYQO5eHzuwK1ria5uo40/img.jpg?width=757&amp;amp;height=647&amp;amp;face=0_0_757_647,https://scrap.kakaocdn.net/dn/ggTlm/hyPeIuDzW8/qUPK0g8GlimrKBCkBroICk/img.jpg?width=757&amp;amp;height=647&amp;amp;face=0_0_757_647');&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++ 이야기 서른두번째: 예외가 성능에 미치는 영향&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;2009/09/25 - [S/W개발/C++ 이야기] - C++ 이야기 서른한번째: 왜 예외를 쓰는 게 좋을까요? 에서 왜 예외를 쓰는 것이 좋은지에 대해 얘기를 해 봤습니다. 정리해서 말씀드리자면 결함내성 특성(fault-tol&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;yesarang.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;결론&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;분명히 &lt;u&gt;try-catch 문을 사용한 예외 처리&lt;/u&gt;가 에러 코드 반환형 보다는 더 &lt;u&gt;가독성 있고 견고한 프로그램&lt;/u&gt;을 만들 수 있습니다. 하지만 그렇다고 무분별하게 모든 곳에 try-catch를 사용했다간 &lt;u&gt;성능 저하&lt;/u&gt;를 겪게 됩니다. 따라서, 예상이 되는 곳에는 조건 문으로 예외를 처리하고, 예상이 되지 않는 곳에 try-catch를 복합적으로 사용하는 것이 좋습니다.&lt;/p&gt;</description>
      <category>Programming</category>
      <category>예외처리</category>
      <author>❤ </author>
      <guid isPermaLink="true">https://luckygg.tistory.com/372</guid>
      <comments>https://luckygg.tistory.com/372#entry372comment</comments>
      <pubDate>Wed, 12 Oct 2022 17:44:12 +0900</pubDate>
    </item>
    <item>
      <title>[VTK] CMake 빌드 및 Visual Studio 환경 구성</title>
      <link>https://luckygg.tistory.com/376</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;VTK 라이브러리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;VTK 라이브러리를 사용하기 위해서는 &lt;u&gt;사용자의 환경에 맞춰 직접 CMake로 빌드&lt;/u&gt;해야 합니다. 예를 들어, Visual Studio 버전이라든가, 32bit 또는 64bit에 맞는 환경으로 빌드해야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이전에도 VTK CMake 빌드와 Visual Studio 프로젝트 환경 설정 방법에 대해 다룬 글이 있는데요. VTK와 Visual Studio 버전이 낮아 좀 더 상위 버전에 맞춰 포스팅을 새로 하게 됐습니다. 이전 글은 아래 링크를 참고하세요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://luckygg.tistory.com/125&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;[VTK] VTK 8.2 및 Visual Studio 2015 환경 구성&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1665323819023&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;[VTK] VTK 8.2 및 Visual Studio 2015 환경 구성&quot; data-og-description=&quot;VTK를 사용하기 위해서는 준비 과정이 다소 길고 복잡합니다. 본 글에서는 차례차례 쉽게 따라 할 수 있도록 정리해 보았습니다. ※ 2019년 7월 3일 추가 혹시 아래 빌드 과정이 안 되는 분들을 위&quot; data-og-host=&quot;luckygg.tistory.com&quot; data-og-source-url=&quot;https://luckygg.tistory.com/125&quot; data-og-url=&quot;https://luckygg.tistory.com/125&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/zxDd8/hyP4BvRzOu/SpwJgx2IwNpZUOkfTNiCf1/img.png?width=300&amp;amp;height=161&amp;amp;face=0_0_300_161,https://scrap.kakaocdn.net/dn/be9Qtn/hyP6uhyjB7/AzXBKGhlVVZCkApLsrbseK/img.png?width=300&amp;amp;height=161&amp;amp;face=0_0_300_161,https://scrap.kakaocdn.net/dn/VPsFF/hyP4I2Ndo3/cNHqR2J5F68kcKsESDZEw0/img.png?width=609&amp;amp;height=615&amp;amp;face=0_0_609_615&quot;&gt;&lt;a href=&quot;https://luckygg.tistory.com/125&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://luckygg.tistory.com/125&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/zxDd8/hyP4BvRzOu/SpwJgx2IwNpZUOkfTNiCf1/img.png?width=300&amp;amp;height=161&amp;amp;face=0_0_300_161,https://scrap.kakaocdn.net/dn/be9Qtn/hyP6uhyjB7/AzXBKGhlVVZCkApLsrbseK/img.png?width=300&amp;amp;height=161&amp;amp;face=0_0_300_161,https://scrap.kakaocdn.net/dn/VPsFF/hyP4I2Ndo3/cNHqR2J5F68kcKsESDZEw0/img.png?width=609&amp;amp;height=615&amp;amp;face=0_0_609_615');&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;[VTK] VTK 8.2 및 Visual Studio 2015 환경 구성&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;VTK를 사용하기 위해서는 준비 과정이 다소 길고 복잡합니다. 본 글에서는 차례차례 쉽게 따라 할 수 있도록 정리해 보았습니다. ※ 2019년 7월 3일 추가 혹시 아래 빌드 과정이 안 되는 분들을 위&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;luckygg.tistory.com&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://luckygg.tistory.com/130&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;[VTK] Visual Studio 2015 MFC에서 VTK 사용 준비하기&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1665330702575&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;[VTK] Visual Studio 2015 MFC에서 VTK 사용 준비하기&quot; data-og-description=&quot;이번 포스팅에서는 Visual Studio 2015 MFC 환경에서 VTK SDK를 사용하는 방법을 소개하고자 합니다. 먼저, VTK를 준비하는 방법은 아래 링크를 참고해주세요. [VTK] VTK 8.2 및 Visual Studio 2015 환경 구성 1...&quot; data-og-host=&quot;luckygg.tistory.com&quot; data-og-source-url=&quot;https://luckygg.tistory.com/130&quot; data-og-url=&quot;https://luckygg.tistory.com/130&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bP0liP/hyP6ouUqBW/ngYaZ8pgGbgyc2CcIr0wfk/img.png?width=800&amp;amp;height=568&amp;amp;face=0_0_800_568,https://scrap.kakaocdn.net/dn/TquM7/hyP6uhA9cm/M4NxIJkLLRYgyCM86yOqvk/img.png?width=800&amp;amp;height=568&amp;amp;face=0_0_800_568,https://scrap.kakaocdn.net/dn/b1O1sy/hyP6y5my7Q/CjGGEU8QiP18lwG8mSTqr0/img.png?width=849&amp;amp;height=603&amp;amp;face=0_0_849_603&quot;&gt;&lt;a href=&quot;https://luckygg.tistory.com/130&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://luckygg.tistory.com/130&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bP0liP/hyP6ouUqBW/ngYaZ8pgGbgyc2CcIr0wfk/img.png?width=800&amp;amp;height=568&amp;amp;face=0_0_800_568,https://scrap.kakaocdn.net/dn/TquM7/hyP6uhA9cm/M4NxIJkLLRYgyCM86yOqvk/img.png?width=800&amp;amp;height=568&amp;amp;face=0_0_800_568,https://scrap.kakaocdn.net/dn/b1O1sy/hyP6y5my7Q/CjGGEU8QiP18lwG8mSTqr0/img.png?width=849&amp;amp;height=603&amp;amp;face=0_0_849_603');&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;[VTK] Visual Studio 2015 MFC에서 VTK 사용 준비하기&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;이번 포스팅에서는 Visual Studio 2015 MFC 환경에서 VTK SDK를 사용하는 방법을 소개하고자 합니다. 먼저, VTK를 준비하는 방법은 아래 링크를 참고해주세요. [VTK] VTK 8.2 및 Visual Studio 2015 환경 구성 1...&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;luckygg.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;VTK 준비하기&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. CMake 설치하기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;VTK를 빌드하기 위해 &lt;u&gt;CMake 프로그램을 설치&lt;/u&gt;해야 합니다. 거의 대부분의 오픈 소스는 이 CMake 프로그램을 사용하여 라이브러리를 빌드할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://luckygg.tistory.com/121&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;[CMake] CMake 설치하기&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1665324080652&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;[CMake] CMake 설치하기&quot; data-og-description=&quot;CMake는 사용자가 원하는 개발환경의 라이브러리 생성을 도와주는 오픈 소스 도구입니다. OpenCV나 VTK 혹은 각 제조사에서 제공하는 SDK를 개발환경에 따라 라이브러리를 새로 생성할 때 사용됩니&quot; data-og-host=&quot;luckygg.tistory.com&quot; data-og-source-url=&quot;https://luckygg.tistory.com/121&quot; data-og-url=&quot;https://luckygg.tistory.com/121&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/dMUHpw/hyP4HbL0lW/BOuZxB9AC2qofJYaEOP2tK/img.png?width=256&amp;amp;height=256&amp;amp;face=0_0_256_256,https://scrap.kakaocdn.net/dn/5TIfn/hyP6CUbDyC/Dg5K4GKLottsNaMkWerss0/img.png?width=256&amp;amp;height=256&amp;amp;face=0_0_256_256,https://scrap.kakaocdn.net/dn/jzkhw/hyP4KGjfuI/2ZvIwDGqpB1MeqpifvJr91/img.png?width=860&amp;amp;height=547&amp;amp;face=0_0_860_547&quot;&gt;&lt;a href=&quot;https://luckygg.tistory.com/121&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://luckygg.tistory.com/121&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/dMUHpw/hyP4HbL0lW/BOuZxB9AC2qofJYaEOP2tK/img.png?width=256&amp;amp;height=256&amp;amp;face=0_0_256_256,https://scrap.kakaocdn.net/dn/5TIfn/hyP6CUbDyC/Dg5K4GKLottsNaMkWerss0/img.png?width=256&amp;amp;height=256&amp;amp;face=0_0_256_256,https://scrap.kakaocdn.net/dn/jzkhw/hyP4KGjfuI/2ZvIwDGqpB1MeqpifvJr91/img.png?width=860&amp;amp;height=547&amp;amp;face=0_0_860_547');&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;[CMake] CMake 설치하기&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;CMake는 사용자가 원하는 개발환경의 라이브러리 생성을 도와주는 오픈 소스 도구입니다. OpenCV나 VTK 혹은 각 제조사에서 제공하는 SDK를 개발환경에 따라 라이브러리를 새로 생성할 때 사용됩니&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;luckygg.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. VTK 라이브러리 소스 다운로드하기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;VTK 홈페이지에 접속하여 최신 버전을 다운로드합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;570&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/GloYa/btrN4OMdD6G/TAaMeigwAhAYRK1iWYzFlk/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/GloYa/btrN4OMdD6G/TAaMeigwAhAYRK1iWYzFlk/img.webp&quot; data-alt=&quot;VTK 소스 다운받기&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/GloYa/btrN4OMdD6G/TAaMeigwAhAYRK1iWYzFlk/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FGloYa%2FbtrN4OMdD6G%2FTAaMeigwAhAYRK1iWYzFlk%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; alt=&quot;VTK 소스 다운받기&quot; loading=&quot;lazy&quot; width=&quot;800&quot; height=&quot;570&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;570&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;VTK 소스 다운받기&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. Visual Studio 설치하기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용하려는 버전의 Visual Studio를 준비합니다. 본문에서는 Visual Studio 2019를 설치했습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;VTK 라이브러리 CMake 빌드하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CMake 프로그램을 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;관리자 권한&lt;/b&gt;&lt;/span&gt;으로 실행합니다. 그리고 &lt;b&gt;Source code&lt;/b&gt;와 &lt;b&gt;build 경로&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;799&quot; data-origin-height=&quot;407&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bLP5ko/btrOeQH5T9O/TReZQjkgvWnWYfCY1cElCk/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bLP5ko/btrOeQH5T9O/TReZQjkgvWnWYfCY1cElCk/img.webp&quot; data-alt=&quot;Source와 Build 경로 지정하기&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bLP5ko/btrOeQH5T9O/TReZQjkgvWnWYfCY1cElCk/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbLP5ko%2FbtrOeQH5T9O%2FTReZQjkgvWnWYfCY1cElCk%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; alt=&quot;Source와 Build 경로 지정하기&quot; loading=&quot;lazy&quot; width=&quot;799&quot; height=&quot;407&quot; data-origin-width=&quot;799&quot; data-origin-height=&quot;407&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Source와 Build 경로 지정하기&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style12&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;&lt;b&gt;항목&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;&lt;b&gt;설명&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;Where is the source code&lt;/td&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;VTK-X.Y.Z.tar.gz 압축 해제된 폴더의 경로&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;Where to build the binaries&lt;/td&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;Binary 파일이 생성될 비어있는 경로&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;좌측 하단의 &lt;b&gt;Configure 버튼&lt;/b&gt;을 클릭합니다. 그리고 아래의 창이 표시되면 사용하려는 &lt;u&gt;Visual Studio의 버전과 Platform(bit 수)을 선택&lt;/u&gt;합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;799&quot; data-origin-height=&quot;576&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/PkwiA/btrOfbekdmO/4RBVlua2mTkdhnxRdR8TZK/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/PkwiA/btrOfbekdmO/4RBVlua2mTkdhnxRdR8TZK/img.webp&quot; data-alt=&quot;CMake 빌드 환경 선택하기&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/PkwiA/btrOfbekdmO/4RBVlua2mTkdhnxRdR8TZK/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FPkwiA%2FbtrOfbekdmO%2F4RBVlua2mTkdhnxRdR8TZK%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; alt=&quot;CMake 빌드 환경 선택하기&quot; loading=&quot;lazy&quot; width=&quot;799&quot; height=&quot;576&quot; data-origin-width=&quot;799&quot; data-origin-height=&quot;576&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;CMake 빌드 환경 선택하기&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Finish 버튼&lt;/b&gt;을 클릭하면 아래와 같이 무언가 진행이 됩니다. PC 사양마다 다르지만, 약 3분 정도 소요됩니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;799&quot; data-origin-height=&quot;311&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eh86Jl/btrOgRfBQMb/BzTPJDW4rxkVRBTk2qJQmK/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eh86Jl/btrOgRfBQMb/BzTPJDW4rxkVRBTk2qJQmK/img.webp&quot; data-alt=&quot;Configure 이후&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eh86Jl/btrOgRfBQMb/BzTPJDW4rxkVRBTk2qJQmK/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Feh86Jl%2FbtrOgRfBQMb%2FBzTPJDW4rxkVRBTk2qJQmK%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; alt=&quot;Configure 이후&quot; loading=&quot;lazy&quot; width=&quot;799&quot; height=&quot;311&quot; data-origin-width=&quot;799&quot; data-origin-height=&quot;311&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Configure 이후&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후 아래와 같은 화면이 표시됩니다. VTK 예전 버전에서는 옵션 선택이 상당히 많았는데요. 9.2.2 기준으로는 옵션이 상당히 줄어들었습니다. &lt;u&gt;특별한 이유가 없다면 기본값 그대로 진행&lt;/u&gt;해도 문제는 없습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저의 경우에는 빌드된 VTK 라이브러리의 Debug/Release 경로를 구분하기 위해 아래와 같이 변경했습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1665325417876&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;C:/Program Files/VTK/${BUILD_TYPE}&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;800&quot; data-origin-height=&quot;1013&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bWcmoP/btrOdh0aFlt/qY9KbadYNfGj91c1aqR1I0/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bWcmoP/btrOdh0aFlt/qY9KbadYNfGj91c1aqR1I0/img.webp&quot; data-alt=&quot;CMake 옵션 선택 화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bWcmoP/btrOdh0aFlt/qY9KbadYNfGj91c1aqR1I0/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbWcmoP%2FbtrOdh0aFlt%2FqY9KbadYNfGj91c1aqR1I0%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; alt=&quot;CMake 옵션 선택 화면&quot; loading=&quot;lazy&quot; width=&quot;800&quot; height=&quot;1013&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;1013&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;CMake 옵션 선택 화면&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;옵션 선택이 끝났다면 &lt;b&gt;Generate 버튼&lt;/b&gt;을 클릭합니다. 이 작업은 금방 끝나며, &lt;b&gt;Open Project 버튼&lt;/b&gt;이 활성화가 됩니다. 이 버튼을 클릭하거나, &lt;u&gt;Visual Studio를 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;관리자 권한&lt;/b&gt;&lt;/span&gt;으로 실행&lt;/u&gt;한 후 &lt;u&gt;Binary 경로에 있는 VTK.sln 파일&lt;/u&gt;을 엽니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;799&quot; data-origin-height=&quot;391&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/pCQv4/btrN9lowSuw/Kmq6tSkCNquCfxVyWBZMD1/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/pCQv4/btrN9lowSuw/Kmq6tSkCNquCfxVyWBZMD1/img.webp&quot; data-alt=&quot;VTK.sln 열고 빌드하기&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/pCQv4/btrN9lowSuw/Kmq6tSkCNquCfxVyWBZMD1/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FpCQv4%2FbtrN9lowSuw%2FKmq6tSkCNquCfxVyWBZMD1%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; alt=&quot;VTK.sln 열고 빌드하기&quot; loading=&quot;lazy&quot; width=&quot;799&quot; height=&quot;391&quot; data-origin-width=&quot;799&quot; data-origin-height=&quot;391&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;VTK.sln 열고 빌드하기&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Visual Studio에서 VTK.sln 파일이 열리면 &lt;u&gt;INSTALL 프로젝트를 빌드&lt;/u&gt;합니다. 이 작업은 다소 시간이 걸립니다. 제 경우 약 15분이 걸렸습니다. Debug 모드의 빌드가 끝나면 &lt;u&gt;Release 모드로 변경하여 마저 빌드&lt;/u&gt;합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;빌드가 완료되면 CMake에서 지정한 경로에 다음과 같이 Debug/Release 각 폴더에 VTK 라이브러리 파일이 생성되어 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;286&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kKTSX/btrN5v6voq9/1kH4KVH4YNLUp1EKc53KLk/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kKTSX/btrN5v6voq9/1kH4KVH4YNLUp1EKc53KLk/img.webp&quot; data-alt=&quot;라이브러리 파일이 생성된 모습&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kKTSX/btrN5v6voq9/1kH4KVH4YNLUp1EKc53KLk/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkKTSX%2FbtrN5v6voq9%2F1kH4KVH4YNLUp1EKc53KLk%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; alt=&quot;라이브러리 파일이 생성된 모습&quot; loading=&quot;lazy&quot; width=&quot;800&quot; height=&quot;286&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;286&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;라이브러리 파일이 생성된 모습&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Visual Studio에서 VTK 라이브러리 환경 설정하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Visual Studio를 실행하고 C++ 콘솔 앱 프로젝트를 생성합니다. &lt;i&gt;&lt;b&gt;프로젝트 속성 &amp;gt; 디버깅 &amp;gt; 환경&lt;/b&gt;&lt;/i&gt;에 dll이 위치한 bin 폴더의 경로를 입력합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1665330814091&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;C:\Program Files\VTK\Debug\bin&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;800&quot; data-origin-height=&quot;557&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bkXrmJ/btrN8BrFsk7/uuwPpNOYlqmfZIPUFGhIkk/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bkXrmJ/btrN8BrFsk7/uuwPpNOYlqmfZIPUFGhIkk/img.webp&quot; data-alt=&quot;프로젝트 속성의 환경&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bkXrmJ/btrN8BrFsk7/uuwPpNOYlqmfZIPUFGhIkk/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbkXrmJ%2FbtrN8BrFsk7%2FuuwPpNOYlqmfZIPUFGhIkk%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; alt=&quot;프로젝트 속성의 환경&quot; loading=&quot;lazy&quot; width=&quot;800&quot; height=&quot;557&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;557&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;i&gt;&lt;b&gt;프로젝트 속성 &amp;gt; C/C++ &amp;gt; 일반 &amp;gt; 추가 포함 디렉터리&lt;/b&gt;&lt;/i&gt;에 VTK 라이브러리의 &lt;b&gt;include 경로&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;800&quot; data-origin-height=&quot;630&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/5harQ/btrOfbrQ3ll/4EkgTzJwIl2KkWqZGuOWh1/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/5harQ/btrOfbrQ3ll/4EkgTzJwIl2KkWqZGuOWh1/img.webp&quot; data-alt=&quot;프로젝트의 include 경로&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/5harQ/btrOfbrQ3ll/4EkgTzJwIl2KkWqZGuOWh1/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F5harQ%2FbtrOfbrQ3ll%2F4EkgTzJwIl2KkWqZGuOWh1%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; alt=&quot;프로젝트의 include 경로&quot; loading=&quot;lazy&quot; width=&quot;800&quot; height=&quot;630&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;630&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;프로젝트의 include 경로&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;&lt;b&gt;프로젝트 속성 &amp;gt; 링커 &amp;gt; 일반 &amp;gt; 추가 라이브러리 디렉터리&lt;/b&gt;&lt;/i&gt;에 VTK 라이브러리의 &lt;b&gt;lib 경로&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;800&quot; data-origin-height=&quot;630&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rBws3/btrOgxBu9A7/16ESeuT9QDEiGIWkMzm0Fk/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rBws3/btrOgxBu9A7/16ESeuT9QDEiGIWkMzm0Fk/img.webp&quot; data-alt=&quot;프로젝트의 lib 경로&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rBws3/btrOgxBu9A7/16ESeuT9QDEiGIWkMzm0Fk/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FrBws3%2FbtrOgxBu9A7%2F16ESeuT9QDEiGIWkMzm0Fk%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; alt=&quot;프로젝트의 lib 경로&quot; loading=&quot;lazy&quot; width=&quot;800&quot; height=&quot;630&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;630&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;프로젝트의 lib 경로&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마지막으로 &lt;i&gt;&lt;b&gt;프로젝트 속성 &amp;gt; 링커 &amp;gt; 일반 &amp;gt; 입력 &amp;gt; 추가 종속성&lt;/b&gt;&lt;/i&gt;&lt;span&gt;에 VTK 라이브러리의&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;b&gt;lib 파일&lt;/b&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;800&quot; data-origin-height=&quot;630&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/p0loG/btrN5GfUnwq/nfF1bEglsSlC0MezK6ZcF1/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/p0loG/btrN5GfUnwq/nfF1bEglsSlC0MezK6ZcF1/img.webp&quot; data-alt=&quot;프로젝트의 lib 파일 목록&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/p0loG/btrN5GfUnwq/nfF1bEglsSlC0MezK6ZcF1/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fp0loG%2FbtrN5GfUnwq%2FnfF1bEglsSlC0MezK6ZcF1%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; alt=&quot;프로젝트의 lib 파일 목록&quot; loading=&quot;lazy&quot; width=&quot;800&quot; height=&quot;630&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;630&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;프로젝트의 lib 파일 목록&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;lib 파일 목록을 쉽게 얻는 방법은 아래 링크를 참고하세요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://luckygg.tistory.com/129&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;[MFC] lib, dll 폴더의 파일 목록 쉽게 얻는 방법&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1665331228367&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;[MFC] lib, dll 폴더의 파일 목록 쉽게 얻는 방법&quot; data-og-description=&quot;가끔 외부 Library를 사용하다 보면 lib, dll 파일을 프로젝트 설정에 입력해야 하는 경우가 있는데요. OpenCV의 경우에는 파일이 몇 가지 없지만, VTK의 경우에는 수 십개의 파일이 존재하다 보니 일일&quot; data-og-host=&quot;luckygg.tistory.com&quot; data-og-source-url=&quot;https://luckygg.tistory.com/129&quot; data-og-url=&quot;https://luckygg.tistory.com/129&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/mFV31/hyP6x6sAjp/O8LMeWzfjeNAHxVhRmXUr0/img.png?width=399&amp;amp;height=206&amp;amp;face=0_0_399_206,https://scrap.kakaocdn.net/dn/oxfYM/hyP4FSzp3q/A1NS2xBXJiGF6FGZEf61EK/img.png?width=399&amp;amp;height=206&amp;amp;face=0_0_399_206,https://scrap.kakaocdn.net/dn/cDkuUY/hyP6tQw4Vc/QOwvfVkW81qWrQAfVbSKKk/img.png?width=499&amp;amp;height=332&amp;amp;face=0_0_499_332&quot;&gt;&lt;a href=&quot;https://luckygg.tistory.com/129&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://luckygg.tistory.com/129&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/mFV31/hyP6x6sAjp/O8LMeWzfjeNAHxVhRmXUr0/img.png?width=399&amp;amp;height=206&amp;amp;face=0_0_399_206,https://scrap.kakaocdn.net/dn/oxfYM/hyP4FSzp3q/A1NS2xBXJiGF6FGZEf61EK/img.png?width=399&amp;amp;height=206&amp;amp;face=0_0_399_206,https://scrap.kakaocdn.net/dn/cDkuUY/hyP6tQw4Vc/QOwvfVkW81qWrQAfVbSKKk/img.png?width=499&amp;amp;height=332&amp;amp;face=0_0_499_332');&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;[MFC] lib, dll 폴더의 파일 목록 쉽게 얻는 방법&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;가끔 외부 Library를 사용하다 보면 lib, dll 파일을 프로젝트 설정에 입력해야 하는 경우가 있는데요. OpenCV의 경우에는 파일이 몇 가지 없지만, VTK의 경우에는 수 십개의 파일이 존재하다 보니 일일&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;luckygg.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;VTK Hello World 실행하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 Visual Studio에 VTK 라이브러리 환경 설정이 모두 끝났습니다. VTK 공식 예제 코드인 &lt;a title=&quot;Hello World 예제 코드&quot; href=&quot;https://kitware.github.io/vtk-examples/site/Cxx/#hello-world&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Hello World&lt;/a&gt;를 실행해 보겠습니다. 전체 코드는 아래와 같습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1665331328385&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#pragma once
#include &amp;lt;vtkAutoInit.h&amp;gt;

#define vtkRenderingCore_AUTOINIT 3(vtkRenderingOpenGL2,vtkInteractionStyle, vtkRenderingFreeType)
#define vtkRenderingContext2D_AUTOINIT 1(vtkRenderingContextOpenGL2)

#include &amp;lt;vtkActor.h&amp;gt;
#include &amp;lt;vtkCamera.h&amp;gt;
#include &amp;lt;vtkCylinderSource.h&amp;gt;
#include &amp;lt;vtkNamedColors.h&amp;gt;
#include &amp;lt;vtkNew.h&amp;gt;
#include &amp;lt;vtkPolyDataMapper.h&amp;gt;
#include &amp;lt;vtkProperty.h&amp;gt;
#include &amp;lt;vtkRenderWindow.h&amp;gt;
#include &amp;lt;vtkRenderWindowInteractor.h&amp;gt;
#include &amp;lt;vtkRenderer.h&amp;gt;

#include &amp;lt;array&amp;gt;

int main(int, char* [])
{
    vtkNew&amp;lt;vtkNamedColors&amp;gt; colors;

    // Set the background color.
    std::array&amp;lt;unsigned char, 4&amp;gt; bkg{ {26, 51, 102, 255} };
    colors-&amp;gt;SetColor(&quot;BkgColor&quot;, bkg.data());

    // This creates a polygonal cylinder model with eight circumferential facets
    // (i.e, in practice an octagonal prism).
    vtkNew&amp;lt;vtkCylinderSource&amp;gt; cylinder;
    cylinder-&amp;gt;SetResolution(8);

    // The mapper is responsible for pushing the geometry into the graphics
    // library. It may also do color mapping, if scalars or other attributes are
    // defined.
    vtkNew&amp;lt;vtkPolyDataMapper&amp;gt; cylinderMapper;
    cylinderMapper-&amp;gt;SetInputConnection(cylinder-&amp;gt;GetOutputPort());

    // The actor is a grouping mechanism: besides the geometry (mapper), it
    // also has a property, transformation matrix, and/or texture map.
    // Here we set its color and rotate it around the X and Y axes.
    vtkNew&amp;lt;vtkActor&amp;gt; cylinderActor;
    cylinderActor-&amp;gt;SetMapper(cylinderMapper);
    cylinderActor-&amp;gt;GetProperty()-&amp;gt;SetColor(
        colors-&amp;gt;GetColor4d(&quot;Tomato&quot;).GetData());
    cylinderActor-&amp;gt;RotateX(30.0);
    cylinderActor-&amp;gt;RotateY(-45.0);

    // The renderer generates the image
    // which is then displayed on the render window.
    // It can be thought of as a scene to which the actor is added
    vtkNew&amp;lt;vtkRenderer&amp;gt; renderer;
    renderer-&amp;gt;AddActor(cylinderActor);
    renderer-&amp;gt;SetBackground(colors-&amp;gt;GetColor3d(&quot;BkgColor&quot;).GetData());
    // Zoom in a little by accessing the camera and invoking its &quot;Zoom&quot; method.
    renderer-&amp;gt;ResetCamera();
    renderer-&amp;gt;GetActiveCamera()-&amp;gt;Zoom(1.5);

    // The render window is the actual GUI window
    // that appears on the computer screen
    vtkNew&amp;lt;vtkRenderWindow&amp;gt; renderWindow;
    renderWindow-&amp;gt;SetSize(300, 300);
    renderWindow-&amp;gt;AddRenderer(renderer);
    renderWindow-&amp;gt;SetWindowName(&quot;Cylinder&quot;);

    // The render window interactor captures mouse events
    // and will perform appropriate camera or actor manipulation
    // depending on the nature of the events.
    vtkNew&amp;lt;vtkRenderWindowInteractor&amp;gt; renderWindowInteractor;
    renderWindowInteractor-&amp;gt;SetRenderWindow(renderWindow);

    // This starts the event loop and as a side effect causes an initial render.
    renderWindow-&amp;gt;Render();
    renderWindowInteractor-&amp;gt;Start();

    return EXIT_SUCCESS;
}&lt;/code&gt;&lt;/pre&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;799&quot; data-origin-height=&quot;681&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/HqXDn/btrOgyf61Mx/lNjQyqJkA7KhAZEdVb4Auk/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/HqXDn/btrOgyf61Mx/lNjQyqJkA7KhAZEdVb4Auk/img.webp&quot; data-alt=&quot;Hello World 예제 실행 결과&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/HqXDn/btrOgyf61Mx/lNjQyqJkA7KhAZEdVb4Auk/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FHqXDn%2FbtrOgyf61Mx%2FlNjQyqJkA7KhAZEdVb4Auk%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; alt=&quot;Hello World 예제 실행 결과&quot; loading=&quot;lazy&quot; width=&quot;799&quot; height=&quot;681&quot; data-origin-width=&quot;799&quot; data-origin-height=&quot;681&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Hello World 예제 실행 결과&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어때요, 잘 따라 하셨나요? 여기까지 문제없이 따라 하셨다면, 이제 VTK 예제 코드를 실행하는데 문제가 없을 것입니다.&lt;/p&gt;</description>
      <category>Programming/Visual Studio</category>
      <category>VTK</category>
      <author>❤ </author>
      <guid isPermaLink="true">https://luckygg.tistory.com/376</guid>
      <comments>https://luckygg.tistory.com/376#entry376comment</comments>
      <pubDate>Mon, 10 Oct 2022 16:19:28 +0900</pubDate>
    </item>
    <item>
      <title>구조적 예외 처리(SEH, Structured Exception Handling) 기초 이야기</title>
      <link>https://luckygg.tistory.com/374</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;구조적 예외 처리(SEH)란?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;구조적 예외 처리(이하 SEH)&lt;/b&gt;는 &lt;u&gt;하드웨어와 소프트웨어 예외를 모두 처리하는 Microsoft Windows의 기본 예외 처리 메커니즘&lt;/u&gt;입니다. &lt;b&gt;하드웨어 예외&lt;/b&gt;는 &lt;b&gt;예외가 발생한 주체가 CPU와 같은 하드웨어&lt;/b&gt;라는 것이고, &lt;b&gt;소프트웨어 예외&lt;/b&gt;는 &lt;b&gt;사용자가 작성한 소프트웨어 및 운영체제가 예외의 주체&lt;/b&gt;라는 의미입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;좀 더 쉬운 예를 들자면, &lt;u&gt;어떤 수를 0으로 나누는 연산&lt;/u&gt;이나 &lt;u&gt;접근할 수 없는 메모리에 접근을 시도하는 명령어&lt;/u&gt;를 실행한다면 &lt;b&gt;하드웨어 예외&lt;/b&gt;가 발생하고, &lt;u&gt;유효하지 않은 인자에 값을 지정&lt;/u&gt;할 때 &lt;b&gt;소프트웨어 예외&lt;/b&gt;가 발생할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이처럼, 하드웨어와 소프트웨어 예외를 모두 처리하는 메커니즘이 SEH입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://docs.microsoft.com/ko-kr/windows/win32/debug/structured-exception-handling&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://docs.microsoft.com/ko-kr/windows/win32/debug/structured-exception-handling&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1660541913613&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;구조적 예외 처리 - Win32 apps&quot; data-og-description=&quot;예외는 프로그램을 실행하는 동안 발생하는 이벤트로, 정상적인 제어 흐름 외부의 코드를 실행해야 합니다.&quot; data-og-host=&quot;docs.microsoft.com&quot; data-og-source-url=&quot;https://docs.microsoft.com/ko-kr/windows/win32/debug/structured-exception-handling&quot; data-og-url=&quot;https://docs.microsoft.com/ko-kr/windows/win32/debug/structured-exception-handling&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bhCn0y/hyPsSi23ZY/bBqp0yKr7WIK8CHEDDWv4k/img.png?width=400&amp;amp;height=400&amp;amp;face=0_0_400_400&quot;&gt;&lt;a href=&quot;https://docs.microsoft.com/ko-kr/windows/win32/debug/structured-exception-handling&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://docs.microsoft.com/ko-kr/windows/win32/debug/structured-exception-handling&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bhCn0y/hyPsSi23ZY/bBqp0yKr7WIK8CHEDDWv4k/img.png?width=400&amp;amp;height=400&amp;amp;face=0_0_400_400');&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;구조적 예외 처리 - Win32 apps&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;예외는 프로그램을 실행하는 동안 발생하는 이벤트로, 정상적인 제어 흐름 외부의 코드를 실행해야 합니다.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;docs.microsoft.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실 일반 응용 프로그램 개발자라면 SEH에 대해 깊게 알 필요는 없다고 생각합니다. SEH는 주로 운영체제를 안정적으로 개발하기 위한 예외 처리로, &lt;u&gt;일반 응용 프로그램 개발자는 언어에서 지원하는 예외 처리를 잘 다뤄야 합니다&lt;/u&gt;. 예를 들어, C++ 프로그램은 C++ 문법인 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;try-catch&lt;/span&gt;&lt;/code&gt;, &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt;&lt;/code&gt;를 이용하여 예외를 다루면 됩니다. 물론, SEH를 사용해도 무방합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참고로, &lt;b&gt;C++ 예외 처리&lt;/b&gt;는 내부적으로 컴파일러와 윈도우가 지원하는 &lt;b&gt;SEH 기능을 이용하여 구현&lt;/b&gt;되었습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;SEH 기본 문법&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SEH는 두 가지 주요 기능으로 구성되어 있습니다. 바로, &lt;b&gt;종료 처리기&lt;/b&gt;와 &lt;b&gt;예외 처리기&lt;/b&gt;입니다. 각 처리에 대해 차례대로 알아보겠습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. 종료 처리기(Termination Handler)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;종료 처리기는 &lt;code&gt;&lt;span class=&quot;token function&quot;&gt;__try&lt;/span&gt;&lt;/code&gt; 블록 내의 제어가 어떻게 빠져나오든 &lt;code&gt;&lt;span class=&quot;token function&quot;&gt;__finally&lt;/span&gt;&lt;/code&gt; 블록의 코드가 반드시 수행될 것이라는 것을 보장합니다. 아래 예제는 종료 처리기 SEH 구문입니다.&lt;/p&gt;
&lt;pre id=&quot;code_1661434481217&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;__try
{
	//...
}
__finally
{
	//종료 처리기
	//...
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;운영 체제와 컴파일러는 항상 종료 처리기의 코드가 수행되도록 보장합니다. 단, &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;ExitProcess&lt;/span&gt;&lt;/code&gt;, &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;ExitThread&lt;/span&gt;&lt;/code&gt;, &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;TerminateProcess&lt;/span&gt;&lt;/code&gt;, &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;TerminateThread&lt;/span&gt;&lt;/code&gt;와 같은 함수를 호출하여 프로세스나 스레드가 종료되는 경우는 제외합니다. 이러한 상황을 제외하곤, &lt;code&gt;&lt;span class=&quot;token function&quot;&gt;__try&lt;/span&gt;&lt;/code&gt; 블록 내에서 &lt;code&gt;&lt;span class=&quot;token function-name&quot;&gt;return&lt;/span&gt;&lt;/code&gt;, &lt;code&gt;&lt;span class=&quot;token function-name&quot;&gt;goto&lt;/span&gt;&lt;/code&gt;와 같은 문을 호출하더라도 &lt;u&gt;종료 처리기는 항상 호출&lt;/u&gt;됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데, 어떻게 종료 처리기인 &lt;code&gt;&lt;span class=&quot;token function&quot;&gt;__finally&lt;/span&gt;&lt;/code&gt; 블록이 항상 호출되는 것일까요? 이는, 컴파일러가 &lt;code&gt;&lt;span class=&quot;token function&quot;&gt;__try&lt;/span&gt;&lt;/code&gt; 블록 내에서 빠져나가기 전에 &lt;code&gt;&lt;span class=&quot;token function&quot;&gt;__finally&lt;/span&gt;&lt;/code&gt; 블록을 반드시 수행될 수 있도록 추가적인 코드를 생성하기 때문입니다. 이를 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;로컬 언와인드(Local Unwind)&lt;/span&gt;&lt;/code&gt;라고 합니다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;로컬 언와인드(Local Unwind)&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앞서 설명한 대로, &lt;span&gt;시스템이&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;token function&quot;&gt;__try&lt;/span&gt;&lt;/code&gt; 블록을 빠져나가기 전에 &lt;code&gt;&lt;span class=&quot;token function&quot;&gt;__finally&lt;/span&gt;&lt;/code&gt; 블록을 먼저 수행해야 하는 코드를 추가로 생성하는 것을 의미합니다. 그런데 '코드를 추가로 생성한다'라는 조건이 눈에 띄는데요. &lt;b&gt;추가적인 코드를 생성한다는 것은 결국 비용이 발생한다는 것&lt;/b&gt;입니다. 그리고 발생한 비용은 &lt;b&gt;프로그램 수행 성능에도 좋지 않은 영향&lt;/b&gt;을 줄 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서, &lt;u&gt;로컬 언와인드가 발생하지 않도록 제어의 흐름을 자연스럽게 작성&lt;/u&gt;해야 합니다. &lt;code&gt;&lt;span class=&quot;token function&quot;&gt;__try&lt;/span&gt;&lt;/code&gt; 블록을 수행하고 자연스럽게 &lt;code&gt;&lt;span class=&quot;token function&quot;&gt;__finally&lt;/span&gt;&lt;/code&gt; 블록을 수행하는 것이 비용을 최소화하는 방법입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또 하나의 주의 사항으로, &lt;code&gt;&lt;span class=&quot;token function&quot;&gt;__try&lt;/span&gt;&lt;/code&gt; 블록에서는 서둘러서 빠져나가는 코드를 작성하지 않는 것을 권장합니다. 예를 들어, &lt;code&gt;&lt;span class=&quot;token function-name&quot;&gt;return&lt;/span&gt;&lt;/code&gt;, &lt;code&gt;&lt;span class=&quot;token function-name&quot;&gt;goto&lt;/span&gt;&lt;/code&gt;, &lt;code&gt;&lt;span class=&quot;token function-name&quot;&gt;continue&lt;/span&gt;&lt;/code&gt;, &lt;code&gt;&lt;span class=&quot;token function-name&quot;&gt;break&lt;/span&gt;&lt;/code&gt;와 같은 문장을 사용하지 않는 것이 가장 좋은 방법입니다. 컴파일러가 로컬 언와인드와 같은 작업을 수행하지 않아도 되기 때문에, 좀 더 작은 코드를 생성할 수 있고 이는 최소한의 비용으로 코드를 좀 더 빠르게 동작하도록 할 수 있기 때문입니다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;__leave 키워드&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;&lt;span class=&quot;token function-name&quot;&gt;__try&lt;/span&gt;&lt;/code&gt; 블록 내에서 &lt;code&gt;&lt;span class=&quot;token function-name&quot;&gt;__leave&lt;/span&gt;&lt;/code&gt; 키워드를 사용하면 &lt;code&gt;&lt;span class=&quot;token function-name&quot;&gt;__try&lt;/span&gt;&lt;/code&gt; 블록의 가장 마지막으로 이동하게 됩니다. 이렇게 하면 앞에서 설명한 것처럼, 코드 수행 흐름이 자연스럽게 &lt;code&gt;&lt;span class=&quot;token function-name&quot;&gt;__try&lt;/span&gt;&lt;/code&gt; 블록에서 &lt;code&gt;&lt;span class=&quot;token function&quot;&gt;__finally&lt;/span&gt;&lt;/code&gt; 블록으로 이동하기 때문에 어떠한 추가 비용이 발생하지 않습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. 예외 처리기(Exception Handler)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예외 처리기는 &lt;code&gt;&lt;span class=&quot;token function&quot;&gt;__try&lt;/span&gt;&lt;/code&gt; 블록의 코드를 수행하던 중 예외가 발생하면 &lt;code&gt;&lt;span class=&quot;token function&quot;&gt;__except&lt;/span&gt;&lt;/code&gt; 문에서 필터를 평가하여 추가 동작을 수행하게 됩니다. 아래 예제는 예외 처리기 SEH 구문입니다.&lt;/p&gt;
&lt;pre id=&quot;code_1661435373977&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;__try
{
	//...
}
__except (예외 필터)
	//예외 처리기
	//...
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예외 처리기의 예외 필터에 대해 설명할 내용이 더 있습니다. 깊게 들어가기 전에, SEH 문법에 대해 잠깐 정리하고 설명을 이어가겠습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;SEH 문법 중간 정리&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;SEH 문법인 &lt;code&gt;&lt;span class=&quot;token function&quot;&gt;__try&lt;/span&gt;&lt;/code&gt; 블록을 만들면 반드시 종료 처리기인 &lt;code&gt;&lt;span class=&quot;token function&quot;&gt;__finally&lt;/span&gt;&lt;/code&gt; 블록 또는 예외 처리기인 &lt;code&gt;&lt;span class=&quot;token function&quot;&gt;__except&lt;/span&gt;&lt;/code&gt; 블록이 따라와야 합니다. &lt;code&gt;&lt;span class=&quot;token function&quot;&gt;__try&lt;/span&gt;&lt;/code&gt; 블록은 &lt;code&gt;&lt;span class=&quot;token function&quot;&gt;__finally&lt;/span&gt;&lt;/code&gt; 블록과 &lt;code&gt;&lt;span class=&quot;token function&quot;&gt;__except&lt;/span&gt;&lt;/code&gt; 블록을 동시에 가질 수 없습니다. 그리고 여러 개의 &lt;code&gt;&lt;span class=&quot;token function&quot;&gt;__except&lt;/span&gt;&lt;/code&gt; 블록도 가질 수 없습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;하지만 &lt;code&gt;&lt;span class=&quot;token function&quot;&gt;__try-__finally&lt;/span&gt;&lt;/code&gt; 블록 내에 &lt;code&gt;&lt;span class=&quot;token function&quot;&gt;__try-__except&lt;/span&gt;&lt;/code&gt; 블록을 포함시키거나 또는 그 반대로 구성하는 것은 가능합니다.&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;3. 예외 필터&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;계속해서 예외 처리기의 예외 필터에 대해 설명하겠습니다. 예외 필터는 총 세 가지를 제공하며, 각 필터마다 서로 다른 동작을 수행하게 됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span&gt;3-1. EXCEPTION_EXECUTE_HANDLER&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1661691848952&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;__try
{
	//...
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
	//예외 처리 수행
    //...
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;글로벌 언와인드(Global Unwind)&lt;/span&gt;&lt;/code&gt;를 수행한 후 &lt;code&gt;&lt;span class=&quot;token function&quot;&gt;__except&lt;/span&gt;&lt;/code&gt; 블록을 수행하게 됩니다. &lt;code&gt;&lt;span class=&quot;token function&quot;&gt;__except&lt;/span&gt;&lt;/code&gt; 블록의 코드가 모두 수행되고 나면 &lt;code&gt;&lt;span class=&quot;token function&quot;&gt;__except&lt;/span&gt;&lt;/code&gt; 바로 다음의 코드를 수행하게 됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span&gt;글로벌 언와인드(Global Unwind)&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;앞에서 종료 처리기를 설명할 때 로컬 언와인드를 설명했었습니다. 이름이 비슷한 글로벌 언와인드를 왜 지금 언급했냐면, 글로벌 언와인드는 예외 필터가 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;EXCEPTION_EXECUTE_HANDLER&lt;/span&gt;&lt;/code&gt; 일 때 동작하기 때문입니다. 예외 필터가 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;EXCEPTION_EXECUTE_HANDLER로&lt;/span&gt;&lt;/code&gt; 평가되면 &lt;code&gt;&lt;span class=&quot;token function&quot;&gt;__try-__except&lt;/span&gt;&lt;/code&gt; 블록 내의 모든 &lt;code&gt;&lt;span class=&quot;token function&quot;&gt;__try-__finally&lt;/span&gt;&lt;/code&gt; 블록을 수행하는 것을 &lt;b&gt;글로벌 언와인드&lt;/b&gt;라고 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Global Unwind.png&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;690&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/70fu6/btrKHcB9NUQ/byvSKqWhMlN88hhq0D8eG0/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/70fu6/btrKHcB9NUQ/byvSKqWhMlN88hhq0D8eG0/img.webp&quot; data-alt=&quot;글로벌 언와인드 수행 흐름&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/70fu6/btrKHcB9NUQ/byvSKqWhMlN88hhq0D8eG0/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F70fu6%2FbtrKHcB9NUQ%2FbyvSKqWhMlN88hhq0D8eG0%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; alt=&quot;글로벌-언와인드-수행-흐름&quot; loading=&quot;lazy&quot; width=&quot;800&quot; height=&quot;690&quot; data-filename=&quot;Global Unwind.png&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;690&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;글로벌 언와인드 수행 흐름&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span&gt;3-2. EXCEPTION_CONTINUE_EXECUTION&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1661691962105&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;__try
{
	//...
}
__except(EXCEPTION_CONTINUE_EXECUTION)
{
	//예외 처리 수행
    //...
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예외 필터가 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;EXCEPTION_CONTINUE_EXECUTION&lt;/span&gt;&lt;/code&gt;로 평가되면 &lt;u&gt;예외를 발생했던 코드를 다시 한번 수행&lt;/u&gt;하도록 합니다. 만약, 예외 발생 후 적절한 조치가 취해지지 않았다면 다시 문제가 발생하게 되겠죠. 이 경우 또 다른 예외가 발생할 수도 있고 또는 무한 루프에 빠질 가능성도 있습니다. 이는 곧 디버깅이 어려워 문제 해결에 어려움이 발생하겠죠.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;3-3. EXCEPTION_CONTINUE_SEARCH&lt;/h4&gt;
&lt;pre id=&quot;code_1661692023417&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;__try
{
	//...
}
__except(EXCEPTION_CONTINUE_SEARCH)
{
	//예외 처리 수행
    //...
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예외 필터가 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;EXCEPTION_CONTINUE_SEARCH&lt;/span&gt;&lt;/code&gt;로 평가되면, 가장 최근에 진입했던 &lt;code&gt;&lt;span class=&quot;token function&quot;&gt;__try&lt;/span&gt;&lt;/code&gt; 블록 중 &lt;code&gt;&lt;span class=&quot;token function&quot;&gt;__except&lt;/span&gt;&lt;/code&gt; 블록을 가진 곳으로 이동하여 예외 필터를 평가하게 됩니다. &lt;code&gt;&lt;span class=&quot;token function&quot;&gt;__try&lt;/span&gt;&lt;/code&gt; 블록이 &lt;code&gt;&lt;span class=&quot;token function&quot;&gt;__finally&lt;/span&gt;&lt;/code&gt; 블록을 가지고 있는 경우 검색 대상에서 제외됩니다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;예외가 처리되는 전체 흐름&lt;/h4&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;SEH Exception Filter.png&quot; data-origin-width=&quot;799&quot; data-origin-height=&quot;837&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bBGJ22/btrKHcB9NWA/kYdyLkLkhyzaS0eSfCgQW1/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bBGJ22/btrKHcB9NWA/kYdyLkLkhyzaS0eSfCgQW1/img.webp&quot; data-alt=&quot;예외가 처리되는 전체 흐름&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bBGJ22/btrKHcB9NWA/kYdyLkLkhyzaS0eSfCgQW1/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbBGJ22%2FbtrKHcB9NWA%2FkYdyLkLkhyzaS0eSfCgQW1%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; alt=&quot;예외가-처리되는-전체-흐름&quot; loading=&quot;lazy&quot; width=&quot;799&quot; height=&quot;837&quot; data-filename=&quot;SEH Exception Filter.png&quot; data-origin-width=&quot;799&quot; data-origin-height=&quot;837&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;예외가 처리되는 전체 흐름&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;참고&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Windows via C/C++ Fifth Edition, Jeffrey Richter&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Programming</category>
      <category>예외처리</category>
      <author>❤ </author>
      <guid isPermaLink="true">https://luckygg.tistory.com/374</guid>
      <comments>https://luckygg.tistory.com/374#entry374comment</comments>
      <pubDate>Sun, 28 Aug 2022 22:08:06 +0900</pubDate>
    </item>
    <item>
      <title>[.Net] 이미지 뷰어는 ImageGlass로 쉽게 개발하기</title>
      <link>https://luckygg.tistory.com/373</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;이미지 뷰어(Image Viewer)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비전 프로그램에서 이미지 뷰어는 &lt;b&gt;실시간으로 취득되는 카메라 영상이나 검사 결과 이미지를 띄우는 역할&lt;/b&gt;을 합니다. 보통은 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;Picture Box&lt;/span&gt;&lt;/code&gt;나 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;Panel&lt;/span&gt;&lt;/code&gt;에다가 그리기 마련인데요. 만약, 무턱대고 카메라 영상을 받는 그대로 출력하면 프로그램 반응 속도에 영향을 주게 됩니다. &lt;u&gt;고해상도의 이미지를 컨트롤의 크기에 맞춰 Stretch 알고리즘을 사용하거나 빠른 속도로 컨트롤의 이미지를 업데이트하면 &lt;span style=&quot;color: #ee2323;&quot;&gt;UI 반응 속도가 느려지기 때문&lt;/span&gt;&lt;/u&gt;입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데 보통은 이런 걱정을 할 필요가 없습니다. 대부분의 프로그램은 영상을 천천히 띄우거나 빠르게 띄우더라도 실시간으로 프로그램을 조작하지 않기 때문입니다. 하지만 비전 프로그램과 같이 실시간으로 다수의&lt;span&gt;&lt;span&gt; 카메라 &lt;/span&gt;&lt;/span&gt;영상을 띄우면서 제어가 필요한 상황이라면 얘기가 달라집니다. &lt;u&gt;이미지 확대/축소, 마우스 Drag &amp;amp; Drop에 따른 이동, 실시간 갱신에 따라 응답 속도가 느려지면 사용자 입장에서는 참으로 답답하고 신뢰성이 떨어지기 때문&lt;/u&gt;입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서론이 길었습니다. 그래서 본문에서는 이미지 뷰어를 어떻게 개발하는지, 그리고 &lt;code&gt;&lt;span class=&quot;token important&quot;&gt;ImageGlass&lt;/span&gt;&lt;/code&gt; 라이브러리를 사용하면 장점이 무엇이고 얼마나 개발하기 편리해지는지 설명합니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;직접 이미지 뷰어 만드는 방법&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ImageGlass를 설명하기에 앞서, 이미지 뷰어를 직접 어떻게 만드는지 알아보겠습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;동작 이해하기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래와 같이 500x500 크기의 이미지와 400x400의 컨트롤이 있다고 예시를 들겠습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;이미지 파일과 컨트롤 크기.png&quot; data-origin-width=&quot;489&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bfxpt3/btrJA5reTqP/ccKfkx8lUtQJKKkhtMk3Tk/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bfxpt3/btrJA5reTqP/ccKfkx8lUtQJKKkhtMk3Tk/img.webp&quot; data-alt=&quot;그림 파일과 컨트롤의 크기&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bfxpt3/btrJA5reTqP/ccKfkx8lUtQJKKkhtMk3Tk/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbfxpt3%2FbtrJA5reTqP%2FccKfkx8lUtQJKKkhtMk3Tk%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; alt=&quot;그림-파일과-컨트롤의-크기&quot; loading=&quot;lazy&quot; width=&quot;800&quot; height=&quot;489&quot; data-filename=&quot;이미지 파일과 컨트롤 크기.png&quot; data-origin-width=&quot;489&quot; data-origin-height=&quot;0&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;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;그림이 그려지는 모습.png&quot; data-origin-width=&quot;447&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bReWpA/btrJCpa7CXw/QLydVByK0Z91zbKRoYZjM1/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bReWpA/btrJCpa7CXw/QLydVByK0Z91zbKRoYZjM1/img.webp&quot; data-alt=&quot;그림이 컨트롤에 그려지는 모습&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bReWpA/btrJCpa7CXw/QLydVByK0Z91zbKRoYZjM1/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbReWpA%2FbtrJCpa7CXw%2FQLydVByK0Z91zbKRoYZjM1%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; alt=&quot;그림이-컨트롤에-그려지는-모습&quot; loading=&quot;lazy&quot; width=&quot;447&quot; data-filename=&quot;그림이 그려지는 모습.png&quot; data-origin-width=&quot;447&quot; data-origin-height=&quot;0&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;span&gt;&lt;span&gt; &lt;/span&gt;컨트롤의 영역을 벗어난 부분은 그려지면 안 되며, 마우스 드래그 앤 드롭이나 스크롤 바 이동으로 &lt;b&gt;시작 offset&lt;/b&gt;이 적용되어 그려져야 합니다. 예를 들어, 시작 offset이 변경되면 다음과 같이 그려지게 됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;이동에 따라 그려지는 모습.png&quot; data-origin-width=&quot;712&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bXVCrF/btrJBKNAeN3/HUHFeaNKHI0gvbUi8aujy0/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bXVCrF/btrJBKNAeN3/HUHFeaNKHI0gvbUi8aujy0/img.webp&quot; data-alt=&quot;이미지 offset 적용에 따라 그려지는 모습&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bXVCrF/btrJBKNAeN3/HUHFeaNKHI0gvbUi8aujy0/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbXVCrF%2FbtrJBKNAeN3%2FHUHFeaNKHI0gvbUi8aujy0%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; alt=&quot;이미지-offset-적용에-따라-그려지는-모습&quot; loading=&quot;lazy&quot; width=&quot;712&quot; data-filename=&quot;이동에 따라 그려지는 모습.png&quot; data-origin-width=&quot;712&quot; data-origin-height=&quot;0&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;이미지 offset 적용에 따라 그려지는 모습&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마우스 드래그 앤 드롭에 따라 offset을 계산하기 위해서는 &lt;code&gt;&lt;span class=&quot;token function-name&quot;&gt;LButtonDown&lt;/span&gt;&lt;/code&gt;, &lt;code&gt;&lt;span class=&quot;token function-name&quot;&gt;LButtonUp&lt;/span&gt;&lt;/code&gt;, &lt;code&gt;&lt;span class=&quot;token function-name&quot;&gt;MouseMove&lt;/span&gt;&lt;/code&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;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;ExamViewer&lt;/b&gt; 이름의 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;Windows Forms 앱&lt;/span&gt;&lt;/code&gt; 프로젝트를 생성합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;557&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/I3l6z/btrJBl1B4kH/AjDy1ZSx2kxlNKreYnxph0/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/I3l6z/btrJBl1B4kH/AjDy1ZSx2kxlNKreYnxph0/img.webp&quot; data-alt=&quot;WinForm 프로젝트 생성하기&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/I3l6z/btrJBl1B4kH/AjDy1ZSx2kxlNKreYnxph0/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FI3l6z%2FbtrJBl1B4kH%2FAjDy1ZSx2kxlNKreYnxph0%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; alt=&quot;WinForm-프로젝트-생성하기&quot; loading=&quot;lazy&quot; width=&quot;557&quot; data-origin-width=&quot;557&quot; data-origin-height=&quot;0&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;WinForm 프로젝트 생성하기&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 솔루션 파일에 &lt;b&gt;MyViewer&lt;/b&gt; 이름의 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;컨트롤 라이브러리&lt;/span&gt;&lt;/code&gt;를 추가합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;556&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bVhDI3/btrJBmzvTnt/quRKrjxTnHwyE94u5IHiq0/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bVhDI3/btrJBmzvTnt/quRKrjxTnHwyE94u5IHiq0/img.webp&quot; data-alt=&quot;컨트롤 라이브러리 생성하기&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bVhDI3/btrJBmzvTnt/quRKrjxTnHwyE94u5IHiq0/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbVhDI3%2FbtrJBmzvTnt%2FquRKrjxTnHwyE94u5IHiq0%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; alt=&quot;컨트롤-라이브러리-생성하기&quot; loading=&quot;lazy&quot; width=&quot;556&quot; data-origin-width=&quot;556&quot; data-origin-height=&quot;0&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;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;393&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lwgRR/btrJC5pVHMK/Ii9z6CY00jsdYLbOPuyPik/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lwgRR/btrJC5pVHMK/Ii9z6CY00jsdYLbOPuyPik/img.webp&quot; data-alt=&quot;두 개의 프로젝트가 추가된 모습&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lwgRR/btrJC5pVHMK/Ii9z6CY00jsdYLbOPuyPik/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlwgRR%2FbtrJC5pVHMK%2FIi9z6CY00jsdYLbOPuyPik%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; alt=&quot;두-개의-프로젝트가-추가된-모습&quot; loading=&quot;lazy&quot; width=&quot;393&quot; data-origin-width=&quot;393&quot; data-origin-height=&quot;0&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;code&gt;&lt;span class=&quot;token function&quot;&gt;UserControl1.cs&lt;/span&gt;&lt;/code&gt;의 코드 구현은 다음과 같습니다. 주석으로 &lt;span&gt;간단한 설명을 &lt;/span&gt;추가했습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1660311709685&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Imaging;
using System.Drawing.Drawing2D;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace MyViewer
{
    public partial class UserControl1: UserControl
    {
        Point _leftClick = Point.Empty; //왼쪽 마우스 클릭 좌표
        Point _offset = Point.Empty; //마우스 드래그 앤 드롭 offset 계산
        Point _lastOffset = new Point(0, 0); //마지막 offset 보관 용도

        Bitmap _bitmap = null; //파일로 불러온 이미지
        Bitmap _canvas = null; //더블 버퍼링을 위한 배경 이미지
        SolidBrush _background = new SolidBrush(Color.FromArgb(255, 255, 255)); //배경 색상
        Rectangle _sizeCanvas = new Rectangle(0, 0, 0, 0); //배경 이미지의 크기

        Rectangle _sizeSrc = new Rectangle(0, 0, 0, 0); //배경 이미지에 그려질 원본 이미지의 위치
        Graphics _g = null; //그려질 컨트롤의 핸들

        public UserControl1()
        {
            InitializeComponent();

            _canvas = new Bitmap(this.Width, this.Height);

            _sizeCanvas.Width = this.Width;
            _sizeCanvas.Height = this.Height;

            _sizeSrc.X = 0;
            _sizeSrc.Y = 0;
            _sizeSrc.Width = this.Width;
            _sizeSrc.Height = this.Height;

            _g = this.CreateGraphics();
        }

        public void LoadImage(string path)
        {
            _bitmap = (Bitmap)Image.FromFile(path);

            draw(_g);
        }

        private void draw(Graphics g)
        {
            if (_bitmap != null)
            {
                var graphics = Graphics.FromImage(_canvas);

                graphics.FillRectangle(_background, _sizeCanvas);

                _sizeSrc.X = -_offset.X;
                _sizeSrc.Y = -_offset.Y;
                graphics.DrawImage(_bitmap, 0, 0, _sizeSrc, GraphicsUnit.Pixel);

                g.DrawImage(_canvas, 0, 0);
            }
        }

        private void UserControl1_MouseMove(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                _offset.X = e.Location.X - _leftClick.X;
                _offset.Y = e.Location.Y - _leftClick.Y;

                _offset.X += _lastOffset.X;
                _offset.Y += _lastOffset.Y;

                draw(_g); //CPU 부하가 높음
            }
        }

        private void UserControl1_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                _leftClick = e.Location;
            }
        }

        private void UserControl1_MouseUp(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                _lastOffset = _offset;
            }
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드는 아래의 첨부된 파일을 참고하세요.&lt;/p&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/bJzGS2/btrJBmTyd9y/cKelEeOxggM7WQkXFqtPYk/ExamViewer.zip?attach=1&amp;amp;knm=tfile.zip&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;ExamViewer.zip&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;size&quot;&gt;0.02MB&lt;/div&gt;
&lt;/div&gt;
  &lt;/a&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;마우스 왼쪽 버튼의 클릭(Down, Up) 동작&lt;/u&gt;과 &lt;u&gt;움직임(Move)에 따라 offset 좌표가 계산&lt;/u&gt;됩니다. 그리고 &lt;u&gt;MouseMove 이벤트&lt;/u&gt;에서 왼쪽 버튼이 클릭되어 있다면(드래그 앤 드롭) &lt;u&gt;이미지 그리는 작업(draw)&lt;/u&gt;도 실시됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;&lt;span class=&quot;token function-name&quot;&gt;draw()&lt;/span&gt;&lt;/code&gt; 함수에서는 &lt;code&gt;&lt;span class=&quot;token function&quot;&gt;_bitmap&lt;/span&gt;&lt;/code&gt;을 컨트롤에 바로 그리지 않습니다. _bitmap을 컨트롤에 바로 그리게 되면, 이미지를 배경에 계속 덧그리게 되어 &lt;u&gt;마우스 이동에 따라 잔상&lt;/u&gt;이 남게 됩니다. 바로 아래와 같은 모습이 됩니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;391&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Fbk8N/btrJC5XKlTD/bsTa135NXI0SYrkfK8FrZk/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Fbk8N/btrJC5XKlTD/bsTa135NXI0SYrkfK8FrZk/img.webp&quot; data-alt=&quot;이미지 이동에 따라 잔상이 남은 모습&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Fbk8N/btrJC5XKlTD/bsTa135NXI0SYrkfK8FrZk/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FFbk8N%2FbtrJC5XKlTD%2FbsTa135NXI0SYrkfK8FrZk%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; alt=&quot;이미지-이동에-따라-잔상이-남은-모습&quot; loading=&quot;lazy&quot; width=&quot;391&quot; data-origin-width=&quot;391&quot; data-origin-height=&quot;0&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;code&gt;&lt;span class=&quot;token function&quot;&gt;_canvas&lt;/span&gt;&lt;/code&gt;를 생성하여 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;더블 버퍼링&lt;/span&gt;&lt;/code&gt;으로 잔상이 남는 현상을 개선합니다. 아래 애니메이션은 위 코드의 동작을 보여줍니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;viewer.gif&quot; data-origin-width=&quot;583&quot; data-origin-height=&quot;389&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dtCLxJ/btrJACI5PDL/GeqJwiJB7enTtiY2kKUPl0/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dtCLxJ/btrJACI5PDL/GeqJwiJB7enTtiY2kKUPl0/img.gif&quot; data-alt=&quot;뷰어 동작 화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dtCLxJ/btrJACI5PDL/GeqJwiJB7enTtiY2kKUPl0/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/dtCLxJ/btrJACI5PDL/GeqJwiJB7enTtiY2kKUPl0/img.gif&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; alt=&quot;뷰어-동작-화면&quot; loading=&quot;lazy&quot; width=&quot;583&quot; height=&quot;389&quot; data-filename=&quot;viewer.gif&quot; data-origin-width=&quot;583&quot; data-origin-height=&quot;389&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;뷰어 동작 화면&lt;/figcaption&gt;
&lt;/figure&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;마우스로 드래그 앤 드롭을 심하게 움직이면 &lt;u&gt;CPU 부하율이 상당히 높아지는 것&lt;/u&gt;을 볼 수 있습니다. 그리고 그려지는 이미지가 자연스럽지 않은 것도 말이죠. 위 예제 코드는 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;MouseMove 이벤트&lt;/span&gt;&lt;/code&gt;에 &lt;code&gt;&lt;span class=&quot;token function-name&quot;&gt;draw()&lt;/span&gt;&lt;/code&gt;를 호출하다 보니, &lt;u&gt;마우스 움직임에 따라 너무 많은 이벤트가 발생한 것이 원인&lt;/u&gt;입니다. 나중에는 확대, 축소 기능도 넣다 보면 더 심해질 것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 이벤트를 줄이되 어떻게 자연스럽게 이미지를 그려낼지 방법을 찾는 것이 중요합니다. 하지만, 굳이 이런 고민을 하면서 이미지 뷰어를 만들 필요가 있을까요? 본인이 다 만들어서 나의 것을 만들어 가는 것도 좋지만, &lt;u&gt;우리에게 시간은 많지 않습니다.&lt;/u&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 이러한 걱정을 할 필요가 없는, 무료로 사용 가능한 이미지 뷰어인 ImageGlass를 알아보겠습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;사용하기 편한 이미지 뷰어, ImageGlass&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;주요 특징&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ImageGlass는 이미지를 볼 수 있도록 도와주는 아주 가벼운 응용 프로그램입니다. 윈도우 사진 뷰어처럼 이미지 파일을 더블 클릭하면 바로 띄어지는 프로그램입니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;493&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/0a870/btrJFO8OTLe/jr0ljjE7ftKRkh9ApIWd7k/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/0a870/btrJFO8OTLe/jr0ljjE7ftKRkh9ApIWd7k/img.webp&quot; data-alt=&quot;ImageGlass 사진 뷰어&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/0a870/btrJFO8OTLe/jr0ljjE7ftKRkh9ApIWd7k/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F0a870%2FbtrJFO8OTLe%2Fjr0ljjE7ftKRkh9ApIWd7k%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; alt=&quot;ImageGlass-사진-뷰어&quot; loading=&quot;lazy&quot; width=&quot;493&quot; data-origin-width=&quot;493&quot; data-origin-height=&quot;0&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;ImageGlass 사진 뷰어&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;주요 특징은 다음과 같습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;다양한 &lt;span&gt;이미지&lt;span&gt; &lt;/span&gt;&lt;/span&gt;줌(확대/축소) 모드, 마우스 드래그 앤 드롭 이동 가능&lt;/li&gt;
&lt;li&gt;클립보드로부터 이미지 열기 가능&lt;/li&gt;
&lt;li&gt;70개 이상의 이미지 포맷 지원&lt;/li&gt;
&lt;li&gt;gif 호환 가능하며, 이미지 프레임 추출 및 애니메이션 재생/일시 중지 가능&lt;/li&gt;
&lt;li&gt;슬라이드 쇼&lt;/li&gt;
&lt;li&gt;썸네일 보기&lt;/li&gt;
&lt;li&gt;단축키 지원&lt;/li&gt;
&lt;li&gt;칼라 채널 선택 가능&lt;/li&gt;
&lt;li&gt;색상 및 픽셀 값 추출 가능&lt;/li&gt;
&lt;li&gt;자르기 기능&lt;/li&gt;
&lt;li&gt;다양한 언어 지원(한국어 포함)&lt;/li&gt;
&lt;li&gt;설치형(installer)/실행형(portable) 지원&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ImageViewer는 아래 공식 홈페이지에서 다운로드 가능합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://imageglass.org/release/imageglass-8-6-7-13-36&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://imageglass.org/release/imageglass-8-6-7-13-36&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1660367701442&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;ImageGlass 8.6.7.13 | ImageGlass&quot; data-og-description=&quot;Download ImageGlass 8.6.7.13&quot; data-og-host=&quot;imageglass.org&quot; data-og-source-url=&quot;https://imageglass.org/release/imageglass-8-6-7-13-36&quot; data-og-url=&quot;https://imageglass.org/release/imageglass-8-6-7-13-36&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/cQu0GP/hyPpyfGZol/DXbyw06PabYKVEiuVdVDkK/img.jpg?width=1196&amp;amp;height=825&amp;amp;face=0_0_1196_825,https://scrap.kakaocdn.net/dn/f1Brc/hyPpAR4yy2/2gUA1cBcFkawZCyUpgMubk/img.jpg?width=1032&amp;amp;height=1034&amp;amp;face=0_0_1032_1034,https://scrap.kakaocdn.net/dn/dpVsio/hyPpKNVbXz/5nkfb97XsJfUXaBc2KgM7K/img.jpg?width=1196&amp;amp;height=825&amp;amp;face=0_0_1196_825&quot;&gt;&lt;a href=&quot;https://imageglass.org/release/imageglass-8-6-7-13-36&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://imageglass.org/release/imageglass-8-6-7-13-36&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/cQu0GP/hyPpyfGZol/DXbyw06PabYKVEiuVdVDkK/img.jpg?width=1196&amp;amp;height=825&amp;amp;face=0_0_1196_825,https://scrap.kakaocdn.net/dn/f1Brc/hyPpAR4yy2/2gUA1cBcFkawZCyUpgMubk/img.jpg?width=1032&amp;amp;height=1034&amp;amp;face=0_0_1032_1034,https://scrap.kakaocdn.net/dn/dpVsio/hyPpKNVbXz/5nkfb97XsJfUXaBc2KgM7K/img.jpg?width=1196&amp;amp;height=825&amp;amp;face=0_0_1196_825');&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;ImageGlass 8.6.7.13 | ImageGlass&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Download ImageGlass 8.6.7.13&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;imageglass.org&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;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;GNU General Public License Version3&lt;/li&gt;
&lt;li&gt;오픈 소스&lt;/li&gt;
&lt;li&gt;C# 지원(v8.x: .Net 4.8, v9.0: .Net 6)&lt;/li&gt;
&lt;li&gt;하드웨어 가속 지원&lt;/li&gt;
&lt;li&gt;ImageViewer Control 지원하여 쉽게 사용 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;혹시 &lt;b&gt;GNU GPLv3 라이선스&lt;/b&gt;가 궁금하다면 아래 링크를 참고하세요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.olis.or.kr/license/Detailselect.do?lId=1072&quot;&gt;https://www.olis.or.kr/license/Detailselect.do?lId=1072&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1660388400429&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;GNU General Public License version 3.0 (GPLv3)&quot; data-og-description=&quot;자유 소프트웨어 재단(FSF)과 이 재단의 GNU 프로젝트에 의해 배포되며 GNU 소프트웨어에 적용되는 공개 소프트웨어의 대표적인 라이선스 체계. GNU GPL이라고도 하며, 저작권(copyright)의 반대라는 의&quot; data-og-host=&quot;www.olis.or.kr&quot; data-og-source-url=&quot;https://www.olis.or.kr/license/Detailselect.do?lId=1072&quot; data-og-url=&quot;https://www.olis.or.kr/license/Detailselect.do?lId=1072&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://www.olis.or.kr/license/Detailselect.do?lId=1072&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.olis.or.kr/license/Detailselect.do?lId=1072&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;GNU General Public License version 3.0 (GPLv3)&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;자유 소프트웨어 재단(FSF)과 이 재단의 GNU 프로젝트에 의해 배포되며 GNU 소프트웨어에 적용되는 공개 소프트웨어의 대표적인 라이선스 체계. GNU GPL이라고도 하며, 저작권(copyright)의 반대라는 의&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.olis.or.kr&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ImageGlass 소스 코드는 아래 공식 Github 주소에서 다운로드 가능합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/d2phap/ImageGlass&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://github.com/d2phap/ImageGlass&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1660368139106&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 - d2phap/ImageGlass:   A lightweight, versatile image viewer&quot; data-og-description=&quot;  A lightweight, versatile image viewer. Contribute to d2phap/ImageGlass development by creating an account on GitHub.&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/d2phap/ImageGlass&quot; data-og-url=&quot;https://github.com/d2phap/ImageGlass&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bG8Wl5/hyPpyzX9Zy/2FRYirdDgEFz6yMzeN1aOK/img.jpg?width=1920&amp;amp;height=724&amp;amp;face=0_0_1920_724&quot;&gt;&lt;a href=&quot;https://github.com/d2phap/ImageGlass&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/d2phap/ImageGlass&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bG8Wl5/hyPpyzX9Zy/2FRYirdDgEFz6yMzeN1aOK/img.jpg?width=1920&amp;amp;height=724&amp;amp;face=0_0_1920_724');&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 - d2phap/ImageGlass:   A lightweight, versatile image viewer&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;  A lightweight, versatile image viewer. Contribute to d2phap/ImageGlass 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;h3 data-ke-size=&quot;size23&quot;&gt;따라 하기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;ExamImageGlass&lt;/b&gt; 이름의 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;Windows Forms 앱&lt;/span&gt;&lt;/code&gt; 프로젝트를 생성합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;557&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dKLvyA/btrJCoJ22Nu/dq5X8PfPPg5j34mkO5hj8K/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dKLvyA/btrJCoJ22Nu/dq5X8PfPPg5j34mkO5hj8K/img.webp&quot; data-alt=&quot;Windows Forms 프로젝트 생성하기&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dKLvyA/btrJCoJ22Nu/dq5X8PfPPg5j34mkO5hj8K/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdKLvyA%2FbtrJCoJ22Nu%2Fdq5X8PfPPg5j34mkO5hj8K%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; alt=&quot;Windows-Forms-프로젝트-생성하기&quot; loading=&quot;lazy&quot; width=&quot;557&quot; data-origin-width=&quot;557&quot; data-origin-height=&quot;0&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Windows Forms 프로젝트 생성하기&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ImageGlass 라이브러리를 사용하기 위한 dll을 참조로 추가해야 합니다. 소스 코드를 다운로드하고 빌드해야 하지만, 저는 이 과정을 생략하고 &lt;b&gt;실행 파일 경로&lt;/b&gt;에서 dll을 가져왔습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;618&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/u7Eob/btrJFOHKxR3/6QOZRl28fb1QOtFZ6sY0Mk/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/u7Eob/btrJFOHKxR3/6QOZRl28fb1QOtFZ6sY0Mk/img.webp&quot; data-alt=&quot;설치 경로의 ImageGlass.ImageBox.dll 참조 추가하기&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/u7Eob/btrJFOHKxR3/6QOZRl28fb1QOtFZ6sY0Mk/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fu7Eob%2FbtrJFOHKxR3%2F6QOZRl28fb1QOtFZ6sY0Mk%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; alt=&quot;설치-경로의-ImageGlass.ImageBox.dll-참조-추가하기&quot; loading=&quot;lazy&quot; width=&quot;618&quot; data-origin-width=&quot;618&quot; data-origin-height=&quot;0&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;설치 경로의 ImageGlass.ImageBox.dll 참조 추가하기&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 WinForm에 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;ImageBox&lt;/span&gt;&lt;/code&gt; 컨트롤을 추가합니다. 참고로, 저의 경우에는 Visual Studio의 디자이너에서 오류가 발생하여 코드로 직접 추가했습니다. 디자이너의 코드 예시는 다음과 같습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1660369365125&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;namespace ExamImageGlass
{
    partial class Form1
    {
        //생략

        private void InitializeComponent()
        {
            this.viewer = new ImageGlass.ImageBoxEx();
            this.btnOpen = new System.Windows.Forms.Button();
            this.SuspendLayout();
            //
            // viewer
            // 
            this.viewer.Location = new System.Drawing.Point(5, 5);
            this.viewer.Name = &quot;viewer&quot;;
            this.viewer.Size = new System.Drawing.Size(500, 500);
            this.viewer.Dock = System.Windows.Forms.DockStyle.None;
            // btnOpen
            // 
            this.btnOpen.Location = new System.Drawing.Point(513, 12);
            this.btnOpen.Name = &quot;btnOpen&quot;;
            this.btnOpen.Size = new System.Drawing.Size(75, 23);
            this.btnOpen.TabIndex = 0;
            this.btnOpen.Text = &quot;Open&quot;;
            this.btnOpen.UseVisualStyleBackColor = true;
            this.btnOpen.Click += new System.EventHandler(this.btnOpen_Click);
            // 
            // Form1
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 12F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(600, 520);
            this.Controls.Add(this.btnOpen);
            this.Controls.Add(this.viewer);
            this.Name = &quot;Form1&quot;;
            this.Text = &quot;Form1&quot;;
            this.ResumeLayout(false);
        }

        private ImageGlass.ImageBoxEx viewer;
        private System.Windows.Forms.Button btnOpen;

        #endregion      
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;&lt;span class=&quot;token function&quot;&gt;Form1.cs&lt;/span&gt;&lt;/code&gt;의 코드는 다음과 같습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1660369418858&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Diagnostics;

namespace ExamImageGlass
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            
            viewer.AllowClickZoom = true; //마우스 클릭으로 확대/축소
            viewer.ShowPixelGrid = true; //확대 시 Pixel Grid 활성화하기
        }

        private void btnOpen_Click(object sender, EventArgs e)
        {
            OpenFileDialog dlg = new OpenFileDialog();
            if (dlg.ShowDialog() == DialogResult.OK)
            {
                viewer.Image = Image.FromFile(dlg.FileName);
            }
        }
    }
}&lt;/code&gt;&lt;/pre&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/KMnU4/btrJBJ8L88K/CqqwSrkxL71WXKA7TAO3WK/ExamImageGlass.zip?attach=1&amp;amp;knm=tfile.zip&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;ExamImageGlass.zip&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;size&quot;&gt;0.01MB&lt;/div&gt;
&lt;/div&gt;
  &lt;/a&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용 방법이 너무 간단하죠? &lt;code&gt;&lt;span class=&quot;token function-name&quot;&gt;AllowClickZoom&lt;/span&gt;&lt;/code&gt;은 마우스의 왼쪽 버튼은 확대, 오른쪽 버튼은 축소 동작을 의미합니다. 그리고 &lt;code&gt;&lt;span class=&quot;token function-name&quot;&gt;ShowPixelGrid&lt;/span&gt;&lt;/code&gt;는 확대 배율이 높아졌을 때 Grid를 표현하는 옵션을 의미합니다. 자세한 동작 결과는 아래 애니메이션을 보겠습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;viewer2.gif&quot; data-origin-width=&quot;602&quot; data-origin-height=&quot;552&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/5DRN4/btrJB3eOP5q/L4Pz80Pswtgykca6iPkVXK/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/5DRN4/btrJB3eOP5q/L4Pz80Pswtgykca6iPkVXK/img.gif&quot; data-alt=&quot;ImageGlass 동작 화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/5DRN4/btrJB3eOP5q/L4Pz80Pswtgykca6iPkVXK/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/5DRN4/btrJB3eOP5q/L4Pz80Pswtgykca6iPkVXK/img.gif&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; alt=&quot;ImageGlass-동작-화면&quot; loading=&quot;lazy&quot; width=&quot;602&quot; height=&quot;552&quot; data-filename=&quot;viewer2.gif&quot; data-origin-width=&quot;602&quot; data-origin-height=&quot;552&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;ImageGlass 동작 화면&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예제로 만든 뷰어보다 더 부드럽고 자연스럽게 그려집니다. 또한, 마우스 이동이나 스크롤 바 이동에 따라 이미지 이동도 가능합니다. 심지어 확대 배율이 높을 경우 Pixel Grid가 표현되어 구분이 더욱 쉬워집니다. 만약, 스크롤 바 사용을 원치 않는다면 사용하지 않겠다는 옵션을 지정하면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금은 예시로 이미지를 불러오고 확대/축소 및 이동하는 모습만 보여드렸는데요. ImageGlass 사진 뷰어처럼 자르기 기능이나 좌표에 따라 픽셀 값을 얻는 기능, 채널 추출 등 필요한 기능을 사용할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Programming/.Net</category>
      <category>.net</category>
      <author>❤ </author>
      <guid isPermaLink="true">https://luckygg.tistory.com/373</guid>
      <comments>https://luckygg.tistory.com/373#entry373comment</comments>
      <pubDate>Sat, 13 Aug 2022 20:24:47 +0900</pubDate>
    </item>
    <item>
      <title>티스토리 블로그 백업 프로그램 v2.6, 무료 배포합니다!</title>
      <link>https://luckygg.tistory.com/332</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;티스토리 블로그는 백업 기능을 제공하지 않지만, &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;Tistory Open API&lt;/span&gt;&lt;/code&gt;를 제공하는데요. 이 API를 이용하여 티스토리 백업 프로그램을 제작해 보았습니다. 해당 프로그램을 사용하여 여러분의 티스토리 블로그를 안전하게 백업하세요.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;main2.png&quot; data-origin-width=&quot;1250&quot; data-origin-height=&quot;822&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/TRQ0y/btre0cmcvKM/ZzKFzgopSItgJrOJicSwMk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/TRQ0y/btre0cmcvKM/ZzKFzgopSItgJrOJicSwMk/img.png&quot; data-alt=&quot;프로그램 소개&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/TRQ0y/btre0cmcvKM/ZzKFzgopSItgJrOJicSwMk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FTRQ0y%2Fbtre0cmcvKM%2FZzKFzgopSItgJrOJicSwMk%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;1250&quot; height=&quot;822&quot; data-filename=&quot;main2.png&quot; data-origin-width=&quot;1250&quot; data-origin-height=&quot;822&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;프로그램 소개&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 style=&quot;text-align: left;&quot; 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;b&gt;모든 블로그&lt;/b&gt; 정보 표시&lt;/li&gt;
&lt;li&gt;각 블로그의 &lt;b&gt;이름, 주소&lt;/b&gt;와 모든 &lt;b&gt;글&lt;/b&gt; &lt;b&gt;수&lt;/b&gt; 표시&lt;/li&gt;
&lt;li&gt;각 글의 &lt;b&gt;HTML 본문 내용&lt;/b&gt;과 &lt;b&gt;첨부된 그림, 파일(pdf, zip 등)&lt;/b&gt; 저장&lt;/li&gt;
&lt;li&gt;&lt;b&gt;덮어쓰기, 건너뛰기, 이미지 저장 등 백업 옵션&lt;/b&gt; 제공&lt;/li&gt;
&lt;li&gt;구 에디터, 신 에디터에서 작성된 모든 글 백업 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;특징에 대한 내용은 아래 '&lt;b&gt;더보기&lt;/b&gt;' 버튼을 클릭하여 확인할 수 있습니다.&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;블로그 목록 표시&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;로그인 후 메인 화면에는 소유 중인 블로그 목록이 표시됩니다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;647&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mV0Hz/btre5PpWV6f/dlkS7k921WZNmygkx88lK0/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mV0Hz/btre5PpWV6f/dlkS7k921WZNmygkx88lK0/img.webp&quot; data-alt=&quot;블로그 목록&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mV0Hz/btre5PpWV6f/dlkS7k921WZNmygkx88lK0/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmV0Hz%2Fbtre5PpWV6f%2FdlkS7k921WZNmygkx88lK0%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; alt=&quot;블로그 목록&quot; loading=&quot;lazy&quot; width=&quot;800&quot; height=&quot;647&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;647&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;블로그 목록&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;h4 data-ke-size=&quot;size20&quot;&gt;상위/하위 카테고리&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;티스토리 블로그의 &lt;b&gt;카테고리 관리 메뉴&lt;/b&gt;에 설정된 그대로 폴더가 생성됩니다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;713&quot; data-origin-height=&quot;427&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/P1JHr/btreYnPwJpI/HYcZkRnC6Wxldy8K9rbEvK/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/P1JHr/btreYnPwJpI/HYcZkRnC6Wxldy8K9rbEvK/img.webp&quot; data-alt=&quot;카테고리 목록&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/P1JHr/btreYnPwJpI/HYcZkRnC6Wxldy8K9rbEvK/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FP1JHr%2FbtreYnPwJpI%2FHYcZkRnC6Wxldy8K9rbEvK%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; alt=&quot;카테고리 목록&quot; loading=&quot;lazy&quot; width=&quot;713&quot; height=&quot;427&quot; data-origin-width=&quot;713&quot; data-origin-height=&quot;427&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;카테고리 목록&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;백업 완료 후 생성된 폴더는 아래와 같습니다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;192&quot; data-origin-height=&quot;384&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/boXVTJ/btre6CDSK12/bJfMTSFs7NLKKKOsq4ngvk/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/boXVTJ/btre6CDSK12/bJfMTSFs7NLKKKOsq4ngvk/img.webp&quot; data-alt=&quot;생성된 카테고리 폴더&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/boXVTJ/btre6CDSK12/bJfMTSFs7NLKKKOsq4ngvk/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FboXVTJ%2Fbtre6CDSK12%2FbJfMTSFs7NLKKKOsq4ngvk%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; alt=&quot;생성된 카테고리 폴더&quot; loading=&quot;lazy&quot; width=&quot;192&quot; height=&quot;384&quot; data-origin-width=&quot;192&quot; data-origin-height=&quot;384&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;생성된 카테고리 폴더&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;h4 data-ke-size=&quot;size20&quot;&gt;백업 결과&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각 포스트는 선택한 옵션에 따라 &lt;b&gt;포스트 &lt;/b&gt;&lt;span style=&quot;background-color: #fafafa;&quot;&gt;&lt;b&gt;제목 이름의 폴더&lt;/b&gt;에&lt;span&gt; &lt;/span&gt;&lt;/span&gt;백업이 됩니다. 참고로, 옵션에 따라 '&lt;b&gt;제목 이름&lt;/b&gt;', '&lt;b&gt;[날짜] 제목 이름&lt;/b&gt;' 그리고 '&lt;b&gt;[글 번호] 제목 이름&lt;/b&gt;'으로 저장이 됩니다. HTML 본문은 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;content.html&lt;/span&gt;&lt;/code&gt;로 저장되고, &lt;b&gt;이미지 태그를 분석&lt;/b&gt;하여 첨부된 그림 파일을 개별 확장자로 저장합니다. &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;첨부된 파일(zip, pdf 등)&lt;/span&gt;&lt;/code&gt;도 같이 저장됩니다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;564&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qUZRh/btre7JbGFCX/qizgaSaE9eEXHPVH2dltg1/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qUZRh/btre7JbGFCX/qizgaSaE9eEXHPVH2dltg1/img.webp&quot; data-alt=&quot;백업 결과물&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qUZRh/btre7JbGFCX/qizgaSaE9eEXHPVH2dltg1/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqUZRh%2Fbtre7JbGFCX%2FqizgaSaE9eEXHPVH2dltg1%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; alt=&quot;백업 결과물&quot; loading=&quot;lazy&quot; width=&quot;800&quot; height=&quot;564&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;564&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;백업 결과물&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;프로그램 다운로드&lt;/h3&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;다운로드 링크를 클릭하면, OneDrive 다운로드 화면으로 연결됩니다. 프로그램 사용 방법은 본문 하단에 작성되어 있습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;※ 다음(DAUM)에서 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;저품질 블로그&lt;/b&gt;&lt;/span&gt;로 지정되면 OpenAPI 접근이 불가합니다. 이 경우 백업이 안 되니 참고하세요.&lt;br /&gt;※ 오래된 티스토리 에디터에서 작성된 게시물은 &lt;span style=&quot;color: #ee2323;&quot;&gt;첨부 파일이 이미지 태그로 감싸져 있는 경우&lt;/span&gt;가 있습니다. 이는 이미지 저장으로 시도되고 결국 &lt;span style=&quot;color: #ee2323;&quot;&gt;백업 실패&lt;/span&gt;로 이어집니다. 이에 따라 백업 결과에 실패가 기록되니 따로 저장해야 합니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a title=&quot;다운로드 링크&quot; href=&quot;https://1drv.ms/u/s!AhrLbATTcIfkyxCRMR6hmny7Y9Un?e=O8zxGN&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;☆Tistory Backup v2.6 다운로드(OneDrive)☆&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;center&gt;
&lt;script src=&quot;https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js&quot;&gt;&lt;/script&gt;
&lt;ins class=&quot;adsbygoogle&quot; style=&quot;display: block;&quot; data-ad-client=&quot;ca-pub-3156423405867571&quot; data-ad-slot=&quot;4203200518&quot; data-ad-format=&quot;link&quot; data-full-width-responsive=&quot;false&quot; data-ad-language=&quot;ko&quot;&gt;&lt;/ins&gt;
&lt;script&gt;
(adsbygoogle = window.adsbygoogle || []).push({});&lt;/script&gt;
&lt;/center&gt;
&lt;h3 style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;업데이트 이력&lt;/h3&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;업데이트 이력은 아래 '&lt;b&gt;더보기&lt;/b&gt;' 버튼을 클릭하여 확인할 수 있습니다.&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;v2.6&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이전 버전의 &lt;span style=&quot;background-color: #fafafa;&quot;&gt;티스토리&lt;span&gt; 에디터에서 작성된 이미지가 저장되지 않는 현상이 개선됐습니다.&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;v2.5&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;자동 로그인이 안되도록 변경했습니다(티스토리 문의 결과 &lt;b&gt;Tistory REST API 로그아웃&lt;/b&gt; 기능은 지원이 안된다고 합니다).&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;v2.4&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;HTML 태그에 따라 이미지가 저장되지 않는 현상을 해결했습니다. 본문에 존재하는 img 태그는 모두 저장됩니다.&lt;/li&gt;
&lt;li&gt;'카레고리 폴더 생성' 옵션을 추가했습니다. 체크하면 카테고리 이름 폴더에 각 포스트가 저장되고, 해제하면 블로그 이름 폴더에 일괄 저장됩니다.&lt;br /&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;298&quot; data-origin-height=&quot;130&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dPGuIP/btrytkdeZEK/lseH6ELtZsbZyo1Lw4iM80/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dPGuIP/btrytkdeZEK/lseH6ELtZsbZyo1Lw4iM80/img.png&quot; data-alt=&quot;카테고리 폴더 생성 옵션&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dPGuIP/btrytkdeZEK/lseH6ELtZsbZyo1Lw4iM80/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdPGuIP%2FbtrytkdeZEK%2FlseH6ELtZsbZyo1Lw4iM80%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;298&quot; height=&quot;130&quot; data-origin-width=&quot;298&quot; data-origin-height=&quot;130&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;카테고리 폴더 생성 옵션&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/li&gt;
&lt;li&gt;'버그 신고' 기능을 추가했습니다. 백업 프로그램 사용 중 버그가 발생하면 해당 버튼을 클릭하여 신고해 주세요.&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;506&quot; data-origin-height=&quot;423&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bWgJqO/btryp34TMbc/LCuDUvczSiJgnmHnkLKZ7K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bWgJqO/btryp34TMbc/LCuDUvczSiJgnmHnkLKZ7K/img.png&quot; data-alt=&quot;버그 신고 방법&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bWgJqO/btryp34TMbc/LCuDUvczSiJgnmHnkLKZ7K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbWgJqO%2Fbtryp34TMbc%2FLCuDUvczSiJgnmHnkLKZ7K%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;506&quot; height=&quot;423&quot; data-origin-width=&quot;506&quot; data-origin-height=&quot;423&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;버그 신고 방법&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/li&gt;
&lt;li&gt;백업 완료 후 저장 경로에 '백업 결과.txt'파일이 생성됩니다. 내용에는 블로그 이름과 저장된 포스트 개수 그리고 저장되지 못한 경우 어떤 게시물에서 무슨 에러가 발생했는지 간략히 기록됩니다.&lt;/li&gt;
&lt;li&gt;기타 UI 변경.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;v2.3&lt;/h4&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;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;v2.2&lt;/h4&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;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;v2.1&lt;/h4&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;br /&gt;(실제 윈도우 폴더 생성 시 이름 마지막에 '.' 문자가 포함되면 '.' 문자가 자동으로 사라집니다. 백업 프로그램도 글 제목 마지막에 '.' 문자를 강제로 지우도록 수정했습니다.)&lt;/li&gt;
&lt;li&gt;백업 시 폴더 제목은 '글 제목' 그대로 저장됐습니다. '글 제목'과 '[날짜] 제목', '[번호] 제목'을 선택할 수 있도록 옵션을 추가했습니다.&lt;br /&gt;&lt;br /&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;303&quot; data-origin-height=&quot;238&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bpeW9I/btrmWqw9mg0/wagRKvKj2uk0aIXmjrIFL0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bpeW9I/btrmWqw9mg0/wagRKvKj2uk0aIXmjrIFL0/img.png&quot; data-alt=&quot;저장 옵션&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bpeW9I/btrmWqw9mg0/wagRKvKj2uk0aIXmjrIFL0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbpeW9I%2FbtrmWqw9mg0%2FwagRKvKj2uk0aIXmjrIFL0%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;303&quot; height=&quot;238&quot; data-origin-width=&quot;303&quot; data-origin-height=&quot;238&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;저장 옵션&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/li&gt;
&lt;li&gt;기타 마이너 업데이트.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;v2.0&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;전반적인 UI 교체.&lt;/li&gt;
&lt;li&gt;블로그를 개별적으로 선택하여 백업 가능.&lt;/li&gt;
&lt;li&gt;다양한 백업 옵션 제공.&lt;/li&gt;
&lt;li&gt;카카오 로그인 인증 이슈 해결.&lt;/li&gt;
&lt;li&gt;설치 파일로 제공.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;v1.1&lt;/h4&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;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;v1.0&lt;/h4&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;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;프로그램 사용 방법&lt;/h3&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;프로그램 사용 방법은 아래 '&lt;b&gt;더보기&lt;/b&gt;' 버튼을 클릭하여 확인할 수 있습니다.&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;로그인하기&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로그램 실행 시 로그인 화면으로 연결됩니다. 카카오 계정 또는 티스토리 계정 버튼을 클릭합니다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;647&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/VfU3J/btre6DphdHl/7GByDegSwgVvKgSJuwhN5K/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/VfU3J/btre6DphdHl/7GByDegSwgVvKgSJuwhN5K/img.webp&quot; data-alt=&quot;로그인 화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/VfU3J/btre6DphdHl/7GByDegSwgVvKgSJuwhN5K/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FVfU3J%2Fbtre6DphdHl%2F7GByDegSwgVvKgSJuwhN5K%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; alt=&quot;로그인 화면&quot; loading=&quot;lazy&quot; width=&quot;800&quot; height=&quot;647&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;647&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;로그인 화면&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;계정 아이디와 비밀번호를 입력하고 로그인 버튼을 클릭합니다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;647&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/VR6wg/btreY4hUSHu/R727KKhXjasA5c9VNvtNS1/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/VR6wg/btreY4hUSHu/R727KKhXjasA5c9VNvtNS1/img.webp&quot; data-alt=&quot;로그인 계정 입력 화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/VR6wg/btreY4hUSHu/R727KKhXjasA5c9VNvtNS1/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FVR6wg%2FbtreY4hUSHu%2FR727KKhXjasA5c9VNvtNS1%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; alt=&quot;로그인 계정 입력 화면&quot; loading=&quot;lazy&quot; width=&quot;800&quot; height=&quot;647&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;647&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;로그인 계정 입력 화면&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;티스토리 API 접근을 위해 '&lt;b&gt;허가하기&lt;/b&gt;' 버튼을 클릭합니다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;647&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/wjVzU/btreZ0fbAHU/iZZOxXolJnq6cPZAGqfMz0/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/wjVzU/btreZ0fbAHU/iZZOxXolJnq6cPZAGqfMz0/img.webp&quot; data-alt=&quot;티스토리 API 접근 권한 화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/wjVzU/btreZ0fbAHU/iZZOxXolJnq6cPZAGqfMz0/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FwjVzU%2FbtreZ0fbAHU%2FiZZOxXolJnq6cPZAGqfMz0%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; alt=&quot;티스토리 API 접근 권한 화면&quot; loading=&quot;lazy&quot; width=&quot;800&quot; height=&quot;647&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;647&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;티스토리 API 접근 권한 화면&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;h4 data-ke-size=&quot;size20&quot;&gt;백업 옵션 설정하기&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #fafafa;&quot;&gt;로그인 이후 아래의 화면에서 우측 하단의 '&lt;/span&gt;&lt;b&gt;설정하기&lt;/b&gt;&lt;span style=&quot;background-color: #fafafa;&quot;&gt;'버튼을 클릭하여 옵션을 설정할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;647&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dJBfsS/btre6DbHDUK/caLz2SImCEefI0dKT4Zme1/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dJBfsS/btre6DbHDUK/caLz2SImCEefI0dKT4Zme1/img.webp&quot; data-alt=&quot;백업 프로그램 메인 화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dJBfsS/btre6DbHDUK/caLz2SImCEefI0dKT4Zme1/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdJBfsS%2Fbtre6DbHDUK%2FcaLz2SImCEefI0dKT4Zme1%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; alt=&quot;백업 프로그램 메인 화면&quot; loading=&quot;lazy&quot; width=&quot;800&quot; height=&quot;647&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;647&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;백업 프로그램 메인 화면&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;아래와 같이 저장 경로와 저장 옵션을 선택할 수 있는데요. 각 항목의 설명은 아래 표와 같습니다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;326&quot; data-origin-height=&quot;470&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Yu0sL/btryrqeebGr/L7ypr8o3eK6yjU8CyiJVKK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Yu0sL/btryrqeebGr/L7ypr8o3eK6yjU8CyiJVKK/img.png&quot; data-alt=&quot;백업 옵션&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Yu0sL/btryrqeebGr/L7ypr8o3eK6yjU8CyiJVKK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FYu0sL%2FbtryrqeebGr%2FL7ypr8o3eK6yjU8CyiJVKK%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;326&quot; height=&quot;470&quot; data-origin-width=&quot;326&quot; data-origin-height=&quot;470&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;백업 옵션&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 140px;&quot; border=&quot;1&quot; data-ke-style=&quot;style12&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 20px; text-align: center;&quot;&gt;&lt;b&gt;항목&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 20px; text-align: center;&quot;&gt;&lt;b&gt;설명&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 20px; text-align: center;&quot;&gt;저장 경로&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;백업 파일이 저장될 위치를 선택합니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 20px; text-align: center;&quot;&gt;덮어 쓰기&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;&lt;span style=&quot;background-color: #fafafa;&quot;&gt;이미 같은 '글'이 존재하더라도 덮어씁니다.&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 20px; text-align: center;&quot;&gt;이미지 파일&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;이미지 파일 저장 여부를 선택합니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 50%; text-align: center; height: 20px;&quot;&gt;첨부 파일&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;첨부 파일 저장 여부를 선택합니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 50%; text-align: center; height: 20px;&quot;&gt;HTML 파일&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;HTML 파일 저장 여부를 선택합니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;카테고리 폴더 생성&lt;/td&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;카테고리 별 폴더를 생성할지 여부를 선택합니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 50%; text-align: center; height: 20px;&quot;&gt;폴더 이름 옵션&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;폴더로 생성되는 글의 제목 형태를 선택합니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;백업하는 방법&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #fafafa;&quot;&gt;로그인 이후 아래의 화면에서 좌측 하단의 '&lt;/span&gt;&lt;b&gt;백업 시작&lt;/b&gt;&lt;span style=&quot;background-color: #fafafa;&quot;&gt;'버튼을 클릭하여 백업을 진행할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;647&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/uiY9A/btre5cFIlvL/qkTOqEGfqcCKTW0oPN8TH1/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/uiY9A/btre5cFIlvL/qkTOqEGfqcCKTW0oPN8TH1/img.webp&quot; data-alt=&quot;백업 시작 버튼&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/uiY9A/btre5cFIlvL/qkTOqEGfqcCKTW0oPN8TH1/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FuiY9A%2Fbtre5cFIlvL%2FqkTOqEGfqcCKTW0oPN8TH1%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; alt=&quot;백업 시작 버튼&quot; loading=&quot;lazy&quot; width=&quot;800&quot; height=&quot;647&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;647&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;백업 시작 버튼&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;백업이 진행되면 하단에 진행률이 표시됩니다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;647&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bj0DJg/btre1bHwxU8/kqVaak3QHECjEMe6DzQnUK/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bj0DJg/btre1bHwxU8/kqVaak3QHECjEMe6DzQnUK/img.webp&quot; data-alt=&quot;백업 진행 중인 화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bj0DJg/btre1bHwxU8/kqVaak3QHECjEMe6DzQnUK/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbj0DJg%2Fbtre1bHwxU8%2FkqVaak3QHECjEMe6DzQnUK%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; alt=&quot;백업 진행 중인 화면&quot; loading=&quot;lazy&quot; width=&quot;800&quot; height=&quot;647&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;647&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;백업 진행 중인 화면&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;백업이 완료되면 아래와 같이 알림 창이 표시됩니다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;232&quot; data-origin-height=&quot;150&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nsyVl/btreY3Dgzcz/8KLMXwR5lQZQjrEDVJgTwK/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nsyVl/btreY3Dgzcz/8KLMXwR5lQZQjrEDVJgTwK/img.webp&quot; data-alt=&quot;백업 완료 알림 화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nsyVl/btreY3Dgzcz/8KLMXwR5lQZQjrEDVJgTwK/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FnsyVl%2FbtreY3Dgzcz%2F8KLMXwR5lQZQjrEDVJgTwK%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; alt=&quot;백업 완료 알림 화면&quot; loading=&quot;lazy&quot; width=&quot;232&quot; height=&quot;150&quot; data-origin-width=&quot;232&quot; data-origin-height=&quot;150&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;백업 완료 알림 화면&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;버그 신고 방법&lt;/h3&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;프로그램 사용 중 문제가 발생하면 아래 '&lt;b&gt;더보기&lt;/b&gt;' 버튼을 클릭하여 절차 확인 후 신고 부탁드립니다.&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;h4 style=&quot;text-align: left;&quot; data-ke-size=&quot;size20&quot;&gt;문제 발생 시 확인 절차&lt;/h4&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;프로그램 우측 상단의 '버그 신고' 버튼을 클릭합니다.&lt;br /&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;284&quot; data-origin-height=&quot;135&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/1LNaK/btryrXCR6ka/zSbcJOBktztKvB12xYtwwK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/1LNaK/btryrXCR6ka/zSbcJOBktztKvB12xYtwwK/img.png&quot; data-alt=&quot;버그 신고 버튼&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/1LNaK/btryrXCR6ka/zSbcJOBktztKvB12xYtwwK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F1LNaK%2FbtryrXCR6ka%2FzSbcJOBktztKvB12xYtwwK%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;284&quot; height=&quot;135&quot; data-origin-width=&quot;284&quot; data-origin-height=&quot;135&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;버그 신고 버튼&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/li&gt;
&lt;li&gt;'버그 신고 방법' 창 표시됩니다. 내용을 차근히 읽고 절차대로 진행합니다.&lt;br /&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;506&quot; data-origin-height=&quot;423&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bXLImD/btryn8lyWxO/QKKteCGVBZfCKGTVhpnuN1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bXLImD/btryn8lyWxO/QKKteCGVBZfCKGTVhpnuN1/img.png&quot; data-alt=&quot;버그 신고 절차&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bXLImD/btryn8lyWxO/QKKteCGVBZfCKGTVhpnuN1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbXLImD%2Fbtryn8lyWxO%2FQKKteCGVBZfCKGTVhpnuN1%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;506&quot; height=&quot;423&quot; data-origin-width=&quot;506&quot; data-origin-height=&quot;423&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;버그 신고 절차&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;</description>
      <category>Programming/프로그램 배포</category>
      <category>티스토리</category>
      <author>❤ </author>
      <guid isPermaLink="true">https://luckygg.tistory.com/332</guid>
      <comments>https://luckygg.tistory.com/332#entry332comment</comments>
      <pubDate>Thu, 11 Aug 2022 22:19:17 +0900</pubDate>
    </item>
    <item>
      <title>[C++] RAII(SBRM)로 안전하게 리소스 관리하기</title>
      <link>https://luckygg.tistory.com/371</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;RAII(Resource Acquisition Is Initialization) - SBRM(Scope Bound Resource Managemnet)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;가비지 컬렉터(Garbage Collector)&lt;/span&gt;&lt;/code&gt;가 있는 C#과 달리, C++ 프로그래밍에서 &lt;b&gt;자원의 관리는 전적으로 개발자의 책임&lt;/b&gt;입니다. 힙(Heap) 영역에서 어떤 핸들을 생성했으면 반드시 해제하여 메모리 사용을 반환해야 하는 것이죠. 만약, 그렇지 않다면 메모리 누수가 발생하거나 예측 불가능한 상황에 직면할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;자원(Resource)&lt;/span&gt;&lt;/code&gt;이라는 것은 흔히 얘기하는 사용자 버퍼 공간이 될 수도 있고, 소켓, 파일, GDI 등 어떤 객체의 핸들이 될 수도 있습니다. 이러한 자원을 생성하고, &lt;b&gt;스코프 영역(Scope bound)&lt;/b&gt;을 벗어나면 자동으로 해제하는 개념을 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;RAII&lt;/span&gt;&lt;/code&gt;라고 합니다. RAII를 &lt;b&gt;디자인 패턴(Design pattern)&lt;/b&gt; 또는 &lt;b&gt;관용구(Idiom)&lt;/b&gt;라고도 하죠.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참고로, RAII 이름이 개념에 비해 적절하지 않다는 의견이 있습니다. &lt;span style=&quot;letter-spacing: 0px;&quot;&gt;RAII 개념의 핵심은 &lt;b&gt;파괴(해제)&lt;/b&gt;인데, 이름은 초기화이기 때문입니다. 그래서 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;SBRM(Scope Bound Resource Management)&lt;/span&gt;&lt;/code&gt;라는 이름이 생긴 것이죠. SBRM은 의미 그대로, 스코프 영역에서의 자원 관리를 뜻합니다. 좀 더 이해하기가 쉽죠?&lt;/span&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;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;아래 링크는 RAII 이름에 대한 번역가 류광님의 해석인데, 해당 링크도 읽어보면 좋을 것 같습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;&lt;a href=&quot;https://occamsrazr.net/tt/297&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://occamsrazr.net/tt/297&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1658654924872&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++ RAII(Resource Acquisition Is Initialization)의 해석&quot; data-og-description=&quot;RAII라는 이름 자체에 대한 &amp;quot;꿈보다 해몽&amp;quot;&quot; data-og-host=&quot;occamsrazr.net&quot; data-og-source-url=&quot;https://occamsrazr.net/tt/297&quot; data-og-url=&quot;http://occamsrazr.net/tt/article/297&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bWyIMS/hyPbUW56MS/5LrrisXEWkUR55ktlDgdGk/img.jpg?width=150&amp;amp;height=150&amp;amp;face=0_0_150_150,https://scrap.kakaocdn.net/dn/gi7JU/hyPbX0z9bF/Xz2cNNCkNwkbwiev5Dqkek/img.jpg?width=150&amp;amp;height=150&amp;amp;face=0_0_150_150&quot;&gt;&lt;a href=&quot;https://occamsrazr.net/tt/297&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://occamsrazr.net/tt/297&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bWyIMS/hyPbUW56MS/5LrrisXEWkUR55ktlDgdGk/img.jpg?width=150&amp;amp;height=150&amp;amp;face=0_0_150_150,https://scrap.kakaocdn.net/dn/gi7JU/hyPbX0z9bF/Xz2cNNCkNwkbwiev5Dqkek/img.jpg?width=150&amp;amp;height=150&amp;amp;face=0_0_150_150');&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++ RAII(Resource Acquisition Is Initialization)의 해석&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;RAII라는 이름 자체에 대한 &quot;꿈보다 해몽&quot;&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;occamsrazr.net&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;RAII가 필요한 상황&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇다면, RAII라는 것이 어떤 상황에서 필요한 것일까요? 몇 가지 예시를 들어 보겠습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;mutex가 안전하게 해제되지 않는 경우&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래 코드는 &lt;code&gt;&lt;span class=&quot;token function-name&quot;&gt;doSomething()&lt;/span&gt;&lt;/code&gt; 함수에 진입하면 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;mutex&lt;/span&gt;&lt;/code&gt;로 lock이 걸려 다른 리소스의 접근을 막게 되고, 이후 예외가 발생하여 가장 근접한 &lt;code&gt;&lt;span class=&quot;token function&quot;&gt;try-catch 문&lt;/span&gt;&lt;/code&gt;으로 빠져나가는 동작을 수행합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1658838496703&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;mutex&amp;gt;

std::mutex mutex;

void doSomething()
{
	mutex.lock();

	throw std::exception(&quot;예외 발생!&quot;);

	mutex.unlock();
}

int main()
{
	try
	{
		doSomething();
	}
	catch (const std::exception&amp;amp; exc)
	{
		std::cout &amp;lt;&amp;lt; exc.what() &amp;lt;&amp;lt; std::endl;
	}
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, unlock이 호출되지 않은 채 불안정하게 함수를 빠져나가는 상황입니다. 이렇게 잠금이 해제되지 않은 채 프로그램이 종료되거나, 다른 곳에서 다시 lock을 호출하면 오류가 발생합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 경우에는 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;lock_guard&lt;/span&gt;&lt;/code&gt;를 사용하여 안전하게 mutex를 사용할 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1658839357844&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;mutex&amp;gt;

std::mutex mutex;

void doSomething()
{
	std::lock_guard&amp;lt;std::mutex&amp;gt; g(mutex);

	throw std::exception(&quot;예외 발생!&quot;);
}

int main()
{
	try
	{
		doSomething();
	}
	catch (const std::exception&amp;amp; exc)
	{
		std::cout &amp;lt;&amp;lt; exc.what() &amp;lt;&amp;lt; std::endl;
	}
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;lock_guard&lt;/span&gt;&lt;/code&gt;는 &lt;b&gt;RAII 스타일 메커니즘이 적용된 편리한 mutex wrapper 클래스&lt;/b&gt;로, lock_guard 객체가 생성되면 mutex 소유권을 얻으려고 시도하고, 스코프 영역을 벗어나면 객체가 파괴되고 해제됩니다. 자세한 설명은 아래 링크를 참고하세요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://en.cppreference.com/w/cpp/thread/lock_guard&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://en.cppreference.com/w/cpp/thread/lock_guard&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1658839562644&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;std::lock_guard - cppreference.com&quot; data-og-description=&quot;template&amp;lt; class Mutex &amp;gt; class lock_guard; (since C++11) The class lock_guard is a mutex wrapper that provides a convenient RAII-style mechanism for owning a mutex for the duration of a scoped block. When a lock_guard object is created, it attempts to take &quot; data-og-host=&quot;en.cppreference.com&quot; data-og-source-url=&quot;https://en.cppreference.com/w/cpp/thread/lock_guard&quot; data-og-url=&quot;https://en.cppreference.com/w/cpp/thread/lock_guard&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://en.cppreference.com/w/cpp/thread/lock_guard&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://en.cppreference.com/w/cpp/thread/lock_guard&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;std::lock_guard - cppreference.com&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;template&amp;lt; class Mutex &amp;gt; class lock_guard; (since C++11) The class lock_guard is a mutex wrapper that provides a convenient RAII-style mechanism for owning a mutex for the duration of a scoped block. When a lock_guard object is created, it attempts to take&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;en.cppreference.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;사용자 메모리가 안전하게 해제되지 않는 경우&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자 메모리를 생성하고 제거하기 위해 &lt;code&gt;&lt;span class=&quot;token function&quot;&gt;new&lt;/span&gt;&lt;/code&gt;와 &lt;code&gt;&lt;span class=&quot;token function&quot;&gt;delete&lt;/span&gt;&lt;/code&gt;를 사용합니다. 아래 예시는, 사용자 메모리를 생성했는데 어떠한 이유로 delete를 정상적으로 호출하지 않아 메모리 누수가 감지되는 상황입니다.&lt;/p&gt;
&lt;pre id=&quot;code_1658840009461&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#define _CRTDBG_MAP_ALLOC
#include &amp;lt;cstdlib&amp;gt;
#include &amp;lt;crtdbg.h&amp;gt;

#ifdef _DEBUG
#define new new ( _NORMAL_BLOCK , __FILE__ , __LINE__ )
#endif

void doSomething()
{
	unsigned char* buffer = new unsigned char[100];

	throw std::exception(&quot;예외 발생!&quot;);

	delete buffer;
	buffer = nullptr;
}

int main()
{
	try
	{
		doSomething();
	}
	catch (const std::exception&amp;amp; exc)
	{
		std::cout &amp;lt;&amp;lt; exc.what() &amp;lt;&amp;lt; std::endl;
	}

	_CrtDumpMemoryLeaks();
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 코드를 실행하면 아래와 같이 메모리 누수가 감지됩니다. 해당 메시지를 더블 클릭하면 정확히 11번째 라인에서 메모리 누수가 있음을 알 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;736&quot; data-origin-height=&quot;201&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cHiPHD/btrIjLG773R/Z60rRKpk32LuumYELk9zg1/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cHiPHD/btrIjLG773R/Z60rRKpk32LuumYELk9zg1/img.webp&quot; data-alt=&quot;메모리 누수가 감지된 결과&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cHiPHD/btrIjLG773R/Z60rRKpk32LuumYELk9zg1/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcHiPHD%2FbtrIjLG773R%2FZ60rRKpk32LuumYELk9zg1%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; alt=&quot;메모리-누수가-감지된-결과&quot; loading=&quot;lazy&quot; width=&quot;736&quot; height=&quot;201&quot; data-origin-width=&quot;736&quot; data-origin-height=&quot;201&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;위 예시의 CRTDBG를 사용하는 방법은 아래 링크를 참고하세요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://luckygg.tistory.com/226&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;[디버깅] 메모리 누수를 점검하는 방법 - CRTDBG (예제 포함)&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1658840150438&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;[디버깅] 메모리 누수를 점검하는 방법 - CRTDBG (예제 포함)&quot; data-og-description=&quot;메모리 누수와 관련된 포스팅은 아래 링크를 참고해주세요. [디버깅] 메모리 누수와 점검하는 방법 소개 [디버깅] 메모리 누수와 점검하는 방법 소개 소개 Unmanaged Code인 C++은 메모리 할당과 해제&quot; data-og-host=&quot;luckygg.tistory.com&quot; data-og-source-url=&quot;https://luckygg.tistory.com/226&quot; data-og-url=&quot;https://luckygg.tistory.com/226&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/dDqOBp/hyPeTPVoXv/e5zgxUbPj6KYd9XjW5jxa0/img.png?width=792&amp;amp;height=232&amp;amp;face=0_0_792_232,https://scrap.kakaocdn.net/dn/gzas6/hyPdkn62io/1icq9w6dLCdhkmIsSM7pBK/img.png?width=792&amp;amp;height=232&amp;amp;face=0_0_792_232,https://scrap.kakaocdn.net/dn/0r9Td/hyPeHopPZz/zM1ikKpqEq1CzKMXpi9ZAK/img.png?width=906&amp;amp;height=228&amp;amp;face=0_0_906_228&quot;&gt;&lt;a href=&quot;https://luckygg.tistory.com/226&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://luckygg.tistory.com/226&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/dDqOBp/hyPeTPVoXv/e5zgxUbPj6KYd9XjW5jxa0/img.png?width=792&amp;amp;height=232&amp;amp;face=0_0_792_232,https://scrap.kakaocdn.net/dn/gzas6/hyPdkn62io/1icq9w6dLCdhkmIsSM7pBK/img.png?width=792&amp;amp;height=232&amp;amp;face=0_0_792_232,https://scrap.kakaocdn.net/dn/0r9Td/hyPeHopPZz/zM1ikKpqEq1CzKMXpi9ZAK/img.png?width=906&amp;amp;height=228&amp;amp;face=0_0_906_228');&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;[디버깅] 메모리 누수를 점검하는 방법 - CRTDBG (예제 포함)&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;메모리 누수와 관련된 포스팅은 아래 링크를 참고해주세요. [디버깅] 메모리 누수와 점검하는 방법 소개 [디버깅] 메모리 누수와 점검하는 방법 소개 소개 Unmanaged Code인 C++은 메모리 할당과 해제&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;luckygg.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 사용자 메모리를 안전하게 사용하기 위해서는 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;스마트 포인터(Smart pointer)&lt;/span&gt;&lt;/code&gt;를 사용할 것을 권장합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1658840372472&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;vector&amp;gt;
#include &amp;lt;memory&amp;gt;

#define _CRTDBG_MAP_ALLOC
#include &amp;lt;cstdlib&amp;gt;
#include &amp;lt;crtdbg.h&amp;gt;

#ifdef _DEBUG
#define new new ( _NORMAL_BLOCK , __FILE__ , __LINE__ )
#endif

void doSomething()
{
	std::unique_ptr&amp;lt;std::vector&amp;lt;unsigned char&amp;gt;&amp;gt; buffer = std::make_unique&amp;lt;std::vector&amp;lt;unsigned char&amp;gt;&amp;gt;(100);
	
	throw std::exception(&quot;예외 발생!&quot;);
}

int main()
{
	try
	{
		doSomething();
	}
	catch (const std::exception&amp;amp; exc)
	{
		std::cout &amp;lt;&amp;lt; exc.what() &amp;lt;&amp;lt; std::endl;
	}

	_CrtDumpMemoryLeaks();
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다소 복잡해 보이는데요. &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;unsigned char&lt;/span&gt;&lt;/code&gt;를 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;vector&lt;/span&gt;&lt;/code&gt;로 구성하고, 이를 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;unique_ptr&lt;/span&gt;&lt;/code&gt;로 관리하는 방식입니다. 이 경우, 아래와 같이 직접 포인터 주소에 접근할 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1658840504616&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;unsigned char* ptr = buffer-&amp;gt;data();&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;&lt;a href=&quot;https://en.cppreference.com/book/intro/smart_pointers&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://en.cppreference.com/book/intro/smart_pointers&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1658840885575&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;smart pointers - cppreference.com&quot; data-og-description=&quot;Warning: This wiki is part of the deprecated and unmaintained CppReference Book project. For up-to-date information on C++, see the main reference at cppreference.com. Smart pointers are used to make sure that an object is deleted if it is no longer used (&quot; data-og-host=&quot;en.cppreference.com&quot; data-og-source-url=&quot;https://en.cppreference.com/book/intro/smart_pointers&quot; data-og-url=&quot;https://en.cppreference.com/book/intro/smart_pointers&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://en.cppreference.com/book/intro/smart_pointers&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://en.cppreference.com/book/intro/smart_pointers&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;smart pointers - cppreference.com&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Warning: This wiki is part of the deprecated and unmaintained CppReference Book project. For up-to-date information on C++, see the main reference at cppreference.com. Smart pointers are used to make sure that an object is deleted if it is no longer used (&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;en.cppreference.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;</description>
      <category>Programming/C++</category>
      <category>C++</category>
      <author>❤ </author>
      <guid isPermaLink="true">https://luckygg.tistory.com/371</guid>
      <comments>https://luckygg.tistory.com/371#entry371comment</comments>
      <pubDate>Wed, 27 Jul 2022 21:00:26 +0900</pubDate>
    </item>
    <item>
      <title>[GigE Interface] GigE를 사용하기 위한 준비 Part 2.</title>
      <link>https://luckygg.tistory.com/55</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;GigE를 사용하기 위한 준비 Part 2.&lt;/h2&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://luckygg.tistory.com/45&quot;&gt;[GigE Interface] Gigabit Ethernet(GigE) 인터페이스&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1657983345890&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;[GigE Interface] Gigabit Ethernet(GigE) 인터페이스&quot; data-og-description=&quot;Gigabit Ethernet(GigE)&amp;nbsp;효율적이고 신뢰할 수 있는 인터페이스. 낮은 비용, 향상된 시스템 유연성, 간단한 구성품, 신뢰할 수 있는 데이터 전송 및 산업 표준 정립 등의 이유로 Gigabit Ethernet이 머신 비&quot; data-og-host=&quot;luckygg.tistory.com&quot; data-og-source-url=&quot;https://luckygg.tistory.com/45&quot; data-og-url=&quot;https://luckygg.tistory.com/45&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/c5NhXv/hyO7IH8IZB/DhBd4jJv5USJ1kSx8TvEFK/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/dcXe4g/hyO7JfYWjK/CKOaj6MKIzimgOTTHwM981/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800&quot;&gt;&lt;a href=&quot;https://luckygg.tistory.com/45&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://luckygg.tistory.com/45&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/c5NhXv/hyO7IH8IZB/DhBd4jJv5USJ1kSx8TvEFK/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/dcXe4g/hyO7JfYWjK/CKOaj6MKIzimgOTTHwM981/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800');&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;[GigE Interface] Gigabit Ethernet(GigE) 인터페이스&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Gigabit Ethernet(GigE)&amp;nbsp;효율적이고 신뢰할 수 있는 인터페이스. 낮은 비용, 향상된 시스템 유연성, 간단한 구성품, 신뢰할 수 있는 데이터 전송 및 산업 표준 정립 등의 이유로 Gigabit Ethernet이 머신 비&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;luckygg.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;GigE 인터페이스를 사용하기 위해서는 하드웨어뿐만 아니라 드라이버 설정과 소프트웨어도 준비를 해야 합니다. 일반적으로 준비 요소로는 아래 네 가지 정도가 있습니다.&lt;/p&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;GigE 카메라를 사용하기 위해서는 네트워크 드라이버에서 설정해야 하는 권장 항목이 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;① &lt;b&gt;점보 프레임 또는 패킷(Jumbo Frame / Packet)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;점보 패킷은 &lt;b&gt;데이터를 한 번에 보낼 수 있는 최대 크기&lt;/b&gt;를 의미하며, 이는 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;MTU(Maximum Transmission Unit)&lt;/span&gt;&lt;/code&gt;라고도 정의합니다.&amp;nbsp;이 값은 데이터를 어느 정도의 크기로 나누어서 처리할 것인지를 설정하는 것인데, 값이 낮을수록 처리 량이 많아져 CPU 부하가 증가하고, 값이 높을수록 처리 량이 줄어들어 CPU 부하가 감소합니다. 기본 값은 1500 byte이며 권장 값은 9KB입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;② &lt;b&gt;수신 버퍼(Receive Buffers)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;수신 패킷에 대해 어댑터가 사용할 수 있는 시스템 메모리의 버퍼 크기를 의미합니다.&amp;nbsp;네트워크 트래픽의 성능을 향상하는 설정이며, 카메라의 패킷 데이터 손실을 줄이기 위해서는 최대 값으로 설정하는 것을 권장합니다.&amp;nbsp;Intel 칩셋의 경우 대부분 2048까지 지원하며 그 외의 칩셋은 값이 낮더라도 항상 최대 값으로 설정해야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;③ &lt;b&gt;인터럽트 조절 속도(Interrupt Moderation Rate)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인터럽트가 자주 발생하면 시스템 문제 발생 시 CPU의 반응 속도가 빨라지게 되지만, 작업 처리 효율이 낮아지는 단점이 있습니다.&amp;nbsp;반대로 인터럽트가 적게 발생하면 CPU의 반응 속도는 느려지지만 작업 처리 효율은 높아집니다.&amp;nbsp;이 설정 값을 '&lt;b&gt;최대(Extreme)&lt;/b&gt;'로 설정하면 인터럽트 속도가 낮아지며 시스템 성능이 향상됩니다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2. GigE SDK&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;카메라 제조사는 GigE SDK를 제공하며, &lt;b&gt;원칙적으로는 해당 제조사의 SDK를 사용해야 안정성을 확보&lt;/b&gt;할 수 있습니다.&amp;nbsp;즉, A사의 카메라를 사용하면 당연히 A사의 SDK를 사용해야 하고, B사의 카메라를 사용하면 B사의 SDK를 사용해야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 경우에 따라 A사의 카메라를 B사의 SDK에 또는 A사의 카메라를 3rd party SDK에 사용하는 경우도 있습니다.&amp;nbsp;같은 GenICam 기반의 SDK라면 문제가 없어야겠지만, 이렇게 사용하는 경우 &lt;b&gt;반드시 호환성을 검증하고 진행&lt;/b&gt;해야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 가장 중요한 점은 &lt;b&gt;시스템에 하나의 SDK만 설치&lt;/b&gt;해야 합니다.&amp;nbsp;대다수의 사용자들이 테스트 때문에 시스템에 여러 개의 SDK를 설치하고 사용하는 경우가 있습니다.&amp;nbsp;이 경우 서로 다른 제조사 드라이버들이 영향을 주어 카메라의 성능이 제대로 발휘되지 않을 수도 있습니다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;3. Filter Driver&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;카메라 제조사마다 GigE SDK 제공 시 필터 드라이버도 포함하여 제공합니다. 이 필터 드라이버는 &lt;b&gt;네트워크의 부하를 줄여주며, 카메라의 데이터 스트리밍을 향상합니다.&lt;/b&gt;&amp;nbsp;별다른 이유가 없다면 반드시 필터 드라이버를 사용하는 것을 권장합니다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;4. Camera Packet Size&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;카메라에도 패킷 사이즈 설정 파라미터가 존재합니다. 일반적으로 이 값은 네트워크 어댑터의 설정된 값보다 작아야 하며, 대부분 8KB~9KB 정도로 설정합니다. 이 값이 너무 작으면 패킷 손실이 발생하여 영상 취득 시 데이터가 누락된 이미지가 얻어지게 됩니다.&lt;/p&gt;</description>
      <category>Machine Vision/Interface</category>
      <category>머신비전</category>
      <author>❤ </author>
      <guid isPermaLink="true">https://luckygg.tistory.com/55</guid>
      <comments>https://luckygg.tistory.com/55#entry55comment</comments>
      <pubDate>Sun, 17 Jul 2022 00:10:07 +0900</pubDate>
    </item>
    <item>
      <title>[.Net] 네트워크 어댑터 IP주소와 고급 속성 변경하기(예제 포함)</title>
      <link>https://luckygg.tistory.com/369</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;네트워크 어댑터 IP 주소와 고급 속성&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;머신 비전에서 GigE 인터페이스를 사용하기 위한 네트워크 설정은 필수입니다. 카메라 연결 및 관리를 위한 &lt;b&gt;고정 IP 주소&lt;/b&gt; 설정은 물론이고, 원활한 데이터 스트리밍을 위한 &lt;b&gt;속성 설정&lt;/b&gt; 및 &lt;b&gt;필터 드라이버(Filter Driver)&lt;/b&gt; 설치는 꼭 필요하죠.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;설정이 필요한 네트워크 속성은 일반적으로 다음의 네 가지가 있습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;점보 패킷(Jumbo Packet)&lt;/li&gt;
&lt;li&gt;수신 버퍼(Receive Buffers)&lt;/li&gt;
&lt;li&gt;전송 버퍼(Transmit Buffers)&lt;/li&gt;
&lt;li&gt;인터럽트 조절 속도(Interrupt Moderation Rate)&lt;/li&gt;
&lt;/ul&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://luckygg.tistory.com/55&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;[GigE Interface] GigE를 사용하기 위한 준비 Part 2.&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1657894276513&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;[GigE Interface] GigE를 사용하기 위한 준비 Part 2.&quot; data-og-description=&quot;GigE를 사용하기 위한 준비 Part 2. 본문 글은 아래 링크를 클릭해주세요. Gigabit Ethernet(GigE) 인터페이스 GigE 인터페이스를 사용하기 위해서는 하드웨어뿐만 아니라 소프트웨어에서도 준비를 해야 &quot; data-og-host=&quot;luckygg.tistory.com&quot; data-og-source-url=&quot;https://luckygg.tistory.com/55&quot; data-og-url=&quot;https://luckygg.tistory.com/55&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/baZRz9/hyO5JBmHWq/qWmL2mK5tj8PadtMKJhCI0/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/bd49VQ/hyO5GxSaMM/gbeLpsqhql0MUiugsLGJk1/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800&quot;&gt;&lt;a href=&quot;https://luckygg.tistory.com/55&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://luckygg.tistory.com/55&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/baZRz9/hyO5JBmHWq/qWmL2mK5tj8PadtMKJhCI0/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/bd49VQ/hyO5GxSaMM/gbeLpsqhql0MUiugsLGJk1/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800');&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;[GigE Interface] GigE를 사용하기 위한 준비 Part 2.&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;GigE를 사용하기 위한 준비 Part 2. 본문 글은 아래 링크를 클릭해주세요. Gigabit Ethernet(GigE) 인터페이스 GigE 인터페이스를 사용하기 위해서는 하드웨어뿐만 아니라 소프트웨어에서도 준비를 해야&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;luckygg.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 IP 주소를 비롯하여, 위에서 언급한 속성을 코드에서 접근하기 위해서는 어떻게 해야 하는지 본문에서 다뤄보겠습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. 네트워크 IP 주소와 서브넷 마스크 얻는 방법&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시스템에 존재하는 네트워크 어댑터의 목록과 IP 주소 그리고 서브넷 마스크를 얻는 방법입니다. &lt;code&gt;&lt;span class=&quot;token function-name&quot;&gt;System.Net.NetworkInformation&lt;/span&gt;&lt;/code&gt; 네임스페이스 추가하여 간단하게 어댑터의 정보를 얻을 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1657979520451&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net.NetworkInformation; //NetworkInformation 네임스페이스 추가

namespace ExamNetwork
{
    class Program
    {
        static void Main(string[] args)
        {
            //모든 네트워크 인터페이스 얻기
            foreach (var network in NetworkInterface.GetAllNetworkInterfaces())
            {
                //IPv4를 지원하는 네트워크 확인
                if (network.Supports(NetworkInterfaceComponent.IPv4) == true)
                {
                    //이더넷 타입 확인
                    if (network.NetworkInterfaceType == NetworkInterfaceType.Ethernet)
                    {
                        //IP 속성 얻기
                        IPInterfaceProperties properties = network.GetIPProperties();
                        //Unicast 주소가 할당된 ip 얻기
                        foreach (UnicastIPAddressInformation uniIp in network.GetIPProperties().UnicastAddresses)
                        {
                            if (uniIp.Address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
                            {
                                string ipAddress = uniIp.Address.ToString();
                                string subNetMask = uniIp.IPv4Mask.ToString();
                                Console.WriteLine(&quot;======================================&quot;);
                                Console.WriteLine($&quot;Name: {network.Name}&quot;);
                                Console.WriteLine($&quot;Description: {network.Description}&quot;);
                                Console.WriteLine($&quot;Type: {network.NetworkInterfaceType}&quot;);
                                Console.WriteLine($&quot;IP: {ipAddress}&quot;);
                                Console.WriteLine($&quot;Subnetmask: {subNetMask}&quot;);
                            }
                        }
                    }
                }
            }

            Console.ReadLine();
        }
    }
}&lt;/code&gt;&lt;/pre&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;662&quot; data-origin-height=&quot;349&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Xt8Ty/btrHrOcWTWQ/vHuFk5cMa0F7CkVoj470Sk/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Xt8Ty/btrHrOcWTWQ/vHuFk5cMa0F7CkVoj470Sk/img.webp&quot; data-alt=&quot;네트워크 어댑터 기본 정보를 출력한 결과&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Xt8Ty/btrHrOcWTWQ/vHuFk5cMa0F7CkVoj470Sk/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FXt8Ty%2FbtrHrOcWTWQ%2FvHuFk5cMa0F7CkVoj470Sk%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; alt=&quot;네트워크-어댑터-기본-정보를-출력한-결과&quot; loading=&quot;lazy&quot; width=&quot;662&quot; height=&quot;349&quot; data-origin-width=&quot;662&quot; data-origin-height=&quot;349&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;/p&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/RrYcQ/btrHqDoK3h0/bNwan5BTHV2QlkZLkJ4CkK/ExamNetwork_1.zip?attach=1&amp;amp;knm=tfile.zip&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;ExamNetwork_1.zip&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;size&quot;&gt;0.00MB&lt;/div&gt;
&lt;/div&gt;
  &lt;/a&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;center&gt;
&lt;script src=&quot;https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js&quot;&gt;&lt;/script&gt;
&lt;ins class=&quot;adsbygoogle&quot; style=&quot;display: block;&quot; data-ad-client=&quot;ca-pub-3156423405867571&quot; data-ad-slot=&quot;4203200518&quot; data-ad-format=&quot;link&quot; data-full-width-responsive=&quot;false&quot; data-ad-language=&quot;ko&quot;&gt;&lt;/ins&gt;
&lt;script&gt;
(adsbygoogle = window.adsbygoogle || []).push({});&lt;/script&gt;
&lt;/center&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. 네트워크의 IP 주소와 서브넷 마스크 설정하는 방법&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 방법으로 IP주소를 설정할 수 있으면 좋겠지만 설정 기능을 지원하지 않습니다. 그래서 IP 주소를 설정하기 위해서는 다른 방법을 사용해야 합니다. 바로 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;WMI 클래스&lt;/span&gt;&lt;/code&gt;를 사용하는 것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;WMI&lt;/span&gt;&lt;/code&gt;는 &lt;b&gt;Windows Management Instrumentation&lt;/b&gt;으로, &lt;b&gt;윈도우 운영체제의 시스템 자원을 관리할 수 있는 집합&lt;/b&gt;입니다. 네트워크 어댑터의 IP 주소와 서브넷 마스크를 설정하기 위해, WMI 클래스인 &lt;code&gt;&lt;span class=&quot;token function-name&quot;&gt;Win32_NetworkAdapterConfiguration&lt;/span&gt;&lt;/code&gt;를 사용하는 것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 클래스를 사용하기 위해서는 &lt;code&gt;&lt;span class=&quot;token function-name&quot;&gt;System.Management&lt;/span&gt;&lt;/code&gt; 어셈블리를 추가해야 합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;748&quot; data-origin-height=&quot;519&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/yt9lJ/btrHsEnDw8d/rs2zIcsxyNmuKIvU9Fn1TK/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/yt9lJ/btrHsEnDw8d/rs2zIcsxyNmuKIvU9Fn1TK/img.webp&quot; data-alt=&quot;프로젝트에 어셈블리 추가하기&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/yt9lJ/btrHsEnDw8d/rs2zIcsxyNmuKIvU9Fn1TK/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fyt9lJ%2FbtrHsEnDw8d%2Frs2zIcsxyNmuKIvU9Fn1TK%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; alt=&quot;프로젝트에-어셈블리-추가하기&quot; loading=&quot;lazy&quot; width=&quot;748&quot; height=&quot;519&quot; data-origin-width=&quot;748&quot; data-origin-height=&quot;519&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;code&gt;&lt;span class=&quot;token important&quot;&gt;관리자 권한&lt;/span&gt;&lt;/code&gt;으로 실행해야 설정이 가능합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1657981010491&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Management; //Managemnet 네임스페이스 추가

namespace ExamNetwork
{
    class Program
    {
        static void Main(string[] args)
        {
            //Win32_NetworkAdapterConfiguration class 얻기
            ManagementClass management = new ManagementClass(&quot;Win32_NetworkAdapterConfiguration&quot;);
            ManagementObjectCollection networks = management.GetInstances();

            foreach (ManagementObject network in networks)
            {
                //네트워크 어댑터의 이름과 설명 얻기
                var description = network[&quot;Description&quot;];
                var caption = network[&quot;Caption&quot;];
                
                //EnableStatic Method 얻기
                var objStatic = network.GetMethodParameters(&quot;EnableStatic&quot;);
                //새로 지정할 IP 주소와 서브넷 마스크 지정하기
                objStatic[&quot;IPAddress&quot;] = new string[] { &quot;192.168.10.1&quot; };
                objStatic[&quot;SubnetMask&quot;] = new string[] { &quot;255.255.255.0&quot; };
                //EnableStatic Method에 파라미터를 넘겨 결과 반환 받기
                var result = (uint)network.InvokeMethod(&quot;EnableStatic&quot;, objStatic, null)[&quot;returnValue&quot;];
                if (result != 0)
                    Console.WriteLine(&quot;IP 설정 실패.&quot;);
            }

            Console.ReadLine();
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;설정이 필요한 네트워크 어댑터 이름을 확인한 후 IP 주소와 서브넷 마스크를 설정합니다. 그리고 그 결과를 아래와 같이 확인할 수 있습니다.&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;478&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/MaehF/btrHsDIYXEl/gl7Bo58ipoy0oVKkADFl3k/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/MaehF/btrHsDIYXEl/gl7Bo58ipoy0oVKkADFl3k/img.webp&quot; data-alt=&quot;네트워크 설정 결과&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/MaehF/btrHsDIYXEl/gl7Bo58ipoy0oVKkADFl3k/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FMaehF%2FbtrHsDIYXEl%2Fgl7Bo58ipoy0oVKkADFl3k%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; alt=&quot;네트워크-설정-결과&quot; loading=&quot;lazy&quot; width=&quot;431&quot; height=&quot;478&quot; data-origin-width=&quot;431&quot; data-origin-height=&quot;478&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;/p&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/RUc0X/btrHqoy26Ab/Y63GOCjj5QUgCCywzElnAk/ExamNetwork_2.zip?attach=1&amp;amp;knm=tfile.zip&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;ExamNetwork_2.zip&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;size&quot;&gt;0.00MB&lt;/div&gt;
&lt;/div&gt;
  &lt;/a&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;&lt;a href=&quot;https://docs.microsoft.com/ko-kr/windows/win32/cimwin32prov/win32-networkadapterconfiguration?redirectedfrom=MSDN&quot;&gt;https://docs.microsoft.com/ko-kr/windows/win32/cimwin32prov/win32-networkadapterconfiguration?redirectedfrom=MSDN&lt;/a&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1657983746378&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;Win32_NetworkAdapterConfiguration 클래스 - Win32 apps&quot; data-og-description=&quot;네트워크 어댑터의 특성 및 동작을 나타냅니다. 이 클래스에는 네트워크 어댑터와 독립적인 TCP/IP 프로토콜 관리를 지원하는 추가 속성 및 메서드가 포함되어 있습니다.&quot; data-og-host=&quot;docs.microsoft.com&quot; data-og-source-url=&quot;https://docs.microsoft.com/ko-kr/windows/win32/cimwin32prov/win32-networkadapterconfiguration?redirectedfrom=MSDN&quot; data-og-url=&quot;https://docs.microsoft.com/ko-kr/windows/win32/cimwin32prov/win32-networkadapterconfiguration&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/DBlou/hyO7GXRQoQ/gfrUDTvsxLnmJQUGcIRh10/img.png?width=400&amp;amp;height=400&amp;amp;face=0_0_400_400&quot;&gt;&lt;a href=&quot;https://docs.microsoft.com/ko-kr/windows/win32/cimwin32prov/win32-networkadapterconfiguration?redirectedfrom=MSDN&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://docs.microsoft.com/ko-kr/windows/win32/cimwin32prov/win32-networkadapterconfiguration?redirectedfrom=MSDN&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/DBlou/hyO7GXRQoQ/gfrUDTvsxLnmJQUGcIRh10/img.png?width=400&amp;amp;height=400&amp;amp;face=0_0_400_400');&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;Win32_NetworkAdapterConfiguration 클래스 - Win32 apps&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;네트워크 어댑터의 특성 및 동작을 나타냅니다. 이 클래스에는 네트워크 어댑터와 독립적인 TCP/IP 프로토콜 관리를 지원하는 추가 속성 및 메서드가 포함되어 있습니다.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;docs.microsoft.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;center&gt;
&lt;script src=&quot;https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js&quot;&gt;&lt;/script&gt;
&lt;ins class=&quot;adsbygoogle&quot; style=&quot;display: block;&quot; data-ad-client=&quot;ca-pub-3156423405867571&quot; data-ad-slot=&quot;4203200518&quot; data-ad-format=&quot;link&quot; data-full-width-responsive=&quot;false&quot; data-ad-language=&quot;ko&quot;&gt;&lt;/ins&gt;
&lt;script&gt;
(adsbygoogle = window.adsbygoogle || []).push({});&lt;/script&gt;
&lt;/center&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. 네트워크 어댑터 고급 설정 변경하기&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;430&quot; data-origin-height=&quot;479&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/4h570/btrHumUjnRN/O7nP0oiKm8oM31ymr18t4k/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/4h570/btrHumUjnRN/O7nP0oiKm8oM31ymr18t4k/img.webp&quot; data-alt=&quot;네트워크 어댑터 고급 설정 화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/4h570/btrHumUjnRN/O7nP0oiKm8oM31ymr18t4k/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F4h570%2FbtrHumUjnRN%2FO7nP0oiKm8oM31ymr18t4k%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; alt=&quot;네트워크-어댑터-고급-설정-화면&quot; loading=&quot;lazy&quot; width=&quot;430&quot; height=&quot;479&quot; data-origin-width=&quot;430&quot; data-origin-height=&quot;479&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;사실 이 부분을 찾기가 가장 까다로웠습니다. 점보 패킷(MTU), 수신 버퍼, 전송 버퍼 등과 같은 고급 설정을 변경하고 싶은데, 제공하는 함수를 도저히 찾을 수 없더군요. 그런데 알고 보니 아주 쉬운 방법이 있었습니다. 바로, &lt;b&gt;레지스트리를 변경&lt;/b&gt;하는 것이죠.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;레지스트리 편집기에서 아래 경로로 이동하면, 시스템에 존재하는 네트워크 목록과 설정 값을 확인할 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1657981583802&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;1. Win + R &amp;gt; regedit //레지스트리 편집기
2. 시작 &amp;gt; 레지스트리 편집기 실행

//네트워크 어댑터 목록 위치
컴퓨터\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class\{4d36e972-e325-11ce-bfc1-08002be10318}&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;800&quot; data-origin-height=&quot;536&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/odtlD/btrHvnFqPvh/fMKlpIpKJhGjwSPqa1eRa1/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/odtlD/btrHvnFqPvh/fMKlpIpKJhGjwSPqa1eRa1/img.webp&quot; data-alt=&quot;레지스트리 편집기에서 네트워크 어댑터의 고급 설정 편집&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/odtlD/btrHvnFqPvh/fMKlpIpKJhGjwSPqa1eRa1/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FodtlD%2FbtrHvnFqPvh%2FfMKlpIpKJhGjwSPqa1eRa1%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; alt=&quot;레지스트리-편집기에서-네트워크-어댑터의-고급-설정-편집&quot; loading=&quot;lazy&quot; width=&quot;800&quot; height=&quot;536&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;536&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;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style12&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;항목&lt;/td&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;이름&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;Jumbo Packet(점보 패킷)&lt;/td&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;*JumboPacket&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;Receive Buffers(수신 버퍼)&lt;/td&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;*ReceiveBuffers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;Transmit Buffers(전송 버퍼)&lt;/td&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;*TransmitBuffers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;Interrupt Moderation(인터럽트 조절)&lt;/td&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;*InterruptModeration&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;Interrupt Moderation Rate(인터럽트 조절 속도)&lt;/td&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;ITR&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, 설정이 필요한 네트워크 어댑터를 찾아서 해당 위치의 &lt;b&gt;키(Key)&lt;/b&gt; &lt;b&gt;값(Value)&lt;/b&gt;을 변경하면 되는 것입니다. 아주 간단하죠? 이 방법도 비주얼 스튜디오 또는 프로그램을 &lt;code&gt;&lt;span class=&quot;token important&quot;&gt;관리자 권한&lt;/span&gt;&lt;/code&gt;으로 실행해야 합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1657982482515&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Win32; //Win32 네임스페이스 추가

namespace ExamNetwork
{
    class Program
    {
        static void Main(string[] args)
        {
            string network_registry = @&quot;SYSTEM\CurrentControlSet\Control\Class\{4d36e972-e325-11ce-bfc1-08002be10318}&quot;;
            //레지스트리 열기
            RegistryKey regNetwork = Registry.LocalMachine.OpenSubKey(network_registry, false);

            //하위 키 이름 얻기
            var adapters = regNetwork.GetSubKeyNames();
            foreach (var adapter in adapters)
            {
                //어댑터의 레지스트리 얻기
                RegistryKey regAdapter = Registry.LocalMachine.OpenSubKey(network_registry + &quot;\\&quot; + adapter, true);

                //어댑터의 이름 얻기
                string deviceInstanceID = regAdapter.GetValue(&quot;DriverDesc&quot;).ToString();
                //점보 패킷 값 읽기
                var value = Convert.ToInt32(regAdapter.GetValue(&quot;*JumboPacket&quot;));
                //점보 패킷 값 쓰기
                regAdapter.SetValue(&quot;*JumboPacket&quot;, &quot;9014&quot;, RegistryValueKind.String);
            }

            Console.ReadLine();
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 예제 코드는 점보 패킷을 확인하고, 값을 9014로 설정하는 방법을 보여줍니다. 다른 설정 값도 위와 같이 적용하면 설정 값 변경이 가능합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;430&quot; data-origin-height=&quot;479&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bUfKIZ/btrHpoNmZE9/41Iay1jG7fiaIwVm9EGw30/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bUfKIZ/btrHpoNmZE9/41Iay1jG7fiaIwVm9EGw30/img.webp&quot; data-alt=&quot;점보 패킷이 변경된 모습&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bUfKIZ/btrHpoNmZE9/41Iay1jG7fiaIwVm9EGw30/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbUfKIZ%2FbtrHpoNmZE9%2F41Iay1jG7fiaIwVm9EGw30%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; alt=&quot;점보-패킷이-변경된-모습&quot; loading=&quot;lazy&quot; width=&quot;430&quot; height=&quot;479&quot; data-origin-width=&quot;430&quot; data-origin-height=&quot;479&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;/p&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/whpeS/btrHpxpi4JQ/3B0l9EbLQ1kKRG1L2rWUek/ExamNetwork_3.zip?attach=1&amp;amp;knm=tfile.zip&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;ExamNetwork_3.zip&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;size&quot;&gt;0.00MB&lt;/div&gt;
&lt;/div&gt;
  &lt;/a&gt;&lt;/figure&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;위에서 보여준 세 가지 방법을 조합하면 네트워크 목록을 확인하고, IP 주소와 고급 설정을 원하는 대로 변경할 수 있는 동작을 구현할 수 있습니다.&lt;/p&gt;</description>
      <category>Programming/.Net</category>
      <category>.net</category>
      <author>❤ </author>
      <guid isPermaLink="true">https://luckygg.tistory.com/369</guid>
      <comments>https://luckygg.tistory.com/369#entry369comment</comments>
      <pubDate>Sat, 16 Jul 2022 23:51:52 +0900</pubDate>
    </item>
    <item>
      <title>[디버깅] Visual Studio C# 원격 디버깅(Remote Debugging) 사용 방법</title>
      <link>https://luckygg.tistory.com/368</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;C#에서 원격 디버깅(Remote Debugging)하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원격 디버깅 주제는 이전에 MFC 환경에서 한 번 다뤘었습니다. 간단하게 다시 정의하면, 원격 디버깅은 개발 환경이 없는 PC에서 프로그램을 실행하고, 로컬 PC에서 디버깅을 하는 것을 의미합니다. 자세한 내용은 아래 링크를 참고하세요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://luckygg.tistory.com/243&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;[디버깅] Visual Studio 2015 MFC 원격 디버깅(Remote Debugging)하기!&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1653700419953&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;[디버깅] Visual Studio 2015 MFC 원격 디버깅(Remote Debugging)하기!&quot; data-og-description=&quot;원격 디버깅(Remote Debugging)? 일반적으로 디버깅이라 함은 컴파일러에서 디버그 모드로 동작하고, 코드를 한 줄 한 줄 실행하며 문제를 찾아가는 과정을 의미합니다. 그런데 원격 디버깅이란 무엇&quot; data-og-host=&quot;luckygg.tistory.com&quot; data-og-source-url=&quot;https://luckygg.tistory.com/243&quot; data-og-url=&quot;https://luckygg.tistory.com/243&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bTXjBb/hyOypJ8b4f/CVBSFglSmwjKHKTlBKeJDk/img.jpg?width=800&amp;amp;height=510&amp;amp;face=596_318_652_379,https://scrap.kakaocdn.net/dn/cOMPb4/hyOypQUw4L/ODOco9aG0x1MKPU1hCJmKk/img.jpg?width=800&amp;amp;height=510&amp;amp;face=596_318_652_379,https://scrap.kakaocdn.net/dn/bGoYV0/hyOyyUBrXQ/WhcKkkpdeVSrxH8tH27T40/img.png?width=1000&amp;amp;height=559&amp;amp;face=0_0_1000_559&quot;&gt;&lt;a href=&quot;https://luckygg.tistory.com/243&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://luckygg.tistory.com/243&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bTXjBb/hyOypJ8b4f/CVBSFglSmwjKHKTlBKeJDk/img.jpg?width=800&amp;amp;height=510&amp;amp;face=596_318_652_379,https://scrap.kakaocdn.net/dn/cOMPb4/hyOypQUw4L/ODOco9aG0x1MKPU1hCJmKk/img.jpg?width=800&amp;amp;height=510&amp;amp;face=596_318_652_379,https://scrap.kakaocdn.net/dn/bGoYV0/hyOyyUBrXQ/WhcKkkpdeVSrxH8tH27T40/img.png?width=1000&amp;amp;height=559&amp;amp;face=0_0_1000_559');&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;[디버깅] Visual Studio 2015 MFC 원격 디버깅(Remote Debugging)하기!&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;원격 디버깅(Remote Debugging)? 일반적으로 디버깅이라 함은 컴파일러에서 디버그 모드로 동작하고, 코드를 한 줄 한 줄 실행하며 문제를 찾아가는 과정을 의미합니다. 그런데 원격 디버깅이란 무엇&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;luckygg.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;원격 디버깅을 위한 네트워크 구성&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원격 디버깅을 위해 로컬 PC와 원격 PC는 같은 네트워크에 존재해야 합니다. 아래 그림과 같이 로컬 PC와 원격 PC를 직접 랜 케이블로 연결하여 네트워크를 구성하면 원격 디버깅이 가능합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;그림1.png&quot; data-origin-width=&quot;650&quot; data-origin-height=&quot;290&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/UIWKC/btrDXonyFei/eqs6OYQI2JqWrUkKsOLztk/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/UIWKC/btrDXonyFei/eqs6OYQI2JqWrUkKsOLztk/img.webp&quot; data-alt=&quot;직접-연결한-네트워크-구성&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/UIWKC/btrDXonyFei/eqs6OYQI2JqWrUkKsOLztk/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FUIWKC%2FbtrDXonyFei%2Feqs6OYQI2JqWrUkKsOLztk%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; alt=&quot;직접-연결한-네트워크-구성&quot; loading=&quot;lazy&quot; width=&quot;650&quot; height=&quot;290&quot; data-filename=&quot;그림1.png&quot; data-origin-width=&quot;650&quot; data-origin-height=&quot;290&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;또는 허브에 연결되어 있는 PC끼리도 원격 디버깅이 가능합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;2.png&quot; data-origin-width=&quot;649&quot; data-origin-height=&quot;290&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dmNa6w/btrDV083v9y/GCEw7XiqkOia0YGGyyRLh1/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dmNa6w/btrDV083v9y/GCEw7XiqkOia0YGGyyRLh1/img.webp&quot; data-alt=&quot;동일-허브에-연결되어-있는-네트워크-구성&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dmNa6w/btrDV083v9y/GCEw7XiqkOia0YGGyyRLh1/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdmNa6w%2FbtrDV083v9y%2FGCEw7XiqkOia0YGGyyRLh1%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; alt=&quot;동일-허브에-연결되어-있는-네트워크-구성&quot; loading=&quot;lazy&quot; width=&quot;649&quot; height=&quot;290&quot; data-filename=&quot;2.png&quot; data-origin-width=&quot;649&quot; data-origin-height=&quot;290&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;동일-허브에-연결되어-있는-네트워크-구성&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;원격 PC 준비 과정&lt;/h2&gt;
&lt;center&gt;
&lt;script src=&quot;https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js&quot;&gt;&lt;/script&gt;
&lt;ins class=&quot;adsbygoogle&quot; style=&quot;display: block;&quot; data-ad-client=&quot;ca-pub-3156423405867571&quot; data-ad-slot=&quot;4203200518&quot; data-ad-format=&quot;link&quot; data-full-width-responsive=&quot;false&quot; data-ad-language=&quot;ko&quot;&gt;&lt;/ins&gt;
&lt;script&gt;
(adsbygoogle = window.adsbygoogle || []).push({});&lt;/script&gt;
&lt;/center&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. 원격 디버거 설치&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원격 디버깅을 위해 원격 PC에서 &lt;b&gt;원격 디버거&lt;/b&gt;를 먼저 실행해야 합니다. 개발환경이 있는 PC라면 버전에 따라 경로가 다소 다르지만, 보통 아래와 같은 경로에 원격 디버거 프로그램이 존재합니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE\Remote Debugger\x64\msvsmon.exe&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약, 개발환경이 없는 PC라면 원격 디버거를 따로 다운로드해야 합니다. Visual Studio 버전에 따른 원격 디버거는 아래 링크에서 다운로드 가능합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://docs.microsoft.com/ko-kr/visualstudio/debugger/remote-debugging-csharp?view=vs-2022&quot;&gt;https://docs.microsoft.com/ko-kr/visualstudio/debugger/remote-debugging-csharp?view=vs-2022&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1653701495243&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# 또는 VB 프로젝트 - Visual Studio (Windows)&quot; data-og-description=&quot;다음 단계별 지침에 따라 원격 컴퓨터에서 Visual Studio C# 또는 Visual Basic 애플리케이션을 디버그하는 방법을 알아봅니다.&quot; data-og-host=&quot;docs.microsoft.com&quot; data-og-source-url=&quot;https://docs.microsoft.com/ko-kr/visualstudio/debugger/remote-debugging-csharp?view=vs-2022&quot; data-og-url=&quot;https://docs.microsoft.com/ko-kr/visualstudio/debugger/remote-debugging-csharp&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bal9MB/hyOyzlIwjN/OM2avLvEEdjPqjXB0oU6Y1/img.png?width=400&amp;amp;height=400&amp;amp;face=0_0_400_400,https://scrap.kakaocdn.net/dn/cqnRap/hyOyq98iON/IKAgbN8YHJJZDIPGPdQsN1/img.png?width=786&amp;amp;height=509&amp;amp;face=0_0_786_509,https://scrap.kakaocdn.net/dn/ZlW3A/hyOyrur0r4/q3IMBrrlZb6sWKw4Pkptkk/img.png?width=770&amp;amp;height=454&amp;amp;face=0_0_770_454&quot;&gt;&lt;a href=&quot;https://docs.microsoft.com/ko-kr/visualstudio/debugger/remote-debugging-csharp?view=vs-2022&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://docs.microsoft.com/ko-kr/visualstudio/debugger/remote-debugging-csharp?view=vs-2022&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bal9MB/hyOyzlIwjN/OM2avLvEEdjPqjXB0oU6Y1/img.png?width=400&amp;amp;height=400&amp;amp;face=0_0_400_400,https://scrap.kakaocdn.net/dn/cqnRap/hyOyq98iON/IKAgbN8YHJJZDIPGPdQsN1/img.png?width=786&amp;amp;height=509&amp;amp;face=0_0_786_509,https://scrap.kakaocdn.net/dn/ZlW3A/hyOyrur0r4/q3IMBrrlZb6sWKw4Pkptkk/img.png?width=770&amp;amp;height=454&amp;amp;face=0_0_770_454');&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# 또는 VB 프로젝트 - Visual Studio (Windows)&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;다음 단계별 지침에 따라 원격 컴퓨터에서 Visual Studio C# 또는 Visual Basic 애플리케이션을 디버그하는 방법을 알아봅니다.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;docs.microsoft.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&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;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;739&quot; data-origin-height=&quot;585&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/sQBgu/btrDWh3LIPM/aRDbv7bIKCALT9ICzmFKs0/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/sQBgu/btrDWh3LIPM/aRDbv7bIKCALT9ICzmFKs0/img.webp&quot; data-alt=&quot;원격 디버거를 관리자 권한으로 실행하기&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/sQBgu/btrDWh3LIPM/aRDbv7bIKCALT9ICzmFKs0/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FsQBgu%2FbtrDWh3LIPM%2FaRDbv7bIKCALT9ICzmFKs0%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; alt=&quot;원격-디버거를-관리자-권한으로-실행하기&quot; loading=&quot;lazy&quot; width=&quot;739&quot; height=&quot;585&quot; data-origin-width=&quot;739&quot; data-origin-height=&quot;585&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;PC 이름&lt;/b&gt;과 &lt;b&gt;포트 번호&lt;/b&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;635&quot; data-origin-height=&quot;210&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/DASkN/btrDUVgA7o3/3QOxaRPP0kxcql2Jyh6ou0/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/DASkN/btrDUVgA7o3/3QOxaRPP0kxcql2Jyh6ou0/img.webp&quot; data-alt=&quot;PC이름과포트 번호가 표시된 모습&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/DASkN/btrDUVgA7o3/3QOxaRPP0kxcql2Jyh6ou0/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FDASkN%2FbtrDUVgA7o3%2F3QOxaRPP0kxcql2Jyh6ou0%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; alt=&quot;PC이름과포트-번호가-표시된-모습&quot; loading=&quot;lazy&quot; width=&quot;635&quot; height=&quot;210&quot; data-origin-width=&quot;635&quot; data-origin-height=&quot;210&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;PC이름과포트 번호가 표시된 모습&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;로컬 PC 준비 과정&lt;/h2&gt;
&lt;center&gt;
&lt;script src=&quot;https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js&quot;&gt;&lt;/script&gt;
&lt;ins class=&quot;adsbygoogle&quot; style=&quot;display: block;&quot; data-ad-client=&quot;ca-pub-3156423405867571&quot; data-ad-slot=&quot;4203200518&quot; data-ad-format=&quot;link&quot; data-full-width-responsive=&quot;false&quot; data-ad-language=&quot;ko&quot;&gt;&lt;/ins&gt;
&lt;script&gt;
(adsbygoogle = window.adsbygoogle || []).push({});&lt;/script&gt;
&lt;/center&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;C# 프로젝트를 준비합니다. 예시로, 간단하게 문자열을 입력받는 Console 프로그램을 준비해 봤습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1654260887673&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ExamRemoteDebugger
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine(&quot;Remote Debugger Sample Program&quot;);
            string input = Console.ReadLine();   
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로젝트의 &lt;b&gt;속성&lt;/b&gt; 메뉴를 선택합니다. 그리고 &lt;b&gt;디버그&lt;/b&gt; 탭에서 &lt;b&gt;원격 컴퓨터 사용&lt;/b&gt;을 체크합니다. 그리고 &lt;span&gt;원격 PC에서 원격 디버거를 실행했을 때 표시됐던&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;b&gt;PC 이름&lt;/b&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;799&quot; data-origin-height=&quot;456&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/GoyBa/btrDWiVS1xb/kiWBHus3UIXbNtsboP6aK0/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/GoyBa/btrDWiVS1xb/kiWBHus3UIXbNtsboP6aK0/img.webp&quot; data-alt=&quot;원격 컴퓨터 사용 체크 및 컴퓨터 정보 입력&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/GoyBa/btrDWiVS1xb/kiWBHus3UIXbNtsboP6aK0/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FGoyBa%2FbtrDWiVS1xb%2FkiWBHus3UIXbNtsboP6aK0%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; alt=&quot;원격-컴퓨터-사용-체크-및-컴퓨터-정보-입력&quot; loading=&quot;lazy&quot; width=&quot;799&quot; height=&quot;456&quot; data-origin-width=&quot;799&quot; data-origin-height=&quot;456&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;이제 프로젝트를 빌드합니다. 프로젝트를 빌드하면 아래 Debug 경로에 파일이 생성됐을 건데요. 이 파일을 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;원격 PC에 동일한 경로로 복사&lt;/b&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;618&quot; data-origin-height=&quot;228&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/OUji8/btrDWjmXuV4/UwHDVX4Rk8D0f0F7MPPYM1/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/OUji8/btrDWjmXuV4/UwHDVX4Rk8D0f0F7MPPYM1/img.webp&quot; data-alt=&quot;빌드 후 생성된 Debug 파일&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/OUji8/btrDWjmXuV4/UwHDVX4Rk8D0f0F7MPPYM1/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FOUji8%2FbtrDWjmXuV4%2FUwHDVX4Rk8D0f0F7MPPYM1%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; alt=&quot;빌드-후-생성된-Debug-파일&quot; loading=&quot;lazy&quot; width=&quot;618&quot; height=&quot;228&quot; data-origin-width=&quot;618&quot; data-origin-height=&quot;228&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;빌드 후 생성된 Debug 파일&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;div class=&quot;rgyInfo&quot;&gt;
&lt;div class=&quot;rgyInfo-circle&quot;&gt;
&lt;div class=&quot;topDiv&quot;&gt;주의&lt;/div&gt;
&lt;div class=&quot;bottomDiv&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;bottomDiv2&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;rgyInfo-text&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;코드를 수정할 때마다 이 과정을 반복&lt;/b&gt;해야 합니다. 로컬 PC와 원격 PC의 정보가 정확히 일치해야 원격 디버깅이 가능하기 때문입니다.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 로컬 PC에서 디버깅을 시작하면, 원격 PC의 원격 디버거에서 다음과 같이 메시지가 표시됩니다.&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;215&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dfToEM/btrDUUvbO9G/lmCn3om7FeLFE7GcMANka1/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dfToEM/btrDUUvbO9G/lmCn3om7FeLFE7GcMANka1/img.webp&quot; data-alt=&quot;원격 디버거에 접속된 로컬 PC의 정보&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dfToEM/btrDUUvbO9G/lmCn3om7FeLFE7GcMANka1/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdfToEM%2FbtrDUUvbO9G%2FlmCn3om7FeLFE7GcMANka1%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; alt=&quot;원격-디버거에-접속된-로컬-PC의-정보&quot; loading=&quot;lazy&quot; width=&quot;635&quot; height=&quot;215&quot; data-origin-width=&quot;635&quot; data-origin-height=&quot;215&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;원격 디버거에 접속된 로컬 PC의 정보&lt;/figcaption&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;464&quot; data-origin-height=&quot;404&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b8ob7o/btrDUIV58pw/ioVB0gAxwU64VGmmasE04k/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b8ob7o/btrDUIV58pw/ioVB0gAxwU64VGmmasE04k/img.webp&quot; data-alt=&quot;원격 PC의 계정 정보 입력&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b8ob7o/btrDUIV58pw/ioVB0gAxwU64VGmmasE04k/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb8ob7o%2FbtrDUIV58pw%2FioVB0gAxwU64VGmmasE04k%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; alt=&quot;원격-PC의-계정-정보-입력&quot; loading=&quot;lazy&quot; width=&quot;464&quot; height=&quot;404&quot; data-origin-width=&quot;464&quot; data-origin-height=&quot;404&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;원격 PC의 계정 정보 입력&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 로컬 PC에서 원격 PC의 제어로 디버깅이 가능해집니다!&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;769&quot; data-origin-height=&quot;489&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cHa2Jk/btrDU3MaWMG/cgaa9a9YeP9kV95bnixSt1/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cHa2Jk/btrDU3MaWMG/cgaa9a9YeP9kV95bnixSt1/img.webp&quot; data-alt=&quot;원격 PC 원격 디버깅 중인 모습&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cHa2Jk/btrDU3MaWMG/cgaa9a9YeP9kV95bnixSt1/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcHa2Jk%2FbtrDU3MaWMG%2Fcgaa9a9YeP9kV95bnixSt1%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; alt=&quot;원격-PC-원격-디버깅-중인-모습&quot; loading=&quot;lazy&quot; width=&quot;769&quot; height=&quot;489&quot; data-origin-width=&quot;769&quot; data-origin-height=&quot;489&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;원격 PC 원격 디버깅 중인 모습&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>Programming/Debugging</category>
      <category>디버깅</category>
      <author>❤ </author>
      <guid isPermaLink="true">https://luckygg.tistory.com/368</guid>
      <comments>https://luckygg.tistory.com/368#entry368comment</comments>
      <pubDate>Fri, 3 Jun 2022 22:05:02 +0900</pubDate>
    </item>
    <item>
      <title>[ASP.NET] 시놀로지 도커(Docker)에서 셀레니움(Selenium) 서비스 만드는 방법</title>
      <link>https://luckygg.tistory.com/367</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;도커(Docker) 셀레니움(Selenium) 서비스&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재 근무하고 있는 회사에는 전자 결재를 위한 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;이카운트 ERP&lt;/b&gt;&lt;/span&gt;를 사용하고 있습니다. 이 서비스는 실시간으로 자료 입력과 조회가 가능하고, 전자 문서 결재 진행 상황을 확인할 수 있죠. 게다가 모바일 앱과 웹 기반 서비스를 제공하고 있어 인터넷만 된다면 언제 어디서든 사용이 가능합니다. 또한, 개발자를 위한 &lt;b&gt;REST API&lt;/b&gt;도 제공하고 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데 한 가지 아주 아쉬운 부분이 있습니다. 업무 특성상 특정 결과를 실시간으로 알람 받고 싶은데, 하필 이 부분만 API로 제공하지 않더군요. 고객센터에도 문의해봤지만 API가 없는 것이 맞고, 아직 개발 계획도 없다고 하더군요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 방법이 아주 없지는 않았습니다. 제가 생각한 구상은 &lt;b&gt;시놀로지 서버의 도커에서 ERP 웹 페이지의 특정 항목을 셀레니움으로 확인&lt;/b&gt;하는 것인데요. 당연히 될거라 생각했고, 결국 원하는 결과를 얻을 수 있었습니다. 이번 본문에서는 도커에서 셀레니움 서비스를 동작하기 위한 준비 과정과 동작 결과를 설명하겠습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;작업 구상&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;셀레니움으로 특정 웹사이트에 접속한 후 특정 데이터를 취득합니다. 그리고 조건이 성립하면 시놀로지 챗(Chat)의 챗봇으로 메시지를 전송하여 알림을 받도록 합니다. 이 동작을 도커 서비스로 제작합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;구상도.png&quot; data-origin-width=&quot;629&quot; data-origin-height=&quot;434&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b0AH0O/btrDkW0orNU/1RB05aeo9LC8M0EUcOAHck/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b0AH0O/btrDkW0orNU/1RB05aeo9LC8M0EUcOAHck/img.webp&quot; data-alt=&quot;서비스-구상도&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b0AH0O/btrDkW0orNU/1RB05aeo9LC8M0EUcOAHck/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb0AH0O%2FbtrDkW0orNU%2F1RB05aeo9LC8M0EUcOAHck%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; alt=&quot;서비스-구상도&quot; loading=&quot;lazy&quot; width=&quot;629&quot; height=&quot;434&quot; data-filename=&quot;구상도.png&quot; data-origin-width=&quot;629&quot; data-origin-height=&quot;434&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;서비스-구상도&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;준비 단계&lt;/h2&gt;
&lt;center&gt;
&lt;script src=&quot;https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js&quot;&gt;&lt;/script&gt;
&lt;ins class=&quot;adsbygoogle&quot; style=&quot;display: block;&quot; data-ad-client=&quot;ca-pub-3156423405867571&quot; data-ad-slot=&quot;4203200518&quot; data-ad-format=&quot;link&quot; data-full-width-responsive=&quot;false&quot; data-ad-language=&quot;ko&quot;&gt;&lt;/ins&gt;
&lt;script&gt;
(adsbygoogle = window.adsbygoogle || []).push({});&lt;/script&gt;
&lt;/center&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. 셀레니움(Selenium) 익히기&lt;/h3&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://luckygg.tistory.com/248&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;[셀레니움/Selenium, C#] C#에서 셀레니움을 사용하는 방법 총정리&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1653574161253&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;[셀레니움/Selenium, C#] C#에서 셀레니움을 사용하는 방법 총정리&quot; data-og-description=&quot;셀레니움(Selenium)이란? 셀레니움은 웹 브라우저 자동화를 위한 라이브러리입니다. 눈에 보이는 모든 콘텐츠에 입력, 클릭, 가져오기 등이 가능합니다. 간단한 웹 사이트 접속부터 로그인, 검색, &quot; data-og-host=&quot;luckygg.tistory.com&quot; data-og-source-url=&quot;https://luckygg.tistory.com/248&quot; data-og-url=&quot;https://luckygg.tistory.com/248&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/N3Hve/hyOywVE52o/RKLNzK2N8oA5IkPa5IqUok/img.jpg?width=800&amp;amp;height=600&amp;amp;face=0_0_800_600,https://scrap.kakaocdn.net/dn/nJ2LI/hyOxm8cAvy/K2KFJMjn5CXB9z3KVFTzH1/img.jpg?width=800&amp;amp;height=600&amp;amp;face=0_0_800_600&quot;&gt;&lt;a href=&quot;https://luckygg.tistory.com/248&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://luckygg.tistory.com/248&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/N3Hve/hyOywVE52o/RKLNzK2N8oA5IkPa5IqUok/img.jpg?width=800&amp;amp;height=600&amp;amp;face=0_0_800_600,https://scrap.kakaocdn.net/dn/nJ2LI/hyOxm8cAvy/K2KFJMjn5CXB9z3KVFTzH1/img.jpg?width=800&amp;amp;height=600&amp;amp;face=0_0_800_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;[셀레니움/Selenium, C#] C#에서 셀레니움을 사용하는 방법 총정리&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;셀레니움(Selenium)이란? 셀레니움은 웹 브라우저 자동화를 위한 라이브러리입니다. 눈에 보이는 모든 콘텐츠에 입력, 클릭, 가져오기 등이 가능합니다. 간단한 웹 사이트 접속부터 로그인, 검색,&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;luckygg.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. 챗봇 연동하기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시놀로지는 &lt;b&gt;챗(Chat)&lt;/b&gt;이라는 메신저를 제공합니다. 셀레니움으로 얻은 데이터를 챗의 챗봇과 연동하여 알림을 받을 겁니다. 아래 링크를 참고하여 챗봇을 어떻게 연동하는지 참고하세요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://luckygg.tistory.com/359&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;[챗봇/.NET] C#에서 시놀로지 Chat에 챗봇 메시지 보내기(예제 포함)&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1653574312853&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;[챗봇/.NET] C#에서 시놀로지 Chat에 챗봇 메시지 보내기(예제 포함)&quot; data-og-description=&quot;시놀로지 Chat 메신저 시놀로지에는 Chat이라는 메신저를 제공하고 있습니다. 이는 패키지 센터에서 설치가 가능한데요. 주요 특징은 다음과 같습니다. 무료로 사용 가능 메시지 고정(공지 사항), &quot; data-og-host=&quot;luckygg.tistory.com&quot; data-og-source-url=&quot;https://luckygg.tistory.com/359&quot; data-og-url=&quot;https://luckygg.tistory.com/359&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/G0ZHB/hyOxv49UQY/EcBwi8K4TtoQKCmpGskUYK/img.jpg?width=780&amp;amp;height=265&amp;amp;face=0_0_780_265,https://scrap.kakaocdn.net/dn/c0ix3W/hyOynEq2EY/K6WPRPsEtBGeKdwH6niK0K/img.jpg?width=780&amp;amp;height=265&amp;amp;face=0_0_780_265&quot;&gt;&lt;a href=&quot;https://luckygg.tistory.com/359&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://luckygg.tistory.com/359&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/G0ZHB/hyOxv49UQY/EcBwi8K4TtoQKCmpGskUYK/img.jpg?width=780&amp;amp;height=265&amp;amp;face=0_0_780_265,https://scrap.kakaocdn.net/dn/c0ix3W/hyOynEq2EY/K6WPRPsEtBGeKdwH6niK0K/img.jpg?width=780&amp;amp;height=265&amp;amp;face=0_0_780_265');&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;[챗봇/.NET] C#에서 시놀로지 Chat에 챗봇 메시지 보내기(예제 포함)&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;시놀로지 Chat 메신저 시놀로지에는 Chat이라는 메신저를 제공하고 있습니다. 이는 패키지 센터에서 설치가 가능한데요. 주요 특징은 다음과 같습니다. 무료로 사용 가능 메시지 고정(공지 사항),&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;luckygg.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. 리눅스(Linux) 작업자 서비스 만들기&lt;/h3&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://luckygg.tistory.com/362&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;[ASP.NET] C# 시놀로지 Linux Docker 용 작업자 서비스 만드는 방법&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1653574379122&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;[ASP.NET] C# 시놀로지 Linux Docker 용 작업자 서비스 만드는 방법&quot; data-og-description=&quot;Linux Docker 작업자 서비스 지난 포스팅에서 ASP.NET Core Worker Service를 빌드하여 Windows 용 Docker에서 서비스를 동작하는 방법을 소개했었습니다. 이번에는 Linux Docker를 위한 작업자 서비스를 제작하려.&quot; data-og-host=&quot;luckygg.tistory.com&quot; data-og-source-url=&quot;https://luckygg.tistory.com/362&quot; data-og-url=&quot;https://luckygg.tistory.com/362&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/b0na6p/hyOxlnVfOd/yw6RtRNipBi564TzEiGZ2k/img.png?width=800&amp;amp;height=434&amp;amp;face=0_0_800_434,https://scrap.kakaocdn.net/dn/bczjuH/hyOxyAOnLv/cXZIXhLlCU7BTuslXAVKs0/img.png?width=800&amp;amp;height=434&amp;amp;face=0_0_800_434,https://scrap.kakaocdn.net/dn/qQKvk/hyOyqunLo7/coiJ57NL47fglCCG972dw0/img.png?width=907&amp;amp;height=698&amp;amp;face=0_0_907_698&quot;&gt;&lt;a href=&quot;https://luckygg.tistory.com/362&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://luckygg.tistory.com/362&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/b0na6p/hyOxlnVfOd/yw6RtRNipBi564TzEiGZ2k/img.png?width=800&amp;amp;height=434&amp;amp;face=0_0_800_434,https://scrap.kakaocdn.net/dn/bczjuH/hyOxyAOnLv/cXZIXhLlCU7BTuslXAVKs0/img.png?width=800&amp;amp;height=434&amp;amp;face=0_0_800_434,https://scrap.kakaocdn.net/dn/qQKvk/hyOyqunLo7/coiJ57NL47fglCCG972dw0/img.png?width=907&amp;amp;height=698&amp;amp;face=0_0_907_698');&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;[ASP.NET] C# 시놀로지 Linux Docker 용 작업자 서비스 만드는 방법&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Linux Docker 작업자 서비스 지난 포스팅에서 ASP.NET Core Worker Service를 빌드하여 Windows 용 Docker에서 서비스를 동작하는 방법을 소개했었습니다. 이번에는 Linux Docker를 위한 작업자 서비스를 제작하려.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;luckygg.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4. 시놀로지 작업 스케줄러 적용하기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이상하게도 Linux Docker에서 셀레니움을 사용하면 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;메모리 누수(Memeory leak)&lt;/b&gt;&lt;/span&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;a href=&quot;https://luckygg.tistory.com/366&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;[Synology NAS] 작업 스케줄러로 작업 예약하기(사용자 정의 스크립트)&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1653574640877&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;[Synology NAS] 작업 스케줄러로 작업 예약하기(사용자 정의 스크립트)&quot; data-og-description=&quot;작업 스케줄러란? 시놀로지 나스의 제어판에는 작업 스케줄러 메뉴가 있습니다. 이 작업 스케줄러를 사용하여 특정 시간에 특정 서비스나 스크립트를 예약하고 실행할 수 있습니다. 예를 들어, &quot; data-og-host=&quot;luckygg.tistory.com&quot; data-og-source-url=&quot;https://luckygg.tistory.com/366&quot; data-og-url=&quot;https://luckygg.tistory.com/366&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/tQEoE/hyOxlIflDi/57eRnnd7sn4JpgA8eMEpZ0/img.jpg?width=800&amp;amp;height=509&amp;amp;face=0_0_800_509,https://scrap.kakaocdn.net/dn/I7Iiq/hyOxi5P0yj/qJ87zDDTQ9NvS4uVXpzk2k/img.jpg?width=800&amp;amp;height=509&amp;amp;face=0_0_800_509&quot;&gt;&lt;a href=&quot;https://luckygg.tistory.com/366&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://luckygg.tistory.com/366&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/tQEoE/hyOxlIflDi/57eRnnd7sn4JpgA8eMEpZ0/img.jpg?width=800&amp;amp;height=509&amp;amp;face=0_0_800_509,https://scrap.kakaocdn.net/dn/I7Iiq/hyOxi5P0yj/qJ87zDDTQ9NvS4uVXpzk2k/img.jpg?width=800&amp;amp;height=509&amp;amp;face=0_0_800_509');&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;[Synology NAS] 작업 스케줄러로 작업 예약하기(사용자 정의 스크립트)&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;작업 스케줄러란? 시놀로지 나스의 제어판에는 작업 스케줄러 메뉴가 있습니다. 이 작업 스케줄러를 사용하여 특정 시간에 특정 서비스나 스크립트를 예약하고 실행할 수 있습니다. 예를 들어,&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;luckygg.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;핵심&lt;/h2&gt;
&lt;center&gt;
&lt;script src=&quot;https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js&quot;&gt;&lt;/script&gt;
&lt;ins class=&quot;adsbygoogle&quot; style=&quot;display: block;&quot; data-ad-client=&quot;ca-pub-3156423405867571&quot; data-ad-slot=&quot;4203200518&quot; data-ad-format=&quot;link&quot; data-full-width-responsive=&quot;false&quot; data-ad-language=&quot;ko&quot;&gt;&lt;/ins&gt;
&lt;script&gt;
(adsbygoogle = window.adsbygoogle || []).push({});&lt;/script&gt;
&lt;/center&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Linux 작업자 서비스를 만드는 전반적인 과정은 아래 링크를 참고합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://luckygg.tistory.com/362&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;[ASP.NET] C# 시놀로지 Linux Docker 용 작업자 서비스 만드는 방법&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1653658616981&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;[ASP.NET] C# 시놀로지 Linux Docker 용 작업자 서비스 만드는 방법&quot; data-og-description=&quot;Linux Docker 작업자 서비스 지난 포스팅에서 ASP.NET Core Worker Service를 빌드하여 Windows 용 Docker에서 서비스를 동작하는 방법을 소개했었습니다. 이번에는 Linux Docker를 위한 작업자 서비스를 제작하려.&quot; data-og-host=&quot;luckygg.tistory.com&quot; data-og-source-url=&quot;https://luckygg.tistory.com/362&quot; data-og-url=&quot;https://luckygg.tistory.com/362&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/EZMcs/hyOyvDer3B/PV5fCjFf6BANUPlZV8IBLK/img.png?width=800&amp;amp;height=434&amp;amp;face=0_0_800_434,https://scrap.kakaocdn.net/dn/dBYKtu/hyOynSJYCz/G2pwhCF2VYtnQsIdvGoKmk/img.png?width=800&amp;amp;height=434&amp;amp;face=0_0_800_434,https://scrap.kakaocdn.net/dn/cqyZSS/hyOywa4KSL/jiV3vCtgTrnp9d4fVANYbk/img.png?width=907&amp;amp;height=698&amp;amp;face=0_0_907_698&quot;&gt;&lt;a href=&quot;https://luckygg.tistory.com/362&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://luckygg.tistory.com/362&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/EZMcs/hyOyvDer3B/PV5fCjFf6BANUPlZV8IBLK/img.png?width=800&amp;amp;height=434&amp;amp;face=0_0_800_434,https://scrap.kakaocdn.net/dn/dBYKtu/hyOynSJYCz/G2pwhCF2VYtnQsIdvGoKmk/img.png?width=800&amp;amp;height=434&amp;amp;face=0_0_800_434,https://scrap.kakaocdn.net/dn/cqyZSS/hyOywa4KSL/jiV3vCtgTrnp9d4fVANYbk/img.png?width=907&amp;amp;height=698&amp;amp;face=0_0_907_698');&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;[ASP.NET] C# 시놀로지 Linux Docker 용 작업자 서비스 만드는 방법&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Linux Docker 작업자 서비스 지난 포스팅에서 ASP.NET Core Worker Service를 빌드하여 Windows 용 Docker에서 서비스를 동작하는 방법을 소개했었습니다. 이번에는 Linux Docker를 위한 작업자 서비스를 제작하려.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;luckygg.tistory.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;pre id=&quot;code_1653697358931&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;ChromeDriverService _driverService = ChromeDriverService.CreateDefaultService();
_driverService.HideCommandPromptWindow = true;

ChromeOptions _options = new ChromeOptions();
_options.AddArgument(&quot;disable-gpu&quot;);
_options.AddArgument(&quot;headless&quot;);
_options.AddArgument(&quot;no-sandbox&quot;);
_options.AddArgument(&quot;disable-dev-shm-usage&quot;);

ChromeDriver _driver = new ChromeDriver(_driverService, _options);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서비스 빌드를 위한 Dockerfile은 다음과 같이 작성합니다. 도커에서 구성 요소를 설치하고, 크롬 드라이버를 설치하는 과정을 의미합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1653697584715&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;FROM mcr.microsoft.com/dotnet/runtime:5.0 AS base

COPY . /app
WORKDIR /app
 
#포트 번호는 예시로 8888
ENV ASPNETCORE_URLS http://*:8888
EXPOSE 8888

# RUN apt-get update
RUN apt-get update &amp;amp;&amp;amp; apt-get install -y gnupg2
RUN apt install -y wget

# CHROME
RUN wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add -
RUN sh -c 'echo &quot;deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main&quot; &amp;gt;&amp;gt; /etc/apt/sources.list.d/goodle.list'
RUN apt-get update
RUN apt-get install -y google-chrome-stable

# CHROME_DRIVER
RUN apt-get install -yqq unzip
RUN apt-get install -y curl
RUN wget -O /tmp/chromedriver.zip http://chromedriver.storage.googleapis.com/`curl -sS chromedriver.storage.googleapis.com/LATEST_RELEASE`/chromedriver_linux64.zip
RUN unzip /tmp/chromedriver.zip chromedriver -d /usr/local/bin/
ENV DISPLAY=:99
 
#ExamWorkerService는 프로젝트 이름
ENTRYPOINT [&quot;dotnet&quot;, &quot;WorkerService.dll&quot;]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앞에서 언급한 것처럼, 도커 서비스에서 셀레니움을 동작하면 메모리 누수가 발생합니다. 작업자 스케줄러에 사용자 정의 스크립트를 추가하여 특정 시간 동안만 동작하고 종료되도록 설정합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1653697814760&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;docker container start [컨테이너 이름]
docker container stop [컨테이너 이름]&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;셀레니움으로 얻은 데이터 중 알림이 필요한 정보를 파싱하여 챗봇으로 메시지를 전달하면, 아래 이미지처럼 챗봇 메시지를 얻을 수 있습니다. 이 메시지가 PC나 스마트폰에 알림이 되어 실시간으로 업무 확인이 가능하게 됐습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;624&quot; data-origin-height=&quot;262&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/daYDTj/btrDmXdbIpZ/NXklsyiXze4FOSNkPhd5t1/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/daYDTj/btrDmXdbIpZ/NXklsyiXze4FOSNkPhd5t1/img.webp&quot; data-alt=&quot;동작-결과&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/daYDTj/btrDmXdbIpZ/NXklsyiXze4FOSNkPhd5t1/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdaYDTj%2FbtrDmXdbIpZ%2FNXklsyiXze4FOSNkPhd5t1%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; alt=&quot;동작-결과&quot; loading=&quot;lazy&quot; width=&quot;624&quot; height=&quot;262&quot; data-origin-width=&quot;624&quot; data-origin-height=&quot;262&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;동작-결과&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>Programming/.Net</category>
      <category>ASP.NET</category>
      <category>Nas</category>
      <category>synology</category>
      <author>❤ </author>
      <guid isPermaLink="true">https://luckygg.tistory.com/367</guid>
      <comments>https://luckygg.tistory.com/367#entry367comment</comments>
      <pubDate>Sat, 28 May 2022 09:38:31 +0900</pubDate>
    </item>
    <item>
      <title>[Synology NAS] 작업 스케줄러로 작업 예약하기(사용자 정의 스크립트)</title>
      <link>https://luckygg.tistory.com/366</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;작업 스케줄러란?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시놀로지 나스의 제어판에는 &lt;b&gt;작업 스케줄러&lt;/b&gt; 메뉴가 있습니다. 이 작업 스케줄러를 사용하여 &lt;b&gt;특정 시간에 특정 서비스나 스크립트를 예약하고 실행&lt;/b&gt;할 수 있습니다. 예를 들어, 휴지통을 주기적으로 비울 수도 있고, 나스 전원을 주기적으로 리부팅할 수도 있습니다.&lt;br /&gt;&lt;br /&gt;이 작업 스케줄러는 직접 설정할 수도 있지만 자동으로 등록되는 경우가 있습니다. 하이퍼 백업 기능을 사용하면 스케줄러에 자동으로 등록되어 있는 것을 확인할 수 있습니다. 반복되는 작업이 있다면 스케줄러를 활용하는 것이 좋습니다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;466&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/N3Keu/btrAYlHqhJb/4R2zSYcnOIvdTaGlFfWr80/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/N3Keu/btrAYlHqhJb/4R2zSYcnOIvdTaGlFfWr80/img.webp&quot; data-alt=&quot;작업-스케줄러-메뉴&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/N3Keu/btrAYlHqhJb/4R2zSYcnOIvdTaGlFfWr80/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FN3Keu%2FbtrAYlHqhJb%2F4R2zSYcnOIvdTaGlFfWr80%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; alt=&quot;작업-스케줄러-메뉴&quot; loading=&quot;lazy&quot; width=&quot;800&quot; height=&quot;466&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;466&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;작업-스케줄러-메뉴&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;작업 스케줄러 종류&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&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;800&quot; data-origin-height=&quot;509&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/x9X8Q/btrAR9B85Or/GcIxVyNmipjsiHkCtQCQw1/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/x9X8Q/btrAR9B85Or/GcIxVyNmipjsiHkCtQCQw1/img.webp&quot; data-alt=&quot;작업-스케줄러-종류&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/x9X8Q/btrAR9B85Or/GcIxVyNmipjsiHkCtQCQw1/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fx9X8Q%2FbtrAR9B85Or%2FGcIxVyNmipjsiHkCtQCQw1%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; alt=&quot;작업-스케줄러-종류&quot; loading=&quot;lazy&quot; width=&quot;800&quot; height=&quot;509&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;509&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;작업-스케줄러-종류&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. 사용자 정의 스크립트&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;사용자가 작성한 스크립트를 실행&lt;/b&gt;하는 메뉴입니다. 스크립트 작성으로 도커의 특정 컨테이너를 실행, 종료할 수도 있습니다. 개인적으로 아주 유용하게 사용하고 있는 스케줄러입니다. '서비스'는 도커 자체를 시작하거나 중지할 수 있는데요. '사용자 정의 스크립트'를 사용해서 &lt;b&gt;도커의 특정 컨테이너를 시작하거나 중지할 수 있습니다&lt;/b&gt;.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스크립트는 다음과 같이 적용합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1650016171348&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;docker container start containername
docker container stop containername&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자 정의 스크립트를 적용하는 자세한 방법은 이후에 나오는 내용에서 설명합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. 휴지통&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;모든 휴지통 또는 특정 공유 폴더의 휴지통을 비우는 기능&lt;/b&gt;입니다. 모든 파일을 삭제하거나 특정 파일의 개수가 유지될 때, 크기 제한 등 여러 옵션을 설정할 수도 있습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. 신호음 제어&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;말 그대로 &lt;b&gt;시놀로지 나스의 신호음을 발생&lt;/b&gt;하는 메뉴입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4. 서비스&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시놀로지 &lt;b&gt;패키지 서비스를 시작하거나 중지&lt;/b&gt;할 수 있는 메뉴입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;5. 트리거된 작업&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;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;사용자 정의 스크립트로 스케줄러 생성하기&lt;/h2&gt;
&lt;center&gt;
&lt;script src=&quot;https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js&quot;&gt;&lt;/script&gt;
&lt;ins class=&quot;adsbygoogle&quot; style=&quot;display: block;&quot; data-ad-client=&quot;ca-pub-3156423405867571&quot; data-ad-slot=&quot;4203200518&quot; data-ad-format=&quot;link&quot; data-full-width-responsive=&quot;false&quot; data-ad-language=&quot;ko&quot;&gt;&lt;/ins&gt;
&lt;script&gt;
(adsbygoogle = window.adsbygoogle || []).push({});&lt;/script&gt;
&lt;/center&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;목적&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;도커 서비스를 개발하던 도중 아주 난감한 문제에 봉착했는데요. 바로, &lt;b&gt;메모리 누수&lt;/b&gt;였습니다. 서비스가 잘 동작하는 줄 알았는데, 시간이 흐르면서 메모리 사용량이 쌓여가고 하루가 지나니 나스가 먹통이 되는 현상이었죠.&lt;br /&gt;&lt;br /&gt;하지만 도커 서비스는 무엇이 문제인지 디버깅이 어렵습니다. 개발환경에서 동작하는 것이 아니라, 실제 운영하는 것이기 때문이죠.&lt;br /&gt;&lt;br /&gt;그래서 대안책을 찾은 것이, &lt;b&gt;특정 시간에 서비스를 켜고 끈다면 메모리 누수를 회복&lt;/b&gt;하고 &lt;b&gt;계속해서 서비스를 운영&lt;/b&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;서론이 좀 길었습니다. 그럼, 사용자 정의 스크립트를 어떻게 추가하는지 설명하겠습니다. 아래 그림과 같이 &lt;b&gt;사용자 정의 스크립트&lt;/b&gt; 메뉴를 선택합니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;생성 &amp;gt; 예약된 작업 &amp;gt; 사용자 정의 스크립트&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;509&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/00oaR/btrAVsgde1X/t3raCF3koiQzHT1yzzsXY0/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/00oaR/btrAVsgde1X/t3raCF3koiQzHT1yzzsXY0/img.webp&quot; data-alt=&quot;사용자-정의-스크립트-추가하기&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/00oaR/btrAVsgde1X/t3raCF3koiQzHT1yzzsXY0/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F00oaR%2FbtrAVsgde1X%2Ft3raCF3koiQzHT1yzzsXY0%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; alt=&quot;사용자-정의-스크립트-추가하기&quot; loading=&quot;lazy&quot; width=&quot;800&quot; height=&quot;509&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;509&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;작업 생성&lt;/b&gt; 창이 표시되면 &lt;b&gt;작업&lt;/b&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;480&quot; data-origin-height=&quot;476&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/szFM0/btrATcLVEQJ/qMlHoIcVDpmt4r7ka747Dk/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/szFM0/btrATcLVEQJ/qMlHoIcVDpmt4r7ka747Dk/img.webp&quot; data-alt=&quot;작업-이름-기입하기&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/szFM0/btrATcLVEQJ/qMlHoIcVDpmt4r7ka747Dk/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FszFM0%2FbtrATcLVEQJ%2FqMlHoIcVDpmt4r7ka747Dk%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; alt=&quot;작업-이름-기입하기&quot; loading=&quot;lazy&quot; width=&quot;480&quot; height=&quot;476&quot; data-origin-width=&quot;480&quot; data-origin-height=&quot;476&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;스케줄 탭&lt;/b&gt;에서는 해당 스크립트를 &lt;b&gt;언제 실행할지&lt;/b&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;481&quot; data-origin-height=&quot;477&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dSOI2e/btrATebUdVi/qjnOXD4WBA6soqWtP1D59k/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dSOI2e/btrATebUdVi/qjnOXD4WBA6soqWtP1D59k/img.webp&quot; data-alt=&quot;요일과-시간-선택하기&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dSOI2e/btrATebUdVi/qjnOXD4WBA6soqWtP1D59k/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdSOI2e%2FbtrATebUdVi%2FqjnOXD4WBA6soqWtP1D59k%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; alt=&quot;요일과-시간-선택하기&quot; loading=&quot;lazy&quot; width=&quot;481&quot; height=&quot;477&quot; data-origin-width=&quot;481&quot; data-origin-height=&quot;477&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;작업 설정&lt;/b&gt; 탭에서는 &lt;b&gt;사용자 정의 스크립트를 기입&lt;/b&gt;할 수 있습니다. 아래 그림의 스크립트는 notifyerp라는 컨테이너를 시작하라는 명령어입니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;480&quot; data-origin-height=&quot;477&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rGLg5/btrAXDatdUZ/qIT2ZfcDDkOjV0kkv2aXw1/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rGLg5/btrAXDatdUZ/qIT2ZfcDDkOjV0kkv2aXw1/img.webp&quot; data-alt=&quot;사용자-정의-스크립트-입력-화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rGLg5/btrAXDatdUZ/qIT2ZfcDDkOjV0kkv2aXw1/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FrGLg5%2FbtrAXDatdUZ%2FqIT2ZfcDDkOjV0kkv2aXw1%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; alt=&quot;사용자-정의-스크립트-입력-화면&quot; loading=&quot;lazy&quot; width=&quot;480&quot; height=&quot;477&quot; data-origin-width=&quot;480&quot; data-origin-height=&quot;477&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;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;506&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/9Zeyi/btrAWzMTWet/ETi8izF1JAqvX5w2HiqKM1/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/9Zeyi/btrAWzMTWet/ETi8izF1JAqvX5w2HiqKM1/img.webp&quot; data-alt=&quot;사용자-정의-스크립트가-추가된-모습&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/9Zeyi/btrAWzMTWet/ETi8izF1JAqvX5w2HiqKM1/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F9Zeyi%2FbtrAWzMTWet%2FETi8izF1JAqvX5w2HiqKM1%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; alt=&quot;사용자-정의-스크립트가-추가된-모습&quot; loading=&quot;lazy&quot; width=&quot;800&quot; height=&quot;506&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;506&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;사용자-정의-스크립트가-추가된-모습&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>Computer/NAS</category>
      <category>Nas</category>
      <category>synology</category>
      <author>❤ </author>
      <guid isPermaLink="true">https://luckygg.tistory.com/366</guid>
      <comments>https://luckygg.tistory.com/366#entry366comment</comments>
      <pubDate>Sun, 1 May 2022 10:39:26 +0900</pubDate>
    </item>
    <item>
      <title>[Visual Studio] 비주얼 스튜디오 2019에서 깃랩(GitLab) 패키지 사용하는 방법</title>
      <link>https://luckygg.tistory.com/365</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;깃랩(GitLab) 패키지&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;깃랩(GitLab)&lt;/span&gt;&lt;/code&gt;은 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;깃(Git)&lt;/span&gt;&lt;/code&gt;, &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;깃헙(GitHub)&lt;/span&gt;&lt;/code&gt;과 마찬가지로 소스 코드의 버전 관리를 위한 시스템입니다. 종류에 따라 설치형도 있고, Console이나 GUI로 제공되는 형태도 있습니다. 그리고 언급한 세 가지 모두 비주얼 스튜디오에서 패키지(플러그인)로도 제공하고 있습니다. 기본적인 개념만 알고 있다면, 굳이 명령어를 입력하지 않고 플러그인 조작으로 쉽게 사용할 수 있는 것이죠.&lt;br /&gt;&lt;br /&gt;여기서 문제가 있습니다. 비주얼 스튜디오 2019에는 기본적으로 소스 제어 옵션으로 &lt;b&gt;깃&lt;/b&gt;과 &lt;b&gt;Team Foundation Server&lt;/b&gt;를 제공하고 있는데요. Visual Studio 2019부터 새로운 옵션이 활성화되어, 이전에 사용하던 깃 메뉴가 보이지 않는 것이죠. 물론, 새로 배워서 사용해도 되겠지만 기존에 사용하던 방식이 익숙하다 보니 불편하긴 합니다.&lt;br /&gt;&lt;br /&gt;그래서 이번 포스팅에서 이전과 같이 깃랩 패키지 메뉴를 사용하는 방법을 공유합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;New Git user experience 옵션 끄기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 기능은 &lt;b&gt;Visual Studio 2019부터 지원&lt;/b&gt;되는데요. 기본 값으로 켜져 있으며 옵션의 위치는 다음과 같습니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;비주얼 스튜디오 &amp;gt; 도구 &amp;gt; 옵션 &amp;gt; 환경 &amp;gt; 미리 보기 기능 &amp;gt; New Git user experience&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;749&quot; data-origin-height=&quot;437&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/BBEq2/btrzQn8nlLk/JSLQjk0k5WkKMA0v74F6Vk/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/BBEq2/btrzQn8nlLk/JSLQjk0k5WkKMA0v74F6Vk/img.webp&quot; data-alt=&quot;New Git user experience 옵션 위치&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/BBEq2/btrzQn8nlLk/JSLQjk0k5WkKMA0v74F6Vk/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FBBEq2%2FbtrzQn8nlLk%2FJSLQjk0k5WkKMA0v74F6Vk%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; alt=&quot;New Git user experience 옵션 위치&quot; loading=&quot;lazy&quot; width=&quot;749&quot; height=&quot;437&quot; data-origin-width=&quot;749&quot; data-origin-height=&quot;437&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;New Git user experience 옵션 위치&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 옵션이 켜져있으면 &lt;b&gt;Git 변경 내용&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;425&quot; data-origin-height=&quot;311&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kDVJQ/btrzRVbY1lo/SApMfs0iEd7sJQjKHWUydK/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kDVJQ/btrzRVbY1lo/SApMfs0iEd7sJQjKHWUydK/img.webp&quot; data-alt=&quot;Git 변경 내용 창&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kDVJQ/btrzRVbY1lo/SApMfs0iEd7sJQjKHWUydK/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkDVJQ%2FbtrzRVbY1lo%2FSApMfs0iEd7sJQjKHWUydK%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; alt=&quot;Git 변경 내용 창&quot; loading=&quot;lazy&quot; width=&quot;425&quot; height=&quot;311&quot; data-origin-width=&quot;425&quot; data-origin-height=&quot;311&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Git 변경 내용 창&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 &lt;b&gt;Git 리포지토리 만들기&lt;/b&gt; 버튼을 클릭하면 아래와 같은 창이 표시됩니다. 마이크로소프트가 GitHub을 인수한 이후 비주얼 스튜디오 기본 옵션으로 GitHub이 추가되었습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;587&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/baI9Ql/btrzOHzvr8m/YpKJLf5h9vNLLK0gqsuQjK/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/baI9Ql/btrzOHzvr8m/YpKJLf5h9vNLLK0gqsuQjK/img.webp&quot; data-alt=&quot;Git 리포지토리 만들기 화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/baI9Ql/btrzOHzvr8m/YpKJLf5h9vNLLK0gqsuQjK/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbaI9Ql%2FbtrzOHzvr8m%2FYpKJLf5h9vNLLK0gqsuQjK%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; alt=&quot;Git 리포지토리 만들기 화면&quot; loading=&quot;lazy&quot; width=&quot;800&quot; height=&quot;587&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;587&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Git 리포지토리 만들기 화면&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;평소에 사용하던 메뉴와 다르죠. 깃랩 계정 연동 후 Git 변경 내용 메뉴를 보면 버튼의 위치와 아이콘이 변경됐습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;772&quot; data-origin-height=&quot;497&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cKdcgj/btrzRV37B5d/o2SMqskH3ukPlCwCpXXns1/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cKdcgj/btrzRV37B5d/o2SMqskH3ukPlCwCpXXns1/img.webp&quot; data-alt=&quot;새로 변경된 메뉴&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cKdcgj/btrzRV37B5d/o2SMqskH3ukPlCwCpXXns1/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcKdcgj%2FbtrzRV37B5d%2Fo2SMqskH3ukPlCwCpXXns1%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; alt=&quot;새로 변경된 메뉴&quot; loading=&quot;lazy&quot; width=&quot;772&quot; height=&quot;497&quot; data-origin-width=&quot;772&quot; data-origin-height=&quot;497&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;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;352&quot; data-origin-height=&quot;470&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/AdbNe/btrzNB7tU4E/7QTWkRg9ZLCNXrydpurLKK/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/AdbNe/btrzNB7tU4E/7QTWkRg9ZLCNXrydpurLKK/img.webp&quot; data-alt=&quot;옵션이 해제된 모습&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/AdbNe/btrzNB7tU4E/7QTWkRg9ZLCNXrydpurLKK/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FAdbNe%2FbtrzNB7tU4E%2F7QTWkRg9ZLCNXrydpurLKK%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; alt=&quot;옵션이 해제된 모습&quot; loading=&quot;lazy&quot; width=&quot;352&quot; height=&quot;470&quot; data-origin-width=&quot;352&quot; data-origin-height=&quot;470&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;옵션이 해제된 모습&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>Programming/Visual Studio</category>
      <category>Visual Studio</category>
      <author>❤ </author>
      <guid isPermaLink="true">https://luckygg.tistory.com/365</guid>
      <comments>https://luckygg.tistory.com/365#entry365comment</comments>
      <pubDate>Tue, 19 Apr 2022 17:27:36 +0900</pubDate>
    </item>
    <item>
      <title>프로필</title>
      <link>https://luckygg.tistory.com/pages/%ED%94%84%EB%A1%9C%ED%95%84</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;안녕하세요, LuckyGg입니다.&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;블로그 운영 초반에는 여행이나 후기 같은 것들도 올렸는데, 방향성을 정립한 이후로는 머신 비전과 프로그래밍, IT 관련 내용으로만 운영하고 있습니다.&lt;br /&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;LuckyGg: skyupju124@gmail.com&lt;/p&gt;</description>
      <author>❤ </author>
      <guid isPermaLink="true">https://luckygg.tistory.com/pages/%ED%94%84%EB%A1%9C%ED%95%84</guid>
      <pubDate>Tue, 5 Apr 2022 22:07:05 +0900</pubDate>
    </item>
    <item>
      <title>C# Project, Solution Rename 이름 변경 프로그램을 무료 배포합니다!</title>
      <link>https://luckygg.tistory.com/354</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;솔루션 및 프로젝트 이름 변경 프로그램&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가끔 테스트 프로젝트를 생성하고 개발하다가 문제가 없으면 해당 프로젝트를 본 프로젝트로 사용하고 싶은 경우가 있습니다. MFC를 사용할 때에는 아래 링크의 프로그램을 사용했었는데요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://blog.daum.net/prodori/15684145&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://blog.daum.net/prodori/15684145&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1642415017264&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;프로젝트명 변경&quot; data-og-description=&quot;프로젝트 문자 변경 툴로 vsrename을 사용하다가 Visual Studio 2010과 같은 유니코드나 UTF_8 포맷으로 작성된 문서들에 대해서 오동작을 하여 직접 만들어 본 툴입니다. ProjectRename.exe  실행 화면은 다&quot; data-og-host=&quot;blog.daum.net&quot; data-og-source-url=&quot;https://blog.daum.net/prodori/15684145&quot; data-og-url=&quot;https://blog.daum.net/prodori/15684145&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/DSBHF/hyM78hIvM9/j4s6tJm31gk3v4EFuTrXE1/img.jpg?width=684&amp;amp;height=249&amp;amp;face=0_0_684_249,https://scrap.kakaocdn.net/dn/bD7KmI/hyM72BNDoo/AiF9O98DA1k1n06oRRLQD1/img.jpg?width=684&amp;amp;height=249&amp;amp;face=0_0_684_249&quot;&gt;&lt;a href=&quot;https://blog.daum.net/prodori/15684145&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://blog.daum.net/prodori/15684145&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/DSBHF/hyM78hIvM9/j4s6tJm31gk3v4EFuTrXE1/img.jpg?width=684&amp;amp;height=249&amp;amp;face=0_0_684_249,https://scrap.kakaocdn.net/dn/bD7KmI/hyM72BNDoo/AiF9O98DA1k1n06oRRLQD1/img.jpg?width=684&amp;amp;height=249&amp;amp;face=0_0_684_249');&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;프로젝트명 변경&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;프로젝트 문자 변경 툴로 vsrename을 사용하다가 Visual Studio 2010과 같은 유니코드나 UTF_8 포맷으로 작성된 문서들에 대해서 오동작을 하여 직접 만들어 본 툴입니다. ProjectRename.exe 실행 화면은 다&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;blog.daum.net&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이상하게 C# &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;솔루션(*.sln)&lt;/span&gt;&lt;/code&gt;이나 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;프로젝트(*.csproj)&lt;/span&gt;&lt;/code&gt; 이름을 변경해주는 프로그램을 제공하는 곳이 없더군요. 누군가 만들어서 배포할 거라 생각했지만, MFC에 비해 이름 변경이 간단해서 그런지 프로그램을 찾지 못했습니다.&lt;br /&gt;&lt;br /&gt;그래서 어차피 필요한 거, 프로그램을 직접 만들어서 배포하기로 했습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;C#에서 Project, Solution 이름 변경하는 방법&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;C# 기준 솔루션 및 프로젝트 파일은 이름을 어떻게 변경하는지 알아보겠습니다. 자세한 내용은 아래 '&lt;b&gt;더보기&lt;/b&gt;' 버튼을 클릭하세요.&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. Solution 이름 변경하는 방법&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;보통 프로젝트를 생성하면 솔루션 이름이 프로젝트 이름과 동일하게 생성됩니다. 이후 새로운 프로젝트를 추가하면 아래와 같은 모습이 됩니다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;110&quot; data-origin-height=&quot;67&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bXAb6h/btruLtx6fqD/Cm1InfCuz96TcOtWolKPA1/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bXAb6h/btruLtx6fqD/Cm1InfCuz96TcOtWolKPA1/img.webp&quot; data-alt=&quot;솔루션 이름 변경 전&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bXAb6h/btruLtx6fqD/Cm1InfCuz96TcOtWolKPA1/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbXAb6h%2FbtruLtx6fqD%2FCm1InfCuz96TcOtWolKPA1%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; alt=&quot;솔루션 이름 변경 전&quot; loading=&quot;lazy&quot; width=&quot;110&quot; height=&quot;67&quot; data-origin-width=&quot;110&quot; data-origin-height=&quot;67&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;솔루션 이름 변경 전&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;솔루션 이름을 변경하는 방법은 아주 간단합니다. &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;*.sln&lt;/span&gt;&lt;/code&gt; 확장자는 유지하고 파일명만 변경하면 됩니다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;91&quot; data-origin-height=&quot;65&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kMkYh/btruAtmyyD3/TWwq7H1iCG0RTqH51PPMA1/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kMkYh/btruAtmyyD3/TWwq7H1iCG0RTqH51PPMA1/img.webp&quot; data-alt=&quot;솔루션 이름 변경 후&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kMkYh/btruAtmyyD3/TWwq7H1iCG0RTqH51PPMA1/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkMkYh%2FbtruAtmyyD3%2FTWwq7H1iCG0RTqH51PPMA1%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; alt=&quot;솔루션 이름 변경 후&quot; loading=&quot;lazy&quot; width=&quot;91&quot; height=&quot;65&quot; data-origin-width=&quot;91&quot; data-origin-height=&quot;65&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;솔루션 이름 변경 후&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. Project 이름 변경하는 방법&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로젝트 이름 변경 방법은 솔루션 파일 이름 변경보다 조금 까다롭습니다. 위 이미지의 예시로 설명하면 다음과 같습니다.&lt;br /&gt;&lt;br /&gt;① 하위 프로젝트 경로 폴더 이름을 &lt;b&gt;새로운 이름&lt;/b&gt;으로 변경합니다. 또는 변경하지 않아도 됩니다.&lt;br /&gt;② 하위 프로젝트 경로의 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;*.csproj&lt;/span&gt;&lt;/code&gt;의 이름을 새로운 이름으로 변경합니다.&lt;br /&gt;③ 변경한 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;*.csproj&lt;/span&gt;&lt;/code&gt; 파일을 메모장으로 엽니다.&lt;br /&gt;④ 아래 표시한 부분을 새로운 이름으로 변경합니다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;564&quot; data-origin-height=&quot;303&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cdshDr/btruHwWFofr/0jyZZc4NI6SXz58CmysGHk/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cdshDr/btruHwWFofr/0jyZZc4NI6SXz58CmysGHk/img.webp&quot; data-alt=&quot;csproj 내용 변경하기&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cdshDr/btruHwWFofr/0jyZZc4NI6SXz58CmysGHk/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcdshDr%2FbtruHwWFofr%2F0jyZZc4NI6SXz58CmysGHk%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; alt=&quot;csproj 내용 변경하기&quot; loading=&quot;lazy&quot; width=&quot;564&quot; height=&quot;303&quot; data-origin-width=&quot;564&quot; data-origin-height=&quot;303&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;csproj 내용 변경하기&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;⑤ &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;*.sln&lt;/span&gt;&lt;/code&gt; 파일을 메모장으로 엽니다.&lt;br /&gt;⑥ 아래 표시한 부분을 새로운 이름과 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;*.csproj&lt;/span&gt;&lt;/code&gt;가 존재하는 경로로 변경합니다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;207&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bpu8Lc/btruIUwfbk4/XTQHCp4WhcmL1ykZLejA2k/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bpu8Lc/btruIUwfbk4/XTQHCp4WhcmL1ykZLejA2k/img.webp&quot; data-alt=&quot;sln 내용 변경하기&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bpu8Lc/btruIUwfbk4/XTQHCp4WhcmL1ykZLejA2k/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbpu8Lc%2FbtruIUwfbk4%2FXTQHCp4WhcmL1ykZLejA2k%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; alt=&quot;sln 내용 변경하기&quot; loading=&quot;lazy&quot; width=&quot;800&quot; height=&quot;207&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;207&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;sln 내용 변경하기&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;CS Rename 프로그램 특징&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;솔루션(*.sln) 파일이 존재하는 폴더를 선택하면 하위 프로젝트(*.csproj) 파일을 모두 탐색&lt;/li&gt;
&lt;li&gt;솔루션 및 프로젝트 파일 이름 변경 시 폴더 이름도 선택적 변경 가능&lt;/li&gt;
&lt;li&gt;비설치 exe 단독 파일&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;아래 첨부된 파일을 다운로드하세요.&lt;/p&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/btbwR5/btrulR9fws7/9ItL80I51cHNyOiBrCNtT1/RenameCSProject%20v1.0.zip?attach=1&amp;amp;knm=tfile.zip&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;RenameCSProject v1.0.zip&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;size&quot;&gt;0.10MB&lt;/div&gt;
&lt;/div&gt;
  &lt;/a&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;업데이트 이력&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;업데이트 이력은 아래 '&lt;b&gt;더보기&lt;/b&gt;' 버튼을 클릭하여 확인할 수 있습니다.&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;v1.0&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;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;프로그램 사용 방법&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로그램 사용 방법은 아래 '&lt;b&gt;더보기&lt;/b&gt;' 버튼을 클릭하여 확인하세요.&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로그램을 실행하면 다음과 같은 화면이 표시됩니다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;354&quot; data-origin-height=&quot;353&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bOMSIR/btruG0DJdsT/wc51AANd6AFZmBZvZDhcQK/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bOMSIR/btruG0DJdsT/wc51AANd6AFZmBZvZDhcQK/img.webp&quot; data-alt=&quot;프로그램 실행 화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bOMSIR/btruG0DJdsT/wc51AANd6AFZmBZvZDhcQK/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbOMSIR%2FbtruG0DJdsT%2Fwc51AANd6AFZmBZvZDhcQK%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; alt=&quot;프로그램 실행 화면&quot; loading=&quot;lazy&quot; width=&quot;354&quot; height=&quot;353&quot; data-origin-width=&quot;354&quot; data-origin-height=&quot;353&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;프로그램 실행 화면&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;우측 상단의 버튼을 클릭하면 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;*.sln&lt;/span&gt;&lt;/code&gt; 파일을 선택하는 화면이 표시됩니다. 이름 변경이 필요한 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;*.sln&lt;/span&gt;&lt;/code&gt; 파일을 선택하면 솔루션 파일과 하위 프로젝트 파일 목록이 표시됩니다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;716&quot; data-origin-height=&quot;576&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dxvZCa/btruKknRuVH/R22vgiz5yzJeKKMEvlncT0/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dxvZCa/btruKknRuVH/R22vgiz5yzJeKKMEvlncT0/img.webp&quot; data-alt=&quot;솔루션 파일 선택하기&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dxvZCa/btruKknRuVH/R22vgiz5yzJeKKMEvlncT0/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdxvZCa%2FbtruKknRuVH%2FR22vgiz5yzJeKKMEvlncT0%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; alt=&quot;솔루션 파일 선택하기&quot; loading=&quot;lazy&quot; width=&quot;716&quot; height=&quot;576&quot; data-origin-width=&quot;716&quot; data-origin-height=&quot;576&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;솔루션 파일 선택하기&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;이름 변경이 필요한 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;*.sln&lt;/span&gt;&lt;/code&gt; 또는 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;*.csproj&lt;/span&gt;&lt;/code&gt;을 선택한 후 새로운 이름을 입력합니다. 폴더 경로까지 변경하려면 체크 박스를 체크합니다. 이후 &lt;b&gt;Convert 버튼&lt;/b&gt;을 클릭하면 이름이 변경됩니다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;730&quot; data-origin-height=&quot;316&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/1V5tK/btruDDCdOhW/aAfJTTze2QAnTlYZt7INLK/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/1V5tK/btruDDCdOhW/aAfJTTze2QAnTlYZt7INLK/img.webp&quot; data-alt=&quot;이름이 변경된 모습&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/1V5tK/btruDDCdOhW/aAfJTTze2QAnTlYZt7INLK/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F1V5tK%2FbtruDDCdOhW%2FaAfJTTze2QAnTlYZt7INLK%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; alt=&quot;이름이 변경된 모습&quot; loading=&quot;lazy&quot; width=&quot;730&quot; height=&quot;316&quot; data-origin-width=&quot;730&quot; data-origin-height=&quot;316&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;이름이 변경된 모습&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;버그 신고 방법&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로그램 사용 중 문제가 발생하면 '&lt;b&gt;오류가 발생하는 절차&lt;/b&gt;'와 '&lt;b&gt;증상&lt;/b&gt;'을 댓글로 남겨주세요.&lt;/p&gt;</description>
      <category>Programming/프로그램 배포</category>
      <category>.net</category>
      <author>❤ </author>
      <guid isPermaLink="true">https://luckygg.tistory.com/354</guid>
      <comments>https://luckygg.tistory.com/354#entry354comment</comments>
      <pubDate>Tue, 8 Mar 2022 22:38:30 +0900</pubDate>
    </item>
    <item>
      <title>[ASP.NET] Core Worker Service로 레드마인 일감을 시놀로지 챗 메시지로 알림 보내기</title>
      <link>https://luckygg.tistory.com/360</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;개발 배경&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저는 회사에서 업무 관리를 위해 시놀로지 도커에서 레드마인을 사용하고 있습니다. 그리고 레드마인의 메일 설정을 통해 일감 생성, 편집 시 메일로 알림을 받고 있습니다. 메일의 경우 아웃룩으로 확인하고 있습니다. 그런데 지금까지 레드마인을 사용하면서 너무나 &lt;b&gt;아쉬운 점&lt;/b&gt;이 있었습니다. 바로 &lt;i&gt;&lt;b&gt;알림을 즉시 확인할 수 없다는 것&lt;/b&gt;&lt;/i&gt;이죠&lt;br /&gt;&lt;br /&gt;레드마인 알림이 있는지 확인하기 위해 아웃룩에서 직접 &lt;b&gt;보내기/받기 버튼을 클릭&lt;/b&gt;하거나 &lt;b&gt;시간 간격을 짧게 설정&lt;/b&gt;해야 했습니다. 하지만 PC에서는 이렇게 확인하면 되지만 스마트폰에서는 알림 받기가 쉽지 않습니다. 알림을 켜자니 수신되는 모든 메일에 대해 알림이 오니 영 불편했습니다&lt;br /&gt;&lt;br /&gt;그래서 생각한 것이, &lt;b&gt;'&lt;/b&gt;&lt;i&gt;&lt;b&gt;레드마인 일감이 생성되면 메신저로 알림을 줄 수 있지 않을까'입니다.&lt;/b&gt;&lt;/i&gt; 게다가 저는 사내 메신저로 &lt;b&gt;시놀로지 챗(Chat)&lt;/b&gt;을 사용하고 있기 때문에, 챗으로 알림 메시지를 받길 원했습니다&lt;br /&gt;&lt;br /&gt;그런데 역시나 안 되는 건 없더군요. 레드마인은 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;REST API&lt;/b&gt;&lt;/span&gt;를, 챗은 &lt;span style=&quot;color: #009a87;&quot;&gt;&lt;b&gt;Incoming Webhook&lt;/b&gt;&lt;/span&gt;을 제공하고 있었습니다. 즉, 실시간으로 레드마인 REST API를 호출하여 신규 일감을 조회하고, 일감이 있다면 챗으로 메시지를 보내면 되는 것이죠!&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;785&quot; data-origin-height=&quot;322&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ZliK2/btrsUclKK1t/QfPGl7znfU2hrE8cd6pHY0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ZliK2/btrsUclKK1t/QfPGl7znfU2hrE8cd6pHY0/img.png&quot; data-alt=&quot;구상도&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ZliK2/btrsUclKK1t/QfPGl7znfU2hrE8cd6pHY0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FZliK2%2FbtrsUclKK1t%2FQfPGl7znfU2hrE8cd6pHY0%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;785&quot; height=&quot;322&quot; data-origin-width=&quot;785&quot; data-origin-height=&quot;322&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;구상도&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;ASP.NET Core Worker Service&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데 문제가 있었습니다. '어디'에서 프로그램을 돌리느냐입니다. 처음에는 특정 컴퓨터에 프로그램을 실행해 무한 루프로 계속 돌릴지, 아니면 윈도우 서비스로 개발하여 컴퓨터가 켜지면 계속 돌아가게 할지 고민을 했었습니다. 그런데 생각해보니 저는 시놀로지 &lt;b&gt;서버&lt;/b&gt;를 사용하고 있었습니다. 즉, 서버에 개발한 프로그램을 돌리면 되지 않을까 싶었죠. 그래서 알게 된 것이 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;ASP.NET Core&lt;/span&gt;&lt;/code&gt;였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;ASP.NET Core&lt;/span&gt;&lt;/code&gt;는 &lt;b&gt;Windows, macOS 및 Linux에서 인터넷 연결 앱을 동작할 수 있는 프레임 워크&lt;/b&gt;입니다. 그리고 C#을 지원합니다. 즉, 간단히 설명하면 제가 원하는 동작을 수행하는 코드를 빌드하고 그 결과물을 ASP.NET Core를 통해 서비스를 동작할 수 있다는 것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;게다가 Visual Studio에서 제작 가능한 &lt;b&gt;ASP.NET Core Worker Service(작업자 서비스)&lt;/b&gt; &lt;b&gt;템플릿&lt;/b&gt;은 장기간 실행되는 서비스 앱을 개발하기 위해 제공됩니다. 즉, 이번 구상과 같이 멈추지 않고 계속해서 돌릴 서비스를 제작하기 위한 프로젝트라는 것이죠.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;
&lt;script src=&quot;https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-3156423405867571&quot;&gt;&lt;/script&gt;
&lt;/p&gt;
&lt;p&gt;&lt;ins class=&quot;adsbygoogle&quot; style=&quot;display: block; text-align: center;&quot; data-ad-layout=&quot;in-article&quot; data-ad-format=&quot;fluid&quot; data-ad-client=&quot;ca-pub-3156423405867571&quot; data-ad-slot=&quot;4203200518&quot;&gt;&lt;/ins&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;
&lt;script&gt;
     (adsbygoogle = window.adsbygoogle || []).push({});
&lt;/script&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;개발 순서&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 본격적으로 개발에 돌입하기에 앞서, '어떻게' 개발해 나갈 것인지 설명하겠습니다. 중간 중간 내용이 꽤 많아서 하위 포스팅을 첨부했습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. 테스트 프로그램&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선 레드마인 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;REST API&lt;/span&gt;&lt;/code&gt;와 시놀로지 챗 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;Incoming Webhook&lt;/span&gt;&lt;/code&gt;을 연동할 줄 알아야겠죠? 레드마인 REST API와 Incoming Webhook을 다루는 방법은 아래 링크를 참고하세요.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://luckygg.tistory.com/358&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;[.Net] C# 레드마인 REST API 사용하는 방법(예제 포함)&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://luckygg.tistory.com/359&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;[챗봇/.NET] C#에서 시놀로지 Chat에 챗봇 메시지 보내기(예제 포함)&lt;/a&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. Windows Docker with Worker Service&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;도커는 Windows와 Linux 운영체제 모두 지원하는데요. 최종 목표는 리눅스 기반의 시놀로지 도커이지만, &lt;b&gt;중간 검증을 위해 윈도우용 도커에서 먼저 테스트&lt;/b&gt;를 진행하려고 합니다. 그리고 도커에서 서비스를 구동하기 위해서는 Visual Studio에서 제공하는 작업자 서비스(Worker Service) 템플릿을 사용하면 됩니다.&lt;br /&gt;&lt;br /&gt;이와 관련된 내용은 아래 링크를 참고하세요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://luckygg.tistory.com/361&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;[ASP.NET] C# Windows Docker 용 작업자 서비스 만드는 방법&lt;/a&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. Synology Docker with Worker Service&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;윈도우 도커에서 검증이 됐다면, 시놀로지 도커에 이미지를 올리고 컨테이너를 실행하면 끝입니다. 여기서 Putty를 사용하여 시놀로지에 접속하는 과정이 있기 때문에 PuTTY 사용 방법도 숙지하시기 바랍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://luckygg.tistory.com/363&quot;&gt;[Synology NAS] 푸티(PuTTY)로 시놀로지 접속하는 방법&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PuTTY 사용법도 익혔다면 리눅스 도커용 작업자 서비스 만드는 방법을 참고하세요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://luckygg.tistory.com/362&quot;&gt;[ASP.NET] C# 시놀로지 Linux Docker 용 작업자 서비스 만드는 방법&lt;/a&gt;​&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;동작 설계&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재 제가 사용하는 레드마인에는 타 부서에서 업무를 요청할 수 있는 '&lt;b&gt;업무 요청&lt;/b&gt;' 프로젝트가 따로 있습니다. 타 부서 담당자들은 모두 이곳에서 일감을 생성하여 업무를 요청하게 됩니다. 그리고 처리된 일감은 해당 프로젝트에서 사라지게 됩니다.&lt;br /&gt;&lt;br /&gt;이를 기반으로, 제가 생각한 서비스의 동작은 다음과 같습니다.&lt;br /&gt;① 업무 요청 프로젝트에 존재하는 '처리되지 않은 일감'을 조회한다.&lt;br /&gt;② 일감 번호를 기억하여 중복으로 메시지를 전달하지 않도록 한다.&lt;br /&gt;③ 메신저로 일감 &lt;b&gt;웹 사이트 주소&lt;/b&gt;와 &lt;b&gt;제목&lt;/b&gt;을 메시지로 전송한다.&amp;nbsp;&lt;br /&gt;&lt;br /&gt;아주 간단하죠? 이를 기반으로 코드 구현을 해보겠습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;동작.png&quot; data-origin-width=&quot;785&quot; data-origin-height=&quot;362&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dhRap2/btruDDIQbxA/M5fI6FMlKBmCfYw4VcYzX1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dhRap2/btruDDIQbxA/M5fI6FMlKBmCfYw4VcYzX1/img.png&quot; data-alt=&quot;서비스 동작&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dhRap2/btruDDIQbxA/M5fI6FMlKBmCfYw4VcYzX1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdhRap2%2FbtruDDIQbxA%2FM5fI6FMlKBmCfYw4VcYzX1%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;785&quot; height=&quot;362&quot; data-filename=&quot;동작.png&quot; data-origin-width=&quot;785&quot; data-origin-height=&quot;362&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;script src=&quot;https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-3156423405867571&quot;&gt;&lt;/script&gt;
&lt;/p&gt;
&lt;p&gt;&lt;ins class=&quot;adsbygoogle&quot; style=&quot;display: block; text-align: center;&quot; data-ad-layout=&quot;in-article&quot; data-ad-format=&quot;fluid&quot; data-ad-client=&quot;ca-pub-3156423405867571&quot; data-ad-slot=&quot;4203200518&quot;&gt;&lt;/ins&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;
&lt;script&gt;
     (adsbygoogle = window.adsbygoogle || []).push({});
&lt;/script&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;코드 구현&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;중간중간 확인해야 할 것들이 꽤 많았습니다. 그럼 본격적으로 프로젝트의 목표를 위한 핵심 코드 구현은 어떻게 되는지 살펴보겠습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1646040479435&quot; class=&quot;cs&quot; data-ke-language=&quot;cs&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class Worker : BackgroundService
{
	//신규 일감 알림 메시지 중복 방지를 위한 객체
	private Dictionary&amp;lt;int, string&amp;gt; _list = new Dictionary&amp;lt;int, string&amp;gt;();
	
    //... 생략...
    
    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            try
            {
            	//1초 마다 지연
                await Task.Delay(1000, stoppingToken);
				//현재 존재하는 일감 조회
                var issues = searchIssues();
                //존재하는 일감이 있다면
                if (issues != null)
                {
                    foreach (var issue in issues)
                    {
                        try
                        {
                        	//일감 번호와 제목을 _list에 추가
                            _list.Add(issue.Id, issue.Subject);
                            //시놀로지 Chat에 메시지 전송
                            notifyChatMessage(issue);
                        }
                        catch (Exception exc)
                        {
                        	//이미 _list에 일감 제목이 존재하면 예외로 처리
                            continue;
                        }
                    }
                }
				//현재 존재하는 일감이 없다면
                else 
                {
                	//모든 신규 일감을 Chat에 메시지를 보냈으므로,
                    //현재 존재하는 목록을 지운다(중복 방지)
                    if (_list.Count != 0)
                    {
                        _list.Clear();
                    }
                }
            }
            catch(Exception exc)
            {
                _logger.LogInformation(exc.Message);
            }
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드는 생각보다 아주 간단하고, 주석으로도 충분히 설명이 될 것 같습니다. 중간에 호출하는 &lt;code&gt;&lt;span class=&quot;token function-name&quot;&gt;searchIssues()&lt;/span&gt;&lt;/code&gt;는 &lt;a title=&quot;레드마인 REST API&quot; href=&quot;https://luckygg.tistory.com/358&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;레드마인 REST API 포스팅&lt;/a&gt;을, &lt;code&gt;&lt;span class=&quot;token function-name&quot;&gt;notifyChatMessage()&lt;/span&gt;&lt;/code&gt;는 &lt;a title=&quot;Chat에 챗봇 메시지 보내기&quot; href=&quot;https://luckygg.tistory.com/359&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Chat에 챗봇 메시지 보내기 포스팅&lt;/a&gt;을 참고하세요.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;후기&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;746&quot; data-origin-height=&quot;208&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bVNWNw/btruAiYk4Z2/opTYHjepRYq2yzTz4hkYKK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bVNWNw/btruAiYk4Z2/opTYHjepRYq2yzTz4hkYKK/img.png&quot; data-alt=&quot;실제 알림 화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bVNWNw/btruAiYk4Z2/opTYHjepRYq2yzTz4hkYKK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbVNWNw%2FbtruAiYk4Z2%2FopTYHjepRYq2yzTz4hkYKK%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;746&quot; height=&quot;208&quot; data-origin-width=&quot;746&quot; data-origin-height=&quot;208&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;해당 서비스를 제작한 후 빠르게 업무 요청 일감을 관리하고 있습니다. 이전에는 다른 일을 하느라 바쁘면 메일 확인이 늦어 업무 확인이 늦어졌는데, 현재는 PC 또는 스마트폰으로 알림이 즉시 오니 바쁘더라도 빨리 확인하게 되어 업무 지연이 최소화되었습니다. 역시 불편하면 직접 만들어서 해결하는 것이 정답인 것 같습니다.&lt;/p&gt;</description>
      <category>Programming/.Net</category>
      <category>ASP.NET</category>
      <category>레드마인</category>
      <author>❤ </author>
      <guid isPermaLink="true">https://luckygg.tistory.com/360</guid>
      <comments>https://luckygg.tistory.com/360#entry360comment</comments>
      <pubDate>Fri, 4 Mar 2022 20:22:13 +0900</pubDate>
    </item>
    <item>
      <title>[ASP.NET] C# 시놀로지 Linux Docker 용 작업자 서비스 만드는 방법</title>
      <link>https://luckygg.tistory.com/362</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;Linux Docker 작업자 서비스&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지난 포스팅에서 ASP.NET Core Worker Service를 빌드하여 Windows 용 Docker에서 서비스를 동작하는 방법을 소개했었습니다. 이번에는 Linux Docker를 위한 작업자 서비스를 제작하려고 하는데요. 저에게 시놀로지(Linux 기반) 서버가 있기 때문에 이번 포스팅에서는 시놀로지 Docker에서 Linux 용 작업자 서비스를 만드는 방법을 소개하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://luckygg.tistory.com/361&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;[ASP.NET] C# Windows Docker 용 작업자 서비스 만드는 방법&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1645618947549&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;[ASP.NET] C# Windows Docker 용 작업자 서비스 만드는 방법&quot; data-og-description=&quot;Windows Docker 작업자 서비스 ASP.NET Core 는 Windows, macOS 및 Linux에서 인터넷 연결 앱을 동작할 수 있는 프레임 워크입니다. 간단히 설명하면 제가 원하는 동작을 수행하는 코드를 빌드하고 그 결과물&quot; data-og-host=&quot;luckygg.tistory.com&quot; data-og-source-url=&quot;https://luckygg.tistory.com/361&quot; data-og-url=&quot;https://luckygg.tistory.com/361&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/YFgqg/hyNv2VXb54/fcPuNgmtecSoxyB3pKNzk0/img.jpg?width=800&amp;amp;height=643&amp;amp;face=360_98_467_215,https://scrap.kakaocdn.net/dn/miQJO/hyNvsvaMRd/L2KV9yxR253aZTRk6rVzWK/img.jpg?width=800&amp;amp;height=643&amp;amp;face=360_98_467_215&quot;&gt;&lt;a href=&quot;https://luckygg.tistory.com/361&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://luckygg.tistory.com/361&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/YFgqg/hyNv2VXb54/fcPuNgmtecSoxyB3pKNzk0/img.jpg?width=800&amp;amp;height=643&amp;amp;face=360_98_467_215,https://scrap.kakaocdn.net/dn/miQJO/hyNvsvaMRd/L2KV9yxR253aZTRk6rVzWK/img.jpg?width=800&amp;amp;height=643&amp;amp;face=360_98_467_215');&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;[ASP.NET] C# Windows Docker 용 작업자 서비스 만드는 방법&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Windows Docker 작업자 서비스 ASP.NET Core 는 Windows, macOS 및 Linux에서 인터넷 연결 앱을 동작할 수 있는 프레임 워크입니다. 간단히 설명하면 제가 원하는 동작을 수행하는 코드를 빌드하고 그 결과물&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;luckygg.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;작업자 서비스 빌드하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;작업자 서비스 프로젝트는 몇 가지를 제외하고 지난번 프로젝트 생성과 동일합니다. 차이나는 부분만 따로 설명하겠습니다. 전체 과정은 위 링크를 참고하세요.&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로젝트 생성 시 &lt;b&gt;Docker OS&lt;/b&gt;를 &lt;b&gt;Linux&lt;/b&gt;로 선택합니다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;877&quot; data-origin-height=&quot;586&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/6elDd/btrs66zNIZ9/1iJPydTPSqSd66kM0w5tI0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/6elDd/btrs66zNIZ9/1iJPydTPSqSd66kM0w5tI0/img.png&quot; data-alt=&quot;대상 프레임워크 및 Docker OS 선택&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/6elDd/btrs66zNIZ9/1iJPydTPSqSd66kM0w5tI0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F6elDd%2Fbtrs66zNIZ9%2F1iJPydTPSqSd66kM0w5tI0%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;877&quot; height=&quot;586&quot; data-origin-width=&quot;877&quot; data-origin-height=&quot;586&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;대상 프레임워크 및 Docker OS 선택&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 &lt;b&gt;Dockerfile&lt;/b&gt; 내용을 다음과 같이 수정합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1644742880664&quot; class=&quot;dockerfile&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;FROM mcr.microsoft.com/dotnet/runtime:5.0 AS base
 
COPY . /app
WORKDIR /app

#포트 번호는 예시로 8888
ENV ASPNETCORE_URLS http://*:8888
EXPOSE 8888

#ExamWorkerService는 프로젝트 이름
ENTRYPOINT [&quot;dotnet&quot;, &quot;ExamWorkerService.dll&quot;]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이대로&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;게시&lt;/b&gt;한 후 빌드 관련 파일이 생성된 폴더에 Dockerfile을 복사하여 붙여 넣습니다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;907&quot; data-origin-height=&quot;698&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/0lVYh/btrs793bi7T/OIyN26CN6qed3EgVhpsZ2K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/0lVYh/btrs793bi7T/OIyN26CN6qed3EgVhpsZ2K/img.png&quot; data-alt=&quot;게시 폴더에 Dockerfile 복사하기&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/0lVYh/btrs793bi7T/OIyN26CN6qed3EgVhpsZ2K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F0lVYh%2Fbtrs793bi7T%2FOIyN26CN6qed3EgVhpsZ2K%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;907&quot; height=&quot;698&quot; data-origin-width=&quot;907&quot; data-origin-height=&quot;698&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;게시 폴더에 Dockerfile 복사하기&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;center&gt;
&lt;script src=&quot;https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js&quot;&gt;&lt;/script&gt;
&lt;ins class=&quot;adsbygoogle&quot; style=&quot;display: block;&quot; data-ad-client=&quot;ca-pub-3156423405867571&quot; data-ad-slot=&quot;4203200518&quot; data-ad-format=&quot;link&quot; data-full-width-responsive=&quot;false&quot; data-ad-language=&quot;ko&quot;&gt;&lt;/ins&gt;
&lt;script&gt;
(adsbygoogle = window.adsbygoogle || []).push({});&lt;/script&gt;
&lt;/center&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;시놀로지 Docker에 작업자 서비스 설치하기&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Linux 기반인 시놀로지 Docker에 작업자 서비스를 설치해 보겠습니다.&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시놀로지 DSM에 접속하고 파일 스테이션(File Station)을 실행합니다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;473&quot; data-origin-height=&quot;360&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b8pwe4/btrt9UEa78G/L9zMRXOYGhhMZ5vRjWzN21/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b8pwe4/btrt9UEa78G/L9zMRXOYGhhMZ5vRjWzN21/img.png&quot; data-alt=&quot;File Station 실행&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b8pwe4/btrt9UEa78G/L9zMRXOYGhhMZ5vRjWzN21/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb8pwe4%2Fbtrt9UEa78G%2FL9zMRXOYGhhMZ5vRjWzN21%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;473&quot; height=&quot;360&quot; data-origin-width=&quot;473&quot; data-origin-height=&quot;360&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;File Station 실행&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 docker 폴더에 하위 폴더를 생성하고 이전 과정에서 빌드한 파일을 모두 복사합니다.&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;906&quot; data-origin-height=&quot;602&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mNBQX/btrs8BMmK1J/dVpAxlXCXP2SEMa19nrqZ1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mNBQX/btrs8BMmK1J/dVpAxlXCXP2SEMa19nrqZ1/img.png&quot; data-alt=&quot;게시한 파일 복사하기&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mNBQX/btrs8BMmK1J/dVpAxlXCXP2SEMa19nrqZ1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmNBQX%2Fbtrs8BMmK1J%2FdVpAxlXCXP2SEMa19nrqZ1%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;906&quot; height=&quot;602&quot; data-origin-width=&quot;906&quot; data-origin-height=&quot;602&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;게시한 파일 복사하기&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;파일을 다 옮겼으면 PuTTY를 실행하여 파일의 경로로 이동합니다. PuTTY로 시놀로지 접속 방법을 모른다면 아래 링크를 참고하세요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://luckygg.tistory.com/363&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;[Synology NAS] 푸티(PuTTY)로 시놀로지 접속하는 방법&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1645618954190&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;[Synology NAS] 푸티(PuTTY)로 시놀로지 접속하는 방법&quot; data-og-description=&quot;Synology NAS와 PuTTY 사용 시놀로지 나스를 평범하게 사용한다면 푸티(PuTTY) 사용 방법을 몰라도 됩니다. 하지만 저처럼 레드마인을 사용한다든가, DSM Root 권한으로 접근하여 뭔가를 수행한다면 PuTTY &quot; data-og-host=&quot;luckygg.tistory.com&quot; data-og-source-url=&quot;https://luckygg.tistory.com/363&quot; data-og-url=&quot;https://luckygg.tistory.com/363&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/sjNea/hyNv4sHCyU/9NlVDAKNTvnKONucli9zoK/img.jpg?width=714&amp;amp;height=699&amp;amp;face=0_0_714_699,https://scrap.kakaocdn.net/dn/Nkwqo/hyNwc5mFm4/25ZhFY06sRAYWEWiNxILF1/img.jpg?width=714&amp;amp;height=699&amp;amp;face=0_0_714_699&quot;&gt;&lt;a href=&quot;https://luckygg.tistory.com/363&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://luckygg.tistory.com/363&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/sjNea/hyNv4sHCyU/9NlVDAKNTvnKONucli9zoK/img.jpg?width=714&amp;amp;height=699&amp;amp;face=0_0_714_699,https://scrap.kakaocdn.net/dn/Nkwqo/hyNwc5mFm4/25ZhFY06sRAYWEWiNxILF1/img.jpg?width=714&amp;amp;height=699&amp;amp;face=0_0_714_699');&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;[Synology NAS] 푸티(PuTTY)로 시놀로지 접속하는 방법&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Synology NAS와 PuTTY 사용 시놀로지 나스를 평범하게 사용한다면 푸티(PuTTY) 사용 방법을 몰라도 됩니다. 하지만 저처럼 레드마인을 사용한다든가, DSM Root 권한으로 접근하여 뭔가를 수행한다면 PuTTY&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;luckygg.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저의 경우 도커를 볼륨 1에 설치했고 notifyredmine 이름의 폴더에 파일을 복사했습니다. 해당 경로로 이동하는 명령어는 다음과 같습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1645619032317&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;cd /volume1/docker/notifyredmine&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 다음의 명령어를 입력하여 빌드를 시작합니다. 마지막의 notifyredmine은 서비스 이름이므로, 짓고 싶은 대로 지어도 상관없습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1645619088240&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;docker build -t notifyredmine .&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;명령어 실행 후 정상적으로 빌드가 되면 아래와 같은 모습이 보여집니다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;915&quot; data-origin-height=&quot;582&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bLHn4V/btrua3HAkMF/Af3UCxf9Vbf0ACv5CTBC60/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bLHn4V/btrua3HAkMF/Af3UCxf9Vbf0ACv5CTBC60/img.png&quot; data-alt=&quot;정상적으로 빌드된 모습&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bLHn4V/btrua3HAkMF/Af3UCxf9Vbf0ACv5CTBC60/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbLHn4V%2Fbtrua3HAkMF%2FAf3UCxf9Vbf0ACv5CTBC60%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;915&quot; height=&quot;582&quot; data-origin-width=&quot;915&quot; data-origin-height=&quot;582&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;정상적으로 빌드된 모습&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;이제 시놀로지 DSM에서 &lt;b&gt;Docker&lt;/b&gt;를 실행하고 &lt;b&gt;이미지 메뉴를 선택&lt;/b&gt;하면 방금 빌드한 이미지가 보이게 됩니다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;915&quot; data-origin-height=&quot;497&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lXgV0/btrubL0EjZq/AciDS3gbzDv3CHgGDPfD2K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lXgV0/btrubL0EjZq/AciDS3gbzDv3CHgGDPfD2K/img.png&quot; data-alt=&quot;도커 이미지 목록&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lXgV0/btrubL0EjZq/AciDS3gbzDv3CHgGDPfD2K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlXgV0%2FbtrubL0EjZq%2FAciDS3gbzDv3CHgGDPfD2K%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;915&quot; height=&quot;497&quot; data-origin-width=&quot;915&quot; data-origin-height=&quot;497&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;도커 이미지 목록&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;이미지 선택 후 상단의 실행 버튼을 클릭하면 아래의 화면이 표시됩니다. &lt;b&gt;컨테이너 이름&lt;/b&gt;을 입력하고 &lt;b&gt;다음 버튼을 클릭&lt;/b&gt;합니다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;916&quot; data-origin-height=&quot;655&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/sou7j/btruefG5iRb/lxIXXrOAE2rFXgVKnByK80/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/sou7j/btruefG5iRb/lxIXXrOAE2rFXgVKnByK80/img.png&quot; data-alt=&quot;컨테이너 생성 화면1&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/sou7j/btruefG5iRb/lxIXXrOAE2rFXgVKnByK80/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fsou7j%2FbtruefG5iRb%2FlxIXXrOAE2rFXgVKnByK80%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;916&quot; height=&quot;655&quot; data-origin-width=&quot;916&quot; data-origin-height=&quot;655&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;컨테이너 생성 화면1&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;아래의 화면이 표시되면 적용 버튼을 클릭하여 컨테이너를 생성합니다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;916&quot; data-origin-height=&quot;653&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/biYv25/btrub9tNT74/6cYldTYw4k7fNbGYGTlXeK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/biYv25/btrub9tNT74/6cYldTYw4k7fNbGYGTlXeK/img.png&quot; data-alt=&quot;컨테이너 생성 화면2&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/biYv25/btrub9tNT74/6cYldTYw4k7fNbGYGTlXeK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbiYv25%2Fbtrub9tNT74%2F6cYldTYw4k7fNbGYGTlXeK%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;916&quot; height=&quot;653&quot; data-origin-width=&quot;916&quot; data-origin-height=&quot;653&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;컨테이너 생성 화면2&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;좌측 메뉴 중 컨테이너를 선택하면 &lt;b&gt;컨테이너 목록&lt;/b&gt;이 보입니다. 방금 생성한 컨테이너가 정상적으로 실행 중인지 확인할 수 있습니다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;915&quot; data-origin-height=&quot;493&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/46xx3/btrt7qC0wDJ/WW58JxSGMbe7vE4twszGe1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/46xx3/btrt7qC0wDJ/WW58JxSGMbe7vE4twszGe1/img.png&quot; data-alt=&quot;컨테이너 목록 화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/46xx3/btrt7qC0wDJ/WW58JxSGMbe7vE4twszGe1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F46xx3%2Fbtrt7qC0wDJ%2FWW58JxSGMbe7vE4twszGe1%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;915&quot; height=&quot;493&quot; data-origin-width=&quot;915&quot; data-origin-height=&quot;493&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;컨테이너 목록 화면&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;정리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번에도 잘 따라 하셨나요? 이번 작업은 지난 포스팅인 Windows Docker 작업자 서비스를 만드는 것과 큰 차이가 없었습니다. 하지만 작업자 서비스를 잘못 빌드하면 컨테이너가 계속해서 죽는 경험을 겪게 될 건데요. 본문 내용을 잘 따라 하신다면 큰 삽질 없이 원하는 작업을 실행할 수 있을 것입니다.&lt;/p&gt;</description>
      <category>Programming/.Net</category>
      <category>ASP.NET</category>
      <author>❤ </author>
      <guid isPermaLink="true">https://luckygg.tistory.com/362</guid>
      <comments>https://luckygg.tistory.com/362#entry362comment</comments>
      <pubDate>Mon, 28 Feb 2022 21:49:28 +0900</pubDate>
    </item>
    <item>
      <title>[Synology NAS] 푸티(PuTTY)로 시놀로지 접속하는 방법</title>
      <link>https://luckygg.tistory.com/363</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;Synology NAS와 PuTTY 사용&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시놀로지 나스를 평범하게 사용한다면 &lt;b&gt;푸티(PuTTY)&lt;/b&gt; 사용 방법을 몰라도 됩니다. 하지만 저처럼 레드마인을 사용한다든가, DSM Root 권한으로 접근하여 뭔가를 수행한다면 PuTTY 사용은 필수입니다. 이번 포스팅을 통해 PuTTY로 시놀로지 나스에 어떻게 접근하는지 사용 방법을 소개합니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;SSH 활성화하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PuTTY로 시놀로지에 접근하기 위해서는 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;SSH 포트를 활성화&lt;/b&gt;&lt;/span&gt;해야 합니다. 시놀로지 DSM에 접속한 후 제어판의 터미널 및 SNMP 설정에서 SSH 포트를 활성화할 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;510&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cGUqZq/btruc55LgiE/P62ydW6PhWLnEOTxokHZik/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cGUqZq/btruc55LgiE/P62ydW6PhWLnEOTxokHZik/img.webp&quot; data-alt=&quot;SSH 서비스 활성화하기&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cGUqZq/btruc55LgiE/P62ydW6PhWLnEOTxokHZik/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcGUqZq%2Fbtruc55LgiE%2FP62ydW6PhWLnEOTxokHZik%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; alt=&quot;SSH 서비스 활성화하기&quot; loading=&quot;lazy&quot; width=&quot;800&quot; height=&quot;510&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;510&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;SSH 서비스 활성화하기&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;PuTTY로 접근하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 PuTTY부터 다운로드합니다. 아래 PuTTY 공식 홈페이지에 접속하여 설치형 또는 실행형 파일을 OS 버전에 맞게 준비합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.chiark.greenend.org.uk/~sgtatham/putty/latest.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://www.chiark.greenend.org.uk/~sgtatham/putty/latest.html&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1644756348139&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;Download PuTTY: latest release (0.76)&quot; data-og-description=&quot;This page contains download links for the latest released version of PuTTY. Currently this is 0.76, released on 2021-07-17. When new releases come out, this page will update to contain the latest, so this is a good page to bookmark or link to. Alternativel&quot; data-og-host=&quot;www.chiark.greenend.org.uk&quot; data-og-source-url=&quot;https://www.chiark.greenend.org.uk/~sgtatham/putty/latest.html&quot; data-og-url=&quot;https://www.chiark.greenend.org.uk/~sgtatham/putty/latest.html&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://www.chiark.greenend.org.uk/~sgtatham/putty/latest.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.chiark.greenend.org.uk/~sgtatham/putty/latest.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;Download PuTTY: latest release (0.76)&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;This page contains download links for the latest released version of PuTTY. Currently this is 0.76, released on 2021-07-17. When new releases come out, this page will update to contain the latest, so this is a good page to bookmark or link to. Alternativel&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.chiark.greenend.org.uk&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PuTTY를 실행하면 다음과 같이 화면이 표시됩니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;714&quot; data-origin-height=&quot;699&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/LCQs5/btruc7P1SJN/jkjhsVv5cxTMeUOH7fhJgK/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/LCQs5/btruc7P1SJN/jkjhsVv5cxTMeUOH7fhJgK/img.webp&quot; data-alt=&quot;PuTTY 실행 화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/LCQs5/btruc7P1SJN/jkjhsVv5cxTMeUOH7fhJgK/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FLCQs5%2Fbtruc7P1SJN%2FjkjhsVv5cxTMeUOH7fhJgK%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; alt=&quot;PuTTY 실행 화면&quot; loading=&quot;lazy&quot; width=&quot;714&quot; height=&quot;699&quot; data-origin-width=&quot;714&quot; data-origin-height=&quot;699&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;PuTTY 실행 화면&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 80px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style12&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 50%; text-align: center; height: 20px;&quot;&gt;&lt;b&gt;항목&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 50%; text-align: center; height: 20px;&quot;&gt;&lt;b&gt;설명&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;Host Name(or IP address)&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;사이트 주소 또는 IP 주소를 입력합니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;Port&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;포트 번호를 입력합니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;Connection type&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;연결 타입을 선택합니다. 본문에서는 SSH를 선택합니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Host Name&lt;/b&gt;과 &lt;b&gt;Port&lt;/b&gt;를 입력한 뒤 &lt;b&gt;Open 버튼을 클릭&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;598&quot; data-origin-height=&quot;381&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eJeLQb/btrt9TZAB8C/DhmWshrRd7FBES2OhsA2M0/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eJeLQb/btrt9TZAB8C/DhmWshrRd7FBES2OhsA2M0/img.webp&quot; data-alt=&quot;시놀로지 로그인 정보 입력 화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eJeLQb/btrt9TZAB8C/DhmWshrRd7FBES2OhsA2M0/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FeJeLQb%2Fbtrt9TZAB8C%2FDhmWshrRd7FBES2OhsA2M0%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; alt=&quot;시놀로지 로그인 정보 입력 화면&quot; loading=&quot;lazy&quot; width=&quot;598&quot; height=&quot;381&quot; data-origin-width=&quot;598&quot; data-origin-height=&quot;381&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;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;523&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/suwwm/btruc6p2Zyq/9JeUaahDgSuPzQE4KbZUA0/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/suwwm/btruc6p2Zyq/9JeUaahDgSuPzQE4KbZUA0/img.webp&quot; data-alt=&quot;공유기의 SSH 포트 포트포워드 설정 예시&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/suwwm/btruc6p2Zyq/9JeUaahDgSuPzQE4KbZUA0/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fsuwwm%2Fbtruc6p2Zyq%2F9JeUaahDgSuPzQE4KbZUA0%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; alt=&quot;공유기의 SSH 포트 포트포워드 설정 예시&quot; loading=&quot;lazy&quot; width=&quot;800&quot; height=&quot;523&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;523&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;공유기의 SSH 포트 포트포워드 설정 예시&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음 콘솔 창에 &lt;i&gt;&lt;b&gt;login as:&lt;/b&gt;&lt;/i&gt; 문구가 표시되면 &lt;b&gt;관리자 아이디&lt;/b&gt;를 입력하고 &lt;i&gt;&lt;b&gt;Enter&lt;/b&gt;&lt;/i&gt; 키를 누릅니다. 그리고 &lt;b&gt;비밀번호&lt;/b&gt;를 입력한 다음 &lt;b&gt;root 권한&lt;/b&gt;을 얻기 위해 아래의 명령어를 입력합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1645618200508&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sudo --login&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후 다시 한번 &lt;b&gt;비밀번호&lt;/b&gt;를 입력한 후 &lt;i&gt;&lt;b&gt;root@...&lt;/b&gt;&lt;/i&gt;로 표시되면 정상적으로 root 권한을 얻은 것입니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;598&quot; data-origin-height=&quot;381&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/QsW5t/btrt6uGgGZV/QcZKaXe55PNHICTNyUge7K/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/QsW5t/btrt6uGgGZV/QcZKaXe55PNHICTNyUge7K/img.webp&quot; data-alt=&quot;root 권한을 얻기 위한 과정&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/QsW5t/btrt6uGgGZV/QcZKaXe55PNHICTNyUge7K/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FQsW5t%2Fbtrt6uGgGZV%2FQcZKaXe55PNHICTNyUge7K%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; alt=&quot;root 권한을 얻기 위한 과정&quot; loading=&quot;lazy&quot; width=&quot;598&quot; height=&quot;381&quot; data-origin-width=&quot;598&quot; data-origin-height=&quot;381&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;root 권한을 얻기 위한 과정&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후 도커 컨테이너라든가 레드마인 관련하여 설치, 삭제 등이 가능해집니다.&lt;/p&gt;</description>
      <category>Computer/NAS</category>
      <category>Nas</category>
      <category>synology</category>
      <author>❤ </author>
      <guid isPermaLink="true">https://luckygg.tistory.com/363</guid>
      <comments>https://luckygg.tistory.com/363#entry363comment</comments>
      <pubDate>Wed, 23 Feb 2022 21:15:16 +0900</pubDate>
    </item>
    <item>
      <title>[ASP.NET] C# Windows Docker 용 작업자 서비스 만드는 방법</title>
      <link>https://luckygg.tistory.com/361</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;Windows Docker 작업자 서비스&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;ASP.NET Core&lt;/span&gt;&lt;/code&gt;는 Windows, macOS 및 Linux에서 인터넷 연결 앱을 동작할 수 있는 프레임 워크입니다. 간단히 설명하면 제가 원하는 동작을 수행하는 코드를 빌드하고 그 결과물을 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;ASP.NET Core&lt;/span&gt;&lt;/code&gt;를 통해 서비스를 동작할 수 있다는 것입니다.&lt;br /&gt;&lt;br /&gt;게다가 Visual Studio에서 제작 가능한 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;ASP.NET Core Worker Service(작업자 서비스)&lt;/span&gt;&lt;/code&gt; &lt;b&gt;템플릿&lt;/b&gt;은 장기간 실행되는 서비스 앱을 개발하기 위해 제공됩니다. 즉, 서버에서 멈추지 않고 계속해서 돌릴 서비스를 제작하기 위한 프로젝트라는 것이죠.&lt;br /&gt;&lt;br /&gt;이번 포스팅에서는 작업자 서비스를 빌드하고 Windows Docker에서 동작시키는 과정을 설명하겠습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Windows Docker 준비하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선 Windows Docker를 먼저 설치합니다. Windows 10에 Docker를 설치하는 방법은 아래 링크를 참고합니다. 현재 홈페이지에서 제공되는 버전과 포스팅에 기재된 버전과 차이는 있지만, 최신 버전으로 동일하게 따라 해도 문제가 없습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://luckygg.tistory.com/165&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;[Docker] Windows 10 Docker Desktop 설치 방법&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1644734993000&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;[Docker] Windows 10 Docker Desktop 설치 방법&quot; data-og-description=&quot;제 블로그에는 레드마인에 관한 내용이 많이 기재되어 있습니다. Windows Redmine 과 Synology NAS Docker Redmine 두 가지로 되어있는데요. 이번에 소개할 내용은 Windows 용 Docker Redmine 설치 방법입니다...&quot; data-og-host=&quot;luckygg.tistory.com&quot; data-og-source-url=&quot;https://luckygg.tistory.com/165&quot; data-og-url=&quot;https://luckygg.tistory.com/165&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/byJJZx/hyNnS8waKZ/N6kGtayz7ZOK3PKLIbpH91/img.png?width=362&amp;amp;height=329&amp;amp;face=0_0_362_329,https://scrap.kakaocdn.net/dn/hqbdj/hyNnW4aNRQ/KMARHaJ36i6XX6mnqjtbz0/img.png?width=362&amp;amp;height=329&amp;amp;face=0_0_362_329,https://scrap.kakaocdn.net/dn/bs7Zpx/hyNpeITN0R/bfuqZlYGqbAKYaHBVBzdG1/img.png?width=860&amp;amp;height=619&amp;amp;face=0_0_860_619&quot;&gt;&lt;a href=&quot;https://luckygg.tistory.com/165&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://luckygg.tistory.com/165&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/byJJZx/hyNnS8waKZ/N6kGtayz7ZOK3PKLIbpH91/img.png?width=362&amp;amp;height=329&amp;amp;face=0_0_362_329,https://scrap.kakaocdn.net/dn/hqbdj/hyNnW4aNRQ/KMARHaJ36i6XX6mnqjtbz0/img.png?width=362&amp;amp;height=329&amp;amp;face=0_0_362_329,https://scrap.kakaocdn.net/dn/bs7Zpx/hyNpeITN0R/bfuqZlYGqbAKYaHBVBzdG1/img.png?width=860&amp;amp;height=619&amp;amp;face=0_0_860_619');&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;[Docker] Windows 10 Docker Desktop 설치 방법&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;제 블로그에는 레드마인에 관한 내용이 많이 기재되어 있습니다. Windows Redmine 과 Synology NAS Docker Redmine 두 가지로 되어있는데요. 이번에 소개할 내용은 Windows 용 Docker Redmine 설치 방법입니다...&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;luckygg.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;
&lt;script src=&quot;https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-3156423405867571&quot;&gt;&lt;/script&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;script&gt;
     (adsbygoogle = window.adsbygoogle || []).push({});
&lt;/script&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;작업자 서비스 빌드하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Visual Studio 2019&lt;/b&gt;에서 작업자 서비스 프로젝트를 빌드하고 결과를 확인하는 방법을 설명합니다.&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Visual Studio에서 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;작업자 서비스 템플릿&lt;/span&gt;&lt;/code&gt;을 선택하고 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;ExamWorkerService&lt;/span&gt;&lt;/code&gt; 이름으로 프로젝트를 생성합니다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;533&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qoDqX/btrteh7ay4t/PDoU1raEKCl2qrcmVJSIU1/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qoDqX/btrteh7ay4t/PDoU1raEKCl2qrcmVJSIU1/img.webp&quot; data-alt=&quot;작업자 서비스 템플릿 선택&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qoDqX/btrteh7ay4t/PDoU1raEKCl2qrcmVJSIU1/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqoDqX%2Fbtrteh7ay4t%2FPDoU1raEKCl2qrcmVJSIU1%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; alt=&quot;작업자 서비스 템플릿 선택&quot; loading=&quot;lazy&quot; width=&quot;800&quot; height=&quot;533&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;533&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;작업자 서비스 템플릿 선택&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;대상 프레임워크&lt;/b&gt;는 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;.NET 5.0&lt;/span&gt;&lt;/code&gt;을 선택하고 &lt;b&gt;Docker 사용 체크&lt;/b&gt; 및 &lt;b&gt;Windows&lt;/b&gt;를 선택합니다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;533&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/CG7yp/btrs7ngZvTN/rvk8usOyADRrjsMBkKavFK/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/CG7yp/btrs7ngZvTN/rvk8usOyADRrjsMBkKavFK/img.webp&quot; data-alt=&quot;대상 프레임워크 및 Docker OS 선택&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/CG7yp/btrs7ngZvTN/rvk8usOyADRrjsMBkKavFK/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FCG7yp%2Fbtrs7ngZvTN%2Frvk8usOyADRrjsMBkKavFK%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; alt=&quot;대상 프레임워크 및 Docker OS 선택&quot; loading=&quot;lazy&quot; width=&quot;800&quot; height=&quot;533&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;533&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;대상 프레임워크 및 Docker OS 선택&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;프로젝트를 생성하면 다음과 같은 기본 코드가 구현되어 있습니다. 1초마다 &lt;b&gt;Worker running at: 시간&lt;/b&gt; 메시지가 출력되는 동작입니다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;643&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cqsQXp/btrtgrVYo5J/LfwUfjA5lEMBKm337w6In0/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cqsQXp/btrtgrVYo5J/LfwUfjA5lEMBKm337w6In0/img.webp&quot; data-alt=&quot;기본으로 제공되는 코드&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cqsQXp/btrtgrVYo5J/LfwUfjA5lEMBKm337w6In0/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcqsQXp%2FbtrtgrVYo5J%2FLfwUfjA5lEMBKm337w6In0%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; alt=&quot;기본으로 제공되는 코드&quot; loading=&quot;lazy&quot; width=&quot;800&quot; height=&quot;643&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;643&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;기본으로 제공되는 코드&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;솔루션 탐색기에서 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;Dockerfile&lt;/span&gt;&lt;/code&gt;을 선택하면, 기본으로 아래의 내용이 작성되어 있는 것을 확인할 수 있습니다. 추후 이 &lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;Dockerfile&lt;/span&gt;&lt;/code&gt;을 상위 경로로 복사할 겁니다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;367&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/d64V6R/btrs8A7Le0t/YLmsrkyQK6ihdfg80Jq6a0/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/d64V6R/btrs8A7Le0t/YLmsrkyQK6ihdfg80Jq6a0/img.webp&quot; data-alt=&quot;Dockerfile 기본 내용&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/d64V6R/btrs8A7Le0t/YLmsrkyQK6ihdfg80Jq6a0/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fd64V6R%2Fbtrs8A7Le0t%2FYLmsrkyQK6ihdfg80Jq6a0%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; alt=&quot;Dockerfile 기본 내용&quot; loading=&quot;lazy&quot; width=&quot;800&quot; height=&quot;367&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;367&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Dockerfile 기본 내용&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;이제 프로젝트 파일의 마우스 우측 메뉴에서&lt;span&gt; &lt;/span&gt;&lt;b&gt;게시&lt;/b&gt;&lt;span&gt; &lt;/span&gt;메뉴를 클릭합니다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;662&quot; data-origin-height=&quot;497&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/2znvB/btrtejjBFy3/Alc4Cd205XYVvM8sQeuvpK/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/2znvB/btrtejjBFy3/Alc4Cd205XYVvM8sQeuvpK/img.webp&quot; data-alt=&quot;프로젝트 파일의 게시 메뉴 클릭&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/2znvB/btrtejjBFy3/Alc4Cd205XYVvM8sQeuvpK/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F2znvB%2FbtrtejjBFy3%2FAlc4Cd205XYVvM8sQeuvpK%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; alt=&quot;프로젝트 파일의 게시 메뉴 클릭&quot; loading=&quot;lazy&quot; width=&quot;662&quot; height=&quot;497&quot; data-origin-width=&quot;662&quot; data-origin-height=&quot;497&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;프로젝트 파일의 게시 메뉴 클릭&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;게시 메뉴에서&lt;span&gt; &lt;/span&gt;&lt;b&gt;폴더&lt;/b&gt;를 선택하고 다음 버튼을 클릭합니다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;564&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b0pHAN/btrs7mCnrkt/DYMOlij95p91r7QJ6uESek/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b0pHAN/btrs7mCnrkt/DYMOlij95p91r7QJ6uESek/img.webp&quot; data-alt=&quot;게시 메뉴의 폴더 선택&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b0pHAN/btrs7mCnrkt/DYMOlij95p91r7QJ6uESek/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb0pHAN%2Fbtrs7mCnrkt%2FDYMOlij95p91r7QJ6uESek%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; alt=&quot;게시 메뉴의 폴더 선택&quot; loading=&quot;lazy&quot; width=&quot;800&quot; height=&quot;564&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;564&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;게시 메뉴의 폴더 선택&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;폴더 위치&lt;/b&gt;는 변경해도 상관없습니다. 게시할 파일이 생성되는 위치를 지정하는 옵션입니다. 폴더 위치 지정 후&lt;span&gt; &lt;/span&gt;&lt;b&gt;마침&lt;/b&gt;&lt;span&gt; &lt;/span&gt;버튼을 클릭합니다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;563&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cOo29E/btrtb14AqNR/1ec4korz1i5jgAH60yGUc1/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cOo29E/btrtb14AqNR/1ec4korz1i5jgAH60yGUc1/img.webp&quot; data-alt=&quot;폴더 위치 지정하기&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cOo29E/btrtb14AqNR/1ec4korz1i5jgAH60yGUc1/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcOo29E%2Fbtrtb14AqNR%2F1ec4korz1i5jgAH60yGUc1%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; alt=&quot;폴더 위치 지정하기&quot; loading=&quot;lazy&quot; width=&quot;800&quot; height=&quot;563&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;563&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;폴더 위치 지정하기&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;게시 옵션 지정이 완료됐습니다. 상단의 게시 버튼을 클릭하면 지정한 폴더에 빌드된 파일이 생성됩니다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;313&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/7Swlm/btrs66meWnz/xcswnsKn8s6SKOGY4HmSQ0/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/7Swlm/btrs66meWnz/xcswnsKn8s6SKOGY4HmSQ0/img.webp&quot; data-alt=&quot;프로젝트 게시하기&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/7Swlm/btrs66meWnz/xcswnsKn8s6SKOGY4HmSQ0/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F7Swlm%2Fbtrs66meWnz%2FxcswnsKn8s6SKOGY4HmSQ0%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; alt=&quot;프로젝트 게시하기&quot; loading=&quot;lazy&quot; width=&quot;800&quot; height=&quot;313&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;313&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;프로젝트 게시하기&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;지정된 폴더에 가보면 생성된 파일이 여럿 있습니다. 그리고 ExamWorkerService.exe를 찾을 수 있는데요.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;617&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xuwfO/btrtb3H52LW/m6SFymattYFkWYU4wz0Yck/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xuwfO/btrtb3H52LW/m6SFymattYFkWYU4wz0Yck/img.webp&quot; data-alt=&quot;빌드된 파일들&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xuwfO/btrtb3H52LW/m6SFymattYFkWYU4wz0Yck/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxuwfO%2Fbtrtb3H52LW%2Fm6SFymattYFkWYU4wz0Yck%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; alt=&quot;빌드된 파일들&quot; loading=&quot;lazy&quot; width=&quot;800&quot; height=&quot;617&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;617&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;빌드된 파일들&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;파일을 실행해 보면 아래와 같이 1초마다 현재 시간을 계속해서 출력합니다. 처음 프로젝트를 생성했을 때 구현되어 있던 예제 코드가 동작하는 것이죠.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;420&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/beFyTL/btrtejKG8sS/nCiRtgKv3hKMkUnNbZjI30/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/beFyTL/btrtejKG8sS/nCiRtgKv3hKMkUnNbZjI30/img.webp&quot; data-alt=&quot;작업자 서비스 동작 화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/beFyTL/btrtejKG8sS/nCiRtgKv3hKMkUnNbZjI30/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbeFyTL%2FbtrtejKG8sS%2FnCiRtgKv3hKMkUnNbZjI30%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; alt=&quot;작업자 서비스 동작 화면&quot; loading=&quot;lazy&quot; width=&quot;800&quot; height=&quot;420&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;420&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;작업자 서비스 동작 화면&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;이제 이 서비스를 Windows Docker에서 돌려보겠습니다.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Windows Docker에 작업자 서비스 설치하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 Windows Docker에 작업자 서비스를 설치하고 실행해 보겠습니다.&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선 프로젝트 상위 경로로 이동하여 앞에서 확인했던 Dockerfile을 복사합니다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;616&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/BkI83/btrtb23uMUF/sVwLim2MSLKP9KATKm8tzK/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/BkI83/btrtb23uMUF/sVwLim2MSLKP9KATKm8tzK/img.webp&quot; data-alt=&quot;프로젝트 상위 경로에 Dockerfile 복사하여 붙여넣기&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/BkI83/btrtb23uMUF/sVwLim2MSLKP9KATKm8tzK/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FBkI83%2Fbtrtb23uMUF%2FsVwLim2MSLKP9KATKm8tzK%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; alt=&quot;프로젝트 상위 경로에 Dockerfile 복사하여 붙여넣기&quot; loading=&quot;lazy&quot; width=&quot;800&quot; height=&quot;616&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;616&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;프로젝트 상위 경로에 Dockerfile 복사하여 붙여넣기&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;명령 프롬프트를 실행하고 위 경로로 이동합니다. 저는 바탕화면에 프로젝트가 있으므로, 명령어는 다음과 같습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1644738083972&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;cd C:\Users\Gg\Desktop\ExamWorkerService&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 Docker 빌드를 위한 명령어는 다음과 같습니다. 마지막의 myservice는 서비스 이름이므로, 짓고 싶은 대로 지어도 상관없습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1644738122709&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;docekr build . -t myservice&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 명령어를 실행하면 도커에 서비스 설치가 시작됩니다. 아래와 같은 메시지가 표시됐다면 정상적으로 설치가 완료된 것입니다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;845&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/blRN9P/btrtei523Vw/FQqBRcjvaxrkvLD6Zlm17K/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/blRN9P/btrtei523Vw/FQqBRcjvaxrkvLD6Zlm17K/img.webp&quot; data-alt=&quot;도커 서비스가 정상적으로 설치된 모습&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/blRN9P/btrtei523Vw/FQqBRcjvaxrkvLD6Zlm17K/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FblRN9P%2Fbtrtei523Vw%2FFQqBRcjvaxrkvLD6Zlm17K%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; alt=&quot;도커 서비스가 정상적으로 설치된 모습&quot; loading=&quot;lazy&quot; width=&quot;800&quot; height=&quot;845&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;845&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;도커 서비스가 정상적으로 설치된 모습&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;Windows Docker를 실행하면 Images에 &lt;code&gt;&lt;span class=&quot;token function-name&quot;&gt;myservice&lt;/span&gt;&lt;/code&gt;가 보이기 시작합니다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;456&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bmKB85/btrs715DfxL/ChgU8EggNqRCke9O0ss8Kk/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bmKB85/btrs715DfxL/ChgU8EggNqRCke9O0ss8Kk/img.webp&quot; data-alt=&quot;Docker 이미지 목록&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bmKB85/btrs715DfxL/ChgU8EggNqRCke9O0ss8Kk/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbmKB85%2Fbtrs715DfxL%2FChgU8EggNqRCke9O0ss8Kk%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; alt=&quot;Docker 이미지 목록&quot; loading=&quot;lazy&quot; width=&quot;800&quot; height=&quot;456&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;456&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Docker 이미지 목록&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;&lt;span class=&quot;token function-name&quot;&gt;myservice&lt;/span&gt;&lt;/code&gt; 항목을 클릭하면 우측에 &lt;b&gt;RUN 버튼&lt;/b&gt;이 표시됩니다. 버튼을 클릭하면 옵션 설정 창이 표시되는데요. 여기서도 별도 지정 없이 &lt;b&gt;Run 버튼&lt;/b&gt;을 클릭합니다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;456&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Hhm6P/btrs7l4z9DJ/ExY0NuUKUFe8tlLP29D9ik/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Hhm6P/btrs7l4z9DJ/ExY0NuUKUFe8tlLP29D9ik/img.webp&quot; data-alt=&quot;myservice 동작하기&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Hhm6P/btrs7l4z9DJ/ExY0NuUKUFe8tlLP29D9ik/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FHhm6P%2Fbtrs7l4z9DJ%2FExY0NuUKUFe8tlLP29D9ik%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; alt=&quot;myservice 동작하기&quot; loading=&quot;lazy&quot; width=&quot;800&quot; height=&quot;456&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;456&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;myservice 동작하기&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;아래 화면은 컨테이너 목록을 보여줍니다. 방금 실행된 컨테이너 이름을 클릭합니다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;457&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b97wKL/btrtakpOauZ/3RvRvng4zoKmEtVVTPbKN1/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b97wKL/btrtakpOauZ/3RvRvng4zoKmEtVVTPbKN1/img.webp&quot; data-alt=&quot;실행 중인 컨테이너 목록&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b97wKL/btrtakpOauZ/3RvRvng4zoKmEtVVTPbKN1/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb97wKL%2FbtrtakpOauZ%2F3RvRvng4zoKmEtVVTPbKN1%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; alt=&quot;실행 중인 컨테이너 목록&quot; loading=&quot;lazy&quot; width=&quot;800&quot; height=&quot;457&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;457&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;실행 중인 컨테이너 목록&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;앞에 과정에서 봤던 1초 간격 로그 출력 메시지가 보입니다. 정상적으로 도커에서 서비스로 동작한다는 것을 의미합니다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;456&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ZNpPK/btrteiZhZRq/5AWqsiUXQnr0nhQ8MxRAb0/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ZNpPK/btrteiZhZRq/5AWqsiUXQnr0nhQ8MxRAb0/img.webp&quot; data-alt=&quot;도커에서의 동작 확인&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ZNpPK/btrteiZhZRq/5AWqsiUXQnr0nhQ8MxRAb0/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FZNpPK%2FbtrteiZhZRq%2F5AWqsiUXQnr0nhQ8MxRAb0%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; alt=&quot;도커에서의 동작 확인&quot; loading=&quot;lazy&quot; width=&quot;800&quot; height=&quot;456&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;456&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;도커에서의 동작 확인&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;정리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라 해 보니 아주 간단하죠? 저는 시놀로지 서버의 Docker에서 서비스를 구동하기 전에 테스트를 위해 Windows Docker에서 이렇게 확인하고 있습니다. Windows는 컴퓨터를 끄면 Docker가 종료되므로 서비스가 멈춰버리니 테스트 및 디버그 용으로 사용하고, 시놀로지 서버는 계속 동작하므로 릴리즈 용으로 사용하는 것이죠.&lt;/p&gt;</description>
      <category>Programming/.Net</category>
      <category>ASP.NET</category>
      <author>❤ </author>
      <guid isPermaLink="true">https://luckygg.tistory.com/361</guid>
      <comments>https://luckygg.tistory.com/361#entry361comment</comments>
      <pubDate>Tue, 15 Feb 2022 18:03:01 +0900</pubDate>
    </item>
    <item>
      <title>[챗봇/.NET] C#에서 시놀로지 Chat에 챗봇 메시지 보내기(예제 포함)</title>
      <link>https://luckygg.tistory.com/359</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;시놀로지 Chat 메신저&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시놀로지에는 &lt;b&gt;Chat이라는 메신저&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;설문조사, 전달, 알림, 메시지 예약, 파일 전송 기능&lt;/li&gt;
&lt;li&gt;공개, 비공개 대화방&lt;/li&gt;
&lt;li&gt;파일 전송&lt;/li&gt;
&lt;li&gt;윈도우, 모바일 앱 지원&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;즉, 카카오톡과 같은 메신저라고 보면 되겠습니다. 물론, 모두가 Chat을 사용하지는 않겠죠. 그래서 저의 경우에는 사내 메신저(업무용)로 활용하고 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;518&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bQiZ0f/btrssDSyp6r/M6c4H6mVsAxVfNOaYxaemk/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bQiZ0f/btrssDSyp6r/M6c4H6mVsAxVfNOaYxaemk/img.webp&quot; data-alt=&quot;시놀로지 챗 PC 화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bQiZ0f/btrssDSyp6r/M6c4H6mVsAxVfNOaYxaemk/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbQiZ0f%2FbtrssDSyp6r%2FM6c4H6mVsAxVfNOaYxaemk%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; alt=&quot;시놀로지 챗 PC 화면&quot; loading=&quot;lazy&quot; width=&quot;800&quot; height=&quot;518&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;518&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;시놀로지 챗 PC 화면&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;시놀로지 Chat Webhook 기능&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시놀로지 챗은 &lt;b&gt;수신, 발신 Webhook&lt;/b&gt;이라는 기능을 제공하고 있습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;수신 Webhook&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;수신 Webhook은 외부에서 Chat으로 메시지를 보낼 수 있습니다. 즉, &lt;b&gt;외부 인터넷에서 시놀로지 Chat으로 메시지&lt;/b&gt;를 보낼 수 있다는 의미죠. 메시지에는 텍스트와 링크 그리고 파일 업로드도 가능합니다. 파일 업로드의 경우 최대 크기는 32MB입니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;605&quot; data-origin-height=&quot;642&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nEMeD/btrsxhATE1W/0t6lflhcy78SMfaTyxCPVK/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nEMeD/btrsxhATE1W/0t6lflhcy78SMfaTyxCPVK/img.webp&quot; data-alt=&quot;수신 Webhook 설정 화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nEMeD/btrsxhATE1W/0t6lflhcy78SMfaTyxCPVK/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FnEMeD%2FbtrsxhATE1W%2F0t6lflhcy78SMfaTyxCPVK%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; alt=&quot;수신 Webhook 설정 화면&quot; loading=&quot;lazy&quot; width=&quot;605&quot; height=&quot;642&quot; data-origin-width=&quot;605&quot; data-origin-height=&quot;642&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;수신 Webhook 설정 화면&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;발신 Webhook&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;발신 Webhook은 Chat 메시지를 트리거 단어로 수신 대기합니다. 즉, 챗에 &lt;b&gt;특정 단어를 입력하면 트리거 신호로 인식하여 관련 데이터를 외부 URL&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;606&quot; data-origin-height=&quot;643&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/QmLAK/btrsA7jK4I3/BY8ADkPXSdVCSb6lpwwLB1/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/QmLAK/btrsA7jK4I3/BY8ADkPXSdVCSb6lpwwLB1/img.webp&quot; data-alt=&quot;발신 Webhook 설정 화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/QmLAK/btrsA7jK4I3/BY8ADkPXSdVCSb6lpwwLB1/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FQmLAK%2FbtrsA7jK4I3%2FBY8ADkPXSdVCSb6lpwwLB1%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; alt=&quot;발신 Webhook 설정 화면&quot; loading=&quot;lazy&quot; width=&quot;606&quot; height=&quot;643&quot; data-origin-width=&quot;606&quot; data-origin-height=&quot;643&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;발신 Webhook 설정 화면&lt;/figcaption&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;&lt;a href=&quot;https://kb.synology.com/ko-kr/DSM/help/Chat/chat_integration?version=6&quot;&gt;https://kb.synology.com/ko-kr/DSM/help/Chat/chat_integration?version=6&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1644069654022&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;Synology Chat에서 통합 사용 | Synology Chat - Synology 지식 센터&quot; data-og-description=&quot;&quot; data-og-host=&quot;kb.synology.com&quot; data-og-source-url=&quot;https://kb.synology.com/ko-kr/DSM/help/Chat/chat_integration?version=6&quot; data-og-url=&quot;https://kb.synology.com/ko-kr/DSM/help/Chat/chat_integration?version=6&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://kb.synology.com/ko-kr/DSM/help/Chat/chat_integration?version=6&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://kb.synology.com/ko-kr/DSM/help/Chat/chat_integration?version=6&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;Synology Chat에서 통합 사용 | Synology Chat - Synology 지식 센터&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;kb.synology.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Webhook 설정 방법&lt;/h2&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;800&quot; data-origin-height=&quot;518&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/zVhAs/btrsvdMwlhr/X2dyoppJQZEHSBTEIZktc0/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/zVhAs/btrsvdMwlhr/X2dyoppJQZEHSBTEIZktc0/img.webp&quot; data-alt=&quot;프로필 클릭&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/zVhAs/btrsvdMwlhr/X2dyoppJQZEHSBTEIZktc0/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FzVhAs%2FbtrsvdMwlhr%2FX2dyoppJQZEHSBTEIZktc0%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; alt=&quot;프로필 클릭&quot; loading=&quot;lazy&quot; width=&quot;800&quot; height=&quot;518&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;518&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;통합&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;460&quot; data-origin-height=&quot;496&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b5x3xz/btrsyshFK5j/gmYO6wl3Whg5l7GXTEnpM0/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b5x3xz/btrsyshFK5j/gmYO6wl3Whg5l7GXTEnpM0/img.webp&quot; data-alt=&quot;통합 메뉴 클릭&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b5x3xz/btrsyshFK5j/gmYO6wl3Whg5l7GXTEnpM0/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb5x3xz%2FbtrsyshFK5j%2FgmYO6wl3Whg5l7GXTEnpM0%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; alt=&quot;통합 메뉴 클릭&quot; loading=&quot;lazy&quot; width=&quot;460&quot; height=&quot;496&quot; data-origin-width=&quot;460&quot; data-origin-height=&quot;496&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;들어오는 Webhooks&lt;/b&gt;를 선택합니다. 본문에서는 &lt;b&gt;나가는 Webhooks&lt;/b&gt;으로 테스트할 조건이 안되기 때문에 들어오는 Webhooks만 다룹니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;590&quot; data-origin-height=&quot;629&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/sFZx5/btrssCeZCn5/oT5kH1us7tSKzxatgy8go0/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/sFZx5/btrssCeZCn5/oT5kH1us7tSKzxatgy8go0/img.webp&quot; data-alt=&quot;들어오는 Webhooks 메뉴 클릭&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/sFZx5/btrssCeZCn5/oT5kH1us7tSKzxatgy8go0/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FsFZx5%2FbtrssCeZCn5%2FoT5kH1us7tSKzxatgy8go0%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; alt=&quot;들어오는 Webhooks 메뉴 클릭&quot; loading=&quot;lazy&quot; width=&quot;590&quot; height=&quot;629&quot; data-origin-width=&quot;590&quot; data-origin-height=&quot;629&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;들어오는 Webhooks 메뉴 클릭&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;들어오는 Webhooks 화면에서 생성 버튼을 클릭합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;589&quot; data-origin-height=&quot;619&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cQXj8a/btrsA7c0rAM/luYeFjWebkazso6CGA1Zfk/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cQXj8a/btrsA7c0rAM/luYeFjWebkazso6CGA1Zfk/img.webp&quot; data-alt=&quot;생성 버튼 클릭&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cQXj8a/btrsA7c0rAM/luYeFjWebkazso6CGA1Zfk/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcQXj8a%2FbtrsA7c0rAM%2FluYeFjWebkazso6CGA1Zfk%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; alt=&quot;생성 버튼 클릭&quot; loading=&quot;lazy&quot; width=&quot;589&quot; height=&quot;619&quot; data-origin-width=&quot;589&quot; data-origin-height=&quot;619&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;프로필 사진, 이름, 채널을 선택하고 Webhook URL을 복사해 둡니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;590&quot; data-origin-height=&quot;623&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ckzEvv/btrsA7c0rBJ/dba0Nh36eS9j0H8EuVKKkk/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ckzEvv/btrsA7c0rBJ/dba0Nh36eS9j0H8EuVKKkk/img.webp&quot; data-alt=&quot;수신 Webhook 설정 예시 화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ckzEvv/btrsA7c0rBJ/dba0Nh36eS9j0H8EuVKKkk/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FckzEvv%2FbtrsA7c0rBJ%2Fdba0Nh36eS9j0H8EuVKKkk%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; alt=&quot;수신 Webhook 설정 예시 화면&quot; loading=&quot;lazy&quot; width=&quot;590&quot; height=&quot;623&quot; data-origin-width=&quot;590&quot; data-origin-height=&quot;623&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;수신 Webhook 설정 예시 화면&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;C#에서 수신 Webhook으로 메시지 보내기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;ExamChatWebhook&lt;/b&gt; 이름으로 &lt;b&gt;Windows Forms 앱&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;800&quot; data-origin-height=&quot;556&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eWk5GH/btrsytnlivf/Qqe34irb7HmBwmO4vBkYnK/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eWk5GH/btrsytnlivf/Qqe34irb7HmBwmO4vBkYnK/img.webp&quot; data-alt=&quot;Windows Forms 프로젝트 생성&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eWk5GH/btrsytnlivf/Qqe34irb7HmBwmO4vBkYnK/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FeWk5GH%2Fbtrsytnlivf%2FQqe34irb7HmBwmO4vBkYnK%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; alt=&quot;Windows Forms 프로젝트 생성&quot; loading=&quot;lazy&quot; width=&quot;800&quot; height=&quot;556&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;556&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Windows Forms 프로젝트 생성&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;UI에 버튼을 하나 배치하고 코드는 다음과 같이 작성합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1644069464652&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Net;
using System.IO;

namespace ExamChatWebhook
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void buttonSendMessage_Click(object sender, EventArgs e)
        {
            //수신 Webhook url
            string webhookUrl = &quot;&quot;;
            string payload = &quot;&amp;amp;payload={\&quot;text\&quot;: \&quot;LuckyGg의 메시지, https://luckygg.tistory.com\&quot;}&quot;;

            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(webhookUrl + payload);
            request.Method = &quot;GET&quot;;
            using (var response = request.GetResponse())
            {
                using (Stream dataStream = response.GetResponseStream())
                {
                    using (var reader = new StreamReader(dataStream))
                    {
                        string requestResult = reader.ReadToEnd();
                    }
                }
            }
        }
    }
}&lt;/code&gt;&lt;/pre&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;780&quot; data-origin-height=&quot;265&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bF0xW8/btrsA57krrR/ax2U3GKkk9ZBgjapKWKWtK/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bF0xW8/btrsA57krrR/ax2U3GKkk9ZBgjapKWKWtK/img.webp&quot; data-alt=&quot;챗으로 수신된 메시지&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bF0xW8/btrsA57krrR/ax2U3GKkk9ZBgjapKWKWtK/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbF0xW8%2FbtrsA57krrR%2Fax2U3GKkk9ZBgjapKWKWtK%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; alt=&quot;챗으로 수신된 메시지&quot; loading=&quot;lazy&quot; width=&quot;780&quot; height=&quot;265&quot; data-origin-width=&quot;780&quot; data-origin-height=&quot;265&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;/p&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/ncttP/btrssvGmoyh/jUuDu8k4AiH8EAHVzkxbP1/ExamChatWebhook.zip?attach=1&amp;amp;knm=tfile.zip&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;ExamChatWebhook.zip&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;size&quot;&gt;0.01MB&lt;/div&gt;
&lt;/div&gt;
  &lt;/a&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>Programming/ChatBot</category>
      <category>.net</category>
      <category>챗봇</category>
      <author>❤ </author>
      <guid isPermaLink="true">https://luckygg.tistory.com/359</guid>
      <comments>https://luckygg.tistory.com/359#entry359comment</comments>
      <pubDate>Sun, 13 Feb 2022 11:03:09 +0900</pubDate>
    </item>
  </channel>
</rss>