<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>AnOldStory</title>
    <link>https://anoldstory.tistory.com/</link>
    <description>심심할때 쓰는 취준생의 삽질 했던 과거 기록</description>
    <language>ko</language>
    <pubDate>Wed, 6 May 2026 21:32:00 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>AnOldStory</managingEditor>
    <image>
      <title>AnOldStory</title>
      <url>https://tistory1.daumcdn.net/tistory/2967957/attach/a9cd489dfd304b858cb6d15f8c44d61c</url>
      <link>https://anoldstory.tistory.com</link>
    </image>
    <item>
      <title>SSL/TLS 인증서 적용하기 (Cloudflare or Let's Encrypt with NPM)</title>
      <link>https://anoldstory.tistory.com/9</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;1. SSL/TLS 인증서&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;SSL이란 흔히 서버와 클라이언트가 통신할때 암호화를 위해 사용된다.&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;흔히 우리가 쉽게 말하자면 웹사이트를 제작할때 https를 입히려고할때 한다.&lt;/span&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;2. Cloudflare SSL/TLS 방식&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;Cloudflare의 SSL 인증 방식은 총 4가지가있다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;( &lt;span style=&quot;text-align: center;&quot;&gt;&amp;larr; &amp;rarr;&lt;/span&gt; 는 SSL로 연결됨, &lt;span style=&quot;text-align: center;&quot;&gt;&amp;larr;─&amp;rarr;&lt;/span&gt; &amp;nbsp;는 일반적으로 연결됨을 의미한다)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;1. 끄기&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;브라우저 &amp;larr;─&amp;rarr; Cloudflare &amp;larr;─&amp;rarr; 원본서버&lt;br /&gt;&lt;/span&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;489&quot; data-origin-height=&quot;139&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cSzkYK/btsHdvp8gXk/7uKLnyffiNywPgdjPdK3oK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cSzkYK/btsHdvp8gXk/7uKLnyffiNywPgdjPdK3oK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cSzkYK/btsHdvp8gXk/7uKLnyffiNywPgdjPdK3oK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcSzkYK%2FbtsHdvp8gXk%2F7uKLnyffiNywPgdjPdK3oK%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;489&quot; height=&quot;139&quot; data-origin-width=&quot;489&quot; data-origin-height=&quot;139&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/blockquote&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;아무 암호화도 적용되지않는다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;2. 가변&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;브라우저 &amp;larr; &amp;rarr; Cloudflare &amp;larr;─&amp;rarr; 원본서버&lt;br /&gt;&lt;/span&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;496&quot; data-origin-height=&quot;130&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/OANA2/btsHbTyJ7uH/ogRoHgIECwvxduzmLqAXi0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/OANA2/btsHbTyJ7uH/ogRoHgIECwvxduzmLqAXi0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/OANA2/btsHbTyJ7uH/ogRoHgIECwvxduzmLqAXi0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FOANA2%2FbtsHbTyJ7uH%2FogRoHgIECwvxduzmLqAXi0%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;496&quot; height=&quot;130&quot; data-origin-width=&quot;496&quot; data-origin-height=&quot;130&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;사용자 입장에서는 HTTPS가 적용된 것으로 보이나 사실은 &lt;b&gt;Cloudflare와 원본 사이 트래픽은 암호화가 되어있지 않다.&lt;/b&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;3. 전체&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;브라우저 &amp;larr; &amp;rarr; Cloudflare &amp;larr; &amp;rarr; 원본서버&lt;br /&gt;&lt;/span&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;493&quot; data-origin-height=&quot;140&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rtE6n/btsHdtTnhBx/TxXBuuZ5RPpv9fDtlUywNK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rtE6n/btsHdtTnhBx/TxXBuuZ5RPpv9fDtlUywNK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rtE6n/btsHdtTnhBx/TxXBuuZ5RPpv9fDtlUywNK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FrtE6n%2FbtsHdtTnhBx%2FTxXBuuZ5RPpv9fDtlUywNK%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;493&quot; height=&quot;140&quot; data-origin-width=&quot;493&quot; data-origin-height=&quot;140&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;모든 구간이 SSL로 연결되어있다.&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;4. 전체(엄격)&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;브라우저 &amp;larr; &amp;rarr; Cloudflare &lt;span style=&quot;text-align: center;&quot;&gt;&amp;larr; &amp;rarr;&lt;/span&gt; 원본서버&lt;br /&gt;&lt;/span&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;504&quot; data-origin-height=&quot;132&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/tuDEx/btsHbtfZhp5/KUZ4jo5wetQhqquyWLv8Sk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/tuDEx/btsHbtfZhp5/KUZ4jo5wetQhqquyWLv8Sk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/tuDEx/btsHbtfZhp5/KUZ4jo5wetQhqquyWLv8Sk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FtuDEx%2FbtsHbtfZhp5%2FKUZ4jo5wetQhqquyWLv8Sk%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;504&quot; height=&quot;132&quot; data-origin-width=&quot;504&quot; data-origin-height=&quot;132&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/blockquote&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;모든 구간이 SSL로 연결되어있다. 그러나 Cloudflare와 원본 서버 사이에는 &lt;b&gt;신뢰할 수 있는 &lt;/b&gt;인증서만 사용된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;3. Cloudflare 인증서 발급&lt;/span&gt;&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Cloudflare에서는&amp;nbsp;3가지&amp;nbsp;인증서를&amp;nbsp;발급해준다. &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;브라우저&amp;nbsp;&amp;larr;&amp;nbsp;ⓐ&amp;nbsp;&amp;rarr;&amp;nbsp;&amp;nbsp;Cloudflare&amp;nbsp;&amp;larr;&amp;nbsp;&amp;nbsp;ⓑ&amp;nbsp;&amp;rarr;&amp;nbsp;&amp;nbsp;원본서&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt; &lt;br /&gt;1.&amp;nbsp;에지&amp;nbsp;인증서&amp;nbsp;(Edge) &lt;br /&gt;해당&amp;nbsp;인증서는&amp;nbsp;브라우저와&amp;nbsp;Cloudflare간의&amp;nbsp;ⓐ구간에서&amp;nbsp;사용되는&amp;nbsp;인증서이다.&amp;nbsp;별도로&amp;nbsp;다운&amp;nbsp;받을&amp;nbsp;순&amp;nbsp;없고&amp;nbsp;업로드만이&amp;nbsp;허용된다&amp;nbsp;(유료) &lt;br /&gt;&lt;br /&gt;2.&amp;nbsp;클라이언트&amp;nbsp;인증서&amp;nbsp;(Client) &lt;br /&gt;해당&amp;nbsp;인증서는&amp;nbsp;말그대로&amp;nbsp;사용자의&amp;nbsp;Client에&amp;nbsp;미리&amp;nbsp;허용해두는&amp;nbsp;인증서이다.&amp;nbsp;해당&amp;nbsp;인증서를&amp;nbsp;사용하기위해선&amp;nbsp;유저와&amp;nbsp;서버에&amp;nbsp;모두&amp;nbsp;설정해두어야&amp;nbsp;사용&amp;nbsp;할&amp;nbsp;수&amp;nbsp;있다. &lt;br /&gt;&lt;br /&gt;3.&amp;nbsp;원본&amp;nbsp;서버&amp;nbsp;(Origin&amp;nbsp;Certificate&amp;nbsp;Authrority&amp;nbsp;보&amp;nbsp;CA라고함) &lt;br /&gt;해당 인증서는 Cloudflare와 원본서버 간 ⓑ구간에서 사용되는 인증서이다. 서버에 적용시켜두면 작동은 하나 최대 단점으로는 클라이언트가 바로 직접 접속할 시 인증서를 신뢰 할 수 없다 오류가 표시된다. &lt;a href=&quot;https://developers.cloudflare.com/ssl/origin-configuration/origin-ca/#troubleshooting&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;(Cloudflare Docs 참고)&lt;/a&gt;&lt;/span&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #333333;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1714911251342&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;Origin CA certificates &amp;middot; Cloudflare SSL/TLS docs&quot; data-og-description=&quot;Origin Certificate Authority (CA) certificates allow you to encrypt traffic between Cloudflare and your origin web server, and reduce origin bandwidth &amp;hellip;&quot; data-og-host=&quot;developers.cloudflare.com&quot; data-og-source-url=&quot;https://developers.cloudflare.com/ssl/origin-configuration/origin-ca/#troubleshooting&quot; data-og-url=&quot;https://developers.cloudflare.com/ssl/origin-configuration/origin-ca/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/conTFz/hyVZg6ZQtf/IcU9CRkxhXkBNcxyw7NNyk/img.png?width=1200&amp;amp;height=601&amp;amp;face=0_0_1200_601,https://scrap.kakaocdn.net/dn/uH5I7/hyVZglEOWL/jcQ9zkSTNVnOoKob5LWvak/img.png?width=1200&amp;amp;height=601&amp;amp;face=0_0_1200_601&quot;&gt;&lt;a href=&quot;https://developers.cloudflare.com/ssl/origin-configuration/origin-ca/#troubleshooting&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://developers.cloudflare.com/ssl/origin-configuration/origin-ca/#troubleshooting&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/conTFz/hyVZg6ZQtf/IcU9CRkxhXkBNcxyw7NNyk/img.png?width=1200&amp;amp;height=601&amp;amp;face=0_0_1200_601,https://scrap.kakaocdn.net/dn/uH5I7/hyVZglEOWL/jcQ9zkSTNVnOoKob5LWvak/img.png?width=1200&amp;amp;height=601&amp;amp;face=0_0_1200_601');&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;Origin CA certificates &amp;middot; Cloudflare SSL/TLS docs&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Origin Certificate Authority (CA) certificates allow you to encrypt traffic between Cloudflare and your origin web server, and reduce origin bandwidth &amp;hellip;&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;developers.cloudflare.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;4. Let's Encrypt with NPM(Nginx Proxy Manager) 기준&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;필자는 NPM(Nginx Proxy Manager)와 Cloudflare을 사용하여 설명하겠다. 사실상 내부적으로는 Let's Encrypt를 사용하는 것과 동일하다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;NPM 로그인 &amp;gt; SSL Certificates &amp;gt; Add SSL Certificate로 들어간 후 아래의 포맷 대로 작성한다.&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;496&quot; data-origin-height=&quot;880&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mLPQb/btsHbmuFb9X/Z3HIUva4dPTUunqToVFWF1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mLPQb/btsHbmuFb9X/Z3HIUva4dPTUunqToVFWF1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mLPQb/btsHbmuFb9X/Z3HIUva4dPTUunqToVFWF1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmLPQb%2FbtsHbmuFb9X%2FZ3HIUva4dPTUunqToVFWF1%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;496&quot; height=&quot;880&quot; data-origin-width=&quot;496&quot; data-origin-height=&quot;880&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;span style=&quot;text-align: start;&quot;&gt;여기서 &amp;lt;Cloudflare API Key&amp;gt;는&amp;nbsp;&lt;/span&gt;&lt;a href=&quot;https://dash.cloudflare.com/profile/api-tokens&quot;&gt;https://dash.cloudflare.com/profile/api-tokens&lt;/a&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;1019&quot; data-origin-height=&quot;120&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Rl9qH/btsHdfgvluj/FbKxOrvlBhUx2oeVgWepHk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Rl9qH/btsHdfgvluj/FbKxOrvlBhUx2oeVgWepHk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Rl9qH/btsHdfgvluj/FbKxOrvlBhUx2oeVgWepHk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FRl9qH%2FbtsHdfgvluj%2FFbKxOrvlBhUx2oeVgWepHk%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;1019&quot; height=&quot;120&quot; data-origin-width=&quot;1019&quot; data-origin-height=&quot;120&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;토큰 생성 &amp;gt; 영역 DNS 편집 템플릿 사용을 들어가고&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;909&quot; data-origin-height=&quot;949&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/FPjfU/btsHa3ISCAm/pRC5kxwXMqrTMIoZ13VQ81/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/FPjfU/btsHa3ISCAm/pRC5kxwXMqrTMIoZ13VQ81/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/FPjfU/btsHa3ISCAm/pRC5kxwXMqrTMIoZ13VQ81/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FFPjfU%2FbtsHa3ISCAm%2FpRC5kxwXMqrTMIoZ13VQ81%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;909&quot; height=&quot;949&quot; data-origin-width=&quot;909&quot; data-origin-height=&quot;949&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;이와 같이 설정하고 요약 계속 &amp;gt; 토큰 생성 을하면&amp;nbsp; 해당 값이 생성된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;다만 NPM이 80포트가 열려있어야 자동적으로 SSL 파일이 생성된다.&lt;/span&gt;&lt;/p&gt;</description>
      <category>⭐개발/⭐홈서버</category>
      <category>client</category>
      <category>CloudFlare</category>
      <category>egde</category>
      <category>HTTPS</category>
      <category>nginx proxy manage</category>
      <category>npm</category>
      <category>origin</category>
      <category>SSL</category>
      <category>TLS</category>
      <category>인증서</category>
      <author>AnOldStory</author>
      <guid isPermaLink="true">https://anoldstory.tistory.com/9</guid>
      <comments>https://anoldstory.tistory.com/9#entry9comment</comments>
      <pubDate>Sun, 5 May 2024 21:10:49 +0900</pubDate>
    </item>
    <item>
      <title>집에서도 ChatGPT처럼 LLM을 사용해보기 with Ollama + OpenWebUi + Llama 3</title>
      <link>https://anoldstory.tistory.com/8</link>
      <description>&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;최근에 Meta에서 오픈소스로 풀은 &lt;a title=&quot;Llama3&quot; href=&quot;https://llama.meta.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Llama3&lt;/a&gt;가 나오면서&lt;br /&gt;집에서도 LLM을 편히 사용할 수 있을꺼같아 시도해보았다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1910&quot; data-origin-height=&quot;947&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/CQMXo/btsGS4mw1ca/l5pVricAqBhg97lBPdEyj0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/CQMXo/btsGS4mw1ca/l5pVricAqBhg97lBPdEyj0/img.png&quot; data-alt=&quot;구성 완료 후 이미지&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/CQMXo/btsGS4mw1ca/l5pVricAqBhg97lBPdEyj0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FCQMXo%2FbtsGS4mw1ca%2Fl5pVricAqBhg97lBPdEyj0%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;1910&quot; height=&quot;947&quot; data-origin-width=&quot;1910&quot; data-origin-height=&quot;947&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;구성 완료 후 이미지&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;1. 구성&lt;/h2&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;프론트엔드는 &lt;a href=&quot;https://openwebui.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;OpenWebUi&lt;/a&gt;&lt;br /&gt;백엔드는 &lt;a title=&quot;Ollama&quot; href=&quot;https://ollama.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;Ollama&lt;/a&gt; 라는 것을 사용하면된다.&lt;br /&gt;Ollama는 Docker처럼 모델들을 다운로드하고 실행시킬 수 있게 하는 프로그램이고&lt;br /&gt;OpenWebUi는 그것을 ChatGPT처럼 웹에서 사용 할 수있게하는 껍데기 같은 역할이다.&lt;br /&gt;&lt;span style=&quot;text-align: center;&quot;&gt;유저의 입력 &amp;rarr; OpenWebUi&amp;nbsp;&lt;/span&gt;&amp;rarr; Ollama &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;쉽게말하자면 Ollama만 설치해도 바로 사용 할 수 있지만&lt;br /&gt;터미널을 켜서 집 컴퓨터에 접속하여 검은창으로 사용하기 불편하다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;집에 서버용 컴퓨터(Ubuntu)와&lt;br /&gt;GPU용 메인 컴퓨터(Window)가 따로 있기에&lt;br /&gt;프론트 엔드와 백엔드를 서로 다른 컴퓨터로 구성하게 되었다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;2. Ollama 설치&lt;/h2&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://ollama.com/download&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;Ollama 다운로드 페이지&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1713918300987&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 Ollama on macOS&quot; data-og-description=&quot;Download Ollama on macOS&quot; data-og-host=&quot;ollama.com&quot; data-og-source-url=&quot;https://ollama.com/download&quot; data-og-url=&quot;https://ollama.com/download&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/t2ahv/hyVSYMuWqg/dPnwl3gVaY08wOGGk9aOAK/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630&quot;&gt;&lt;a href=&quot;https://ollama.com/download&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://ollama.com/download&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/t2ahv/hyVSYMuWqg/dPnwl3gVaY08wOGGk9aOAK/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;Download Ollama on macOS&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Download Ollama on macOS&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;ollama.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;해당 페이지에 들어가 해당 기종에 맞게 설치한다.&lt;br /&gt;추천하는건 Docker로 설치하는 것이지만 필자는 GPU 설정이 귀찮기에 그냥 설치한다.&lt;br /&gt;해당 방법은 &lt;a href=&quot;https://ollama.com/blog/ollama-is-now-available-as-an-official-docker-image&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;여기에&lt;/a&gt; 잘 설명되어있다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;Tip. exe 파일에 명령어 인자를 추가하면 설치 위치를 지정할 수 있다.&amp;nbsp;&lt;br /&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;460&quot; data-origin-height=&quot;16&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ZK8x2/btsGQ2csyCX/6GoE9iq2eX62IT5MJ4KDE1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ZK8x2/btsGQ2csyCX/6GoE9iq2eX62IT5MJ4KDE1/img.png&quot; data-alt=&quot;윈도우 기준&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ZK8x2/btsGQ2csyCX/6GoE9iq2eX62IT5MJ4KDE1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FZK8x2%2FbtsGQ2csyCX%2F6GoE9iq2eX62IT5MJ4KDE1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;460&quot; height=&quot;16&quot; data-origin-width=&quot;460&quot; data-origin-height=&quot;16&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;윈도우 기준&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;pre id=&quot;code_1713918564768&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;.\OllamaSetup.exe /DIR=D:\원하는위치&lt;/code&gt;&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;748&quot; data-origin-height=&quot;296&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cRd8Qk/btsGTdDxKTC/pNnqkgLQzWYLDW5e8hHoK1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cRd8Qk/btsGTdDxKTC/pNnqkgLQzWYLDW5e8hHoK1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cRd8Qk/btsGTdDxKTC/pNnqkgLQzWYLDW5e8hHoK1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcRd8Qk%2FbtsGTdDxKTC%2FpNnqkgLQzWYLDW5e8hHoK1%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;296&quot; data-origin-width=&quot;748&quot; data-origin-height=&quot;296&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1713918907457&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;ollama run llama3&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;명령어를 실행하면 Llama3가 다운로드 되기 시작한다.&lt;br /&gt;Default Parameter는 8b이며 4.7GB이다.&lt;br /&gt;만약 70B를 받고싶다면 llama3:70b라고 하면된다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;일반적으로 용량은 &lt;br /&gt;&lt;b&gt;&lt;u&gt;본인 GPU VRAM크기보다 작은 것을 다운&lt;/u&gt;&lt;/b&gt;받아야&lt;br /&gt;원활하게 작동한다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://ollama.com/library&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;다운로드 가능한 모델 목록&lt;/a&gt;에서 원하는 모델들을 다운로드 받을 수 있다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;이제 윈도우에서 해당 Ollama를 외부 서버에서 접근하려면 환경변수 설정이 필요하다.&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;362&quot; data-origin-height=&quot;79&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/buIJAN/btsGTBxpP3C/eXjSepDdKQ5TR9ps1cL9RK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/buIJAN/btsGTBxpP3C/eXjSepDdKQ5TR9ps1cL9RK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/buIJAN/btsGTBxpP3C/eXjSepDdKQ5TR9ps1cL9RK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbuIJAN%2FbtsGTBxpP3C%2FeXjSepDdKQ5TR9ps1cL9RK%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;362&quot; height=&quot;79&quot; data-origin-width=&quot;362&quot; data-origin-height=&quot;79&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;text-align: start;&quot;&gt;[Windows 설정] - [시스템] - [정보] - [고급 시스템 설정] - [고급] - [환경 변수] - [새로만들기]&lt;br /&gt;로 위 3가지 를 설정해주면 된다.&amp;nbsp;&lt;br /&gt;OLLAMA_HOST, OLLAMA_ORIGINS 는 외부에서 접근 가능하게 하는것&lt;br /&gt;OLLAMA_MODELS 는 모델을 저장할 위치를 지정하는 것이다.&lt;/span&gt;&lt;span style=&quot;text-align: start;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;3. OpenWebUi 설치&lt;/h2&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/open-webui/open-webui/releases&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;OpenWebUi 다운로드 페이지&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;OpenWebUI는 편히 Docker로 설치하였다.&lt;/p&gt;
&lt;pre id=&quot;code_1713920139859&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;docker run -d -p 3000:8080 --add-host=host.docker.internal:host-gateway -v open-webui:/app/backend/data --name open-webui --restart always ghcr.io/open-webui/open-webui:main&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;해당 명령어를 실행 후 &lt;br /&gt;http://localhost:3000로 접속하여 계정을 만든 후 들어가면된다.&lt;br /&gt;계정은 로컬에 저장되는 것이므로 마음대로 해도된다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;4. Ollama와 OpenWebUi 연결&lt;/h2&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;그 후 좌측 하단 본인 이름을 누른 후 Settings를 누르면 여러가지 설정을 할 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;258&quot; data-origin-height=&quot;307&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dDfpWL/btsGRnm4ezF/XLq1z94Lyr2L2vxx9aJVNK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dDfpWL/btsGRnm4ezF/XLq1z94Lyr2L2vxx9aJVNK/img.png&quot; data-alt=&quot;톱니 바퀴 모양을 누르면 된다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dDfpWL/btsGRnm4ezF/XLq1z94Lyr2L2vxx9aJVNK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdDfpWL%2FbtsGRnm4ezF%2FXLq1z94Lyr2L2vxx9aJVNK%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;258&quot; height=&quot;307&quot; data-origin-width=&quot;258&quot; data-origin-height=&quot;307&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;톱니 바퀴 모양을 누르면 된다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;Settings를 눌러보자.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;701&quot; data-origin-height=&quot;703&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bwHKtm/btsGTb60WN9/BCX6zP5UI0hoSdNN6gR9f1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bwHKtm/btsGTb60WN9/BCX6zP5UI0hoSdNN6gR9f1/img.png&quot; data-alt=&quot;URL은 본인이 설치한 Ollama서버를 적으면된다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bwHKtm/btsGTb60WN9/BCX6zP5UI0hoSdNN6gR9f1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbwHKtm%2FbtsGTb60WN9%2FBCX6zP5UI0hoSdNN6gR9f1%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;701&quot; height=&quot;703&quot; data-origin-width=&quot;701&quot; data-origin-height=&quot;703&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;URL은 본인이 설치한 Ollama서버를 적으면된다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;그 후 [Connections]에 서버 URL을 작성하면된다.&lt;br /&gt;해당 URL을 작성 후 우측에 새로고침 모양을 누르면&lt;br /&gt;Server Connection Verified가 떠야한다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;만약 Ollama설치를 로컬로 했다면 &lt;br /&gt;http://localhost:11434로 설정하면된다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;5. 사용하기&lt;/h2&gt;
&lt;p style=&quot;text-align: center;&quot; 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;932&quot; data-origin-height=&quot;922&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bg2oBQ/btsGSPJYQUO/VbnCjB9MVSagj5fKdWU0L0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bg2oBQ/btsGSPJYQUO/VbnCjB9MVSagj5fKdWU0L0/img.png&quot; data-alt=&quot;필자는 여러가지 모델을 설치했기에 모델이 여러가지 뜬다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bg2oBQ/btsGSPJYQUO/VbnCjB9MVSagj5fKdWU0L0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbg2oBQ%2FbtsGSPJYQUO%2FVbnCjB9MVSagj5fKdWU0L0%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;932&quot; height=&quot;922&quot; data-origin-width=&quot;932&quot; data-origin-height=&quot;922&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;필자는 여러가지 모델을 설치했기에 모델이 여러가지 뜬다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;매번 설정하기 귀찮다면&lt;br /&gt;모델을 누른 후에 &lt;b&gt;Set as default&lt;/b&gt;를 누르면&lt;br /&gt;접속시 마다 같은 모델이 자동으로 선택된다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;그후 ChatGPT처럼 작성하면 잘 작동된다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;697&quot; data-origin-height=&quot;284&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/FJrdp/btsGQ8p958D/0gMROvlme65DInE7QYzti1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/FJrdp/btsGQ8p958D/0gMROvlme65DInE7QYzti1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/FJrdp/btsGQ8p958D/0gMROvlme65DInE7QYzti1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FFJrdp%2FbtsGQ8p958D%2F0gMROvlme65DInE7QYzti1%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;284&quot; data-origin-width=&quot;697&quot; data-origin-height=&quot;284&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;6. (선택) GGUF 파일 넣어보기&lt;/h2&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;필자의 그래픽카드는 3090Ti 24GB를 사용하고있는데&lt;br /&gt;4GB의 모델말고 좀더 큰 용량으로 성능 테스트하고 싶어졌다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;Ollama에는 적당한게 보이지 않자 허깅페이스에서 적당한 파일을 찾았다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://huggingface.co/MaziyarPanahi/Meta-Llama-3-70B-Instruct-GGUF/tree/main&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://huggingface.co/MaziyarPanahi/Meta-Llama-3-70B-Instruct-GGUF/tree/main&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;여기서 Meta-Llma-3-70B-Instruct.IQ2_XS.gguf 파일을 받았다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;해당 파일을 Ollama에 등록하고싶으면 &lt;br /&gt;해당 위치로 가서 Modelfile이라는 파일을 생성하고 아래의 내용을 작성한다.&lt;/p&gt;
&lt;pre id=&quot;code_1713922265580&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;FROM ./Meta-Llama-3-70B-Instruct.IQ2_XS.gguf&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;그후 해당 디렉토리에서&lt;/p&gt;
&lt;pre id=&quot;code_1713922699265&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;ollama create Meta-Llama-3-70B-Instruct.IQ2_XS -f Modelfile&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;을 하면 GGUF파일이 등록된다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;7. 후기&lt;/h2&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://ai.meta.com/blog/meta-llama-3/&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://ai.meta.com/blog/meta-llama-3/&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;의외로 한국어를 잘 못한다.&lt;br /&gt;학습 데이터에 5%만 영어가 아닌 30개의 언어를 사용했다보니&lt;br /&gt;한국어로 영어만큼의 성능을 기대하긴 힘든거같다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;또한 의외로 검열을 적게한거같아 &lt;br /&gt;SQL Injection같은 공격 기법들을 잘 설명해줘서 유용하다.&lt;/p&gt;</description>
      <category>⭐개발/⭐홈서버</category>
      <category>GGUF</category>
      <category>llama3</category>
      <category>LLM</category>
      <category>ollama</category>
      <category>openwebui</category>
      <author>AnOldStory</author>
      <guid isPermaLink="true">https://anoldstory.tistory.com/8</guid>
      <comments>https://anoldstory.tistory.com/8#entry8comment</comments>
      <pubDate>Wed, 24 Apr 2024 10:38:35 +0900</pubDate>
    </item>
    <item>
      <title>[JAVA] Switch가 If 보다 빠른 이유 (lookupswitch와 tableswitch의 분기 조건)</title>
      <link>https://anoldstory.tistory.com/7</link>
      <description>&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;일반적으로 Java에서 &lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;switch문은 if문 보다 빠르다&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;그 이유에 대해 차근차근 알아보자&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;1. If와 Switch의 차이&lt;/span&gt;&lt;/h2&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;우선 Switch 와 If문의 컴파일시 bytecode차이를 분석해보자.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;우선 If 와 Switch는 모두 문맥상 같은 역할을 하고있도록 구성하였다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;먼저 If를 살펴본다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1706534481574&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// IfExample.java
public class IfExample {
    public int test(int i) {
        if (i == 1) return 6;
        if (i == 2) return 7;
        return 11;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1712573224560&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// IfExample.class
Compiled from &quot;IfExample.java&quot;
public class IfExample {
  public IfExample();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object.&quot;&amp;lt;init&amp;gt;&quot;:()V
       4: return

  public int test(int);
    Code:
       0: iload_1
       1: iconst_1
       2: if_icmpne     8                   // if (i != 1) goto 8
       5: bipush        6                   // return 6
       7: ireturn
       8: iload_1
       9: iconst_2                          
      10: if_icmpne     16                  // if (i != 2) goto 16
      13: bipush        7                   // return 7
      15: ireturn
      16: bipush        11                  // 그외 경우 return 11
      18: ireturn                       
}&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;예상한대로 If는 모든 경우의 수를 하나씩 확인한 후 반환한다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;다음은 Switch를 살펴본다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1712573473060&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// SwitchExample.java
public class SwitchExample {
    public int test(int i) {
        switch (i) {
            case 1:
                return 6;
            case 2:
                return 7;
            default:
                return 11;
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1712573618426&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// SwitchExample.class
Compiled from &quot;SwitchExample.java&quot;
public class SwitchExample {
  public SwitchExample();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object.&quot;&amp;lt;init&amp;gt;&quot;:()V
       4: return

  public int test(int);
    Code:
       0: iload_1
       1: lookupswitch  { // 2				
                     1: 28					// if (i==1) goto 28
                     2: 31 					// if (i==2) goto 31
               default: 34					// 그외의 경우 goto 34
          }
      28: bipush        6					// return 6
      30: ireturn
      31: bipush        7					// return 7
      33: ireturn
      34: bipush        11					// return 11
      36: ireturn
}&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;무엇인가 If문과 다른 부분이 보이는가?&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;b&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;If는 매 분기별로 JVM 명령어를 한줄씩 읽어 나가고&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;Switch는 모든 분기를 JVM 명령어 하나로 처리한다.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;그러므로 해당 Jump Table을 만드는 초기 비용을 제외하면&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;Switch문이 별도의 분기 없이 바로 탐색이 가능하다&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;그렇지만 실제로 bytecode로 변환된 코드에는 두가지 Switch가 존재한다.&lt;br /&gt;아래에서 해당 부분을 확인해보자.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;2. Switch의 두가지 종류 LookupSwitch, TableSwitch&lt;/span&gt;&lt;/h2&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;그러나 &lt;u&gt;Switch를 bytecode로 변환해보면 경우에 따라 다르게 변환이된다.&amp;nbsp;&lt;/u&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;아까와 같은 코드에 case 분기를 하나 더 추가시키고 컴파일해본다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1712574887287&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// SwitchExample_2.java
public class SwitchExample_2 {
    public int test(int i) {
        switch (i) {
            case 1:
                return 6;
            case 2:
                return 7;
            case 3:
                return 8;
            default:
                return 11;
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1712575104206&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// SwitchExample_2.class
Compiled from &quot;SwitchExample_2.java&quot;
public class SwitchExample_2 {
  public SwitchExample_2();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object.&quot;&amp;lt;init&amp;gt;&quot;:()V
       4: return

  public int test(int);
    Code:
       0: iload_1
       1: tableswitch   { // 1 to 3
                     1: 28                  // if(i==1) goto 28
                     2: 31                  // if(i==2) goto 31 
                     3: 34                  // if(i==3) goto 34
               default: 37                  // 그 외에 goto 37
          }
      28: bipush        6                   // return 6
      30: ireturn
      31: bipush        7                   // return 7
      33: ireturn
      34: bipush        8                   // return 8
      36: ireturn
      37: bipush        11                  // return 11
      39: ireturn
}&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;차이점을 느낄 수 있는가?&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;기존에는 분기가 lookupswitch로 이루어졌지만&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;하나가 더 추가되었을 경우 tableswitch라는 명령어로 변경되었다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;a title=&quot;Oracle Java 22 Switch 컴파일링 문서&quot; href=&quot;https://docs.oracle.com/javase/specs/jvms/se22/html/jvms-3.html#jvms-3.10&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Oracle Java 22 문서&lt;/a&gt;에는 이와 같이 적혀있다.&lt;/span&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;The tableswitch instruction is used when the cases of the switch &amp;nbsp;can be efficiently represented as indices into a table of target offsets.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;tableswitch는 offset 테이블로 효율적으로 표현될 수 있을때 사용되어집니다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;이말은 &lt;br /&gt;특정 경우에는 &lt;b&gt;lookupswitch&lt;/b&gt;를 &lt;br /&gt;특정 경우에는 &lt;b&gt;tableswitch&lt;/b&gt;를 &lt;br /&gt;사용한다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;그렇다면 실제로 어떤 기준으로 나뉘어지는 것인가?&lt;br /&gt;해당 부분은 &lt;a title=&quot;OpenJDK Determine Switch&quot; href=&quot;https://github.com/openjdk/jdk/blob/jdk-22%2B36/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java#L1331C45-L1331C56&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;OpenJDK 소스코드 &lt;/a&gt;에서 확인해볼 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1712576127827&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// jdk/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java
private void handleSwitch(JCTree swtch, JCExpression selector, List&amp;lt;JCCase&amp;gt; cases,boolean patternSwitch) {
...

    long table_space_cost = 4 + ((long) hi - lo + 1); // words
    long table_time_cost = 3; // comparisons
    long lookup_space_cost = 3 + 2 * (long) nlabels;
    long lookup_time_cost = nlabels;
    int opcode =
        nlabels &amp;gt; 0 &amp;amp;&amp;amp;
        table_space_cost + 3 * table_time_cost &amp;lt;=
        lookup_space_cost + 3 * lookup_time_cost
        ?
        tableswitch : lookupswitch;
...
}&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;위의 표를 정리해보자면 아래와 같다.&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 99.8837%; height: 100px;&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: 33.3333%; text-align: center;&quot;&gt;Opcode&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; text-align: center;&quot;&gt;Space Cost&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; text-align: center;&quot;&gt;Time Cost&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 33.3333%; text-align: center;&quot;&gt;tableswitch&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;4 + ( hi - lo + 1 )&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 33.3333%; text-align: center;&quot;&gt;lookupswitch&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;3 + 2 * nlabels&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;nlabels&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;lo = key들의 최소 값&lt;br /&gt;hi =&amp;nbsp; key들의 최대 값&lt;br /&gt;nlabels = 각 스위치 수&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;그리고 Switch의 $$Space Cost+Time Cost*3$$중 작은 값으로 선택되어진다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;간단하게 요약하자면 &lt;br /&gt;&lt;b&gt;tableswitch&lt;/b&gt;는 &lt;b&gt;해당 값이 최소와 최대값 사이에 있는가&lt;/b&gt;를 따지고&lt;br /&gt;&lt;b&gt;lookupswitch&lt;/b&gt;는 &lt;b&gt;해당 값이 일치 하는지를 모두 확인&lt;/b&gt;해본다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;아래와 같은 예시로 확인해보자.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1712578119135&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// SwitchExample_3.java
public class SwitchExample_3 {
    public int test(int i) {
        switch (i) {
            case 1:
                return 6;
            case 2:
                return 7;
            case 4:
                return 5;
            case 6:
                return 6;
            default:
                return 11;
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;$$ \begin{align} &amp;amp; lo = 1 \\&amp;amp; hi = 6 \\&amp;amp; nlabels = 4 \\&amp;amp; tableswitch =&amp;nbsp; ( 4+(6-1+1) ) +3 * 3 = 19 \\&amp;amp; lookupswitch = ( 3+2*4 ) + 3 * 4 = 23 \end{align} $$&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;tableswitch는 lookupswitch보다 작으니 tableswitch로 선택되어진다.&lt;br /&gt;또한, 해당 switch의 필요하지않은 key에는 default값이 들어가게된다.&lt;/p&gt;
&lt;pre id=&quot;code_1712578653419&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// SwitchExample_3.class
Compiled from &quot;SwitchExample_3.java&quot;
public class SwitchExample_3 {
  public SwitchExample_3();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object.&quot;&amp;lt;init&amp;gt;&quot;:()V
       4: return

  public int test(int);
    Code:
       0: iload_1
       1: tableswitch   { // 1 to 6
                     1: 40                 // if (i==1) goto 40
                     2: 43                 // if (i==2) goto 43
                     3: 52                 // 그외 goto 52
                     4: 46                 // if (i==4) goto 46
                     5: 52                 // 그외 goto 52
                     6: 49                 // if (i==6) goto 49
               default: 52                 // 그외 goto 52
          }
      40: bipush        6                  // return 6 
      42: ireturn
      43: bipush        7                  // return 7
      45: ireturn
      46: bipush        8                  // return 8
      48: ireturn
      49: bipush        9                  // return 9
      51: ireturn
      52: bipush        11                 // return 11
      54: ireturn
}&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;놀랍게도 3, 5인 경우에는 default값이 들어가 해결되었다.&lt;br /&gt;실질적으로 시간 효율성을 위해 공간 효율성을 포기한거 같다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;그렇다면 정수형이 아닌 문자열같은 경우에는 어떻게 작동하는가?&lt;br /&gt;아래에서 해당 부분을 확인해보자.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;3. 문자열에 대한 Switch 작동 방식&lt;/h2&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;문자열에 대한 처리를 보면 이해가 된다.&lt;/p&gt;
&lt;pre id=&quot;code_1712579894834&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// SwitchExample_String.java
...
switch (i) {
    case &quot;ga&quot;:
        return 6;
    case &quot;na&quot;:
        return 7;
   	case &quot;da&quot;:
    	return 8;
    default:
        return 11;
}
...&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;원본 문자열들은 HashCode로 변환된 후, 해당 값들을 기준으로 switch가 진행된다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1712580109403&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// SwitchExample_String.java
...
byte tmp = -1;
switch (tmp.hashCode()) {
    case 3290:
    	if (tmp.equals(&quot;ga&quot;)){
        	tmp = 0;
        } else if (tmp.equals(&quot;da&quot;)){
        	tmp = 2; // 만약 hash가 충돌 날경우
        }
        break;
    case 3507:
    	if (tmp.eqauls(&quot;na&quot;)){
        	tmp = 1;
        }
        break;
}
switch(tmp){
    case 0:
    	return 6;
    case 1: 
    	return 7;
   	case 2:
    	return 8;
    default:
    	return 11;
}
...&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;소스코드 : &lt;a href=&quot;https://github.com/AnOldStory/blogcode/tree/main/java_if_switch&quot;&gt;https://github.com/AnOldStory/blogcode/tree/main/java_if_switch&lt;/a&gt;&lt;br /&gt;참고 자료 :&lt;br /&gt;Oracle JVM docs : &lt;a href=&quot;https://docs.oracle.com/javase/specs/jvms/se22/html/jvms-3.html#jvms-3.10&quot;&gt;https://docs.oracle.com/javase/specs/jvms/se22/html/jvms-3.html#jvms-3.10&lt;/a&gt;&amp;nbsp;&lt;br /&gt;openjdk 22 : &lt;a href=&quot;https://github.com/openjdk/jdk/blob/jdk-22%2B36/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java#L1331C45-L1331C56&quot;&gt;https://github.com/openjdk/jdk/blob/jdk-22%2B36/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java#L1331C45-L1331C56&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>⭐Computer Science/⭐JAVA</category>
      <category>bytecode</category>
      <category>If</category>
      <category>java</category>
      <category>JVM</category>
      <category>lookupswitch</category>
      <category>Switch</category>
      <category>tableswitch</category>
      <author>AnOldStory</author>
      <guid isPermaLink="true">https://anoldstory.tistory.com/7</guid>
      <comments>https://anoldstory.tistory.com/7#entry7comment</comments>
      <pubDate>Tue, 9 Apr 2024 09:25:40 +0900</pubDate>
    </item>
  </channel>
</rss>