<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>Simplify</title>
    <link>https://4urdev.tistory.com/</link>
    <description>javascript, HTML5, node.js, java, android, c++, Qt, QML</description>
    <language>ko</language>
    <pubDate>Sat, 11 Apr 2026 07:52:38 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>Simplify - Jonghun</managingEditor>
    <image>
      <title>Simplify</title>
      <url>https://t1.daumcdn.net/cfile/tistory/277B1C3355BDD62F1C</url>
      <link>https://4urdev.tistory.com</link>
    </image>
    <item>
      <title>Privacy Policy</title>
      <link>https://4urdev.tistory.com/pages/Privacy-Policy</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;Who&amp;nbsp;we&amp;nbsp;are &lt;br /&gt;&lt;br /&gt;Our website address is: &lt;a href=&quot;https://4urdev.tistory.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://4urdev.tistory.com/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Comments &lt;br /&gt;&lt;br /&gt;When&amp;nbsp;visitors&amp;nbsp;leave&amp;nbsp;comments&amp;nbsp;on&amp;nbsp;the&amp;nbsp;site&amp;nbsp;we&amp;nbsp;collect&amp;nbsp;the&amp;nbsp;data&amp;nbsp;shown&amp;nbsp;in&amp;nbsp;the&amp;nbsp;comments&amp;nbsp;form,&amp;nbsp;and&amp;nbsp;also&amp;nbsp;the&amp;nbsp;visitor&amp;rsquo;s&amp;nbsp;IP&amp;nbsp;address&amp;nbsp;and&amp;nbsp;browser&amp;nbsp;user&amp;nbsp;agent&amp;nbsp;string&amp;nbsp;to&amp;nbsp;help&amp;nbsp;spam&amp;nbsp;detection. &lt;br /&gt;&lt;br /&gt;An&amp;nbsp;anonymized&amp;nbsp;string&amp;nbsp;created&amp;nbsp;from&amp;nbsp;your&amp;nbsp;email&amp;nbsp;address&amp;nbsp;(also&amp;nbsp;called&amp;nbsp;a&amp;nbsp;hash)&amp;nbsp;may&amp;nbsp;be&amp;nbsp;provided&amp;nbsp;to&amp;nbsp;the&amp;nbsp;Gravatar&amp;nbsp;service&amp;nbsp;to&amp;nbsp;see&amp;nbsp;if&amp;nbsp;you&amp;nbsp;are&amp;nbsp;using&amp;nbsp;it.&amp;nbsp;The&amp;nbsp;Gravatar&amp;nbsp;service&amp;nbsp;privacy&amp;nbsp;policy&amp;nbsp;is&amp;nbsp;available&amp;nbsp;here:&amp;nbsp;&lt;a href=&quot;https://automattic.com/privacy/.&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://automattic.com/privacy/.&lt;/a&gt;&amp;nbsp;After&amp;nbsp;approval&amp;nbsp;of&amp;nbsp;your&amp;nbsp;comment,&amp;nbsp;your&amp;nbsp;profile&amp;nbsp;picture&amp;nbsp;is&amp;nbsp;visible&amp;nbsp;to&amp;nbsp;the&amp;nbsp;public&amp;nbsp;in&amp;nbsp;the&amp;nbsp;context&amp;nbsp;of&amp;nbsp;your&amp;nbsp;comment. &lt;br /&gt;&lt;br /&gt;Media &lt;br /&gt;&lt;br /&gt;If&amp;nbsp;you&amp;nbsp;upload&amp;nbsp;images&amp;nbsp;to&amp;nbsp;the&amp;nbsp;website,&amp;nbsp;you&amp;nbsp;should&amp;nbsp;avoid&amp;nbsp;uploading&amp;nbsp;images&amp;nbsp;with&amp;nbsp;embedded&amp;nbsp;location&amp;nbsp;data&amp;nbsp;(EXIF&amp;nbsp;GPS)&amp;nbsp;included.&amp;nbsp;Visitors&amp;nbsp;to&amp;nbsp;the&amp;nbsp;website&amp;nbsp;can&amp;nbsp;download&amp;nbsp;and&amp;nbsp;extract&amp;nbsp;any&amp;nbsp;location&amp;nbsp;data&amp;nbsp;from&amp;nbsp;images&amp;nbsp;on&amp;nbsp;the&amp;nbsp;website. &lt;br /&gt;&lt;br /&gt;Cookies &lt;br /&gt;&lt;br /&gt;If&amp;nbsp;you&amp;nbsp;leave&amp;nbsp;a&amp;nbsp;comment&amp;nbsp;on&amp;nbsp;our&amp;nbsp;site&amp;nbsp;you&amp;nbsp;may&amp;nbsp;opt-in&amp;nbsp;to&amp;nbsp;saving&amp;nbsp;your&amp;nbsp;name,&amp;nbsp;email&amp;nbsp;address&amp;nbsp;and&amp;nbsp;website&amp;nbsp;in&amp;nbsp;cookies.&amp;nbsp;These&amp;nbsp;are&amp;nbsp;for&amp;nbsp;your&amp;nbsp;convenience&amp;nbsp;so&amp;nbsp;that&amp;nbsp;you&amp;nbsp;do&amp;nbsp;not&amp;nbsp;have&amp;nbsp;to&amp;nbsp;fill&amp;nbsp;in&amp;nbsp;your&amp;nbsp;details&amp;nbsp;again&amp;nbsp;when&amp;nbsp;you&amp;nbsp;leave&amp;nbsp;another&amp;nbsp;comment.&amp;nbsp;These&amp;nbsp;cookies&amp;nbsp;will&amp;nbsp;last&amp;nbsp;for&amp;nbsp;one&amp;nbsp;year. &lt;br /&gt;&lt;br /&gt;If&amp;nbsp;you&amp;nbsp;visit&amp;nbsp;our&amp;nbsp;login&amp;nbsp;page,&amp;nbsp;we&amp;nbsp;will&amp;nbsp;set&amp;nbsp;a&amp;nbsp;temporary&amp;nbsp;cookie&amp;nbsp;to&amp;nbsp;determine&amp;nbsp;if&amp;nbsp;your&amp;nbsp;browser&amp;nbsp;accepts&amp;nbsp;cookies.&amp;nbsp;This&amp;nbsp;cookie&amp;nbsp;contains&amp;nbsp;no&amp;nbsp;personal&amp;nbsp;data&amp;nbsp;and&amp;nbsp;is&amp;nbsp;discarded&amp;nbsp;when&amp;nbsp;you&amp;nbsp;close&amp;nbsp;your&amp;nbsp;browser. &lt;br /&gt;&lt;br /&gt;When&amp;nbsp;you&amp;nbsp;log&amp;nbsp;in,&amp;nbsp;we&amp;nbsp;will&amp;nbsp;also&amp;nbsp;set&amp;nbsp;up&amp;nbsp;several&amp;nbsp;cookies&amp;nbsp;to&amp;nbsp;save&amp;nbsp;your&amp;nbsp;login&amp;nbsp;information&amp;nbsp;and&amp;nbsp;your&amp;nbsp;screen&amp;nbsp;display&amp;nbsp;choices.&amp;nbsp;Login&amp;nbsp;cookies&amp;nbsp;last&amp;nbsp;for&amp;nbsp;two&amp;nbsp;days,&amp;nbsp;and&amp;nbsp;screen&amp;nbsp;options&amp;nbsp;cookies&amp;nbsp;last&amp;nbsp;for&amp;nbsp;a&amp;nbsp;year.&amp;nbsp;If&amp;nbsp;you&amp;nbsp;select&amp;nbsp;&quot;Remember&amp;nbsp;Me&quot;,&amp;nbsp;your&amp;nbsp;login&amp;nbsp;will&amp;nbsp;persist&amp;nbsp;for&amp;nbsp;two&amp;nbsp;weeks.&amp;nbsp;If&amp;nbsp;you&amp;nbsp;log&amp;nbsp;out&amp;nbsp;of&amp;nbsp;your&amp;nbsp;account,&amp;nbsp;the&amp;nbsp;login&amp;nbsp;cookies&amp;nbsp;will&amp;nbsp;be&amp;nbsp;removed. &lt;br /&gt;&lt;br /&gt;If&amp;nbsp;you&amp;nbsp;edit&amp;nbsp;or&amp;nbsp;publish&amp;nbsp;an&amp;nbsp;article,&amp;nbsp;an&amp;nbsp;additional&amp;nbsp;cookie&amp;nbsp;will&amp;nbsp;be&amp;nbsp;saved&amp;nbsp;in&amp;nbsp;your&amp;nbsp;browser.&amp;nbsp;This&amp;nbsp;cookie&amp;nbsp;includes&amp;nbsp;no&amp;nbsp;personal&amp;nbsp;data&amp;nbsp;and&amp;nbsp;simply&amp;nbsp;indicates&amp;nbsp;the&amp;nbsp;post&amp;nbsp;ID&amp;nbsp;of&amp;nbsp;the&amp;nbsp;article&amp;nbsp;you&amp;nbsp;just&amp;nbsp;edited.&amp;nbsp;It&amp;nbsp;expires&amp;nbsp;after&amp;nbsp;1&amp;nbsp;day. &lt;br /&gt;&lt;br /&gt;Embedded&amp;nbsp;content&amp;nbsp;from&amp;nbsp;other&amp;nbsp;websites &lt;br /&gt;&lt;br /&gt;Articles&amp;nbsp;on&amp;nbsp;this&amp;nbsp;site&amp;nbsp;may&amp;nbsp;include&amp;nbsp;embedded&amp;nbsp;content&amp;nbsp;(e.g.&amp;nbsp;videos,&amp;nbsp;images,&amp;nbsp;articles,&amp;nbsp;etc.).&amp;nbsp;Embedded&amp;nbsp;content&amp;nbsp;from&amp;nbsp;other&amp;nbsp;websites&amp;nbsp;behaves&amp;nbsp;in&amp;nbsp;the&amp;nbsp;exact&amp;nbsp;same&amp;nbsp;way&amp;nbsp;as&amp;nbsp;if&amp;nbsp;the&amp;nbsp;visitor&amp;nbsp;has&amp;nbsp;visited&amp;nbsp;the&amp;nbsp;other&amp;nbsp;website. &lt;br /&gt;&lt;br /&gt;These&amp;nbsp;websites&amp;nbsp;may&amp;nbsp;collect&amp;nbsp;data&amp;nbsp;about&amp;nbsp;you,&amp;nbsp;use&amp;nbsp;cookies,&amp;nbsp;embed&amp;nbsp;additional&amp;nbsp;third-party&amp;nbsp;tracking,&amp;nbsp;and&amp;nbsp;monitor&amp;nbsp;your&amp;nbsp;interaction&amp;nbsp;with&amp;nbsp;that&amp;nbsp;embedded&amp;nbsp;content,&amp;nbsp;including&amp;nbsp;tracking&amp;nbsp;your&amp;nbsp;interaction&amp;nbsp;with&amp;nbsp;the&amp;nbsp;embedded&amp;nbsp;content&amp;nbsp;if&amp;nbsp;you&amp;nbsp;have&amp;nbsp;an&amp;nbsp;account&amp;nbsp;and&amp;nbsp;are&amp;nbsp;logged&amp;nbsp;in&amp;nbsp;to&amp;nbsp;that&amp;nbsp;website. &lt;br /&gt;&lt;br /&gt;Who&amp;nbsp;we&amp;nbsp;share&amp;nbsp;your&amp;nbsp;data&amp;nbsp;with &lt;br /&gt;&lt;br /&gt;If&amp;nbsp;you&amp;nbsp;request&amp;nbsp;a&amp;nbsp;password&amp;nbsp;reset,&amp;nbsp;your&amp;nbsp;IP&amp;nbsp;address&amp;nbsp;will&amp;nbsp;be&amp;nbsp;included&amp;nbsp;in&amp;nbsp;the&amp;nbsp;reset&amp;nbsp;email. &lt;br /&gt;&lt;br /&gt;How&amp;nbsp;long&amp;nbsp;we&amp;nbsp;retain&amp;nbsp;your&amp;nbsp;data &lt;br /&gt;&lt;br /&gt;If&amp;nbsp;you&amp;nbsp;leave&amp;nbsp;a&amp;nbsp;comment,&amp;nbsp;the&amp;nbsp;comment&amp;nbsp;and&amp;nbsp;its&amp;nbsp;metadata&amp;nbsp;are&amp;nbsp;retained&amp;nbsp;indefinitely.&amp;nbsp;This&amp;nbsp;is&amp;nbsp;so&amp;nbsp;we&amp;nbsp;can&amp;nbsp;recognize&amp;nbsp;and&amp;nbsp;approve&amp;nbsp;any&amp;nbsp;follow-up&amp;nbsp;comments&amp;nbsp;automatically&amp;nbsp;instead&amp;nbsp;of&amp;nbsp;holding&amp;nbsp;them&amp;nbsp;in&amp;nbsp;a&amp;nbsp;moderation&amp;nbsp;queue. &lt;br /&gt;&lt;br /&gt;For&amp;nbsp;users&amp;nbsp;that&amp;nbsp;register&amp;nbsp;on&amp;nbsp;our&amp;nbsp;website&amp;nbsp;(if&amp;nbsp;any),&amp;nbsp;we&amp;nbsp;also&amp;nbsp;store&amp;nbsp;the&amp;nbsp;personal&amp;nbsp;information&amp;nbsp;they&amp;nbsp;provide&amp;nbsp;in&amp;nbsp;their&amp;nbsp;user&amp;nbsp;profile.&amp;nbsp;All&amp;nbsp;users&amp;nbsp;can&amp;nbsp;see,&amp;nbsp;edit,&amp;nbsp;or&amp;nbsp;delete&amp;nbsp;their&amp;nbsp;personal&amp;nbsp;information&amp;nbsp;at&amp;nbsp;any&amp;nbsp;time&amp;nbsp;(except&amp;nbsp;they&amp;nbsp;cannot&amp;nbsp;change&amp;nbsp;their&amp;nbsp;username).&amp;nbsp;Website&amp;nbsp;administrators&amp;nbsp;can&amp;nbsp;also&amp;nbsp;see&amp;nbsp;and&amp;nbsp;edit&amp;nbsp;that&amp;nbsp;information. &lt;br /&gt;&lt;br /&gt;What&amp;nbsp;rights&amp;nbsp;you&amp;nbsp;have&amp;nbsp;over&amp;nbsp;your&amp;nbsp;data &lt;br /&gt;&lt;br /&gt;If&amp;nbsp;you&amp;nbsp;have&amp;nbsp;an&amp;nbsp;account&amp;nbsp;on&amp;nbsp;this&amp;nbsp;site,&amp;nbsp;or&amp;nbsp;have&amp;nbsp;left&amp;nbsp;comments,&amp;nbsp;you&amp;nbsp;can&amp;nbsp;request&amp;nbsp;to&amp;nbsp;receive&amp;nbsp;an&amp;nbsp;exported&amp;nbsp;file&amp;nbsp;of&amp;nbsp;the&amp;nbsp;personal&amp;nbsp;data&amp;nbsp;we&amp;nbsp;hold&amp;nbsp;about&amp;nbsp;you,&amp;nbsp;including&amp;nbsp;any&amp;nbsp;data&amp;nbsp;you&amp;nbsp;have&amp;nbsp;provided&amp;nbsp;to&amp;nbsp;us.&amp;nbsp;You&amp;nbsp;can&amp;nbsp;also&amp;nbsp;request&amp;nbsp;that&amp;nbsp;we&amp;nbsp;erase&amp;nbsp;any&amp;nbsp;personal&amp;nbsp;data&amp;nbsp;we&amp;nbsp;hold&amp;nbsp;about&amp;nbsp;you.&amp;nbsp;This&amp;nbsp;does&amp;nbsp;not&amp;nbsp;include&amp;nbsp;any&amp;nbsp;data&amp;nbsp;we&amp;nbsp;are&amp;nbsp;obliged&amp;nbsp;to&amp;nbsp;keep&amp;nbsp;for&amp;nbsp;administrative,&amp;nbsp;legal,&amp;nbsp;or&amp;nbsp;security&amp;nbsp;purposes. &lt;br /&gt;&lt;br /&gt;Where&amp;nbsp;your&amp;nbsp;data&amp;nbsp;is&amp;nbsp;sent &lt;br /&gt;&lt;br /&gt;Visitor&amp;nbsp;comments&amp;nbsp;may&amp;nbsp;be&amp;nbsp;checked&amp;nbsp;through&amp;nbsp;an&amp;nbsp;automated&amp;nbsp;spam&amp;nbsp;detection&amp;nbsp;service.&lt;/p&gt;</description>
      <author>Simplify - Jonghun</author>
      <guid isPermaLink="true">https://4urdev.tistory.com/pages/Privacy-Policy</guid>
      <pubDate>Wed, 6 Sep 2023 21:08:18 +0900</pubDate>
    </item>
    <item>
      <title>Homebrew 를 이용해서 패키지 관리하기</title>
      <link>https://4urdev.tistory.com/112</link>
      <description>&lt;p&gt;맥(Mac) 을 이용해서 개발을 하고 있다면, 여기서 소개하는 brew 가 많은 도움이 될 수 있습니다. 물론, 개발이 아닌 목적으로도 맥을 사용하는 사람이라면 마찬가지겠죠. (하지만 개발을 하고 있는 사람이 그 효과를 크게 느낄 것입니다)&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Homebrew 는 Ruby 기반으로 만들어진 패키지 관리 프로그램 입니다. 더 상세한 내용이나 기술적인 내용을 다루기 보다는 간단한 사용법을 정리해 둠으로서 개인적인 정리 목적도 있고, 향후에 찾아보기 편하기 위함도 있습니다. 원본 출처는 아래 출처 항목에서 다시 다루었고, 모든 저작권은 해당 페이지에 있음을 밝힙니다. 저는 자주 사용하는 것 위주로, 어떤 것들이 있는지 위주로 해서 설명을 더해 놓겠습니다만, 모든 내용은 해당 출처에 자세하게 설명되어 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Homebrew 는 'brew' 라는 명령어로 시작하여 설치 관련한 여러 작업들을 할 수 있게 합니다. 당연히 해당 프로그램이 설치될 것이고, shell 에 PATH 로서 해당 명령어가 매핑되어 있을 겁니다. 저는 개인적으로는, 동일한 프로그램을 여러 버전으로 사용하기 위해서 접하게 된 것도 있고, 화면을 통한 설치가 아니라는 점에서 매우 매력적으로 느꼈습니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;설치&lt;/h3&gt;
&lt;p&gt;Homebrew 는 다음 명령어를 통해 설치할 수 있습니다. 터미널을 실행하거나 iterm2 등 터미널 명령어가 가능한 프로그램을 실행시키고, 아래 명령어를 입력합니다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1591602464127&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/usr/bin/ruby -e &quot;$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;사실 위 명령어를 실행하기 위해서는 xcode 라는 맥용 개발 툴의 특정 명령어가 필요합니다. 다음을 입력해서 xcode command line tools&amp;nbsp; 라는 명령어를 설치합니다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1591602594668&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;xcode-select --install&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;다시 위의 명령어를 입력하면 homebrew 설치가 완료됩니다. 아래 버전을 확인하는 명령어로 제대로 설치되었는지 확인합니다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1591602993112&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;brew -v&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Homebrew 사용하기&lt;/h3&gt;
&lt;p&gt;앞서 설명한 것 처럼 Homebrew 는 brew 라는 명령어로 실행합니다. 다음 몇 가지를 익히고 있으면 사용하는 데 어려움이 전혀 없습니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;검색하기&lt;/h4&gt;
&lt;p&gt;Homebrew 에서는 설치하는 프로그램들을 Formula 라고 부릅니다. 다음 예시에서 처럼&amp;nbsp;&lt;span class=&quot;hl-text&quot;&gt;brew search &amp;lt;formula 이름&amp;gt;&lt;/span&gt; 으로 검색해서 어떤 것들을 설치할 수 있고, 어떤 버전을 설치할 수 있는지 확인할 수 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1591603836405&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;brew search java
brew search chrome&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;(위 예시에서 볼 수 있듯, 설치되는 프로그램 (formula) 이 화면이 있는 것인지 아니면 어떤 명령어 집합인지 등은 아무런 문제가 되지 않습니다. 그저 검색해서 원하는 formula 가 있다면 설치/실행할 수 있습니다. 심지어는 intelliJ, Eclipse 같은 화면이 있는 프로그램도 Homebrew 로 설치하고 관리하는 것이 가능한것으로 알고 있습니다.)&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;설치하기&lt;/h4&gt;
&lt;p&gt;formula 의 설치는&lt;span class=&quot;hl-text&quot;&gt;brew install &amp;lt;formula 이름&amp;gt;&lt;/span&gt;으로 할 수 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1591604163261&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;brew install rbenv&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;업그레이드(업데이트)하기&lt;/h4&gt;
&lt;p&gt;설치된 formula 를 업데이트 하기 위해서는 우선 &lt;span class=&quot;hl-text&quot;&gt;brew outdated&lt;/span&gt; 를 입력하여 오래된(구형인) formula 를 검색합니다. 그리고&amp;nbsp;&lt;span class=&quot;hl-text&quot;&gt;brew upgrade &amp;lt;formula 이름&amp;gt;&lt;/span&gt; &amp;nbsp;를 입력하여 업데이트를 진행합니다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1591604508568&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 버전업된 패키지 확인하기
brew outdated

# 패키지 업그레이드
brew upgrade rbenv

# 모든 패키지 업그레이드하기
brew upgrade&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;삭제하기&lt;/h4&gt;
&lt;p&gt;Homebrew 에서는 특정 버전으로 업그레이드 하더라도 이전 버전을 삭제하지는 않기 때문에 깔끔한 정리를 위해서는 삭제를 해줘야 합니다. 특정 formula 를 삭제하려면, &lt;span class=&quot;hl-text&quot;&gt;brew cleanup &amp;lt;formula 이름&amp;gt;&lt;/span&gt; 를 입력합니다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1591604601257&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;brew cleanup rbenv&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;이렇게 입력하면 해당 formula 에 구형 버전들을 모두 정리하게 되고, 만약 해당 formula 자체를 삭제하고 싶다면 다음과 같이 &lt;span class=&quot;hl-text&quot;&gt;brew uninstall &amp;lt;formula 이름&amp;gt;&lt;/span&gt;를 입력합니다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1591604840569&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;brew uninstall rbenv&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;관리하기&lt;/h4&gt;
&lt;p&gt;만약 사용중인 formula 목록을 확인하고 싶다면&amp;nbsp;&lt;span class=&quot;hl-text&quot;&gt;brew list&lt;/span&gt; 를, 특정 formula 의 상세 정보를 보고 싶다면&amp;nbsp;&lt;span class=&quot;hl-text&quot;&gt;brew info &amp;lt;formula 이름&amp;gt;&lt;/span&gt; 를 입력합니다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1591604920392&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 설치한 패키지 목록보기
brew list

# 패키지의 정보 보기
brew info rbenv&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Homebrew 관리&lt;/h3&gt;
&lt;p&gt;계속해서 사용을 하다 보면 Homebrew 자체를 업데이트/삭제 해야 하는 경우도 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;업데이트 하기&lt;/h4&gt;
&lt;pre id=&quot;code_1591605045136&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;brew update&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;삭제하기&lt;/h4&gt;
&lt;pre id=&quot;code_1591605064786&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;ruby -e &quot;$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/uninstall)&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;참고&lt;/h3&gt;
&lt;p&gt;위에서 설명한 명령어들로 모든 작업들을 할 수 있지만, 보기 좋게 나열해 놓고 확인하고 싶은 경우에는 Cakebrew 라는 것을 검색해서 설치해 보시기를 바랍니다. 터미널 만으로 관리하는 것이 크게 와닿지 않아 어려운 분들에게는 도움이 많이 될 것입니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;스크린샷 2020-06-08 오후 5.01.25.png&quot; data-origin-width=&quot;702&quot; data-origin-height=&quot;698&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/TrRgT/btqEHw7CRNk/NcJdqu1KfpwXR9i9DBt1ek/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/TrRgT/btqEHw7CRNk/NcJdqu1KfpwXR9i9DBt1ek/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/TrRgT/btqEHw7CRNk/NcJdqu1KfpwXR9i9DBt1ek/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FTrRgT%2FbtqEHw7CRNk%2FNcJdqu1KfpwXR9i9DBt1ek%2Fimg.png&quot; data-filename=&quot;스크린샷 2020-06-08 오후 5.01.25.png&quot; data-origin-width=&quot;702&quot; data-origin-height=&quot;698&quot; data-ke-mobilestyle=&quot;widthContent&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;출처&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://tutorialpost.apptilus.com/code/posts/tools/homebrew-for-mac/&quot;&gt;https://tutorialpost.apptilus.com/code/posts/tools/homebrew-for-mac/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Other/Dev. Tips</category>
      <author>Simplify - Jonghun</author>
      <guid isPermaLink="true">https://4urdev.tistory.com/112</guid>
      <comments>https://4urdev.tistory.com/112#entry112comment</comments>
      <pubDate>Mon, 8 Jun 2020 16:53:31 +0900</pubDate>
    </item>
    <item>
      <title>Minikube 설정 변경하기 How to change 'Minikube' configurations</title>
      <link>https://4urdev.tistory.com/111</link>
      <description>&lt;p&gt;Minikube 는 간소화된 형태로 kubernetes(k8s) 를 사용하기에 적합한 프로그램입니다. 이에 대해서는 향후에라도 설치 방법과 사용법에 대해서 조금 더 깊이있게 다루겠지만, 최근 들어서 조금 사용해보다 보니, 설정에 대한 부분은 메모 목적으로라도 남겨놓아야 할 것 같아서 글을 남깁니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Kinikube 의 경우 아래 명령어를 통해서 간단하게 실행이 가능합니다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1590050603421&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;minikube start --driver=&amp;lt;driver name&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;위에서 driver name 부분은 다음 목록을 사용하여 설정 가능합니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;docker (&lt;a href=&quot;https://minikube.sigs.k8s.io/docs/drivers/docker/&quot;&gt;driver installation&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;virtualbox (&lt;a href=&quot;https://minikube.sigs.k8s.io/docs/drivers/virtualbox/&quot;&gt;driver installation&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;podman (&lt;a href=&quot;https://minikube.sigs.k8s.io/docs/drivers/podman/&quot;&gt;driver installation&lt;/a&gt;) (EXPERIMENTAL)&lt;/li&gt;
&lt;li&gt;vmwarefusion&lt;/li&gt;
&lt;li&gt;kvm2 (&lt;a href=&quot;https://minikube.sigs.k8s.io/docs/reference/drivers/kvm2/&quot;&gt;driver installation&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;hyperkit (&lt;a href=&quot;https://minikube.sigs.k8s.io/docs/reference/drivers/hyperkit/&quot;&gt;driver installation&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;hyperv (&lt;a href=&quot;https://minikube.sigs.k8s.io/docs/reference/drivers/hyperv/&quot;&gt;driver installation&lt;/a&gt;) Note that the IP below is dynamic and can change. It can be retrieved with&lt;span&gt;&amp;nbsp;&lt;/span&gt;minikube ip.&lt;/li&gt;
&lt;li&gt;vmware (&lt;a href=&quot;https://minikube.sigs.k8s.io/docs/reference/drivers/vmware/&quot;&gt;driver installation&lt;/a&gt;) (VMware unified driver)&lt;/li&gt;
&lt;li&gt;parallels (&lt;a href=&quot;https://minikube.sigs.k8s.io/docs/reference/drivers/parallels/&quot;&gt;driver installation&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;예를 들어 driver name 으로 virtualbox 를 사용한다고 하면 당연히 virtualbox 가 실행하는 머신에 설치되어 있어야 합니다. 그런데 이것을 기본값으로 하고 싶으면 아래 예제와 같이 진행하면 됩니다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1590051104032&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;minikube start --driver=virtualbox&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1590051135334&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;minikube config set driver virtualbox&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;이와 마찬가지로 만약 기본 메모리 정보를 변경하고 싶으면 아래와 같이 명령어를 입력합니다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1590051190282&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;minikube config set memory 2048&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;그런데, driver 를 여러 가지로 변경하며서 실행하더라도, 동일한 설정을 유지하고 싶을 수 있습니다. 위의 명령어는 각 minikube container 안에 설정값으로 남게 되므로, virtualbox 에서의 설정과 docker 에서의 설정이 다를 수 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;이러한 경우에는 ~/.minikube/config 폴더에 들어가서 config.json 파일을 열어 봅니다. 현재 시점 기준으로 해당 파일에는 아무런 내용도 없는 빈 json 파일이 들어 있습니다&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1590051319864&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;{}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;이 파일에 아래와 같이 추가해 줍니다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1590051340021&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;{
    &quot;memory&quot; : 2048
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;별거 아니지만 항상 까먹고 그래서 이력으로 남겨봅니다. 위 json 에서 문법이 틀리면, 실행 시점에 에러가 나지는 않는 것 같습니다만, 설정이 제대로 적용되지 않으니 문법을 잘 지켜서 적용하시기 바랍니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;참고&lt;/p&gt;
&lt;p&gt;- &lt;a href=&quot;https://kubernetes.io/docs/setup/learning-environment/minikube/#specifying-the-vm-driver&quot;&gt;https://kubernetes.io/docs/setup/learning-environment/minikube/#specifying-the-vm-driver&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;-&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Web &amp;amp; Server/Docker &amp;amp; Container</category>
      <author>Simplify - Jonghun</author>
      <guid isPermaLink="true">https://4urdev.tistory.com/111</guid>
      <comments>https://4urdev.tistory.com/111#entry111comment</comments>
      <pubDate>Thu, 21 May 2020 17:56:31 +0900</pubDate>
    </item>
    <item>
      <title>Gradle 프로젝트에 로컬 jar 파일 추가하기 - How to add local jar file to Gradle project</title>
      <link>https://4urdev.tistory.com/110</link>
      <description>&lt;p&gt;Java 프로그램을 구현하다 보면 어떠한 방식으로든 각종 라이브러리를 추가해서 사용하게 됩니다. 예를 들어 Stirng 처리와 관련된 편리한 라이브러리들이라든지, 통신 관련 모듈 등등 추가해서 사용해야 하는 것들은 무궁무진하게 많습니다. 프로젝트 규모가 조금 크거나, 프로젝트 내에 여러 sub-project 가 존재하는 경우, 프로젝트들의 일관성이나 관리를 위해서 공통 라이브러리를 만들어서 구현하는 경우도 많고, 이러한 경우에 로컬 저장소를 이용하기도 합니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;그런데 저장소 까지는 필요없고, 그저 로컬 jar 파일 하나를 추가하는 경우도 있습니다. 이클립스에서 Java Build Path 에 추가해 주는 것과 비슷한 형태인데, 조금 더 전형적인 방법으로 추가해 보고자 합니다. 여기서는 필자가 잘 익숙하지 않은 Gradle 프로젝트를 예로 들고 Maven 프로젝트는 추후 추가해서 적도록 하겠습니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;중앙 저장소 이용&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;일반적인 경우 이와 같은 형태로 구성하게 됩니다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1582530492630&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;repositories {
    mavenCentral()
}

dependencies {
    compile(&quot;org.projectlombok:lombok:1.16.8&quot;)
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;위에서 repositories 부분에 선언한 mavenCentrl 부분이 바로 중앙 저장소를 의미하고 일반적으로 사용하는 repository 를 의미합니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;프로젝트 내의 jar 파일 추가하기, libs 폴더 추가하기&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1582530590290&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;dependencies {
    compile files('libs/lombok-1.16.8.jar')
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;위와 같이 파일의 위치를 명시해 주면 그 파일을 컴파일할 때에 폴함시킬 수 있습니다. 가장 손쉽게 추가하는 방법입니다. 그런데 만약 libs 폴더의 모든 jar 파일을 추가한다면 다음과 같이 구성합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1582530666270&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;가장 기본적인 부분인데도 막상 추가하려고 보면 문법이 가물가물한 경우가 많아 위와 같이 정리해 봅니다. 물론 로컬(프로젝트에서 자체 구성) repository 를 구축해 두고 이를 통째로 repositories 에 추가하는 방법도 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1582530790775&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;repositories {
  maven { url &quot;http://maven.springframework.org/release&quot; }
  maven { url &quot;http://maven.restlet.org&quot; }
  mavenCentral()
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;출처 &amp;amp; 참고자료&amp;nbsp;&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;a href=&quot;https://jsonobject.tistory.com/222&quot;&gt;https://jsonobject.tistory.com/222&lt;/a&gt;&lt;/p&gt;</description>
      <category>Web &amp;amp; Server/Spring &amp;amp; Spring Boot</category>
      <category>add</category>
      <category>gradle</category>
      <category>local</category>
      <category>Multiple</category>
      <category>Repository</category>
      <author>Simplify - Jonghun</author>
      <guid isPermaLink="true">https://4urdev.tistory.com/110</guid>
      <comments>https://4urdev.tistory.com/110#entry110comment</comments>
      <pubDate>Mon, 24 Feb 2020 16:53:36 +0900</pubDate>
    </item>
    <item>
      <title>자바 프로그래밍으로 엑셀 파일 읽기 - How to read Excel file with Java programming (with POI)</title>
      <link>https://4urdev.tistory.com/109</link>
      <description>&lt;p&gt;서버 측 프로그래밍을 하다 보면, 특히나 웹 프로그래밍을 하다보면, Excel 파일을 읽고 쓰는 일이 빈번합니다. 예를 들어 화면에 출력된 내용을 Excel 파일로 내보내기(export)한다거나, 한꺼번에 다량의 항목을 등록하려 할 때에 Excel 파일로 등록하기(import) 등의 기능이 이에 해당합니다. 물론 다양한 방법으로 Excel 파일을 읽고 쓰는 것이 가능하지만, 가장 흔히 사용되고 편리한 것은 POI 라는 것을 이용하는 것입니다. 사실 과거에 - 아주 오래전 - 는 엑셀 파일을 테스트 파일로 읽어들이면, xml 파일과 유사한 형태를 띄고 있어 쉽게 읽고 쓰는 것이 가능했지만, 최근에는 보안상의 이유인지 이 마저도 제대로 보이지 않고, 특히 xlsx 파일은 똑바로 읽을 방법이 없습니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;간단하지만 가볍게 봐 두면 한번 쯤은 사용하게 되는 기능인 것 같습니다. 코드부터 보여드리고 몇 가지 팁을 적겠습니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1582528216680&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package excel;
 
import java.io.FileInputStream;
 
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
 
public class ExcelRead {
 
    public static void main(String[] args) {
 
        try {
            FileInputStream file = new FileInputStream(&quot;D:/tmp/upload/right_excel/test.xlsx&quot;);
            XSSFWorkbook workbook = new XSSFWorkbook(file);
 
            int rowindex=0;
            int columnindex=0;
            //시트 수 (첫번째에만 존재하므로 0을 준다)
            //만약 각 시트를 읽기위해서는 FOR문을 한번더 돌려준다
            XSSFSheet sheet=workbook.getSheetAt(0);
            //행의 수
            int rows=sheet.getPhysicalNumberOfRows();
            for(rowindex=0;rowindex&amp;lt;rows;rowindex++){
                //행을읽는다
                XSSFRow row=sheet.getRow(rowindex);
                if(row !=null){
                    //셀의 수
                    int cells=row.getPhysicalNumberOfCells();
                    for(columnindex=0; columnindex&amp;lt;=cells; columnindex++){
                        //셀값을 읽는다
                        XSSFCell cell=row.getCell(columnindex);
                        String value=&quot;&quot;;
                        //셀이 빈값일경우를 위한 널체크
                        if(cell==null){
                            continue;
                        }else{
                            //타입별로 내용 읽기
                            switch (cell.getCellType()){
                            case XSSFCell.CELL_TYPE_FORMULA:
                                value=cell.getCellFormula();
                                break;
                            case XSSFCell.CELL_TYPE_NUMERIC:
                                value=cell.getNumericCellValue()+&quot;&quot;;
                                break;
                            case XSSFCell.CELL_TYPE_STRING:
                                value=cell.getStringCellValue()+&quot;&quot;;
                                break;
                            case XSSFCell.CELL_TYPE_BLANK:
                                value=cell.getBooleanCellValue()+&quot;&quot;;
                                break;
                            case XSSFCell.CELL_TYPE_ERROR:
                                value=cell.getErrorCellValue()+&quot;&quot;;
                                break;
                            }
                        }
                        System.out.println(rowindex+&quot;번 행 : &quot;+columnindex+&quot;번 열 값은: &quot;+value);
                    }
 
                }
            }
 
        }catch(Exception e) {
            e.printStackTrace();
        }
 
    }
 
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;편의 상, 아래 출처&amp;amp; 참고자료에 적힌 블로그에서 코드 블럭을 가져왔습니다. 저 역시 유사하게 사용하있고 간단한 것들은 이 정도로 충분합니다만, 다음과 같은 부분에 대해서 추가적으로 팁을 드리고자 합니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;xls * xlsx 파일 두 가지 모두 처리하기&amp;nbsp;&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1582528532191&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;FileInputStream fileInputStream = new FileInputStream(templateFile);
if (templateFile.getAbsolutePath().endsWith(&quot;xlsx&quot;)) {
    workbook = new XSSFWorkbook(fileInputStream);
} else if (templateFile.getAbsolutePath().endsWith(&quot;xls&quot;)) {
    workbook = new HSSFWorkbook(fileInputStream);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;파일 확장자에 따라서 분기합니다. 이렇게 하면 위 소스에서 몇 가지 부분이 에러가 발생할 텐데, 그 상위 클래스로 잡하주면 됩니다. 예를 들어 XSSFCell 은 그냥 Cell 로 잡아주면 되고, Cell Type을 분기하는 부분은 아래와 같이 분기하면 됩니다.&lt;/p&gt;
&lt;pre id=&quot;code_1582528684873&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;switch (cell.getCellType()) {
	case FORMULA:
    
    ...&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;첫 줄이 비어있는, 중간부터 쓰여있는 표 형태를 읽는 경우&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1582528742465&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;int lastRowIndex = sheet.getLastRowNum();
	for (rowIndex = 0; rowIndex &amp;lt;= lastRowIndex; rowIndex++) {
		int realRowIndex = rowIndex + sheet.getFirstRowNum();
		Row row = sheet.getRow(realRowIndex);
        
        ...&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;위와 같은 형태로 처리하면 중간에 덩그러니 쓰여있는 형태의 파일도 제대로 읽어올 수 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;getLastRowNum() 함수는 그야말로 유효한 값이 있는 마지막 행 번호를 받아옵니다. 그런데, 0번 Row 부터 처리하면 빈 row 가 나올 수 있기 때문에 첫 줄은 getFirstRowNum() 으로 가져오는 것이 맞습니다. 이렇게 하면 빈줄 읽어와서 처리하는 것 대신에, 유효한 첫 줄부터 유효한 마지막 줄 까지를 읽을 수 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;셀 읽는 범위 처리&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;위와 같이 getPhysicalNumberOfCells() 를 호출해서 얻는 숫자는 유효한 컬럼 수를 return 합니다. 만얀 A, B 컬럼 정도가 비어있다면, 위 형태로는 마지막까지 읽지 못하고 마지막 두 컬럼을 읽지 못합니다. 따라서 아래와 같이 처리합니다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1582529050221&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;nt lastCellIndex = row.getLastCellNum();
	for (columnIndex = 0; columnIndex &amp;lt;= lastCellIndex; columnIndex++) {						
		Cell cell = row.getCell(columnIndex);
		Object value = null;
        
        if (cell != null) {
        
        ...&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;마지막 cell 번호를 getLastCellNum() 으로 얻어옵니다. 이렇게 하면 유효한 값이 있는 마지막 셀을 얻어오므로, 0번 컬럼부터 체크하면서 null 여부를 판단하면 마지막 셀 까지 다 읽어낼 수 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;여러가지 트릭이나 편법이 있고, 더 좋은 방법들이 있는 줄 알고 있습니다만, 위에서 설명한 세 가지는 유용한 정보로 보여 공유 차원에서 올립니다. 적고 나니 getFirstCellNum() 이 있는지 궁금하네요. (아마 있을 듯 싶습니다..)&lt;/p&gt;
&lt;p&gt;엑셀을 읽을 때 정해진 틀 내에서 처리하도록 가이드하는 것도 중요하므로 보통 '다량 건 일괄 등록'과 같은 기능을 개발하는 경우에는 templete 파일을 제공하고 이 틀에 맞추어 등록하도록 가이드합니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;그래도 혹시 모르고, 조금 더 자유롭게 등록하게 하기 위해서, 또 다양한 파이를 그대로 읽기 위해서는 위와 같이 작업해 두는 것이 좋습니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;출처 &amp;amp; 참고자료&amp;nbsp;&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;a href=&quot;https://huskdoll.tistory.com/m/890&quot;&gt;https://huskdoll.tistory.com/m/890&lt;/a&gt;&lt;/p&gt;</description>
      <category>Other/Java</category>
      <category>Excel</category>
      <category>Java</category>
      <category>POI</category>
      <category>엑셀</category>
      <category>자바</category>
      <author>Simplify - Jonghun</author>
      <guid isPermaLink="true">https://4urdev.tistory.com/109</guid>
      <comments>https://4urdev.tistory.com/109#entry109comment</comments>
      <pubDate>Mon, 24 Feb 2020 16:27:55 +0900</pubDate>
    </item>
    <item>
      <title>오라클 URL 에 대해.. - About Oracle Driver URL</title>
      <link>https://4urdev.tistory.com/108</link>
      <description>&lt;p&gt;오라클은 오랜 시간동안 기업형 서비스의 Database 로서 자리매김하고 있는 것 같습니다. 항상 아무 생각없이 지나쳐 왔고, DBA 역할을 하는 분이 공유해준 내용을 바탕으로 그저 사용하기 바빴을 뿐, 이 부분에 대해서 구체적으로 분석해본 적이 없는 것 같아 간단하게 나마 적어두려고 합니다 .정리가 잘 된 블로그가 있어, 참고하여 적습니다. 해당 포스트 관리자 분께 감사드립니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;(제 머리가 나빠, 기억해 두려는 목적으로 제 블로그에도 정리하고, 맨 아래에 출처도 명시해 둡니다. )&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;어쩌면 너무 오랜 역사를 가지고 있고, 이정도는 기본(?) 이라는 발상이 있어서인지, 어디에도 이 부분에 대해서 잘 설명되어 있지 않다는 느낌을 많이 받습니다. 게다가 소프트웨어 개발자의 경우에는 DB 문서에 친숙하지 않은 부분도 있긴 할겁니다.(핑계입니다)&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;저는 Java 개발자이고, 따라서 당연히 JDBC 드라이버를 사용할 때에 필요한 URL 형태를 기준으로 설명합니다. ORACLE 에서 URL을 지정할 때에 아래와 같은 형태도 있지만, Listener 를 대상으로 하는 URL 형태도 있으므로, 이에 대해서 주의해야 합니다. 저는 여기서는 간단히 일반적인 형태만을 기술하겠습니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span&gt;jdbc:oracle:driver_type:[username/password]@[//]host_name[:port][/XE]&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p&gt;&lt;span&gt;위의 형태와 같은 아래 정보를 해석해 보겠습니다.&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1582526735096&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;jdbc:oracle:thin:@localhost:1521:xe
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;span&gt;[ ]안에 있는 정보 option 값입니다. 이는 반드시 명기할 필요는 없다는 뜻이다. (특히 비밀번호의 경우, 암호화를 거치게 되면 외계어를 포함하게 되는 경우가 있는데, 잘못하면 위 URL 정보가 깨질 수 있으므로, 잘 적지 않고, 별도로 처리해주는 경우가 많습니다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;jdbc:oracle:&lt;span style=&quot;color: #ee2323;&quot;&gt;thin&lt;/span&gt;은 사용하는 JDBC드라이버가 thin 타입을 의미합니다. 자바용 오라클 JDBC드라이버는 크게 두가지가 있는데 하나는 Java JDBC THIN 드라이버고, 다른 하나는 OCI기반의 드라이버라고 합니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;username/password&lt;/span&gt; 는 로그인할 수 있는 id, password 정보입니다.&amp;nbsp;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;:port&lt;/span&gt; 번호도 option입니다. 다만 Oracle의 listener port인 1521을 사용하지 않을 경우는 이 값을 명기해 줘야 합니다. 예를 들어서 jdbc:oracle:thin:hr/hr@//localhost:1522 와 같이 1522번 포트를 사용하는 경우가 이에 해당합니다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;localhost&lt;/span&gt;는 Oracle DB가 설치되어 있는 서버의 IP인데 위 경우는 로컬에 설치되어 있다는 뜻이다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;1521&lt;/span&gt; 은 오라클 listener의 포트번호이다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;/XE&lt;/span&gt;는 Oracle database client의 고유한 service name 입니다. 디폴트로 XE를 사용하므로 이 정보도 option입니다. 이에 대한 설정 정보는 Oracle이 설치된 폴더 아래의 app\oracle\product\11.2.0\server\network\ADMIN\&lt;span style=&quot;color: #006dd7;&quot;&gt;listener.ora&lt;/span&gt; 파일에 다음과 같이 표시되어 있다.&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;DEFAULT_SERVICE_LISTENER = (XE)&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;출처 &amp;amp; 참고자료&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;a href=&quot;https://developer-joe.tistory.com/82&quot;&gt;https://developer-joe.tistory.com/82&lt;/a&gt;&lt;/p&gt;</description>
      <category>Other/Dev. Tips</category>
      <category>jdbc</category>
      <category>Oracle</category>
      <category>url</category>
      <category>오라클</category>
      <author>Simplify - Jonghun</author>
      <guid isPermaLink="true">https://4urdev.tistory.com/108</guid>
      <comments>https://4urdev.tistory.com/108#entry108comment</comments>
      <pubDate>Mon, 24 Feb 2020 15:53:31 +0900</pubDate>
    </item>
    <item>
      <title>jqGrid 에서 셀 속성 변경하기 - How to change cell attribute with jqGrid</title>
      <link>https://4urdev.tistory.com/107</link>
      <description>&lt;p&gt;jqGird 는 Web 을 개발하는 데 있어서 유명하고 편리한 라이브러리 중 하나입니다. 기본적으로 jqGrid 는 무료로 사용할 수 있고, 복잡하지 않은 설정을 지원하며, 오랜 기간동안 개선되어 온 결과 많은 기능과 customizable 한 것들이 많이 있습니다. 여기서는 그 중에서 특정 셀(cell)의 속성을 어떻게 변경하는지 살펴보고자 합니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;이 포스트는 jqGrid 를 조금이라도 사용할 수 있는 개발자분들을 대상으로 작성되었습니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;jqGrid 에서 특정 조건에 따라서 컬럼, 즉 cell의 attribute를 변경하고자 할 때에는 다음의 두 항목을 이용합니다. 물론 이 두 항목 모두 jqGrid Options 중에서 colModel 에 선언하는 형태입니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;cellAttr&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;함수 형태로서, 해당 셀의 속성을 변경하고자 할 때에 사용합니다. 가장 강력한 형태라고도 할 수 있는데, 여기서 특정 조건일 때, 아니면 숫자에 대해서 콤마(,)를 찍어준다거나, 어떤 조건일 때 스타일을 변경하는 등의 작업을 할 수 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;넘어오는 파라미터는 다음과 같으며, 기본적으로 이 함수는 선언되어 있지 않습니다. (data에서 넘어온 글자 그대로 표현합니다)&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;rowId&lt;span&gt; - 해당 셀이 위치하는 row Id 입니다.&lt;/span&gt;&lt;br /&gt;val&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;- 이 셀에서 보여지는 값을 의미합니다. 이 값은 아래에서 설명할 formatter를 통해서 넘어온 값이라고 할 수 있습니다.&amp;nbsp;&lt;/span&gt;&lt;br /&gt;rawObject&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;- 해당 셀이 포함된 행의 원본 데이터를 의미합니다.&amp;nbsp;&lt;/span&gt;&lt;br /&gt;cm&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;- 모든 프로퍼티 정보를 가지고 있습니다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;rdata&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt; - &lt;span style=&quot;color: #000000;&quot;&gt;가장 많이 사용하는 파라미터로서, 해당 row를 가져옵니다. 예를 들어, 이 셀의 값(val)이 100이 넘는데, 이 row의 ID 컬럼이 S로 시작한다면 이 셀을 빨간색으로 칠해! 라고 할 때에 유용합니다. 즉, 다른 셀의 값을 참조하고자 할 때에 아주 유용하게 사용됩니다.&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;formatter&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이 속성 역시 colModel에 지정하는데, 이건 셀에 표현될 글자 자체에 초점을 둡니다. 앞서 살표본 cellAttr 의 경우 셀 자체 html 속성에 대한 부분을 수정하려는 목적이 강하다면 formatter는 cell에 포현되는 문구 자체에 초점을 둡니다. 3자리마다 콤마(,)를 찍어준다거나, 100, 200 등의 숫자에 대해서 type 을 변경해서 보여주거나 하는 등으로 값을 변경하고자 할 때에 사용하면 좋습니다.&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;참고&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;위 속성 이외에도&lt;a href=&quot;http://www.trirand.com/jqgridwiki/doku.php?id=wiki:colmodel_options&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&amp;nbsp;&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;a href=&quot;http://www.trirand.com/jqgridwiki/doku.php?id=wiki:colmodel_options&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span class=&quot;hl-text&quot;&gt;jqGrid Documentation&lt;/span&gt; &lt;/a&gt; &lt;span style=&quot;color: #000000; letter-spacing: 0px;&quot;&gt;에 가보면 다양한 속성들이 많이 있습니다. 단순이 개발자도구를 열어, css를 수정해 가며 화면을 수정하기 보다는 조금 더 정확하고 버전 업그레이드를 보장받을 수 있는 이런 함수들을 자주 활용하는 것이 좋습니다.&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;사용법 예제&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1582442891579&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$( function() {
    $('#list').jqGrid({
	    //url: 'TrControl?cmd=getSumAmtID',
        datatype: 'json',
        colModel: [
            {name: 'id', index:'id', width: '100', align: 'left', cellattr:idColorFmt},
            {name: 'nm', index:'nm', width: '150', align: 'left', cellattr:idColorFmt},
            {name: 'amt', index:'amt', width: '150', align: 'right', formatter:numFormat, cellattr:idColorFmt}
        ],
        colNames : [ '아이디', '계정명', '금액'],
        caption: '계정별 집계',
        height: '100%',
        treeGrid: true,
        ExpandColClick: true,
        treeReader: {
	        level_field:        &quot;level&quot;,
	        parent_id_field:    &quot;upid&quot;
	    }
	});
});

// table cell의 attribute 설정. Style 등등
function idColorFmt( rowId, tv, rawObject, cm, rdata) {
    switch( rawObject.level) {
        case 1:
            return 'style=&quot;background-color:#58D3F7&quot;';
            break;
        case 2:
            return 'style=&quot;background-color:#E0F2F7&quot;';
            break;
        case 3:
            return 'style=&quot;background-color:white&quot;';
            break;
        default:
    }
    return  &quot;&quot;;
}

// 글자 포멧팅
function numFormat( cellvalue, options, rowObject ){
    return numberWithCommas(cellvalue)
}

function numberWithCommas(x) {
    return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, &quot;,&quot;);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;출처 및 참고&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://m.blog.naver.com/PostView.nhn?blogId=rakeion&amp;amp;logNo=120208417974&amp;amp;proxyReferer=https%3A%2F%2Fwww.google.com%2F&quot;&gt;https://m.blog.naver.com/PostView.nhn?blogId=rakeion&amp;amp;logNo=120208417974&amp;amp;proxyReferer=https%3A%2F%2Fwww.google.com%2F&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.trirand.com/jqgridwiki/doku.php?id=wiki:colmodel_options&quot;&gt;http://www.trirand.com/jqgridwiki/doku.php?id=wiki:colmodel_options&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Other/Dev. Tips</category>
      <author>Simplify - Jonghun</author>
      <guid isPermaLink="true">https://4urdev.tistory.com/107</guid>
      <comments>https://4urdev.tistory.com/107#entry107comment</comments>
      <pubDate>Sun, 23 Feb 2020 16:36:38 +0900</pubDate>
    </item>
    <item>
      <title>리눅스 환경에서 tar 압축하기 - How to compress a *.tar file in linux</title>
      <link>https://4urdev.tistory.com/106</link>
      <description>&lt;p&gt;사실 너무 기본적이 내용이긴 하지만, 항상 느끼지만, 자꾸 까먹기 때문에 이 기회에 정리해 둡니다. 정리만 하더라도 제 블로그에서 찾기 쉽고, 정리하면서 기억도 되는거라서 정리해 두려고 합니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;우선 tar 로 묶는 것은 jar 랑 비슷하게, 그저 파일을 하나로 묶는 역할만을 합니다. 이것이 아니라, tar.gz 로 만들면, 이건 압축해서 묶는 것에 해당합니다. 동일한 형태로 명령어가 되어 있고, 옵션만 다르기 때문에 기억해 두면 좋습니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;tar 로 묶기/풀기&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;우선 tar로 묶기 위해서는 리눅스에서 tar 명령어를 사용합니다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1581515061776&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;tar -cvf {파일명.tar} {폴더명 또는 파일명}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;우선 묶는 데에는 &lt;span style=&quot;color: #ee2323;&quot;&gt;C&lt;/span&gt;ompress 의 약자인 c 를, 압축을 해제하는 데에는 e&lt;span style=&quot;color: #ee2323;&quot;&gt;X&lt;/span&gt;tract 의 약어인 x 를 옵션으로 사용한다는 점을 기억하고 있다면 다음과 같은 명령어로 묶은 tar를 풀어줄 수 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1581515143690&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;tar -xvf {파일명.tar}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;tar.gz 로 압축하기/해제하기&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;만약 텍스트 파일이 압축 후에 훨씬 더 작아질 여지가 있다면 압축 옵션을 이용하여 더 작게 파일을 만들어 두는 것이 저장공간 확보에 더욱 도움이 됩니다. 앞선 살펴본 명령어와 유사하나, Zip 의 z 가 포함된다는 점만 기억해 주면 됩니다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1581515302500&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;tar -zcvf {파일명.tar.gz} {폴더명 or 파일명}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;위와 같은 명령어로 압축을 진행할 수 있고, 압축 대상이 되는 부분에는 여러 개의 파일을 지정해도 되고, *.log 와 같이 다중 파일이 선택되도록 입력해 주면 됩니다. 앞서 살펴본 옵션에 z 만 추가된 사항입니다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1581515372320&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;tar -zxvf {파일명.tar.gz}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;마찬가지로, 압축 해제 역시 z 옵션만 추가해 주면 됩니다. 만약 gz 로 압축된 파일에 z 를 빼고 실행하면 어떻게 되는지 모르겠습니다만, 가급적 맞춰서 해주시길 권장합니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;위에서 사용하지 않은 옵션들을 아래와 같이 정리합니다. 이해하기 좋게 글로 적겠습니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;특히 리눅스 환경에서 같은 프로그램 구동 환경을 압축하고 이를 다른 시스템에 배포(옮기는)하는 작업을 하려면 &lt;span class=&quot;key&quot;&gt;-p&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #333333;&quot;&gt;파일 권한을 저장하는&lt;/span&gt; 옵션도 유용합니다. &lt;span class=&quot;key&quot;&gt;-v&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;/span&gt;는 사실 다른 프로그램들도 많이들 사용하고 있는 verbose 의 약자로 보면 되고,&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;key&quot;&gt;-C&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;/span&gt;로 경로를 지정하는 것은 명령어로서는 잘 사용하지는 않는 것 같으나 알아두면 써먹을데가 있을지도 모르겠습니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;사실 위 처럼 zip 명령어를 사용하는 방법도 있고, 이걸 더 편히 생각하시거나 특히 windows 에 공유하고자 하는 사람들은 zip 을 선호하기도 합니다. (물론 요즘은 아무런 관계가 없어요) 하지만 기본적인 linux 환경에서 zip 은 제공하고 있지 않다고 보는게 맞고, 따라서 apt 등을 통해 설치해 주어야 한다는 점에서는 tar.gz 를 충분히 활용해 보는 것이 좋아 보입니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;참고 및 출처&lt;/b&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://nota.tistory.com/m/53&quot;&gt;https://nota.tistory.com/m/53&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Web &amp;amp; Server/OS, Windows, Linux</category>
      <category>compress</category>
      <category>Linux</category>
      <category>tar</category>
      <category>tar.gz</category>
      <category>압축</category>
      <author>Simplify - Jonghun</author>
      <guid isPermaLink="true">https://4urdev.tistory.com/106</guid>
      <comments>https://4urdev.tistory.com/106#entry106comment</comments>
      <pubDate>Wed, 12 Feb 2020 22:56:29 +0900</pubDate>
    </item>
    <item>
      <title>제이버드 비스타 개봉기 - JayBird VISTA Open box</title>
      <link>https://4urdev.tistory.com/105</link>
      <description>&lt;p&gt;최근 들어서, 블루투스 이어폰을 사용하는 것이 아주 쉽게 보입니다. 지하철 등 공공장소에서 보면 다양한 종류의 무선 이어폰들을 사용하는 것을 볼 수 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;블루투스 이어폰을 처음 접한 것은 LG Tone+ 750 제품이었던 것으로 기억합니다. 줄감기 기능조차 없는 초창기 모델이었는데, 단순히 궁금증에, 그리고 다들 편하게들 사용한다는 이유로 일찌감치부터 사용했습니다. 그 이후로 '명작'으로 불리우는 1000번대 시리즈가 나오고 줄감기 기능이나 각종 향상된 음질을 제공하면서 그 발전을 함께해온 것 같습니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;최근, 애플에서 출시된 에어팟 프로도 구입을 해서 사용을 했었는데, 안타깝게도 해당 제품은 리뷰할 시간도 없이 바로 사용했던 것 같습니다. (회사에서 수령해서 바로 충전하고 사용) 아이폰, 아이패드, 맥북에서 아주 쉽게 사용할 수 있었고, 제게는 별로 쓸모가 없었지만 노이즈 캔슬링 기능은 정말 너무 좋은 기능이었습니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;그리고 나서 최근, 다시 2개의 폰을 가지고 다닐 수 밖에 없는 상황이 되어 안드로이드 폰(갤럭시 S10)에 에어팟 프로를 연결해서 사용했는데... 아무래도 제품 특성상 연결이 고르지 못하거나 소리가 너무 작거나, 자주 끊기는 등의 문제를 겪을 수 밖에 없었습니다. 또한, 운동에 대해서 항상 관심을 가지고 있어, 운동용으로 에어팟 프로는 크게 괌심이 가진 않았습니다. 그 결정적인 이유가 바로 '땀', '방수' 입니다. 운동을 하게 되면 땀도 나고 무심결에, 물기가 묻게 되는 경우가 있는데 에어팟의 경우 운동에 최적화된 것은 아니어서 인지, 적합하다는 느낌은 못받았습니다. 물론 운동용으로 못쓸 제품은 아닙니다만, 앞서 말한 문제점들이 복합적이었겠지요..&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;서론이 길었지만, 결국 눈독들이고 있던 제이버드의 비스타를 구입하여 개봉기를 올립니다. 사실 구입하여 수령한 지는 10일? 가량 지난 것 같습니다만, 어차피 사용하면서 느낀점들도 적을 것이기 때문에 이제서라도 올립니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;구입, 수령&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;우선 구입은 여러가지 루트를 뒤져봐도 20만원이 훌쩍 넘는 가격이라, 제때 배송해 줄 것 같은 곳을 골라 네이버페이로 질렀습니다. 네이버 페이 충전 + 후기 등록 등등 해서 조금 적립을 받았고, 해당 페이지에서 (공유는 하지 않겠습니다. 다들 주는 편이라) 신세계 상품권 4만원어치를 사은품으로 제공해주기 때문에 위암을 삼았습니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;20200205_190258.jpg&quot; data-origin-width=&quot;4032&quot; data-origin-height=&quot;3024&quot; width=&quot;500&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/8Hrs2/btqBS7cCgzy/vrGDDjYiwTkM0RJXlRPDd0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/8Hrs2/btqBS7cCgzy/vrGDDjYiwTkM0RJXlRPDd0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/8Hrs2/btqBS7cCgzy/vrGDDjYiwTkM0RJXlRPDd0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F8Hrs2%2FbtqBS7cCgzy%2FvrGDDjYiwTkM0RJXlRPDd0%2Fimg.jpg&quot; data-filename=&quot;20200205_190258.jpg&quot; data-origin-width=&quot;4032&quot; data-origin-height=&quot;3024&quot; width=&quot;500&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;박스는 생각했던 것 보다 엄청 큰 사이즈였지만, 깔끔하게 포장, 단단한 박스여서 좀 믿음이 갔습니다. 물론 제품에 대한 여러 스펙이나 사양은 너무 많이 검색을 해놔서 별로 크게 와닿지는 않았습니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;20200205_190323.jpg&quot; data-origin-width=&quot;4032&quot; data-origin-height=&quot;3024&quot; width=&quot;500&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bcZOjl/btqBUAST3s6/5WeMwSmXNAsaTXLNu7lGvK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bcZOjl/btqBUAST3s6/5WeMwSmXNAsaTXLNu7lGvK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bcZOjl/btqBUAST3s6/5WeMwSmXNAsaTXLNu7lGvK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbcZOjl%2FbtqBUAST3s6%2F5WeMwSmXNAsaTXLNu7lGvK%2Fimg.jpg&quot; data-filename=&quot;20200205_190323.jpg&quot; data-origin-width=&quot;4032&quot; data-origin-height=&quot;3024&quot; width=&quot;500&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;20200205_190332.jpg&quot; data-origin-width=&quot;4032&quot; data-origin-height=&quot;3024&quot; width=&quot;500&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kH5s0/btqBW1hc3k2/ktnNDI8Ns01wLlpZYYKxWk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kH5s0/btqBW1hc3k2/ktnNDI8Ns01wLlpZYYKxWk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kH5s0/btqBW1hc3k2/ktnNDI8Ns01wLlpZYYKxWk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkH5s0%2FbtqBW1hc3k2%2FktnNDI8Ns01wLlpZYYKxWk%2Fimg.jpg&quot; data-filename=&quot;20200205_190332.jpg&quot; data-origin-width=&quot;4032&quot; data-origin-height=&quot;3024&quot; width=&quot;500&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;제이버드는 나름 깔끔한 인터페이스의 전용 앱을 제공합니다. 전용앱을 쓰지 않아도 그대로 사용할 수 있고, 큰 문제없지만, 전용 앱을 사용하면 각각의 배터리 상태 정보 등을 볼 수 있고,(좌/우 따로) 가장 중요한 여러가지 프리셋들을 사용할 수 있습니다. 프리셋은 다른 사람이 올려놓은 것을 공유해서 볼 수도있고, 제가 직접 만들고 공유도 가능합니다. (마켓 개념) 아직까지는 설치해서 잘 사용하고 있지만, 딱히 필요없어지면 지울지도 모릅니다. (결정적으로 알림을 쓸 수가 없어, 휴대폰 장체의 설정에서 강제로 숨겨줘야 합니다.)&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;20200205_190436.jpg&quot; data-origin-width=&quot;4032&quot; data-origin-height=&quot;3024&quot; width=&quot;500&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rCgof/btqBVf8BRxV/0edn2sHPBNv2Fvwvzv0Do0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rCgof/btqBVf8BRxV/0edn2sHPBNv2Fvwvzv0Do0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rCgof/btqBVf8BRxV/0edn2sHPBNv2Fvwvzv0Do0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FrCgof%2FbtqBVf8BRxV%2F0edn2sHPBNv2Fvwvzv0Do0%2Fimg.jpg&quot; data-filename=&quot;20200205_190436.jpg&quot; data-origin-width=&quot;4032&quot; data-origin-height=&quot;3024&quot; width=&quot;500&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;20200205_190447.jpg&quot; data-origin-width=&quot;4032&quot; data-origin-height=&quot;3024&quot; width=&quot;500&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lcmPf/btqBUSFMft1/X0KnkW4AKjusaqtwpxkqK1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lcmPf/btqBUSFMft1/X0KnkW4AKjusaqtwpxkqK1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lcmPf/btqBUSFMft1/X0KnkW4AKjusaqtwpxkqK1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlcmPf%2FbtqBUSFMft1%2FX0KnkW4AKjusaqtwpxkqK1%2Fimg.jpg&quot; data-filename=&quot;20200205_190447.jpg&quot; data-origin-width=&quot;4032&quot; data-origin-height=&quot;3024&quot; width=&quot;500&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;내부 패키지 역시 너무나 깔끔하고 책을 펼치듯 열면 제품이 있습니다. 위 사진에서 제품 양옆으로 각진 부분이 보이는데 접힌 것이 아니라, 패키지 자체가 입체감을 준 것입니다. 위에는 케이스와 그 안에 비스타 양쪽이 들어있고, 아래쪽 박스를 열면 여러 구성품과 여분의 이어팁?이 들어 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;이어팁에는 번호가 적혀 있는데, 기본적으로는 2번이 장착되어 있습니다. 처음에 빠질까봐 걱정되서 과감히 3번으로 교체해서 사용했는데, 사용시작한지 10여분만에 다시 2번으로 돌아왔습니다. &lt;s&gt;지금도 사실 너무 꽉 끼는게 아닌가 싶어 1번도 도전해 볼 생각입니다.&lt;/s&gt; 1번은 귓바퀴에 고정되는 부분이 너무 작아 포기합니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;충전기, 사용편의&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;제품은 3가지 색상으로 출시되었는데, 저는 별로 고민하지 않고 검정으로 선택했습니다. 검정이 가장 무난하거든요. 아래 그림과 같이 내부는 노란색이라 살짝 망설였지만, 그대로 블랙으로 주문하였습니다. 해당 충전기에서 분리하면 바로 기존 연결된 장치(휴대폰)에 연결되고, 앞서 소개한 어플을 이용하면 안내 음성의 언어도 변경할 수 있습니다. 한국어는 조금 어색하게 들리는 듯 하여 그냥 영어로 사용중입니다.&amp;nbsp;&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-filename=&quot;20200205_190510.jpg&quot; data-origin-width=&quot;4032&quot; data-origin-height=&quot;3024&quot; width=&quot;500&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/beU4SC/btqBWqV4xpe/Y4XwWrkF2b8L0GmfKXmJkk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/beU4SC/btqBWqV4xpe/Y4XwWrkF2b8L0GmfKXmJkk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/beU4SC/btqBWqV4xpe/Y4XwWrkF2b8L0GmfKXmJkk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbeU4SC%2FbtqBWqV4xpe%2FY4XwWrkF2b8L0GmfKXmJkk%2Fimg.jpg&quot; data-filename=&quot;20200205_190510.jpg&quot; data-origin-width=&quot;4032&quot; data-origin-height=&quot;3024&quot; width=&quot;500&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;20200205_190550.jpg&quot; data-origin-width=&quot;4032&quot; data-origin-height=&quot;3024&quot; width=&quot;500&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Y0Xfy/btqBS65NiSi/HRMkuhNUHKbvkd07K0rNg0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Y0Xfy/btqBS65NiSi/HRMkuhNUHKbvkd07K0rNg0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Y0Xfy/btqBS65NiSi/HRMkuhNUHKbvkd07K0rNg0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FY0Xfy%2FbtqBS65NiSi%2FHRMkuhNUHKbvkd07K0rNg0%2Fimg.jpg&quot; data-filename=&quot;20200205_190550.jpg&quot; data-origin-width=&quot;4032&quot; data-origin-height=&quot;3024&quot; width=&quot;500&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;충전은 USB-C 타입으로 충전 가능합니다. 사실 얼마 전 까지 사용했던 LG Tone+ 1700 제품이 micro-USB 라서 너무 맘에 들지 않았는데, 이 제품은 USB-C 라서 너무 반갑습니다. 저렇게 꽂아놓으면 한참 깜빡이는데, 충전이 다되도 깜빡이는 느낌은 기분탓이겠죠..?&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;총평, 결론&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;20200205_190723.jpg&quot; data-origin-width=&quot;4032&quot; data-origin-height=&quot;3024&quot; width=&quot;500&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/RzIbb/btqBTK9dRDl/VmOfbq6XNUXeX01kRSKkKK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/RzIbb/btqBTK9dRDl/VmOfbq6XNUXeX01kRSKkKK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/RzIbb/btqBTK9dRDl/VmOfbq6XNUXeX01kRSKkKK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FRzIbb%2FbtqBTK9dRDl%2FVmOfbq6XNUXeX01kRSKkKK%2Fimg.jpg&quot; data-filename=&quot;20200205_190723.jpg&quot; data-origin-width=&quot;4032&quot; data-origin-height=&quot;3024&quot; width=&quot;500&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;사실 음질이나 저음이 어쩌고.. 그런 이야기 잘 모릅니다. 그저 음악이 깔끔하게, 왜곡없이 들리기만 바랬을 뿐이고 방수기능, 그리고 연결성, 운동중에도 잘 떨어지지 않을 만큼 견고함이 필요했습니다. 이러한 점에 초점을 두신다면 아마 저처럼 최고로 만족할 만 한 이어폰이라고 할 수 있겠습니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;다만, 1~2번 이어팁의 격차?가 너무 커서 그 중간 레벨이 있으면 좋겠다는 점이 아쉬운 점으로 남아있고, 고무 제질 특성 상 어쩔 수 없이 먼지가 좀 묻는다는 점도 아쉬운 점입니다. (어쩔수 없겠지요) 제품 등록 등을 통해서 제품에 대한 보증을 받을 수 있고, 본인의 제품에 대해서 서비스 받을 수 있게 (나의 기기로 등록) 되었으면 하는 아쉬움도 남습니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;또한 최근 여러가지 이유로 마스크를 착용하고 다니는데, 마스크 착용시 귀에 거는 끈이 앞으로 귀를 당기게 되면, 이 형태의 이어팁이 귀에 살짝 무리를 준다는 점입니다. 아주 신경쓰이는 것은 아닌데 이어팁은 뒤로 밀려고 하고(고정되야 하니까) 마스크 끈은 앞으로 당겨져서 귓바퀴가 살짝 눌리는 느낌이 듭니다. (꼬집는 정도는 아닙니다)&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;운동을 슬슬 하려했는데 아직 추위가 남아 다음주로 미룹니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;운동 시작하게 되면 다시 한 번 포스팅 할 기회가 있었으면 좋겠네요..^^&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>NEWS/Review</category>
      <category>JayBird</category>
      <category>Vista</category>
      <category>블루투스</category>
      <category>비스타</category>
      <category>이어폰</category>
      <category>제이버드</category>
      <author>Simplify - Jonghun</author>
      <guid isPermaLink="true">https://4urdev.tistory.com/105</guid>
      <comments>https://4urdev.tistory.com/105#entry105comment</comments>
      <pubDate>Wed, 12 Feb 2020 00:19:12 +0900</pubDate>
    </item>
    <item>
      <title>Java Executor 에 대해 - About Java Executor</title>
      <link>https://4urdev.tistory.com/104</link>
      <description>&lt;p&gt;Java에서 이야기하는 Executor 에 대해서 잘 정리되어 있는 글이 있어, 학습하고자 참고하여 문서를 남깁니다. 모든 내용을 담고 있지는 않으므로, 아래 출처 / 참고자료 부분에 있는 링크를 따라가서 보시기 바랍니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;사실 Executor 까지 참고하여 구현하게 되는 상황이 얼마나 될까 싶긴 합니다. 특히 저 처럼 업무(기능) 개발 위주로 업무를 진행하는 사람들은 기능 개발에 급급할 뿐 그 이상의 깊이있는 내용을 찾아보는 것이 쉽지는 않습니다. 물론, 다양한 부분에 대해서 찾아보고, 깊이있는 학습을 진행하는 것은 업무 개발에 있어서도 도움은 많이 될 것입니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;일반적으로..&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;아래와 같은 소스 코드.. 아마도 서버 측 프로그램을 조금이라도 들여다 본 분이라면 이와 같은 형태를 접했을 것입니다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1578036197158&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;while(true){
  Request request = acceptRequest();
  Runnable requestHAndler = new RequestHandler(request);
  new Thread(requestHandler).start();
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;클라이언트에서 오는 요청 정보를 받아서, 이 요청 정보를 처리하는 handler 에 정보를 담고, 그 handler(runnable)를 Thread 를 생성하여 실행하는 소스입니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;위와 같이 처리하면 개발 과정에서 몇 번의 테스트에서는 정상적으로 잘 동작하는 것 처럼 보입니다. 물론 이 코드에 문제가 있다기 보다는 서버 측 개발에서는 아래와 같은 점이 전혀 고려되지 않았다는 점이 문제입니다.&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Thread 를 매 번 new 하기 때문에 resource가 무한정 생성되어 Memory leak 이 발생할 수 있습니다. 물론 이 문제는 아주 천천히 - JVM이 handle할 수 있는 수준에서의 요청에 대해서는 GC가 동작하여 적절하게 메모리를 관리해 줄 수 있습니다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Thread 생성 및 종료에 따른 오버헤드가 발생하고, 많은 수의 Thread 가 생성되는 경우 이를 스케쥴링 하는 데 있어서 오버헤드도 발생합니다. 단순히 매번 new 하는 것이 속도 저하에 문제가 되고, 서버 운영 측면에서는 JVM에 부하를 주는 요소일 수 있습니다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;이를 해결하기 위해서 아래와 같은 부분이 서버 프로그래밍에는 추가되어 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Map 과 같은 Thread Pool 을 이용하여 총 생성될 수 있는 Thread 개수를 제한하고, 유휴 상태인 Thread를 이용하여 다음 작업을 수행합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;이러한 해결방법과 유사하게, 이를 더 편하게 하고 관리 측면에서도 유리하게 하기 위해 &lt;span&gt;Java5 부터 &lt;/span&gt;&lt;span class=&quot;hl-text&quot;&gt;Executor&lt;/span&gt; 인터페이스&lt;span&gt;(&lt;b&gt;concurrency api&lt;/b&gt;)를 제공하고 있으며, 그 구현체로 쓰레드 풀, 큐등을 다양하게 제공하고 있습니다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;Executor 에 대해..&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/JFdys/btqASyVbQVY/rF4Vpz23cveqqFTni9bnC0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/JFdys/btqASyVbQVY/rF4Vpz23cveqqFTni9bnC0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/JFdys/btqASyVbQVY/rF4Vpz23cveqqFTni9bnC0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FJFdys%2FbtqASyVbQVY%2FrF4Vpz23cveqqFTni9bnC0%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;Java Executor 는 위와 같은 구조로 되어 있습니다. 이제 각각의 요소들이 어떻게 이루어져 있는 지 조금 더 상세하게 살펴보려고 합니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Executor&amp;nbsp;인터페이스&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;제공된 작업(Runnable 구현체)을 실행 하는 객체가 구현해야할 인터페이스입니다. 이 인터페이스는 작업을 제공 하는 코드와 작업을 실행 하는 매커니즘 사이의 커플링을 제거해 줍니다.&lt;/p&gt;
&lt;pre id=&quot;code_1578037844487&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package java.util.concurrent.Executor;
  
public interface Executor {
    void excute(Runnable command);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;ExecutorService&amp;nbsp;인터페이스&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Executor 의 라이프 사이클을 관리할 수 있는 기능을 정의 합니다. Runnable 뿐만 아니라 Callable 도 작업으로 사용할 수 있습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;void&amp;nbsp;shutdown();&amp;nbsp;&lt;br /&gt;이미 Executor 에 전달된 작업은 실행되지만, 새로운 작업은 받지 않습니다.&lt;/li&gt;
&lt;li&gt;List&amp;lt;&amp;nbsp;Runnable&amp;nbsp;&amp;gt;&amp;nbsp;shutdownNow();&amp;nbsp;&lt;br /&gt;현재 실행되고 있는 작업을 모두 중지 시키고, 현재 대기 하고 있는 작업을 멈추게 합니다. 그리고 현재 실행되기 위해 대기중인 작업 목록 리스트를 반환합니다.&lt;/li&gt;
&lt;li&gt;boolean&amp;nbsp;isShutdown();&amp;nbsp;&lt;br /&gt;Executor 가 셧다운 되었는지의 여부를 반환합니다.&lt;/li&gt;
&lt;li&gt;boolean&amp;nbsp;isTerminated();&amp;nbsp;&lt;br /&gt;shutdown() 실행 후, 모든 작업이 종료되었는지 여부를 확인한다.&lt;/li&gt;
&lt;li&gt;boolean&amp;nbsp;awaitTermination(long&amp;nbsp;timeout,&amp;nbsp;TimeUnit&amp;nbsp;unit);&amp;nbsp;&lt;br /&gt;셧다운을 실행한 뒤, 지정한 시간 동안 모든 작업이 종료될 때 까지 대기한다. 지정한 시간 이내에서 실행중인 모든 작업이 종료되면 true를 리턴하고, 여전히 실행중인 작업이 남아 있다면 false를 리턴한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1578038308432&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;excutor.shutdown(); 

try{ 
    if(!excutor.awaitTermination(5, TimeUnit.SECONDS)){ 
        System.out.println(&quot;아직 처리중인 작업 존재&quot;); 
        System.out.println(&quot;작업 강제 종료 실행&quot;); 
        excutor.shutdownNow(); 
        if(!executor.awaitTermination(5, TimeUnit.SECONDS)) { 
            System.out.println(&quot;여전히 종료하지 않은 작업 존재&quot;); 
        } 
    } 
} catch (InterruptedException e) { 
    excutor.shutdownNow(); 
    Thread.currentThread().interrupt(); 
} 

System.out.println(&quot;서버 셧다운 완료&quot;); &lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;ExecutorService&amp;nbsp;인터페이스는&amp;nbsp;작업&amp;nbsp;수행과&amp;nbsp;관련해서&amp;nbsp;추가적으로&amp;nbsp;메소드를&amp;nbsp;제공하고&amp;nbsp;있습니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&amp;lt; T &amp;gt; Future&amp;lt; T &amp;gt;submit(Callable&amp;lt; T &amp;gt; task) &lt;br /&gt;결과값을 리턴하는 작업을 추가한다.&lt;/li&gt;
&lt;li&gt;Future&amp;lt;?&amp;gt; submit(Runnable task) &lt;br /&gt;결과값이 없는 작업을 추가한다.&lt;/li&gt;
&lt;li&gt;&amp;lt;&amp;nbsp;T&amp;nbsp;&amp;gt;&amp;nbsp;Future&amp;lt;&amp;nbsp;T&amp;nbsp;&amp;gt;&amp;nbsp;submit(Runnable&amp;nbsp;task,&amp;nbsp;T&amp;nbsp;result)&amp;nbsp;&lt;br /&gt;새로운 작업을 추가한다. result는 작업이 성공적으로 수행될 때 사용될 리턴 값을 의미한다.&lt;/li&gt;
&lt;li&gt;&amp;lt;&amp;nbsp;T&amp;nbsp;&amp;gt;&amp;nbsp;List&amp;lt;Future&amp;lt;&amp;nbsp;T&amp;nbsp;&amp;gt;&amp;nbsp;&amp;gt;&amp;nbsp;invokeAll(Collections&amp;lt;?&amp;nbsp;extends&amp;nbsp;Callable&amp;lt;&amp;nbsp;T&amp;nbsp;&amp;gt;&amp;nbsp;&amp;gt;&amp;nbsp;tasks)&amp;nbsp;&lt;br /&gt;주어진 작업을 모두 실행한다. 각 실행 결과값을 구할 수 있는 Future의 list 를 리턴한다.&lt;/li&gt;
&lt;li&gt;&amp;lt; T &amp;gt; List&amp;lt;Future&amp;lt; T &amp;gt; &amp;gt; invokeAll(Collections&amp;lt;? extends Callable&amp;lt; T &amp;gt; &amp;gt; tasks , long timeout, TimeUnit unit)&lt;br /&gt;위의 invokeAll() 과 동일하다. 지정한 시간 동안 완료되지 못한 작업은 취소되는 차이점이 있다.&lt;/li&gt;
&lt;li&gt;&amp;lt;&amp;nbsp;T&amp;nbsp;&amp;gt;&amp;nbsp;invokeAny(Collection&amp;lt;?&amp;nbsp;extends&amp;nbsp;Callable&amp;lt;&amp;nbsp;T&amp;nbsp;&amp;gt;&amp;nbsp;&amp;gt;&amp;nbsp;tasks)&amp;nbsp;&lt;br /&gt;작업을 수행하고, 작업 결과 중 성공적으로 완료된 것의 결과를 리턴한다. 정상적으로 수행된 결과가 발생하거나 예외가 발생하는 경우 나머지 완료되지 않은 작업은 취소된다.&lt;/li&gt;
&lt;li&gt;T&amp;nbsp;invokeAny(Collections&amp;lt;?&amp;nbsp;extends&amp;nbsp;Callable&amp;lt;&amp;nbsp;T&amp;nbsp;&amp;gt;&amp;nbsp;&amp;gt;&amp;nbsp;tasks,&amp;nbsp;long&amp;nbsp;timeout,&amp;nbsp;TimeUnit&amp;nbsp;unit)&amp;nbsp;&lt;br /&gt;invokeAny() 와 동일하다. 지정한 시간 동안만 대기한다는 차이점이 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;Callable 은 Runnable 과 비슷한데, 차이점이 있다면 결과 값을 리턴할 수 있다는 점이다. Future 는 Callable의 결과값을 구하는 데 사용됩니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;ScheduledExecutorService 인터페이스&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Executor 구현체&lt;/b&gt;&lt;span&gt;는 전달받은 작업을 큐에 넣은 후, 사용할 수 있는 스레드가 존재하면, 해당 스레드에 작업을 실행 하도록 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 id=&quot;executor-----&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;Executor 를 이용하여 스레드를 실행하는 코드&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1578038728291&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// Excutor 를 이용한 스레드 실행.
Excutor excutor = new SomeExcutor();

while(true) {
    Request request = acceptRequest();
    Runnable requestHandler = new RequestHandler(request);
    excutor.excute(requestHandler);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;출처 / 참고자료&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://devarchi33.github.io/java/Java-Excutor-%EA%B8%B0%EC%B4%88/&quot;&gt;https://devarchi33.github.io/java/Java-Excutor-%EA%B8%B0%EC%B4%88/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Other/Java</category>
      <author>Simplify - Jonghun</author>
      <guid isPermaLink="true">https://4urdev.tistory.com/104</guid>
      <comments>https://4urdev.tistory.com/104#entry104comment</comments>
      <pubDate>Fri, 3 Jan 2020 15:59:14 +0900</pubDate>
    </item>
  </channel>
</rss>