<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[Kevin's devlog]]></title><description><![CDATA[농구 좋아하는 개발자의 삽질로그]]></description><link>https://blog.hkwon.me/</link><image><url>https://blog.hkwon.me/favicon.png</url><title>Kevin&apos;s devlog</title><link>https://blog.hkwon.me/</link></image><generator>Ghost 5.89</generator><lastBuildDate>Sat, 18 Apr 2026 11:01:01 GMT</lastBuildDate><atom:link href="https://blog.hkwon.me/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[pytorch 소스 빌드 시 주의사항]]></title><description><![CDATA[<p>&#xD68C;&#xC0AC;&#xC5D0;&#xC11C; &#xC0AC;&#xC6A9; &#xC911;&#xC778; H100*8ea &#xBA38;&#xC2E0;&#xC5D0;&#xC11C; pytorch&#xB85C; llama3 80b &#xBAA8;&#xB378;&#xC744; &#xC591;&#xC790;&#xD654;&#xD558;&#xACE0; &#xD30C;&#xC778;&#xD29C;&#xB2DD;&#xD558;&#xB294; &#xB0B4;&#xBD80; PoC &#xC9C4;&#xD589; &#xC911;&#xC5D0; &#xC774;&#xCABD; &#xC138;&#xACC4;&#xC5D0;&#xC11C; &#xAF64; &#xC720;&#xBA85;&#xD55C;(?) &#xC624;</p>]]></description><link>https://blog.hkwon.me/pytorch-build-from-source/</link><guid isPermaLink="false">66d7c5bb5a7d91000130795f</guid><category><![CDATA[pytorch]]></category><category><![CDATA[build]]></category><dc:creator><![CDATA[Kevin H. Kwon]]></dc:creator><pubDate>Wed, 04 Sep 2024 08:53:43 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1518792528501-352f829886dc?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDF8fGJ1aWxkfGVufDB8fHx8MTcyNTQxNjkwMHww&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" medium="image"/><content:encoded><![CDATA[<img src="https://images.unsplash.com/photo-1518792528501-352f829886dc?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDF8fGJ1aWxkfGVufDB8fHx8MTcyNTQxNjkwMHww&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" alt="pytorch &#xC18C;&#xC2A4; &#xBE4C;&#xB4DC; &#xC2DC; &#xC8FC;&#xC758;&#xC0AC;&#xD56D;"><p>&#xD68C;&#xC0AC;&#xC5D0;&#xC11C; &#xC0AC;&#xC6A9; &#xC911;&#xC778; H100*8ea &#xBA38;&#xC2E0;&#xC5D0;&#xC11C; pytorch&#xB85C; llama3 80b &#xBAA8;&#xB378;&#xC744; &#xC591;&#xC790;&#xD654;&#xD558;&#xACE0; &#xD30C;&#xC778;&#xD29C;&#xB2DD;&#xD558;&#xB294; &#xB0B4;&#xBD80; PoC &#xC9C4;&#xD589; &#xC911;&#xC5D0; &#xC774;&#xCABD; &#xC138;&#xACC4;&#xC5D0;&#xC11C; &#xAF64; &#xC720;&#xBA85;&#xD55C;(?) &#xC624;&#xB958;&#xB97C; &#xC9C0;&#xC18D;&#xC801;&#xC73C;&#xB85C; &#xB9CC;&#xB098;&#xAC8C; &#xB410;&#xB2E4;.  </p><blockquote class="kg-blockquote-alt">unhandled cuda error (run with NCCL_DEBUG=INFO for details), NCCL version 2.xx.x</blockquote><p>&#xC9C4;&#xC9DC; &#xBD88;&#xCE5C;&#xC808;&#xD558;&#xAC8C;&#xB3C4; <code>NCCL_DEBUG=INFO</code> &#xB97C; &#xC8FC;&#xACE0; &#xB85C;&#xADF8; &#xB808;&#xBCA8;&#xC744; &#xB354; &#xB0B4;&#xB9AC;&#xACE0; &#xD574;&#xBD10;&#xB3C4; &#xB85C;&#xADF8;&#xC0C1; &#xBCC4;&#xB2E4;&#xB978; &#xBB38;&#xC81C;(&#xACB0;&#xAD6D; &#xB2F5;&#xC740; &#xB85C;&#xADF8;&#xC5D0; &#xC788;&#xC5C8;&#xC9C0;&#xB9CC;..)&#xB97C; &#xCC3E;&#xC744;&#xC218;&#xB294; &#xC5C6;&#xC5C8;&#xACE0;, <code>nccl</code> &#xBB38;&#xC81C;&#xC778;&#xAC74;&#xAC00; &#xBC84;&#xC804;&#xC744; &#xB0B4;&#xB838;&#xB2E4; &#xC62C;&#xB838;&#xB2E4;. <code>cuda</code> &#xBB38;&#xC81C;&#xC778;&#xAC00; &#xBC84;&#xC804;&#xC744; &#xB0B4;&#xB838;&#xB2E4; &#xC62C;&#xB838;&#xB2E4;. &#xC5F4;&#xC2EC;&#xD788; &#xC0BD;&#xC9C8; &#xD558;&#xB358; &#xC911; pytorch github issue &#xC774;&#xC7A1;&#xB4EF; &#xB4A4;&#xC9C0;&#xB2E4;&#xAC00; cuda12.4&#xC5D0;&#xC11C; pytorch&#xB97C; &#xC18C;&#xC2A4; &#xBE4C;&#xB4DC;&#xD574;&#xC11C; &#xD574;&#xACB0;&#xD588;&#xB2E4;&#xB294; &#xBA54;&#xC138;&#xC9C0;&#xB97C; &#xBCF4;&#xACE0; &#xD55C;&#xBC88; &#xC2DC;&#xB3C4;&#xD574; &#xBCFC;&#xAE4C; &#xD574;&#xC11C; pytorch &#xC18C;&#xC2A4; &#xBE4C;&#xB4DC;&#xB97C; &#xC9C4;&#xD589;&#xD574; &#xBCF4;&#xC558;&#xB2E4;. </p><div class="kg-card kg-callout-card kg-callout-card-blue"><div class="kg-callout-emoji">&#x1F600;</div><div class="kg-callout-text">&#xC5EC;&#xB2F4;&#xC774;&#xC9C0;&#xB9CC;, &#xC0AC;&#xC2E4; &#xC704; &#xC624;&#xB958;&#xB294; nccl&#xC774;&#xB098; pytorch, cuda &#xBB38;&#xC81C;&#xB294; &#xC544;&#xB2C8;&#xC600;&#xACE0;, lora &#xC635;&#xC158;&#xC744; &#xC798;&#xBABB;&#xC918;&#xC11C;... &#xB2E8;&#xC21C;&#xD788; &#xBA54;&#xBAA8;&#xB9AC;&#xAC00; &#xBD80;&#xC871;&#xD574;&#xC11C; &#xB098;&#xB358; &#xD734;&#xBA3C; &#xC5D0;&#xB7EC;&#xC600;&#xAE34; &#xD588;&#xB2E4;. &#xADFC;&#xB370; &#xB85C;&#xADF8;&#xB3C4; &#xB108;&#xBB34; &#xBD88;&#xCE5C;&#xC808;&#xD558;&#xAE34; &#xD558;&#xB2E4;. pytorch/nvidia &#xBC18;&#xC131;&#xD558;&#xB77C;.. </div></div><p>&#xBE4C;&#xB4DC;&#xB97C; &#xC9C4;&#xD589;&#xD574; &#xBCF4;&#xB2E4; &#xBA87;&#xAC00;&#xC9C0; &#xC774;&#xC288;&#xC0AC;&#xD56D;&#xC774; &#xC788;&#xC5C8;&#xACE0; &#xACB0;&#xAD6D;&#xC5D4; &#xD56D;&#xC0C1; &#xC9C0;&#xB098;&#xACE0; &#xB098;&#xBA74; &#xBCC4;&#xAC83; &#xC544;&#xB2CC; &#xC124;&#xC815;&#xB4E4;... &#xAC70;&#xC758; &#xD558;&#xB8E8;&#xB97C; &#xB0A0;&#xB824;&#xBC84;&#xB9AC;&#xACE0; &#xB9D0;&#xC558;&#xB2E4;. </p><p>&#xADF8;&#xB798;&#xC11C; &#xB2E4;&#xB978;&#xC774;&#xB4E4;&#xC758; &#xC0BD;&#xC9C8; &#xBC29;&#xC9C0;&#xB97C; &#xC704;&#xD574;&#xC11C; &#xC774; &#xB610;&#xD55C; &#xAE30;&#xB85D; &#xD574; &#xB454;&#xB2E4;. </p><h1 id="%EC%86%8C%EC%8A%A4-%EB%B9%8C%EB%93%9C-%EC%8B%9C-%EC%A3%BC%EC%9D%98%EC%82%AC%ED%95%AD">&#xC18C;&#xC2A4; &#xBE4C;&#xB4DC; &#xC2DC; &#xC8FC;&#xC758;&#xC0AC;&#xD56D;</h1><p>&#xC0AC;&#xC2E4; &#xC18C;&#xC2A4;&#xB85C; &#xBD80;&#xD130; &#xBE4C;&#xB4DC; &#xC808;&#xCC28;&#xB294; &#xADF8;&#xB807;&#xAC8C; &#xC5B4;&#xB835;&#xC9C4; &#xC54A;&#xB2E4;. &#xB2E4;&#xD050;&#xBA3C;&#xD2B8; &#xC21C;&#xC11C;&#xB370;&#xB85C; &#xCDA9;&#xC2E4;&#xD788; &#xC218;&#xD589;&#xD558;&#xBA74; &#xB41C;&#xB2E4;.</p><figure class="kg-card kg-bookmark-card kg-card-hascaption"><a class="kg-bookmark-container" href="https://github.com/pytorch/pytorch?ref=blog.hkwon.me#from-source"><div class="kg-bookmark-content"><div class="kg-bookmark-title">GitHub - pytorch/pytorch: Tensors and Dynamic neural networks in Python with strong GPU acceleration</div><div class="kg-bookmark-description">Tensors and Dynamic neural networks in Python with strong GPU acceleration - pytorch/pytorch</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://github.githubassets.com/assets/pinned-octocat-093da3e6fa40.svg" alt="pytorch &#xC18C;&#xC2A4; &#xBE4C;&#xB4DC; &#xC2DC; &#xC8FC;&#xC758;&#xC0AC;&#xD56D;"><span class="kg-bookmark-author">GitHub</span><span class="kg-bookmark-publisher">pytorch</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://opengraph.githubassets.com/31a8b2aea582e25e7b2c5f3576e5681d365e44e757dd754d8ff9d42912c48008/pytorch/pytorch" alt="pytorch &#xC18C;&#xC2A4; &#xBE4C;&#xB4DC; &#xC2DC; &#xC8FC;&#xC758;&#xC0AC;&#xD56D;"></div></a><figcaption><p><span style="white-space: pre-wrap;">build from source</span></p></figcaption></figure><p> &#xC81C;&#xC57D; &#xC870;&#xAC74;&#xC740; &#xC544;&#xB798;&#xC640; &#xAC19;&#xACE0;,</p><ul><li>Python 3.8 or later (for Linux, Python 3.8.1+ is needed)</li><li>A compiler that fully supports C++17, such as clang or gcc (gcc 9.4.0 or newer is required)</li></ul><p>&#xB098;&#xBA38;&#xC9C0; &#xC758;&#xC874;&#xC131; &#xC124;&#xCE58;&#xB294; <code>conda</code> &#xD658;&#xACBD; &#xAE30;&#xC900;&#xC73C;&#xB85C; &#xB418;&#xC5B4; &#xC788;&#xC5B4;&#xC11C; &#xB098;&#xCC98;&#xB7FC; <code>pip</code> &#xB9CC; &#xC0AC;&#xC6A9;&#xD560; &#xC218; &#xC788;&#xB294; &#xD658;&#xACBD;&#xC774;&#xBA74; &#xC57D;&#xAC04; &#xC560;&#xB85C;&#xC0AC;&#xD56D;&#xC774; &#xAF43; &#xD544; &#xC218; &#xC788;&#xB2E4;. </p><p>&#xCD5C;&#xC885;&#xC801;&#xC73C;&#xB85C;&#xB294; &#xCEE8;&#xD14C;&#xC774;&#xB108; &#xAE30;&#xBC18;&#xC5D0;&#xC11C; &#xC791;&#xC5C5;&#xC744; &#xD574;&#xC57C; &#xD558;&#xACE0; <code>DDP(Distributed Data parallel)</code> &#xB098; <code>OpenMPI</code> &#xB97C; &#xD1B5;&#xD55C; &#xBD84;&#xC0B0; &#xAE30;&#xB2A5;&#xC744; &#xC0AC;&#xC6A9;&#xD574;&#xC57C; &#xD574;&#xC11C; &#xBA3C;&#xC800; base &#xC774;&#xBBF8;&#xC9C0;&#xB294; ubuntu 22.04&#xC5D0; OpenMPI&#xB97C; &#xBA3C;&#xC800; &#xC124;&#xCE58; &#xD588;&#xC5C8;&#xB2E4;.</p><pre><code class="language-dockerfile">FROM nvidia/cuda:12.4.1-cudnn-devel-ubuntu22.04

# &#xAE30;&#xD0C0; &#xB0B4;&#xAC00; &#xD544;&#xC694;&#xD55C; &#xB77C;&#xC774;&#xBE0C;&#xB7EC;&#xB9AC;&#xB4E4; &#xC124;&#xCE58;...

# Install Open MPI
RUN \
    echo &quot;Install Open MPI 4.1.6&quot; \
    &amp;&amp; mkdir /tmp/openmpi \
    &amp;&amp; cd /tmp/openmpi \
    &amp;&amp; wget https://download.open-mpi.org/release/open-mpi/v4.1/openmpi-4.1.6.tar.gz \
    &amp;&amp; tar zxf openmpi-4.1.6.tar.gz \
    &amp;&amp; cd openmpi-4.1.6 \
    &amp;&amp; ./configure --prefix=/usr  --enable-orterun-prefix-by-default  --with-cuda=$CUDA_HOME --with-cuda-libdir=$CUDA_HOME/lib64/stubs --with-slurm  &gt; /dev/null \
    &amp;&amp; make -j $(nproc) all \
    &amp;&amp; make -s install \
    &amp;&amp; ldconfig \
    &amp;&amp; rm -rf /tmp/openmpi \
    &amp;&amp; ompi_info | grep &quot;MPI extensions&quot;

</code></pre><p>&#xADF8;&#xB9AC;&#xACE0; pytorch &#xC18C;&#xC2A4;&#xB97C; &#xD074;&#xB860; &#xBC1B;&#xACE0; &#xC544;&#xB798;&#xC640; &#xAC19;&#xC740; &#xC2A4;&#xD06C;&#xB9BD;&#xD2B8;&#xB97C; &#xD1B5;&#xD574; &#xC2E4;&#xC81C; &#xBE4C;&#xB4DC; &#xC791;&#xC5C5;&#xC744; &#xC9C4;&#xD589;&#xD588;&#xB2E4;. </p><pre><code class="language-bash">python -m pip install mkl-include mkl-static ninja scikit-build
python -m pip install -r requirements.txt

export CMAKE_PREFIX_PATH=&quot;/usr/include/openmpi;/usr/lib/openmpi;/usr/lib&quot;

USE_CUDA=1 \
USE_CUDNN=1 \
USE_MPI=1 \
USE_SYSTEM_NCCL=1 \
USE_ROCM=0 \
NCCL_INCLUDE_DIR=/usr/include \
python setup.py develop</code></pre><p>&#xC5EC;&#xAE30;&#xC11C; &#xC8FC;&#xC758; &#xD560;&#xC810;&#xC740; 2&#xAC00;&#xC9C0; &#xC815;&#xB3C4;&#xC774;&#xACE0;, &#xB098;&#xBA38;&#xC9C0;&#xB294; &#xBE4C;&#xB4DC; &#xC635;&#xC158;&#xC5D0; &#xB530;&#xB77C; &#xC57D;&#xAC04; &#xCC28;&#xC774;&#xAC00; &#xC788;&#xB2E4;. </p><ul><li><code>CMAKE_PREFIX_PATH</code>&#xC5D0;&#xC11C; <code>openmpi</code> &#xC758; &#xD5E4;&#xB354; &#xD30C;&#xC77C; &#xC704;&#xCE58;&#xC640; &#xACF5;&#xC720;&#xB77C;&#xC774;&#xBE0C;&#xB7EC;&#xB9AC;(so)&#xD30C;&#xC77C; &#xC788;&#xB294; &#xC704;&#xCE58;&#xB97C; &#xC815;&#xD655;&#xD558;&#xAC8C; &#xC9C0;&#xC815;&#xD558;&#xC9C0; &#xC54A;&#xC73C;&#xBA74; MPI &#xAC00; &#xD65C;&#xC131;&#xD654; &#xB418;&#xC9C0; &#xC54A;&#xC740;&#xCC44; &#xBE4C;&#xB4DC;&#xB41C;&#xB2E4;.</li><li><code>NCCL_INCLUDE_DIR</code> &#xB3C4; &#xC815;&#xD655;&#xD558;&#xAC8C; &#xC9C0;&#xC815;&#xD574;&#xC57C; &#xD55C;&#xB2E4;. NCCL &#xD65C;&#xC131;&#xD654; &#xC2E4;&#xD328;...</li></ul><p>&#xC774; &#xBCC4;&#xAC70; &#xC544;&#xB2CC; &#xC124;&#xC815; 2&#xAC1C; &#xCC3E;&#xB290;&#xB77C; &#xAC70;&#xC758; &#xD558;&#xB8E8;&#xB97C; &#xB0A0;&#xB9B0; &#xB4EF; &#xD558;&#xB2E4;. </p><h1 id="%EC%A0%95%EB%A6%AC">&#xC815;&#xB9AC;</h1><p>pytorch&#xB97C; &#xC18C;&#xC2A4; &#xBE4C;&#xB4DC;&#xD558;&#xB294; &#xC21C;&#xAC04;&#xC774; &#xC5BC;&#xB9C8;&#xB098; &#xC624;&#xACA0;&#xB0D0;&#xB9CC;&#xC740;... &#xBE44;&#xC2B7;&#xD55C; &#xC0C1;&#xD669;&#xC758; &#xBD84;&#xB4E4;&#xC744; &#xC704;&#xD574; &#xC815;&#xB9AC;&#xD574; &#xBCF8;&#xB2E4;. </p><p>&#xC5EC;&#xD558;&#xAC04; &#xC624;&#xB298;&#xC758; &#xB098;&#xC758; &#xAD50;&#xD6C8;&#xC740; </p><ul><li>&#xB85C;&#xADF8;&#xB294; &#xB098;&#xC758; &#xC0DD;&#xBA85;&#xC904;, &#xBCF4;&#xACE0; &#xC2F6;&#xC740; &#xB85C;&#xADF8;&#xB9CC; &#xBCF4;&#xACE0; &#xB118;&#xAE30;&#xC9C0; &#xB9D0;&#xC790;</li><li>&#xAE09;&#xD560;&#xC218;&#xB85D; &#xCC9C;&#xCC9C;&#xD788; &#xCC28;&#xADFC;&#xCC28;&#xADFC; &#xD558;&#xB098;&#xC529; &#xD558;&#xB098;&#xC529;</li></ul><p> </p><p></p><p></p><p></p><p></p>]]></content:encoded></item><item><title><![CDATA[나의 프로그래밍 폰트 사용 일대기]]></title><description><![CDATA[<p>&#xC2DC;&#xC791;&#xC740; 2003&#xB144; &#xC774;&#xC81C; &#xB9C9; &#xD504;&#xB85C;&#xADF8;&#xB798;&#xBA38;&#xB85C;&#xC368; &#xCCAB;&#xBC1C;&#xC744; &#xB0B4;&#xB51B;&#xC744; &#xB54C;&#xBD80;&#xD130; &#xB098;&#xB294; &#xD504;&#xB85C;&#xADF8;&#xB798;&#xBC0D; &#xD3F0;&#xD2B8;&#xC5D0; &#xB300;&#xD574;&#xC11C; &#xAD00;&#xC2EC;&#xC774; &#xB9CE;&#xC740; &#xD3B8;&#xC774;&#xC5C8;&#xB2E4;. </p><p>&#xD654;&#xBA74; &#xBD99;&#xC7A1;</p>]]></description><link>https://blog.hkwon.me/hkwon-programming-fonts/</link><guid isPermaLink="false">66cd91a45a7d910001307773</guid><category><![CDATA[programming]]></category><category><![CDATA[fonts]]></category><dc:creator><![CDATA[Kevin H. Kwon]]></dc:creator><pubDate>Wed, 28 Aug 2024 06:51:03 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1525972292986-69295aebf4cc?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDE5fHxmb250fGVufDB8fHx8MTcyNDc0ODIwMnww&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" medium="image"/><content:encoded><![CDATA[<img src="https://images.unsplash.com/photo-1525972292986-69295aebf4cc?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDE5fHxmb250fGVufDB8fHx8MTcyNDc0ODIwMnww&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" alt="&#xB098;&#xC758; &#xD504;&#xB85C;&#xADF8;&#xB798;&#xBC0D; &#xD3F0;&#xD2B8; &#xC0AC;&#xC6A9; &#xC77C;&#xB300;&#xAE30;"><p>&#xC2DC;&#xC791;&#xC740; 2003&#xB144; &#xC774;&#xC81C; &#xB9C9; &#xD504;&#xB85C;&#xADF8;&#xB798;&#xBA38;&#xB85C;&#xC368; &#xCCAB;&#xBC1C;&#xC744; &#xB0B4;&#xB51B;&#xC744; &#xB54C;&#xBD80;&#xD130; &#xB098;&#xB294; &#xD504;&#xB85C;&#xADF8;&#xB798;&#xBC0D; &#xD3F0;&#xD2B8;&#xC5D0; &#xB300;&#xD574;&#xC11C; &#xAD00;&#xC2EC;&#xC774; &#xB9CE;&#xC740; &#xD3B8;&#xC774;&#xC5C8;&#xB2E4;. </p><p>&#xD654;&#xBA74; &#xBD99;&#xC7A1;&#xACE0; &#xB9E4;&#xC77C; &#xAE00;&#xC790;&#xB4E4;&#xACFC; &#xC528;&#xB984;&#xD558;&#xB294; &#xC9C1;&#xC5C5;&#xC774;&#xB2E4;&#xBCF4;&#xB2C8; &#xB2F9;&#xC5F0;&#xD558;&#xAC8C;&#xB3C4; &#xC880;&#xB354; &#xB208;&#xC5D0; &#xC798; &#xBCF4;&#xC774;&#xACE0;, &#xBCF4;&#xAE30;&#xC5D0; &#xC880;&#xB354; &#xBBF8;&#xB824;&#xD558;&#xACE0; &#xC870;&#xD654;&#xC2A4;&#xB7EC;&#xC6B4; &#xD3F0;&#xD2B8;&#xB97C; &#xCC3E;&#xB294; &#xAC83;&#xC774; &#xC5B4;&#xCC0C;&#xBCF4;&#xBA74; &#xC57D;&#xAC04; &#xBCF8;&#xB2A5;(?)&#xC801;&#xC73C;&#xB85C; &#xAD00;&#xC2EC;&#xC744; &#xAC00;&#xC84C;&#xB358;&#xAC8C; &#xC544;&#xB2CC;&#xAC00; &#xC2F6;&#xAE30;&#xB3C4; &#xD558;&#xACE0; &#xB9D0;&#xC774;&#xB2E4;.  </p><p>&#xCD5C;&#xADFC;&#xAE4C;&#xC9C0;&#xB3C4; &#xC774; &#xC8FC;&#xCCB4;&#xD560; &#xC218; &#xC5C6;&#xB294; &#xBCF8;&#xB2A5;&#xC5D0; &#xB530;&#xB77C; &#xB9C8;&#xC74C;&#xC5D0; &#xB4DC;&#xB294; &#xD3F0;&#xD2B8;&#xB97C; &#xCC3E;&#xC544; &#xC720;&#xB791;&#xD558;&#xB294; &#xD0D0;&#xD5D8;&#xAC00;&#xC758; &#xB9C8;&#xC778;&#xB4DC;&#xB85C; &#xC5EC;&#xAE30;&#xC800;&#xAE30; &#xB4E4;&#xB9AC;&#xB294; &#xD3F0;&#xD2B8; &#xC18C;&#xC2DD;&#xB4E4;&#xC5D0; &#xAD00;&#xC2EC;&#xC744; &#xAE30;&#xC6B8;&#xC774;&#xB2E4;&#xAC00; &#xC774;&#xBC88;&#xC5D0; &#xD070;&#xB9D8; &#xBA39;&#xACE0; &#xC720;&#xB8CC; &#xD3F0;&#xD2B8;(&#xD3EC;&#xC2A4;&#xD305; &#xB9C8;&#xC9C0;&#xB9C9;&#xC5D0; &#xC18C;&#xAC1C;)&#xB97C; &#xAD6C;&#xB9E4;&#xD558;&#xC600;&#xB2E4;. </p><p>&#xAD6C;&#xB9E4;&#xB97C; &#xC9C4;&#xD589;&#xD574;&#xBCF4;&#xBA74;&#xC11C; &#xB0B4;&#xAC00; &#xD504;&#xB85C;&#xADF8;&#xB798;&#xBA38; &#xC0DD;&#xD65C;&#xD558;&#xBA74;&#xC11C; &#xC5BC;&#xB9C8;&#xB098; &#xB9CE;&#xC740; &#xD3F0;&#xD2B8;&#xB97C; &#xAC70;&#xCCD0;&#xC654;&#xC5C8;&#xB098; &#xAD81;&#xAE08;&#xD574;&#xC9C0;&#xAE30;&#xB3C4; &#xD558;&#xACE0; &#xD55C;&#xBC88; &#xC815;&#xB9AC; &#xD574;&#xBCF4;&#xB294;&#xAC83;&#xB3C4; &#xC7AC;&#xBBF8;&#xC788;&#xACA0;&#xB2E4; &#xC2F6;&#xC5B4; &#xCD94;&#xC5B5;&#xC744; &#xACF1;&#xC539;&#xC5B4; &#xBCF4;&#xB2C8; &#xC0DD;&#xAC01;&#xBCF4;&#xB2E4; &#xB9CE;&#xC740; &#xD3F0;&#xD2B8;&#xB4E4;&#xC774; &#xB0B4;&#xC190;&#xC744; &#xAC70;&#xCCD0;&#xAC14;&#xAD6C;&#xB098; &#xC2F6;&#xB2E4;. </p><p>&#xC774; &#xD3F0;&#xD2B8;&#xB4E4;&#xC774; &#xB098;&#xB984; &#xB0B4; &#xC190;&#xC73C;&#xB85C; &#xB9CC;&#xB4E4;&#xC5B4;&#xB0B8; &#xD504;&#xB85C;&#xADF8;&#xB7A8;&#xB4E4;&#xC5D0; &#xC0DD;&#xAE30;&#xB97C; &#xBD88;&#xC5B4; &#xB123;&#xC5B4;&#xC900;&#xAC8C; &#xC544;&#xB2CC;&#xAC00;&#xB77C;&#xB294; &#xAC10;&#xC131;&#xC801;&#xC778; &#xC0DD;&#xAC01;&#xC774; &#xB4E4;&#xAE30;&#xB3C4; &#xD558;&#xACE0;.. &#xC11C;&#xB860;&#xC774; &#xAE38;&#xC5C8;&#xACE0; &#xC5EC;&#xD558;&#xAC04; &#xC9C0;&#xADF9;&#xD788; &#xAC1C;&#xC778;&#xC801;&#xC778; &#xCD94;&#xC5B5;&#xACFC; &#xC0AC;&#xC6A9;&#xAE30;&#xB85C; &#xB0B4; &#xD504;&#xB85C;&#xADF8;&#xB798;&#xBC0D; &#xD3F0;&#xD2B8; &#xC77C;&#xB300;&#xAE30;&#xB97C; &#xD55C;&#xBC88; &#xC791;&#xC131;&#xD574; &#xBCF8;&#xB2E4;. </p><h2 id="%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D-%ED%8F%B0%ED%8A%B8%EC%9D%98-%ED%95%84%EC%88%98-%EC%A1%B0%EA%B1%B4">&#xD504;&#xB85C;&#xADF8;&#xB798;&#xBC0D; &#xD3F0;&#xD2B8;&#xC758; &#xD544;&#xC218; &#xC870;&#xAC74;</h2><p>&#xB9CE;&#xC774; &#xC54C;&#xB824;&#xC838; &#xC788;&#xB294; &#xC0AC;&#xC2E4;&#xC774;&#xC9C0;&#xB9CC; &#xC77C;&#xBC18;&#xC801;&#xC73C;&#xB85C; &#xC0AC;&#xC6A9;&#xD558;&#xB294; &#xD3F0;&#xD2B8;&#xC640; &#xB2E4;&#xB974;&#xAC8C; &#xD504;&#xB85C;&#xADF8;&#xB798;&#xBC0D; &#xD3F0;&#xD2B8;&#xB294; &#xB2E4;&#xC74C;&#xACFC; &#xAC19;&#xC740; &#xC870;&#xAC74;&#xB4E4;&#xC774; &#xAC70;&#xC758; &#xD544;&#xC218;&#xC801;&#xC73C;&#xB85C; &#xC694;&#xAD6C;&#xB418;&#xACE0; &#xB098;&#xB3C4; &#xADF8;&#xC5D0; &#xB9C8;&#xCC2C;&#xAC00;&#xC9C0;&#xB85C; &#xB3D9;&#xC758;&#xD558;&#xB294; &#xBC14;&#xC774;&#xB2E4;.</p><p>&#xB0B4;&#xAC00; &#xC0AC;&#xC6A9;&#xD588;&#xB358; &#xD3F0;&#xD2B8;&#xB294; &#xBB34;&#xC870;&#xAC74; &#xC544;&#xB798;&#xC758; &#xC870;&#xAC74;&#xC774; &#xC9C0;&#xCF1C;&#xC838;&#xC57C; &#xD588;&#xB2E4;.</p><h3 id="%EA%B3%A0%EC%A0%95%ED%8F%AD-%ED%8F%B0%ED%8A%B8">&#xACE0;&#xC815;&#xD3ED; &#xD3F0;&#xD2B8;</h3><p>&#xB0B4;&#xAC00; &#xD3F0;&#xD2B8; &#xC0AC;&#xC6A9;/&#xD504;&#xB85C;&#xADF8;&#xB7A8; &#xC791;&#xC131; &#xC2DC;&#xC5D0; &#xAC00;&#xC7A5; &#xC911;&#xC694;&#xD558;&#xAC8C; &#xC0DD;&#xAC01;&#xD558;&#xB294; &#xAC83; &#xB208;&#xC5D0; &#xC798; &#xC77D;&#xD600;&#xC57C; &#xD558;&#xB294; <strong>&#xAC00;&#xB3C5;&#xC131;</strong>&#xC778;&#xB370; &#xACF5;&#xBC31;&#xC774;&#xB098; &#xD0ED; &#xB4F1;&#xC744; &#xD1B5;&#xD574; &#xB4E4;&#xC5EC;&#xC4F0;&#xAE30; &#xD558;&#xAC70;&#xB098; &#xC904;&#xC744; &#xC815;&#xB82C;&#xD558;&#xAC70;&#xB098; &#xD560; &#xB54C;&#xB294; &#xACE0;&#xC815;&#xD3ED;&#xC744; &#xAC00;&#xC9C4; &#xD3F0;&#xD2B8;&#xC5EC;&#xC57C; &#xC774; &#xAC00;&#xB3C5;&#xC131;&#xC744; &#xC9C0;&#xD0A4;&#xB294; &#xAC83;&#xC774;&#xD6E8;&#xC52C; &#xB354; &#xC720;&#xB9AC;&#xD558;&#xB2E4;.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.hkwon.me/content/images/2024/08/image-23.png" class="kg-image" alt="&#xB098;&#xC758; &#xD504;&#xB85C;&#xADF8;&#xB798;&#xBC0D; &#xD3F0;&#xD2B8; &#xC0AC;&#xC6A9; &#xC77C;&#xB300;&#xAE30;" loading="lazy" width="850" height="540" srcset="https://blog.hkwon.me/content/images/size/w600/2024/08/image-23.png 600w, https://blog.hkwon.me/content/images/2024/08/image-23.png 850w" sizes="(min-width: 720px) 720px"><figcaption><a href="https://design.tutsplus.com/articles/what-is-a-monospaced-font--cms-34717?ref=blog.hkwon.me"><span style="white-space: pre-wrap;">https://design.tutsplus.com/articles/what-is-a-monospaced-font--cms-34717</span></a><span style="white-space: pre-wrap;"> &#xC778;&#xC6A9; &#xACE0;&#xC815;&#xD3ED;&#xACFC; &#xAC00;&#xBCC0;&#xD3ED;&#xC758; &#xCC28;&#xC774;</span></figcaption></figure><h3 id="%EB%AC%B8%EC%9E%90%EA%B0%84-%EB%AA%85%ED%99%95%ED%95%9C-%EA%B5%AC%EB%B6%84">&#xBB38;&#xC790;&#xAC04; &#xBA85;&#xD655;&#xD55C; &#xAD6C;&#xBD84;</h3><p>&#xC601;&#xBB38;&#xC790; 0O&#xC640; &#xC22B;&#xC790; 0, &#xC601;&#xBB38;&#xC790; iILl&#xACFC; &#xC22B;&#xC790; 1 &#xB4F1; &#xAE00;&#xB9AC;&#xD504;(Glyph)&#xAC00; &#xC57D;&#xAC04; &#xBE44;&#xC2B7;&#xD55C; &#xB188;&#xB4E4;&#xB07C;&#xB9AC; &#xD63C;&#xB3D9;&#xB418;&#xC9C0; &#xC54A;&#xACE0; &#xAD6C;&#xBD84;&#xB418;&#xB294; &#xD3F0;&#xD2B8;&#xC5EC;&#xC57C; &#xD504;&#xB85C;&#xADF8;&#xB7A8; &#xC791;&#xC131; &#xC2DC;&#xC5D0; &#xC624;&#xD0C0; &#xB610;&#xB294; &#xD63C;&#xB3D9;&#xC744; &#xC904;&#xC77C; &#xC218; &#xC788;&#xAE30; &#xB54C;&#xBB38;&#xC5D0; &#xC774;&#xB7EC;&#xD55C; &#xC870;&#xAC74;&#xB4E4;&#xC740; &#xAC70;&#xC758; &#xD544;&#xC218;&#xC801;&#xC73C;&#xB85C; &#xC9C0;&#xCF1C;&#xC838;&#xC57C; &#xB9C8;&#xC74C;&#xC758; &#xD3C9;&#xD654;&#xB97C; &#xC720;&#xC9C0; &#xD560; &#xC218; &#xC788;&#xB2E4;.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.hkwon.me/content/images/2024/08/image-25.png" class="kg-image" alt="&#xB098;&#xC758; &#xD504;&#xB85C;&#xADF8;&#xB798;&#xBC0D; &#xD3F0;&#xD2B8; &#xC0AC;&#xC6A9; &#xC77C;&#xB300;&#xAE30;" loading="lazy" width="974" height="222" srcset="https://blog.hkwon.me/content/images/size/w600/2024/08/image-25.png 600w, https://blog.hkwon.me/content/images/2024/08/image-25.png 974w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">jetbrain mono &#xB85C; &#xBB38;&#xC790; &#xAD6C;&#xBD84; &#xC608;&#xC2DC;</span></figcaption></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.hkwon.me/content/images/2024/08/image-21.png" class="kg-image" alt="&#xB098;&#xC758; &#xD504;&#xB85C;&#xADF8;&#xB798;&#xBC0D; &#xD3F0;&#xD2B8; &#xC0AC;&#xC6A9; &#xC77C;&#xB300;&#xAE30;" loading="lazy" width="1208" height="708" srcset="https://blog.hkwon.me/content/images/size/w600/2024/08/image-21.png 600w, https://blog.hkwon.me/content/images/size/w1000/2024/08/image-21.png 1000w, https://blog.hkwon.me/content/images/2024/08/image-21.png 1208w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Peter Ritchie&#xB2D8;&#xC758; X</span></figcaption></figure><p>&#xD504;&#xB85C;&#xADF8;&#xB798;&#xBA38; &#xCE5C;&#xAD6C; &#xC5FF;&#xBA39;&#xC77C;&#xB824;&#xBA74; &#xC138;&#xBBF8;&#xCF5C;&#xB860;(;)&#xC744; &#xADF8;&#xB9AC;&#xC2A4;&#xC5B4; &#xBB3C;&#xC74C;&#xD45C;(;)&#xB85C; &#xBC14;&#xAFB8;&#xB77C;&#xB294; &#xC774; &#xC0DD;&#xD0DC;&#xACC4;&#xC758; &#xC720;&#xBA85;&#xD55C; &#xB18D;&#xB2F4;&#xB3C4; &#xC774;&#xB7EC;&#xD55C; &#xBB38;&#xC790; &#xAD6C;&#xBD84;&#xC5D0; &#xB300;&#xD55C; &#xB9CE;&#xC740; &#xD504;&#xB85C;&#xADF8;&#xB798;&#xBA38;&#xB4E4;&#xC758; &#xC2E0;&#xB150;&#xC5D0; &#xB300;&#xD55C; &#xC720;&#xCF8C;&#xD55C;(SQL &#xB9C8;&#xC9C0;&#xB9C9;&#xC5D0; &#xADF8;&#xB9AC;&#xC2A4;&#xC5B4; &#xBB3C;&#xC74C;&#xD45C;&#xB77C; &#xC0DD;&#xAC01;&#xD558;&#xBA74; &#xC9C4;&#xC9DC; &#xC720;&#xCF8C;&#xD560;&#xAE4C; &#x1F631;) &#xC720;&#xBA38; &#xC544;&#xB2D0;&#xAE4C; &#xC2F6;&#xB2E4;.</p><h3 id="ligature-powerline-symbol-icon-optional">Ligature, Powerline Symbol, Icon [Optional]</h3><figure class="kg-card kg-gallery-card kg-width-wide kg-card-hascaption"><div class="kg-gallery-container"><div class="kg-gallery-row"><div class="kg-gallery-image"><img src="https://blog.hkwon.me/content/images/2024/08/image-27.png" width="1544" height="724" loading="lazy" alt="&#xB098;&#xC758; &#xD504;&#xB85C;&#xADF8;&#xB798;&#xBC0D; &#xD3F0;&#xD2B8; &#xC0AC;&#xC6A9; &#xC77C;&#xB300;&#xAE30;" srcset="https://blog.hkwon.me/content/images/size/w600/2024/08/image-27.png 600w, https://blog.hkwon.me/content/images/size/w1000/2024/08/image-27.png 1000w, https://blog.hkwon.me/content/images/2024/08/image-27.png 1544w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://blog.hkwon.me/content/images/2024/08/image-26.png" width="955" height="642" loading="lazy" alt="&#xB098;&#xC758; &#xD504;&#xB85C;&#xADF8;&#xB798;&#xBC0D; &#xD3F0;&#xD2B8; &#xC0AC;&#xC6A9; &#xC77C;&#xB300;&#xAE30;" srcset="https://blog.hkwon.me/content/images/size/w600/2024/08/image-26.png 600w, https://blog.hkwon.me/content/images/2024/08/image-26.png 955w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://blog.hkwon.me/content/images/2024/08/image-28.png" width="1798" height="576" loading="lazy" alt="&#xB098;&#xC758; &#xD504;&#xB85C;&#xADF8;&#xB798;&#xBC0D; &#xD3F0;&#xD2B8; &#xC0AC;&#xC6A9; &#xC77C;&#xB300;&#xAE30;" srcset="https://blog.hkwon.me/content/images/size/w600/2024/08/image-28.png 600w, https://blog.hkwon.me/content/images/size/w1000/2024/08/image-28.png 1000w, https://blog.hkwon.me/content/images/size/w1600/2024/08/image-28.png 1600w, https://blog.hkwon.me/content/images/2024/08/image-28.png 1798w" sizes="(min-width: 720px) 720px"></div></div></div><figcaption><p><a href="https://betterwebtype.com/5-monospaced-fonts-with-coding-ligatures/?ref=blog.hkwon.me"><span style="white-space: pre-wrap;">https://betterwebtype.com/5-monospaced-fonts-with-coding-ligatures/</span></a> <a href="https://www.nerdfonts.com/?ref=blog.hkwon.me"><span style="white-space: pre-wrap;">https://www.nerdfonts.com/</span></a><span style="white-space: pre-wrap;"> &#xC778;&#xC6A9;</span></p></figcaption></figure><p><code>Ligature</code>&#xB294; &#xC11C;&#xB85C; &#xB2E4;&#xB978; &#xAE00;&#xB9AC;&#xD504;&#xB97C; &#xAC00;&#xC9C4; &#xBB38;&#xC790;&#xB4E4;&#xC744; &#xD1B5;&#xD569;&#xD574;&#xC11C; &#xBCF4;&#xC5EC;&#xC8FC;&#xC5B4;&#xC11C; &#xD654;&#xBA74;&#xC0C1;&#xC5D0; &#xC880;&#xB354; &#xBBF8;&#xB824;&#xD558;&#xAC8C; &#xD45C;&#xD604;&#xD558;&#xB294; &#xAC83;&#xC744; &#xC598;&#xAE30;&#xD558;&#xBA70; &#xB610;&#xD55C; &#xCD5C;&#xADFC;&#xC5D0;&#xB294; <code>zsh</code> &#xC0AC;&#xC6A9;&#xC790;&#xB4E4;&#xC774; &#xB9CE;&#xC544; &#xC9C0;&#xBA74;&#xC11C; &#xD130;&#xBBF8;&#xB110;&#xC5D0;&#xC11C; &#xC790;&#xC8FC; &#xC0AC;&#xC6A9;&#xD558;&#xB294; &#xC258;&#xD504;&#xB86C;&#xD504;&#xD2B8;&#xB098; VIM &#xB4F1;&#xC758; &#xC0C1;&#xD0DC;&#xBC14;&#xC5D0; <code>Powerline Symbol</code> &#xB4F1;&#xC758; &#xC544;&#xC774;&#xCF58;&#xC744; &#xD3F0;&#xD2B8;&#xC5D0; &#xD569;&#xC131;(<a href="https://www.nerdfonts.com/?ref=blog.hkwon.me" rel="noreferrer">Nerd font</a>)&#xD574;&#xC11C; &#xB9CE;&#xC774;&#xB4E4; &#xC0AC;&#xC6A9;&#xD558;&#xACE0; &#xC788;&#xB2E4;. </p><h2 id="%EB%82%B4%EA%B0%80-%EC%82%AC%EC%9A%A9%ED%95%B4-%EC%99%94%EB%8D%98-%ED%8F%B0%ED%8A%B8">&#xB0B4;&#xAC00; &#xC0AC;&#xC6A9;&#xD574; &#xC654;&#xB358; &#xD3F0;&#xD2B8;</h2><p>&#xC815;&#xD655;&#xD558;&#xC9C4; &#xC54A;&#xC9C0;&#xB9CC; &#xB098;&#xC758; &#xC0AC;&#xC6A9; &#xC5F0;&#xB300;&#xAE30; &#xC21C;&#xC73C;&#xB85C; &#xD55C;&#xBC88; &#xC815;&#xB9AC;&#xD574;&#xBCF4;&#xC558;&#xACE0; &#xC0AC;&#xC6A9;&#xB41C; &#xC774;&#xBBF8;&#xC9C0; &#xC608;&#xC81C;&#xB294; &#xB300;&#xCCB4;&#xB85C; <a href="https://www.programmingfonts.org/?ref=blog.hkwon.me" rel="noreferrer">programmingfonts</a> &#xC5D0;&#xC11C; &#xC778;&#xC6A9;&#xD558;&#xC600;&#xB2E4;. </p><p>&#xC7AC;&#xBBF8;&#xB85C; &#xAC04;&#xB2E8;&#xD55C; &#xC0AC;&#xC6A9;&#xAE30;&#xC640; &#xB098;&#xB984;&#xC758; &#xBCC4;&#xC810;&#xB3C4; &#xD55C;&#xBC88; &#xB9E4;&#xACA8;&#xBCF4;&#xC558;&#xB2E4;.</p><h4 id="fixedsys-1980">Fixedsys, 1980</h4><p>&#x2B50;&#x2B50;&#x2B50;</p><figure class="kg-card kg-image-card"><img src="https://blog.hkwon.me/content/images/2024/08/image-29.png" class="kg-image" alt="&#xB098;&#xC758; &#xD504;&#xB85C;&#xADF8;&#xB798;&#xBC0D; &#xD3F0;&#xD2B8; &#xC0AC;&#xC6A9; &#xC77C;&#xB300;&#xAE30;" loading="lazy" width="1700" height="1034" srcset="https://blog.hkwon.me/content/images/size/w600/2024/08/image-29.png 600w, https://blog.hkwon.me/content/images/size/w1000/2024/08/image-29.png 1000w, https://blog.hkwon.me/content/images/size/w1600/2024/08/image-29.png 1600w, https://blog.hkwon.me/content/images/2024/08/image-29.png 1700w" sizes="(min-width: 720px) 720px"></figure><p>&#xAC00;&#xC7A5; &#xBA3C;&#xC800; &#xC5B8;&#xAE09;&#xC744; &#xC548;&#xD560; &#xC218;&#xAC00; &#xC5C6;&#xACA0;&#xB2E4;. </p><p>&#xCD94;&#xC5B5;&#xBCF4;&#xC815;&#xC6A9; &#xD3F0;&#xD2B8;! &#xC708;&#xB3C4;&#xC6B0; &#xB178;&#xD2B8;&#xD328;&#xB4DC;&#xC778;&#xAC00; &#xC544;&#xB9C8; &#xAE30;&#xBCF8; &#xD3F0;&#xD2B8;&#xC600;&#xB358;&#xAC78;&#xB85C; &#xAE30;&#xC5B5;&#xD558;&#xACE0; &#xC774;&#xAC8C; &#xC544;&#xB9C8; &#xC708;&#xB3C4;&#xC6B0; 1.0&#xC778;&#xAC00; &#xBD80;&#xD130; &#xACC4;&#xC18D; &#xC788;&#xB358; &#xD3F0;&#xD2B8;&#xB85C; &#xC54C;&#xACE0;&#xB294; &#xC788;&#xB2E4;. </p><p>DOS &#xCF54;&#xB9E8;&#xB4DC;&#xB77C;&#xC778; &#xD1B5;&#xD574;&#xC11C; <code>telnet</code> &#xC0AC;&#xC6A9;&#xD558;&#xB358; &#xC2DC;&#xC808; &#xC790;&#xC8FC; &#xC560;&#xC6A9;&#xD558;&#xB358; &#xD3F0;&#xD2B8;&#xC600;&#xACE0;, &#xCD5C;&#xCD08;&#xB85C; &#xACE0;&#xC815;&#xD3ED; &#xD3F0;&#xD2B8;&#xAC00; &#xC774;&#xB7F0;&#xAC70;&#xAD6C;&#xB098;&#xB77C;&#xB294;&#xAC78; &#xC54C;&#xB824;&#xC900; &#xD3F0;&#xD2B8;&#xB2E4;.</p><p>&#xCD5C;&#xADFC; 10&#xB144; &#xB0B4;&#xC5D0;&#xB294; &#xC708;&#xB3C4;&#xC6B0;&#xB97C; &#xAC70;&#xC758; &#xC4F0;&#xC9C0; &#xC54A;&#xC544;&#xC11C;.. &#xC694;&#xC998;&#xC758; <code>consolas</code> &#xAC00; &#xC608;&#xC804; <code>fixedsys</code> &#xC815;&#xB3C4;  &#xB290;&#xB08C;&#xC774; &#xB418;&#xC9C0; &#xC54A;&#xC744;&#xAE4C; &#xC2F6;&#xACE0;, &#xCD08;&#xB144;&#xC0DD; &#xB54C; &#xC678;&#xC5D0;&#xB294; &#xAC70;&#xC758; &#xC0AC;&#xC6A9;&#xD558;&#xC9C4; &#xC54A;&#xC558;&#xB358; &#xCD94;&#xC5B5;&#xC758; &#xD3F0;&#xD2B8;&#xB2E4;. </p><h4 id="bitstream-vera-sans-mono-2002">Bitstream Vera Sans Mono, 2002</h4><p>&#x2B50;&#x2B50;&#x2B50;&#x2B50;</p><figure class="kg-card kg-image-card"><img src="https://blog.hkwon.me/content/images/2024/08/image-30.png" class="kg-image" alt="&#xB098;&#xC758; &#xD504;&#xB85C;&#xADF8;&#xB798;&#xBC0D; &#xD3F0;&#xD2B8; &#xC0AC;&#xC6A9; &#xC77C;&#xB300;&#xAE30;" loading="lazy" width="1824" height="1040" srcset="https://blog.hkwon.me/content/images/size/w600/2024/08/image-30.png 600w, https://blog.hkwon.me/content/images/size/w1000/2024/08/image-30.png 1000w, https://blog.hkwon.me/content/images/size/w1600/2024/08/image-30.png 1600w, https://blog.hkwon.me/content/images/2024/08/image-30.png 1824w" sizes="(min-width: 720px) 720px"></figure><p>&#xC96C;&#xB2C8;&#xC5B4; &#xD504;&#xB85C;&#xADF8;&#xB798;&#xBA38; &#xC2DC;&#xC808; &#xAF64;&#xB098; &#xC624;&#xB79C;&#xC2DC;&#xAC04; &#xB098;&#xC758; <code>eclipse</code> &#xC5D0;&#xC11C; &#xC624;&#xB79C;&#xC2DC;&#xAC04; &#xD568;&#xAED8; &#xD588;&#xB358; &#xD3F0;&#xD2B8;&#xB2E4;. &#xC544;&#xB9C8;&#xB3C4; &#xCD5C;&#xADFC;&#xC5D0; &#xB098;&#xC628; &#xB9CE;&#xC740; &#xD3F0;&#xD2B8; &#xB4E4;&#xC5D0;&#xAC8C; &#xB9CE;&#xC740; &#xC601;&#xAC10;&#xC744; &#xC900; &#xD3F0;&#xD2B8; &#xC544;&#xB2D0;&#xAE4C; &#xD558;&#xACE0;, &#xBAA8;&#xB4E0; &#xAD6C;&#xC11D;&#xC5D0;&#xC11C; &#xD3C9;&#xADE0; &#xC774;&#xC0C1;&#xC758; &#xD3C9;&#xC810;&#xC774; &#xB098;&#xC62C; &#xB9CC;&#xD55C; &#xD3F0;&#xD2B8;&#xB2E4;. </p><p>&#xC544;&#xB9C8;&#xB3C4; &#xB9CE;&#xC740; &#xD504;&#xB85C;&#xADF8;&#xB798;&#xBA38; &#xD3F0;&#xD2B8; &#xC21C;&#xC704;&#xB97C; &#xB9E4;&#xAE30;&#xB294; &#xACF3;&#xC5D0;&#xB3C4; &#xD56D;&#xC0C1; &#xC218;&#xC704;&#xAD8C;&#xC744; &#xC9C0;&#xD0A4;&#xC9C0; &#xC54A;&#xC744;&#xAE4C; &#xC2F6;&#xC740; &#xD3F0;&#xD2B8;&#xB2E4;.</p><h4 id="nanum-gothic-coding-font-2009">Nanum Gothic Coding Font, 2009</h4><p>&#x2B50;&#x2B50;&#x2B50;</p><figure class="kg-card kg-image-card"><img src="https://blog.hkwon.me/content/images/2024/08/image-31.png" class="kg-image" alt="&#xB098;&#xC758; &#xD504;&#xB85C;&#xADF8;&#xB798;&#xBC0D; &#xD3F0;&#xD2B8; &#xC0AC;&#xC6A9; &#xC77C;&#xB300;&#xAE30;" loading="lazy" width="1568" height="1042" srcset="https://blog.hkwon.me/content/images/size/w600/2024/08/image-31.png 600w, https://blog.hkwon.me/content/images/size/w1000/2024/08/image-31.png 1000w, https://blog.hkwon.me/content/images/2024/08/image-31.png 1568w" sizes="(min-width: 720px) 720px"></figure><p><code>D2Coding</code>&#xC774; &#xB098;&#xC624;&#xAE30; &#xC774;&#xC804;&#xC5D0; &#xB124;&#xC774;&#xBC84;&#xC5D0;&#xC11C; &#xC57C;&#xC2EC;&#xCC28;&#xAC8C;(?) &#xBC1C;&#xD45C;&#xD55C; &#xD3F0;&#xD2B8; &#xC600;&#xACE0;, <code>Bitstream</code> &#xBCF4;&#xB2E4;&#xB294; &#xAE00;&#xC790;&#xD3ED;&#xC774; &#xC57D; 90% &#xC218;&#xC900; &#xC815;&#xB3C4;&#xC5EC;&#xC11C; &#xCC98;&#xC74C;&#xC5D0;&#xB294; &#xC880;&#xB354; &#xAC00;&#xB85C;&#xB85C; &#xAE38;&#xAC8C; &#xBCF4;&#xAE30; &#xD3B8;&#xD55C; &#xB290;&#xB08C;&#xC774;&#xC5B4;&#xC11C; &#xC0AC;&#xC6A9;&#xC744; &#xC880; &#xD558;&#xB2E4;&#xAC00; &#xAE00;&#xC790;&#xD3ED;, &#xC790;&#xAC04;&#xC774; &#xB108;&#xBB34; &#xC880; &#xC791;&#xC740; &#xD3B8;&#xC774;&#xC774;&#xC11C; &#xC624;&#xB79C; &#xC2DC;&#xAC04; &#xC0AC;&#xC6A9;&#xD560;&#xB54C;&#xB294; &#xC57D;&#xAC04; &#xB208;&#xC5D0; &#xD53C;&#xB85C;&#xD568;&#xC774; &#xC788;&#xC5B4;&#xC11C; &#xAE38;&#xAC8C; &#xC0AC;&#xC6A9;&#xD558;&#xC9C4; &#xC54A;&#xC558;&#xB358; &#xD3F0;&#xD2B8;&#xC600;&#xB2E4;. </p><h4 id="envy-code-r-2008">Envy Code R, 2008</h4><p>&#x2B50;&#x2B50;&#x2B50;&#x2B50;</p><figure class="kg-card kg-image-card"><img src="https://blog.hkwon.me/content/images/2024/08/image-32.png" class="kg-image" alt="&#xB098;&#xC758; &#xD504;&#xB85C;&#xADF8;&#xB798;&#xBC0D; &#xD3F0;&#xD2B8; &#xC0AC;&#xC6A9; &#xC77C;&#xB300;&#xAE30;" loading="lazy" width="1620" height="1046" srcset="https://blog.hkwon.me/content/images/size/w600/2024/08/image-32.png 600w, https://blog.hkwon.me/content/images/size/w1000/2024/08/image-32.png 1000w, https://blog.hkwon.me/content/images/size/w1600/2024/08/image-32.png 1600w, https://blog.hkwon.me/content/images/2024/08/image-32.png 1620w" sizes="(min-width: 720px) 720px"></figure><p>&#xC774;&#xB54C;&#xCBE4; &#xC544;&#xB9C8; <code>Visual Studio</code>&#xB85C; &#xBC95;&#xC81C;&#xCC98; &#xD504;&#xB85C;&#xC81D;&#xD2B8;&#xC600;&#xC5C8;&#xB098; &#xD55C;&#xAE00;OCX&#xB85C; &#xBC95;&#xB839;&#xC548; &#xD3B8;&#xC9D1;&#xAE30; <code>Visual Basic</code> &#xC73C;&#xB85C; &#xBC24;&#xD328;&#xAC00;&#xBA70; &#xCF54;&#xB529; &#xD558;&#xB358; &#xC2DC;&#xAE30; &#xC600;&#xB098; &#xBCF8;&#xB370;, &#xC6B0;&#xC5F0;&#xCE58; &#xC54A;&#xAC8C; &#xCC3E;&#xC544;&#xBCF4;&#xB358; <code>VB</code>&#xAD00;&#xB828; &#xBE14;&#xB85C;&#xADF8;&#xC5D0;&#xC11C; &#xC774; &#xD3F0;&#xD2B8;&#xB97C; &#xCD94;&#xCC9C; &#xD558;&#xAE38;&#xB798; &#xD55C; 2~3&#xB144; &#xC815;&#xB3C4; &#xC774;&#xAC83;&#xB9CC; &#xCB49; &#xC0AC;&#xC6A9;&#xD588;&#xB358; &#xAE30;&#xC5B5;&#xC774; &#xC788;&#xB2E4;. </p><p><code>1</code>&#xD558;&#xACE0; <code>l</code>&#xC774; &#xC0B4;&#xC9DD; &#xD5F7;&#xAC08;&#xB9AC;&#xAE34; &#xD588;&#xC9C0;&#xB9CC; <code>Bitstream</code> &#xACFC;&#xB294; &#xC57D;&#xAC04; &#xB2E4;&#xB978; &#xB465;&#xAE00;&#xB465;&#xAE00;&#xD55C; &#xB9DB;&#xC5D0; &#xAF64; &#xC624;&#xB7AB; &#xB3D9;&#xC548; &#xD568;&#xAED8; &#xD588;&#xB358; &#xD3F0;&#xD2B8;&#xB2E4;.</p><h4 id="anonymous-pro-2009">Anonymous Pro, 2009</h4><p>&#x2B50;&#x2B50;&#x2B50;&#x2B50;</p><figure class="kg-card kg-image-card"><img src="https://blog.hkwon.me/content/images/2024/08/image-33.png" class="kg-image" alt="&#xB098;&#xC758; &#xD504;&#xB85C;&#xADF8;&#xB798;&#xBC0D; &#xD3F0;&#xD2B8; &#xC0AC;&#xC6A9; &#xC77C;&#xB300;&#xAE30;" loading="lazy" width="1658" height="1042" srcset="https://blog.hkwon.me/content/images/size/w600/2024/08/image-33.png 600w, https://blog.hkwon.me/content/images/size/w1000/2024/08/image-33.png 1000w, https://blog.hkwon.me/content/images/size/w1600/2024/08/image-33.png 1600w, https://blog.hkwon.me/content/images/2024/08/image-33.png 1658w" sizes="(min-width: 720px) 720px"></figure><p>&#xC544;&#xB9C8;&#xB3C4; <code>Adobe</code>&#xC5D0;&#xC11C; &#xBB34;&#xB8CC;&#xB85C; &#xD480;&#xB838;&#xB358; <code>Anonymous</code> &#xAE30;&#xBC18;&#xC73C;&#xB85C; &#xB9CC;&#xB4E4;&#xC5B4;&#xC9C4; &#xD3F0;&#xD2B8;&#xB85C; &#xC54C;&#xACE0; &#xC788;&#xC5C8;&#xACE0;, &#xD55C;&#xCC38; &#xAC1C;&#xBC1C;&#xC790;&#xB4E4; &#xC0AC;&#xC5D0;&#xC11C; &#xC720;&#xD589;&#xD558;&#xAE38;&#xB798; &#xC870;&#xAE08; &#xC368;&#xBCF4;&#xC558;&#xC9C0;&#xB9CC; &#xB0B4; &#xD0C0;&#xC785;&#xC740; &#xC544;&#xB2C8;&#xC5C8;&#xB358; &#xD3F0;&#xD2B8;&#xC600;&#xB2E4;. </p><p>&#xADF8;&#xB798;&#xB3C4; &#xC544;&#xC9C1; &#xAC1C;&#xBC1C;&#xC790;&#xB4E4; &#xC0AC;&#xC774;&#xC5D0;&#xC11C;&#xB294; &#xC778;&#xAE30; &#xC88B;&#xC740; &#xD3F0;&#xD2B8; &#xC911; &#xD558;&#xB098;!</p><h4 id="source-code-pro-2012">Source Code Pro, 2012</h4><p>&#x2B50;&#x2B50;&#x2B50;&#x2B50;</p><figure class="kg-card kg-image-card"><img src="https://blog.hkwon.me/content/images/2024/08/image-34.png" class="kg-image" alt="&#xB098;&#xC758; &#xD504;&#xB85C;&#xADF8;&#xB798;&#xBC0D; &#xD3F0;&#xD2B8; &#xC0AC;&#xC6A9; &#xC77C;&#xB300;&#xAE30;" loading="lazy" width="1862" height="1044" srcset="https://blog.hkwon.me/content/images/size/w600/2024/08/image-34.png 600w, https://blog.hkwon.me/content/images/size/w1000/2024/08/image-34.png 1000w, https://blog.hkwon.me/content/images/size/w1600/2024/08/image-34.png 1600w, https://blog.hkwon.me/content/images/2024/08/image-34.png 1862w" sizes="(min-width: 720px) 720px"></figure><p>&#xADF8;&#xB7EC;&#xACE0; &#xBCF4;&#xB2C8; &#xC774; &#xD3F0;&#xD2B8;&#xB3C4; <code>Adobe</code>&#xC5D0;&#xC11C; &#xB098;&#xC654;&#xB358; &#xD3F0;&#xD2B8;&#xC600;&#xB098; &#xADF8;&#xB7AC;&#xB358;&#xAC70; &#xAC19;&#xC740;&#xB370;, &#xAC00;&#xB85C;&#xAE38;&#xC774;&#xAC00; &#xC880; &#xAE34; &#xD3F0;&#xD2B8;&#xC600;&#xACE0; &#xC774; &#xD3F0;&#xD2B8;&#xB3C4; &#xC544;&#xC9C1; &#xAC1C;&#xBC1C;&#xC790;&#xB4E4; &#xC0AC;&#xC774;&#xC5D0;&#xC11C;&#xB294; &#xB9CE;&#xC774; &#xC0AC;&#xC6A9;&#xD558;&#xB294; &#xD3F0;&#xD2B8;&#xB85C; &#xC54C;&#xACE0; &#xC788;&#xC9C0;&#xB9CC;.. &#xC774;&#xC0C1;&#xD558;&#xAC8C; &#xC815;&#xC774; &#xC548;&#xAC00;&#xB294; &#xD3F0;&#xD2B8;&#xB4E4;&#xC911; &#xD558;&#xB098;..</p><h4 id="d2coding-2016">D2Coding, 2016</h4><p>&#x2B50;&#x2B50;&#x2B50;</p><figure class="kg-card kg-image-card"><img src="https://blog.hkwon.me/content/images/2024/08/image-35.png" class="kg-image" alt="&#xB098;&#xC758; &#xD504;&#xB85C;&#xADF8;&#xB798;&#xBC0D; &#xD3F0;&#xD2B8; &#xC0AC;&#xC6A9; &#xC77C;&#xB300;&#xAE30;" loading="lazy" width="1570" height="1036" srcset="https://blog.hkwon.me/content/images/size/w600/2024/08/image-35.png 600w, https://blog.hkwon.me/content/images/size/w1000/2024/08/image-35.png 1000w, https://blog.hkwon.me/content/images/2024/08/image-35.png 1570w" sizes="(min-width: 720px) 720px"></figure><p>&#xC5ED;&#xC2DC;&#xB098; &#xB124;&#xC774;&#xBC84;&#xC5D0;&#xC11C; &#xBC30;&#xD3EC;&#xD55C; &#xAC1C;&#xBC1C;&#xC790;&#xC6A9; &#xBB34;&#xB8CC; &#xD3F0;&#xD2B8;&#xB85C; &#xD55C;&#xAE00;&#xC774; &#xB098;&#xB214;&#xACE0;&#xB515;&#xC73C;&#xB85C; &#xBA38;&#xC9C0;&#xB418;&#xC5B4; &#xC788;&#xC5B4;&#xC11C; &#xC9C0;&#xAE08;&#xB3C4; &#xAF64; &#xB098; &#xB9CE;&#xC740; &#xD32C;&#xCE35;&#xC744; &#xBCF4;&#xC720;&#xD55C; &#xD3F0;&#xD2B8;&#xC774;&#xB2E4;. </p><p>&#xC5ED;&#xC2DC;&#xB098; &#xC790;&#xD3ED;&#xACFC; &#xC790;&#xAC04;&#xC774; &#xC880; &#xC9E7;&#xC740;(&#xB124;&#xC774;&#xBC84; &#xC2A4;&#xD0C0;&#xC77C;&#xC778;&#xAC00; &#xBCF4;&#xB2E4;)&#xD3B8;&#xC758; &#xD3F0;&#xD2B8;&#xB85C; &#xAD70;&#xB354;&#xB354;&#xAE30;&#xB294; &#xC5C6;&#xC9C0;&#xB9CC;.. &#xC5ED;&#xC2DC;&#xB098; &#xC774;&#xC0C1;&#xD558;&#xAC8C; &#xC815;&#xC774; &#xC548;&#xAC00;.. &#xB9CE;&#xC774; &#xC0AC;&#xC6A9;&#xD558;&#xC9C4; &#xC54A;&#xC558;&#xB2E4;. </p><h4 id="fira-code-2014">Fira Code, 2014</h4><p>&#x2B50;&#x2B50;&#x2B50;&#x2B50;&#x2B50;</p><figure class="kg-card kg-image-card"><img src="https://blog.hkwon.me/content/images/2024/08/image-36.png" class="kg-image" alt="&#xB098;&#xC758; &#xD504;&#xB85C;&#xADF8;&#xB798;&#xBC0D; &#xD3F0;&#xD2B8; &#xC0AC;&#xC6A9; &#xC77C;&#xB300;&#xAE30;" loading="lazy" width="1878" height="1040" srcset="https://blog.hkwon.me/content/images/size/w600/2024/08/image-36.png 600w, https://blog.hkwon.me/content/images/size/w1000/2024/08/image-36.png 1000w, https://blog.hkwon.me/content/images/size/w1600/2024/08/image-36.png 1600w, https://blog.hkwon.me/content/images/2024/08/image-36.png 1878w" sizes="(min-width: 720px) 720px"></figure><p><code>IDE</code>&#xB97C; &#xC8FC;&#xB85C; <code>eclipse</code>&#xB97C; &#xB354; &#xB9CE;&#xC774; &#xC0AC;&#xC6A9;&#xD558;&#xB358; &#xC2DC;&#xC808; 3~4&#xB144;&#xC740; &#xC774; &#xD3F0;&#xD2B8;&#xB85C; &#xACC4;&#xC18D; &#xC0AC;&#xC6A9; &#xD588;&#xB358; &#xAE30;&#xC5B5;&#xC774; &#xC788;&#xB2E4;. &#xB0B4;&#xAC00; &#xC0AC;&#xC6A9; &#xD588;&#xB358; &#xD3F0;&#xD2B8; &#xC911;&#xC5D0; &#xC81C;&#xC77C; &#xCC98;&#xC74C;&#xC73C;&#xB85C; <code>ligature</code>&#xAC00; &#xC801;&#xC6A9;&#xB41C; &#xD3F0;&#xD2B8;&#xC600;&#xB358;&#xAC70; &#xAC19;&#xACE0; &#xADF8; &#xB9DB;&#xC5D0;&#xB77C;&#xB3C4; &#xC880; &#xB354; &#xAE38;&#xAC8C; &#xC0AC;&#xC6A9;&#xD588;&#xB358; &#xD3F0;&#xD2B8;&#xC600;&#xB2E4;.</p><p>&#xC774; &#xD3F0;&#xD2B8;&#xB3C4; &#xC544;&#xC9C1; &#xAC1C;&#xBC1C;&#xC790;&#xB4E4; &#xC0AC;&#xC774;&#xC5D0;&#xC11C; &#xB9CE;&#xC774; &#xC0AC;&#xC6A9; &#xB418;&#xACE0; &#xC0C1;&#xC704;&#xAD8C; &#xD3F0;&#xD2B8; &#xB290;&#xB08C;~</p><h4 id="menlo-2009-monaco-2006">Menlo 2009, Monaco 2006</h4><p>&#x2B50;&#x2B50;&#x2B50;&#x2B50;&#x2B50;</p><figure class="kg-card kg-image-card"><img src="https://blog.hkwon.me/content/images/2024/08/image-45.png" class="kg-image" alt="&#xB098;&#xC758; &#xD504;&#xB85C;&#xADF8;&#xB798;&#xBC0D; &#xD3F0;&#xD2B8; &#xC0AC;&#xC6A9; &#xC77C;&#xB300;&#xAE30;" loading="lazy" width="1310" height="788" srcset="https://blog.hkwon.me/content/images/size/w600/2024/08/image-45.png 600w, https://blog.hkwon.me/content/images/size/w1000/2024/08/image-45.png 1000w, https://blog.hkwon.me/content/images/2024/08/image-45.png 1310w" sizes="(min-width: 720px) 720px"></figure><p>&#xB9E5;&#xBD81;&#xC744; &#xBCF8;&#xACA9;&#xC801;&#xC73C;&#xB85C; &#xC0AC;&#xC6A9;&#xD558;&#xBA74;&#xC11C;&#xBD80;&#xD130; &#xD130;&#xBBF8;&#xB110; &#xAE30;&#xBCF8; &#xD3F0;&#xD2B8; &#xC600;&#xB098; &#xADF8;&#xB7AC;&#xB294;&#xB370; &#xC0DD;&#xAC01;&#xBCF4;&#xB2E4; &#xAC00;&#xB3C5;&#xC131;&#xB3C4; &#xAF64; &#xC88B;&#xACE0; &#xD130;&#xBBF8;&#xB110; &#xC0AC;&#xC6A9; &#xC6A9;&#xB3C4;&#xB85C; &#xAF64;&#xB098; &#xC624;&#xB7AB;&#xB3D9;&#xC548; &#xC560;&#xC6A9; &#xD588;&#xACE0;,  &#xC6F9;&#xBE0C;&#xB77C;&#xC6B0;&#xC800;&#xC6A9; &#xCF54;&#xB4DC; &#xD45C;&#xD604;&#xC774;&#xB098; &#xC5D0;&#xB514;&#xD130;&#xC5D0; <code>consolas</code> &#xC640; &#xAC19;&#xC774; &#xAE30;&#xBCF8;&#xC73C;&#xB85C; &#xC0AC;&#xC6A9;&#xD558;&#xAE30; &#xAF64;&#xB098; &#xC88B;&#xC740; &#xD3F0;&#xD2B8;&#xC774;&#xB2E4;.</p><p><code>Menlo</code>&#xB294; &#xB9E5;&#xC5D0;&#xC11C;&#xB294; &#xC544;&#xBB34;&#xC0DD;&#xAC01;&#xC5C6;&#xC774; &#xADF8;&#xB0E5; &#xAE30;&#xBCF8; &#xD3F0;&#xD2B8;&#xB85C; &#xC0AC;&#xC6A9;&#xD558;&#xAE30;&#xC5D0;&#xB294; &#xC544;&#xC8FC; &#xD6CC;&#xB96D;&#xD55C; &#xD3F0;&#xD2B8;&#xC774;&#xB2E4;.</p><h4 id="ibm-plex-mono-2017">IBM Plex Mono, 2017</h4><p>&#x2B50;&#x2B50;&#x2B50;&#x2B50;</p><figure class="kg-card kg-image-card"><img src="https://blog.hkwon.me/content/images/2024/08/image-40.png" class="kg-image" alt="&#xB098;&#xC758; &#xD504;&#xB85C;&#xADF8;&#xB798;&#xBC0D; &#xD3F0;&#xD2B8; &#xC0AC;&#xC6A9; &#xC77C;&#xB300;&#xAE30;" loading="lazy" width="1824" height="1042" srcset="https://blog.hkwon.me/content/images/size/w600/2024/08/image-40.png 600w, https://blog.hkwon.me/content/images/size/w1000/2024/08/image-40.png 1000w, https://blog.hkwon.me/content/images/size/w1600/2024/08/image-40.png 1600w, https://blog.hkwon.me/content/images/2024/08/image-40.png 1824w" sizes="(min-width: 720px) 720px"></figure><p>&#xB9D0;&#xADF8;&#xB300;&#xB85C; <code>IBM</code>&#xC5D0;&#xC11C; &#xC624;&#xD508;&#xC18C;&#xC2A4;&#xB85C; &#xBC30;&#xD3EC;&#xB41C; &#xD3F0;&#xD2B8;&#xC778;&#xB370; &#xC598;&#xB3C4; &#xC7A0;&#xAE50; &#xC0AC;&#xC6A9;&#xD558;&#xB2E4;&#xAC00;  &#xB9D0;&#xC558;&#xB358; &#xD3F0;&#xD2B8;&#xC774;&#xAE34; &#xD55C;&#xB370; &#xC544;&#xC9C1;&#xB3C4; &#xC774; &#xD3F0;&#xD2B8;&#xB97C; &#xC0AC;&#xB791;&#xD558;&#xB294; &#xAC1C;&#xBC1C;&#xC790;&#xB294; &#xAF64;&#xB098; &#xC788;&#xB294;&#xAC78;&#xB85C; &#xC54C;&#xACE0; &#xC788;&#xACE0; &#xC9C0;&#xAE08; &#xC6B0;&#xB9AC; &#xD300;&#xC6D0;&#xC911; &#xD55C;&#xBA85;&#xB3C4; &#xC774; &#xD3F0;&#xD2B8;&#xB97C; &#xC560;&#xC6A9;&#xD558;&#xACE0; &#xC788;&#xB2E4;.</p><h4 id="cascadia-code-2019">Cascadia Code, 2019</h4><p>&#x2B50;&#x2B50;&#x2B50;&#x2B50;</p><figure class="kg-card kg-image-card"><img src="https://blog.hkwon.me/content/images/2024/08/image-37.png" class="kg-image" alt="&#xB098;&#xC758; &#xD504;&#xB85C;&#xADF8;&#xB798;&#xBC0D; &#xD3F0;&#xD2B8; &#xC0AC;&#xC6A9; &#xC77C;&#xB300;&#xAE30;" loading="lazy" width="1778" height="1034" srcset="https://blog.hkwon.me/content/images/size/w600/2024/08/image-37.png 600w, https://blog.hkwon.me/content/images/size/w1000/2024/08/image-37.png 1000w, https://blog.hkwon.me/content/images/size/w1600/2024/08/image-37.png 1600w, https://blog.hkwon.me/content/images/2024/08/image-37.png 1778w" sizes="(min-width: 720px) 720px"></figure><p>&#xC774; &#xD3F0;&#xD2B8;&#xB294; <code>Microsoft</code>&#xC5D0;&#xC11C; &#xC624;&#xD508;&#xC18C;&#xC2A4;&#xB85C; &#xBC30;&#xD3EC;&#xD55C; &#xD3F0;&#xD2B8;&#xC778;&#xB370; &#xCC98;&#xC74C;&#xC5D0;&#xB294; &#xADF8;&#xB807;&#xC9C0;&#xB294; &#xC54A;&#xC558;&#xB358;&#xAC70; &#xAC19;&#xC740;&#xB370; &#xC774;&#xC81C;&#xB294; &#xAE30;&#xBCF8; &#xC708;&#xB3C4;&#xC6B0; &#xD130;&#xBBF8;&#xB110;&#xACFC; &#xBE44;&#xC96C;&#xC5BC; &#xC2A4;&#xD29C;&#xB514;&#xC624; &#xAE30;&#xBCF8; &#xD3F0;&#xD2B8;&#xB85C; &#xC9C0;&#xC815;&#xB41C;&#xAC70; &#xAC19;&#xB2E4;.</p><p>&#xC57D;&#xAC04; &#xB290;&#xB08C;&#xC774; <code>Fira Code</code>&#xC640; &#xBE44;&#xC2B7;&#xD55C; &#xB290;&#xB08C;&#xC774; &#xC788;&#xC5C8;&#xACE0; &#xC774;&#xD0E4;&#xB9AD;&#xCCB4;&#xAC00; &#xB2E4;&#xB978; &#xD3F0;&#xD2B8;&#xC640; &#xB2E4;&#xB978;&#xAC8C; &#xC57D;&#xAC04; &#xC7AC;&#xBBF8;&#xC9C4; &#xB290;&#xB08C;&#xC774; &#xC788;&#xB2E4;.</p><p>&#xADFC;&#xB370; &#xC774; &#xB2E4;&#xC74C;&#xC5D0; &#xC18C;&#xAC1C;&#xD560; &#xD3F0;&#xD2B8; &#xB54C;&#xBB38;&#xC5D0; &#xADF8;&#xB9AC; &#xC624;&#xB798; &#xC0AC;&#xC6A9;&#xD558;&#xC9C4; &#xC54A;&#xC558;&#xB358; &#xAE30;&#xC5B5;&#xC774; &#xC788;&#xB2E4;.</p><h4 id="jetbrains-mono-2020">JetBrains Mono 2020</h4><p>&#x2B50;&#x2B50;&#x2B50;&#x2B50;&#x2B50;</p><figure class="kg-card kg-image-card"><img src="https://blog.hkwon.me/content/images/2024/08/image-38.png" class="kg-image" alt="&#xB098;&#xC758; &#xD504;&#xB85C;&#xADF8;&#xB798;&#xBC0D; &#xD3F0;&#xD2B8; &#xC0AC;&#xC6A9; &#xC77C;&#xB300;&#xAE30;" loading="lazy" width="1808" height="1038" srcset="https://blog.hkwon.me/content/images/size/w600/2024/08/image-38.png 600w, https://blog.hkwon.me/content/images/size/w1000/2024/08/image-38.png 1000w, https://blog.hkwon.me/content/images/size/w1600/2024/08/image-38.png 1600w, https://blog.hkwon.me/content/images/2024/08/image-38.png 1808w" sizes="(min-width: 720px) 720px"></figure><p><code>JetBrain</code>&#xC5D0;&#xC11C; &#xCC98;&#xC74C; &#xCD9C;&#xC2DC; &#xD560;&#xB54C; &#xBD80;&#xD130; &#xCD5C;&#xADFC; &#xBA87;&#xB144;&#xAC04; &#xC8FC;&#xB825;&#xC73C;&#xB85C; &#xC0AC;&#xC6A9;&#xD558;&#xB358; &#xD3F0;&#xD2B8;&#xC774;&#xB2E4;. </p><p>&#xC790;&#xAC04;&#xC774; &#xADF8;&#xB807;&#xAC8C; &#xB112;&#xC740;&#xD3B8;&#xC740; &#xC544;&#xB2C8;&#xACE0; <code>IntelliJ</code>&#xB97C; &#xACC4;&#xC18D; &#xC0AC;&#xC6A9;&#xD558;&#xB2E4;&#xBCF4;&#xB2C8; &#xAC70;&#xBD80;&#xAC10; &#xC5C6;&#xC774; &#xADF8;&#xB0E5; &#xACC4;&#xC18D; &#xC0AC;&#xC6A9;&#xD588;&#xB358;&#xAC70; &#xAC19;&#xB2E4;. </p><p><code>x-height</code>&#xAC00; &#xB418;&#xAC8C; &#xC801;&#xC808;&#xD788; &#xC124;&#xC815;&#xB418;&#xC5B4; &#xC788;&#xC5B4;&#xC11C; &#xCF54;&#xB4DC;&#xB97C; &#xACC4;&#xC18D; &#xBCF4;&#xACE0; &#xC218;&#xC815;&#xD560; &#xB54C; &#xD3B8;&#xC548;&#xD568;&#xC744; &#xB290;&#xAF08;&#xB358;&#xAC70; &#xAC19;&#xB2E4;. &#xBE44;&#xAD50;&#xC801; &#xCD5C;&#xC2E0;&#xC5D0; &#xB098;&#xC628; &#xD3F0;&#xD2B8;&#xC5EC;&#xC11C; <code>ligature</code>&#xB3C4; &#xC798; &#xC801;&#xC6A9; &#xB418;&#xC5B4; &#xC788;&#xACE0; &#xCD5C;&#xC560; &#xD3F0;&#xD2B8; &#xC911; &#xD558;&#xB098;&#xC774;&#xB2E4;.</p><h4 id="meslo-lg-2013">Meslo LG 2013</h4><p>&#x2B50;&#x2B50;&#x2B50;&#x2B50;&#x2B50;</p><figure class="kg-card kg-image-card"><img src="https://blog.hkwon.me/content/images/2024/08/image-39.png" class="kg-image" alt="&#xB098;&#xC758; &#xD504;&#xB85C;&#xADF8;&#xB798;&#xBC0D; &#xD3F0;&#xD2B8; &#xC0AC;&#xC6A9; &#xC77C;&#xB300;&#xAE30;" loading="lazy" width="1824" height="1038" srcset="https://blog.hkwon.me/content/images/size/w600/2024/08/image-39.png 600w, https://blog.hkwon.me/content/images/size/w1000/2024/08/image-39.png 1000w, https://blog.hkwon.me/content/images/size/w1600/2024/08/image-39.png 1600w, https://blog.hkwon.me/content/images/2024/08/image-39.png 1824w" sizes="(min-width: 720px) 720px"></figure><p><code>Jetbrains Mono</code>&#xC640; &#xD568;&#xAED8; &#xAC00;&#xC7A5; &#xB9CE;&#xC774; &#xC0AC;&#xC6A9;&#xD588;&#xB358; &#xD3F0;&#xD2B8;&#xC774;&#xB2E4;. &#xC8FC;&#xB85C; &#xB9E5; &#xD130;&#xBBF8;&#xB110;&#xC6A9; &#xD3F0;&#xD2B8;&#xB85C; &#xB9CE;&#xC774; &#xC37C;&#xC5C8;&#xB294;&#xB370; &#xC598;&#xB294; &#xB2E4;&#xB978; &#xD3F0;&#xD2B8;&#xC640; &#xB2E4;&#xB974;&#xAC8C; &#xC904;&#xAC04;&#xACA9;&#xC774; &#xD3F0;&#xD2B8;&#xC5D0; &#xD3EC;&#xD568;&#xB41C; &#xD3F0;&#xD2B8;&#xAC00; &#xD568;&#xAED8; &#xB098;&#xC654;&#xC5C8;&#xB2E4;. </p><p><code>Menlo Regular</code> &#xAE30;&#xBC18;&#xC73C;&#xB85C; &#xCEE4;&#xC2A4;&#xD140;&#xC744; &#xC57D;&#xAC04; &#xD55C; &#xD3F0;&#xD2B8;&#xB85C; &#xB2E4;&#xB978; &#xD3F0;&#xD2B8;&#xC640;&#xB294; &#xB2E4;&#xB974;&#xAC8C; <code>LineGap</code>&#xC774;&#xB77C;&#xACE0; &#xD558;&#xB294; &#xC18D;&#xC131;&#xC744; &#xAC00;&#xC9C0;&#xACE0; &#xC788;&#xB2E4;. &#xC904;&#xAC04;&#xACA9;&#xC774; &#xB354; &#xB113;&#xAC8C; &#xACE0;&#xC815;&#xB41C; &#xC138;&#xD2B8;&#xB97C; &#xAC19;&#xC774; &#xBC30;&#xD3EC;&#xD55C;&#xB2E4;&#xACE0; &#xBCF4;&#xBA74; &#xB418;&#xB294;&#xB370; <code>IDE</code>&#xB098; &#xD130;&#xBBF8;&#xB110;&#xC5D0;&#xC11C; &#xC904;&#xAC04;&#xACA9; &#xC635;&#xC158;&#xC774; &#xC5C6;&#xB294; &#xACBD;&#xC6B0;&#xC5D0; &#xC720;&#xC6A9;&#xD558;&#xAC8C; &#xC0AC;&#xC6A9; &#xAC00;&#xB2A5;&#xD574;&#xC11C; &#xC8FC;&#xB85C; &#xD130;&#xBBF8;&#xB110;&#xC5D0;&#xC11C; &#xC8FC;&#xB825;&#xC73C;&#xB85C; &#xACC4;&#xC18D; &#xC0AC;&#xC6A9;&#xD588;&#xC5C8;&#xB2E4;.</p><h4 id="monolisa-2022">Monolisa, 2022</h4><p>&#x2B50;&#x2B50;&#x2B50;&#x2B50;&#x2B50;</p><figure class="kg-card kg-image-card"><img src="https://blog.hkwon.me/content/images/2024/08/image-42.png" class="kg-image" alt="&#xB098;&#xC758; &#xD504;&#xB85C;&#xADF8;&#xB798;&#xBC0D; &#xD3F0;&#xD2B8; &#xC0AC;&#xC6A9; &#xC77C;&#xB300;&#xAE30;" loading="lazy" width="2000" height="1458" srcset="https://blog.hkwon.me/content/images/size/w600/2024/08/image-42.png 600w, https://blog.hkwon.me/content/images/size/w1000/2024/08/image-42.png 1000w, https://blog.hkwon.me/content/images/size/w1600/2024/08/image-42.png 1600w, https://blog.hkwon.me/content/images/size/w2400/2024/08/image-42.png 2400w" sizes="(min-width: 720px) 720px"></figure><p>&#xC11C;&#xB450;&#xC5D0; &#xC598;&#xAE30; &#xD588;&#xB4EF;&#xC774; &#xC720;&#xB8CC;&#xB85C; &#xAD6C;&#xB9E4;&#xD55C; &#xD3F0;&#xD2B8;&#xAC00; &#xBC14;&#xB85C; &#xC774; &#xD3F0;&#xD2B8;&#xC774;&#xB2E4;. </p><p>&#xC6B0;&#xC5F0;&#xCE58; &#xC54A;&#xAC8C; &#xC11C;&#xD551; &#xC911;&#xC5D0; &#xCD94;&#xCC9C;&#xD558;&#xB294; &#xAE00;&#xC744; &#xBC1C;&#xACAC;&#xD588;&#xACE0; <code>Playground</code> &#xD398;&#xC774;&#xC9C0;&#xC5D0;&#xC11C; &#xC774;&#xAC83;&#xC800;&#xAC83; &#xB0B4; &#xC785;&#xB9DB;&#xC5D0; &#xB9DE;&#xAC8C; &#xCEE4;&#xC2A4;&#xD140;&#xC774; &#xAC00;&#xB2A5;&#xD558;&#xACE0; &#xC774;&#xD0E4;&#xB9AD; &#xAE00;&#xC790; &#xD45C;&#xD604;&#xB3C4; &#xB108;&#xBB34; &#xB9D8;&#xC5D0; &#xB4E4;&#xC5B4;&#xC11C;... &#xACB0;&#xAD6D; <code>pro</code> &#xBC84;&#xC804;&#xC744; &#xAD6C;&#xB9E4;&#xD588;&#xB2E4;. </p><p>&#xC9C0;&#xAE08; &#xAC70;&#xC758; &#xBAA8;&#xB4E0; <code>IDE</code>&#xC640; &#xD130;&#xBBF8;&#xB110; &#xB4F1; &#xD0A4;&#xBCF4;&#xB4DC;&#xB85C; &#xCE60; &#xC218; &#xC788;&#xB294; &#xAC70;&#xC758; &#xBAA8;&#xB4E0; &#xACF3;&#xC5D0; &#xC774; &#xD3F0;&#xD2B8;&#xB97C; &#xC0AC;&#xC6A9;&#xD558;&#xACE0; &#xC788;&#xB2E4;. &#xC65C;&#xB0D0;&#xD558;&#xBA74;... &#xB3C8; &#xC8FC;&#xACE0; &#xC0C0;&#xAE30; &#xB54C;&#xBB38;&#xC5D0; &#xC77C;&#xB2E8; &#xBF55;&#xC744; &#xBF51;&#xC544;&#xC57C; &#xD574;&#xC11C; &#x1F605;&#x1F605;&#x1F605;</p><p>&#xB0B4; &#xC778;&#xC0DD; &#xCC98;&#xC74C;&#xC73C;&#xB85C; &#xB3C8;&#xC744; &#xC8FC;&#xACE0; &#xC0B0; &#xD3F0;&#xD2B8;&#xC774;&#xAE30;&#xB3C4; &#xD558;&#xC9C0;&#xB9CC; &#xADF8; &#xC774;&#xC804;&#xC5D0; &#xB0B4;&#xAC00; &#xC6D0;&#xD588;&#xB358; &#xAE00;&#xB9AC;&#xD504;&#xC758; &#xBBF8;&#xBB18;&#xD55C; &#xBAA8;&#xC591; &#xBCC0;&#xD654;&#xB3C4; &#xAC00;&#xB2A5;&#xD574;&#xC11C; &#xC77C;&#xB2E8; &#xBA87;&#xB144; &#xAC04;&#xC740; &#xD3F0;&#xD2B8; &#xAC71;&#xC815;&#xC5C6;&#xC774; &#xC798; &#xC0AC;&#xC6A9;&#xD560; &#xAC83; &#xAC19;&#xB2E4;.</p><h2 id="%EB%82%98%EB%A7%8C%EC%9D%98-best-5">&#xB098;&#xB9CC;&#xC758; Best 5</h2><p>&#xC0AC;&#xC6A9;&#xD588;&#xB358; &#xD3F0;&#xD2B8;&#xB4E4; &#xC911;&#xC5D0;&#xC11C; &#xC0AC;&#xC6A9;&#xAE30;&#xAC04; &#xB4F1;&#xC744; &#xACE0;&#xB824;&#xD55C; &#xB098;&#xB984;&#xC758; &#xC21C;&#xC704;&#xB97C; &#xAD73;&#xC774; &#xD55C;&#xBC88; &#xB9E4;&#xACA8;&#xBCF4;&#xC790;&#xBA74; &#xB2E4;&#xC74C;&#xACFC; &#xAC19;&#xB2E4;.</p><ol><li><strong>Monolisa - &#xC774;&#xAC74; &#xB3C8;&#xC8FC;&#xACE0; &#xC0C0;&#xAE30; &#xB54C;&#xBB38;&#xC5D0; &#xC5B4;&#xCA54; &#xC218; &#xC5C6;&#xB2E4; &#x314B;&#x314B;&#x314B;</strong></li><li><strong>Jetbrains Mono</strong></li><li><strong>Meslo LGMDZ nerd font mono</strong></li><li>Fira code</li><li>Cascadia Code</li></ol><h2 id="%EB%A7%88%EB%AC%B4%EB%A6%AC">&#xB9C8;&#xBB34;&#xB9AC;</h2><p>&#xD504;&#xB85C;&#xADF8;&#xB798;&#xBC0D; &#xD3F0;&#xD2B8; &#xD0D0;&#xD5D8;&#xC790;&#xB4E4;&#xC744; &#xC704;&#xD574; &#xC57D;&#xAC04;&#xC758; &#xB3C4;&#xC6C0;&#xC774; &#xB410;&#xC73C;&#xBA74; &#xC88B;&#xACA0;&#xACE0;, &#xC544;&#xC9C1; &#xB0B4; &#xC5EC;&#xC815;(?)&#xB3C4; &#xC5D4;&#xB529;&#xC774; &#xC544;&#xB2C8;&#xAE30; &#xB54C;&#xBB38;&#xC5D0; &#xC5EC;&#xC815;&#xC774; &#xBA48;&#xCD94;&#xB294; &#xC21C;&#xAC04;&#xAE4C;&#xC9C0; &#xB9C8;&#xC74C;&#xC5D0; &#xB4DC;&#xB294; &#xD3F0;&#xD2B8;&#xAC00; &#xC788;&#xB2E4;&#xBA74; &#xACC4;&#xC18D; &#xCD94;&#xAC00;&#xD574;&#xBCF4;&#xACA0;&#xB2E4;. </p><p>&#xB2E4;&#xC74C;&#xC740; &#xADF8; &#xB3D9;&#xC548; &#xAC70;&#xCCD0;&#xAC04; <code>&#xD0A4;&#xBCF4;&#xB4DC;</code>&#xB3C4; &#xD55C;&#xBC88; &#xB9AC;&#xBDF0; &#xD574;&#xBCFC;&#xAE4C; &#x314B;&#x314B;</p><p>Happy Coding~!</p>]]></content:encoded></item><item><title><![CDATA[Istio 를 통한 path(url) 기반 Local Rate Limit 적용]]></title><description><![CDATA[<p>&#xBA87; &#xB144; &#xC804;&#xC778;&#xC9C0;&#xB294; &#xAE30;&#xC5B5;&#xB098;&#xC9C4; &#xC54A;&#xC9C0;&#xB9CC; Rate Limit &#xC801;&#xC6A9;&#xC740; &#xD56D;&#xC0C1; &#xC560;&#xD50C;&#xB9AC;&#xCF00;&#xC774;&#xC158; &#xCABD;&#xC5D0;&#xC11C; &#xCC98;&#xB9AC;&#xD558;&#xB294; &#xAC83;&#xC774; &#xB2F9;&#xC5F0;&#xD558;&#xB2E4;&#xB294; &#xAC83;&#xC774; &#xC8FC;&#xB41C; &#xC758;&#xACAC;&#xC774;&#xC5C8;&#xB2E4;. &#xADF8;</p>]]></description><link>https://blog.hkwon.me/istio-local-rate-limit/</link><guid isPermaLink="false">66c57d6f5a7d910001307561</guid><category><![CDATA[istio]]></category><category><![CDATA[rate limit]]></category><category><![CDATA[local rate limit]]></category><dc:creator><![CDATA[Kevin H. Kwon]]></dc:creator><pubDate>Thu, 22 Aug 2024 11:48:33 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1683875745903-2d0f2c2d3aef?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDI3fHxsaW1pdHxlbnwwfHx8fDE3MjQyMTg4Mjh8MA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" medium="image"/><content:encoded><![CDATA[<img src="https://images.unsplash.com/photo-1683875745903-2d0f2c2d3aef?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDI3fHxsaW1pdHxlbnwwfHx8fDE3MjQyMTg4Mjh8MA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" alt="Istio &#xB97C; &#xD1B5;&#xD55C; path(url) &#xAE30;&#xBC18; Local Rate Limit &#xC801;&#xC6A9;"><p>&#xBA87; &#xB144; &#xC804;&#xC778;&#xC9C0;&#xB294; &#xAE30;&#xC5B5;&#xB098;&#xC9C4; &#xC54A;&#xC9C0;&#xB9CC; Rate Limit &#xC801;&#xC6A9;&#xC740; &#xD56D;&#xC0C1; &#xC560;&#xD50C;&#xB9AC;&#xCF00;&#xC774;&#xC158; &#xCABD;&#xC5D0;&#xC11C; &#xCC98;&#xB9AC;&#xD558;&#xB294; &#xAC83;&#xC774; &#xB2F9;&#xC5F0;&#xD558;&#xB2E4;&#xB294; &#xAC83;&#xC774; &#xC8FC;&#xB41C; &#xC758;&#xACAC;&#xC774;&#xC5C8;&#xB2E4;. &#xADF8;&#xB798;&#xC11C; &#xADF8;&#xB54C; &#xB2F9;&#xC2DC; Bucket4J &#xB97C; &#xD1B5;&#xD574;&#xC11C; Spring &#xCABD;&#xC5D0;&#xC11C; &#xCC98;&#xB9AC;&#xD558;&#xACE0; &#xD588;&#xB358; &#xAE30;&#xC5B5;&#xC774; &#xC788;&#xB2E4;.</p><p>&#xC774;&#xC81C;&#xB294; &#xB2F9;&#xC5F0;&#xD558;&#xAC8C;&#xB3C4; Istio&#xC640; &#xAC19;&#xC740; Service Mesh&#xCABD;&#xC5D0;&#xC11C; &#xCC98;&#xB9AC;&#xD558;&#xB294; &#xAC83;&#xC774; &#xC751;&#xB2F9; &#xB9DE;&#xB2E4;&#xACE0; &#xC0DD;&#xAC01;&#xB418;&#xB294; &#xAC83;&#xC774; &#xAC1C;&#xBC1C; &#xC138;&#xC0C1;&#xC774; &#xC774;&#xC81C; &#xC810;&#xC810; &#xB354; &#xD074;&#xB77C;&#xC6B0;&#xB4DC;&#xD5A5;&#xC73C;&#xB85C; &#xC774;&#xB3D9;&#xB41C;&#xB2E4;&#xB294; &#xB290;&#xB08C;&#xC774;&#xB2E4;.</p><p>&#xAC15;&#xB825;&#xD55C; &#xC624;&#xD508; &#xC18C;&#xC2A4; &#xC11C;&#xBE44;&#xC2A4; &#xBA54;&#xC2DC;&#xC778; Istio&#xB294; &#xB9C8;&#xC774;&#xD06C;&#xB85C;&#xC11C;&#xBE44;&#xC2A4; &#xC544;&#xD0A4;&#xD14D;&#xCC98;&#xB97C; &#xC6B4;&#xC601;/&#xAD00;&#xB9AC; &#xD558;&#xAE30; &#xC704;&#xD55C; &#xAD49;&#xC7A5;&#xD788; &#xB2E4;&#xC591;&#xD55C; &#xAE30;&#xB2A5;&#xC744; &#xC81C;&#xACF5;&#xD55C;&#xB2E4;. &#xD558;&#xC9C0;&#xB9CC; &#xB108;&#xBB34; &#xB9CE;&#xC740; &#xAE30;&#xB2A5;&#xC744; &#xB2F4;&#xC740; &#xD0D3; &#xC77C;&#xAE4C;.. &#xAE30;&#xB2A5;&#xC774; &#xB108;&#xBB34; &#xB9CE;&#xACE0; &#xC124;&#xC815;&#xD558;&#xAE30; &#xB108;&#xBB34; &#xC5B4;&#xB835;&#xACE0; &#xB108;&#xBB34; &#xBD88;&#xD3B8;&#xD558;&#xB2E4; &#x1F602;</p><p>&#xB9CC;&#xB4E4;&#xACE0; &#xC788;&#xB294; &#xC11C;&#xBE44;&#xC2A4;&#xC5D0;&#xC11C; Rate Limit&#xC744; &#xC801;&#xC6A9;&#xD558;&#xB824; &#xD588;&#xACE0;, &#xB2E4;&#xC591;&#xD55C; &#xACBD;&#xC6B0;&#xC758; &#xC218;&#xC5D0; &#xC758;&#xD574;&#xC11C; &#xD558;&#xB098;&#xC758; &#xC778;&#xC2A4;&#xD134;&#xC2A4;&#xC5D0;&#xC11C; &#xD2B9;&#xBCC4;&#xD55C; Path&#xB97C; &#xAC00;&#xC9C4; &#xB188;&#xB9CC; &#xC81C;&#xD55C;&#xC744; &#xAC00;&#xD558;&#xB824; &#xD558;&#xB2C8;, &#xACF5;&#xC2DD; &#xBB38;&#xC11C; &#xCC38;&#xC870; &#xB9CC;&#xC73C;&#xB85C;&#xB294; &#xD574;&#xACB0;&#xC774; &#xC798; &#xC548;&#xB418;&#xC5C8;&#xACE0; &#xBA87;&#xC77C;&#xC740; &#xACE0;&#xC0DD;&#xD55C; &#xAE30;&#xC5B5;&#xC774; &#xC788;&#xC5B4;&#xC11C; Istio &#xBC0F; Envoy&#xC5D0; &#xB300;&#xD55C; &#xAC04;&#xB7B5;&#xD55C; &#xC815;&#xB9AC;&#xC640; &#xC0BD;&#xC9C8;&#xAE30;&#xB97C; &#xD55C;&#xBC88; &#xD480;&#xC5B4; &#xC368;&#xBCFC;&#xAE4C; &#xD55C;&#xB2E4;. </p><h1 id="rate-limit%EC%9D%B4%EB%9E%80">Rate Limit&#xC774;&#xB780;</h1><p>Rate Limit&#xB780; &#xC11C;&#xBE44;&#xC2A4; &#xD639;&#xC740; API&#xB97C; &#xC6B4;&#xC601;&#xD568;&#xC5D0; &#xC788;&#xC5B4;&#xC11C; &#xD2B9;&#xC815; &#xC2DC;&#xAC04; &#xB3D9;&#xC548; &#xD5C8;&#xC6A9;&#xB418;&#xB294; &#xCD5C;&#xB300; &#xC694;&#xCCAD; &#xD69F;&#xC218;&#xB97C; &#xC81C;&#xD55C;&#xD558;&#xB294; &#xAE30;&#xB2A5;&#xC774;&#xACE0;, &#xB300;&#xBD80;&#xBD84; &#xC548;&#xC815;&#xC801;&#xC778; &#xC11C;&#xBE44;&#xC2A4; &#xC6B4;&#xC601;&#xC744; &#xC704;&#xD574; &#xD2B9;&#xC815; &#xC2DC;&#xC2A4;&#xD15C;&#xC758; &#xACFC;&#xBD80;&#xD558; &#xB4F1;&#xC744; &#xC870;&#xC808;&#xD558;&#xAC70;&#xB098; &#xC81C;&#xC5B4;&#xD558;&#xAE30; &#xC704;&#xD574; &#xC0AC;&#xC6A9;&#xD55C;&#xB2E4;. </p><p>&#xD55C;&#xAD6D;&#xB9D0;&#xB85C; &#xD558;&#xC790;&#xBA74; &#xC694;&#xCCAD; &#xC81C;&#xD55C; &#xD639;&#xC740; &#xD638;&#xCD9C; &#xC81C;&#xD55C;, &#xC18D;&#xB3C4; &#xC81C;&#xD55C; &#xB4F1;&#xC73C;&#xB85C; &#xBD88;&#xB9AC;&#xC6B0;&#xAE30;&#xB294; &#xD558;&#xB294;&#xB370; &#xC5B4;&#xB290; &#xAC83; &#xD558;&#xB098; &#xD45C;&#xD604;&#xC774; &#xC81C;&#xB300;&#xB85C; &#xC548;&#xB418;&#xB294; &#xAC83; &#xAC19;&#xC544;&#xC11C; &#xC55E;&#xC73C;&#xB85C;&#xB3C4; &#xADF8;&#xB0E5; Rate Limit&#xC73C;&#xB85C; &#xAE30;&#xC220;&#xD55C;&#xB2E4;.</p><p>&#xC774;&#xB7EC;&#xD55C; &#xC81C;&#xD55C; &#xD615;&#xD0DC; &#xC11C;&#xBE44;&#xC2A4;&#xB97C; &#xAD6C;&#xD604;&#xD558;&#xAE30; &#xC704;&#xD55C; &#xC54C;&#xACE0;&#xB9AC;&#xC998;&#xC740; &#xC544;&#xB798;&#xC640; &#xAC19;&#xC740; &#xAC83;&#xB4E4;&#xC774; &#xB9CE;&#xC774; &#xC0AC;&#xC6A9;&#xB418;&#xACE0;, Istio&#xC5D0;&#xC11C;&#xB294; <code>Token Bucket</code> &#xC744; &#xC0AC;&#xC6A9;&#xD55C;&#xB2E4;. &#xAC04;&#xB2E8;&#xD55C; &#xC54C;&#xACE0;&#xB9AC;&#xC998; &#xC124;&#xBA85;&#xC740; <a href="https://en.wikipedia.org/wiki/Rate_limiting?ref=blog.hkwon.me" rel="noreferrer">&#xC704;&#xD0A4; &#xD398;&#xC774;&#xC9C0;</a>&#xB97C; &#xCC38;&#xC870;&#xD558;&#xBA74; &#xC88B;&#xACA0;&#xB2E4;.</p><ul><li>Token Bucket Algorithm <em>#envoy&#xC5D0;&#xC120; &#xC774; &#xC54C;&#xACE0;&#xB9AC;&#xC998; &#xC0AC;&#xC6A9;</em></li><li>Leaky&#xA0;Bucket&#xA0;Algorithm</li><li>Fixed&#xA0;Window&#xA0;Counter</li><li>Sliding&#xA0;Window&#xA0;Log</li></ul><h1 id="istio%EC%9D%98-rate-limit">Istio&#xC758; Rate Limit </h1><p>&#xC55E;&#xC11C; &#xC598;&#xAE30;&#xD588;&#xC9C0;&#xB9CC; Istio&#xB97C; &#xD1B5;&#xD574; &#xB4E4;&#xC5B4;&#xC624;&#xB294; &#xD2B8;&#xB798;&#xD53D;&#xC744; &#xB3D9;&#xC801;&#xC73C;&#xB85C; &#xC81C;&#xC5B4;&#xD558;&#xACE0; &#xAD00;&#xB9AC;&#xD558;&#xB294; &#xAE30;&#xB2A5;&#xC740; &#xAD49;&#xC7A5;&#xD788; &#xC885;&#xB958;&#xAC00; &#xB9CE;&#xB2E4;. &#xD2B8;&#xB798;&#xD53D;&#xC5D0; &#xB300;&#xD55C; &#xAD00;&#xB9AC;, &#xBCF4;&#xC548;, &#xC815;&#xCC45;, &#xAD00;&#xCE21; &#xB4F1;&#xC758; &#xBAA8;&#xB4E0; &#xCC98;&#xB9AC;&#xB294; Envoy Proxy&#xB97C; &#xD1B5;&#xD574; &#xB3D9;&#xC801;&#xC73C;&#xB85C; &#xC124;&#xC815; &#xB418;&#xACE0; &#xAD00;&#xB9AC;&#xB41C;&#xB2E4;.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.hkwon.me/content/images/2024/08/image-3.png" class="kg-image" alt="Istio &#xB97C; &#xD1B5;&#xD55C; path(url) &#xAE30;&#xBC18; Local Rate Limit &#xC801;&#xC6A9;" loading="lazy" width="1538" height="1016" srcset="https://blog.hkwon.me/content/images/size/w600/2024/08/image-3.png 600w, https://blog.hkwon.me/content/images/size/w1000/2024/08/image-3.png 1000w, https://blog.hkwon.me/content/images/2024/08/image-3.png 1538w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">&#xCD9C;&#xCC98;: </span><a href="https://istio.io/latest/about/service-mesh/?ref=blog.hkwon.me"><span style="white-space: pre-wrap;">https://istio.io/latest/about/service-mesh/</span></a></figcaption></figure><p>&#xADF8;&#xB798;&#xC11C; &#xBA3C;&#xC800; Rate Limit &#xC124;&#xC815;&#xC744; &#xC11C;&#xC220;&#xD558;&#xAE30;&#xC804;&#xC5D0; Envoy&#xAC00; &#xC5B4;&#xB5A4;&#xC2DD;&#xC73C;&#xB85C; &#xD2B8;&#xB798;&#xD53D;&#xC744; &#xAD00;&#xB9AC;&#xD558;&#xB294;&#xC9C0; &#xC54C;&#xC544;&#xBCFC; &#xD544;&#xC694;&#xC131;&#xC774; &#xC788;&#xC5B4;&#xC11C; &#xB9AC;&#xC11C;&#xCE58; &#xD574;&#xBCF8; &#xAE40;&#xC5D0; &#xC0B4;&#xD3B4;&#xBCF4;&#xACE0; &#xB118;&#xC5B4;&#xAC00;&#xC57C;&#xD560; &#xC77C;&#xBD80; &#xC911;&#xC694;&#xD55C; &#xCC98;&#xB9AC; &#xACFC;&#xC815;&#xC744; &#xC544;&#xB798;&#xC640; &#xAC19;&#xC774; &#xC815;&#xB9AC;&#xD574;&#xBCF4;&#xC558;&#xB2E4;.</p><figure class="kg-card kg-image-card kg-width-wide kg-card-hascaption"><img src="https://blog.hkwon.me/content/images/2024/08/image-10.png" class="kg-image" alt="Istio &#xB97C; &#xD1B5;&#xD55C; path(url) &#xAE30;&#xBC18; Local Rate Limit &#xC801;&#xC6A9;" loading="lazy" width="2000" height="484" srcset="https://blog.hkwon.me/content/images/size/w600/2024/08/image-10.png 600w, https://blog.hkwon.me/content/images/size/w1000/2024/08/image-10.png 1000w, https://blog.hkwon.me/content/images/size/w1600/2024/08/image-10.png 1600w, https://blog.hkwon.me/content/images/2024/08/image-10.png 2000w" sizes="(min-width: 1200px) 1200px"><figcaption><span style="white-space: pre-wrap;">&#xCD9C;&#xCC98;: &#xAD8C;&#xD601; &#xBE14;&#xB85C;&#xADF8;</span></figcaption></figure><p>&#xD2B8;&#xB798;&#xD53D;&#xC774; Istio&#xB97C; &#xD1B5;&#xD574; &#xC720;&#xC785;&#xC774; &#xB418;&#xBA74; Sidecar&#xB97C; &#xD1B5;&#xD574; &#xBC30;&#xD3EC;&#xB41C; Envoy Proxy&#xB294; &#xC694;&#xC57D;&#xD558;&#xC790;&#xBA74; &#xB2E4;&#xC74C;&#xACFC; &#xAC19;&#xC740; &#xB3D9;&#xC791;&#xC744; &#xC218;&#xD589;&#xD55C;&#xB2E4;. <a href="https://www.envoyproxy.io/docs/envoy/latest/intro/life_of_a_request?ref=blog.hkwon.me#" rel="noreferrer">&#xC804;&#xCCB4; &#xC694;&#xCCAD;&#xC5D0; &#xB300;&#xD55C; &#xB77C;&#xC774;&#xD504;&#xC0AC;&#xC774;&#xD074; &#xBB38;&#xC11C;</a>&#xC5D0; &#xC0C1;&#xC138;&#xD55C; &#xC124;&#xBA85;&#xC740; &#xB2F4;&#xACA8; &#xC788;&#xC73C;&#xB2C8; &#xB514;&#xD14C;&#xC77C;&#xD55C; &#xBD80;&#xBD84;&#xC774; &#xAD81;&#xAE08;&#xD558;&#xC2E0; &#xBD84;&#xB4E4;&#xC740; &#xCC38;&#xC870;&#xD558;&#xC2DC;&#xBA74; &#xC88B;&#xACA0;&#xB2E4;.</p><ul><li>Listener Filter&#xB294;&#xA0;&#xB9AC;&#xC2A4;&#xB108;&#xC5D0; &#xAD6C;&#xC131;&#xB41C; &#xC8FC;&#xC18C;&#xC640; &#xD3EC;&#xD2B8;&#xC5D0; &#xC0C1;&#xC751;&#xD558;&#xB294; &#xC694;&#xCCAD;&#xC774; &#xB4E4;&#xC5B4;&#xC624;&#xBA74;, &#xB9AC;&#xC2A4;&#xB108; &#xB0B4;&#xBD80;&#xC801;&#xC73C;&#xB85C; &#xB9AC;&#xC2A4;&#xB108; &#xD544;&#xD130;&#xB85C; &#xC804;&#xB2EC;&#xD558;&#xC5EC; &#xCEE4;&#xB125;&#xC158; &#xBA54;&#xD0C0;&#xB370;&#xC774;&#xD130;&#xB97C; &#xC870;&#xC791;&#xD558;&#xACE0; &#xB124;&#xD2B8;&#xC6CC;&#xD06C; &#xD544;&#xD130;&#xB85C; &#xC804;&#xB2EC;</li><li>Network Filter&#xB97C; &#xC21C;&#xD68C;&#xD558;&#xBA74;&#xC11C; &#xD2B8;&#xB798;&#xD53D; &#xD2B9;&#xC131;&#xC5D0; &#xB530;&#xB978; &#xC801;&#xD569;&#xD55C; Filter&#xB97C; &#xCC3E;&#xACE0; &#xD574;&#xB2F9; Filter&#xAC00; &#xC694;&#xCCAD;&#xC744; &#xCC98;&#xB9AC;. &#xC81C;&#xACF5;&#xB418;&#xB294; &#xBE4C;&#xD2B8;&#xC778; &#xD544;&#xD130; &#xC885;&#xB958;&#xAC00; &#xC5B4;&#xB9C8;&#xBB34;&#xC2DC;&#xD558;&#xACE0; &#xC790;&#xC138;&#xD55C; &#xD544;&#xD130; &#xC815;&#xBCF4;&#xB294; <a href="https://www.envoyproxy.io/docs/envoy/latest/configuration/listeners/network_filters/network_filters?ref=blog.hkwon.me" rel="noreferrer">&#xB808;&#xD37C;&#xB7F0;&#xC2A4;</a>&#xB97C; &#xCC38;&#xC870;</li><li>HTTP &#xC694;&#xCCAD;&#xC778; &#xACBD;&#xC6B0; HTTP Connection Filter&#xB97C; &#xD1B5;&#xD574; &#xD2B8;&#xB798;&#xD53D;&#xC744; &#xCC98;&#xB9AC;</li><li>&#xB9C8;&#xC9C0;&#xB9C9; Route &#xB97C; &#xD1B5;&#xD574; Upstream endpoint&#xB85C; &#xC5F0;&#xACB0;</li><li>&#xC804;&#xCCB4; &#xC694;&#xCCAD;&#xC5D0; &#xB300;&#xD55C; &#xC0C1;&#xC138;&#xD55C; &#xC124;&#xBA85;&#xC740; <a href="https://www.envoyproxy.io/docs/envoy/latest/intro/life_of_a_request?ref=blog.hkwon.me#" rel="noreferrer">&#xACF5;&#xC2DD; &#xBB38;&#xC11C;(Life of a request)</a> &#xC798; &#xC124;&#xBA85;&#xB418;&#xC5B4; &#xC788;&#xC73C;&#xBBC0;&#xB85C; &#xC0C1;&#xC138;&#xD55C; &#xC124;&#xBA85;&#xC774; &#xD544;&#xC694;&#xD55C; &#xACBD;&#xC6B0; &#xCC38;&#xC870;</li></ul><p>&#xC5EC;&#xAE30;&#xC11C; Rate Limit &#xCC98;&#xB9AC;&#xB97C; &#xB2F4;&#xB2F9; &#xD558;&#xB294; &#xBD80;&#xBD84;&#xC740; Network Filter &#xC911;&#xC5D0; &#xD558;&#xB098;&#xC774;&#xBA70;, &#xB72F;&#xC5B4;&#xBCF4;&#xBA74; &#xC544;&#xB798;&#xC640; &#xAC19;&#xC740; &#xD504;&#xB85C;&#xC138;&#xC2A4;&#xB85C; &#xCC98;&#xB9AC;&#xB41C;&#xB2E4;&#xACE0; &#xBCFC; &#xC218; &#xC788;&#xB2E4;.</p><p>Network Filer, HTTP Filter 2&#xAC00;&#xC9C0;&#xC5D0;&#xC11C; &#xBAA8;&#xB450; Rate Limit &#xC124;&#xC815;&#xC744; &#xC9C4;&#xD589;&#xD560; &#xC218; &#xC788;&#xACE0;, &#xC6D0;&#xD558;&#xB294; &#xAD6C;&#xD604; &#xBC29;&#xC2DD;&#xC5D0; &#xB530;&#xB77C; &#xD574;&#xB2F9; Filter&#xC5D0; &#xC124;&#xC815;&#xC744; &#xD558;&#xBA74; &#xB41C;&#xB2E4;. </p><figure class="kg-card kg-image-card kg-width-wide kg-card-hascaption"><img src="https://blog.hkwon.me/content/images/2024/08/image-13.png" class="kg-image" alt="Istio &#xB97C; &#xD1B5;&#xD55C; path(url) &#xAE30;&#xBC18; Local Rate Limit &#xC801;&#xC6A9;" loading="lazy" width="2000" height="423" srcset="https://blog.hkwon.me/content/images/size/w600/2024/08/image-13.png 600w, https://blog.hkwon.me/content/images/size/w1000/2024/08/image-13.png 1000w, https://blog.hkwon.me/content/images/size/w1600/2024/08/image-13.png 1600w, https://blog.hkwon.me/content/images/2024/08/image-13.png 2000w" sizes="(min-width: 1200px) 1200px"><figcaption><span style="white-space: pre-wrap;">&#xCD9C;&#xCC98;: &#xAD8C;&#xD601; &#xBE14;&#xB85C;&#xADF8;</span></figcaption></figure><p>Envoy&#xB294; Global&#xACFC; Local&#xC758; &#xB450; &#xAC00;&#xC9C0; Rate Limit&#xC744; &#xC9C0;&#xC6D0;&#xD558;&#xACE0;, &#xAC01;&#xAC01;&#xC758; &#xB124;&#xD2B8;&#xC6CC;&#xD06C; &#xD544;&#xD130; &#xD639;&#xC740; HTTP &#xD544;&#xD130;&#xB97C; &#xD1B5;&#xD574; Rate Limit&#xC744; &#xC124;&#xC815;&#xD558;&#xACE0; &#xAD00;&#xB9AC; &#xD560; &#xC218; &#xC788;&#xB2E4;. &#xAC01;&#xAC01;&#xC758; &#xD615;&#xC2DD;&#xC5D0; &#xB530;&#xB77C; &#xAD6C;&#xC131;&#xD574;&#xC57C;&#xD560; &#xCD94;&#xAC00;&#xC801;&#xC778; &#xC678;&#xBD80; &#xC11C;&#xBE44;&#xC2A4; &#xB4F1;&#xC774; &#xC788;&#xC73C;&#xBBC0;&#xB85C; &#xAC04;&#xB7B5;&#xD788; &#xC124;&#xBA85;&#xD574; &#xBCF8;&#xB2E4;.</p><h2 id="global-rate-limit">Global Rate Limit</h2><p>Global Rate Limit&#xC740; &#xC804;&#xCCB4; &#xBA54;&#xC2DC;&#xC758; Limiting&#xB97C; &#xC81C;&#xACF5;&#xD558;&#xAE30; &#xC704;&#xD574; Global gRPC Rate Limit Service&#xB97C; &#xC0AC;&#xC6A9;&#xD55C;&#xB2E4;. Istio &#xC678;&#xBD80;&#xC5D0;&#xC11C; Rate Limit&#xC744; &#xCC98;&#xB9AC;&#xD558;&#xAE30; &#xC704;&#xD574; Redis&#xB97C; &#xAE30;&#xBC18;&#xC73C;&#xB85C; &#xD55C; Go&#xB85C; &#xC9DC;&#xC5EC;&#xC9C4; &#xC11C;&#xBE44;&#xC2A4;&#xC774;&#xACE0; &#xD574;&#xB2F9; &#xC124;&#xC815;&#xC744; &#xC0AC;&#xC6A9;&#xD558;&#xB824;&#xBA74; Redis&#xC640; &#xD568;&#xAED8; &#xC678;&#xBD80; Rate Limiter&#xB97C; &#xC124;&#xCE58;&#xD574;&#xC57C; &#xD55C;&#xB2E4;. </p><figure class="kg-card kg-image-card kg-width-wide kg-card-hascaption"><img src="https://blog.hkwon.me/content/images/2024/08/image-17.png" class="kg-image" alt="Istio &#xB97C; &#xD1B5;&#xD55C; path(url) &#xAE30;&#xBC18; Local Rate Limit &#xC801;&#xC6A9;" loading="lazy" width="2000" height="1222" srcset="https://blog.hkwon.me/content/images/size/w600/2024/08/image-17.png 600w, https://blog.hkwon.me/content/images/size/w1000/2024/08/image-17.png 1000w, https://blog.hkwon.me/content/images/size/w1600/2024/08/image-17.png 1600w, https://blog.hkwon.me/content/images/2024/08/image-17.png 2066w" sizes="(min-width: 1200px) 1200px"><figcaption><span style="white-space: pre-wrap;">&#xCD9C;&#xCC98;: &#xAD8C;&#xD601; &#xBE14;&#xB85C;&#xADF8;</span></figcaption></figure><p>Local &#xBC29;&#xC2DD;&#xACFC;&#xC758; &#xCC28;&#xC774;&#xC810;&#xC740; &#xAC01;&#xAC01; &#xC778;&#xC2A4;&#xD134;&#xC2A4;&#xC758; Envoy Proxy&#xB97C; &#xC0AC;&#xC6A9;&#xD558;&#xB294; &#xAC83;&#xC774; &#xC544;&#xB2C8;&#xB77C; Ingress Gateway&#xC758; Envoy&#xB97C; &#xD1B5;&#xD574; &#xC804;&#xC5ED;&#xC73C;&#xB85C; &#xC124;&#xC815;&#xD558;&#xB294; &#xAC83;&#xC774; &#xAC00;&#xC7A5; &#xD070; &#xCC28;&#xC774;&#xC810;&#xC774;&#xB77C; &#xBCFC; &#xC218; &#xC788;&#xB2E4;. &#xB098;&#xBA38;&#xC9C0; &#xC774;&#xC288;&#xB098; &#xCC28;&#xC774;&#xC810; &#xC815;&#xB9AC;&#xD574;&#xBCF4;&#xC790;&#xBA74; &#xB2E4;&#xC74C;&#xACFC; &#xAC19;&#xB2E4;.</p><ul><li>&#xBCC4;&#xB3C4;&#xC758; Global Rate Limit Service&#xB97C; &#xAD6C;&#xD604; &#xD574;&#xC57C;&#xD568;<ul><li>&#xC0D8;&#xD50C;&#xC740; &#xC81C;&#xACF5;&#xB428;, <a href="https://github.com/Ishujeet/Istio-rate-limit/blob/master/global-rate-limit/rate-limit-service.yaml?ref=blog.hkwon.me" rel="noreferrer">sample</a></li><li>&#xC124;&#xCE58; &#xC790;&#xCCB4;&#xB294; &#xC5B4;&#xB835;&#xC9C4; &#xC54A;&#xB294;&#xB370; &#xC0D8;&#xD50C; &#xC790;&#xCCB4;&#xB294; 2022&#xB144; 08&#xC6D4; 16&#xC77C; &#xAD6C;&#xD604;&#xCCB4;&#xB85C; &#xC124;&#xCE58;&#xD558;&#xB294;&#xB370; &#xC218;&#xC815;&#xB41C;&#xC9C0; &#xAF64; &#xB418;&#xC5B4; &#xBCF4;&#xC774;&#xAE34; &#xD558;&#xB2C8; &#xCC38;&#xC870;</li><li>redis backend&#xAC00; &#xD544;&#xC694;</li></ul></li><li>Local Rate Limit&#xACFC; &#xBCD1;&#xD589;&#xD558;&#xC5EC; &#xC0AC;&#xC6A9; &#xAC00;&#xB2A5;</li><li>Istio Ingress Gateway&#xC758; Envoy&#xC5D0;&#xC11C; &#xC804;&#xC5ED;&#xC73C;&#xB85C; &#xC124;&#xC815;&#xB41C; Rate Limit&#xC744; &#xCC98;&#xB9AC;</li></ul><p>&#xC774;&#xBC88; &#xD3EC;&#xC2A4;&#xD305;&#xC758; &#xC8FC;&#xC81C;&#xB294; Local Rate Limit &#xCABD;&#xC774;&#xBBC0;&#xB85C; Global &#xAD00;&#xB828;&#xB41C;&#xAC74; &#xB2E4;&#xC74C;&#xC5D0; &#xC2DC;&#xAC04;&#xC774; &#xB098;&#xBA74; &#xBCC4;&#xB3C4;&#xC758; &#xD3EC;&#xC2A4;&#xD305;&#xC73C;&#xB85C; &#xB2E4;&#xB904; &#xBCFC; &#xC0DD;&#xAC01;&#xC774;&#xB2E4;. </p><h2 id="local-rate-limit">Local Rate Limit</h2><p>Envoy &#xC790;&#xCCB4;&#xC801;&#xC73C;&#xB85C; &#xD2B8;&#xB798;&#xD53D; &#xC694;&#xCCAD;(L4, HTTP)&#xC758; Local Rate Limit&#xC744; &#xC9C0;&#xC6D0;&#xB2E4;. &#xC774;&#xB97C; &#xD1B5;&#xD574; &#xB2E4;&#xB978; &#xC678;&#xBD80; &#xC11C;&#xBE44;&#xC2A4;&#xB97C; &#xD638;&#xCD9C;&#xD558;&#xC9C0; &#xC54A;&#xACE0;&#xB3C4; &#xD504;&#xB85D;&#xC2DC; &#xC790;&#xCCB4; &#xC778;&#xC2A4;&#xD134;&#xC2A4; &#xC218;&#xC900;&#xC5D0;&#xC11C; Rate Limit&#xC744; &#xC801;&#xC6A9;&#xD560; &#xC218; &#xC788;&#xB2E4;. </p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.hkwon.me/content/images/2024/08/image-16.png" class="kg-image" alt="Istio &#xB97C; &#xD1B5;&#xD55C; path(url) &#xAE30;&#xBC18; Local Rate Limit &#xC801;&#xC6A9;" loading="lazy" width="1792" height="1364" srcset="https://blog.hkwon.me/content/images/size/w600/2024/08/image-16.png 600w, https://blog.hkwon.me/content/images/size/w1000/2024/08/image-16.png 1000w, https://blog.hkwon.me/content/images/size/w1600/2024/08/image-16.png 1600w, https://blog.hkwon.me/content/images/2024/08/image-16.png 1792w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">&#xCD9C;&#xCC98;: &#xAD8C;&#xD601; &#xBE14;&#xB85C;&#xADF8;</span></figcaption></figure><p>&#xB0B4;&#xAC00; Local&#xB85C; &#xC120;&#xD0DD;&#xD55C; &#xC774;&#xC720;&#xB3C4; Redis &#xB4F1;&#xC758; &#xBCC4;&#xB3C4;&#xC758; &#xBC31;&#xC5D4;&#xB4DC; &#xB370;&#xC774;&#xD130;&#xBCA0;&#xC774;&#xC2A4;&#xB97C; &#xAD6C;&#xC131;&#xD558;&#xACE0; &#xB530;&#xB85C; &#xC6B4;&#xC601;&#xD574;&#xC57C;&#xD558;&#xB294; &#xBD80;&#xB2F4;&#xC774; &#xC788;&#xC5B4;&#xC11C; Istio/Envoy &#xB9CC;&#xC73C;&#xB85C; &#xAD6C;&#xC131;&#xD560; &#xC218; &#xC788;&#xAE30;&#xB97C; &#xC120;&#xD638;&#xD574;&#xC11C; &#xB098;&#xB294; Local &#xBC29;&#xC2DD;&#xC744; &#xC120;&#xD0DD;&#xD588;&#xC9C0;&#xB9CC; &#xC5B4;&#xB5BB;&#xAC8C; &#xAD6C;&#xC131;&#xD558;&#xC5EC; &#xC6B4;&#xC601;&#xD560; &#xC9C0;&#xB294; &#xC8FC;&#xC5B4;&#xC9C4; &#xD658;&#xACBD;&#xC5D0; &#xB530;&#xB77C; &#xC120;&#xD0DD;&#xD558;&#xBA74; &#xB420; &#xAC83; &#xAC19;&#xB2E4;. </p><p>&#xAD6C;&#xC131;&#xC744; &#xC704;&#xD55C; &#xC0AC;&#xC804; &#xC815;&#xBCF4;&#xB294; &#xC0B4;&#xD3B4;&#xBD24;&#xC73C;&#xBBC0;&#xB85C; &#xC774;&#xC81C; &#xBCF8;&#xACA9;&#xC801;&#xC73C;&#xB85C; Local Rate Limit&#xC744; &#xC124;&#xC815;&#xD574; &#xBCF4;&#xC790;.</p><h2 id="all-you-need-is-envoyfilter">All you need is &quot;EnvoyFilter&quot;</h2><p>&#xC0AC;&#xC2E4; &#xC124;&#xC815;&#xD560; &#xAC83;&#xC740; &#xB9CE;&#xC9C0; &#xC54A;&#xB2E4;. <code>Envoy Filter</code> &#xB97C; &#xC801;&#xC815;&#xD55C; &#xD3EC;&#xB9F7;&#xC73C;&#xB85C; &#xC791;&#xC131;&#xD558;&#xBA74; &#xB41C;&#xB2E4;. &#xADFC;&#xB370; &#xC774; &#xC608;&#xC81C;&#xAC00; &#xC815;&#xB9D0; &#xAC70;&#xC9C0; &#xAC19;&#xB2E4;. &#xACF5;&#xC2DD; &#xBB38;&#xC11C; &#xC0D8;&#xD50C;&#xB3C4; &#xC815;&#xB9D0; &#xC815;&#xB9D0; &#xAC70;&#xC9C0; &#xAC19;&#xB2E4;. &#xB3C4;&#xC800;&#xD788; &#xADF8;&#xAC83;&#xB9CC; &#xBCF4;&#xACE0;&#xB294; &#xB530;&#xB77C; &#xB9CC;&#xB4E4; &#xC218; &#xC5C6;&#xC744; &#xC815;&#xB3C4;&#xB85C; &#xAC70;&#xC9C0; &#xAC19;&#xB2E4;. </p><p>&#xADF8;&#xB798;&#xB3C4; &#xBB50; &#xCC28;&#xADFC;&#xCC28;&#xADFC; &#xC77C;&#xB2E8; &#xC804;&#xCCB4; &#xC11C;&#xBE44;&#xC2A4;&#xB97C; &#xAC78;&#xB824;&#xBA74; &#xACF5;&#xC2DD; &#xBB38;&#xC11C;&#xC5D0; &#xB098;&#xC640; &#xC788;&#xB294; &#xAC83;&#xCC98;&#xB7FC; <code>HTTP_FILTER</code> &#xC804;&#xC5D0; <code>RATE_LIMIT</code> &#xD544;&#xD130;&#xB97C; &#xCD94;&#xAC00;&#xD574;&#xC57C; &#xD55C;&#xB2E4;. </p><pre><code class="language-yaml">$ kubectl apply -f - &lt;&lt;EOF
apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
  name: filter-local-ratelimit-svc
  namespace: istio-system
spec:
  workloadSelector:
    labels:
      app: productpage
  configPatches:
    - applyTo: HTTP_FILTER
      match:
        context: SIDECAR_INBOUND
        listener:
          filterChain:
            filter:
              name: &quot;envoy.filters.network.http_connection_manager&quot;
      patch:
        operation: INSERT_BEFORE
        value:
          name: envoy.filters.http.local_ratelimit
          typed_config:
            &quot;@type&quot;: type.googleapis.com/udpa.type.v1.TypedStruct
            type_url: type.googleapis.com/envoy.extensions.filters.http.local_ratelimit.v3.LocalRateLimit
            value:
              stat_prefix: http_local_rate_limiter
              token_bucket:
                max_tokens: 4
                tokens_per_fill: 4
                fill_interval: 60s
              filter_enabled:
                runtime_key: local_rate_limit_enabled
                default_value:
                  numerator: 100
                  denominator: HUNDRED
              filter_enforced:
                runtime_key: local_rate_limit_enforced
                default_value:
                  numerator: 100
                  denominator: HUNDRED
              response_headers_to_add:
                - append: false
                  header:
                    key: x-local-rate-limit
                    value: &apos;true&apos;
EOF</code></pre><p>&#xC5EC;&#xAE30;&#xC11C; &#xC911;&#xC694;&#xD558;&#xAC8C; &#xBD10;&#xC57C;&#xD560; &#xC124;&#xC815; &#xAC12;&#xC740; &#xC544;&#xB798;&#xC640; &#xAC19;&#xB2E4;. </p><ul><li><code>stat_prefix</code><ul><li><code>promethus</code> &#xB97C; &#xD1B5;&#xD574;&#xC11C; &#xAD00;&#xB828;&#xB41C; &#xBA54;&#xD2B8;&#xB9AD;&#xC744; &#xC218;&#xC9D1;&#xD560; &#xC218; &#xC788;&#xB294;&#xB370; &#xADF8;&#xB54C; &#xC0AC;&#xC6A9;&#xB418;&#xB294; prefix &#xC815;&#xBCF4;&#xB2E4;. </li></ul></li><li><code>token_bucket</code><ul><li>&#xC774; &#xC608;&#xC81C;&#xB294; <strong>1&#xBD84;&#xC5D0; &#xCD1D; 4&#xAC1C;&#xC758; &#xC694;&#xCCAD;</strong>&#xB9CC; &#xBC1B;&#xACE0; &#xB098;&#xBA38;&#xC9C0;&#xB294; &#xC81C;&#xD55C; &#xD558;&#xB294; &#xC124;&#xC815;&#xC73C;&#xB85C;</li><li><code>max_tokens: 4</code> &#xB294; &#xBC84;&#xD0B7;&#xC5D0; &#xB2F4;&#xC744; &#xC218; &#xC788;&#xB294; &#xCD5C;&#xB300; &#xD1A0;&#xD070; &#xC218;&#xC774;&#xACE0;, &#xBC84;&#xD0B7;&#xC5D0; &#xCD08;&#xAE30; &#xC124;&#xC815;&#xC5D0; &#xD3EC;&#xD568;&#xB418;&#xB294; &#xD1A0;&#xD070;&#xC758; &#xC218;&#xC774;&#xAE30;&#xB3C4; &#xD558;&#xB2E4;.</li><li><code>tokens_per_fill: 4</code> &#xB294; &#xAC01; &#xD1A0;&#xD070; &#xCC44;&#xC6C0; &#xAC04;&#xACA9; &#xB3D9;&#xC548; &#xBC84;&#xD0B7;&#xC5D0; &#xCD94;&#xAC00;&#xB418;&#xB294; &#xD1A0;&#xD070; &#xC218;&#xB2E4;. &#xC9C0;&#xC815;&#xD558;&#xC9C0; &#xC54A;&#xC73C;&#xBA74; &#xAE30;&#xBCF8;&#xAC12;&#xC740; <code>max_tokens</code> &#xAC12;&#xC774;&#xB2E4;.</li><li><code>fill_interval: 60s</code> &#xB294; &#xD1A0;&#xD070;&#xC774; &#xBC84;&#xD0B7;&#xC5D0; &#xCD94;&#xAC00;&#xB418;&#xB294; &#xCC44;&#xC6C0; &#xAC04;&#xACA9;&#xC774;&#xB2E4;. &#xAC01; &#xCC44;&#xC6C0; &#xAC04;&#xACA9; &#xB3D9;&#xC548; &#xBC84;&#xD0B7;&#xC5D0; &#xD1A0;&#xD070;&#xC774; &#xCD94;&#xAC00;&#xB420; &#xB54C;&#xB9C8;&#xB2E4; <code>tokens_per_fill</code> &#xAC1C;&#xC218;&#xAC00; &#xCD94;&#xAC00;&#xB41C;&#xB2E4;. &#xC774; &#xACBD;&#xC6B0; 1&#xBD84;&#xC774; &#xC9C0;&#xB098;&#xBA74; 4&#xAC1C;&#xC758; &#xD1A0;&#xD070;&#xC774; &#xB2E4;&#xC2DC; &#xCC44;&#xC6CC;&#xC9C0;&#xB294; &#xACBD;&#xC6B0;&#xC774;&#xB2E4;. &#xBC84;&#xD0B7;&#xC5D0;&#xB294; &#xCD5C;&#xB300; &#xD1A0;&#xD070; &#xC218;&#xBCF4;&#xB2E4; &#xB9CE;&#xC740; &#xD1A0;&#xD070;&#xC774; &#xD3EC;&#xD568;&#xB418;&#xC9C0; &#xC54A;&#xB294;&#xB2E4;. &#xC608;&#xB97C; &#xB4E4;&#xC5B4; &#xAE30;&#xAC04; &#xB3D9;&#xC548; 2&#xAC1C;&#xAC00; &#xB0A8;&#xC558;&#xB2E4;&#xACE0; &#xD574;&#xC11C; 2+4&#xAC00; &#xC544;&#xB2C8;&#xB77C; 4&#xAC1C;&#xAC00; &#xB2E4;&#xC2DC; &#xC9C0;&#xC815;&#xB418;&#xB294; &#xBC29;&#xC2DD;&#xC774;&#xB2E4;.</li></ul></li></ul><p>&#xC774;&#xC81C; &#xD2B9;&#xC815;&#xD55C; &#xD3EC;&#xD2B8;&#xB77C;&#xB358;&#xAC00; path &#xC124;&#xC815;&#xC744; &#xCD94;&#xAC00;&#xD558;&#xB824;&#xBA74; <code>HTTP_ROUTE</code> &#xACFC; &#xD568;&#xAED8; &#xC124;&#xC815;&#xC744; &#xD574;&#xC57C; &#xD55C;&#xB2E4;. &#xC544;&#xB798; &#xC608;&#xC81C;&#xB294; &#xACF5;&#xC2DD;&#xBB38;&#xC11C;&#xC5D0; &#xB098;&#xC640;&#xC788;&#xB294; <code>9080</code> &#xC73C;&#xB85C; &#xB4E4;&#xC5B4;&#xC624;&#xB294; &#xBAA8;&#xB4E0; &#xC694;&#xCCAD;&#xC5D0; &#xB300;&#xD574;&#xC11C; Rate Limit&#xC744; &#xAC70;&#xB294; &#xC608;&#xC81C;&#xC774;&#xB2E4;.</p><pre><code class="language-yaml">metadata:
  name: filter-local-ratelimit-svc
  namespace: istio-system
spec:
  workloadSelector:
    labels:
      app: productpage
  configPatches:
    - applyTo: HTTP_FILTER
      match:
        context: SIDECAR_INBOUND
        listener:
          filterChain:
            filter:
              name: &quot;envoy.filters.network.http_connection_manager&quot;
      patch:
        operation: INSERT_BEFORE
        value:
          name: envoy.filters.http.local_ratelimit
          typed_config:
            &quot;@type&quot;: type.googleapis.com/udpa.type.v1.TypedStruct
            type_url: type.googleapis.com/envoy.extensions.filters.http.local_ratelimit.v3.LocalRateLimit
            value:
              stat_prefix: http_local_rate_limiter
    - applyTo: HTTP_ROUTE
      match:
        context: SIDECAR_INBOUND
        routeConfiguration:
          vhost:
            name: &quot;inbound|http|9080&quot;
            route:
              action: ANY
      patch:
        operation: MERGE
        value:
          typed_per_filter_config:
            envoy.filters.http.local_ratelimit:
              &quot;@type&quot;: type.googleapis.com/udpa.type.v1.TypedStruct
              type_url: type.googleapis.com/envoy.extensions.filters.http.local_ratelimit.v3.LocalRateLimit
              value:
                stat_prefix: http_local_rate_limiter
                token_bucket:
                  max_tokens: 4
                  tokens_per_fill: 4
                  fill_interval: 60s
                filter_enabled:
                  runtime_key: local_rate_limit_enabled
                  default_value:
                    numerator: 100
                    denominator: HUNDRED
                filter_enforced:
                  runtime_key: local_rate_limit_enforced
                  default_value:
                    numerator: 100
                    denominator: HUNDRED
                response_headers_to_add:
                  - append: false
                    header:
                      key: x-local-rate-limit
                      value: &apos;true&apos;
EOF</code></pre><p>&#xC774;&#xC81C; &#xC774;&#xB807;&#xAC8C; &#xC124;&#xC815;&#xD558;&#xBA74; <code>9080</code>&#xC73C;&#xB85C; &#xB4E4;&#xC5B4;&#xC624;&#xB294; &#xBAA8;&#xB4E0; &#xC694;&#xCCAD;&#xC5D0; &#xB300;&#xD574;&#xC11C; limit&#xC774; &#xAC78;&#xB9AC;&#xAC8C; &#xB41C;&#xB2E4;.</p><p>&#xC0AC;&#xC2E4; path &#xAE30;&#xC900;&#xC73C;&#xB85C; limit&#xC744; &#xC124;&#xC815;&#xD558;&#xB824;&#xACE0; &#xD588;&#xB358; &#xC774;&#xC720;&#xB294; &#xC11C;&#xBE44;&#xC2A4;&#xC758; health check url&#xC740; 15&#xCD08;&#xC5D0; &#xD55C;&#xBC88; <code>probe</code>&#xB97C; &#xCCB4;&#xD06C;&#xD558;&#xB294;&#xB370; &#xACC4;&#xC18D; &#xC0AC;&#xC6A9;&#xB418;&#xB294;&#xB370; &#xC774;&#xAC8C; &#xACC4;&#xC18D; token &#xAC2F;&#xC218;&#xC5D0; &#xC7A1;&#xD788;&#xB2E4; &#xBCF4;&#xB2C8; &#xD2B9;&#xC815; &#xC778;&#xC2A4;&#xD134;&#xC2A4;&#xC5D0;&#xC11C; &#xD574;&#xB2F9; url&#xC744; &#xC81C;&#xC678;&#xD558;&#xACE0; &#xB0B4;&#xAC00; &#xC6D0;&#xD558;&#xB294; url&#xB9CC;  &#xAC78;&#xACE0; &#xC2F6;&#xC5B4;&#xC11C; &#xCC3E;&#xAE30; &#xC2DC;&#xC791;&#xD588;&#xB358; &#xC124;&#xC815;&#xC774;&#xC5C8;&#xB2E4;. </p><p>&#xADFC;&#xB370; &#xB098;&#xBA38;&#xC9C0; &#xC124;&#xC815;&#xC744; &#xC5B4;&#xB5A4;&#xC2DD;&#xC73C;&#xB85C; MERGE, INSERT &#xD574;&#xC57C;&#xD558;&#xB294;&#xC9C0; &#xCE5C;&#xC808;&#xD558;&#xAC8C; &#xC124;&#xBA85;&#xB41C; &#xBB38;&#xC11C;&#xB294; &#xAC70;&#xC758; &#xC804;&#xBB34; &#xD588;&#xACE0; Envoy &#xBB38;&#xC11C;&#xB97C; &#xC704;&#xC8FC;&#xB85C; &#xD574;&#xB2F9; &#xC815;&#xBCF4;&#xB97C; &#xCC3E;&#xC558;&#xB2E4;. </p><p>&#xC77C;&#xB2E8; Envoy Filter&#xB97C; &#xC124;&#xC815;&#xD558;&#xB294; &#xBC29;&#xBC95;&#xC740; &#xC544;&#xB798;&#xC5D0; &#xB098;&#xC640; &#xC788;&#xAE34; &#xD558;&#xB2E4;. &#xADFC;&#xB370; &#xD070; &#xB3C4;&#xC6C0;&#xC740; &#xB418;&#xC9C0; &#xC54A;&#xB294;&#xB2E4;.</p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://istio.io/latest/docs/reference/config/networking/envoy-filter/?ref=blog.hkwon.me"><div class="kg-bookmark-content"><div class="kg-bookmark-title">Envoy Filter</div><div class="kg-bookmark-description">Customizing Envoy configuration generated by Istio.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://istio.io/latest/favicons/apple-touch-icon-180x180.png" alt="Istio &#xB97C; &#xD1B5;&#xD55C; path(url) &#xAE30;&#xBC18; Local Rate Limit &#xC801;&#xC6A9;"><span class="kg-bookmark-author">Istio</span><span class="kg-bookmark-publisher">18 minute read</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://raw.githubusercontent.com/istio/istio.io/master/static/img/istio-social.png" alt="Istio &#xB97C; &#xD1B5;&#xD55C; path(url) &#xAE30;&#xBC18; Local Rate Limit &#xC801;&#xC6A9;"></div></a></figure><p>&#xC5EC;&#xAE30;&#xC11C; <code>HTTP_ROUTE</code> &#xC124;&#xC815;&#xC5D0; &#xBA87;&#xAC00; &#xC124;&#xC815;&#xB9CC; &#xCD94;&#xAC00;&#xD558;&#xBA74; &#xB418;&#xB294;&#xAC83;&#xC774;&#xC5C8;&#xB294;&#xB370; &#xC0AC;&#xC2E4; &#xCC3E;&#xAE30; &#xC27D;&#xC9C4; &#xC54A;&#xC558;&#xB2E4;. &#xBD80;&#xB514; &#xB2E4;&#xB978; &#xBD84;&#xB4E4;&#xC740; &#xD574;&#xB2F9;&#xC815;&#xBCF4;&#xB97C; &#xCC3E;&#xC544; &#xD5E4;&#xB9E4;&#xB294; &#xC2DC;&#xAC04;&#xC774; &#xB9CE;&#xC774; &#xC904;&#xAE38; &#xBC14;&#xB77C;&#xBA70;..</p><p>&#xC8FC;&#xC694;&#xD55C; &#xC124;&#xC815;&#xC740; <code>HTTP_ROUTE</code> &#xC758; <code>route</code> &#xC124;&#xC815;&#xC5D0; &#xB2E4;&#xC74C;&#xACFC; &#xAC19;&#xC740; &#xC561;&#xC158;&#xC744; &#xC544;&#xB798;&#xC640; &#xAC19;&#xC774; &#xCD94;&#xAC00;&#xD558;&#xACE0; </p><pre><code class="language-yaml">route:
  rate_limits:
    - actions:
      - header_value_match:
          descriptor_value: &quot;infer&quot;
          expect_match: true
          headers:
            - name: :path
              string_match:
                safe_regex:
                  google_re2: {}
                  regex: &quot;^/v2/models/[a-zA-Z0-9-_]+/versions/[0-9]+/infer&quot;</code></pre><p>&#xC774; &#xC608;&#xC81C;&#xB294; &#xC815;&#xADDC;&#xD45C;&#xD604;&#xC2DD;&#xC73C;&#xB85C; &#xD2B9;&#xC815; URL&#xB9CC; descriptor&#xB85C; &#xBD84;&#xB958; &#xD574;&#xC11C; header&#xC5D0; <code>infer</code> &#xB77C;&#xB294; &#xAC12;&#xC744; &#xB123;&#xAE30; &#xC704;&#xD568;&#xC774;&#xB2E4;.</p><p>&#xADF8;&#xB9AC;&#xACE0; <code>HTTP_ROUTE</code> &#xC758; <code>local_ratelimit</code> &#xC124;&#xC815;&#xC5D0; &#xD574;&#xB2F9; descriptor &#xC124;&#xC815;&#xC744; &#xCD94;&#xAC00;&#xD558;&#xBA74; &#xB41C;&#xB2E4;!</p><pre><code>envoy.filters.http.local_ratelimit:
  &apos;@type&apos;: type.googleapis.com/envoy.extensions.filters.http.local_ratelimit.v3.LocalRateLimit
  stat_prefix: [[${param.statPrefix}]]
  token_bucket:
    max_tokens: 2147483647
    tokens_per_fill: 2147483647
    fill_interval: 60s
  filter_enabled:
    runtime_key: test_enabled
    default_value:
      numerator: 100
      denominator: HUNDRED
  filter_enforced:
    runtime_key: test_enabled
    default_value:
      numerator: 100
      denominator: HUNDRED
  response_headers_to_add:
    - append: false
      header:
        key: x-local-rate-limit
        value: &quot;true&quot;
  descriptors:
    - entries:
        - key: header_match
          value: infer
      token_bucket:
        max_tokens: [[${param.maxTokens}]]
        tokens_per_fill: [[${param.tokensPerFill}]]
        fill_interval: [[${param.fillInterval}]]</code></pre><p>&#xC5EC;&#xAE30;&#xC11C;&#xB294; &#xAE30;&#xBCF8;&#xC73C;&#xB85C; &#xC124;&#xC815;&#xB420; &#xAC12;&#xC744; &#xC9C0;&#xC815;&#xD558;&#xACE0; <code>descriptors</code> &#xC124;&#xC815;&#xC5D0; <code>header_match</code> &#xAC00; <code>infer</code> &#xC778; &#xACBD;&#xC6B0; &#xD2B9;&#xBCC4;&#xD55C; &#xC124;&#xC815;&#xC744; &#xD560; &#xC218; &#xC788;&#xAC8C; &#xC9C0;&#xC815;&#xD558;&#xBA74; &#xB41C;&#xB2E4;. </p><p>&#xC804;&#xCCB4; &#xC124;&#xC815;&#xC740; &#xC544;&#xB798;&#xC640; &#xAC19;&#xB2E4;.</p><pre><code>kind: EnvoyFilter
metadata:
  name: filter-local-ratelimit-svc
  namespace: istio-system
spec:
  workloadSelector:
    labels:
      app: productpage
  configPatches:
    - applyTo: HTTP_FILTER
      match:
        context: SIDECAR_INBOUND
        listener:
          filterChain:
            filter:
              name: envoy.filters.network.http_connection_manager
      patch:
        operation: INSERT_BEFORE
        value:
          name: envoy.filters.http.local_ratelimit
          typed_config:
            &apos;@type&apos;: type.googleapis.com/udpa.type.v1.TypedStruct
            type_url: type.googleapis.com/envoy.extensions.filters.http.local_ratelimit.v3.LocalRateLimit
            value:
              stat_prefix: [[${param.statPrefix}]]_all
    - applyTo: HTTP_ROUTE
      match:
        context: SIDECAR_INBOUND
        routeConfiguration:
          vhost:
            name: &quot;inbound|http|8000&quot;
            route:
              action: ANY
      patch:
        operation: MERGE
        value:
          route:
            rate_limits:
              - actions:
                  - header_value_match:
                      descriptor_value: &quot;infer&quot;
                      expect_match: true
                      headers:
                        - name: :path
                          string_match:
                            safe_regex:
                              google_re2: {}
                              regex: &quot;^/v2/models/[a-zA-Z0-9-_]+/versions/[0-9]+/infer&quot;
          typed_per_filter_config:
            envoy.filters.http.local_ratelimit:
              &apos;@type&apos;: type.googleapis.com/envoy.extensions.filters.http.local_ratelimit.v3.LocalRateLimit
              stat_prefix: [[${param.statPrefix}]]
              token_bucket:
                max_tokens: 2147483647
                tokens_per_fill: 2147483647
                fill_interval: 60s
              filter_enabled:
                runtime_key: test_enabled
                default_value:
                  numerator: 100
                  denominator: HUNDRED
              filter_enforced:
                runtime_key: test_enabled
                default_value:
                  numerator: 100
                  denominator: HUNDRED
              response_headers_to_add:
                - append: false
                  header:
                    key: x-local-rate-limit
                    value: &quot;true&quot;
              descriptors:
                - entries:
                    - key: header_match
                      value: infer
                  token_bucket:
                    max_tokens: [[${param.maxTokens}]]
                    tokens_per_fill: [[${param.tokensPerFill}]]
                    fill_interval: [[${param.fillInterval}]]</code></pre><p>&#xADF8;&#xB7EC;&#xBA74; &#xC774;&#xC81C; &#xB0B4;&#xAC00; &#xC6D0;&#xD558;&#xB294; &#xD2B9;&#xC815; API&#xB9CC; &#xC124;&#xC815;&#xC774; &#xAC00;&#xB2A5;&#xD558;&#xB2E4;. &#xB9CC;&#xC138;~!</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.hkwon.me/content/images/2024/08/image-19.png" class="kg-image" alt="Istio &#xB97C; &#xD1B5;&#xD55C; path(url) &#xAE30;&#xBC18; Local Rate Limit &#xC801;&#xC6A9;" loading="lazy" width="2000" height="723" srcset="https://blog.hkwon.me/content/images/size/w600/2024/08/image-19.png 600w, https://blog.hkwon.me/content/images/size/w1000/2024/08/image-19.png 1000w, https://blog.hkwon.me/content/images/size/w1600/2024/08/image-19.png 1600w, https://blog.hkwon.me/content/images/2024/08/image-19.png 2000w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">&#xADF8;&#xB798;&#xC11C; &#xACB0;&#xAD6D; &#xB9CC;&#xB4E4;&#xC5B4;&#xB0B8; &#xC11C;&#xBE44;&#xC2A4;&#xB0B4; &#xAD6C;&#xD604;</span></figcaption></figure><h2 id="%ED%94%84%EB%A1%9C%EB%A9%94%ED%85%8C%EC%9A%B0%EC%8A%A4%EB%A5%BC-%ED%86%B5%ED%95%9C-%EB%AA%A8%EB%8B%88%ED%84%B0%EB%A7%81">&#xD504;&#xB85C;&#xBA54;&#xD14C;&#xC6B0;&#xC2A4;&#xB97C; &#xD1B5;&#xD55C; &#xBAA8;&#xB2C8;&#xD130;&#xB9C1;</h2><p><code>stat_prefix</code> &#xC124;&#xBA85;&#xC744; &#xD1B5;&#xD574; &#xAC04;&#xB2E8;&#xD788; &#xC598;&#xAE30;&#xD588;&#xC9C0;&#xB9CC; Filter &#xAC78;&#xB9B0; &#xC694;&#xCCAD; &#xC815;&#xBCF4;&#xB294; &#xC544;&#xB798;&#xC640; &#xAC19;&#xC740; metric&#xC73C;&#xB85C; &#xC870;&#xD68C;&#xAC00; &#xAC00;&#xB2A5;&#xD558;&#xB2E4;.</p><p>&#xBAA8;&#xB4E0; &#xD1B5;&#xACC4;&#xAC12;&#xC740; Prometheus&#xC758; &#xACBD;&#xC6B0; Counter &#xD615;&#xC2DD;&#xC73C;&#xB85C; &#xC800;&#xC7A5;&#xB41C;&#xB2E4;.</p><table>
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>enabled</td>
<td>Counter</td>
<td>Limiter&#xAC00; &#xBC1B;&#xC544;&#xB0B8; &#xC804;&#xCCB4; &#xB9AC;&#xD018;&#xC2A4;&#xD2B8; &#xAC2F;&#xC218;</td>
</tr>
<tr>
<td>ok</td>
<td>Counter</td>
<td>token bucket&#xC774; &#xC815;&#xC0C1;&#xC801;&#xC73C;&#xB85C; &#xCC98;&#xB9AC;&#xD55C; &#xC804;&#xCCB4; &#xAC74;&#xC218;</td>
</tr>
<tr>
<td>rate_limited</td>
<td>Counter</td>
<td>&#xC774; &#xD1B5;&#xACC4;&#xB294; &#xD2B9;&#xC815; &#xC2DC;&#xAC04; &#xB3D9;&#xC548; Rate Limit&#xC5D0; &#xAC78;&#xB824; Envoy&#xAC00; &#xCC98;&#xB9AC;&#xD558;&#xC9C0; &#xC54A;&#xACE0; &#xCC28;&#xB2E8;&#xD55C; &#xC694;&#xCCAD;&#xC758; &#xC218;&#xB97C; &#xB098;&#xD0C0;&#xB0C4;</td>
</tr>
<tr>
<td>enforced</td>
<td>Counter</td>
<td>&#xC81C;&#xD55C;&#xC774; &#xAC78;&#xB9B0; &#xC804;&#xCCB4; &#xB9AC;&#xD018;&#xC2A4;&#xD2B8; &#xAC2F;&#xC218; (e.g.: 429 returned)</td>
</tr>
</tbody>
</table>
<figure class="kg-card kg-image-card"><img src="https://blog.hkwon.me/content/images/2024/08/image-20.png" class="kg-image" alt="Istio &#xB97C; &#xD1B5;&#xD55C; path(url) &#xAE30;&#xBC18; Local Rate Limit &#xC801;&#xC6A9;" loading="lazy" width="1768" height="1536" srcset="https://blog.hkwon.me/content/images/size/w600/2024/08/image-20.png 600w, https://blog.hkwon.me/content/images/size/w1000/2024/08/image-20.png 1000w, https://blog.hkwon.me/content/images/size/w1600/2024/08/image-20.png 1600w, https://blog.hkwon.me/content/images/2024/08/image-20.png 1768w" sizes="(min-width: 720px) 720px"></figure><p>&#xC774;&#xB807;&#xAC8C; <code>[stat_prefix]_http_local_rate_limit_ok</code> &#xC870;&#xD68C; &#xAC00;&#xB2A5;&#xD558;&#xB2E4;.</p><h1 id="summary">Summary</h1><p>&#xC9C0;&#xAE08;&#xAE4C;&#xC9C0; Istio Envoy Proxy&#xC758; Local Rate Limit &#xC124;&#xC815; &#xAE30;&#xB2A5; &#xC911;&#xC5D0; Path &#xAE30;&#xBC18;&#xC73C;&#xB85C; &#xC124;&#xC815;&#xD558;&#xB294; &#xBC29;&#xBC95;&#xC5D0; &#xB300;&#xD574; &#xC8FC;&#xC800;&#xB9AC; &#xC8FC;&#xC800;&#xB9AC; &#xC124;&#xBA85;&#xC744; &#xD574;&#xBCF4;&#xC558;&#xB2E4;.</p><p>&#xBD80;&#xB514; &#xAC19;&#xC740; &#xACE0;&#xBBFC;&#xC744; &#xD558;&#xB294; &#xBD84;&#xB4E4;&#xC758; &#xC0BD;&#xC9C8; &#xC2DC;&#xAC04;&#xC744; &#xB9CE;&#xC774; &#xC904;&#xC5EC; &#xC8FC;&#xAE38;~</p><p>&#xD3EC;&#xC2A4;&#xD305; &#xAE00;&#xACFC; &#xAD00;&#xB828;&#xD558;&#xC5EC; &#xC9C8;&#xBB38;&#xC774;&#xB098; &#xD53C;&#xB4DC;&#xBC31; &#xB4F1;&#xC740; &#xC790;&#xC720;&#xB86D;&#xAC8C; &#xB9C1;&#xD06C;&#xB4DC;&#xC778; &#xD504;&#xB85C;&#xD544;&#xC5D0; &#xC5F0;&#xB77D;&#xC8FC;&#xC138;&#xC694;~</p><p>LinkedIn <a href="https://www.linkedin.com/in/hkwon77?ref=blog.hkwon.me">https://www.linkedin.com/in/hkwon77</a></p><p></p><p></p>]]></content:encoded></item><item><title><![CDATA[Istio를 통한 header기반 API 라우팅/호출 시 cors preflight request 이슈 트러블슈팅 기록]]></title><description><![CDATA[<p>&#xD604;&#xC7AC; &#xAC1C;&#xBC1C;&#xD558;&#xACE0; &#xC788;&#xB294; &#xC77C;&#xBD80; &#xCEE8;&#xD14C;&#xC774;&#xB108; &#xAE30;&#xBC18;&#xC758; &#xC11C;&#xBE44;&#xC2A4;&#xB4E4;&#xC744; Istio&#xB97C; &#xD1B5;&#xD574; &#xC11C;&#xBE44;&#xC2A4;&#xB4E4;&#xC744; &#xAD6C;&#xC131;&#xD558;&#xACE0; &#xD2B8;&#xB798;&#xD53D;&#xC744; &#xAD00;&#xB9AC;&#xD558;&#xACE0; &#xC788;&#xB2E4;. </p><p>&#xC774;&#xB54C; &#xCEE8;&#xD14C;&#xC774;</p>]]></description><link>https://blog.hkwon.me/istio-custom-header/</link><guid isPermaLink="false">66bad8635a7d91000130749e</guid><category><![CDATA[삽질]]></category><category><![CDATA[istio]]></category><category><![CDATA[cors]]></category><category><![CDATA[preflight]]></category><dc:creator><![CDATA[Kevin H. Kwon]]></dc:creator><pubDate>Tue, 13 Aug 2024 07:15:40 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1477541915273-59a4b030923b?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDF8fHByZWZsaWdodHxlbnwwfHx8fDE3MjM1MjExMTd8MA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" medium="image"/><content:encoded><![CDATA[<img src="https://images.unsplash.com/photo-1477541915273-59a4b030923b?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDF8fHByZWZsaWdodHxlbnwwfHx8fDE3MjM1MjExMTd8MA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" alt="Istio&#xB97C; &#xD1B5;&#xD55C; header&#xAE30;&#xBC18; API &#xB77C;&#xC6B0;&#xD305;/&#xD638;&#xCD9C; &#xC2DC; cors preflight request &#xC774;&#xC288; &#xD2B8;&#xB7EC;&#xBE14;&#xC288;&#xD305; &#xAE30;&#xB85D;"><p>&#xD604;&#xC7AC; &#xAC1C;&#xBC1C;&#xD558;&#xACE0; &#xC788;&#xB294; &#xC77C;&#xBD80; &#xCEE8;&#xD14C;&#xC774;&#xB108; &#xAE30;&#xBC18;&#xC758; &#xC11C;&#xBE44;&#xC2A4;&#xB4E4;&#xC744; Istio&#xB97C; &#xD1B5;&#xD574; &#xC11C;&#xBE44;&#xC2A4;&#xB4E4;&#xC744; &#xAD6C;&#xC131;&#xD558;&#xACE0; &#xD2B8;&#xB798;&#xD53D;&#xC744; &#xAD00;&#xB9AC;&#xD558;&#xACE0; &#xC788;&#xB2E4;. </p><p>&#xC774;&#xB54C; &#xCEE8;&#xD14C;&#xC774;&#xB108; &#xC11C;&#xBE44;&#xC2A4;&#xAC00; &#xAC19;&#xC740; &#xADDC;&#xACA9;&#xC774; &#xC5EC;&#xB7EC;&#xAC1C;&#xAC00; &#xAC19;&#xC740; url&#xACFC; port&#xB97C; &#xD560;&#xB2F9; &#xBC1B;&#xC544;&#xC11C; &#xC0AC;&#xC6A9;&#xD574;&#xC57C;&#xB294; &#xC560;&#xB85C; &#xC0AC;&#xD56D;&#xC774; &#xC788;&#xC5B4; Istio&#xC5D0;&#xC11C; <code>header</code> &#xAE30;&#xBC18;&#xC73C;&#xB85C; &#xD2B9;&#xBCC4;&#xD55C; &#xD5E4;&#xB354;&#xAC00; &#xC788;&#xB294; &#xACBD;&#xC6B0;&#xC5D0;&#xB9CC; &#xB77C;&#xC6B0;&#xD305;&#xC774; &#xB420; &#xC218; &#xC788;&#xB3C4;&#xB85D; &#xAD6C;&#xC131;&#xD558;&#xACE0; &#xD14C;&#xC2A4;&#xD2B8;&#xB97C; &#xC9C4;&#xD589;&#xD588;&#xC5C8;&#xB2E4;.  </p><p><a href="https://istio.io/latest/docs/tasks/traffic-management/request-routing/?ref=blog.hkwon.me" rel="noreferrer">Istio Request Routing</a> &#xC608;&#xC81C;&#xC640; &#xAC19;&#xC774; <code>header</code> &#xC5D0; <code>model-api-key</code> &#xAC12;&#xC5D0; &#xB530;&#xB77C; &#xC815;&#xD655;&#xD558;&#xAC8C; &#xB9E4;&#xCE58;&#xB41C; &#xC694;&#xCCAD;&#xB9CC; &#xC9C0;&#xC815;&#xD55C; &#xC11C;&#xBE44;&#xC2A4;&#xB85C; &#xB77C;&#xC6B0;&#xD305; &#xB418;&#xB3C4;&#xB85D; &#xC124;&#xC815;&#xD558;&#xC600;&#xB2E4;.</p><pre><code class="language-yaml">apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  generation: 1
  labels:
    cheetah.xxx: xxx
  name: ...
  namespace: cheetah
spec:
  gateways:
  - model-deployment-gateway
  hosts:
  - &apos;*&apos;
  http:
  - match:
    - headers:
        model-api-key:
          exact: &quot;xyz&quot;
    route:
    - destination:
        host: model-deploy-01j46dj4ah5abd1zz8pc21vkg9
        port:
          number: 8000</code></pre><p><code>curl</code> &#xC774;&#xB098; &#xAE30;&#xD0C0; &#xB2E4;&#xB978; &#xB3C4;&#xAD6C;&#xB4E4;&#xB85C; &#xD14C;&#xC2A4;&#xD2B8; &#xC2DC;&#xC5D0;&#xB294; &#xD070; &#xBB38;&#xC81C;&#xAC00; &#xB418;&#xC9C4; &#xC54A;&#xC558;&#xB294;&#xB370;, &#xBE0C;&#xB77C;&#xC6B0;&#xC800;&#xC5D0;&#xC11C; &#xD574;&#xB2F9; API&#xB97C; &#xD638;&#xCD9C;&#xD574;&#xC11C; &#xBB54;&#xAC00; &#xBA54;&#xD0C0;&#xB370;&#xC774;&#xD130;&#xB97C; &#xC5BB;&#xC5B4;&#xC624;&#xB294; &#xACBD;&#xC6B0;&#xAC00; &#xC788;&#xC5C8;&#xB294;&#xB370;, &#xB2F9;&#xC5F0;&#xD558;&#xAC8C;&#xB3C4; &#xC11C;&#xBE44;&#xC2A4;&#xB418;&#xB294; &#xB3C4;&#xBA54;&#xC778;&#xC774; &#xAC19;&#xC9C0; &#xC54A;&#xACE0; IP &#xAE30;&#xBC18;&#xC73C;&#xB85C; &#xC11C;&#xBE44;&#xC2A4;&#xB97C; &#xD558;&#xB2E4;&#xBCF4;&#xB2C8; CORS(&#xAD50;&#xCC28; &#xCD9C;&#xCC98; &#xB9AC;&#xC18C;&#xC2A4; &#xACF5;&#xC720;) &#xC774;&#xC288;&#xAC00; &#xBC1C;&#xC0DD;&#xD588;&#xC5C8;&#xB2E4;. </p><p>&#xBE0C;&#xB77C;&#xC6B0;&#xC800;&#xC5D0;&#xC11C;&#xB294; CORS&#xB97C; &#xAC80;&#xC99D;&#xD558;&#xAE30; &#xC704;&#xD55C; pre-flight(&#xC0AC;&#xC804; &#xAC80;&#xC99D; &#xC694;&#xCCAD;) &#xC694;&#xCCAD;&#xC744; &#xD2B9;&#xBCC4;&#xD55C; &#xD5E4;&#xB354;(Options)&#xC640; &#xD568;&#xAED8; &#xB358;&#xC838;&#xC11C; &#xC720;&#xD6A8;&#xD55C; &#xC694;&#xCCAD;&#xC778;&#xC9C0; &#xAC80;&#xC99D; &#xBC1B;&#xACE0; &#xC2E4;&#xC81C; API&#xB97C; &#xC694;&#xCCAD;&#xD558;&#xB294;&#xB370; &#xC774; &#xACFC;&#xC815;&#xC5D0;&#xC11C; &#xC544;&#xB798;&#xC640; &#xAC19;&#xC774; &#xC624;&#xB958;&#xAC00; &#xBC1C;&#xC0DD;&#xD588;&#xB2E4;. </p><blockquote>Access to XMLHttpRequest at &#x2018;<a href="https://myapi.com/Form?ref=blog.hkwon.me" rel="noopener nofollow ugc">https://myapi.com/Form</a>&#x2019; from origin &#x2018;<a href="https://myui.net/?ref=blog.hkwon.me" rel="noopener nofollow ugc">https://myui.net</a>&#x2019; has been blocked by CORS policy: Response to preflight request doesn&#x2019;t pass access control check: Redirect is not allowed for a preflight request.</blockquote><p>CORS Preflight &#xC640; &#xAD00;&#xB828;&#xB41C; &#xC808;&#xCC28;&#xC640; &#xC790;&#xC138;&#xD55C; &#xB0B4;&#xC6A9;&#xC740; &#xC544;&#xB798;&#xC758; &#xBB38;&#xC11C;&#xB4E4;&#xC774; &#xC9C4;&#xC9DC; &#xC815;&#xB9AC;(&#xC9C4;&#xB9AC;&#xC758;MDN)&#xAC00; &#xC798;&#xB418;&#xC5B4; &#xC788;&#xB2E4;. &#xD55C;&#xBC88; &#xD6D1;&#xC5B4; &#xBCF4;&#xC2DC;&#xAE38; &#xAD8C;&#xC7A5;&#xD55C;&#xB2E4;. </p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://fetch.spec.whatwg.org/?ref=blog.hkwon.me#cors-preflight-fetch"><div class="kg-bookmark-content"><div class="kg-bookmark-title">Fetch Standard</div><div class="kg-bookmark-description"></div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://resources.whatwg.org/logo-fetch.svg" alt="Istio&#xB97C; &#xD1B5;&#xD55C; header&#xAE30;&#xBC18; API &#xB77C;&#xC6B0;&#xD305;/&#xD638;&#xCD9C; &#xC2DC; cors preflight request &#xC774;&#xC288; &#xD2B8;&#xB7EC;&#xBE14;&#xC288;&#xD305; &#xAE30;&#xB85D;"><span class="kg-bookmark-author">WHATWG</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://resources.whatwg.org/logo-fetch.svg" alt="Istio&#xB97C; &#xD1B5;&#xD55C; header&#xAE30;&#xBC18; API &#xB77C;&#xC6B0;&#xD305;/&#xD638;&#xCD9C; &#xC2DC; cors preflight request &#xC774;&#xC288; &#xD2B8;&#xB7EC;&#xBE14;&#xC288;&#xD305; &#xAE30;&#xB85D;"></div></a></figure><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS?ref=blog.hkwon.me#preflighted_requests"><div class="kg-bookmark-content"><div class="kg-bookmark-title">Cross-Origin Resource Sharing (CORS) - HTTP | MDN</div><div class="kg-bookmark-description">Cross-Origin Resource Sharing (CORS) is an HTTP-header based mechanism that allows a server to indicate any origins (domain, scheme, or port) other than its own from which a browser should permit loading resources. CORS also relies on a mechanism by which browsers make a &#x201C;preflight&#x201D; request to the server hosting the cross-origin resource, in order to check that the server will permit the actual request. In that preflight, the browser sends headers that indicate the HTTP method and headers that will be used in the actual request.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://developer.mozilla.org/favicon-48x48.cbbd161b.png" alt="Istio&#xB97C; &#xD1B5;&#xD55C; header&#xAE30;&#xBC18; API &#xB77C;&#xC6B0;&#xD305;/&#xD638;&#xCD9C; &#xC2DC; cors preflight request &#xC774;&#xC288; &#xD2B8;&#xB7EC;&#xBE14;&#xC288;&#xD305; &#xAE30;&#xB85D;"><span class="kg-bookmark-author">MDN Web Docs</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://developer.mozilla.org/mdn-social-share.cd6c4a5a.png" alt="Istio&#xB97C; &#xD1B5;&#xD55C; header&#xAE30;&#xBC18; API &#xB77C;&#xC6B0;&#xD305;/&#xD638;&#xCD9C; &#xC2DC; cors preflight request &#xC774;&#xC288; &#xD2B8;&#xB7EC;&#xBE14;&#xC288;&#xD305; &#xAE30;&#xB85D;"></div></a></figure><p>&#xC5B4;&#xCC0C;&#xB410;&#xB4E0; &#xC77C;&#xBC18;&#xC801;&#xC778; CORS &#xAD00;&#xB828;&#xB41C; &#xC124;&#xC815;&#xC774;&#xAC70;&#xB2C8; &#xD574;&#xC11C; &#xACF5;&#xC2DD; Istio &#xBB38;&#xC11C;&#xC5D0;&#xC11C; <a href="https://istio.io/latest/docs/reference/config/networking/virtual-service/?ref=blog.hkwon.me#CorsPolicy" rel="noreferrer">Cors Policy</a> &#xB97C; &#xBCF4;&#xACE0; &#xC544;&#xB798;&#xC640; &#xAC19;&#xC774; &#xC218;&#xC815;&#xD574;&#xC11C; &#xD14C;&#xC2A4;&#xD2B8;&#xB97C; &#xB2E4;&#xC2DC; &#xC9C4;&#xD589;&#xD588;&#xB2E4;. </p><pre><code class="language-yaml">apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  generation: 1
  labels:
    cheetah.xxx: xxx
  name: ...
  namespace: cheetah
spec:
  gateways:
  - model-deployment-gateway
  hosts:
  - &apos;*&apos;
  http:
  - corsPolicy:
      allowCredentials: true
      allowHeaders:
      - authorization
      - content-type
      - accept
      - origin
      - user-agent
      - model-api-key
      allowMethods:
      - POST
      - GET
      - PUT
      - DELETE
      - OPTIONS
      allowOrigins:
      - exact: &apos;*&apos;
      maxAge: 24h
    match:
    - headers:
        model-api-key:
          exact: &quot;xyz&quot;
    route:
    - destination:
        host: model-deploy-01j46dj4ah5abd1zz8pc21vkg9
        port:
          number: 8000</code></pre><p><code>corsPolicy</code>&#xC5D0; <code>allowHeader</code>&#xC640; <code>allowMethds</code>&#xC5D0; &#xD5C8;&#xC6A9;&#xD560; &#xAC12;&#xB4E4;&#xC744; &#xC704;&#xCC98;&#xB7FC; &#xC798; &#xC124;&#xC815;&#xD558;&#xACE0; &#xB2E4;&#xC2DC; &#xD14C;&#xC2A4;&#xD2B8; &#xD574;&#xBCF4;&#xB294;&#xB370; &#xC774;&#xBC88;&#xC5D4; &#xB72C;&#xAE08;&#xC5C6;&#xC774; 404 not found&#xAC00; &#xB098;&#xACE0; &#xC788;&#xB2E4;. </p><p>&#xB2E4;&#xC2DC; &#xD55C;&#xBC88; &#xC808;&#xCC28;&#xB370;&#xB85C; &#xC81C;&#xB300;&#xB85C; &#xB418;&#xACE0; &#xC788;&#xB294;&#xC9C0; &#xC774;&#xAC83;&#xC800;&#xAC83; &#xB85C;&#xADF8;&#xB97C; &#xD655;&#xC778;&#xD574; &#xBCF4;&#xC558;&#xB2E4;.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.hkwon.me/content/images/2024/08/image-1.png" class="kg-image" alt="Istio&#xB97C; &#xD1B5;&#xD55C; header&#xAE30;&#xBC18; API &#xB77C;&#xC6B0;&#xD305;/&#xD638;&#xCD9C; &#xC2DC; cors preflight request &#xC774;&#xC288; &#xD2B8;&#xB7EC;&#xBE14;&#xC288;&#xD305; &#xAE30;&#xB85D;" loading="lazy" width="1442" height="1334" srcset="https://blog.hkwon.me/content/images/size/w600/2024/08/image-1.png 600w, https://blog.hkwon.me/content/images/size/w1000/2024/08/image-1.png 1000w, https://blog.hkwon.me/content/images/2024/08/image-1.png 1442w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">MDN Pre-flight request</span></figcaption></figure><p>&#xC704; &#xADF8;&#xB9BC; &#xCC98;&#xB7FC; &#xAC00;&#xC7A5; &#xCCAB;&#xBC88;&#xC9F8; Preflight &#xC694;&#xCCAD;&#xC744; &#xB0A0;&#xB9AC;&#xB294; &#xC2DC;&#xC810;&#xC774; &#xBB38;&#xC81C;&#xC600;&#xB2E4;. &#xD574;&#xB2F9; &#xBD80;&#xBD84;&#xC740; <code>axios</code>&#xB098; <code>fetch</code> &#xAC19;&#xC740; &#xB77C;&#xC774;&#xBE0C;&#xB7EC;&#xB9AC;&#xB97C; &#xC0AC;&#xC6A9;&#xD558;&#xC5EC; &#xB0A0;&#xB9AC;&#xB294; &#xC694;&#xCCAD;&#xC774; &#xC544;&#xB2C8;&#xB77C; &#xBE0C;&#xB77C;&#xC6B0;&#xC800; &#xC5D0;&#xC11C; <code>CORS</code> &#xD655;&#xC778;&#xC744; &#xC704;&#xD574; &#xC900;&#xBE44;&#xB418;&#xB294; &#xC808;&#xCC28;&#xC778;&#xB370;, <strong>&#xD2B9;&#xBCC4;&#xD55C; &#xD5E4;&#xB354;</strong>&#xB97C; &#xC0AC;&#xC6A9;&#xD55C; &#xC694;&#xCCAD; &#xC989; <code>model-api-key</code>&#xB77C;&#xB294; &#xD5E4;&#xB354;&#xB97C; &#xD1B5;&#xD574; istio&#xB85C; &#xB77C;&#xC6B0;&#xD305; &#xD55C; &#xACBD;&#xC6B0;&#xAC00; &#xBB38;&#xC81C;&#xAC00; &#xB418;&#xACE0; &#xC788;&#xC5C8;&#xB2E4;. </p><p><strong><em>&#xBE0C;&#xB77C;&#xC6B0;&#xC800;&#xC5D0;&#xC11C; <code>Options</code> &#xBA54;&#xC18C;&#xB4DC;&#xB85C; Preflight &#xAC80;&#xC99D; &#xC694;&#xCCAD; &#xC2DC;&#xC5D0;&#xB294; custom header&#xB97C; &#xC9C0;&#xC6D0;&#xD558;&#xC9C0; &#xC54A;&#xB294; &#xAC83;&#xC774;&#xC5C8;&#xB2E4;. </em></strong></p><p>&#xB2F9;&#xC5F0;&#xD788; &#xCEE4;&#xC2A4;&#xD140; &#xD5E4;&#xB354;&#xAC00; &#xC5C6;&#xC5B4;&#xC11C; &#xB77C;&#xC6B0;&#xD305;&#xD560; &#xC11C;&#xBC84;&#xAC00; &#xC5C6;&#xAE30; &#xB54C;&#xBB38;&#xC5D0; 404 &#xC624;&#xB958;&#xAC00; &#xBC1C;&#xC0DD;&#xB418;&#xC5C8;&#xB2E4;. </p><p>Istio&#xC758; &#xC124;&#xC815;&#xC73C;&#xB85C; &#xBB54;&#xAC00; &#xAC00;&#xB2A5;&#xD558;&#xC9C0; &#xC54A;&#xC744;&#xAE4C; &#xC2F6;&#xC5C8;&#xC9C0;&#xB9CC; &#xACB0;&#xAD6D;&#xC5D4; &#xBC29;&#xBC95;&#xC744; &#xCC3E;&#xC9C4; &#xBABB;&#xD588;&#xACE0; &#xACB0;&#xAD6D;&#xC5D4; &#xAC19;&#xC740; url&#xC640; port&#xB85C; &#xB5A0; &#xC788;&#xB294; preflight &#xAC80;&#xC99D;&#xC6A9; dummy &#xC11C;&#xBC84;&#xB97C; &#xB9CC;&#xB4E4;&#xC5B4;&#xC11C; &#xB744;&#xC6CC;&#xB450;&#xACE0; preflight &#xAC80;&#xC99D; &#xC2DC;&#xC5D0;&#xB294; dummy &#xC11C;&#xBC84;&#xB85C; &#xC694;&#xCCAD;&#xD558;&#xACE0; &#xC2E4; &#xC694;&#xCCAD;&#xC740; &#xD5E4;&#xB354;&#xB97C; &#xAE30;&#xBC18;&#xC73C;&#xB85C; &#xC694;&#xCCAD;&#xD558;&#xAC8C;&#xB054; &#xAE30;&#xB2A5;&#xC740; &#xBCC0;&#xACBD; &#xD558;&#xC600;&#xB2E4;. </p><h2 id="%EC%A0%95%EB%A6%AC">&#xC815;&#xB9AC;</h2><ul><li><code>CORS</code> &#xCC98;&#xB9AC; &#xC808;&#xCC28;&#xC5D0; &#xB300;&#xD574;&#xC11C; &#xC219;&#xC9C0; &#xD544;&#xC694;</li><li>Istio&#xC640; &#xC0C1;&#xAD00; &#xC5C6;&#xC774; &#xBE0C;&#xB77C;&#xC6B0;&#xC800;&#xC5D0;&#xC11C; Preflight &#xC694;&#xCCAD;&#xC5D0;&#xC11C;&#xB294; &#xC0AC;&#xC6A9;&#xC790; &#xC815;&#xC758; header&#xAC00; &#xD3EC;&#xD568;&#xB418;&#xC9C4; &#xC54A;&#xB294;&#xB2E4;. </li><li>Istio&#xAC00; &#xC544;&#xB2C8;&#xB354;&#xB77C;&#xB3C4; custom header&#xB97C; &#xBC18;&#xB4DC;&#xC2DC; &#xC0AC;&#xC6A9;&#xD574;&#xC57C; &#xD558;&#xB294; &#xACBD;&#xC6B0;&#xB77C;&#xBA74; dummy &#xC11C;&#xBE44;&#xC2A4;&#xB97C; &#xD558;&#xB098; &#xB744;&#xC6CC;&#xB450;&#xACE0; preflight&#xC640; &#xBCF8; &#xC694;&#xCCAD;&#xC744; &#xBD84;&#xB9AC;&#xD558;&#xC5EC; &#xC0AC;&#xC6A9;&#xD55C;&#xB2E4;.</li></ul>]]></content:encoded></item><item><title><![CDATA[Kubernetes cluster에 Feature gates 활성화 방법]]></title><description><![CDATA[<p>&#xCD5C;&#xADFC;&#xC5D0; nvidia a100 gpu&#xB97C; mig&#xB85C; &#xB098;&#xB220;&#xC11C; &#xC0AC;&#xC6A9; &#xD558;&#xB294;  &#xB178;&#xB4DC;&#xC5D0;&#xC11C; <code>cadvisor</code>&#xAC00; gpu metric&#xC744; &#xC218;&#xC9D1;&#xC744; &#xC798; &#xBABB;&#xD574;&#xC11C; <code>kubulet</code>&#xC5D0;&#xC11C; &#xACC4;&#xC18D; &#xC624;&#xB958;&#xAC00; &#xB5A8;&#xC5B4;&#xC838;&#xC11C; &#xD2B8;&#xB7EC;&#xBE14;&#xC288;&#xD305;&#xC744;</p>]]></description><link>https://blog.hkwon.me/kubernetes-cluster-feature-gates/</link><guid isPermaLink="false">66b1a7b306efdd000133fd9f</guid><category><![CDATA[k8s]]></category><category><![CDATA[featuregates]]></category><category><![CDATA[cadvisor]]></category><category><![CDATA[kubernetes]]></category><dc:creator><![CDATA[Kevin H. Kwon]]></dc:creator><pubDate>Tue, 18 Jan 2022 08:51:34 GMT</pubDate><media:content url="https://blog.hkwon.me/content/images/2024/08/doors-1767562_1920.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://blog.hkwon.me/content/images/2024/08/doors-1767562_1920.jpg" alt="Kubernetes cluster&#xC5D0; Feature gates &#xD65C;&#xC131;&#xD654; &#xBC29;&#xBC95;"><p>&#xCD5C;&#xADFC;&#xC5D0; nvidia a100 gpu&#xB97C; mig&#xB85C; &#xB098;&#xB220;&#xC11C; &#xC0AC;&#xC6A9; &#xD558;&#xB294;  &#xB178;&#xB4DC;&#xC5D0;&#xC11C; <code>cadvisor</code>&#xAC00; gpu metric&#xC744; &#xC218;&#xC9D1;&#xC744; &#xC798; &#xBABB;&#xD574;&#xC11C; <code>kubulet</code>&#xC5D0;&#xC11C; &#xACC4;&#xC18D; &#xC624;&#xB958;&#xAC00; &#xB5A8;&#xC5B4;&#xC838;&#xC11C; &#xD2B8;&#xB7EC;&#xBE14;&#xC288;&#xD305;&#xC744; &#xC9C4;&#xD589;&#xD588;&#xC5C8;&#xB2E4;.</p><p>dcgm-exporter&#xB85C; prometheus&#xB85C; metric&#xC744; &#xC218;&#xC9D1;&#xD558;&#xACE0; &#xC788;&#xC5B4;&#xC11C; &#xAD73;&#xC774; <code>cadvisor</code>&#xC5D0;&#xC11C; nvidia accelerator meric&#xC744; &#xC218;&#xC9D1;&#xD560; &#xC774;&#xC720;&#xAC00; &#xC5C6;&#xC5B4;&#xC838;&#xC11C; &#xC774;&#xAC83;&#xC800;&#xAC83; &#xC790;&#xB8CC;&#xB97C; &#xCC3E;&#xC544;&#xBCF4;&#xB2C8; 1.19 &#xBC84;&#xC804;&#xBD80;&#xD130;&#xB294; <code>DisableAcceleratorUsageMetrics</code> <code>feature gates</code>&#xB85C; &#xD574;&#xB2F9; &#xC218;&#xC9D1; &#xC635;&#xC158;&#xC744; &#xBE44;&#xD65C;&#xC131;&#xD654; &#xC2DC;&#xD0AC; &#xC218; &#xC788;&#xB294; &#xAC83;&#xC73C;&#xB85C; &#xBCF4;&#xC5EC;&#xC11C; &#xC801;&#xC6A9;&#xD588;&#xB2E4;.</p><p>&#xC801;&#xC6A9;&#xD558;&#xB294; &#xC911;&#xC5D0; &#xC0DD;&#xAC01;&#xBCF4;&#xB2E4; kubernetes cluster &#xC6B4;&#xC601; &#xC911;&#xC5D0; <code>feature gates</code>&#xB97C; &#xC218;&#xC815;&#xD560; &#xC77C;&#xC774; &#xB9CE;&#xC544;&#xC11C; &#xB9E4;&#xBC88; &#xAE4C;&#xBA39;&#xACE0;(&#xC65C; &#xB9E8;&#xB0A0; &#xD560;&#xB54C; &#xB9C8;&#xB2E4; &#xC0C8;&#xB86D;&#xC9C0;??) &#xCC3E;&#xAE30; &#xADC0;&#xCC2E;&#xC544;&#xC11C; &#xC815;&#xB9AC;&#xB97C; &#xD55C;&#xBC88; &#xD574;&#xBCF8;&#xB2E4;.</p><h1 id="feature-gates%EB%9E%80">Feature Gates&#xB780;</h1><p><code>Feature gates</code>&#xB294; kubernetes&#xC5D0;&#xC11C; &#xC81C;&#xACF5;&#xB418;&#xB294; &#xAE30;&#xB2A5; &#xC124;&#xC815;&#xC5D0; &#xB300;&#xD55C; &#xD0A4;-&#xAC12; &#xC138;&#xD2B8;&#xC774;&#xB2E4;. <code>-feature-gates</code> &#xCEE4;&#xB9E8;&#xB4DC; &#xB77C;&#xC778; &#xD50C;&#xB799;&#xC774;&#xB098; kubulet, api server &#xC124;&#xC815; &#xD30C;&#xC77C;&#xC744; &#xD1B5;&#xD574; Alpha, Beta Feature&#xC5D0; &#xB300;&#xD574;&#xC11C; &#xAE30;&#xB2A5;&#xC744; &#xD65C;&#xC131;/&#xBE44;&#xD65C;&#xC131; &#xC2DC;&#xD0AC; &#xC218; &#xC788;&#xB2E4;.</p><p>&#xC544;&#xB798;&#xC758; &#xBB38;&#xC11C;&#xC5D0;&#xC11C; &#xBC84;&#xC804; &#xBCC4;&#xB85C; &#xC124;&#xC815;&#xD560; &#xC218; &#xC788;&#xB294; feature&#xC5D0; &#xB300;&#xD574;&#xC11C; &#xD655;&#xC778; &#xD560; &#xC218; &#xC788;&#xB2E4;.</p><p><a href="https://kubernetes.io/docs/reference/command-line-tools-reference/feature-gates/?ref=blog.hkwon.me">https://kubernetes.io/docs/reference/command-line-tools-reference/feature-gates/</a></p><h2 id="1-kubelet%EC%97%90%EC%84%9C-feature-gate-%ED%99%9C%EC%84%B1%ED%99%94">1. Kubelet&#xC5D0;&#xC11C; Feature gate &#xD65C;&#xC131;&#xD654;</h2><p>&#xCCAB;&#xBC88;&#xC9F8;&#xB85C;&#xB294; &#xBAA8;&#xB4E0; &#xD074;&#xB7EC;&#xC2A4;&#xD130;&#xC5D0;&#xC11C; kubelet service&#xC758; feature gate&#xB97C; &#xD65C;&#xC131;&#xD654;&#xB97C; &#xC9C4;&#xD589;&#xD55C;&#xB2E4;.</p><p>systemd&#xB85C; kubelet&#xC774; &#xC124;&#xC815; &#xB418;&#xC5B4; &#xC788;&#xB2E4;&#xBA74; &#xD658;&#xACBD;&#xBCC0;&#xC218; &#xD30C;&#xC77C;&#xC744; &#xD655;&#xC778;&#xD55C;&#xB2E4;.</p><pre><code class="language-bash">hkwon@a100-cheetah-1:/etc/systemd/system/kubelet.service.d# cat 10-kubeadm.conf
# Note: This dropin only works with kubeadm and kubelet v1.11+
[Service]
Environment=&quot;KUBELET_KUBECONFIG_ARGS=--bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --kubeconfig=/etc/kubernetes/kubelet.conf&quot;
Environment=&quot;KUBELET_CONFIG_ARGS=--config=/var/lib/kubelet/config.yaml&quot;
# This is a file that &quot;kubeadm init&quot; and &quot;kubeadm join&quot; generates at runtime, populating the KUBELET_KUBEADM_ARGS variable dynamically
EnvironmentFile=-/var/lib/kubelet/kubeadm-flags.env
# This is a file that the user can use for overrides of the kubelet args as a last resort. Preferably, the user should use
# the .NodeRegistration.KubeletExtraArgs object in the configuration files instead. KUBELET_EXTRA_ARGS should be sourced from this file.
EnvironmentFile=-/etc/default/kubelet
ExecStart=
ExecStart=/usr/bin/kubelet $KUBELET_KUBECONFIG_ARGS $KUBELET_CONFIG_ARGS $KUBELET_KUBEADM_ARGS $KUBELET_EXTRA_ARGS --node-ip=183.111.96.75
</code></pre><p>EnvironmentFile&#xC740; user overrides &#xD558;&#xB294; &#xC124;&#xC815;&#xC740; <code>/etc/default/kubelet</code> &#xD30C;&#xC77C;&#xC744; &#xC0AC;&#xC6A9;&#xD558;&#xB77C;&#xACE0; &#xB418;&#xC5B4; &#xC788;&#xC73C;&#xB2C8;  &#xD574;&#xB2F9; &#xD30C;&#xC77C;&#xC744; &#xD3B8;&#xC9D1;&#xD558;&#xC5EC; <code>$KUBELET_EXTRA_ARGS</code> &#xBCC0;&#xC218;&#xB97C; &#xC124;&#xC815;&#xD55C;&#xB2E4;.</p><p>&#xB0B4;&#xAC00; &#xD65C;&#xC131;&#xD654;&#xD560; <code>feature gates</code>&#xB294; <code>DisableAcceleratorUsageMetrics</code> &#xC774;&#xBBC0;&#xB85C; &#xD574;&#xB2F9; feature&#xB97C; <code>true</code>&#xB85C; &#xC124;&#xC815;&#xD55C;&#xB2E4;.</p><pre><code class="language-bash">$ sudo vi /etc/default/kubelet
KUBELET_EXTRA_ARGS=--feature-gates=DisableAcceleratorUsageMetrics=true
</code></pre><p>&#xC0C8;&#xB85C; &#xC124;&#xC815;&#xD55C; &#xB0B4;&#xC6A9;&#xC744; &#xC801;&#xC6A9;&#xD558;&#xB824;&#xBA74; <code>kubelet</code> &#xC11C;&#xBE44;&#xC2A4;&#xB97C; &#xC7AC;&#xC2DC;&#xC791;&#xD574;&#xC57C; &#xD55C;&#xB2E4;. &#xB178;&#xB4DC;&#xAC00; ready status&#xB85C; &#xB2E4;&#xC2DC; &#xAC00;&#xAE30; &#xC704;&#xD574; 5&#xBD84; &#xC815;&#xB3C4;&#xB294; &#xAD6C;&#xB3D9;&#xC911;&#xC778; pod&#xC5D0;&#xB294; &#xC601;&#xD5A5;&#xC744; &#xBBF8;&#xCE58;&#xC9C0; &#xC54A;&#xC73C;&#xB2C8; &#xC124;&#xC815;&#xC5D0; &#xBCC4;(?) &#xC774;&#xC0C1;&#xC774; &#xC5C6;&#xB2E4;&#xBA74; &#xB178;&#xB4DC;&#xB4E4;&#xC758; <code>kubelet</code> &#xC744; &#xC7AC;&#xC2DC;&#xC791;&#xD55C;&#xB2E4;.</p><p>&#xBB3C;&#xB860; &#xC911;&#xC694;&#xD55C; &#xC2DC;&#xC2A4;&#xD15C;&#xC778; &#xACBD;&#xC6B0; node drain &#xD6C4;&#xC5D0; &#xC7AC;&#xC2DC;&#xC791;&#xC744; &#xAD8C;&#xACE0;&#xD55C;&#xB2E4;.</p><pre><code class="language-bash">$ sudo systemctl restart kubelet
</code></pre><p>&#xC124;&#xC815;&#xC774; &#xC131;&#xACF5;&#xC801;&#xC73C;&#xB85C; &#xC801;&#xC6A9; &#xB418;&#xC5C8;&#xB294;&#xC9C0; &#xD655;&#xC778; &#xD560; &#xC218; &#xC788;&#xB2E4;.</p><pre><code class="language-bash">$ ps aux | grep kubelet | grep feature-gates

$ journalctl --no-pager -u kubelet -x -e -f
</code></pre><h2 id="2-kube-api-server%EC%97%90%EC%84%9C-feature-gate-%ED%99%9C%EC%84%B1%ED%99%94">2. Kube api server&#xC5D0;&#xC11C; Feature gate &#xD65C;&#xC131;&#xD654;</h2><p>&#xC774;&#xC81C; kubenetes &#xCEF4;&#xD3EC;&#xB10C;&#xD2B8;(kube-apiserver, kube-controller-manager and kube-scheduler)&#xB4E4;&#xC5D0;&#xC11C; <code>feature gates</code>&#xB97C; &#xD65C;&#xC131;&#xD654; &#xD55C;&#xB2E4;.</p><h3 id="kube-component%EB%93%A4%EC%97%90-feature-gate-%EC%B6%94%EA%B0%80">kube component&#xB4E4;&#xC5D0; feature gate  &#xCD94;&#xAC00;</h3><p>&#xAE30;&#xBCF8;component&#xB4E4;&#xC758; manifets&#xB294; &#xC544;&#xB798;&#xC5D0; &#xC704;&#xCE58;&#xD558;&#xACE0; &#xD574;&#xB2F9; &#xC124;&#xC815;&#xC744; &#xCD94;&#xAC00;&#xD558;&#xC5EC; &#xC800;&#xC7A5;&#xD55C;&#xB2E4;.</p><pre><code class="language-bash">$ sudo vi cd /etc/kubernetes/manifests/kube-apiserver.yaml

...
spec:
  containers:
  - command:
    - kube-apiserver
    - --advertise-address=183.111.68.73
    ...
    - --feature-gates=VolumeSnapshotDataSource=true, DisableAcceleratorUsageMetrics=true
</code></pre><pre><code class="language-bash">$ sudo vi cd /etc/kubernetes/manifests/kube-controller-manager.yaml.yaml

...
spec:
  containers:
  - command:
    - kube-controller-manager
    ...
    - --feature-gates=VolumeSnapshotDataSource=true, DisableAcceleratorUsageMetrics=true
</code></pre><pre><code class="language-bash">$ sudo vi cd /etc/kubernetes/manifests/kube-scheduler.yaml

...
spec:
  containers:
  - command:
    - kube-scheduler
    ...
    - --feature-gates=RemoveSelfLink=false, VolumeSnapshotDataSource=true, DisableAcceleratorUsageMetrics=true
</code></pre><p>&#xD574;&#xB2F9; &#xD30C;&#xC77C;&#xB4E4;&#xC774; &#xC218;&#xC815;&#xB418;&#xBA74;  &#xC790;&#xB3D9;&#xC73C;&#xB85C; component pod&#xB4E4;&#xC740; &#xC7AC;&#xC2DC;&#xC791;&#xB41C;&#xB2E4;. &#xC544;&#xB798;&#xC640; &#xAC19;&#xC774; &#xC81C;&#xB300;&#xB85C; &#xC801;&#xC6A9; &#xB418;&#xC5C8;&#xB294;&#xC9C0; &#xD655;&#xC778;&#xD55C;&#xB2E4;.</p><pre><code class="language-bash">$ ps aux | grep apiserver | grep feature-gates
root      765532 13.4  4.0 1375592 641716 ?      Ssl  06:37   0:41 kube-apiserver --advertise-address=183.111.68.73 ... 
--feature-gates=VolumeSnapshotDataSource=true, DisableAcceleratorUsageMetrics=true
</code></pre><p>&#xC798; &#xC801;&#xC6A9; &#xB418;&#xC5C8;&#xB294;&#xC9C0; &#xB2E4;&#xC2DC; gpu node&#xC758; kubelet &#xB85C;&#xADF8;&#xB97C; &#xD655;&#xC778;&#xD574; &#xBCF8;&#xB2E4;.</p><h1 id="%EC%A0%95%EB%A6%AC">&#xC815;&#xB9AC;</h1><p><code>feature-gates</code>&#xB97C; &#xC801;&#xC6A9;&#xD558;&#xB294; &#xBD84;&#xB4E4;&#xC758; &#xC2DC;&#xAC04;&#xC744; &#xC904;&#xC77C; &#xC218; &#xC788;&#xAE30;&#xB97C;~!</p><p>&#xB354; &#xC88B;&#xC740; &#xBC29;&#xBC95;&#xC774; &#xC788;&#xB2E4;&#xBA74; &#xB313;&#xAE00; &#xACE0;&#xACE0;~!</p>]]></content:encoded></item><item><title><![CDATA[Mac에서 Docker Desktop clean uninstall 방법]]></title><description><![CDATA[<p>Mac&#xC5D0;&#xC11C; &#xAC11;&#xC790;&#xAE30; Docker desktop&#xC774; &#xBB34;&#xD55C; &#xB9AC;&#xC2A4;&#xD0C0;&#xD2B8;&#xAC00; &#xB418;&#xBA74;&#xC11C; &#xB9DB;&#xD0F1;&#xC774;&#xAC00; &#xAC00;&#xB294; &#xC0C1;&#xD669;&#xC774; &#xBC1C;&#xC0DD;&#xB410;&#xB2E4;. </p><p>&#xC880; &#xC624;&#xB798; &#xAC78;&#xB9AC;&#xB294; Docker build&#xB97C; &#xB3CC;&#xB824; &#xB193;&#xACE0; &#xD1F4;&#xADFC; &#xD588;&#xB294;&#xB370;</p>]]></description><link>https://blog.hkwon.me/macoseseo-docker-clean-uninstall-bangbeob/</link><guid isPermaLink="false">66b1a7b306efdd000133fd9d</guid><dc:creator><![CDATA[Kevin H. Kwon]]></dc:creator><pubDate>Tue, 09 Nov 2021 00:26:29 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1605745341112-85968b19335b?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDF8fGRvY2tlcnxlbnwwfHx8fDE2MzY0MTc2NDA&amp;ixlib=rb-1.2.1&amp;q=80&amp;w=2000" medium="image"/><content:encoded><![CDATA[<img src="https://images.unsplash.com/photo-1605745341112-85968b19335b?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDF8fGRvY2tlcnxlbnwwfHx8fDE2MzY0MTc2NDA&amp;ixlib=rb-1.2.1&amp;q=80&amp;w=2000" alt="Mac&#xC5D0;&#xC11C; Docker Desktop clean uninstall &#xBC29;&#xBC95;"><p>Mac&#xC5D0;&#xC11C; &#xAC11;&#xC790;&#xAE30; Docker desktop&#xC774; &#xBB34;&#xD55C; &#xB9AC;&#xC2A4;&#xD0C0;&#xD2B8;&#xAC00; &#xB418;&#xBA74;&#xC11C; &#xB9DB;&#xD0F1;&#xC774;&#xAC00; &#xAC00;&#xB294; &#xC0C1;&#xD669;&#xC774; &#xBC1C;&#xC0DD;&#xB410;&#xB2E4;. </p><p>&#xC880; &#xC624;&#xB798; &#xAC78;&#xB9AC;&#xB294; Docker build&#xB97C; &#xB3CC;&#xB824; &#xB193;&#xACE0; &#xD1F4;&#xADFC; &#xD588;&#xB294;&#xB370; Desktop&#xC774; &#xC804;&#xC6D0;&#xC774; &#xB098;&#xAC14;&#xB098; &#xC911;&#xAC04;&#xC5D0; &#xB9AC;&#xBD80;&#xD305; &#xB418;&#xBA74;&#xC11C; Docker desktop&#xC774; &#xC815;&#xC0C1; &#xB3D9;&#xC791;&#xB418;&#xC9C0; &#xC54A;&#xB294;&#xB2E4;..</p><p>&#xCD5C;&#xC2E0;&#xBC84;&#xC804; &#xBC1B;&#xC544;&#xC11C; &#xC7AC;&#xC124;&#xCE58;&#xB3C4; &#xD574;&#xBCF4;&#xACE0; &#xC5EC;&#xC804;&#xD788; &#xD574;&#xACB0;&#xC774; &#xC548;&#xB418;&#xC11C; &#xC2F9; &#xC9C0;&#xC6B0;&#xACE0; &#xB2E4;&#xC2DC; &#xC124;&#xCE58;&#xD558;&#xB2C8; &#xC815;&#xC0C1; &#xC791;&#xB3D9; &#xD55C;&#xB2E4;.</p><p>&#xC544;&#xB798;&#xB294; &#xBB38;&#xC81C; &#xD574;&#xACB0;&#xD574;&#xBCF4;&#xBA74;&#xC11C; &#xD588;&#xB358; &#xC77C;&#xB4E4; &#xC815;&#xB9AC;</p><p>Docker - Troubleshoot &#xBA54;&#xB274;&#xB97C; &#xD1B5;&#xD574; &#xD574;&#xACB0;&#xC744; &#xC2DC;&#xC791;&#xD574; &#xBCF8;&#xB2E4;.</p><figure class="kg-card kg-image-card"><img src="https://blog.hkwon.me/content/images/2024/08/1-1.png" class="kg-image" alt="Mac&#xC5D0;&#xC11C; Docker Desktop clean uninstall &#xBC29;&#xBC95;" loading="lazy" width="500" height="676"></figure><p>&#xBA3C;&#xC800; Clean/Purge data &#xB97C; &#xD1B5;&#xD574; data &#xCABD;&#xC5D0; &#xAF2C;&#xC778; &#xBD80;&#xBD84;&#xC774; &#xC788;&#xB2E4;&#xBA74; clean &#xD574;&#xC900;&#xB2E4;.</p><figure class="kg-card kg-image-card"><img src="https://blog.hkwon.me/content/images/2024/08/2-1.png" class="kg-image" alt="Mac&#xC5D0;&#xC11C; Docker Desktop clean uninstall &#xBC29;&#xBC95;" loading="lazy" width="1630" height="1192" srcset="https://blog.hkwon.me/content/images/size/w600/2024/08/2-1.png 600w, https://blog.hkwon.me/content/images/size/w1000/2024/08/2-1.png 1000w, https://blog.hkwon.me/content/images/size/w1600/2024/08/2-1.png 1600w, https://blog.hkwon.me/content/images/2024/08/2-1.png 1630w" sizes="(min-width: 720px) 720px"></figure><p>&#xC774;&#xAC78;&#xB85C; &#xD574;&#xACB0;&#xC774; &#xC548;&#xB41C;&#xB2E4;&#xBA74; &#xC544;&#xC608; Reset to factory defaults &#xB85C; &#xCD08;&#xAE30;&#xD654; &#xD574;&#xBCF8;&#xB2E4;.</p><p>&#xC774;&#xAC83;&#xB3C4; &#xD574;&#xACB0;&#xC774; &#xC548;&#xB41C;&#xB2E4;&#xBA74; Uninstall &#xD6C4;&#xC5D0; &#xC544;&#xB798;&#xC758; cache &#xBC0F; &#xB514;&#xB809;&#xD1A0;&#xB9AC;&#xB97C; &#xC2F9; &#xC815;&#xB9AC;&#xD574;&#xC900;&#xB2E4;.</p><ul><li>~/Library/Application Support/Docker Desktop</li><li>~/Library/Caches/com.docker.docker</li><li>~/Library/Cookies/com.docker.docker.binarycookies</li><li>~/Library/Group Containers/group.com.docker</li><li>~/Library/Logs/Docker Desktop</li><li>~/Library/Preferences/com.docker.docker.plist</li><li>~/Library/Preferences/com.electron.docker-frontend.plist</li><li>~/Library/Saved Application State/com.electron.docker-frontend.savedState</li><li>~/.docker</li></ul><p>&#xB098; &#xAC19;&#xC740; &#xACBD;&#xC6B0;&#xC5D0;&#xB294; &#xC544;&#xC608; clean &#xC73C;&#xB85C; &#xC2F9; &#xC9C0;&#xC6B0;&#xACE0; &#xC7AC;&#xC124;&#xCE58; &#xD558;&#xB2C8; &#xC815;&#xC0C1; &#xB3D9;&#xC791;~</p><p>Docker desktop&#xB3C4; &#xC774;&#xC81C; &#xBC18;&#xCBE4; &#xC720;&#xB8CC;&#xD654; &#xB418;&#xACE0;, mac&#xC5D0;&#xC11C; &#xBB54;&#xAC00; &#xC9C0;&#xC6D0;&#xC774; &#xC601; &#xC2DC;&#xC6D0;&#xCC2E;&#xC740; &#xB290;&#xB08C;, &#xB300;&#xCCB4;&#xC81C;&#xB97C; &#xC880; &#xC54C;&#xC544;&#xBD10;&#xC57C;&#xACA0;&#xB2E4;.</p>]]></content:encoded></item><item><title><![CDATA[Ubuntu 18.04 이상 Netplan을 사용한 Static IP 설정]]></title><description><![CDATA[<p>Ubuntu&#xB294; &#xD55C; 3&#xB144;&#xC804;&#xBD80;&#xD130;&#xC778;&#xAC00; CentOS&#xBCF4;&#xB2E8; &#xAC1C;&#xC778;&#xC801;&#xC73C;&#xB85C; &#xB354; &#xC8FC;&#xB825;&#xC73C;&#xB85C; &#xB9CE;&#xC774; &#xC0AC;&#xC6A9;&#xD588;&#xB358;&#xAC70; &#xAC19;&#xB2E4;.</p>
<p>16.04 LTS &#xB098;&#xC62C;&#xB54C;&#xBD80;&#xD130; &#xAFB8;&#xC900;&#xD788; &#xC4F0;&#xAE34; &#xD588;&#xC5C8;&#xB294;&#xB370; &#xC5B4;</p>]]></description><link>https://blog.hkwon.me/ubuntu-18-04-netplan/</link><guid isPermaLink="false">66b1a7b306efdd000133fd98</guid><category><![CDATA[ubuntu19.04]]></category><category><![CDATA[netplan]]></category><category><![CDATA[network]]></category><dc:creator><![CDATA[Kevin H. Kwon]]></dc:creator><pubDate>Mon, 28 May 2018 09:51:19 GMT</pubDate><media:content url="https://blog.hkwon.me/content/images/2024/08/lan-2815248_1280.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://blog.hkwon.me/content/images/2024/08/lan-2815248_1280.jpg" alt="Ubuntu 18.04 &#xC774;&#xC0C1; Netplan&#xC744; &#xC0AC;&#xC6A9;&#xD55C; Static IP &#xC124;&#xC815;"><p>Ubuntu&#xB294; &#xD55C; 3&#xB144;&#xC804;&#xBD80;&#xD130;&#xC778;&#xAC00; CentOS&#xBCF4;&#xB2E8; &#xAC1C;&#xC778;&#xC801;&#xC73C;&#xB85C; &#xB354; &#xC8FC;&#xB825;&#xC73C;&#xB85C; &#xB9CE;&#xC774; &#xC0AC;&#xC6A9;&#xD588;&#xB358;&#xAC70; &#xAC19;&#xB2E4;.</p>
<p>16.04 LTS &#xB098;&#xC62C;&#xB54C;&#xBD80;&#xD130; &#xAFB8;&#xC900;&#xD788; &#xC4F0;&#xAE34; &#xD588;&#xC5C8;&#xB294;&#xB370; &#xC5B4;&#xB290;&#xC0CC;&#xAC00; &#xBC8C;&#xC368; 18.04&#xAC00; LTS &#xBC84;&#xC804;&#xC73C;&#xB85C; &#xB098;&#xC654;&#xB2E4;.</p>
<p>16.04&#xB85C; &#xBC14;&#xAFD4;&#xC11C; &#xC4F8;&#xB54C;&#xB3C4; <code>systemctl</code> &#xB54C;&#xBB38;&#xC5D0; &#xD55C;&#xB3D9;&#xC548; &#xB9E4;&#xC6B0; &#xD798;&#xB4E4;&#xC5C8;&#xB294;&#xB370; 18.04 &#xC62C;&#xB77C;&#xAC00;&#xACE0; &#xBC8C;&#xC368;&#xBD80;&#xD130; &#xBC14;&#xB010; &#xAC83;&#xB4E4;&#xC774; &#xB108;&#xBB34; &#xB9CE;&#xB2E4;. &#xBB50; &#xC774;&#xB9AC; &#xBC30;&#xC6B8;&#xAC8C; &#xB9CE;&#xC544; &#x3160;&#x3160;</p>
<p>&#xC5B4;&#xCC0C;&#xB410;&#xB4E0; &#xB610; &#xC78A;&#xC5B4;&#xBC84;&#xB9AC;&#xAE30; &#xC804;&#xC5D0; &#xB2E4;&#xC74C;&#xC5D0; &#xD5E4;&#xB9E4;&#xC9C0; &#xC54A;&#xAC8C; &#xAE30;&#xC5B5;&#xD574;&#xBCF8;&#xB2E4;.</p>
<h2 id="static-ip-%EC%84%A4%EC%A0%95">Static IP &#xC124;&#xC815;</h2>
<p>&#xCCAB;&#xBC88;&#xC9F8; &#xB09C;&#xAD00;&#xC740; &#xB124;&#xD2B8;&#xC6CC;&#xD06C; &#xC778;&#xD130;&#xD398;&#xC774;&#xC2A4; &#xC124;&#xC815;&#xC774;&#xB2E4;.</p>
<p>17.10&#xBD80;&#xD130; &#xB124;&#xD2B8;&#xC6CC;&#xD06C; &#xC778;&#xD130;&#xD398;&#xC774;&#xC2A4; &#xC124;&#xC815;&#xC774; <code>NetPlan</code>&#xC774;&#xB77C;&#xB294; &#xC0C8;&#xB85C;&#xC6B4; &#xB124;&#xD2B8;&#xC6CC;&#xD06C; &#xC124;&#xC815; &#xC2DC;&#xC2A4;&#xD15C;&#xC73C;&#xB85C; &#xBCC0;&#xACBD;&#xB41C; &#xAC83; &#xAC19;&#xB2E4;.</p>
<p>&#xD655;&#xC2E4;&#xD788; &#xAE30;&#xC874;&#xC758; &#xC778;&#xD130;&#xD398;&#xC774;&#xC2A4; &#xC124;&#xC815;(/etc/network/interfaces)&#xBCF4;&#xB2E4;&#xB294; &#xB354; &#xAC04;&#xACB0;&#xD558;&#xACE0; &#xC27D;&#xAC8C; YAML&#xC744; &#xC0AC;&#xC6A9;&#xD558;&#xC5EC; &#xAD00;&#xB9AC;&#xAC00; &#xAC00;&#xB2A5;&#xD558;&#xB2E4;.</p>
<pre><code class="language-bash">/etc/netplan/*.yaml
</code></pre>
<p>&#xD574;&#xB2F9; &#xC704;&#xCE58;&#xC5D0; &#xC778;&#xD130;&#xD398;&#xC774;&#xC2A4; &#xC124;&#xC815;&#xC774; &#xAC00;&#xB2A5;&#xD558;&#xACE0; <code>NetworkManager</code>&#xC640; <code>networkd</code> &#xB450;&#xAC1C;&#xC758; &#xB80C;&#xB354;&#xB7EC;&#xB97C; &#xC0AC;&#xC6A9;&#xD560; &#xC218; &#xC788;&#xB2E4;.</p>
<p><code>NetworkManger</code> &#xB80C;&#xB354;&#xB7EC;&#xB97C; &#xC0AC;&#xC6A9;&#xD558;&#xB294; &#xACBD;&#xC6B0;&#xC5D0;&#xB294; X Window &#xD658;&#xACBD;&#xC5D0;&#xC11C;&#xB9CC; &#xC0AC;&#xC6A9;&#xD558;&#xACE0; &#xB098;&#xBA38;&#xC9C0; &#xACBD;&#xC6B0;&#xB294; <code>networkd</code> &#xB80C;&#xB354;&#xB7EC;&#xB97C; &#xC0AC;&#xC6A9;&#xD558;&#xBA74; &#xB41C;&#xB2E4;.</p>
<h2 id="%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC-%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4-%ED%99%95%EC%9D%B8">&#xB124;&#xD2B8;&#xC6CC;&#xD06C; &#xC778;&#xD130;&#xD398;&#xC774;&#xC2A4; &#xD655;&#xC778;</h2>
<p>&#xC6B0;&#xC120; <code>ifconfig -a</code> &#xB97C; &#xD1B5;&#xD574; &#xC124;&#xC815;&#xD560; &#xB124;&#xD2B8;&#xC6CC;&#xD06C; &#xC778;&#xD130;&#xD398;&#xC774;&#xC2A4;&#xB97C; &#xD655;&#xC778;&#xD55C;&#xB2E4;.</p>
<pre><code class="language-bash">hkwon@canary-test-server:~$ ifconfig -a
enp0s3: flags=4163&lt;UP,BROADCAST,RUNNING,MULTICAST&gt;  mtu 1500
        inet 10.0.2.15  netmask 255.255.255.0  broadcast 10.0.2.255
        inet6 fe80::a00:27ff:fe57:92b1  prefixlen 64  scopeid 0x20&lt;link&gt;
        ether 08:00:27:57:92:b1  txqueuelen 1000  (Ethernet)
        RX packets 375  bytes 314494 (314.4 KB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 178  bytes 18901 (18.9 KB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

enp0s8: flags=4098&lt;BROADCAST,MULTICAST&gt;  mtu 1500
        ether 08:00:27:22:8f:0b  txqueuelen 1000  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73&lt;UP,LOOPBACK,RUNNING&gt;  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10&lt;host&gt;
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 28  bytes 2208 (2.2 KB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 28  bytes 2208 (2.2 KB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
</code></pre>
<p><code>enp0s8</code> &#xC778;&#xD130;&#xD398;&#xC774;&#xC2A4;&#xB97C; <code>NetPlan</code>&#xC744; &#xD1B5;&#xD574; &#xC124;&#xC815;&#xD574;&#xBCF4;&#xC790;.</p>
<h2 id="netplan%EC%9D%84-%ED%86%B5%ED%95%9C-static-ip-%EC%84%A4%EC%A0%95"><code>netPlan</code>&#xC744; &#xD1B5;&#xD55C; Static IP &#xC124;&#xC815;</h2>
<p>&#xC544;&#xB9C8; &#xB514;&#xD3F4;&#xD2B8;&#xB85C; &#xC138;&#xD305;&#xD588;&#xB2E4;&#xBA74; &#xC544;&#xB798;&#xC640; &#xAC19;&#xC774; &#xAE30;&#xBCF8; &#xC778;&#xD130;&#xD398;&#xC774;&#xC2A4; &#xC124;&#xC815;&#xC774; &#xC874;&#xC7AC;&#xD55C;&#xB2E4;.</p>
<pre><code class="language-yaml">/etc/netplan/50-cloud-init.yaml
# This file is generated from information provided by
# the datasource.  Changes to it will not persist across an instance.
# To disable cloud-init&apos;s network configuration capabilities, write a file
# /etc/cloud/cloud.cfg.d/99-disable-network-config.cfg with the following:
# network: {config: disabled}
network:
    ethernets:
        enp0s3:
            addresses: []
            dhcp4: true
            optional: true
    version: 2
</code></pre>
<p><code>dhcp</code>&#xB85C; &#xC124;&#xC815;&#xB41C; <code>enp0s3</code> &#xC778;&#xD130;&#xD398;&#xC774;&#xC2A4;&#xAC00; &#xBCF4;&#xC77C; &#xAC83;&#xC774;&#xB2E4;.</p>
<p>&#xC0C8;&#xB85C;&#xC6B4; &#xC778;&#xD130;&#xD398;&#xC774;&#xC2A4;&#xC778; <code>enp0s8</code>&#xBC88;&#xC744; &#xC124;&#xC815;&#xD574;&#xBCF4;&#xC790;</p>
<pre><code class="language-bash">$ sudo vi /etc/netplan/01-netcfg.yaml
</code></pre>
<p>&#xB098;&#xB294; <code>virtualbox</code> &#xD638;&#xC2A4;&#xD2B8;&#xB124;&#xD2B8;&#xC6CC;&#xD06C;&#xB97C; &#xC0AC;&#xC6A9;&#xD55C; &#xC778;&#xD130;&#xD398;&#xC774;&#xC2A4;&#xB97C; &#xCD94;&#xAC00;&#xD574;&#xC11C; <code>ethernets</code> &#xC139;&#xC158;&#xC758; <code>ip</code>&#xB97C; <code>192.168.56.100/24</code>&#xB85C; &#xC124;&#xC815;&#xD558;&#xACE0; &#xAE30;&#xD0C0; &#xC544;&#xB798;&#xC640; &#xAC19;&#xC774; <code>gateway</code>&#xC640; <code>dns</code> &#xC815;&#xBCF4;&#xB97C; &#xC785;&#xB825;&#xD55C;&#xB2E4;.</p>
<pre><code class="language-yaml"># This file describes the network interfaces available on your system
# For more information, see netplan(5).
network:
 version: 2
 renderer: networkd
 ethernets:
   enp0s8:
     dhcp4: no
     dhcp6: no
     addresses: [192.168.56.100/24]
     gateway4: 192.168.56.1
     nameservers:
       addresses: [8.8.8.8,8.8.4.4]
</code></pre>
<p>&#xB2E4;&#xB978; &#xC139;&#xC158;&#xC740; &#xBCFC; &#xD544;&#xC694; &#xC5C6;&#xACE0; <code>ethernets</code> &#xC139;&#xC158;&#xB9CC; &#xC815;&#xD655;&#xD558;&#xAC8C; &#xC124;&#xC815;&#xD558;&#xACE0; &#xC800;&#xC7A5;&#xD55C;&#xB2E4;.</p>
<ul>
<li>dhcp4 : IPv4 dhcp &#xC124;&#xC815;</li>
<li>dhcp6 : IPv6 dhcp &#xC124;&#xC815;</li>
<li>addresses : <code>,</code>&#xB85C; &#xAD6C;&#xBD84;&#xD55C; IP &#xBA40;&#xD2F0;&#xB85C; &#xAC00;&#xB2A5;</li>
<li>gateway4 : IPv4 gateway &#xC124;&#xC815;</li>
<li>nameservers : dns &#xC124;&#xC815; <code>,</code>&#xB85C; &#xAD6C;&#xBD84; &#xBA40;&#xD2F0;&#xB85C; &#xC124;&#xC815; &#xAC00;&#xB2A5; [&#xC0DD;&#xB7B5; &#xAC00;&#xB2A5;]</li>
</ul>
<h2 id="%EC%84%A4%EC%A0%95-%EC%9E%AC%EC%A0%81%EC%9A%A9">&#xC124;&#xC815; &#xC7AC;&#xC801;&#xC6A9;</h2>
<p>&#xC0C8; &#xC124;&#xC815;&#xC744; &#xC801;&#xC6A9;&#xD558;&#xB824;&#xBA74; &#xC544;&#xB798;&#xC758; &#xBA85;&#xB839;&#xC5B4;&#xB97C; &#xC2E4;&#xD589;&#xD55C;&#xB2E4;.</p>
<pre><code class="language-bash">$ sudo netplan apply
</code></pre>
<p>&#xB2E4;&#xC2DC; <code>ifconfig -a</code> &#xD574;&#xC11C; &#xB124;&#xD2B8;&#xC6CC;&#xD06C; &#xC778;&#xD130;&#xD398;&#xC774;&#xC2A4; &#xC815;&#xBCF4;&#xB97C; &#xD655;&#xC778;&#xD55C;&#xB2E4;.</p>
<pre><code class="language-bash">enp0s3: flags=4163&lt;UP,BROADCAST,RUNNING,MULTICAST&gt;  mtu 1500
        inet 10.0.2.15  netmask 255.255.255.0  broadcast 10.0.2.255
        inet6 fe80::a00:27ff:fe57:92b1  prefixlen 64  scopeid 0x20&lt;link&gt;
        ether 08:00:27:57:92:b1  txqueuelen 1000  (Ethernet)
        RX packets 1566  bytes 400006 (400.0 KB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 980  bytes 153691 (153.6 KB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

enp0s8: flags=4163&lt;UP,BROADCAST,RUNNING,MULTICAST&gt;  mtu 1500
        inet 192.168.56.100  netmask 255.255.255.0  broadcast 192.168.56.255
        inet6 fe80::a00:27ff:fe22:8f0b  prefixlen 64  scopeid 0x20&lt;link&gt;
        ether 08:00:27:22:8f:0b  txqueuelen 1000  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 5  bytes 386 (386.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73&lt;UP,LOOPBACK,RUNNING&gt;  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10&lt;host&gt;
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 40  bytes 3108 (3.1 KB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 40  bytes 3108 (3.1 KB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
</code></pre>
<p>&#xC815;&#xC0C1;&#xC801;&#xC73C;&#xB85C; &#xBCC0;&#xACBD;&#xB41C; &#xAC83;&#xC744; &#xD655;&#xC778; &#xD560; &#xC218; &#xC788;&#xB2E4;.</p>
<pre><code class="language-bash">MacBook-Pro:~ hkwon$ ssh hkwon@192.168.56.100
The authenticity of host &apos;192.168.56.100 (192.168.56.100)&apos; can&apos;t be established.
ECDSA key fingerprint is SHA256:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added &apos;192.168.56.100&apos; (ECDSA) to the list of known hosts.
hkwon@192.168.56.100&apos;s password:
Welcome to Ubuntu 18.04 LTS (GNU/Linux 4.15.0-22-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage
...
</code></pre>
<p>&#xC678;&#xBD80;&#xC5D0;&#xC11C;&#xB3C4; &#xC815;&#xC0C1;&#xC801;&#xC73C;&#xB85C; &#xC138;&#xD305;&#xB41C; IP&#xB85C; &#xC811;&#xC18D; &#xAC00;&#xB2A5;&#xD55C; &#xAC83;&#xC744; &#xBCFC; &#xC218; &#xC788;&#xB2E4;.</p>
]]></content:encoded></item><item><title><![CDATA[GeoJSON으로 대한민국 시군구읍면동 맵차트 그리기]]></title><description><![CDATA[<p>&#xCD5C;&#xADFC;&#xC5D0; &#xC9C4;&#xD589;&#xD558;&#xACE0; &#xC788;&#xB294; &#xC0AC;&#xC774;&#xB4DC; &#xD504;&#xB85C;&#xC81D;&#xD2B8; &#xC911; &#xD558;&#xB098;&#xC5D0; &#xC804;&#xAD6D;/&#xC2DC;/&#xAD70;/&#xAD6C;/&#xC74D;/&#xBA74;/&#xB3D9; &#xBCC4; &#xB9F5;&#xCC28;&#xD2B8;&#xB97C; &#xADF8;&#xB824;&#xC57C; &#xD560;&#xC77C;&#xC774; &#xC0DD;&#xACBC;&#xC5C8;&#xB2E4;.</p>
<p>&#xD2B9;&#xC815; &#xC9C0;&#xC5ED;&#xC758; &#xBD84;&#xD3EC;</p>]]></description><link>https://blog.hkwon.me/draw-korean-map-chart-with-geojson/</link><guid isPermaLink="false">66b1a7b306efdd000133fd96</guid><category><![CDATA[GeoJSON]]></category><category><![CDATA[Map Chart]]></category><category><![CDATA[GDAL]]></category><category><![CDATA[ogr2ogr]]></category><category><![CDATA[ECharts]]></category><category><![CDATA[지도]]></category><category><![CDATA[Chart]]></category><dc:creator><![CDATA[Kevin H. Kwon]]></dc:creator><pubDate>Tue, 22 Aug 2017 05:00:00 GMT</pubDate><media:content url="https://blog.hkwon.me/content/images/2024/08/map-1149538_640.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://blog.hkwon.me/content/images/2024/08/map-1149538_640.jpg" alt="GeoJSON&#xC73C;&#xB85C; &#xB300;&#xD55C;&#xBBFC;&#xAD6D; &#xC2DC;&#xAD70;&#xAD6C;&#xC74D;&#xBA74;&#xB3D9; &#xB9F5;&#xCC28;&#xD2B8; &#xADF8;&#xB9AC;&#xAE30;"><p>&#xCD5C;&#xADFC;&#xC5D0; &#xC9C4;&#xD589;&#xD558;&#xACE0; &#xC788;&#xB294; &#xC0AC;&#xC774;&#xB4DC; &#xD504;&#xB85C;&#xC81D;&#xD2B8; &#xC911; &#xD558;&#xB098;&#xC5D0; &#xC804;&#xAD6D;/&#xC2DC;/&#xAD70;/&#xAD6C;/&#xC74D;/&#xBA74;/&#xB3D9; &#xBCC4; &#xB9F5;&#xCC28;&#xD2B8;&#xB97C; &#xADF8;&#xB824;&#xC57C; &#xD560;&#xC77C;&#xC774; &#xC0DD;&#xACBC;&#xC5C8;&#xB2E4;.</p>
<p>&#xD2B9;&#xC815; &#xC9C0;&#xC5ED;&#xC758; &#xBD84;&#xD3EC;&#xB3C4;&#xB77C;&#xB358;&#xC9C0; &#xD788;&#xD2B8;&#xB9F5; &#xC815;&#xB3C4;&#xB97C; &#xC9C0;&#xB3C4;&#xC5D0; &#xBCF4;&#xC5EC;&#xC918;&#xC57C; &#xD558;&#xB294; &#xC694;&#xAD6C;&#xC0AC;&#xD56D;&#xC774;&#xC5C8;&#xB294;&#xB370;(&#xB124;&#xC774;&#xBC84; &#xBD80;&#xB3D9;&#xC0B0;&#xCC98;&#xB7FC;)</p>
<p><img src="https://blog.hkwon.me/content/images/2024/08/1.png" alt="GeoJSON&#xC73C;&#xB85C; &#xB300;&#xD55C;&#xBBFC;&#xAD6D; &#xC2DC;&#xAD70;&#xAD6C;&#xC74D;&#xBA74;&#xB3D9; &#xB9F5;&#xCC28;&#xD2B8; &#xADF8;&#xB9AC;&#xAE30;" loading="lazy"></p>
<p>&#xADF8;&#xAC04; GIS&#xCABD;&#xC774;&#xB098; &#xC774;&#xB7F0;&#xCABD;&#xC740; SI&#xC0AC;&#xC5C5;&#xC744; &#xC8FC;&#xB85C; &#xD558;&#xB2E4;&#xBCF4;&#xB2C8; &#xC194;&#xB8E8;&#xC158; &#xBCA0;&#xC774;&#xC2A4;&#xB85C; &#xB2E4;&#xB904;&#xBD24;&#xC9C0;&#xB9CC; &#xC9C1;&#xC811; &#xAD6C;&#xD604;&#xD574;&#xBCF8;&#xC801;&#xC740; &#xC5C6;&#xC5B4;&#xC11C; &#xC774;&#xB9AC;&#xC800;&#xB9AC; &#xC790;&#xB8CC; &#xC870;&#xC0AC;&#xB97C; &#xD574;&#xBCF4;&#xB2C8; &#xADF8;&#xB7ED;&#xC800;&#xB7ED; &#xC624;&#xD508;&#xC18C;&#xC2A4;&#xB97C; &#xD65C;&#xC6A9;&#xD574;&#xC11C;&#xB3C4; &#xC6D0;&#xD588;&#xB358; &#xC694;&#xAD6C;&#xC0AC;&#xD56D; &#xC815;&#xB3C4;&#xB294; &#xCDA9;&#xBD84;&#xD788; &#xCEE4;&#xBC84; &#xD560; &#xAC83; &#xAC19;&#xC544;&#xC11C; &#xC9C4;&#xD589;&#xD574;&#xBCF4;&#xC558;&#xB2E4;.</p>
<p>&#xC5B8;&#xC81C;&#xB098;&#xCC98;&#xB7FC; &#xBB50; &#xC774;&#xB7F0;&#xC800;&#xB7F0; &#xC0BD;&#xC9C8;&#xC740; &#xD588;&#xC9C0;&#xB9CC; &#xC791;&#xC5C5;&#xD558;&#xACE0; &#xB098;&#xB2C8; &#xAF64;&#xB098; &#xAC04;&#xB2E8;&#xD558;&#xAC8C; &#xAD6C;&#xD604;&#xC774; &#xAC00;&#xB2A5;&#xD558;&#xB2E4;.</p>
<h2 id="%EC%A4%80%EB%B9%84%EB%AC%BC">&#xC900;&#xBE44;&#xBB3C;</h2>
<p>&#xC2DC;/&#xAD70;/&#xAD6C;/&#xC74D;/&#xBA74;/&#xB3D9; &#xBCC4; &#xB9F5; &#xCC28;&#xD2B8;&#xB97C; &#xADF8;&#xB9AC;&#xAE30; &#xC704;&#xD574; &#xAC00;&#xC7A5; &#xC911;&#xC694;&#xD55C;&#xAC74; &#xC0AC;&#xC2E4; <mark>&#xC9C0;&#xB3C4; &#xB370;&#xC774;&#xD130;</mark>&#xC774;&#xB2E4;.</p>
<p>&#xC6B0;&#xC120; &#xC6D0;&#xCC9C;&#xB370;&#xC774;&#xD130;&#xB294; <a href="https://en.wikipedia.org/wiki/Shapefile?ref=blog.hkwon.me">SHP File(Shape file &#xC774;&#xD558; SHP)</a>&#xC774; &#xD544;&#xC694;&#xD558;&#xB2E4;.</p>
<p><code>SHP</code> &#xD3EC;&#xB9F7;&#xC740; GIS(&#xC9C0;&#xB9AC;&#xC815;&#xBCF4;&#xC2DC;&#xC2A4;&#xD15C;) &#xC5D0;&#xC11C; &#xAC00;&#xC7A5; &#xC720;&#xBA85;&#xD55C; &#xC9C0;&#xB9AC;&#xC815;&#xBCF4;&#xB97C; &#xD45C;&#xD604;&#xD558;&#xAE30; &#xC704;&#xD55C; &#xBCA1;&#xD130; &#xB370;&#xC774;&#xD130; &#xD3EC;&#xB9F7;&#xC774;&#xB2E4;.</p>
<p>ESRI&#xB77C;&#xB294; &#xACF3;&#xC5D0;&#xC11C; &#xAC1C;&#xBC1C;&#xB418;&#xC5C8;&#xACE0; &#xCD5C;&#xADFC;&#xC5D4; &#xAC70;&#xC758; GIS &#xC18C;&#xD504;&#xD2B8;&#xC704;&#xC5D0; &#xC81C;&#xD488;&#xCABD;&#xC5D0;&#xC11C;&#xB294; de facto&#xB85C; &#xAD11;&#xBC94;&#xC704;&#xD558;&#xAC8C; &#xC0AC;&#xC6A9;&#xB418;&#xACE0; &#xC788;&#xB294; &#xAC83; &#xAC19;&#xB2E4;.</p>
<p>&#xB9E4;&#xC6B0; &#xACE0;&#xB9D9;&#xAC8C;&#xB3C4; &#xC544;&#xB798; &#xBE14;&#xB85C;&#xADF8;&#xB098; &#xD3EC;&#xD138;&#xC5D0;&#xC11C; &#xB2E4;&#xC6B4;&#xB85C;&#xB4DC; &#xBC1B;&#xC744; &#xC218; &#xC788;&#xB2E4;.</p>
<ul>
<li><a href="http://www.gisdeveloper.co.kr/?p=2332&amp;ref=blog.hkwon.me">&#xACF5;&#xAC04;&#xC815;&#xBCF4;&#xC2DC;&#xC2A4;&#xD15C; &#xC5F0;&#xAD6C;&#xC18C;</a></li>
<li><a href="http://openapi.nsdi.go.kr/nsdi/eios/ServiceDetail.do?ref=blog.hkwon.me">&#xAD6D;&#xAC00;&#xACF5;&#xAC04;&#xC815;&#xBCF4;&#xD3EC;&#xD138;</a></li>
</ul>
<p>&#xD2B9;&#xD788;&#xB098; &#xACF5;&#xAC04;&#xC815;&#xBCF4;&#xC2DC;&#xC2A4;&#xD15C; &#xC5F0;&#xAD6C;&#xC18C;&#xC5D0;&#xC11C; &#xC81C;&#xACF5;&#xD574;&#xC8FC;&#xB294; <code>SHP</code> &#xD30C;&#xC77C;&#xC740; &#xAF64;&#xB098; &#xC720;&#xC6A9;&#xD574;&#xC11C; &#xD574;&#xB2F9; &#xD30C;&#xC77C;&#xB85C; &#xC791;&#xC5C5;&#xC744; &#xC9C4;&#xD589;&#xD588;&#xB2E4;.<br>
(&#xC2DC;&#xAC04;&#xACFC; &#xB178;&#xB825;&#xC774; &#xBD84;&#xBA85; &#xB4E4;&#xC5B4;&#xAC00;&#xB294; &#xC77C;&#xC77C;&#xD150;&#xB370; &#xB9E4;&#xBC88; &#xC5C5;&#xB370;&#xC774;&#xD2B8;&#xB3C4; &#xB9C8;&#xB2E4;&#xD558;&#xC9C0; &#xC54A;&#xACE0; &#xB9E4;&#xC6B0; &#xAC10;&#xC0AC;&#xD558;&#xB2E4;)</p>
<h2 id="%EC%9B%B9%EC%97%90%EC%84%9C-%EC%96%B4%EB%96%BB%EA%B2%8C-%ED%91%9C%ED%98%84%ED%95%98%EC%A7%80">&#xC6F9;&#xC5D0;&#xC11C; &#xC5B4;&#xB5BB;&#xAC8C; &#xD45C;&#xD604;&#xD558;&#xC9C0;?</h2>
<p>&#xBE0C;&#xB77C;&#xC6B0;&#xC800;&#xC5D0;&#xC11C; <code>SHP</code> &#xD30C;&#xC77C;&#xC744; &#xC9C1;&#xC811; &#xD578;&#xB4E4;&#xB9C1;&#xD558;&#xAE30;&#xC5D0;&#xB294; &#xD798;&#xB4E4;&#xACE0; &#xB9F5;&#xC744; &#xD45C;&#xD604;&#xD558;&#xAE30; &#xC704;&#xD574;&#xC11C;&#xB294; <code>GeoJSON</code>&#xC774;&#xB77C;&#xB294; &#xC9C0;&#xB9AC; &#xC815;&#xBCF4; &#xD45C;&#xC2DC;&#xB97C; &#xC704;&#xD55C; &#xD45C;&#xC900; Json&#xD3EC;&#xB9F7;&#xC73C;&#xB85C; &#xBCC0;&#xD658;&#xD574;&#xC57C; &#xD55C;&#xB2E4;.</p>
<p><code>GeoJSON</code>&#xC758; &#xD3EC;&#xB9F7;&#xC740; &#xB2E4;&#xC591;&#xD55C; &#xC9C0;&#xB9AC; &#xB370;&#xC774;&#xD130; &#xAD6C;&#xC870;&#xB97C; &#xC778;&#xCF54;&#xB529;&#xD558;&#xACE0; &#xD45C;&#xD604;&#xD558;&#xAE30; &#xC704;&#xD55C; &#xD615;&#xC2DD;&#xC73C;&#xB85C; RFC &#xD45C;&#xC900;(<a href="https://tools.ietf.org/html/rfc7946?ref=blog.hkwon.me">RFC 7946</a>)&#xC73C;&#xB85C; &#xC815;&#xD574;&#xC838; &#xC788;&#xACE0; &#xD574;&#xB2F9; &#xD615;&#xC2DD;&#xC73C;&#xB85C; &#xBCC0;&#xD658;&#xC744; &#xD558;&#xBA74; &#xB41C;&#xB2E4;.</p>
<p><code>SHP</code> to <code>GeoJSON</code>&#xC5D0;&#xB294; &#xC5EC;&#xB7EC;&#xAC00;&#xC9C0; &#xBC29;&#xBC95;&#xB4E4;&#xC774; &#xC788;&#xACA0;&#xC9C0;&#xB9CC; &#xB098;&#xB294; <a href="http://www.gdal.org/index.html?ref=blog.hkwon.me">GDAL</a>&#xC774;&#xB77C;&#xB294; &#xC9C0;&#xB9AC;&#xB370;&#xC774;&#xD130; &#xBCC0;&#xD658; &#xB77C;&#xC774;&#xBE0C;&#xB7EC;&#xB9AC;&#xC5D0;&#xC11C; &#xC81C;&#xACF5;&#xD558;&#xB294; <code>ogr2ogr</code> &#xC774;&#xB77C;&#xB294; tool&#xC744; &#xC0AC;&#xC6A9;&#xD588;&#xB2E4;.</p>
<h2 id="%EB%B3%80%ED%99%98%EC%97%90-%EC%95%9E%EC%84%9C-%EC%B5%9C%EC%A0%81%ED%99%94%EA%B0%80-%ED%95%84%EC%9A%94%ED%95%98%EB%8B%A4">&#xBCC0;&#xD658;&#xC5D0; &#xC55E;&#xC11C; &#xCD5C;&#xC801;&#xD654;&#xAC00; &#xD544;&#xC694;&#xD558;&#xB2E4;</h2>
<p>&#xC55E;&#xC11C; &#xC598;&#xAE30;&#xD588;&#xB4EF;&#xC774; <code>SHP</code>&#xC5D0; &#xD45C;&#xD604;&#xB418;&#xB294; &#xBCA1;&#xD130; &#xC815;&#xBCF4;&#xB294; &#xD3F4;&#xB9AC;&#xACE4;&#xB4E4;&#xC774; &#xAF64; &#xB514;&#xD14C;&#xC77C;&#xD558;&#xAC8C; &#xADF8;&#xB824;&#xC838; &#xC788;&#xAE30; &#xB54C;&#xBB38;&#xC5D0; &#xC0AC;&#xC774;&#xC988;&#xAC00; &#xD06C;&#xAE30;&#xB3C4; &#xD558;&#xACE0; &#xC880;&#xB354; &#xC2EC;&#xD50C;&#xD558;&#xAC8C; &#xD45C;&#xD604;&#xD560; &#xD544;&#xC694;&#xAC00; &#xC788;&#xB2E4;.</p>
<p>&#xC5EC;&#xB7EC;&#xAC00;&#xC9C0; &#xBCC0;&#xD658;&#xD234;&#xC744; &#xCC3E;&#xB2E4;&#xBCF4;&#xB2C8; <a href="https://github.com/mbloch/mapshaper?ref=blog.hkwon.me">Mapshaper</a>&#xB77C;&#xB294; <code>SHP</code> &#xC5D0;&#xB514;&#xD305; &#xD234;&#xC744; &#xB9CE;&#xC774; &#xC0AC;&#xC6A9;&#xD558;&#xB294; &#xAC83; &#xAC19;&#xACE0; javascript&#xB85C; &#xB9CC;&#xB4E4;&#xC5B4;&#xC838; &#xC788;&#xAE30; &#xB54C;&#xBB38;&#xC5D0; <code>node.js</code>&#xB9CC; &#xC124;&#xCE58;&#xD558;&#xBA74; &#xC27D;&#xAC8C; &#xC0AC;&#xC6A9;&#xD560; &#xC218; &#xC788;&#xACE0; <code>GUI</code> &#xD234;&#xB3C4; &#xAC19;&#xC774; &#xC81C;&#xACF5;&#xD574;&#xC900;&#xB2E4;.</p>
<p><code>Simplify</code> &#xC791;&#xC5C5;&#xC744; &#xC218;&#xD589;&#xD558;&#xAE30; &#xC804;&#xC5D0; <code>node.js</code>&#xAC00; &#xBA3C;&#xC800; &#xC124;&#xCE58;&#xB418;&#xC5B4; &#xC788;&#xC5B4;&#xC57C; &#xD55C;&#xB2E4;.</p>
<pre><code class="language-bash"># mapshaper &#xC124;&#xCE58;
$ npm install -g mapshaper
</code></pre>
<p>&#xC774;&#xC81C; <code>Mapshaper CLI</code>&#xB97C; &#xC0AC;&#xC6A9;&#xD560; &#xC218; &#xC788;&#xACE0; &#xACF5;&#xAC04;&#xC815;&#xBCF4;&#xC2DC;&#xC2A4;&#xD15C; &#xC5F0;&#xAD6C;&#xC18C;&#xC5D0;&#xC11C; &#xC81C;&#xACF5;&#xD558;&#xB294; &#xC2DC;&#xAD70;&#xAD6C; <code>SHP</code> &#xD30C;&#xC77C;&#xC744; <code>Simplify</code>&#xD574;&#xBCF4;&#xC790;</p>
<pre><code class="language-bash">$ mapshaper -i TL_SCCO_SIG.shp \
            encoding=euc-kr  \
            -simplify weighted 0.5% \
            -o format=shapefile \
            TL_SCCO_SIG_convert.shp

hkwon@DESKTOP-HDB86IE:/mnt/c/Temp/map/SIG_201703$ ls -al
&#xD569;&#xACC4; 11551133
drwxrwxrwx 0 root root      512  8&#xC6D4; 22 09:05 .
drwxrwxrwx 0 root root      512  8&#xC6D4; 22 08:50 ..
-rwxrwxrwx 1 root root    21629  5&#xC6D4;  3 12:37 TL_SCCO_SIG.dbf
-rwxrwxrwx 1 root root      406  1&#xC6D4; 15  2014 TL_SCCO_SIG.prj
-rwxrwxrwx 1 root root 21438444  5&#xC6D4;  3 12:37 TL_SCCO_SIG.shp
-rwxrwxrwx 1 root root     2100  5&#xC6D4;  3 12:37 TL_SCCO_SIG.shx
-rwxrwxrwx 1 root root    21629  8&#xC6D4; 22 09:05 TL_SCCO_SIG_convert.dbf
-rwxrwxrwx 1 root root      406  8&#xC6D4; 22 09:05 TL_SCCO_SIG_convert.prj
-rwxrwxrwx 1 root root  1597344  8&#xC6D4; 22 09:05 TL_SCCO_SIG_convert.shp
-rwxrwxrwx 1 root root     2100  8&#xC6D4; 22 09:05 TL_SCCO_SIG_convert.shx
</code></pre>
<p>&#xBCC0;&#xD658;&#xB41C; &#xACB0;&#xACFC;&#xB97C; <code>Mapshaper GUI</code>&#xC5D0;&#xC11C; &#xD655;&#xC778;&#xD574; &#xBCF4;&#xBA74;</p>
<p><img src="https://blog.hkwon.me/content/images/2024/08/2.png" alt="GeoJSON&#xC73C;&#xB85C; &#xB300;&#xD55C;&#xBBFC;&#xAD6D; &#xC2DC;&#xAD70;&#xAD6C;&#xC74D;&#xBA74;&#xB3D9; &#xB9F5;&#xCC28;&#xD2B8; &#xADF8;&#xB9AC;&#xAE30;" loading="lazy"></p>
<p>&#xC0AC;&#xC774;&#xC988;&#xAC00; 21M&#xC5D0;&#xC11C; 1.5M &#xC815;&#xB3C4;&#xB85C; &#xC904;&#xC5B4;&#xB4E4;&#xACE0; &#xB514;&#xD14C;&#xC77C;&#xD558;&#xB358; &#xC12C;&#xB4E4; line&#xC774; &#xAC04;&#xACB0;&#xD654;&#xB41C;&#xAC78; &#xBCFC; &#xC218; &#xC788;&#xB2E4;. &#xB354; &#xB2E4;&#xC591;&#xD55C; &#xBCC0;&#xD658; &#xC635;&#xC158;&#xC740; &#xD574;&#xB2F9; &#xB77C;&#xC774;&#xBE0C;&#xB7EC;&#xB9AC; <code>github</code>&#xC5D0;&#xC11C; &#xCC3E;&#xC544;&#xBCF4;&#xBA74; &#xB418;&#xACE0; &#xAC1C;&#xC778;&#xC801;&#xC778; &#xAE30;&#xC900;&#xC5D0;&#xC11C;&#xB294; <code>0.5%</code> &#xC815;&#xB3C4;&#xAC00; &#xC81C;&#xC77C; &#xC801;&#xB2F9;&#xD558;&#xAC8C; &#xB2E8;&#xC21C;&#xD654; &#xB418;&#xB294; &#xAC83; &#xAC19;&#xB2E4;.</p>
<h2 id="geojson-%EC%9C%BC%EB%A1%9C-%EB%B3%80%ED%99%98">GeoJSON &#xC73C;&#xB85C; &#xBCC0;&#xD658;</h2>
<p><code>SHP</code> &#xD30C;&#xC77C;&#xC774; &#xC900;&#xBE44; &#xB410;&#xC73C;&#xB2C8; &#xC774;&#xC81C; <code>GeoJSON</code>&#xC73C;&#xB85C; &#xBCC0;&#xD658;&#xC744; &#xD558;&#xBA74; &#xB370;&#xC774;&#xD130; &#xC900;&#xBE44;&#xB294; &#xC644;&#xB8CC;&#xB41C;&#xB2E4;.</p>
<p>&#xC55E;&#xC11C; &#xC598;&#xAE30;&#xD588;&#xB4EF;&#xC774; SHP to GeoJSON&#xC740; GDAL &#xD328;&#xD0A4;&#xC9C0;&#xC758; ogr2ogr&#xB97C; &#xC0AC;&#xC6A9;&#xD574;&#xC11C; &#xBCC0;&#xD658;&#xD560; &#xC218; &#xC788;&#xB2E4;.</p>
<p>&#xC708;&#xB3C4;&#xC6B0;&#xB098; &#xB9AC;&#xB205;&#xC2A4; &#xBA38;&#xC2E0; &#xB458;&#xB2E4; &#xC124;&#xCE58; &#xD328;&#xD0A4;&#xC9C0;&#xB294; &#xC81C;&#xACF5;&#xD574;&#xC8FC;&#xACE0; &#xC788;&#xC73C;&#xB2C8; &#xC0C1;&#xD669;&#xC5D0; &#xB9DE;&#xAC8C; GDAL &#xD328;&#xD0A4;&#xC9C0;&#xB97C; &#xC124;&#xCE58;&#xD55C;&#xB2E4;.</p>
<pre><code class="language-bash"># ubuntu&#xC5D0;&#xC11C; &#xC124;&#xCE58;
$ sudo add-apt-repository ppa:ubuntugis/ppa &amp;&amp; sudo apt-get update
$ sudo apt-get install gdal-bin
</code></pre>
<p>&#xC774;&#xC81C; <code>ogr2ogr</code>&#xC744; &#xC0AC;&#xC6A9;&#xD560; &#xC900;&#xBE44;&#xAC00; &#xB410;&#xACE0; &#xAE30;&#xBCF8; &#xC635;&#xC158;&#xC740; &#xC544;&#xB798;&#xC640; &#xAC19;&#xB2E4;.</p>
<pre><code class="language-bash">$ ogr2ogr
Usage: ogr2ogr [--help-general] [-skipfailures] [-append] [-update]
               [-select field_list] [-where restricted_where|@filename]
               [-progress] [-sql &lt;sql statement&gt;|@filename] [-dialect dialect]
               [-preserve_fid] [-fid FID]
               [-spat xmin ymin xmax ymax] [-spat_srs srs_def] [-geomfield field]
               [-a_srs srs_def] [-t_srs srs_def] [-s_srs srs_def]
               [-f format_name] [-overwrite] [[-dsco NAME=VALUE] ...]
               dst_datasource_name src_datasource_name
               [-lco NAME=VALUE] [-nln name]
               [-nlt type|PROMOTE_TO_MULTI|CONVERT_TO_LINEAR]
               [-dim 2|3|layer_dim] [layer [layer ...]]
.....
Note: ogr2ogr --long-usage for full help.
</code></pre>
<p>&#xC0AC;&#xC6A9;&#xD560; &#xC635;&#xC158;&#xC911; <code>COORDINATE_PRECISION</code>&#xC740; &#xC88C;&#xD45C; &#xD45C;&#xD604;&#xAC12;&#xC774; &#xB108;&#xBB34; &#xCEE4;&#xC11C; &#xC815;&#xBC00;&#xD55C; &#xC791;&#xC5C5;&#xC740; &#xD558;&#xC9C0; &#xC54A;&#xC744; &#xAC83;&#xC774;&#xAE30; &#xB54C;&#xBB38;&#xC5D0; &#xC18C;&#xC218;&#xC810; 3&#xC790;&#xB9AC;&#xB85C; &#xC904;&#xC5EC;&#xC11C; &#xBCC0;&#xD658;&#xD558;&#xB294; &#xC635;&#xC158;&#xC744; &#xC92C;&#xB2E4;. &#xBB3C;&#xB860; &#xADF8;&#xB9CC;&#xD07C; <code>GeoJSON</code>&#xC758; &#xC0AC;&#xC774;&#xC988;&#xB3C4; &#xC791;&#xC544;&#xC9C4;&#xB2E4;.</p>
<p>&#xC544;&#xB798;&#xC758; &#xBA85;&#xB839;&#xC5B4;&#xB85C; &#xBCC0;&#xD658;&#xC774; &#xAC00;&#xB2A5;&#xD558;&#xB2E4;.</p>
<pre><code class="language-bash">$ ogr2ogr -f GeoJSON -lco COORDINATE_PRECISION=3 \
          &quot;sig.json&quot; \
          &quot;TL_SCCO_SIG_convert&quot;
</code></pre>
<p>&#xC804;&#xAD6D; &#xB9F5;&#xC740; &#xC2DC;&#xB3C4; <code>SHP</code> &#xD30C;&#xC77C;&#xB85C; &#xC27D;&#xAC8C; &#xBCC0;&#xD658;&#xD560; &#xC218; &#xC788;&#xACE0; &#xC2DC;&#xAD70;&#xAD6C;, &#xC74D;&#xBA74;&#xB3D9;&#xC740; &#xC804;&#xCCB4;&#xAC00; &#xC774;&#xC5B4;&#xC9C4; &#xD558;&#xB098;&#xC758; &#xB9F5;&#xC73C;&#xB85C; &#xB418;&#xC5B4; &#xC788;&#xC73C;&#xB2C8; &#xC694;&#xB188;&#xC744; &#xC2DC;&#xAD70;&#xAD6C;, &#xC74D;&#xBA74;&#xB3D9; &#xBCC4;&#xB85C; &#xC798;&#xB77C;&#xB0B4;&#xC11C; &#xC800;&#xC7A5;&#xD574;&#xC57C; &#xC11C;&#xC6B8;&#xD2B9;&#xBCC4;&#xC2DC;.json, &#xC11C;&#xC6B8;&#xD2B9;&#xBCC4;&#xC2DC;_&#xAC15;&#xB0A8;&#xAD6C;.json &#xACFC; &#xAC19;&#xC740; &#xBD84;&#xB9AC;&#xB41C; &#xD30C;&#xC77C;&#xC744; &#xC5BB;&#xC744; &#xC218; &#xC788;&#xB2E4;.</p>
<p>&#xB2E4;&#xD589;&#xD788; &#xAD6D;&#xAC00;&#xACF5;&#xAC04;&#xC815;&#xBCF4;&#xD3EC;&#xD138;&#xC5D0;&#xC11C; &#xC81C;&#xACF5;&#xD574;&#xC8FC;&#xB294; &#xD30C;&#xC77C;&#xC5D0;&#xB294; &#xD589;&#xC815;&#xAD6C;&#xC5ED;&#xCF54;&#xB4DC;&#xAC00; &#xD568;&#xAED8; &#xD3EC;&#xD568;&#xB418;&#xC5B4; &#xC788;&#xC5B4; &#xC27D;&#xAC8C; &#xAD6C;&#xBD84;&#xD574; &#xB0BC; &#xC218; &#xC788;&#xC744; &#xAC83;&#xC73C;&#xB85C; &#xBCF4;&#xC600;&#xACE0; &#xAC04;&#xB2E8;&#xD558;&#xAC8C; <code>gulp</code> &#xD0DC;&#xC2A4;&#xD06C;&#xB97C; &#xB9CC;&#xB4E4;&#xC5B4; &#xBCC0;&#xD658;&#xC791;&#xC5C5;&#xC744; &#xC5F0;&#xACB0;&#xC2DC;&#xCF30;&#xB2E4;.</p>
<p>&#xD589;&#xC815;&#xAD6C;&#xC5ED;&#xCF54;&#xB4DC;&#xC5D0; &#xAD00;&#xB828;&#xB41C; &#xB0B4;&#xC6A9;&#xC740; [&#xD1B5;&#xACC4;&#xCCAD;&gt;&#xD1B5;&#xACC4;&#xBD84;&#xB958;&#xD3EC;&#xD138;&gt;&#xD2B9;&#xC218;/&#xC77C;&#xBC18;/&#xAD6D;&#xC81C;/&#xD589;&#xC815;&#xAD6C;&#xC5ED;&#xBD84;&#xB958;&gt;&#xD589;&#xC815;&#xAD6C;&#xC5ED;&#xBD84;&#xB958;&gt;&#xC790;&#xB8CC;&#xC2E4;] &#xC744; &#xCC38;&#xC870;&#xD558;&#xBA74; &#xB41C;&#xB2E4;.</p>
<pre><code class="language-javascript">var fs = require(&quot;fs&quot;);

var gulp  = require(&apos;gulp&apos;),
    gutil = require(&apos;gulp-util&apos;),
    clean = require(&apos;gulp-clean&apos;),
    exec  = require(&apos;child_process&apos;).exec,
    _     = require(&apos;lodash&apos;),
    iconv = require(&apos;iconv-lite&apos;);

var shpPath = {
    ctprvn : {
        source : &apos;src/CTPRVN_201703/TL_SCCO_CTPRVN.shp&apos;,
        convert : &apos;src/CTPRVN_201703/TL_SCCO_CTPRVN_CONVERT.shp&apos;,
        json : &apos;dist/ctprvn.json&apos;
    },
    sig : {
        source : &apos;src/SIG_201703/TL_SCCO_SIG.shp&apos;,
        convert : &apos;src/SIG_201703/TL_SCCO_SIG_CONVERT.shp&apos;,
        json : &apos;dist/sig.json&apos;
    },
    emd : {
        source : &apos;src/EMD_201703/TL_SCCO_EMD.shp&apos;,
        convert : &apos;src/EMD_201703/TL_SCCO_EMD_CONVERT.shp&apos;,
        json : &apos;dist/emd.json&apos;
    }
}

gulp.task(&apos;default&apos;, [&apos;convert&apos;]);

gulp.task(&apos;clean-shp&apos;, function() {
    return gulp.src([&apos;dist/*.json&apos;, &apos;src/**/*_CONVERT.*&apos;])
        .pipe(clean());
});

gulp.task(&apos;clean-split&apos;, function() {
    if (!fs.existsSync(&apos;dist/sig&apos;)){
        fs.mkdirSync(&apos;dist/sig&apos;);
    }

    if (!fs.existsSync(&apos;dist/emd&apos;)){
        fs.mkdirSync(&apos;dist/emd&apos;);
    }

    return gulp.src([&apos;dist/sig/*.json&apos;, &apos;dist/emd/*.json&apos;])
        .pipe(clean());
});

gulp.task(&apos;convert&apos;, [&apos;clean-shp&apos;], function() {
    for (var key in shpPath) {
        console.log(&apos;==========&apos;);

        mapshaper(key, shpPath[key].source);
    }
});

gulp.task(&apos;split&apos;, [&apos;clean-split&apos;], function() {
    // &#xC2DC;&#xAD70;&#xAD6C; geojson &#xC0DD;&#xC131;
    splitGeojson(&apos;sig&apos;);

    // &#xB3D9; geojson &#xC0DD;&#xC131;
    splitGeojson(&apos;emd&apos;);
});

function mapshaper(key) {
    var command = &apos;mapshaper -i &apos;
                + shpPath[key].source
                + &apos; encoding=euc-kr -simplify weighted 0.5% -o format=shapefile &apos;
                + shpPath[key].convert;

    console.log(command);

    exec(command, function (error, stdout, stderr) {
        if (error) {
            console.error(`exec error: ${error}`);
            return;
        }

        console.log(stdout);
        console.log(stderr);

        console.log(&apos;=&gt; convert size&apos;)
        console.log(&apos;%s : %d bytes&apos;, shpPath[key].source,  fs.statSync(shpPath[key].source).size);
        console.log(&apos;%s : %d bytes&apos;, shpPath[key].convert, fs.statSync(shpPath[key].convert).size);
        console.log(&apos;=&gt;&apos;)

        ogr2ogr(key);
    });
}

function ogr2ogr(key) {
    var command = &apos;ogr2ogr -f GeoJSON -lco COORDINATE_PRECISION=3 &quot;&apos;
                + shpPath[key].json
                +&apos;&quot; &quot;&apos; + shpPath[key].convert + &apos;&quot;&apos;;

    console.log(command);

    exec(command, function (error, stdout, stderr) {
        if (error) {
            console.error(`exec error: ${error}`);
            return;
        }

        console.log(stdout);
        console.log(stderr);

        console.log(&apos;=&gt; convert json size&apos;)
        console.log(&apos;%s : %d bytes&apos;, shpPath[key].json, fs.statSync(shpPath[key].json).size);
        console.log(&apos;=&gt;&apos;)
    });
}

function splitGeojson(type) {
    console.log(&quot;\n *Split geoJSON START* \n&quot;);
    console.log(type);

    var fileName = shpPath[type].json;
    //var exception = [ &quot;47940&quot; ];
    var exception = [];

    // &#xC2DC;&#xAD70;&#xAD6C; &#xB370;&#xC774;&#xD130; sido &#xBCC4;&#xB85C; &#xC790;&#xB974;&#xAE30;
    var contents = fs.readFileSync(fileName);
    var features ={};
    contents = iconv.decode(contents, &apos;utf-8&apos;);

    var jsonContent = JSON.parse(contents);

    for (var key in jsonContent.features) {
        var feature = jsonContent.features[key];
        var subKey, cd, name;

        if (type == &apos;sig&apos;) {
            cd = feature.properties.SIG_CD;
            name = feature.properties.SIG_KOR_NM;
            subKey = feature.properties.SIG_CD.substr(0, 2);
        } else if (type == &apos;emd&apos;) {
            cd = feature.properties.EMD_CD;
            name = feature.properties.EMD_KOR_NM;
            subKey = feature.properties.EMD_CD.substr(0, 5);
        }

        console.log(`feature.properties.cd: ${cd}, feature.properties.name: ${name}`);

        if (features.hasOwnProperty(subKey)) {
            if (!_.has(exception, cd)) {
                features[subKey].push(feature);
            }
        } else {
            features[subKey] = [];

            if (!_.has(exception, cd)) {
                features[subKey].push(feature);
            }
        }
    }

    for (var key in features) {
        var featuresCollection = _.template(&apos;{&quot;type&quot;: &quot;FeatureCollection&quot;, &quot;features&quot;: [ \
                &lt;% _.forEach(iterator, function(val, index, list) { %&gt; \
                \n  &lt;%= JSON.stringify(val) %&gt;&lt;% \
                if (index &lt; list.length - 1) { \
                %&gt;, &lt;% \
                } \
                }); %&gt; \
            \n]}&apos;);

        var jsonStr = featuresCollection({
            &apos;iterator&apos;: features[key]
        });

        // split json&#xD30C;&#xC77C; &#xC0DD;&#xC131;
        fs.writeFileSync(&quot;dist/&quot; + type + &quot;/&quot; + key + &quot;.json&quot;, jsonStr);
    }

    console.log(&quot;\n *EXIT* \n&quot;);
}
</code></pre>
<p>&#xC0AC;&#xC6A9;&#xD588;&#xB358; &#xB77C;&#xC774;&#xBE0C;&#xB7EC;&#xB9AC;&#xB294; &#xCC38;&#xC870; &#xBC14;&#xB780;&#xB2E4;.</p>
<pre><code class="language-javascript">  &quot;devDependencies&quot;: {
    &quot;gulp&quot;: &quot;^3.9.1&quot;,
    &quot;gulp-clean&quot;: &quot;^0.3.2&quot;,
    &quot;gulp-exec&quot;: &quot;^2.1.3&quot;,
    &quot;gulp-util&quot;: &quot;^3.0.8&quot;,
    &quot;iconv-lite&quot;: &quot;^0.4.17&quot;,
    &quot;lodash&quot;: &quot;^4.17.4&quot;
  }
</code></pre>
<p>&#xD589;&#xC815;&#xAD6C;&#xC5ED; &#xCF54;&#xB4DC; &#xBCC4;&#xB85C; &#xD30C;&#xC77C;&#xC744; &#xB2E4; &#xBD84;&#xB9AC;&#xD574;&#xB0B4;&#xBA74; &#xC774;&#xC81C; &#xC6D0;&#xD558;&#xB294; &#xB9F5;&#xC744; &#xADF8;&#xB9B4; &#xC900;&#xBE44;&#xAC00; &#xB41C;&#xB2E4;.</p>
<pre><code class="language-bash"># &#xC774;&#xB807;&#xAC8C; &#xCD5C;&#xC885;&#xC801;&#xC73C;&#xB85C; &#xD589;&#xC815;&#xAD6C;&#xC5ED; &#xCF54;&#xB4DC; &#xBCC4;&#xB85C; &#xCB49; &#xC0DD;&#xC131;&#xD558;&#xBA74; &#xB41C;&#xB2E4;.
$ tree
&#x251C;&#x2500;&#x2500; ctprvn
&#x251C;&#x2500;&#x2500; ctprvn.json
&#x251C;&#x2500;&#x2500; emd
&#x2502;&#xA0;&#xA0; &#x251C;&#x2500;&#x2500; 11110.json
&#x2502;&#xA0;&#xA0; &#x251C;&#x2500;&#x2500; 11140.json
&#x2502;&#xA0;&#xA0; &#x251C;&#x2500;&#x2500; 11170.json
...&#xC0DD;&#xB7B5;
&#x2502;&#xA0;&#xA0; &#x251C;&#x2500;&#x2500; 48870.json
&#x2502;&#xA0;&#xA0; &#x251C;&#x2500;&#x2500; 48880.json
&#x2502;&#xA0;&#xA0; &#x251C;&#x2500;&#x2500; 48890.json
&#x2502;&#xA0;&#xA0; &#x251C;&#x2500;&#x2500; 50110.json
&#x2502;&#xA0;&#xA0; &#x2514;&#x2500;&#x2500; 50130.json
&#x251C;&#x2500;&#x2500; emd.json
&#x251C;&#x2500;&#x2500; sig
&#x2502;&#xA0;&#xA0; &#x251C;&#x2500;&#x2500; 11.json
&#x2502;&#xA0;&#xA0; &#x251C;&#x2500;&#x2500; 26.json
&#x2502;&#xA0;&#xA0; &#x251C;&#x2500;&#x2500; 27.json
&#x2502;&#xA0;&#xA0; &#x251C;&#x2500;&#x2500; 28.json
&#x2502;&#xA0;&#xA0; &#x251C;&#x2500;&#x2500; 29.json
&#x2502;&#xA0;&#xA0; &#x251C;&#x2500;&#x2500; 30.json
&#x2502;&#xA0;&#xA0; &#x251C;&#x2500;&#x2500; 31.json
&#x2502;&#xA0;&#xA0; &#x251C;&#x2500;&#x2500; 36.json
&#x2502;&#xA0;&#xA0; &#x251C;&#x2500;&#x2500; 41.json
&#x2502;&#xA0;&#xA0; &#x251C;&#x2500;&#x2500; 42.json
&#x2502;&#xA0;&#xA0; &#x251C;&#x2500;&#x2500; 43.json
&#x2502;&#xA0;&#xA0; &#x251C;&#x2500;&#x2500; 44.json
&#x2502;&#xA0;&#xA0; &#x251C;&#x2500;&#x2500; 45.json
&#x2502;&#xA0;&#xA0; &#x251C;&#x2500;&#x2500; 46.json
&#x2502;&#xA0;&#xA0; &#x251C;&#x2500;&#x2500; 47.json
&#x2502;&#xA0;&#xA0; &#x251C;&#x2500;&#x2500; 48.json
&#x2502;&#xA0;&#xA0; &#x2514;&#x2500;&#x2500; 50.json
&#x2514;&#x2500;&#x2500; sig.json

3 directories, 270 files
</code></pre>
<h2 id="%EC%9D%B4%EC%A0%9C-%EC%8B%A4%EC%A0%9C-%EB%A7%B5%EC%9D%84-%EA%B7%B8%EB%A0%A4%EB%B3%B4%EC%9E%90">&#xC774;&#xC81C; &#xC2E4;&#xC81C; &#xB9F5;&#xC744; &#xADF8;&#xB824;&#xBCF4;&#xC790;</h2>
<p><code>GeoJSON</code> &#xD30C;&#xC77C;&#xC774; &#xC900;&#xBE44;&#xB410;&#xC73C;&#xB2C8; &#xC774;&#xC81C; &#xB9F5;&#xCC28;&#xD2B8;&#xB97C; &#xADF8;&#xB9AC;&#xBA74; &#xB41C;&#xB2E4;. &#x314E;&#x314E;</p>
<p>&#xB9CE;&#xC740; &#xC0C1;&#xC6A9;/&#xC624;&#xD508;&#xC18C;&#xC2A4; &#xCC28;&#xD2B8; &#xB77C;&#xC774;&#xBE0C;&#xB7EC;&#xB9AC;&#xB4E4;&#xC740; <code>Custom GeoJSON</code> &#xD30C;&#xC77C;&#xC744; &#xC77D;&#xC5B4;&#xC11C; &#xB9F5;&#xCC28;&#xD2B8;&#xB97C; &#xADF8;&#xB9B4; &#xC218; &#xC788;&#xB2E4;. &#xC791;&#xC5C5; &#xD560;&#xB54C; &#xB9AC;&#xC11C;&#xCE58;&#xB97C; &#xC7A0;&#xAE50; &#xD588;&#xC5C8;&#xB294;&#xB370; &#xB300;&#xD45C;&#xC801;&#xC73C;&#xB85C;&#xB294; &#xC544;&#xB798;&#xC758; &#xCC28;&#xD2B8; &#xB77C;&#xC774;&#xBE0C;&#xB7EC;&#xB9AC;&#xB4E4;&#xC774; &#xAC00;&#xB2A5;&#xD558;&#xB2E4;.</p>
<ul>
<li>&#xC0C1;&#xC6A9;
<ul>
<li><a href="https://www.amcharts.com/?ref=blog.hkwon.me">AMCHARTS</a> - <a href="https://www.amcharts.com/kbase/using-geojson-maps-amcharts/?ref=blog.hkwon.me">using-geojson-maps-amcharts</a></li>
<li><a href="https://www.highcharts.com/?ref=blog.hkwon.me">highcharts</a> - <a href="https://www.highcharts.com/docs/maps/custom-geojson-maps?ref=blog.hkwon.me">Custom GeoJSON maps</a></li>
<li><a href="https://www.anychart.com/?ref=blog.hkwon.me">AnyChart</a> - <a href="https://docs.anychart.com/Maps/Custom_GeoJson_Maps?ref=blog.hkwon.me">Custom GeoJSON Maps</a></li>
</ul>
</li>
<li>&#xC624;&#xD508;&#xC18C;&#xC2A4;
<ul>
<li><a href="https://ecomfe.github.io/echarts-doc/public/en/index.html?ref=blog.hkwon.me">ECharts</a> - <a href="https://ecomfe.github.io/echarts-examples/public/editor.html?c=map-HK&amp;ref=blog.hkwon.me">Population Density of HongKong(2011) &#xC608;&#xC81C;</a></li>
<li>D3, Leaflet</li>
</ul>
</li>
</ul>
<p>&#xB3C8;&#xB9CC; &#xC788;&#xB2E4;&#xBA74;&#xC57C; &#xC0C1;&#xC6A9; &#xB77C;&#xC774;&#xBE0C;&#xB7EC;&#xB9AC; &#xC0AC;&#xC6A9;&#xB3C4; &#xCDA9;&#xBD84;&#xD558;&#xACA0;&#xC9C0;&#xB9CC; &#xC624;&#xD508;&#xC18C;&#xC2A4;&#xB85C;&#xB3C4; &#xAD6C;&#xD604;&#xC740; &#xAC00;&#xB2A5;&#xD558;&#xB2E4;.</p>
<p>&#xC9C0;&#xAE08;&#xC774;&#xC57C; <code>D3</code> &#xACF5;&#xBD80;&#xAC00; &#xC5B4;&#xB290; &#xC815;&#xB3C4; &#xB418;&#xC11C; <code>D3</code>&#xAC00; &#xD3B8;&#xD558;&#xACA0;&#xC9C0;&#xB9CC; &#xB9CC;&#xB4E4; &#xB2F9;&#xC2DC;&#xC5D0;&#xB294; &#xC775;&#xC219;&#xD558;&#xC9C0; &#xC54A;&#xC544;&#xC11C; &#xBC14;&#xC774;&#xB450;&#xC5D0;&#xC11C; &#xB9CC;&#xB4E0; <code>ECharts</code> &#xB85C; &#xC791;&#xC5C5;&#xC744; &#xC9C4;&#xD589;&#xD588;&#xC5C8;&#xB2E4;.</p>
<p>&#xC598;&#xB3C4; &#xCC38; &#xBB3C;&#xAC74;&#xC778; &#xAC83; &#xAC19;&#xACE0; &#xC798; &#xB9CC;&#xB4E4;&#xC5C8;&#xB2E4;. &#xC81C;&#xACF5;&#xD574; &#xC8FC;&#xB294; &#xC608;&#xC81C;&#xB3C4; &#xC5C4;&#xCCAD; &#xB9CE;&#xC544;&#xC11C; &#xC27D;&#xAC8C; &#xC801;&#xC6A9; &#xAC00;&#xB2A5;&#xD558;&#xB2E4;.</p>
<p>&#xAC04;&#xB2E8;&#xD558;&#xAC8C; &#xAC2D;&#xC218;&#xC775;&#xC728;&#xB85C; &#xD788;&#xD2B8;&#xB9F5;&#xC744; &#xC2DC;&#xB3C4;/&#xC2DC;&#xAD70;&#xAD6C;/&#xC74D;&#xBA74;&#xB3D9; &#xB2E8;&#xC704;&#xB85C; &#xADF8;&#xB9B4; &#xC218; &#xC788;&#xACE0; <code>GeoJSON</code>&#xC774; &#xC788;&#xC73C;&#xB2C8; &#xC27D;&#xAC8C; &#xB124;&#xC774;&#xBC84;&#xB9F5; &#xC704;&#xC5D0;&#xB3C4; &#xB808;&#xC774;&#xC5B4;&#xB97C; &#xADF8;&#xB9B4; &#xC218; &#xC788;&#xB2E4;.</p>
<p><img src="https://blog.hkwon.me/content/images/2024/08/3.png" alt="GeoJSON&#xC73C;&#xB85C; &#xB300;&#xD55C;&#xBBFC;&#xAD6D; &#xC2DC;&#xAD70;&#xAD6C;&#xC74D;&#xBA74;&#xB3D9; &#xB9F5;&#xCC28;&#xD2B8; &#xADF8;&#xB9AC;&#xAE30;" loading="lazy"></p>
<p><img src="https://blog.hkwon.me/content/images/2024/08/4.png" alt="GeoJSON&#xC73C;&#xB85C; &#xB300;&#xD55C;&#xBBFC;&#xAD6D; &#xC2DC;&#xAD70;&#xAD6C;&#xC74D;&#xBA74;&#xB3D9; &#xB9F5;&#xCC28;&#xD2B8; &#xADF8;&#xB9AC;&#xAE30;" loading="lazy"></p>
<p><img src="https://blog.hkwon.me/content/images/2024/08/5.png" alt="GeoJSON&#xC73C;&#xB85C; &#xB300;&#xD55C;&#xBBFC;&#xAD6D; &#xC2DC;&#xAD70;&#xAD6C;&#xC74D;&#xBA74;&#xB3D9; &#xB9F5;&#xCC28;&#xD2B8; &#xADF8;&#xB9AC;&#xAE30;" loading="lazy"></p>
<p><img src="https://blog.hkwon.me/content/images/2024/08/6.png" alt="GeoJSON&#xC73C;&#xB85C; &#xB300;&#xD55C;&#xBBFC;&#xAD6D; &#xC2DC;&#xAD70;&#xAD6C;&#xC74D;&#xBA74;&#xB3D9; &#xB9F5;&#xCC28;&#xD2B8; &#xADF8;&#xB9AC;&#xAE30;" loading="lazy"></p>
<p>&#xC704;&#xCC98;&#xB7FC; &#xC6D0;&#xD558;&#xB294; &#xBC29;&#xD5A5;&#xB370;&#xB85C; &#xD788;&#xD2B8;&#xB9F5; &#xADF8;&#xB9AC;&#xB294;&#xB370;&#xB294; <code>ECharts</code> &#xC815;&#xB3C4;&#xB85C; &#xCDA9;&#xBD84;&#xD588;&#xB2E4;.</p>
<p><code>ECharts</code>&#xB97C; &#xC0AC;&#xC6A9;&#xD558;&#xB294; &#xBC29;&#xBC95;&#xC740; &#xBCC4;&#xB3C4;&#xC758; &#xC124;&#xBA85;&#xC774; &#xD544;&#xC694; &#xC5C6;&#xC744; &#xC815;&#xB3C4;&#xB85C; &#xC704;&#xC5D0; &#xC801;&#xC5B4;&#xB193;&#xC740; &#xC608;&#xC81C;&#xC5D0; &#xC790;&#xC138;&#xD788; &#xB098;&#xC640;&#xC788;&#xC5B4;&#xC11C; &#xB530;&#xB85C; &#xBAA8;&#xB4C8; &#xC0AC;&#xC6A9;&#xBC95;&#xC744; &#xC124;&#xBA85;&#xD560; &#xD544;&#xC694;&#xB294; &#xC5C6;&#xC744; &#xAC83; &#xAC19;&#xACE0; &#xC0AC;&#xC6A9;&#xD588;&#xB358; &#xBAA8;&#xB4C8;&#xC740; &#xCC38;&#xACE0;&#xB85C; &#xC62C;&#xB824;&#xB454;&#xB2E4;.</p>
<pre><code class="language-html">&lt;script type=&quot;text/javascript&quot; src=&quot;/static/echarts/echarts.js&quot;&gt;&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot; src=&quot;/static/echarts/chart/line.js&quot;&gt;&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot; src=&quot;/static/echarts/chart/map.js&quot;&gt;&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot; src=&quot;/static/js/region.min.js&quot;&gt;&lt;/script&gt;
</code></pre>
<pre><code class="language-javascript">...
&lt;div class=&quot;mapview&quot;&gt;
  &lt;div id=&quot;mapChart&quot; class=&quot;feature-box light-gray-bg bordered text-center&quot; style=&quot;height:350px;&quot;&gt;
  &lt;/div&gt;
&lt;/div&gt;
...

...
MapChart.drawMapChart(&apos;mapChart&apos;);
...

---

/**
 * **** &#xB9F5; &#xCC28;&#xD2B8; &#xBAA8;&#xB4C8;
 * Created by hkwon on 2017-05-12.
 */

// &#xC9C0;&#xC5ED;&#xC911;&#xC2EC; &#xB9F5; &#xCC28;&#xD2B8; &#xBAA8;&#xB4C8;
(function (root, factory) {
  if (typeof define === &apos;function&apos; &amp;&amp; define.amd) {
    define([&quot;jquery&quot;, &quot;lodash&quot;], factory);
  } else if (typeof module === &apos;object&apos; &amp;&amp; module.exports) {
    module.exports = factory(require(&quot;jquery&quot;), require(&quot;lodash&quot;));
  } else {
    root.MapChart = factory(root.$, root._);
  }
}(this, function ($, _) {
  var MapChart = {};

  var version = &apos;1.0&apos;;

  //-----
  //--variables
  var type, code;
  var seriesData = [];
  var geo;
  var myChart;
  var ecConfig;

  // ECharts global toolbox option
  var toolboxOption = {
    show: true,
    orient: &apos;vertical&apos;,
    x: &apos;right&apos;,
    y: &apos;center&apos;,
    feature: {
      mark: {
        show: true,
        title: {
          mark: &apos;&#xB9C8;&#xD0B9;&apos;,
          markUndo: &apos;&#xB9C8;&#xD0B9; &#xC6D0;&#xBCF5;&apos;,
          markClear: &apos;&#xB9C8;&#xD0B9; &#xC81C;&#xAC70;&apos;
        }
      },
      dataView: {
        show: true,
        readOnly: false,
        title: &apos;&#xB370;&#xC774;&#xD130; &#xBCF4;&#xAE30;&apos;,
        lang: [&apos;a&apos;, &apos;b&apos;, &apos;c&apos;]
      },
      dataZoom: {
        show: false,
        title: {
          dataZoom: &apos;&#xD655;&#xB300;&apos;,
          dataZoomReset: &apos;&#xC90C; &#xCDE8;&#xC18C;&apos;
        }
      },
      magicType: {
        show: false,
        title: {
          line: &apos;line&apos;,
          bar: &apos;bar&apos;,
          stack: &apos;statck&apos;,
          tiled: &apos;tiled&apos;,
          force: &apos;force&apos;,
          chord: &apos;chord&apos;,
          pie: &apos;pie&apos;,
          funnel: &apos;funnel&apos;
        },
        option: {
          // line: {...},
          // bar: {...},
          // stack: {...},
          // tiled: {...},
          // force: {...},
          // chord: {...},
          // pie: {...},
          // funnel: {...}
        },
        type: []
      },
      restore: {
        show: true,
        title: &apos;&#xC0C8;&#xB85C;&#xACE0;&#xCE68;&apos;
      },
      saveAsImage: {
        show: true,
        type: &apos;png&apos;,
        title: &apos;&#xC774;&#xBBF8;&#xC9C0;&#xB85C; &#xC800;&#xC7A5;&apos;,
        lang: [&apos;&#xC800;&#xC7A5;&apos;]
      }
    }
  };

  // ECharts global data range option
  var dataRangeOption = {
    min: 1,
    max: 3,
    text: [&apos;&#xB192;&#xC74C;&apos;, &apos;&#xB0AE;&#xC74C;&apos;],
    realtime: false,
    precision: 1,
    padding: 10,
    calculable: true,
    color: [&apos;#EA1583&apos;,&apos;#EC3A88&apos;,&apos;#F16785&apos;,&apos;#F48F80&apos;,&apos;#F8AA6F&apos;,&apos;#FCCF50&apos;, &apos;#FCF135&apos;]
  };

  // ECharts global data range option
  var tooltipOption = {
    trigger: &apos;item&apos;,
    showDelay: 0,
    transitionDuration: 0.2,
    formatter: function (params) {
      console.log(&apos;tooltip &apos; + params.seriesName);
      var seriesName = params.seriesName ? params.seriesName : &apos;&#xB2E8;&#xC9C0; &#xC5C6;&#xC74C;&apos;;
      return seriesName + &apos;&lt;br/&gt;&apos; + params.name + &apos; : &apos; + params.value;
    }
  };

  //-----
  //--utilities function

  var findCodeByName = function (name) {
    var code;

    for (key in geo.features) {
      if (geo.features.hasOwnProperty(key)) {
        if (geo.features[key].properties.name === name) {
          if (type === &apos;ctprvn&apos;) {
            code = geo.features[key].properties.CTPRVN_CD;
          } else if (type === &apos;sig&apos;) {
            code = geo.features[key].properties.SIG_CD;
          } else if (type === &apos;emd&apos;) {
            code = geo.features[key].properties.EMD_CD;
          }
        }
      }
    }

    return (code + &quot;0000000000&quot;).slice(0, 10);
  };

  //-----
  //--dom handler

  //-----
  //--event handler
  var addEventHandler = function () {
    // Event &#xB4F1;&#xB85D;
    myChart.on(&apos;click&apos;, function (params) {
      var name = params.name;

      window.location = &apos;/region/&apos; + findCodeByName(name);
    });
  };

  //-----
  //--private methods
  var loadAndDrawMapChart = function(id) {
    var dataArr = [];

    if (regionJsonDatas) {
      for (var k in regionJsonDatas) {
        var dataObj = {};

        dataObj[&apos;name&apos;] = regionJsonDatas[k].lowest_area_nm;
        dataObj[&apos;value&apos;] = (regionJsonDatas[k].roi === &apos;-&apos;) ? 0 : parseFloat(regionJsonDatas[k].roi);

        dataArr.push(dataObj);
      }

      // data range max,min &#xACC4;&#xC0B0;
      dataRangeOption.max = parseFloat(_.maxBy(dataArr, &apos;value&apos;).value);
      dataRangeOption.min = parseFloat(_.minBy(dataArr, &apos;value&apos;).value);

      console.log(&apos;max&apos; + dataRangeOption.max);
      console.log(&apos;min&apos; + dataRangeOption.min);
    } else {
      console.log(&apos;&#xB370;&#xC774;&#xD130;&#xAC00; &#xC874;&#xC7AC;&#xD558;&#xC9C0; &#xC54A;&#xC2B5;&#xB2C8;&#xB2E4;.&apos;);

      return false;
    }

    seriesData[0] = {
      name: &apos;****&apos;,
      type: &apos;map&apos;,
      roam: true,
      mapType: &apos;CUSTOM_MAP&apos;,
      itemStyle: {
        normal: {label: {show: false}},
        emphasis: {label: {show: true}}
      },
      data: dataArr,
      nameMap: {}
    };

    configureECharts();
    drawEChartsMap(id);
    addEventHandler();
  };

  // Configure ECharts for module loader
  var configureECharts = function () {
    console.log(&apos;initializeChart&apos;);

    require.config({
      paths: {
        echarts: &apos;/static/echarts&apos;
      }
    });
  };

  // Draw ECharts map
  var drawEChartsMap = function(id) {
    require(
      [
        &apos;echarts&apos;,
        &apos;echarts/chart/map&apos;,
      ],
      function (ec, theme) {
        // Initialize after dom ready
        myChart = ec.init(document.getElementById(id));

        // code &#xBCC4; map data load
        require(&apos;echarts/util/mapData/params&apos;).params.CUSTOM_MAP = {
          getGeoJson: function (callback) {
            $.getJSON(&apos;/static/geojson/&apos; + type + &apos;/&apos; + code + &apos;.json&apos;, callback)
              .done(function (data) {
                geo = data;
              });
          }
        }

        var option = {
          title : {
              text : &apos;****&apos;
          },
          tooltip : tooltipOption,
          toolbox: toolboxOption,
          dataRange: dataRangeOption,
          series : seriesData
        };

        // Load data into the ECharts instance
        myChart.setOption(option);

        ecConfig = require(&apos;echarts/config&apos;);
      }
    );
  };

  // uri&#xC5D0; &#xD45C;&#xD604;&#xB41C; &#xD589;&#xC815;&#xB3D9; code&#xC5D0; &#xB530;&#xB978; type &#xD310;&#xBCC4;
  // geojson&#xC5D0; &#xAE30;&#xC7AC;&#xB41C; &#xCF54;&#xB4DC; &#xCCB4;&#xACC4;&#xB85C; &#xBCC0;&#xD658;
  var setType = function() {
    var matchType;
    var uri = $(location).attr(&apos;pathname&apos;);

    var re = new RegExp(&quot;\/region\/(.*)&quot;);
    var match = uri.match(re);

    if (match[1]) {
      if (match[1].substring(2, 10) === &apos;00000000&apos;) {
        code = match[1].substring(0, 2);
        type = &apos;sig&apos;;
      } else if (match[1].substring(5, 10) === &apos;00000&apos;) {
        code = match[1].substring(0, 5);
        type = &apos;emd&apos;;
      } else if (match[1].substring(9,10) === &apos;00&apos;) {
        type = &apos;apt&apos;;
      }
    } else {
      code = &apos;ctprvn&apos;;
      type = &apos;ctprvn&apos;;
    }
  };

  //-----
  //--public methods

  // &#xCC28;&#xD2B8; &#xADF8;&#xB9AC;&#xAE30;
  MapChart.drawMapChart = function(id) {
    setType();
    loadAndDrawMapChart(id);
  };

  // &#xB9F5;&#xCC28;&#xD2B8; &#xBC18;&#xD658;
  MapChart.getChart = function() {
    return myChart;
  }

  return MapChart;
}));
</code></pre>
<p>&#xBE44;&#xC2B7;&#xD55C; &#xAE30;&#xB2A5;&#xC774; &#xD544;&#xC694;&#xD558;&#xB2E4;&#xBA74; <code>ECharts</code>&#xB85C;&#xB3C4; &#xCDA9;&#xBD84;&#xD788; &#xC6D0;&#xD558;&#xB294; &#xBC29;&#xD5A5;&#xC73C;&#xB85C; &#xADF8;&#xB824;&#xBCFC; &#xC218; &#xC788;&#xC744; &#xAC83; &#xAC19;&#xB2E4;.</p>
<p>&#xAC1C;&#xC778;&#xC801;&#xC73C;&#xB85C; <code>D3</code>&#xC5D0; &#xC694;&#xC0C8; &#xC2EC;&#xCDE8;&#xD574; &#xC788;&#xC5B4;&#xC11C; &#xC2DC;&#xAC04;&#xC774; &#xB41C;&#xB2E4;&#xBA74; <code>D3</code>&#xB85C; &#xB41C; &#xC608;&#xC81C;&#xB3C4; &#xB9CC;&#xB4E4;&#xC5B4; &#xBCFC;&#xAE4C;&#xD558;&#xB294;&#xB370;.. &#xACFC;&#xC5F0;.. &#xADC0;&#xCC28;&#xB2C8;&#xC998;&#xACFC; &#xC2DC;&#xAC04;&#xC774; &#xB418;&#xB824;&#xB098; &#xC2F6;&#xAE34;&#xD558;&#xB2E4;.</p>
<p>&#xADF8;&#xB798;&#xB3C4; &#xD654;&#xC774;&#xD305;~</p>
]]></content:encoded></item><item><title><![CDATA[XenServer – local ISO Library만들기]]></title><description><![CDATA[<p>XenServer &#xAD6C;&#xC131; &#xC2DC; &#xC124;&#xCE58;&#xD560; os&#xC758; iso &#xC774;&#xBBF8;&#xC9C0; attach &#xD558;&#xB294; &#xAC00;&#xC7A5; &#xAE30;&#xBCF8;&#xC801;&#xC778; &#xBC29;&#xBC95;&#xC740; <code>cifs</code> &#xB97C; &#xC0AC;&#xC6A9;&#xD574;&#xC11C;</p>
<p>&#xC708;&#xB3C4;&#xC6B0; &#xBA38;&#xC2E0;&#xC758; &#xACF5;&#xC720; &#xD3F4;&#xB354;&#xB97C; attach&#xD558;&#xC5EC; &#xC0AC;&#xC6A9;&#xD558;&#xB294; &#xBC29;</p>]]></description><link>https://blog.hkwon.me/create-xenserver-local-iso-library/</link><guid isPermaLink="false">66b1a7b306efdd000133fd97</guid><category><![CDATA[xenserver]]></category><category><![CDATA[iso]]></category><category><![CDATA[xencenter]]></category><category><![CDATA[xe]]></category><category><![CDATA[sr-create]]></category><dc:creator><![CDATA[Kevin H. Kwon]]></dc:creator><pubDate>Fri, 11 Aug 2017 06:13:15 GMT</pubDate><media:content url="https://blog.hkwon.me/content/images/2024/08/patrick-lindenberg-1iVKwElWrPA-unsplash.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://blog.hkwon.me/content/images/2024/08/patrick-lindenberg-1iVKwElWrPA-unsplash.jpg" alt="XenServer &#x2013; local ISO Library&#xB9CC;&#xB4E4;&#xAE30;"><p>XenServer &#xAD6C;&#xC131; &#xC2DC; &#xC124;&#xCE58;&#xD560; os&#xC758; iso &#xC774;&#xBBF8;&#xC9C0; attach &#xD558;&#xB294; &#xAC00;&#xC7A5; &#xAE30;&#xBCF8;&#xC801;&#xC778; &#xBC29;&#xBC95;&#xC740; <code>cifs</code> &#xB97C; &#xC0AC;&#xC6A9;&#xD574;&#xC11C;</p>
<p>&#xC708;&#xB3C4;&#xC6B0; &#xBA38;&#xC2E0;&#xC758; &#xACF5;&#xC720; &#xD3F4;&#xB354;&#xB97C; attach&#xD558;&#xC5EC; &#xC0AC;&#xC6A9;&#xD558;&#xB294; &#xBC29;&#xBC95;&#xC774; &#xC788;&#xB2E4;.</p>
<p>&#xADFC;&#xB370; &#xC694;&#xC0C1;&#xD558;&#xAC8C; <code>cifs</code>&#xAC00; &#xC798; &#xC548;&#xC7A1;&#xD788;&#xAC70;&#xB098; &#xD558;&#xB294; &#xACBD;&#xC6B0;&#xC5D0;&#xB294; xenserver host&#xC5D0; local iso library&#xB97C; &#xB9CC;&#xB4E4;&#xC5B4; &#xC0AC;&#xC6A9;&#xD558;&#xBA74; &#xB41C;&#xB2E4;.</p>
<h2 id="%ED%81%B0-%ED%8C%8C%EC%9D%BC%EC%9D%98-iso-library-%EB%A7%8C%EB%93%A4%EA%B8%B0">&#xD070; &#xD30C;&#xC77C;&#xC758; ISO Library &#xB9CC;&#xB4E4;&#xAE30;</h2>
<p>Xenserver &#xD638;&#xC2A4;&#xD2B8;&#xC758; &#xB8E8;&#xD2B8; &#xD30C;&#xD2F0;&#xC158;&#xC740; &#xAE30;&#xBCF8;&#xC774; &#xC544;&#xB9C8; 4G&#xB85C; &#xB418;&#xC5B4; &#xC788;&#xC73C;&#xBBC0;&#xB85C; sr-mount &#xB418;&#xC5B4; &#xC788;&#xB294; &#xD30C;&#xD2F0;&#xC158;&#xC5D0; xenserver storage&#xB97C; &#xB9CC;&#xB4E4;&#xBA74; &#xB41C;&#xB2E4;.</p>
<pre><code class="language-bash">[root@localhost ~]# df -k
Filesystem           1K-blocks      Used Available Use% Mounted on
/dev/sda1              4127440   2012800   1904976  52% /
none                    954268       112    954156   1% /dev/shm
/opt/xensource/packages/iso/XenCenter.iso
                         57216     57216         0 100% /var/xen/xc-install
/dev/mapper/XSLocalEXT--bb2de5e6--d46d--c812--a949--dd0934750a62-bb2de5e6--d46d--c812--a949--dd0934750a62
                     3829180512 866521236 2768148020  24% /var/run/sr-mount/bb2de5e6-d46d-c812-a949-dd0934750a62 &lt;-- &#xC5EC;&#xAE30;&#xC5D0; &#xB9CC;&#xB4E4;&#xBA74; &#xB41C;&#xB2E4;.
</code></pre>
<p>&#xC2A4;&#xD1A0;&#xB9AC;&#xC9C0; location&#xC744; &#xC544;&#xB798;&#xC640; &#xAC19;&#xC774; &#xC0DD;&#xC131;&#xD558;&#xACE0;</p>
<pre><code class="language-bash">$ mkdir /var/run/sr-mount/bb2de5e6-d46d-c812-a949-dd0934750a62/iso_storage
</code></pre>
<p>&#xB2E4;&#xC74C;&#xACFC; &#xAC19;&#xC774; &#xC2A4;&#xD1A0;&#xB9AC;&#xC9C0;&#xB97C; &#xC0DD;&#xC131;&#xD558;&#xBA74; &#xB41C;&#xB2E4;.</p>
<pre><code class="language-bash">xe sr-create name-label=ISO_Storage type=iso device-config:location=/var/run/sr-mount/bb2de5e6-d46d-c812-a949-dd0934750a62/iso_storage device-config:legacy_mode=true content-type=iso
</code></pre>
<p>&#xC694;&#xB807;&#xAC8C; <code>xencenter</code>&#xC5D0;&#xC11C; &#xBCF4;&#xBA74; &#xC0C8;&#xB85C;&#xC6B4; iso library&#xAC00; &#xC0DD;&#xC131;&#xB41C;&#xAC83;&#xC774; &#xBCF4;&#xC778;&#xB2E4;.</p>
<p><img src="https://blog.hkwon.me/content/images/2024/08/1-2.png" alt="XenServer &#x2013; local ISO Library&#xB9CC;&#xB4E4;&#xAE30;" loading="lazy"></p>
<p>&#xC778;&#xD130;&#xB137;&#xC774; &#xB418;&#xB294; &#xD658;&#xACBD;&#xC774;&#xB77C;&#xBA74; <code>wget</code>&#xC73C;&#xB85C; &#xD30C;&#xC77C;&#xC744; &#xC9C1;&#xC811; &#xBC1B;&#xC74C; &#xB418;&#xACE0; ftp&#xB85C; &#xD574;&#xB2F9; location&#xC5D0; &#xC774;&#xBBF8;&#xC9C0;&#xB97C; &#xB123;&#xACE0; storage &#xC635;&#xC158;&#xC5D0;&#xC11C; <code>rescan</code>&#xC744; &#xD558;&#xBA74; iso &#xC774;&#xBBF8;&#xC9C0;&#xAC00; &#xBCF4;&#xC774;&#xAC8C; &#xB41C;&#xB2E4;.</p>
<p><img src="https://blog.hkwon.me/content/images/2024/08/2-2.png" alt="XenServer &#x2013; local ISO Library&#xB9CC;&#xB4E4;&#xAE30;" loading="lazy"></p>
<p>&#xC774;&#xC81C; VM &#xC0DD;&#xC131; &#xC2DC; &#xD574;&#xB2F9; iso &#xC774;&#xBBF8;&#xC9C0;&#xB97C; &#xC120;&#xD0DD;&#xD574;&#xC11C; guest os &#xC124;&#xCE58;&#xD558;&#xBA74; &#xB41C;&#xB2E4;.</p>
<p><img src="https://blog.hkwon.me/content/images/2024/08/3-1.png" alt="XenServer &#x2013; local ISO Library&#xB9CC;&#xB4E4;&#xAE30;" loading="lazy"></p>
<p>DVD&#xB3C4; &#xC5C6;&#xACE0; &#xD070; &#xD30C;&#xC77C;&#xC758; iso(everything &#xBC84;&#xC804; &#xB4F1;)&#xB4E4;&#xC744; &#xC124;&#xCE58;&#xD558;&#xAE30; &#xD798;&#xB4E0; &#xD658;&#xACBD;&#xC778; &#xACBD;&#xC6B0; &#xC704;&#xCC98;&#xB7FC; ISO Library&#xB97C; &#xC0DD;&#xC131;&#xD558;&#xACE0; &#xC0AC;&#xC6A9;&#xD558;&#xBA74; &#xC88B;&#xC744; &#xB4EF; &#xD558;&#xB2E4;.</p>
]]></content:encoded></item><item><title><![CDATA[Thymeleaf 확장으로 새로운 dialect 추가해보기]]></title><description><![CDATA[<p>&#xCD5C;&#xADFC;&#xC5D0; &#xBA87;&#xBA87; &#xD504;&#xB85C;&#xC81D;&#xD2B8;&#xB97C; <code>Thymeleaf</code>&#xB97C; &#xD15C;&#xD50C;&#xB9BF; &#xC5D4;&#xC9C4;&#xC73C;&#xB85C; &#xC120;&#xC815;&#xD574;&#xC11C; &#xC9C4;&#xD589;&#xC744; &#xD558;&#xACE0; &#xC788;&#xB2E4;.</p>
<p>&#xC77C;&#xB2E8; &#xAE30;&#xC874;&#xC758; &#xAC1C;&#xBC1C;&#xC790;&#xB4E4;&#xC774; JSP &amp; JSTL&#xC744; &#xC0AC;&#xC6A9;&#xD558;&#xB294; &#xAC83;&#xC5D0;</p>]]></description><link>https://blog.hkwon.me/thymeleaf-extend-dialect/</link><guid isPermaLink="false">66b1a7b306efdd000133fd95</guid><category><![CDATA[thymeleaf]]></category><category><![CDATA[extend]]></category><category><![CDATA[dialect]]></category><category><![CDATA[link]]></category><dc:creator><![CDATA[Kevin H. Kwon]]></dc:creator><pubDate>Wed, 05 Apr 2017 02:19:31 GMT</pubDate><media:content url="https://blog.hkwon.me/content/images/2024/08/connect-1586220_1280.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://blog.hkwon.me/content/images/2024/08/connect-1586220_1280.jpg" alt="Thymeleaf &#xD655;&#xC7A5;&#xC73C;&#xB85C; &#xC0C8;&#xB85C;&#xC6B4; dialect &#xCD94;&#xAC00;&#xD574;&#xBCF4;&#xAE30;"><p>&#xCD5C;&#xADFC;&#xC5D0; &#xBA87;&#xBA87; &#xD504;&#xB85C;&#xC81D;&#xD2B8;&#xB97C; <code>Thymeleaf</code>&#xB97C; &#xD15C;&#xD50C;&#xB9BF; &#xC5D4;&#xC9C4;&#xC73C;&#xB85C; &#xC120;&#xC815;&#xD574;&#xC11C; &#xC9C4;&#xD589;&#xC744; &#xD558;&#xACE0; &#xC788;&#xB2E4;.</p>
<p>&#xC77C;&#xB2E8; &#xAE30;&#xC874;&#xC758; &#xAC1C;&#xBC1C;&#xC790;&#xB4E4;&#xC774; JSP &amp; JSTL&#xC744; &#xC0AC;&#xC6A9;&#xD558;&#xB294; &#xAC83;&#xC5D0; &#xB108;&#xBB34; &#xC775;&#xC219;&#xD558;&#xB2E4;&#xBCF4;&#xB2C8; &#xB3C4;&#xC785;&#xC744; &#xD558;&#xB294;&#xAC8C; &#xC27D;&#xC9C4; &#xC54A;&#xC558;&#xC73C;&#xB098; Spring Framework&#xC640; &#xAD81;&#xD569;&#xB3C4; &#xC798; &#xB9DE;&#xC544;&#xBCF4;&#xC774;&#xACE0; &#xAC1C;&#xC778; &#xD504;&#xB85C;&#xC81D;&#xD2B8;&#xB97C; &#xBA87;&#xAC1C; &#xD574;&#xBCF4;&#xB2C8; &#xD655;&#xC2E4;&#xD788; &#xB3C4;&#xC785;&#xD558;&#xB294; &#xAC83;&#xC774; &#xB0AB;&#xB2E4; &#xC2F6;&#xC5B4;&#xC11C; &#xCD5C;&#xADFC; &#xD504;&#xB85C;&#xC81D;&#xD2B8;&#xB294; &#xC77C;&#xB2E8; <code>Thymeleaf</code>&#xB85C; &#xC9C4;&#xD589;&#xC744; &#xD558;&#xACE0; &#xC788;&#xB2E4;.</p>
<h2 id="%EB%AA%87%EA%B0%80%EC%A7%80-%EC%82%B4%EC%A7%9D-%EC%95%84%EC%89%AC%EC%9A%B4-%EA%B8%B0%EB%8A%A5%EB%93%A4">&#xBA87;&#xAC00;&#xC9C0; &#xC0B4;&#xC9DD; &#xC544;&#xC26C;&#xC6B4; &#xAE30;&#xB2A5;&#xB4E4;</h2>
<p><code>Link URL Expressions</code>&#xC744; &#xC0AC;&#xC6A9;&#xD55C; <code>th:href</code> attribute&#xB97C; &#xC0AC;&#xC6A9;&#xD568;&#xC5D0; &#xC788;&#xC5B4;&#xC11C; request&#xC5D0; &#xB118;&#xC5B4;&#xC628; query string&#xC744; &#xADF8;&#xB300;&#xB85C; &#xB2E4;&#xC74C; &#xB9C1;&#xD06C;&#xB85C; &#xB118;&#xACA8;&#xC57C;&#xB418;&#xB294; &#xACBD;&#xC6B0;&#xAC00; &#xBC1C;&#xC0DD;&#xD558;&#xACE0;&#xB294; &#xD558;&#xB294;&#xB370; &#xC804;&#xCCB4; query string&#xC744; &#xBC1B;&#xC544;&#xC624;&#xB294; &#xAE30;&#xBCF8; &#xAE30;&#xB2A5;&#xC740; &#xC874;&#xC7AC;&#xD558;&#xC9C0; &#xC54A;&#xB294;&#xB2E4;.</p>
<p>&#xBA87;&#xAC00;&#xC9C0; &#xBC29;&#xBC95;&#xC774; &#xC874;&#xC7AC;&#xD558;&#xAE34; &#xD558;&#xC9C0;&#xB9CC; &#xB2E4; &#xB9D8;&#xC5D0; &#xB4E4;&#xC9C4; &#xC54A;&#xB294;&#xB2E4;.</p>
<pre><code class="language-html">&lt;div th:with=&quot;currentUrl=(${#request.getRequestURI() + &apos;?&apos; +
    #strings.defaultString(#request.getQueryString(), &apos;&apos;)})&quot;&gt;
  &lt;a th:href=&quot;@{${currentUrl}(myparam=test)}&quot;&gt;click here&lt;/a&gt;
&lt;/div&gt;
</code></pre>
<p><code>javax.servlet.http.HttpServletRequest</code>&#xB97C; &#xC9C1;&#xC811; &#xC561;&#xC138;&#xC2A4;&#xD560; &#xC218; &#xC788;&#xB294; <code>#request</code> &#xD45C;&#xD604;&#xC744; &#xC0AC;&#xC6A9;&#xD558;&#xBA74; &#xB300;&#xCDA9; &#xC6D0;&#xD558;&#xB294; &#xAE30;&#xB2A5;&#xC744; &#xB9CC;&#xB4E4;&#xC5B4; &#xBCFC;&#xC21C; &#xC788;&#xB2E4;.</p>
<p>&#xD558;&#xC9C0;&#xB9CC; &#xD30C;&#xB77C;&#xBBF8;&#xD130;&#xAC00; &#xC911;&#xBCF5;&#xC778; &#xACBD;&#xC6B0;&#xC5D0;&#xB294; &#xC911;&#xBCF5;&#xD574;&#xC11C; &#xACC4;&#xC18D; &#xCD94;&#xAC00;&#xB418;&#xACE0; &#xBB34;&#xC5C7;&#xBCF4;&#xB2E4; &#xC800;&#xAC78; &#xB9E4;&#xBC88; &#xB9C1;&#xD06C;&#xB9C8;&#xB2E4; &#xC368;&#xC8FC;&#xB294; &#xC544;&#xC8FC; &#xB9D8;&#xC5D0; &#xC548;&#xB4DC;&#xB294; &#xC0C1;&#xD669;&#xC774; &#xBC1C;&#xC0DD;&#xD55C;&#xB2E4;.</p>
<pre><code class="language-html">&lt;div th:with=&quot;currentUrl=(${@currentUrlWithoutParam.apply(&apos;myparam&apos;)})&quot;&gt;
  &lt;a th:href=&quot;@{${currentUrl}(myparam=test)}&quot;&gt;click here&lt;/a&gt;
&lt;/div&gt;
</code></pre>
<pre><code class="language-java">@Bean
public Function&lt;String, String&gt; currentUrlWithoutParam() {
    return param -&gt; ServletUriComponentsBuilder.fromCurrentRequest()
            .replaceQueryParam(param).toUriString();
}
</code></pre>
<p>&#xD639;&#xC740; <code>Function</code>&#xC744; &#xB9CC;&#xB4E4;&#xC5B4;&#xC11C; &#xAC04;&#xB2E8;&#xD558;&#xAC8C; &#xCC98;&#xB9AC;&#xD560; &#xC218;&#xB3C4; &#xC788;&#xC9C0;&#xB9CC; &#xC5ED;&#xC2DC;&#xB098; &#xC774; &#xBC29;&#xBC95;&#xB3C4; &#xADF8;&#xB9AC; &#xD0D0;&#xD0C1;&#xCE58; &#xC54A;&#xB2E4;.</p>
<pre><code class="language-html">&lt;span th:with=&quot;urlBuilder=${T(org.springframework.web.servlet.support.ServletUriComponentsBuilder).fromCurrentRequest()}&quot;
      th:text=&quot;${urlBuilder.replaceQueryParam(&apos;p2&apos;, &apos;32&apos;).toUriString()}&quot;&gt;
&lt;/span&gt;
</code></pre>
<p><code>org.springframework.web.servlet.support.ServletUriComponentsBuilder</code>&#xB97C; &#xC9C1;&#xC811; &#xBD88;&#xB7EC;&#xC640;&#xC11C; &#xC0AC;&#xC6A9;&#xD558;&#xB294; &#xBC29;&#xBC95;&#xB3C4; &#xCC3E;&#xC544;&#xC11C; &#xC2DC;&#xB3C4;&#xD574;&#xBCF4;&#xC558;&#xC9C0;&#xB9CC; &#xC5B4;&#xB290;&#xD558;&#xB098; <code>th:with</code> &#xB97C; &#xC368;&#xC57C;&#xD558;&#xACE0; &#xB9E4;&#xBC88; &#xB9C1;&#xD06C;&#xB97C; &#xB9CC;&#xB4E4;&#xB54C;&#xB9C8;&#xB2E4; &#xB9E4;&#xC6B0; &#xBD88;&#xD3B8;&#xD55C; &#xC0C1;&#xD669;&#xC774; &#xBC1C;&#xC0DD;&#xD574;&#xC11C; &#xC790;&#xC8FC;&#xC4F0;&#xB294; &#xAE30;&#xB2A5;&#xC774;&#xB2E4;&#xBCF4;&#xB2C8;..</p>
<p><code>Thymeleaf</code> &#xD655;&#xC7A5; &#xAE30;&#xB2A5;&#xC744; &#xD1B5;&#xD574; <code>th:link</code> &#xB77C;&#xB294; &#xC0C8;&#xB85C;&#xC6B4; attribute&#xB97C; &#xB9CC;&#xB4E4;&#xC5B4;&#xC11C; &#xCC98;&#xB9AC;&#xD574;&#xBCF4;&#xAE30;&#xB85C; &#xD588;&#xB2E4;.</p>
<h2 id="thlink-attribute-%EC%B6%94%EA%B0%80%EB%A5%BC-%EC%9C%84%ED%95%B4-thymeleaf%EB%A5%BC-%ED%99%95%EC%9E%A5%ED%95%B4%EB%B3%B4%EC%9E%90">th:link attribute &#xCD94;&#xAC00;&#xB97C; &#xC704;&#xD574; Thymeleaf&#xB97C; &#xD655;&#xC7A5;&#xD574;&#xBCF4;&#xC790;</h2>
<p>&#xAD00;&#xB828; &#xB808;&#xD37C;&#xB7F0;&#xC2A4;(<a href="http://www.thymeleaf.org/doc/tutorials/3.0/extendingthymeleaf.html?ref=blog.hkwon.me">Tutorial: Extending Thymeleaf</a>)&#xC640; &#xAE30;&#xC874;&#xC758; &#xD655;&#xC7A5;&#xAE30;&#xB2A5;&#xB4E4; &#xC18C;&#xC2A4;&#xB97C; &#xB458;&#xB7EC;&#xBCF4;&#xB2C8; &#xADF8;&#xB9AC; &#xC5B4;&#xB835;&#xC9C0; &#xC54A;&#xAC8C; &#xAE30;&#xB2A5;&#xC744; &#xD655;&#xC7A5;&#xD560; &#xC218; &#xC788;&#xB2E4;.</p>
<h3 id="dialects-and-processors">Dialects and Processors</h3>
<p><code>Thymeleaf Dialects</code>&#xB780; &#xC0C8;&#xB86D;&#xAC8C; &#xB9CC;&#xB4E4; &#xD15C;&#xD50C;&#xB9BF;&#xC758; &#xAE30;&#xB2A5; &#xC9D1;&#xD569;&#xC774;&#xB77C;&#xACE0; &#xBCF4;&#xBA74; &#xB420; &#xAC83; &#xAC19;&#xB2E4;. <code>Dialect</code>&#xB294; &#xB2E4;&#xC218;&#xC758; <code>Processors</code>&#xC640; <code>Expression</code>&#xC744; &#xAC00;&#xC9C8; &#xC218; &#xC788;&#xB2E4;.</p>
<p>&#xC5EC;&#xAE30;&#xC11C; &#xC598;&#xAE30;&#xD558;&#xB294; <code>Processor</code>&#xB294; &#xB9CC;&#xB4E4;&#xB824;&#xACE0; &#xD558;&#xB294; Attribute&#xB098; Tag&#xC758; &#xAE30;&#xB2A5;&#xC744; &#xC2E4;&#xC81C; &#xCC98;&#xB9AC;&#xD558;&#xB294; &#xB85C;&#xC9C1;&#xC774;&#xACE0;, <code>Expression</code>&#xC740; <code>#request</code>&#xCC98;&#xB7FC; <code>ThymeLeaf</code>&#xC758; &#xAE30;&#xBCF8; &#xD45C;&#xD604;&#xC2DD;&#xC744; &#xD655;&#xC7A5;&#xD558;&#xB294; &#xAC83;&#xC744; &#xC598;&#xAE30;&#xD55C;&#xB2E4;.</p>
<p>&#xB808;&#xD37C;&#xB7F0;&#xC2A4;&#xC5D0;&#xB294; <code>org.thymeleaf.dialect.IDialect</code>&#xB97C; &#xAD6C;&#xD604;&#xD574;&#xC11C; &#xC0AC;&#xC6A9;&#xD558;&#xBA74; &#xB41C;&#xB2E4;&#xB77C;&#xACE0; &#xB098;&#xC640; &#xC788;&#xACE0; &#xC544;&#xB798;&#xC640; &#xAC19;&#xC740; sub interface&#xB4E4;&#xC744; &#xBA87;&#xAC00;&#xC9C0; &#xC81C;&#xACF5;&#xD55C;&#xB2E4;.</p>
<ul>
<li>IProcessorDialect for dialects that provide processors.</li>
<li>IPreProcessorDialect for dialects that provide pre-processors.</li>
<li>IPostProcessorDialect for dialects that provide post-processors.</li>
<li>IExpressionObjectDialect for dialects that provide expression objects.</li>
<li>IExecutionAttributeDialect for dialects that provide execution attributes.</li>
</ul>
<p>&#xB9CC;&#xB4DC;&#xB824;&#xB294; &#xD655;&#xC7A5;&#xC758; &#xAE30;&#xB2A5;&#xC5D0; &#xB9DE;&#xAC8C; &#xC801;&#xC808;&#xD55C; &#xC778;&#xD130;&#xD398;&#xC774;&#xC2A4;&#xB97C; &#xC120;&#xD0DD;&#xD558;&#xBA74; &#xB41C;&#xB2E4;.</p>
<p><code>Processors</code>&#xB294; <code>Dialect</code>&#xC640; &#xB9C8;&#xCC2C;&#xAC00;&#xC9C0;&#xB85C; <code>org.thymeleaf.processor.IProcessor</code> &#xC778;&#xD130;&#xD398;&#xC774;&#xC2A4;&#xB97C; &#xAD6C;&#xD604;&#xD574;&#xC11C; &#xC0AC;&#xC6A9;&#xD558;&#xBA74; &#xB418;&#xACE0;</p>
<ul>
<li>Template start/end</li>
<li>Element Tags</li>
<li>Texts</li>
<li>Comments</li>
<li>CDATA Sections</li>
<li>DOCTYPE Clauses</li>
<li>XML Declarations</li>
<li>Processing Instructions</li>
</ul>
<p>&#xC704;&#xC758; &#xD0C0;&#xC785;&#xC5D0; &#xB9DE;&#xAC8C; &#xC54C;&#xB9DE;&#xC740; sub interface&#xB97C; &#xAD6C;&#xD604;&#xD558;&#xBA74; &#xB41C;&#xB2E4;.</p>
<h3 id="extralinkdialect-%EC%83%9D%EC%84%B1">ExtraLinkDialect &#xC0DD;&#xC131;</h3>
<p><code>ExtraLinkDialect</code>&#xB77C;&#xB294; <code>Dialect</code>&#xB97C; &#xC774;&#xC81C; &#xC2E4;&#xC81C;&#xB85C; &#xB9CC;&#xB4E4;&#xC5B4;&#xBCF4;&#xC790;.</p>
<p>&#xACE0;&#xB9D9;&#xAC8C;&#xB3C4; <code>AbstractProcessorDialect</code>&#xB77C;&#xB294; <code>IProcessorDialect</code>&#xB97C; &#xAD6C;&#xD604;&#xD55C; &#xD074;&#xB798;&#xC2A4;&#xB97C; &#xC81C;&#xACF5;&#xD574; &#xC8FC;&#xACE0; &#xC788;&#xB2E4;.</p>
<pre><code class="language-java">package me.hkwon.thymeleaf.dialect;

import java.util.LinkedHashSet;
import java.util.Set;
import me.hkwon.thymeleaf.dialect.processor.LinkAttrProcessor;
import org.thymeleaf.dialect.AbstractProcessorDialect;
import org.thymeleaf.processor.IProcessor;
import org.thymeleaf.templatemode.TemplateMode;

public class ExtraLinkDialect extends AbstractProcessorDialect {
    public static final String NAME = &quot;ExtraLink&quot;;
    public static final String DEFAULT_PREFIX = &quot;th&quot;;
    public static final int PROCESSOR_PRECEDENCE = 800;
    private String charset;

    public ExtraLinkDialect(String charset) {
        super(&quot;ExtraLink&quot;, &quot;th&quot;, 800);
        this.charset = charset;
    }

    public Set&lt;IProcessor&gt; getProcessors(String dialectPrefix) {
        LinkedHashSet processors = new LinkedHashSet();
        processors.add(new LinkAttrProcessor(TemplateMode.HTML, 
            dialectPrefix, this.charset));
        return processors;
    }
}
</code></pre>
<p>&#xAC04;&#xB2E8;&#xD558;&#xB2E4;. &#xC0C8;&#xB85C;&#xC6B4; &#xD15C;&#xD50C;&#xB9BF;&#xC758; prefix&#xB294; <code>th</code>&#xB97C; &#xC0AC;&#xC6A9;&#xD588;&#xC9C0;&#xB9CC; &#xC6D0;&#xD558;&#xB294; &#xAC78;&#xB85C; &#xBCC0;&#xACBD;&#xD558;&#xBA74; &#xB418;&#xACE0; &#xC2E4;&#xC81C; &#xAE30;&#xB2A5;&#xB4E4;&#xC744; &#xB2F4;&#xB2F9;&#xD560; <code>Processors</code>&#xB97C; &#xCD94;&#xAC00;&#xC2DC;&#xCF1C; &#xC8FC;&#xBA74; &#xB41C;&#xB2E4;.</p>
<h3 id="linkattrprocessor-%EC%83%9D%EC%84%B1">LinkAttrProcessor &#xC0DD;&#xC131;</h3>
<p>&#xC544;&#xB798;&#xB294; Link &#xCC98;&#xB9AC;&#xB97C; &#xC704;&#xD574; &#xC2E4;&#xC81C; &#xAD6C;&#xD604;&#xD55C; <code>LinkAttrProcessor</code> &#xD074;&#xB798;&#xC2A4;&#xB2E4;. &#xC2E0;&#xADDC; Attribute&#xB97C; &#xCC98;&#xB9AC; &#xD558;&#xAE30; &#xC704;&#xD574;&#xC11C; <code>AbstractAttributeTagProcessor</code>&#xB97C; &#xC0AC;&#xC6A9;&#xD588;&#xB2E4;.</p>
<pre><code class="language-java">/**
 * Thymeleaf Extra Link Processor
 *
 * @author hkwon
 */
@Slf4j
public class LinkAttrProcessor extends AbstractAttributeTagProcessor {
    public static final int ATTR_PRECEDENCE = 1300;
    public static final String ATTR_NAME = &quot;link&quot;;
    private static final char PARAMS_START_CHAR = &apos;(&apos;;
    private static final char PARAMS_END_CHAR = &apos;)&apos;;
    private static final char EXPRESSION_END_CHAR = &apos;}&apos;;
    private static final char PARAMS_DELIMITER = &apos;,&apos;;
    private String charset;

    // &#xC0DD;&#xC131;&#xC790;
    ...

        @Override
    protected void doProcess(ITemplateContext context,
                             IProcessableElementTag tag, AttributeName attributeName,
                             String attributeValue, IElementTagStructureHandler structureHandler) {
        final RequestContext requestContext = (RequestContext)context.getVariable(SpringContextVariableNames.SPRING_REQUEST_CONTEXT);
        final LinkExpression linkExpression;
        final Object expressionResult;

        if (StringUtils.isEmptyOrWhitespace(attributeValue)) {
            expressionResult = null;
        } else {
            // Get Attribute expression
            linkExpression = (LinkExpression) StandardExpressions.getExpressionParser(context.getConfiguration()).parseExpression(context, attributeValue);

            if (linkExpression == null) {
                expressionResult = null;
            } else {
                if (requestContext.getQueryString() == null) {
                    expressionResult = linkExpression.execute(context);
                } else {
                    // Append whole request parameters to attributeValue
                    URI uri = null;
                    List&lt;NameValuePair&gt; nvp = null;

                    try {
                        uri = new URI(requestContext.getRequestUri() + &quot;?&quot; + requestContext.getQueryString());
                        nvp = URLEncodedUtils.parse(uri, Charset.forName(charset));
                    } catch (URISyntaxException e) {
                        log.error(&quot;Passed URI has not valid syntax : &quot; + uri, e);
                    }

                    // Exclude duplication query string
                    AssignationSequence assignationSequence = linkExpression.getParameters();

                    if (assignationSequence != null) {
                        for (Assignation assignation : assignationSequence) {
                            nvp.removeIf(e -&gt; assignation.getLeft().getStringRepresentation().equals(e.getName()));
                        }
                    }

                    final String parameters = nvp.stream()
                            .map(nv -&gt; nv.getName() + &quot;=${&apos;&quot; + nv.getValue() + &quot;&apos;}&quot;)
                            .collect(Collectors.joining(&quot;,&quot;));

                    final StringBuilder sb = new StringBuilder();

                    if (linkExpression.hasParameters()) {
                        // Manipulate expression string with request parameters
                        final int lastIndex = attributeValue.lastIndexOf(PARAMS_END_CHAR);

                        sb.append(attributeValue.substring(0, lastIndex))
                                .append(PARAMS_DELIMITER)
                                .append(parameters)
                                .append(attributeValue.substring(lastIndex, attributeValue.length()));

                    } else {
                        sb.append(attributeValue.substring(0, attributeValue.lastIndexOf(EXPRESSION_END_CHAR)))
                                .append(PARAMS_START_CHAR)
                                .append(parameters)
                                .append(PARAMS_END_CHAR)
                                .append(EXPRESSION_END_CHAR);
                    }

                    attributeValue = sb.toString();

                    expressionResult = EngineEventUtils.computeAttributeExpression(context, tag, attributeName, attributeValue).execute(context);
                }
            }
        }

        structureHandler.setAttribute(&quot;href&quot;, HtmlEscape.escapeHtml4Xml(expressionResult == null ? null : expressionResult.toString()));
    }
}
</code></pre>
<p>&#xD2B9;&#xBCC4;&#xD55C; &#xC124;&#xBA85;&#xC740; &#xD544;&#xC694; &#xC5C6;&#xC744; &#xAC83; &#xAC19;&#xACE0; &#xCC98;&#xB9AC;&#xB294; &#xC544;&#xB798;&#xC758; &#xC21C;&#xC11C;&#xB85C; &#xC9C4;&#xD589;&#xD588;&#xB2E4;.</p>
<ul>
<li>request&#xC5D0;&#xC11C; query string &#xC5BB;&#xC5B4;&#xC624;&#xAE30;</li>
<li>LinkExpression &#xAC80;&#xC99D;</li>
<li>LinkExpression&#xC5D0; &#xD30C;&#xB77C;&#xBBF8;&#xD130; &#xCD94;&#xAC00;</li>
<li>Expression &#xC7AC;&#xC0DD;&#xC131;</li>
<li>attribute &#xC124;&#xC815;</li>
</ul>
<p>&#xC880; &#xD574;&#xBA68;&#xB358; &#xBD80;&#xBD84;&#xC774; <code>ITemplateContext context</code>&#xC5D0;&#xC11C; Request &#xAC1D;&#xCCB4;&#xB97C; &#xC5BB;&#xC5B4;&#xC624;&#xAE30;&#xAC00; &#xC27D;&#xC9C0; &#xC54A;&#xC558;&#xB294;&#xB370; &#xC5EC;&#xAE30;&#xC800;&#xAE30; &#xB4A4;&#xC838;&#xBCF4;&#xB2C8;</p>
<pre><code class="language-java">final RequestContext requestContext = (RequestContext)context.getVariable(SpringContextVariableNames.SPRING_REQUEST_CONTEXT);
</code></pre>
<p>&#xCC98;&#xB7FC; Request &#xAC1D;&#xCCB4;&#xB97C; &#xC5BB;&#xC5B4;&#xC640;&#xC11C; list&#xC5D0; &#xB123;&#xC5B4;&#xB450;&#xACE0; &#xC2E0;&#xADDC;&#xB85C; &#xB4E4;&#xC624;&#xC5B4;&#xB294; parameter&#xAC00; &#xC788;&#xB2E4;&#xBA74; &#xB300;&#xCCB4;&#xD558;&#xC5EC; &#xB9C1;&#xD06C;&#xB97C; &#xB9CC;&#xB4E4;&#xC5B4; &#xB0B4;&#xB294; &#xB85C;&#xC9C1;&#xC744; &#xCD94;&#xAC00;&#xD588;&#xB2E4;.</p>
<p>&#xBCC4;&#xB3C4;&#xC758; expression&#xC744; &#xB9CC;&#xB4DC;&#xB294; &#xAC83;&#xC740; &#xC624;&#xBC14;&#xD558;&#xB294; &#xAC83; &#xAC19;&#xACE0; LinkExpression&#xC744; &#xAE30;&#xBCF8;&#xC801;&#xC73C;&#xB85C; &#xC0AC;&#xC6A9;&#xD558;&#xB294; &#xAC83;&#xC774; &#xB9DE;&#xC544; &#xBCF4;&#xC5EC;&#xC11C; &#xADF8;&#xB807;&#xAC8C; &#xAD6C;&#xD604;&#xC744; &#xD588;&#xACE0;,</p>
<p>&#xD45C;&#xD604;&#xC2DD; &#xC790;&#xCCB4;&#xAC00; &#xBA40;&#xD2F0; &#xD30C;&#xB77C;&#xBBF8;&#xD130;&#xB97C; @{link(param=1)(param=2)} &#xCC98;&#xB7FC; &#xC81C;&#xACF5;&#xD574;&#xC8FC;&#xC9C4; &#xC54A;&#xAE30; &#xB54C;&#xBB38;&#xC5D0; <code>)</code> &#xC5EC;&#xBD80;&#xB9CC; &#xD30C;&#xC545;&#xD558;&#xBA74; &#xB418;&#xBBC0;&#xB85C; &#xC704;&#xC640; &#xAC19;&#xC774; &#xCC98;&#xB9AC;&#xD574;&#xBCF4;&#xC558;&#xB2E4;.</p>
<h3 id="dialect-engine%EC%97%90-%EB%93%B1%EB%A1%9D">Dialect Engine&#xC5D0; &#xB4F1;&#xB85D;</h3>
<p>Spring boot &#xB97C; &#xC0AC;&#xC6A9;&#xD55C;&#xB2E4;&#xBA74; <code>IProcessorDialect</code> &#xD074;&#xB798;&#xC2A4;&#xB97C; &#xAD6C;&#xD604;&#xD55C; &#xB188;&#xC740; &#xC790;&#xB3D9;&#xC73C;&#xB85C; &#xB4F1;&#xB85D;&#xD574;&#xC8FC;&#xAE30; &#xB54C;&#xBB38;&#xC5D0; &#xBCC4;&#xB2E4;&#xB978; &#xC124;&#xC815; &#xC5C6;&#xC5B4; <code>Bean</code>&#xC744; &#xCD94;&#xAC00;&#xD574;&#xC8FC;&#xBA74; &#xB41C;&#xB2E4;.</p>
<pre><code class="language-java">@Configuration
public class ThymeleafConfig {
	@Bean
	public ExtraLinkDialect extraLinkDialect() {
		return new ExtraLinkDialect(&quot;UTF-8&quot;);
	}
}
</code></pre>
<p>&#xD639;&#xC740; <code>SpringTemplateEngine</code> &#xC0DD;&#xC131; &#xC2DC; addDialect&#xB85C; &#xCD94;&#xAC00;&#xD574; &#xC8FC;&#xBA74;&#xB41C;&#xB2E4;.</p>
<pre><code class="language-java">@Bean
public SpringTemplateEngine templateEngine() {
    SpringTemplateEngine templateEngine = new SpringTemplateEngine();

    templateEngine.setEnableSpringELCompiler(true);
    templateEngine.setTemplateResolver(templateResolver());
    templateEngine.setMessageSource(messageSource);
    templateEngine.addDialect(new LayoutDialect());
    templateEngine.addDialect(new SpringDataDialect());
    templateEngine.addDialect(new ExtraLinkDialect(&quot;UTF-8&quot;));

    return templateEngine;
}
</code></pre>
<h2 id="%EC%82%AC%EC%9A%A9%EB%B0%A9%EB%B2%95">&#xC0AC;&#xC6A9;&#xBC29;&#xBC95;</h2>
<p>&#xC0AC;&#xC6A9; &#xBC29;&#xBC95;&#xC740; &#xC544;&#xB798;&#xC640; &#xAC19;&#xB2E4;.</p>
<pre><code class="language-html">http://localhost:8080/users?pageNum=2&amp;query=&#xAC80;&#xC0C9;&#xC5B4;&amp;test=1%26encoding
</code></pre>
<p>&#xAC8C;&#xC2DC;&#xD310; &#xBAA9;&#xB85D;&#xC870;&#xD68C; url&#xC744; &#xC774;&#xB807;&#xAC8C; &#xD638;&#xCD9C;&#xD55C; &#xACBD;&#xC6B0; &#xC0C1;&#xC138;&#xC870;&#xD68C; &#xD654;&#xBA74;&#xC73C;&#xB85C; &#xAC00;&#xB294; &#xB9C1;&#xD06C;&#xB294;</p>
<pre><code class="language-html">&lt;a th:link=&quot;@{/users/__${user.userId}__}&quot; th:text=&quot;${user.userId}&quot;&gt;&#xC544;&#xC774;&#xB514;&lt;/a&gt;
</code></pre>
<p>&#xCC98;&#xB7FC; <code>th:link</code>&#xB97C; &#xC0AC;&#xC6A9;&#xD588;&#xB2E4;. &#xADF8;&#xB7FC; &#xC2E4;&#xC81C; &#xC0DD;&#xC131;&#xB418;&#xB294; link&#xB294;</p>
<pre><code class="language-html">&lt;a href=&quot;/users/hkwon?pageNum=2&amp;amp;query=%EA%B2%80%EC%83%89%EC%96%B4&amp;amp;test=1%26encoding&quot;&gt;&#xAD8C;&#xD601;&lt;/a&gt;
</code></pre>
<p>&#xCC98;&#xB7FC; &#xC0DD;&#xC131;&#xC774; &#xB41C;&#xB2E4;. &#xC0C1;&#xC138;&#xC870;&#xD68C; &#xC654;&#xB2E4;&#xAC00; &#xB2E4;&#xC2DC; &#xBAA9;&#xB85D;&#xC73C;&#xB85C; &#xC624;&#xB294; &#xACBD;&#xC6B0;&#xC5D0; &#xAC80;&#xC0C9;&#xC5B4; &#xB4F1; &#xACC4;&#xC18D; &#xB04C;&#xACE0; &#xB2E4;&#xB2D0; &#xD30C;&#xB77C;&#xBBF8;&#xD130;&#xAC00; &#xC788;&#xB294; &#xACBD;&#xC6B0; &#xC0AC;&#xC6A9;&#xD558;&#xBA74; &#xC88B;&#xB2E4;.</p>
<p>&#xD398;&#xC774;&#xC9D5; &#xCC98;&#xB9AC;&#xC2DC;&#xC5D0;&#xB3C4; pageNum &#xD30C;&#xB77C;&#xBBF8;&#xD130;&#xB97C; &#xCD94;&#xAC00;&#xB85C; &#xB118;&#xAE30;&#xBA74;</p>
<pre><code class="language-html">&lt;div th:fragment=&quot;pagination(page)&quot;&gt;
  &lt;nav aria-label=&quot;Page navigation&quot;&gt;
    &lt;ul class=&quot;pagination justify-content-center&quot;&gt;
      &lt;li class=&quot;page-item&quot; th:class=&quot;${page.getPrePage() == 0} ? &apos;disabled&apos;&quot;&gt;
        &lt;a class=&quot;page-link&quot; th:link=&quot;@{&apos;&apos;(pageNum=${page.getPrePage()})}&quot; tabindex=&quot;-1&quot; th:if=&quot;${page.getPrePage() &gt; 0}&quot;&gt;Previous&lt;/a&gt;
      &lt;/li&gt;
      &lt;li class=&quot;page-item&quot; th:each=&quot;i : ${#numbers.sequence(1, page.getPages())}&quot; th:class=&quot;${page.getPageNum() == i} ? &apos;active&apos;&quot;&gt;
        &lt;a class=&quot;page-link&quot; th:link=&quot;@{&apos;&apos;(pageNum=${i})}&quot; th:text=&quot;${i}&quot;&gt;1&lt;/a&gt;
      &lt;/li&gt;
      &lt;li class=&quot;page-item&quot; th:class=&quot;!${page.isHasNextPage()} ? &apos;disabled&apos;&quot;&gt;
        &lt;a class=&quot;page-link&quot; th:link=&quot;@{&apos;&apos;(pageNum=${page.getNextPage()})}&quot; th:if=&quot;${page.getNextPage() &gt; 0}&quot;&gt;Next&lt;/a&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/nav&gt;
&lt;/div&gt;
</code></pre>
<p>&#xC911;&#xBCF5;&#xB418;&#xB294; &#xD30C;&#xB77C;&#xBBF8;&#xD130;&#xB294;  <code>th:link=&quot;@{&apos;&apos;(pageNum=${i})}&quot;</code> &#xD45C;&#xD604;&#xC2DD;&#xC5D0; &#xB123;&#xC740; &#xAC83; &#xCC98;&#xB7FC; &#xAE30;&#xC874; &#xAC83;&#xC740; &#xC81C;&#xC678;&#xD558;&#xACE0; &#xC0DD;&#xC131;&#xB418;&#xB294;&#xAC78; &#xBCFC; &#xC218; &#xC788;&#xB2E4;.</p>
<pre><code class="language-html">&lt;nav aria-label=&quot;Page navigation&quot;&gt;
  &lt;ul class=&quot;pagination justify-content-center&quot;&gt;
    &lt;li&gt;
      &lt;a class=&quot;page-link&quot; href=&quot;?pageNum=1&quot; tabindex=&quot;-1&quot; )&gt;Previous&lt;/a&gt;
    &lt;/li&gt;
    &lt;li&gt;
      &lt;a class=&quot;page-link&quot; href=&quot;?pageNum=1&amp;amp;query=%EA%B2%80%EC%83%89%EC%96%B4&amp;amp;test=1%26encoding&quot;&gt;1&lt;/a&gt;
    &lt;/li&gt;
    &lt;li class=&quot;active&quot;&gt;
      &lt;a class=&quot;page-link&quot; href=&quot;?pageNum=2&amp;amp;query=%EA%B2%80%EC%83%89%EC%96%B4&amp;amp;test=1%26encoding&quot;&gt;2&lt;/a&gt;
    &lt;/li&gt;
    &lt;li&gt;
      &lt;a class=&quot;page-link&quot; href=&quot;?pageNum=3&amp;amp;query=%EA%B2%80%EC%83%89%EC%96%B4&amp;amp;test=1%26encoding&quot;&gt;3&lt;/a&gt;
    &lt;/li&gt;
    &lt;li&gt;
      &lt;a class=&quot;page-link&quot; href=&quot;?pageNum=4&amp;amp;query=%EA%B2%80%EC%83%89%EC%96%B4&amp;amp;test=1%26encoding&quot;&gt;4&lt;/a&gt;
    &lt;/li&gt;
    &lt;li&gt;
      &lt;a class=&quot;page-link&quot; href=&quot;?pageNum=3&quot; )&gt;Next&lt;/a&gt;
    &lt;/li&gt;
  &lt;/ul&gt;
&lt;/nav&gt;
</code></pre>
<p>&#xD655;&#xC7A5;&#xC5D0; &#xAD49;&#xC7A5;&#xD788; &#xC5F4;&#xB824;&#xC788;&#xB294; &#xC5D4;&#xC9C4;&#xC774;&#xAE30; &#xB54C;&#xBB38;&#xC5D0; &#xD544;&#xC694;&#xD55C; &#xAE30;&#xB2A5;&#xB4E4;&#xC740; &#xADF8;&#xB54C;&#xADF8;&#xB54C; &#xB9CC;&#xB4E4;&#xC5B4;&#xC11C; &#xC368;&#xB3C4; &#xBB34;&#xBC29;&#xD560; &#xAC83; &#xAC19;&#xC740; &#xB290;&#xB08C;&#xC774;&#xB2E4;.</p>
<p>&#xC804;&#xCCB4; &#xC0AC;&#xC6A9;&#xB41C; &#xC18C;&#xC2A4;&#xB294; &#xC544;&#xB798;&#xC5D0;&#xC11C; &#xD655;&#xC778;&#xD560; &#xC218; &#xC788;&#xB2E4;.</p>
<p><a href="https://github.com/hkwon77/thymeleaf-extra-link?ref=blog.hkwon.me">https://github.com/hkwon77/thymeleaf-extra-link</a></p>
<h2 id="%EC%B0%B8%EC%A1%B0">&#xCC38;&#xC870;</h2>
<ul>
<li><a href="http://www.thymeleaf.org/doc/tutorials/3.0/extendingthymeleaf.html?ref=blog.hkwon.me#processors">http://www.thymeleaf.org/doc/tutorials/3.0/extendingthymeleaf.html#processors</a></li>
<li><a href="http://www.thymeleaf.org/doc/articles/sayhelloextendingthymeleaf5minutes.html?ref=blog.hkwon.me">http://www.thymeleaf.org/doc/articles/sayhelloextendingthymeleaf5minutes.html</a></li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Spring Boot(Spring) i18n 설정 시 주의사항]]></title><description><![CDATA[<p>&#xC7A5;&#xC7A5; &#xB124;&#xC2DC;&#xAC04;(?)&#xC758; &#xC0BD;&#xC9C8; &#xD6C4;&#xC5D0; &#xD639;&#xC2DC;&#xB098; &#xB2E4;&#xB978; &#xB204;&#xAD70;&#xAC00;&#xAC00; &#xBE44;&#xC2B7;&#xD55C; &#xACE4;&#xB780;&#xD55C; &#xC0C1;&#xD669;&#xC5D0; &#xBE60;&#xC84C;&#xC744; &#xB54C; &#xB3C4;&#xC6C0;&#xC774; &#xB418;&#xAE38; &#xBC14;&#xB77C;&#xBA74;&#xC11C; &#xD3EC;&#xC2A4;&#xD2B8;&#xB97C; &#xC368;&#xBCF8;&#xB2E4;.</p>
<p>&#xC0AC;&#xB0B4;</p>]]></description><link>https://blog.hkwon.me/spring-boot-spring-i18n-configuration/</link><guid isPermaLink="false">66b1a7b306efdd000133fd94</guid><category><![CDATA[spring]]></category><category><![CDATA[spring boot]]></category><category><![CDATA[i18n]]></category><category><![CDATA[spring.messages.basename]]></category><category><![CDATA[MessageSourceAutoConfiguration]]></category><dc:creator><![CDATA[Kevin H. Kwon]]></dc:creator><pubDate>Mon, 27 Mar 2017 09:27:11 GMT</pubDate><media:content url="https://blog.hkwon.me/content/images/2024/08/hands-600497_1280.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://blog.hkwon.me/content/images/2024/08/hands-600497_1280.jpg" alt="Spring Boot(Spring) i18n &#xC124;&#xC815; &#xC2DC; &#xC8FC;&#xC758;&#xC0AC;&#xD56D;"><p>&#xC7A5;&#xC7A5; &#xB124;&#xC2DC;&#xAC04;(?)&#xC758; &#xC0BD;&#xC9C8; &#xD6C4;&#xC5D0; &#xD639;&#xC2DC;&#xB098; &#xB2E4;&#xB978; &#xB204;&#xAD70;&#xAC00;&#xAC00; &#xBE44;&#xC2B7;&#xD55C; &#xACE4;&#xB780;&#xD55C; &#xC0C1;&#xD669;&#xC5D0; &#xBE60;&#xC84C;&#xC744; &#xB54C; &#xB3C4;&#xC6C0;&#xC774; &#xB418;&#xAE38; &#xBC14;&#xB77C;&#xBA74;&#xC11C; &#xD3EC;&#xC2A4;&#xD2B8;&#xB97C; &#xC368;&#xBCF8;&#xB2E4;.</p>
<p>&#xC0AC;&#xB0B4;&#xC5D0;&#xC11C; &#xC194;&#xB8E8;&#xC158; &#xAD00;&#xB828; &#xB0B4;&#xBD80; &#xD504;&#xB85C;&#xC81D;&#xD2B8; &#xAD6C;&#xC131; &#xC911;&#xC5D0; &#xAC04;&#xB2E8;&#xD558;&#xAC8C; &#xBC30;&#xD3EC;&#xD574;&#xC57C;&#xD558;&#xB294; &#xC11C;&#xBE44;&#xC2A4; &#xAD6C;&#xC870;&#xAC00; &#xC788;&#xC5B4;&#xC11C; &#xADF8; &#xB3D9;&#xC548; &#xB208;&#xC73C;&#xB85C;&#xB9CC; &#xD6D1;&#xC5B4;&#xBD24;&#xB358; Spring Boot&#xB97C; &#xC0AC;&#xC6A9;&#xD558;&#xAE30;&#xB85C; &#xB9D8; &#xBA39;&#xACE0; &#xB808;&#xD37C;&#xB7F0;&#xC2A4; &#xBCF4;&#xBA74;&#xC11C; &#xD558;&#xB098;&#xC529; &#xBD99;&#xC5EC;&#xB098;&#xAC00;&#xB294; &#xB3C4;&#xC911;&#xC5D0; &#xC608;&#xAE30;&#xCE58; &#xC54A;&#xAC8C; i18n &#xAD6C;&#xC131; &#xC911;&#xC5D0; &#xBA54;&#xC2DC;&#xC9C0; &#xD30C;&#xC77C;&#xC744; &#xACC4;&#xC18D; &#xBABB; &#xBD88;&#xB7EC;&#xC624;&#xB294; &#xBD88;&#xC0C1;&#xC0AC;&#xAC00; &#xC77C;&#xC5B4;&#xB0AC;&#xB2E4;.</p>
<h2 id="%EA%B2%B0%EB%A1%A0%EB%B6%80%ED%84%B0-%EB%A7%90%ED%95%98%EC%9E%90%EB%A9%B4">&#xACB0;&#xB860;&#xBD80;&#xD130; &#xB9D0;&#xD558;&#xC790;&#xBA74;..</h2>
<p>&#xACB0;&#xB860;&#xC801;&#xC73C;&#xB85C; &#xB9D0;&#xD558;&#xC790;&#xBA74; messages &#xD30C;&#xC77C;&#xC758; &#xC774;&#xB984;&#xC5D0; <code>.</code> &#xC774; &#xB4E4;&#xC5B4;&#xAC00;&#xBA74; &#xB85C;&#xB529;&#xC774; &#xC548;&#xB41C;&#xB2E4;.</p>
<h2 id="%EB%B9%84%EA%B7%B9%EC%9D%98-%EC%8B%9C%EC%9E%91">&#xBE44;&#xADF9;&#xC758; &#xC2DC;&#xC791;</h2>
<p>&#xB808;&#xD37C;&#xB7F0;&#xC2A4;&#xB97C; &#xBCF4;&#xBA74;&#xC11C; &#xCC28;&#xADFC;&#xD788; &#xD558;&#xB77C;&#xB294; &#xB370;&#xB85C; &#xC2DC;&#xC791;&#xD588;&#xB2E4;.</p>
<pre><code class="language-yaml">spring:
  messages:
    always-use-message-format: false
    cache-seconds: -1
    basename: i18n/message, i18n/error.message # &#xC774; &#xBD80;&#xBD84;
    encoding: UTF-8
</code></pre>
<p>&#xB808;&#xD37C;&#xB7F0;&#xC2A4;&#xC5D0; &#xB530;&#xB974;&#xBA74; Spring Boot&#xC758; <code>MessageSourceAutoConfiguration</code>&#xC744; &#xC0AC;&#xC6A9;&#xD55C; <code>INTERNATIONALIZATION</code> &#xC124;&#xC815;&#xC740; &#xC544;&#xB798;&#xC640; &#xAC19;&#xC774; &#xC9C4;&#xD589;&#xD560; &#xC218; &#xC788;&#xB2E4;.</p>
<pre><code class="language-property"># INTERNATIONALIZATION (MessageSourceAutoConfiguration)
spring.messages.always-use-message-format=false # Set whether to always apply the MessageFormat rules, parsing even messages without arguments.
spring.messages.basename=messages # Comma-separated list of basenames, each following the ResourceBundle convention.
spring.messages.cache-seconds=-1 # Loaded resource bundle files cache expiration, in seconds. When set to -1, bundles are cached forever.
spring.messages.encoding=UTF-8 # Message bundles encoding.
spring.messages.fallback-to-system-locale=true # Set whether to fall back to the system Locale if no files for a specific Locale have been found.
</code></pre>
<p>message &#xD30C;&#xC77C;&#xC744; &#xD558;&#xB098;&#xB85C; &#xAC00;&#xC838;&#xAC00;&#xC9C0; &#xC54A;&#xACE0; &#xC5EC;&#xB7EC;&#xAC1C; &#xC0AC;&#xC6A9;&#xD560; &#xACBD;&#xC6B0; <code>comma</code>&#xB85C; &#xAD6C;&#xBD84;&#xD574;&#xC11C; &#xB2E4;&#xC218;&#xC758; basename&#xC744; &#xC124;&#xC815;&#xD558;&#xC5EC; &#xC0AC;&#xC6A9;&#xD560; &#xC218; &#xC788;&#xB2E4;.</p>
<p>&#xD574;&#xC11C; &#xC704; yaml &#xC124;&#xC815; &#xCC98;&#xB7FC; &#xB2F9;&#xB2F9;&#xD558;&#xAC8C; <code>i18n/error.message</code>&#xC744; &#xCD94;&#xAC00;&#xD558;&#xC600;&#xB2E4;.</p>
<pre><code class="language-yaml">    basename: i18n/message, i18n/error.message
</code></pre>
<p>&#xC8FD;&#xC5B4;&#xB3C4; &#xD30C;&#xC77C; &#xB85C;&#xB529;&#xC744; &#xBABB;&#xD558;&#xB294; &#xAC83;&#xC774;&#xB2E4;. --debug &#xC124;&#xC815;&#xC744; &#xAC78;&#xC5B4;&#xB3C4; &#xD56D;&#xC0C1; &#xB9E8; &#xC55E;&#xC5D0; &#xC788;&#xB294; basename&#xB9CC; &#xC77D;&#xC5B4;&#xC624;&#xB294; &#xAC83; &#xCC98;&#xB7FC; &#xBCF4;&#xC778;&#xB2E4;.</p>
<pre><code class="language-bash">   MessageSourceAutoConfiguration matched:
      - ResourceBundle found bundle URL [file:/C:/app/workspace/xstream-portal/src/main/resources/i18n/message.properties] (MessageSourceAutoConfiguration.ResourceBundleCondition)
      - @ConditionalOnMissingBean (types: org.springframework.context.MessageSource; SearchStrategy: current) did not find any beans (OnBeanCondition)
</code></pre>
<p><code>WebMvcConfigurerAdapter</code> &#xC73C;&#xB85C; &#xC124;&#xC815;&#xC774; &#xCD94;&#xAC00;&#xB418;&#xBA74; &#xD639;&#xC5EC;&#xB098; <code>MessageSourceAutoConfiguration</code>&#xC774; &#xBB34;&#xC2DC;&#xB418;&#xACE0;  &#xBB38;&#xC81C;&#xAC00; &#xB418;&#xB294; &#xAC83;&#xC778;&#xAC00;?</p>
<p>&#xD639;&#xC2DC;&#xB098; &#xD574;&#xC11C; AutoConfiguration &#xBB38;&#xC81C;&#xC778;&#xAC00; &#xD574;&#xC11C; MessageSourceAutoConfiguration&#xC744; exclude&#xD558;&#xACE0; &#xC9C1;&#xC811; &#xC544;&#xB798;&#xCC98;&#xB7FC; &#xC124;&#xC815;&#xD574;&#xBD10;&#xB3C4;</p>
<pre><code class="language-java">@EnableAutoConfiguration(exclude = {MessageSourceAutoConfiguration.class})
...
@Value(&quot;${spring.messages.basename}&quot;)
String messagesBasename = null
...
@Bean
public ReloadableResourceBundleMessageSource messageSource(){
   ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
   messageSource.setBasenames(messagesBasename.split(&quot;,&quot;));
   messageSource.setDefaultEncoding(messagesEncoding);
   messageSource.setCacheSeconds(messagesCacheSeconds);

   return messageSource;
}
</code></pre>
<p>&#xC5EC;&#xC804;&#xD788; &#xBABB;&#xBD88;&#xB7EC;&#xC624;&#xACE0; basename&#xC758; convention &#xBB38;&#xC81C;&#xC778;&#xAC00; &#xD574;&#xC11C; &#xC544;&#xB798;&#xCC98;&#xB7FC; &#xB2E4; &#xD574;&#xBD10;&#xB3C4;..</p>
<pre><code class="language-yaml">spring:
  messages:
    basename: i18n/message, i18n/error.message
    basename: classpath:i18n/message, classpath:i18n/error.message
    basename: classpath:/i18n/message, classpath:/i18n/error.message
    basename: classpath*:i18n/message, classpath*:i18n/error.message
    basename: classpath*:/i18n/message, classpath*:/i18n/error.message
</code></pre>
<p>&#xC5EC;&#xC804;&#xD788; &#xBABB;&#xBD88;&#xB7EC;&#xC624;&#xB294; &#xAC83;&#xC774;&#xB2E4; &#x314E;&#x314E;&#x314E;&#x314E;&#x314E;&#x314E;&#x314E;&#x314E; &#xC774;&#xCBE4;&#xB418;&#xBA74; &#xC815;&#xC2E0;&#xC774; &#xD63C;&#xB780;&#xD574;&#xC9C0;&#xACE0; &#xAD6C;&#xAE00;&#xC740; &#xB354; &#xC774;&#xC0C1; &#xC870;&#xB825;&#xC790;&#xAC00; &#xB418;&#xC9C0; &#xC54A;&#xB294; &#xC0C1;&#xD669;&#xC774; &#xBC1C;&#xC0DD;&#xD55C;&#xB2E4;.</p>
<p>&#xC544;&#xC608; &#xCC98;&#xC74C;&#xBD80;&#xD130; &#xB2E4;&#xC2DC; &#xC2DC;&#xC791;&#xD574;&#xBD10;&#xB3C4;. &#xC798;&#xB418;&#xC5B4; &#xC788;&#xB294; sample &#xD504;&#xB85C;&#xC81D;&#xD2B8;&#xB974; &#xBC1B;&#xC544;&#xC11C; &#xBCC0;&#xACBD;&#xD574;&#xBD10;&#xB3C4;.. &#xC548;&#xB41C;&#xB2E4;..</p>
<p>&#xB9C8;&#xC74C;&#xC744; &#xB2E4;&#xC2DC; &#xD55C;&#xBC88; &#xAC00;&#xB2E4;&#xB4EC;&#xACE0;.. &#xADFC;&#xB370;.. &#xC124;&#xB9C8;.. &#xD639;&#xC2DC;&#xB098; &#xD574;&#xC11C; &#xAD00;&#xB828;&#xB41C; &#xC18C;&#xC2A4;&#xB97C; &#xAE4C;&#xBCF4;&#xAE30; &#xC2DC;&#xC791;&#xD558;&#xB2C8;..</p>
<pre><code class="language-java">final String resourceName = toResourceName(bundleName, &quot;properties&quot;);
</code></pre>
<p><a href="https://github.com/spring-projects/spring-framework/blob/master/spring-context/src/main/java/org/springframework/context/support/ResourceBundleMessageSource.java?ref=blog.hkwon.me">ResourceBundleMessageSource</a>&#xC5D0;&#xC11C; Bundle &#xD30C;&#xC77C; &#xC0DD;&#xC131; &#xC2DC; toResourceName &#xBA54;&#xC18C;&#xB4DC;&#xAC00; &#xD638;&#xCD9C;&#xB41C;&#xB2E4;. &#xB530;&#xB77C;&#xAC00;&#xBCF4;&#xB2C8;...</p>
<pre><code class="language-java">public final String toResourceName(String arg0, String arg1) {
    StringBuilder arg2 = new StringBuilder(arg0.length() + 1 + arg1.length());
    arg2.append(arg0.replace(&apos;.&apos;, &apos;/&apos;)).append(&apos;.&apos;).append(arg1);
    return arg2.toString();
}
</code></pre>
<p><strong>&#xC263;!!</strong> <code>.</code>&#xC744; path &#xAD6C;&#xBD84;&#xC790;&#xB85C; &#xBCC0;&#xD658;&#xD55C;&#xB2E4; &#x3160;&#x3160;&#x3160;&#x3160;&#x3160;&#x3160;</p>
<p>&#xB9C8;&#xC74C;&#xC744; &#xAC00;&#xB2E4; &#xB4EC;&#xACE0; <code>.</code>&#xC774; &#xB4E4;&#xC5B4;&#xAC00;&#xC9C0; &#xC54A;&#xB294; basename&#xC73C;&#xB85C; &#xBCC0;&#xACBD;&#xD558;&#xB2C8; &#xC798; &#xC548;&#xB2E4;. &#xC544;&#xC8FC; &#xC798; &#xC77D;&#xC5B4;&#xC628;&#xB2E4;.</p>
<pre><code class="language-yaml">spring:
  messages:
    basename: i18n/message, i18n/error, # &#xC5F4;&#xBC1B;&#xC544;&#xC11C; &#xC0BC;&#xC2ED;&#xAC1C; &#xC815;&#xB3C4; &#xB354; &#xBD99;&#xC5EC;&#xBD24;&#xB294;&#xB370; &#xC798; &#xB41C;&#xB2E4; &#x314B;&#x314B;&#x314B;
</code></pre>
<pre><code class="language-bash">&#x2514;&#x2500;&#x2500; resources
    &#x251C;&#x2500;&#x2500; application.yml
    &#x251C;&#x2500;&#x2500; banner.txt
    &#x251C;&#x2500;&#x2500; i18n
    &#x2502;&#xA0;&#xA0; &#x251C;&#x2500;&#x2500; error.properties
    &#x2502;&#xA0;&#xA0; &#x251C;&#x2500;&#x2500; error_ko_KR.properties
    &#x2502;&#xA0;&#xA0; &#x251C;&#x2500;&#x2500; message.properties
    &#x2502;&#xA0;&#xA0; &#x2514;&#x2500;&#x2500; message_ko_KR.properties
    &#x251C;&#x2500;&#x2500; logback-spring.xml
    ....
</code></pre>
<h2 id="i18n-%EC%84%A4%EC%A0%95-%EC%8B%9C-%EC%A3%BC%EC%9D%98%EC%82%AC%ED%95%AD">i18n &#xC124;&#xC815; &#xC2DC; &#xC8FC;&#xC758;&#xC0AC;&#xD56D;</h2>
<ul>
<li>basename&#xC758; resource &#xC774;&#xB984;&#xC5D0;&#xB294; <code>.</code>&#xB97C; &#xB123;&#xC9C0; &#xC54A;&#xB294;&#xB2E4;. &#xC55E;&#xC73C;&#xB85C; &#xB2E4;&#xB978; &#xD30C;&#xC77C; &#xB9CC;&#xB4E4;&#xB54C;&#xB3C4; &#xC548; &#xB123;&#xC744; &#xAC83; &#xAC19;&#xB2E4;. &#x315C;&#x315C;</li>
<li>Spring&#xACFC; Spring Boot&#xC758; <code>basename</code> Convention&#xC740; &#xC57D;&#xAC04; &#xC0C1;&#xC774;&#xD558;&#xB2E4;. <code>classpath</code> <code>prefix</code>&#xAC00; &#xBD99;&#xC9C0; &#xC54A;&#xB294;&#xB2E4;.</li>
<li>&#xC704;&#xCC98;&#xB7FC; &#xC544;&#xBB34; &#xB0B4;&#xC6A9;&#xC774; &#xC5C6;&#xB354;&#xB77C;&#xACE0; basename.properties &#xD30C;&#xC77C;&#xC744; &#xC0DD;&#xC131;&#xD55C;&#xB2E4;.</li>
<li>--debug &#xC635;&#xC158;&#xC758; autoconfiguration report&#xB294; &#xBAA8;&#xB4E0; &#xC815;&#xBCF4;&#xAC00; &#xB2E4; &#xB098;&#xC624;&#xC9C0; &#xC54A;&#xB294;&#xB2E4;.</li>
<li>&#xC0BD;&#xC9C8;&#xD558;&#xC9C0; &#xB9D0;&#xACE0; &#xC548;&#xB420;&#xB54C;&#xB294; &#xAE30;&#xBCF8;&#xBD80;&#xD130; &#xCC9C;&#xCC9C;&#xD788;..</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[VirtualBox 호스트 전용 어댑터 설정]]></title><description><![CDATA[<p>&#xB098;&#xC774;&#xAC00; &#xB4E4;&#xC5B4;&#xAC00;&#xB2C8; &#xB9E4;&#xBC88; <code>vm</code> &#xB9CC;&#xB4E4; &#xB54C;&#xB9C8;&#xB2E4; &#xC5BC;&#xB9C8; &#xB418;&#xC9C0; &#xC54A;&#xB294; &#xC774; &#xB0B4;&#xC6A9;&#xC744; &#xAC80;&#xC0C9;&#xD574;&#xC11C; &#xCC3E;&#xC744;&#xB824;&#xB2C8; &#xC8FD;&#xC744;&#xB9DB;&#xC774;&#xB77C; &#x314E;&#x314E;</p>
<p>&#xADF8;&#xB0E5; &#xCC3E;&#xAE30;&#xB77C;&#xB3C4; &#xD3B8;&#xD558;&#xAC8C; &#xBE14;</p>]]></description><link>https://blog.hkwon.me/virtualbox-hoseuteu-jeonyong-eodaebteo-seoljeong-2/</link><guid isPermaLink="false">66b1a7b306efdd000133fd93</guid><dc:creator><![CDATA[Kevin H. Kwon]]></dc:creator><pubDate>Fri, 17 Mar 2017 09:12:35 GMT</pubDate><content:encoded><![CDATA[<p>&#xB098;&#xC774;&#xAC00; &#xB4E4;&#xC5B4;&#xAC00;&#xB2C8; &#xB9E4;&#xBC88; <code>vm</code> &#xB9CC;&#xB4E4; &#xB54C;&#xB9C8;&#xB2E4; &#xC5BC;&#xB9C8; &#xB418;&#xC9C0; &#xC54A;&#xB294; &#xC774; &#xB0B4;&#xC6A9;&#xC744; &#xAC80;&#xC0C9;&#xD574;&#xC11C; &#xCC3E;&#xC744;&#xB824;&#xB2C8; &#xC8FD;&#xC744;&#xB9DB;&#xC774;&#xB77C; &#x314E;&#x314E;</p>
<p>&#xADF8;&#xB0E5; &#xCC3E;&#xAE30;&#xB77C;&#xB3C4; &#xD3B8;&#xD558;&#xAC8C; &#xBE14;&#xB85C;&#xADF8;&#xC5D0; &#xAE30;&#xB85D;&#xD574;&#xBCF8;&#xB2E4;.</p>
<p><code>VirtualBox</code>&#xC5D0;&#xC11C; &#xAE30;&#xBCF8;&#xC73C;&#xB85C; <code>vm</code>&#xC744; &#xC124;&#xCE58;&#xD558;&#xBA74; NAT &#xB124;&#xD2B8;&#xC6CC;&#xD06C;&#xB85C; &#xC5F0;&#xACB0;&#xC774; &#xB418;&#xC11C; &#xADF8;&#xB0E5; ssh client&#xB85C; &#xC811;&#xC18D;&#xD558;&#xB294;&#xB370; &#xAF64; &#xBD88;&#xD3B8;&#xD558;&#xB2E4;.</p>
<p>&#xD638;&#xC2A4;&#xD2B8; &#xC804;&#xC6A9; &#xC5B4;&#xD0ED;&#xD130; &#xC124;&#xC815;&#xC744; &#xD1B5;&#xD574; &#xB0B4;&#xBD80; &#xACE0;&#xC815; IP&#xB85C; &#xC138;&#xD305;&#xD558;&#xB294; &#xBC29;&#xBC95;&#xC744; &#xAE30;&#xC220;&#xD574;&#xBCF8;&#xB2E4;.</p>
<p>Windows &#xAE30;&#xC900;&#xC774;&#xC9C0;&#xB9CC; mac&#xB3C4; &#xAC70;&#xC758; &#xB3D9;&#xC77C;&#xD558;&#xB2E4;.</p>
<h2 id="virtualbox-%ED%99%98%EA%B2%BD%EC%84%A4%EC%A0%95%EC%97%90%EC%84%9C-%EC%96%B4%EB%8C%91%ED%84%B0-%EC%B6%94%EA%B0%80">VirtualBox &#xD658;&#xACBD;&#xC124;&#xC815;&#xC5D0;&#xC11C; &#xC5B4;&#xB311;&#xD130; &#xCD94;&#xAC00;</h2>
<p>VirtualBox- &#xD30C;&#xC77C; - &#xD658;&#xACBD;&#xC124;&#xC815; - &#xB124;&#xD2B8;&#xC6CC;&#xD06C; - &#xD638;&#xC2A4;&#xD2B8; &#xC804;&#xC6A9; &#xB124;&#xD2B8;&#xC6CC;&#xD06C; &#xBA54;&#xB274;&#xC5D0;&#xC11C;</p>
<p>&#xD638;&#xC2A4;&#xD2B8; &#xC804;&#xC6A9; &#xC5B4;&#xB311;&#xD130;&#xB97C; + &#xBC84;&#xD2BC;&#xC73C;&#xB85C; &#xC2E0;&#xADDC; &#xD638;&#xC2A4;&#xD2B8; &#xC804;&#xC6A9; &#xC5B4;&#xB311;&#xD130;&#xB97C; &#xC0DD;&#xC131;&#xD55C;&#xB2E4;.</p>
<p><img src="https://blog.hkwon.me/content/images/2024/08/1-3.png" alt loading="lazy"></p>
<p>&#xD3B8;&#xC9D1;&#xC744; &#xD074;&#xB9AD;&#xD558;&#xC5EC; &#xC544;&#xB798;&#xC640; &#xAC19;&#xC774; IP &#xC8FC;&#xC18C;&#xB97C; &#xD655;&#xC778;&#xD55C;&#xB2E4;.</p>
<p>&#xC608;&#xC81C;&#xB294; <code>192.168.253.1</code> &#xC778; &#xAC83;&#xC744; &#xBCFC; &#xC218; &#xC788;&#xB2E4;.</p>
<p><img src="https://blog.hkwon.me/content/images/2024/08/2-3.png" alt loading="lazy"></p>
<p>&#xB610; DHCP &#xAE30;&#xB2A5;&#xC740; &#xC0AC;&#xC6A9;&#xD558;&#xC9C0; &#xC54A;&#xC73C;&#xBBC0;&#xB85C; &#xCCB4;&#xD06C;&#xB418;&#xC9C0; &#xC54A;&#xB294; &#xAC83;&#xC744; &#xD655;&#xC778;&#xD55C;&#xB2E4;.</p>
<p><img src="https://blog.hkwon.me/content/images/2024/08/3-2.png" alt loading="lazy"></p>
<h2 id="vm-%EC%84%A4%EC%A0%95%EC%97%90%EC%84%9C-%EC%96%B4%EB%8C%91%ED%84%B0-%EC%B6%94%EA%B0%80">VM &#xC124;&#xC815;&#xC5D0;&#xC11C; &#xC5B4;&#xB311;&#xD130; &#xCD94;&#xAC00;</h2>
<p>VM&#xC124;&#xC815;&#xC5D0;&#xC11C; &#xD658;&#xACBD;&#xC124;&#xC815;&#xC5D0;&#xC11C; &#xCD94;&#xAC00;&#xD55C; &#xC5B4;&#xB311;&#xD130;&#xB97C; &#xCD94;&#xAC00;&#xD55C;&#xB2E4;. VM&#xC774; &#xC885;&#xB8CC;&#xB41C; &#xC0C1;&#xD0DC;&#xC5D0;&#xC11C; &#xC791;&#xC5C5;&#xC744; &#xC9C4;&#xD589;&#xD574;&#xC57C; &#xD55C;&#xB2E4;.</p>
<p><img src="https://blog.hkwon.me/content/images/2024/08/4-1.png" alt loading="lazy"></p>
<p>&#xC5B4;&#xB311;&#xD130;2&#xBC88;&#xC5D0; &#xC2E0;&#xADDC;&#xB85C; &#xCD94;&#xAC00;&#xD55C; <code>#2</code>&#xBC88; &#xC758; &#xD638;&#xC2A4;&#xD2B8; &#xC804;&#xC6A9; &#xC5B4;&#xB311;&#xD130;&#xB97C; &#xCD94;&#xAC00;&#xD55C;&#xB2E4;.</p>
<p><img src="https://blog.hkwon.me/content/images/2024/08/5-1.png" alt loading="lazy"></p>
<p>GUEST OS&#xB97C; &#xC2DC;&#xC791;&#xD55C;&#xB2E4;.</p>
<h2 id="guest-os-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC-%EC%84%A4%EC%A0%95">GUEST OS &#xB124;&#xD2B8;&#xC6CC;&#xD06C; &#xC124;&#xC815;</h2>
<p>ifconfig&#xC73C;&#xB85C; &#xD604;&#xC7AC; &#xC5B4;&#xB311;&#xD130; &#xC815;&#xBCF4;&#xB97C; &#xD655;&#xC778;&#xD574;&#xBCF8;&#xB2E4;.</p>
<pre><code class="language-bash">$ ifconfig -a
enp0s3    Link encap:Ethernet  HWaddr 08:00:27:ec:8e:1c  
          inet addr:10.0.2.15  Bcast:10.0.2.255  Mask:255.255.255.0
          inet6 addr: fe80::a00:27ff:feec:8e1c/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:6 errors:0 dropped:0 overruns:0 frame:0
          TX packets:56 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:1596 (1.5 KB)  TX bytes:7105 (7.1 KB)

enp0s8    Link encap:Ethernet  HWaddr 08:00:27:86:ed:d1  
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:10303 (0.0 KB)  TX bytes:0 (0.0 KB)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:164 errors:0 dropped:0 overruns:0 frame:0
          TX packets:164 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1 
          RX bytes:12080 (12.0 KB)  TX bytes:12080 (12.0 KB)

</code></pre>
<p><code>enp0s3</code> &#xB85C; &#xD604;&#xC7AC; nat &#xC5B4;&#xB311;&#xD130;&#xB85C; &#xAD6C;&#xC131;&#xC774; &#xB418;&#xC5B4; &#xC788;&#xACE0; &#xC2E0;&#xADDC;&#xB85C; <code>enp0s8</code> &#xC5B4;&#xB311;&#xD130;&#xC5D0; &#xB300;&#xD574;&#xC11C; &#xD638;&#xC2A4;&#xD2B8; &#xC804;&#xC6A9; &#xB124;&#xD2B8;&#xC6CC;&#xD06C;&#xB97C; &#xC124;&#xC815;&#xD55C;&#xB2E4;.</p>
<pre><code class="language-bash">$ sudo vi /etc/network/interfaces
# This file describes the network interfaces available on your system
# and how to activate them. For more information, see interfaces(5).

source /etc/network/interfaces.d/*

# The loopback network interface
auto lo
iface lo inet loopback

# The primary network interface
auto enp0s3
iface enp0s3 inet dhcp

# The host-only network interface &#xC2E0;&#xADDC;&#xB85C; &#xCD94;&#xAC00;
auto enp0s8
iface enp0s8 inet static
address 192.168.253.101
netmask 255.255.255.0
network 192.168.253.0
</code></pre>
<p>&#xC124;&#xC815;&#xC774; &#xC644;&#xB8CC; &#xB410;&#xC73C;&#xBA74; <code>network service</code>&#xB97C; &#xC7AC;&#xC2DC;&#xC791;&#xD55C;&#xB2E4;.</p>
<pre><code class="language-bash">$ sudo systemctl restart networking
or
$ sudo /etc/init.d/networking restart
</code></pre>
<p>&#xC124;&#xC815;&#xC774; &#xC644;&#xB8CC;&#xB410;&#xC73C;&#xBA74; <code>host OS</code>&#xC5D0;&#xC11C; <code>ping</code>&#xC744; &#xB0A0;&#xB824;&#xBCF4;&#xBA74;</p>
<pre><code class="language-bash">C:\Users\hkwon&gt;ping 192.168.253.101

Ping 192.168.253.101 32&#xBC14;&#xC774;&#xD2B8; &#xB370;&#xC774;&#xD130; &#xC0AC;&#xC6A9;:
192.168.253.101&#xC758; &#xC751;&#xB2F5;: &#xBC14;&#xC774;&#xD2B8;=32 &#xC2DC;&#xAC04;&lt;1ms TTL=64
192.168.253.101&#xC758; &#xC751;&#xB2F5;: &#xBC14;&#xC774;&#xD2B8;=32 &#xC2DC;&#xAC04;&lt;1ms TTL=64
192.168.253.101&#xC758; &#xC751;&#xB2F5;: &#xBC14;&#xC774;&#xD2B8;=32 &#xC2DC;&#xAC04;&lt;1ms TTL=64
192.168.253.101&#xC758; &#xC751;&#xB2F5;: &#xBC14;&#xC774;&#xD2B8;=32 &#xC2DC;&#xAC04;&lt;1ms TTL=64

192.168.253.101&#xC5D0; &#xB300;&#xD55C; Ping &#xD1B5;&#xACC4;:
    &#xD328;&#xD0B7;: &#xBCF4;&#xB0C4; = 4, &#xBC1B;&#xC74C; = 4, &#xC190;&#xC2E4; = 0 (0% &#xC190;&#xC2E4;),
&#xC655;&#xBCF5; &#xC2DC;&#xAC04;(&#xBC00;&#xB9AC;&#xCD08;):
    &#xCD5C;&#xC18C; = 0ms, &#xCD5C;&#xB300; = 0ms, &#xD3C9;&#xADE0; = 0ms
</code></pre>
<p>ssh &#xD074;&#xB77C;&#xC774;&#xC5B8;&#xD2B8;&#xB85C; &#xC811;&#xC18D; &#xD574;&#xC11C; &#xC774;&#xC81C; &#xC791;&#xC5C5;&#xD558;&#xBA74; &#xB41C;&#xB2E4;~</p>
<p>&#xC774;&#xC0C1;!</p>
]]></content:encoded></item><item><title><![CDATA[Slack Subversion Intergration 한글 코멘트 사용하기]]></title><description><![CDATA[<p><code>Slack</code>&#xC744; &#xB0B4;&#xAC00; &#xD22C;&#xC785;&#xB418;&#xB294; &#xD300;&#xB9C8;&#xB2E4; &#xC0AC;&#xC6A9;&#xD55C;&#xC9C0;&#xAC00; &#xAF64; &#xB418;&#xC5C8;&#xB2E4;.</p>
<p>&#xD2B9;&#xD788;&#xB098; CI&#xC11C;&#xBC84;&#xC758; Job &#xC0C1;&#xD0DC;&#xB098; &#xD615;&#xC0C1;&#xAD00;&#xB9AC; &#xC11C;&#xBC84;&#xC758; commit notification&#xC744; slack app&#xAE30;&#xB2A5;&#xC73C;&#xB85C; &#xBC1B;&#xB294;&#xAC74;</p>]]></description><link>https://blog.hkwon.me/slack-subversion-intergration/</link><guid isPermaLink="false">66b1a7b306efdd000133fd92</guid><category><![CDATA[slack]]></category><category><![CDATA[subversion]]></category><category><![CDATA[integration]]></category><category><![CDATA[hook]]></category><category><![CDATA[svn hook]]></category><dc:creator><![CDATA[Kevin H. Kwon]]></dc:creator><pubDate>Tue, 17 Jan 2017 11:53:36 GMT</pubDate><content:encoded><![CDATA[<p><code>Slack</code>&#xC744; &#xB0B4;&#xAC00; &#xD22C;&#xC785;&#xB418;&#xB294; &#xD300;&#xB9C8;&#xB2E4; &#xC0AC;&#xC6A9;&#xD55C;&#xC9C0;&#xAC00; &#xAF64; &#xB418;&#xC5C8;&#xB2E4;.</p>
<p>&#xD2B9;&#xD788;&#xB098; CI&#xC11C;&#xBC84;&#xC758; Job &#xC0C1;&#xD0DC;&#xB098; &#xD615;&#xC0C1;&#xAD00;&#xB9AC; &#xC11C;&#xBC84;&#xC758; commit notification&#xC744; slack app&#xAE30;&#xB2A5;&#xC73C;&#xB85C; &#xBC1B;&#xB294;&#xAC74; &#xAF64;&#xB098; &#xC720;&#xC6A9;&#xD558;&#xB2E4;.(&#xBE4C;&#xB4DC; &#xAE68;&#xC9C4;&#xAC70; &#xBC8C;&#xAE08; &#xB9E4;&#xAE38;&#xB54C; &#xCC38; &#xC88B;&#xB2E4; &#x314E;&#x314E;)</p>
<p>&#xC694;&#xC0CC; &#xD615;&#xC0C1;&#xAD00;&#xB9AC;&#xC11C;&#xBC84;&#xB85C; Git&#xC744; &#xB9CE;&#xC774; &#xC0AC;&#xC6A9;&#xD55C;&#xB2E4;&#xC9C0;&#xB9CC; &#xC544;&#xC9C1; SI&#xCABD;&#xC5D0;&#xC11C;&#xB294; SVN&#xC774; &#xC8FC;&#xB97C; &#xC774;&#xB8E8;&#xACE0; &#xC788;&#xB2E4;.</p>
<p>&#xCC3E;&#xC544;&#xBCF4;&#xB2C8; &#xB9CE;&#xC740; &#xC608;&#xC81C;&#xB4E4;&#xC774; github, gitlab&#xC774;&#xB098; bitbucket &#xC124;&#xC815;&#xD558;&#xB294; &#xAC74; &#xC790;&#xC138;&#xD558;&#xAC8C; &#xB3C4;&#xC6C0;&#xB9D0;&#xC774; &#xB9CE;&#xC740;&#xB370; subversion &#xC124;&#xC815; &#xC608;&#xC81C;&#xB294; &#xC5C4;&#xCCAD; &#xAC04;&#xB2E8;&#xD558;&#xAE34; &#xD558;&#xC9C0;&#xB9CC; &#xD55C;&#xAE00; &#xCF54;&#xBA58;&#xD2B8;&#xAC00; &#xC798;&#xB098;&#xC624;&#xAC8C; &#xC124;&#xC815;&#xD558;&#xB824;&#xBA74; &#xC544;&#xC8FC; &#xC57D;&#xAC04;&#xC758; &#xC218;&#xC815;&#xC774; &#xD544;&#xC694;&#xD558;&#xB2E4;.</p>
<h2 id="slack-subversion-intergration-%EC%84%A4%EC%A0%95">Slack Subversion Intergration &#xC124;&#xC815;</h2>
<p><code>Slack</code>&#xC5D0;&#xC11C;&#xC758; &#xC124;&#xC815;&#xC740; &#xB9E4;&#xC6B0; &#xAC04;&#xB2E8;&#xD558;&#xB2E4;.</p>
<p><code>App Directory</code> &#xBA54;&#xB274;&#xC5D0;&#xC11C; <code>Subversion</code> &#xC744; &#xC120;&#xD0DD;&#xD558;&#xBA74; &#xB05D;;;</p>
<p>Hook&#xC5D0; &#xC0AC;&#xC6A9;&#xB420; <code>Token</code> &#xAC12;&#xACFC; <code>SVN post-commit handler</code> &#xC0D8;&#xD50C;&#xB9CC; &#xAC00;&#xC838;&#xB2E4; &#xC0AC;&#xC6A9;&#xD558;&#xBA74; &#xB41C;&#xB2E4;.</p>
<p><img src="https://blog.hkwon.me/content/images/2024/08/1-4.png" alt loading="lazy"></p>
<h2 id="subversion-hook-%EC%84%A4%EC%A0%95">Subversion hook &#xC124;&#xC815;</h2>
<p>Subversion Hook&#xC740; &#xB9CC;&#xB4E4;&#xC5B4;&#xB454; &#xB808;&#xD30C;&#xC9C0;&#xD1A0;&#xB9AC;&#xC5D0; &#xC774;&#xBCA4;&#xD2B8;&#xAC00; &#xBC1C;&#xC0DD; &#xD588;&#xC744; &#xACBD;&#xC6B0; &#xC120;/&#xD6C4;&#xCC98;&#xB9AC;&#xB97C; &#xC704;&#xD574; &#xC81C;&#xACF5;&#xB41C;&#xB2E4;.</p>
<p><code>comment</code>&#xB97C; &#xC785;&#xB825;&#xD558;&#xC9C0; &#xC54A;&#xAC70;&#xB098; &#xC774;&#xC288;&#xD2B8;&#xB798;&#xCEE4; &#xBC88;&#xD638; &#xC5C6;&#xC73C;&#xBA74; <code>commit</code>&#xC774; &#xBD88;&#xAC00;&#xB2A5;&#xD558;&#xAC8C; &#xD558;&#xAC70;&#xB098; &#xD558;&#xB294; &#xB4F1;&#xC758; &#xC791;&#xC5C5;&#xC744;  &#xCD94;&#xAC00;&#xD558;&#xB294;&#xB370; &#xB9CE;&#xC774;&#xB4E4; &#xC0AC;&#xC6A9;&#xD558;&#xACE0;, Slack Notification&#xB3C4; &#xC774;&#xC640; &#xAC19;&#xC740; hook&#xC744; &#xC0AC;&#xC6A9;&#xD574;&#xC11C; slack&#xC5D0; notification&#xC774; &#xB420; &#xC218; &#xC788;&#xAC8C; &#xC791;&#xC5C5;&#xD560; &#xC218; &#xC788;&#xB2E4;.</p>
<p>Hook &#xC2A4;&#xD06C;&#xB9BD;&#xD2B8;&#xB294; &#xC11C;&#xBC84;&#xC5D0;&#xC11C; &#xC2E4;&#xD589;&#xC774; &#xB420; &#xC218; &#xC788;&#xB294; &#xC2A4;&#xD06C;&#xB9BD;&#xD2B8;&#xB294; &#xAC70;&#xC758; &#xB2E4; &#xC9C0;&#xC6D0;&#xB41C;&#xB2E4;. (php, perl, shell, &#xAE30;&#xD0C0;&#xB4F1;&#xB4F1;)</p>
<p>&#xADF8;&#xB9AC;&#xACE0; &#xB9E8; &#xC704; &#xADF8;&#xB9BC;&#xC5D0;&#xB3C4; &#xBCF4;&#xC774;&#xC9C0;&#xB9CC; &#xAC10;&#xC0AC;&#xD558;&#xAC8C;&#xB3C4; &#xC0D8;&#xD50C;&#xB85C; <a href="https://github.com/tinyspeck/services-examples/blob/master/subversion.pl?ref=blog.hkwon.me">&#xD384;&#xC2A4;&#xD06C;&#xB9BD;&#xD2B8; &#xC608;&#xC81C;</a>&#xB97C; &#xAC19;&#xC774; &#xC81C;&#xACF5;&#xD574; &#xC8FC;&#xACE0; &#xC788;&#xB2E4;.</p>
<p>&#xB2E4;&#xB9CC; &#xC544;&#xC26C;&#xC6E0;&#xB358;&#xAC74; &#xC5EC;&#xC804;&#xD788; &#xC601;&#xC5B4;&#xAD8C; &#xC774;&#xC678;&#xC758; &#xAD6D;&#xAC00;&#xB4E4;&#xC740; &#xBCC4; &#xC2E0;&#xACBD;&#xC744; &#xC548;&#xC368;&#xC900;&#xB2E4;&#xB294;&#xAC70;.. &#xD55C;&#xAE00;&#xC774; &#xB4E4;&#xC5B4;&#xAC04; <code>comment</code>&#xB4E4;&#xC740; &#xC8C4;&#xB2E4; &#xC720;&#xB2C8;&#xCF54;&#xB4DC;&#xB85C; &#xB098;&#xC628;&#xB2E4;.</p>
<p><img src="https://blog.hkwon.me/content/images/2024/08/2-4.png" alt="alt" loading="lazy"></p>
<p>&#xD384;&#xC2A4;&#xD06C;&#xB9BD;&#xD2B8;&#xB294; &#xB9CC;&#xB4E4;&#xC5B4; &#xBCF8;&#xC801;&#xC774; &#xC5C6;&#xC9C0;&#xB9CC; &#xAC04;&#xB2E8;&#xD558;&#xAC8C; &#xC11C;&#xCE6D;&#xD574;&#xBCF4;&#xB2C8; &#xC870;&#xAE08;&#xB9CC; &#xC190;&#xBCF4;&#xBA74; &#xD55C;&#xAE00;&#xB3C4; &#xC798; &#xB098;&#xC628;&#xB2E4; :)</p>
<p>&#xC774;&#xC81C; &#xC138;&#xD305;&#xC744; &#xC2DC;&#xC791;&#xD574;&#xBCF4;&#xBA74;~</p>
<p>&#xC11C;&#xBC84;&#xC5D0;&#xC11C; &#xB808;&#xD30C;&#xC9C0;&#xD1A0;&#xB9AC;&#xB97C; &#xC0DD;&#xC131;&#xD558;&#xBA74; <code>root directory</code>&#xC5D0; <code>hook</code>&#xC774;&#xB77C;&#xB294; &#xB514;&#xB809;&#xD1A0;&#xB9AC;&#xAC00; &#xC874;&#xC7AC;&#xD55C;&#xB2E4;.</p>
<p>&#xAE30;&#xBCF8;&#xC801;&#xC73C;&#xB85C; &#xC544;&#xB798;&#xC640; &#xAC19;&#xC774; &#xBA87;&#xAC00;&#xC9C0; &#xD15C;&#xD50C;&#xB9BF;&#xB3C4; &#xC81C;&#xACF5;&#xD55C;&#xB2E4;.</p>
<pre><code class="language-bash">$ ls -al /repository_path/hooks
post-commit.tmpl
post-lock.tmpl
post-revprop-change.tmpl
post-unlock.tmpl
pre-commit.tmpl
pre-lock.tmpl
pre-revprop-change.tmpl
pre-unlock.tmpl
start-commit.tmpl
pre-commit &lt;-- &#xC2E0;&#xADDC;&#xB85C; &#xCD94;&#xAC00;
</code></pre>
<p><code>commit</code> &#xC774; &#xB418;&#xBA74; slack&#xC5D0; notification&#xC774; &#xAC00;&#xBA74; &#xB418;&#xBBC0;&#xB85C; &#xD574;&#xB2F9; <code>hooks</code> &#xB514;&#xB809;&#xD1A0;&#xB9AC;&#xC5D0;  <code>post-commit</code> &#xD30C;&#xC77C;&#xC744; &#xD384;&#xC2A4;&#xD06C;&#xB9BD;&#xD2B8; &#xC608;&#xC81C; &#xD30C;&#xC77C;&#xB85C; &#xB9CC;&#xB4E4;&#xBA74; &#xB41C;&#xB2E4;. (&#xD655;&#xC7A5;&#xC790;&#xB294; &#xC5C6;&#xC774; &#xB9CC;&#xB4E4;&#xBA74;&#xB41C;&#xB2E4;.)</p>
<pre><code class="language-perl">#!/usr/bin/perl


# Copyright 2013 Tiny Speck, Inc
#
# Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.


#
# An SVN post-commit handler for posting to Slack. Setup the channel and get the token
# from your team&apos;s services page. Change the options below to reflect your team&apos;s settings.
#
# Requires these perl modules:
# HTTP::Request
# LWP::UserAgent
# JSON


# Submits the following post to the slack servers

# POST https: //foo.slack.com/services/hooks/subversion?token=xxxxxx
# Content-Type: application/x-www-form-urlencoded
# Host: foo.slack.com
# Content-Length: 101
#
# payload=%7B%22revision%22%3A1%2C%22url%22%3A%22http%3A%2F%2Fsvnserver%22%2C%22author%22%3A%22digiguru%22%2C%22log%22%3A%22Log%20info%22%7D

#
# I am not a perl programmer. Beware.
#

use warnings;
use strict;

use HTTP::Request::Common qw(POST);
use HTTP::Status qw(is_client_error);
use LWP::UserAgent;
use JSON;
# &#xD55C;&#xAE00; &#xC0AC;&#xC6A9;&#xC744; &#xC704;&#xD574; &#xCD94;&#xAC00;
use Encode qw(decode_utf8);


#
# Customizable vars. Set these to the information for your team
#

my $opt_domain = &quot;team.slack.com&quot;; # Your team&apos;s domain
my $opt_token = &quot;&#xD1A0;&#xD070;&#xAC12;&quot;; # The token from your SVN services page


#
# this script gets called by the SVN post-commit handler
# with these args:
#
# [0] path to repo
# [1] revision committed
#
# we need to find out what happened in that revision and then act on it
#

# &#xD55C;&#xAE00; &#xC0AC;&#xC6A9;&#xC744; &#xC704;&#xD574; &#xBCC0;&#xACBD;
my $log = qx|export LC_ALL=&quot;ko_KR.UTF-8&quot;; /usr/bin/svnlook log -r $ARGV[1] $ARGV[0]|;
$log = decode_utf8($log);
#my $log = `/usr/bin/svnlook log -r $ARGV[1] $ARGV[0]`;
my $files = `/usr/bin/svnlook changed -r $ARGV[1] $ARGV[0]`;
my $who = `/usr/bin/svnlook author -r $ARGV[1] $ARGV[0]`;
my $url = &quot;http://svn.dev/repos/kcx/?op=revision&amp;rev=$ARGV[1]&quot;; # optionally set this to the url of your internal commit browser. Ex: http://svnserver/wsvn/main/?op=revision&amp;rev=$ARGV[1]
chomp $who;

my $payload = {
	&apos;revision&apos;	=&gt; $files.&apos;[&apos;.$ARGV[1].&apos;]&apos;,
	&apos;url&apos;		=&gt; $url,
	&apos;author&apos;	=&gt; $who,
	&apos;log&apos;		=&gt; $log,
};

my $ua = LWP::UserAgent-&gt;new;
$ua-&gt;timeout(15);

my $req = POST( &quot;https://${opt_domain}/services/hooks/subversion?token=${opt_token}&quot;, [&apos;payload&apos; =&gt; encode_json($payload)] );
my $s = $req-&gt;as_string;
print STDERR &quot;Request:\n$s\n&quot;;

my $resp = $ua-&gt;request($req);
$s = $resp-&gt;as_string;
print STDERR &quot;Response:\n$s\n&quot;;
</code></pre>
<p>perl &#xBAA8;&#xB4C8;&#xC774; &#xAE30;&#xBCF8;&#xC801;&#xC73C;&#xB85C; &#xC124;&#xCE58;&#xAC00; &#xC548;&#xB418;&#xC788;&#xB2E4;&#xBA74; &#xAC04;&#xB2E8;&#xD558;&#xAC8C; &#xC124;&#xCE58; &#xAC00;&#xB2A5;&#xD558;&#xB2E4;. (ubuntu &#xAE30;&#xC900;)</p>
<pre><code class="language-bash">$ sudo apt-get install libjson-perl
</code></pre>
<p>&#xC790; &#xC774;&#xC81C; &#xC138;&#xD305;&#xC740; &#xC644;&#xB8CC; &#xB410;&#xC73C;&#xB2C8; &#xAC04;&#xB2E8;&#xD558;&#xAC8C; <code>commit</code> &#xC744; &#xB0A0;&#xB824;&#xBCF4;&#xBA74;</p>
<p><img src="https://blog.hkwon.me/content/images/2024/08/3-3.png" alt="alt" loading="lazy"></p>
<p>&#xC774;&#xB807;&#xAC8C; subversion &#xCC44;&#xB110;&#xC5D0; commit &#xB418;&#xBA74; &#xD55C;&#xAE00; comment&#xB3C4; &#xC81C;&#xB300;&#xB85C; notification&#xC744; &#xBC1B;&#xC744; &#xC218; &#xC788;&#xB2E4;.</p>
<p>&#xD574;&#xB2F9; &#xC608;&#xC81C;&#xB294; unix &#xC11C;&#xBC84; &#xAE30;&#xBC18;&#xC758; svn server&#xB9CC; &#xC801;&#xC6A9; &#xAC00;&#xB2A5;&#xD558;&#xACE0;</p>
<p><code>visualsvn</code>&#xC744; &#xC0AC;&#xC6A9;&#xD55C;&#xB2E4;&#xBA74; <a href="https://github.com/robertmiles3/svn-slack-notifier?ref=blog.hkwon.me">svn-slack-notifier</a>&#xB97C; &#xBE44;&#xC2B7;&#xD55C; &#xBC29;&#xBC95;&#xC73C;&#xB85C; &#xC0AC;&#xC6A9;&#xD558;&#xBA74; &#xB41C;&#xB2E4;.</p>
]]></content:encoded></item><item><title><![CDATA[Gradle Test task 로깅 설정하기]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>TDD&#xC758; &#xB9F9;&#xC2E0;&#xC790;&#xB294; &#xC544;&#xB2C8;&#xC9C0;&#xB9CC; &#xBCF4;&#xD1B5; &#xAC1C;&#xBC1C;&#xC744; &#xC9C4;&#xD589;&#xD560; &#xB54C; &#xD14C;&#xC2A4;&#xD2B8; &#xCF00;&#xC774;&#xC2A4;&#xB97C; &#xBA3C;&#xC800; &#xB9CC;&#xB4E4;&#xBA74;&#xC11C; &#xCF54;&#xB529;&#xD558;&#xB290;&#xB77C; &#xB514;&#xBC84;&#xAE45;&#xC744; &#xD14C;&#xC2A4;&#xD2B8; &#xCF00;&#xC774;&#xC2A4;&#xB85C; &#xB9CE;&#xC774;</p>]]></description><link>https://blog.hkwon.me/gradle-test-task-logging/</link><guid isPermaLink="false">66b1a7b306efdd000133fd91</guid><category><![CDATA[gradle]]></category><category><![CDATA[test]]></category><category><![CDATA[logging]]></category><category><![CDATA[log]]></category><dc:creator><![CDATA[Kevin H. Kwon]]></dc:creator><pubDate>Tue, 29 Nov 2016 06:27:48 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>TDD&#xC758; &#xB9F9;&#xC2E0;&#xC790;&#xB294; &#xC544;&#xB2C8;&#xC9C0;&#xB9CC; &#xBCF4;&#xD1B5; &#xAC1C;&#xBC1C;&#xC744; &#xC9C4;&#xD589;&#xD560; &#xB54C; &#xD14C;&#xC2A4;&#xD2B8; &#xCF00;&#xC774;&#xC2A4;&#xB97C; &#xBA3C;&#xC800; &#xB9CC;&#xB4E4;&#xBA74;&#xC11C; &#xCF54;&#xB529;&#xD558;&#xB290;&#xB77C; &#xB514;&#xBC84;&#xAE45;&#xC744; &#xD14C;&#xC2A4;&#xD2B8; &#xCF00;&#xC774;&#xC2A4;&#xB85C; &#xB9CE;&#xC774; &#xD558;&#xB294; &#xD3B8;&#xC778;&#xB370; Gradle <code>test</code> &#xD0DC;&#xC2A4;&#xD06C;&#xB294; &#xAE30;&#xBCF8;&#xC801;&#xC73C;&#xB85C; console &#xB85C;&#xAE45;&#xC774; disable&#xB41C; &#xCC44;&#xB85C; &#xAD6C;&#xB3D9;&#xB41C;&#xB2E4;.</p>
<p>&#xAC1C;&#xBC1C;&#xC2DC;&#xC5D0;&#xB294; stacktrace&#xB97C; &#xC0C1;&#xC138;&#xD558;&#xAC8C; &#xBCFC; &#xD544;&#xC694;&#xB3C4; &#xC788;&#xB294;&#xB370; &#xC544;&#xB798; &#xC124;&#xC815;&#xC744; &#xD1B5;&#xD574; &#xBCFC; &#xC218; &#xC788;&#xB2E4;.</p>
<p>Gradle reference&#xB294; &#xC798;&#xB418;&#xC5B4; &#xC788;&#xB294; &#xB4EF; &#xC798; &#xC548;&#xB418;&#xC5B4; &#xC788;&#xB294;(?) &#xBB54;&#xAC00; &#xD558;&#xB098;&#xC529; &#xBE60;&#xC838; &#xC788;&#xB294; &#xB290;&#xB08C;&#xC774;&#xB784;&#xAE4C;..</p>
<p>&#xAE30;&#xBCF8;&#xAC12;&#xC774; &#xC5B4;&#xB5A4;&#xAC12;&#xC73C;&#xB85C; &#xB418;&#xC5B4; &#xC788;&#xB2E4;&#xB358;&#xC9C0; &#xC5B4;&#xB5A4; &#xAC12;&#xC774; &#xC801;&#xC808;&#xD558;&#xAC8C; &#xB4E4;&#xC5B4;&#xAC00;&#xB294;&#xC9C0; &#xC0C1;&#xC138;&#xD558;&#xAC8C; &#xC548;&#xB098;&#xC640; &#xC788;&#xB294; &#xACBD;&#xC6B0;&#xAC00; &#xC880; &#xC788;&#xB294; &#xD3B8;&#xC778;&#xAC70; &#xAC19;&#xB2E4;.</p>
<h2 id="testtask">Test task &#xB85C;&#xAE45; &#xC124;&#xC815;</h2>
<pre><code class="language-groovy">test {
    testLogging {
        // test jvm&#xC758; standard out and standard error&#xC744; console&#xC5D0; &#xCD9C;&#xB825;&#xD55C;&#xB2E4;.
        showStandardStreams = true
        showCauses = true
        showExceptions = true
        showStackTraces = true
        exceptionFormat = &apos;full&apos;
    }
}
</code></pre>
<h2 id="testloggingproperty">&#xCC38;&#xACE0; TestLogging Property</h2>
<table>
<thead>
<tr>
<th style="width:250px">Property</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td style="font-weight:bold">displayGranularity</td>
<td>&#xB85C;&#xADF8;&#xB85C; &#xAE30;&#xB85D;&#xB418;&#xB294; &#xC774;&#xBCA4;&#xD2B8;&#xC758; &#xD45C;&#xC2DC; &#xB2E8;&#xC704;.<br>&quot;0&quot;&#xC73C;&#xB85C; &#xC138;&#xD305;&#xD560; &#xB54C; &#xBA54;&#xC18C;&#xB4DC; &#xB2E8;&#xC704; &#xC774;&#xBCA4;&#xD2B8;&#xB294; &quot;Test Run &gt; Test Worker x &gt; org.SomeClass &gt; org.someMethod&quot;&#xB85C; &#xD45C;&#xC2DC;&#xB41C;&#xB2E4;.<br> &quot;2&quot;&#xB85C; &#xC138;&#xD305;&#xD558;&#xBA74; &#xAC19;&#xC740; &#xC774;&#xBCA4;&#xD2B8;&#xB294; &quot;org.someClass &gt; org.someMethod&quot;&#xB85C; &#xD45C;&#xC2DC;&#xB41C;&#xB2E4;.</td>
</tr>
<tr>
<td style="font-weight:bold">events</td>
<td>&#xB85C;&#xAE45;&#xB420; &#xC774;&#xBCA4;&#xD2B8;.<br><a href="https://docs.gradle.org/current/javadoc/org/gradle/api/tasks/testing/logging/TestLogEvent.html?ref=blog.hkwon.me">TestLogEvent</a> (FAILED, PASSED, SKIPPED, STANDARD_ERROR, STANDARD_OUT, STARTED)</td>
</tr>
<tr>
<td style="font-weight:bold">exceptionFormat</td>
<td>showStackTrace&#xAC00; true &#xC5EC;&#xC57C;&#xB9CC; &#xD65C;&#xC131;&#xD654;<br>&#xB85C;&#xAE45;&#xD558;&#xB824;&#xB294; test exception &#xD3EC;&#xB9F7;<br><a href="https://docs.gradle.org/current/javadoc/org/gradle/api/tasks/testing/logging/TestExceptionFormat.html?ref=blog.hkwon.me">TestExceptionFormat</a>(FULL, SHORT)</td>
</tr>
<tr>
<td style="font-weight:bold">maxGranularity</td>
<td>&#xB85C;&#xAE45;&#xB418;&#xB294; &#xC774;&#xBCA4;&#xD2B8; &#xD45C;&#xC2DC;&#xBC29;&#xC2DD;(max)<br>&quot;0&quot; test&#xB97C; &#xC218;&#xD589;&#xD558;&#xB294; gradle test suite &#xC804;&#xCCB4;<br>&quot;1&quot; test&#xAC00; &#xC218;&#xD589;&#xB418;&#xB294; &#xAC01; test JVM &#xC815;&#xBCF4;<br>&quot;2&quot; &#xD14C;&#xC2A4;&#xD2B8; &#xD074;&#xB798;&#xC2A4;<br>&quot;3&quot; &#xD14C;&#xC2A4;&#xD2B8; &#xBA54;&#xC18C;&#xB4DC;. </td>
</tr>
<tr>
<td style="font-weight:bold">minGranularity</td>
<td>maxGranularity &#xC640; &#xB3D9;&#xC77C;</td>
</tr>
<tr>
<td style="font-weight:bold">showCauses</td>
<td>showException&#xAC00; true&#xC5EC;&#xC57C;&#xB9CC; &#xD65C;&#xC131;&#xD654;<br>&#xD14C;&#xC2A4;&#xD2B8; &#xC218;&#xD589; &#xC2DC; exception&#xC774; &#xBC1C;&#xC0DD; &#xD588;&#xC744; &#xB54C; causes &#xC815;&#xBCF4;&#xB97C; &#xBCF4;&#xC5EC;&#xC900;&#xB2E4;.</td>
</tr>
<tr>
<td style="font-weight:bold">showExceptions</td>	
<td>&#xD14C;&#xC2A4;&#xD2B8; &#xC218;&#xD589; &#xC2DC; exception&#xC774; &#xBC1C;&#xC0DD; &#xD588;&#xC744; &#xB54C; exception&#xC815;&#xBCF4;&#xB97C; &#xB85C;&#xAE45;&#xD55C;&#xB2E4;. &#xBCF4;&#xD1B5; &quot;Failed&quot; &#xC774;&#xBCA4;&#xD2B8; &#xBC1C;&#xC0DD; &#xC2DC; &#xC218;&#xD589;&#xD55C;&#xB2E4;.</td>
</tr>
<tr>
<td style="font-weight:bold">showStackTraces</td>	
<td>&#xD14C;&#xC2A4;&#xD2B8; &#xC218;&#xD589; &#xC2DC; exception&#xC774; &#xBC1C;&#xC0DD; &#xD588;&#xC744; &#xB54C; showStackTraces&#xC815;&#xBCF4;&#xB97C; &#xBCF4;&#xC5EC;&#xC900;&#xB2E4;.</td>
</tr>
<tr>
<td style="font-weight:bold">showStandardStreams</td>	
<td>standard out, standard error &#xB97C; &#xB85C;&#xAE45;&#xD55C;&#xB2E4;.</td>
</tr>
<tr>
<td style="font-weight:bold">stackTraceFilters</td>	
<td>test stack trace &#xC815;&#xBCF4;&#xB97C; filter&#xB97C; &#xD1B5;&#xD574; &#xC815;&#xC81C;&#xD55C;&#xB2E4;.<br><a href="https://docs.gradle.org/current/javadoc/org/gradle/api/tasks/testing/logging/TestStackTraceFilter.html?ref=blog.hkwon.me">TestStackTraceFilter</a>&#xB97C; &#xC0AC;&#xC6A9;</td>
</tr>
</tbody>
</table>
<h2 id="reference">Reference</h2>
<p><a href="https://docs.gradle.org/current/dsl/org.gradle.api.tasks.testing.logging.TestLogging.html?ref=blog.hkwon.me">https://docs.gradle.org/current/dsl/org.gradle.api.tasks.testing.logging.TestLogging.html</a></p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[SI프로젝트 빅뱅 오픈 왜 이렇게 항상 힘드나]]></title><description><![CDATA[<p>&#xAC70;&#xC758; 1&#xB144;&#xC744; &#xB2EC;&#xB824;&#xC628; &#xD504;&#xB85C;&#xC81D;&#xD2B8;&#xAC00; &#xC800;&#xBC88;&#xC8FC; &#xAE08;&#xC694;&#xC77C;&#xC744; &#xAE30;&#xC810;&#xC73C;&#xB85C; &#xC624;&#xD508;&#xD558;&#xBA74;&#xC11C; &#xC548;&#xC815;&#xD654; &#xB2E8;&#xACC4;&#xC5D0; &#xC811;&#xC5B4;&#xB4E4;&#xACE0; &#xC788;&#xB2E4;.</p>
<p>&#xB355;&#xBD84;&#xC5D0; &#xC694; &#xBA87;&#xB2EC;&#xAC04; &#xBE14;&#xB85C;</p>]]></description><link>https://blog.hkwon.me/si-bigbang-open/</link><guid isPermaLink="false">66b1a7b306efdd000133fd90</guid><category><![CDATA[SI]]></category><category><![CDATA[PROJECT MANAGEMENT]]></category><dc:creator><![CDATA[Kevin H. Kwon]]></dc:creator><pubDate>Thu, 08 Sep 2016 11:27:02 GMT</pubDate><media:content url="https://blog.hkwon.me/content/images/2024/08/project.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://blog.hkwon.me/content/images/2024/08/project.jpg" alt="SI&#xD504;&#xB85C;&#xC81D;&#xD2B8; &#xBE45;&#xBC45; &#xC624;&#xD508; &#xC65C; &#xC774;&#xB807;&#xAC8C; &#xD56D;&#xC0C1; &#xD798;&#xB4DC;&#xB098;"><p>&#xAC70;&#xC758; 1&#xB144;&#xC744; &#xB2EC;&#xB824;&#xC628; &#xD504;&#xB85C;&#xC81D;&#xD2B8;&#xAC00; &#xC800;&#xBC88;&#xC8FC; &#xAE08;&#xC694;&#xC77C;&#xC744; &#xAE30;&#xC810;&#xC73C;&#xB85C; &#xC624;&#xD508;&#xD558;&#xBA74;&#xC11C; &#xC548;&#xC815;&#xD654; &#xB2E8;&#xACC4;&#xC5D0; &#xC811;&#xC5B4;&#xB4E4;&#xACE0; &#xC788;&#xB2E4;.</p>
<p>&#xB355;&#xBD84;&#xC5D0; &#xC694; &#xBA87;&#xB2EC;&#xAC04; &#xBE14;&#xB85C;&#xADF8;&#xBA70; &#xC2A4;&#xD130;&#xB514;&#xBA70; &#xAC1C;&#xC778;&#xC0DD;&#xD65C;&#xC774;&#xAC74; &#xB610; &#xB4B7;&#xC804;&#xC774; &#xB418;&#xBC84;&#xB9AC;&#xB294; &#xC0C1;&#xD669;&#xC774; &#xBC8C;&#xC5B4;&#xC9C0;&#xACE0; &#xB9D0;&#xC558;&#xB2E4;.</p>
<p>SI&#xC0DD;&#xD65C;&#xC744; 15&#xB144; &#xAC00;&#xAE4C;&#xC774; &#xD574;&#xC624;&#xBA74;&#xC11C; &#xD504;&#xB85C;&#xC81D;&#xD2B8; &#xADDC;&#xBAA8;&#xAC00; &#xCEE4;&#xC9C0;&#xBA74; &#xCEE4;&#xC9C8;&#xC218;&#xB85D; &#xC624;&#xD508;&#xC774; &#xAC00;&#xAE4C;&#xC640;&#xC9C0;&#xBA74; &#xAC00;&#xAE4C;&#xC640; &#xC9C8;&#xC218;&#xB85D; &#xC57C;&#xADFC;&#xB3C4; &#xB9CE;&#xC544;&#xC9C0;&#xACE0; , &#xBA39;&#xB294; &#xC695;&#xB3C4; &#xB9CE;&#xC544;&#xC9C0;&#xACE0;.. &#xC6B4;&#xB3D9;&#xC740; &#xC5F4;&#xC2EC;&#xD788; &#xD55C;&#xB2E4;&#xACE0;&#xB294; &#xD558;&#xB294;&#xB370; &#xCCB4;&#xB825;&#xB3C4; &#xC608;&#xC804; &#xAC19;&#xC9C0; &#xC54A;&#xC740;&#xC9C0; &#xBAB8;&#xB3C4; &#xB9C8;&#xC74C;&#xB3C4; &#xB354;&#xC6B1;&#xB354; &#xC9C0;&#xCCD0; &#xB9CC; &#xAC04;&#xB2E4;.</p>
<p>&#xD574;&#xB97C; &#xB354;&#xD574; &#xAC08;&#xC218;&#xB85D; &#xC65C; &#xC624;&#xD508;&#xC740; &#xB354; &#xD798;&#xB4E4;&#xC5B4; &#xB9CC; &#xC9C0;&#xB294;&#xAC78;&#xAE4C;.. &#xAC1C;&#xC120;&#xC758; &#xC5EC;&#xC9C0;&#xB294; &#xC9C4;&#xC9DC; &#xC5C6;&#xB294;&#xAC83;&#xC778;&#xAC00;?</p>
<h2 id="%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EB%A7%89%EB%B0%94%EC%A7%80-%EB%8F%84%EB%8C%80%EC%B2%B4-%EC%99%9C-%EC%9D%B4%EB%A0%87%EA%B2%8C-%ED%9E%98%EB%93%A0%EA%B1%B8%EA%B9%8C">&#xD504;&#xB85C;&#xC81D;&#xD2B8; &#xB9C9;&#xBC14;&#xC9C0; &#xB3C4;&#xB300;&#xCCB4; &#xC65C; &#xC774;&#xB807;&#xAC8C; &#xD798;&#xB4E0;&#xAC78;&#xAE4C;</h2>
<div style="text-align:center;margin-bottom:20px;">
![&#xB534;&#xC0B0;](/content/images/2016/08/blog-1156232365.jpg)
</div>
<p>&#xADF8;&#xAC04; &#xB0B4;&#xAC00; &#xC9C1;&#xC811; &#xC218;&#xD589;&#xD558;&#xAC70;&#xB098; &#xC9C0;&#xCF1C;&#xBD10;&#xC654;&#xB358; &#xD504;&#xB85C;&#xC81D;&#xD2B8;&#xB97C; &#xB3CC;&#xC774;&#xCF1C;&#xBCF4;&#xBA74;, &#xC815;&#xB9D0; &#xB9C9;&#xD310;&#xC5D0; &#xAC1C;&#xBC1C;&#xC790;&#xB4E4;&#xB07C;&#xB9AC; &#xC544;&#xB984;&#xB2E4;&#xC6B4; <strong>Double&#xC695;</strong>&#xC774; &#xC624;&#xACE0;&#xAC00;&#xB294; &#xBE44;&#xCC38;&#xD55C; &#xD504;&#xB85C;&#xC81D;&#xD2B8;&#xBD80;&#xD130; &#xBAA9;&#xD45C; &#xD588;&#xB358; &#xACE0;&#xC9C0;&#xB294; <strong>&#xD55C;&#xB77C;&#xC0B0;</strong>&#xC778;&#xB370; <strong>&#xB2EC;&#xB098;&#xB77C;</strong>&#xAE4C;&#xC9C0; &#xAC00;&#xC57C;&#xD558;&#xB294; &#xC218; &#xC5C6;&#xC774; &#xC2E4;&#xD328;&#xB418;&#xAC70;&#xB098;, &#xB9E5;&#xBE60;&#xC9C0;&#xB294; &#xD504;&#xB85C;&#xC81D;&#xD2B8;&#xB4E4;, &#xBAA8;&#xB450; <strong>&#xAD11;&#xC778;</strong>&#xC774; &#xB418;&#xC5B4; &#xB9C8;&#xCE58; &#xC601;&#xD654; &#xB9E4;&#xB4DC;&#xB9E5;&#xC2A4;&#xC758; &#xAD11;&#xD65C;&#xD55C; &#xC0AC;&#xB9C9;&#xC5D0;&#xC11C; &#xC11C;&#xB85C; &#xC8FD;&#xACE0; &#xC8FD;&#xC774;&#xAE30;&#xB97C; &#xBC18;&#xBCF5;&#xD558;&#xBA70; &#xB204;&#xAC00; &#xC545;&#xC774;&#xBA70; &#xB204;&#xAC00; &#xC120;&#xC778;&#xC9C0;&#xB294; &#xC911;&#xC694;&#xD558;&#xC9C0; &#xC54A;&#xB294; &#xB124;&#xBC84; &#xC5D4;&#xB529;&#xC758; &#xBBF8;&#xCE5C; &#xD504;&#xB85C;&#xC81D;&#xD2B8; &#xB4E4;&#xAE4C;&#xC9C0; &#xC218; &#xC5C6;&#xC774; &#xB9CE;&#xC740; &#xD504;&#xB85C;&#xC81D;&#xD2B8;&#xB97C; &#xC9C0;&#xCF1C;&#xBD10; &#xC654;&#xC9C0;&#xB9CC;.. (&#xBB3C;&#xB860; &#xB0B4;&#xAC00; &#xC218;&#xD589;&#xD55C; &#xD504;&#xB85C;&#xC81D;&#xD2B8;&#xB294; &#xC774;&#xC815;&#xB3C4; &#xAE09;&#xC740; &#xC544;&#xB2C8;&#xC5C8;&#xB2E4; ^^;)</p>
<p>&#xC774;&#xB7EC;&#xD55C; &#xC2E4;&#xD328;&#xB41C; &#xD504;&#xB85C;&#xC81D;&#xD2B8; &#xB4E4;&#xC758; &#xB300;&#xD45C;&#xC801;&#xC778; &#xC2E4;&#xD328; &#xC694;&#xC778;&#xC744; &#xAC1C;&#xC778;&#xC801;&#xC73C;&#xB85C; &#xBD84;&#xC11D;&#xD574; &#xBCF4;&#xBA74; &#xB2E4;&#xC74C;&#xACFC; &#xAC19;&#xB2E4;&#xACE0; &#xC0DD;&#xAC01; &#xB41C;&#xB2E4;.</p>
<ul>
<li>&#xCC98;&#xC74C;&#xBD80;&#xD130; &#xC798;&#xBABB;&#xB41C; &#xB9CC;&#xB0A8;(&#xACC4;&#xC57D;)</li>
<li>&#xC694;&#xAD6C;&#xC0AC;&#xD56D;&#xC758; &#xB04A;&#xC784; &#xC5C6;&#xB294; &#xBCC0;&#xACBD;</li>
<li>&#xAC1C;&#xBC1C;&#xBC29;&#xBC95;&#xB860; &#xC120;&#xC815;&#xC758; &#xBB38;&#xC81C;</li>
<li>&#xB0B4;&#xBD80; &#xAC08;&#xB4F1;, &#xB9AC;&#xB354;&#xC27D;&#xC758; &#xBD80;&#xC7AC;</li>
<li>&#xC81C;&#xB300;&#xB85C;&#xB41C; &#xC544;&#xD0A4;&#xD14D;&#xCC98;, &#xAC1C;&#xBC1C;&#xC2A4;&#xD0AC;&#xC758; &#xBD80;&#xC7AC;</li>
<li>&#xACE0;&#xAC1D;&#xACFC;&#xC758; &#xAD00;&#xACC4;(&#xC815;&#xCE58;)</li>
<li>&#xC678;&#xBD80;&#xC694;&#xC778; (&#xBC95;&#xC774;&#xB098; &#xC81C;&#xC57D;, &#xADDC;&#xC81C; &#xB4F1;&#xC758; &#xBCC0;&#xACBD;)</li>
<li>...</li>
</ul>
<p>&#xC5EC;&#xAE30;&#xC5D0; &#xBB34;&#xC5C7;&#xBCF4;&#xB2E4; &#xC774; &#xC5EC;&#xB7EC;&#xAC00;&#xC9C0; &#xBB38;&#xC81C;&#xC810; &#xB4E4;&#xC5D0;&#xC11C; &#xACF5;&#xD1B5;&#xC801;&#xC73C;&#xB85C; &#xC5EE;&#xC5EC; &#xC788;&#xB294; &#xAC00;&#xC7A5; &#xD070; &#xBB38;&#xC81C;&#xC810;&#xC740; &#xBC14;&#xB85C; ==<strong>&#xC81C;&#xB300;&#xB85C;&#xB41C; &#xCEE4;&#xBBA4;&#xB2C8;&#xCF00;&#xC774;&#xC158;&#xC758; &#xBD80;&#xC7AC;</strong>==&#xAC00; &#xC544;&#xB2D0;&#xAE4C; &#xD55C;&#xB2E4;.</p>
<h3 id="%EC%B2%98%EC%9D%8C%EB%B6%80%ED%84%B0-%EC%9E%98%EB%AA%BB%EB%90%9C-%EB%A7%8C%EB%82%A8%EA%B3%84%EC%95%BD-%EC%9A%94%EA%B5%AC%EC%82%AC%ED%95%AD%EC%9D%98-%EB%81%8A%EC%9E%84-%EC%97%86%EB%8A%94-%EB%B3%80%EA%B2%BD">&#xCC98;&#xC74C;&#xBD80;&#xD130; &#xC798;&#xBABB;&#xB41C; &#xB9CC;&#xB0A8;(&#xACC4;&#xC57D;), &#xC694;&#xAD6C;&#xC0AC;&#xD56D;&#xC758; &#xB04A;&#xC784; &#xC5C6;&#xB294; &#xBCC0;&#xACBD;</h3>
<p>&#xADF8;&#xB807;&#xB2E4;! &#xB09C; &#xB108;&#xC640; &#xB9CC;&#xB098;&#xC9C0; &#xB9D0;&#xC544;&#xC57C; &#xD588;&#xC5B4;... &#xB9DD;&#xD558;&#xB294; &#xD504;&#xB85C;&#xC81D;&#xD2B8;&#xC758; &#xC804;&#xD615;&#xC740; &#xC544;&#xB9C8; &#xC2DC;&#xC791;&#xBD80;&#xD130; &#xC798;&#xBABB;&#xB41C; &#xD504;&#xB85C;&#xC81D;&#xD2B8; &#xC77C; &#xAC83;&#xC774;&#xB2E4;.</p>
<p>&#xACF5;&#xACF5;SI&#xC0AC;&#xC5C5;&#xC758; &#xACBD;&#xC6B0;&#xC5D0;&#xB294; FP(Function Point, &#xAE30;&#xB2A5;&#xC810;&#xC218;)&#xB97C; &#xAE30;&#xBC18;&#xC73C;&#xB85C;&#xD558;&#xB294; &#xB098;&#xB984; &#xBA85;&#xD655;&#xD55C; &#xC694;&#xAD6C;&#xC0AC;&#xD56D;&#xC744; RFP&#xC5D0; &#xB2F4;&#xACE0; &#xC2DC;&#xC791;&#xD55C;&#xB2E4;.</p>
<p>FP&#xAC00; &#xC815;&#xB2F5;&#xC740; &#xC544;&#xB2D0;&#xC9C0;&#xC5B8;&#xC815; &#xC5B4;&#xB290; &#xC815;&#xB3C4;&#xB294; &#xD504;&#xB85C;&#xC81D;&#xD2B8; &#xBE44;&#xC6A9; &#xC0B0;&#xC815;&#xC5D0;&#xB294; &#xBB34;&#xB9AC;&#xB294; &#xC5C6;&#xC744; &#xC218;&#xB3C4; &#xC788;&#xB2E4;. &#xD558;&#xC9C0;&#xB9CC; &#xBB38;&#xC81C;&#xB294; RFP &#xC791;&#xC131; &#xB2F9;&#xC2DC; &#xADF8; &#xB9E4;&#xC6B0; &#xC9E7;&#xC740; &#xC2DC;&#xAC04;&#xC5D0; 50~100&#xC5B5; &#xADDC;&#xBAA8;&#xC758; &#xD504;&#xB85C;&#xC81D;&#xD2B8;&#xC758; &#xC804;&#xCCB4; &#xAE30;&#xB2A5;&#xC744; &#xC0B0;&#xC815;&#xD558;&#xAE30;&#xB3C4; &#xD798;&#xB4E4; &#xBFD0;&#xB354;&#xB7EC; &#xBC1C;&#xC8FC;&#xAE4C;&#xC9C0; &#xD55C;&#xB2EC; &#xC548;&#xC5D0; &#xADF8; &#xADDC;&#xBAA8;&#xB97C; &#xD30C;&#xC545;&#xD558;&#xAE30;&#xB3C4; &#xB9E4;&#xC6B0; &#xD798;&#xACA8;&#xC6B4;&#xAC74; &#xBA85;&#xBC31;&#xD55C; &#xC0AC;&#xC2E4;&#xC774;&#xB2E4;.</p>
<p>&#xBC1C;&#xC8FC; &#xC774;&#xD6C4; &#xC0AC;&#xC5C5;&#xC790;&#xC57C; RFP &#xB0B4;&#xC6A9;&#xB9CC; &#xBBFF;&#xACE0; &#xC2DC;&#xC791;&#xD588;&#xC9C0;&#xB9CC;, &#xACE0;&#xAC1D;&#xC758; &#xD55C;&#xB9C8;&#xB514; &#xD55C;&#xB9C8;&#xB514;&#xC5D0; &#xAD11;&#xC778;&#xC774; &#xB418;&#xC5B4; &#xAC00;&#xB294; &#xAC83;&#xC774;&#xB2E4;.</p>
<blockquote>
<p>&#xC0AC;&#xC2E4; &#xC774;&#xAC74; &#xB0B4;&#xAC00; &#xC0DD;&#xAC01;&#xD55C; &#xAE30;&#xB2A5;&#xC774; &#xC544;&#xB0D0; - &#xCD5C;&#xBAA8; &#xACE0;&#xAC1D;</p>
<p>&#xC694;&#xAD6C;&#xC0AC;&#xD56D;&#xC744; &#xB0B4;&#xB294; &#xBD80;&#xC11C;&#xAC00; IT&#xB97C; &#xC798; &#xBAB0;&#xB77C;&#xC11C; &#xADF8;&#xB7AC;&#xC5B4; - &#xAD8C;&#xBAA8; &#xACE0;&#xAC1D;</p>
<p>&#xC704;&#xC5D0;&#xC11C; &#xADF8;&#xAC74; &#xC544;&#xB2C8;&#xB798; - &#xAE40;&#xBAA8; &#xACE0;&#xAC1D;</p>
<p>&#xB2E4;&#xC74C; &#xC0AC;&#xC5C5; &#xD558;&#xAE30; &#xC2EB;&#xC5B4;? - Double&#xC695; &#xB098;&#xC624;&#xB294; &#xACE0;&#xAC1D;</p>
<p>&#xB0B4;&#xC77C;&#xC774; &#xC624;&#xD508;&#xC774;&#xB2C8;&#xAE4C; &#xC774;&#xAC74; &#xD574;&#xC918;&#xC57C;&#xC9C0; - &#xC640;.. x&#xBC1C;..</p>
</blockquote>
<p><mark>&#xC694;&#xAD6C;&#xC0AC;&#xD56D;&#xC740; &#xBCC0;&#xACBD; &#xB420; &#xC218; &#xC788;&#xB294; &#xAC83;&#xC774; &#xB2F9;&#xC5F0;</mark>&#xD558;&#xB2E4;. &#xD558;&#xC9C0;&#xB9CC; &#xBB38;&#xC81C;&#xB294; &#xBCC0;&#xACBD;&#xC758; &#xADDC;&#xBAA8;&#xB294; &#xCC45;&#xC815;&#xB41C; &#xBE44;&#xC6A9; &#xC548;&#xC5D0;&#xC11C; &#xC18C;&#xD654;&#xD560; &#xC218; &#xC788;&#xB290;&#xB0D0; &#xC5C6;&#xB290;&#xB0D0;&#xAC00; &#xD310;&#xB2E8;&#xB418;&#xC5B4;&#xC57C; &#xD55C;&#xB2E4;.</p>
<p>&#xC694;&#xAD6C;&#xC0AC;&#xD56D; &#xBCC0;&#xACBD;&#xC740; &#xC801;&#xC808;&#xD55C; &#xC808;&#xCC28;&#xC640; &#xC2B9;&#xC778;&#xC744; &#xAC70;&#xCCD0; &#xBCC0;&#xACBD; &#xAD00;&#xB9AC; &#xB418;&#xC57C; &#xD558;&#xB294; &#xAC83;&#xC740; &#xB204;&#xAD6C;&#xB098; &#xC544;&#xB294; &#xC0AC;&#xC2E4;&#xC774;&#xC9C0;&#xB9CC;, &#xD604;&#xC2E4;&#xC744; &#xADF8;&#xB807;&#xC9C0; &#xC54A;&#xC740; &#xACBD;&#xC6B0;&#xAC00; &#xD5C8;&#xB2E4;&#xD558;&#xB2E4;.</p>
<p>&#xACE0;&#xAC1D; &#xC785;&#xC7A5;&#xC5D0;&#xC11C;&#xB294; &quot;&#xCC45;&#xC784;&quot;&#xC758; &#xC18C;&#xC9C0;&#xAC00; &#xC788;&#xAE30; &#xB54C;&#xBB38;&#xC5D0; &#xB9E4;&#xC6B0; &#xC560;&#xB9E4;&#xBAA8;&#xD638;&#xD55C;(&#xC774;&#xAC74; &#xD574;&#xC57C;&#xB418;&#xB294;&#xAC74;&#xC9C0; &#xC548;&#xD574;&#xC57C;&#xB418;&#xB294;&#xAC74;&#xC9C0; &#xD310;&#xB2E8; &#xBD88;&#xAC00;) &#xC694;&#xAD6C;&#xC0AC;&#xD56D;&#xC744; &#xB0B4;&#xAE30; &#xC77C;&#xC464;&#xACE0;, &#xC624;&#xD508;&#xC774; &#xB0B4;&#xC77C;&#xC778;&#xB370; &#xC790;&#xAE30; &#xC785;&#xC9C0;&#xB97C; &#xC704;&#xD574; &#xBB34;&#xB9AC;&#xD55C; &#xC694;&#xAD6C;&#xC0AC;&#xD56D;&#xC744; &#xB0A8;&#xBC1C;&#xD55C;&#xB2E4;&#xAC70;&#xB098;, IT&#xB97C; &#xC9C4;&#xC9DC; &#xC798; &#xBAB0;&#xB77C;&#xC11C; &#xAD6C;&#xAE00;&#xC774;&#xB098; &#xB124;&#xC774;&#xBC84; &#xAC19;&#xC740; &#xC0AC;&#xC774;&#xD2B8;&#xB97C; &#xB9CC;&#xB4E4;&#xC5B4;&#xB0B4;&#xB77C;&#xB294; &#xC694;&#xAD6C;&#xC0AC;&#xD56D;&#xC744; &#xC544;&#xC8FC; &#xC27D;&#xAC8C; &#xB358;&#xC9C0;&#xB294; &#xACBD;&#xC6B0;&#xB3C4; &#xB9CE;&#xB2E4;.</p>
<p>&#xD68C;&#xC0AC; &#xC785;&#xC7A5;&#xC5D0;&#xC11C;&#xB294; &#xC2E0;&#xADDC; &#xACE0;&#xAC1D; &#xC0AC;&#xC774;&#xD2B8;&#xC758; &#xBC1C;&#xAD74;&#xC744; &#xC704;&#xD574; &#xBB34;&#xB9AC;&#xD55C; &#xC785;&#xCC30;&#xACFC; &#xD568;&#xAED8; &#xB2E4;&#xC74C; &#xC0AC;&#xC5C5;&#xC758; &#xBC1C;&#xD310;&#xC744; &#xC704;&#xD55C; &#xD504;&#xB85C;&#xC138;&#xC77C;&#xC988;&#xB78D;&#xC2DC;&#xACE0; &#xACFC;&#xB3C4;&#xD55C; &#xC694;&#xAD6C;&#xC0AC;&#xD56D; &#xBCC0;&#xACBD;&#xACFC; &#xCD94;&#xAC00; &#xC694;&#xAD6C;&#xC0AC;&#xD56D;&#xC5D0;&#xB3C4; &#xB3C4;&#xB355;&#xACBD;&#xC5D0;&#xC11C; &#xB9D0;&#xD558;&#xB294; &#xB300;&#xC6D0;&#xACBD;&#xC9C0;(&#x5927;&#x5713;&#x5883;&#x667A;)&#xB97C; &#xC774;&#xB8E8;&#xC5B4; &#xBAA8;&#xB4E0; &#xAC83;&#xC744; &#xB2E4; &#xBC1B;&#xC544; &#xB4E4;&#xC774;&#xB294; &#xC790;&#xBE44;&#xC2EC;&#xC744; &#xBB34;&#xD55C;&#xD788; &#xBCA0;&#xD478;&#xB294; &#xACBD;&#xC6B0;&#xB3C4; &#xBE44;&#xC77C;&#xBE44;&#xC7AC;&#xD558;&#xB2E4;.</p>
<h3 id="%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EA%B4%80%EB%A6%AC-%EB%B0%A9%EB%B2%95%EB%A1%A0">&#xD504;&#xB85C;&#xC81D;&#xD2B8; &#xAD00;&#xB9AC; &#xBC29;&#xBC95;&#xB860;!?</h3>
<p>SI&#xD604;&#xC7A5;&#xC5D0;&#xC11C;&#xB294; &#xC544;&#xC9C1;&#xB3C4; &#xC218;&#xB9CE;&#xC740; &#xD504;&#xB85C;&#xC81D;&#xD2B8;&#xB4E4;&#xC774; &#xC804;&#xD1B5;&#xC801; &#xD3ED;&#xD3EC;&#xC218; &#xBC29;&#xBC95;&#xB860;&#xC744; &#xAE30;&#xBC18;&#xC73C;&#xB85C;&#xD55C; &#xBCC0;&#xD615;&#xB41C; &#xBC29;&#xBC95;&#xB860;&#xC744; &#xC0AC;&#xC6A9;&#xD558;&#xACE0; &#xC788;&#xB2E4;. &#xCD5C;&#xADFC;&#xC5D0;&#xB294; &#xC560;&#xC790;&#xC77C; &#xD504;&#xB85C;&#xC138;&#xC2A4;&#xB97C; &#xB3C4;&#xC785;&#xD55C; &#xD504;&#xB85C;&#xC81D;&#xD2B8;&#xB4E4;&#xB3C4; &#xB098;&#xC624;&#xAE34; &#xD558;&#xB294; &#xAC83; &#xAC19;&#xAE34;&#xD55C;&#xB370; &#xC5EC;&#xC804;&#xD788; &#xADDC;&#xBAA8;&#xAC00; &#xD070; &#xD504;&#xB85C;&#xC81D;&#xD2B8;&#xB4E4;&#xC740; &#xD3ED;&#xD3EC;&#xC218; &#xBC29;&#xBC95;&#xB860;&#xC744; &#xAE30;&#xBC18;&#xC73C;&#xB85C; &#xD558;&#xB294; &#xBC29;&#xBC95;&#xB860;&#xC744; &#xB300;&#xBD80;&#xBD84;&#xC744; &#xC0AC;&#xC6A9;&#xD558;&#xACE0; &#xC788;&#xB2E4;.</p>
<p>&#xD3ED;&#xD3EC;&#xC218; &#xBC29;&#xBC95;&#xB860;&#xC758; &#xAC00;&#xC7A5; &#xD070; &#xB2E8;&#xC810;&#xC740; <strong>&#xD504;&#xB85C;&#xC81D;&#xD2B8; &#xCD08;&#xAE30;&#xC5D0; &#xBAA8;&#xB4E0; &#xC694;&#xAD6C;&#xC0AC;&#xD56D;&#xACFC; &#xC77C;&#xC815;, &#xC790;&#xC6D0;&#xC5D0; &#xB300;&#xD55C; &#xC815;&#xC758;</strong>&#xAC00; &#xC774;&#xB8E8;&#xC5B4;&#xC9C0;&#xAE30; &#xB54C;&#xBB38;&#xC5D0; &#xB2E8;&#xACC4;&#xAC00; &#xB05D;&#xB098;&#xACE0; &#xB2E4;&#xC74C; &#xB2E8;&#xACC4;&#xB85C; &#xC774;&#xC804;&#xB420; &#xB54C; &#xBCC0;&#xACBD;&#xC0AC;&#xD56D;&#xC5D0; &#xB300;&#xD574; &#xB2A5;&#xB3D9;&#xC801;&#xC73C;&#xB85C; &#xB300;&#xCC98;&#xD558;&#xAE30; &#xB9E4;&#xC6B0; &#xD798;&#xB4E4;&#xB2E4;&#xB294; &#xAC83;&#xC774;&#xB2E4;.</p>
<p>&#xB0B4;&#xAC00; &#xC0DD;&#xAC01;&#xD558;&#xB294; &#xD3ED;&#xD3EC;&#xC218; &#xBC29;&#xBC95;&#xB860;&#xC758; &#xAC00;&#xC7A5; &#xD070; &#xB2E8;&#xC810;&#xC740; &#xBC14;&#xB85C;</p>
<blockquote>
<p>&#xAC1C;&#xBC1C;&#xC5D0; &#xB4E4;&#xC5B4;&#xAC00;&#xAE30; &#xC2DC;&#xC791;&#xD55C;&#xB2E4;&#xBA74; &#xBAA8;&#xB4E0; &#xBCC0;&#xACBD;&#xC0AC;&#xD56D;&#xC740; &#xC704;&#xD611;&#xC774; &#xB418;&#xBC84;&#xB9AC;&#xACE0; &#xB9CC;&#xB2E4;.</p>
</blockquote>
<p>&#xAC70;&#xAE30;&#xC5D0; &#xAC1C;&#xBC1C;&#xC774; &#xB05D;&#xB098;&#xAC08; &#xBB34;&#xB835;&#xC5D0; &#xC694;&#xAD6C;&#xC0AC;&#xD56D; &#xBCC0;&#xACBD;&#xC740; &#xC0DD;&#xAC01;&#xB9CC; &#xD574;&#xB3C4; &#xC655;&#xC9DC;&#xC99D;&#xC774; &#xBC00;&#xB824;&#xC62C; &#xC815;&#xB3C4;&#xB85C; &#xC2A4;&#xD2B8;&#xB808;&#xC2A4;&#xAC00; &#xB418;&#xB294; &#xAC83;&#xC774; &#xD604;&#xC2E4;&#xC774;&#xB2E4;.</p>
<h3 id="%EC%A0%9C%EB%8C%80%EB%A1%9C%EB%90%9C-%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%98-%EA%B0%9C%EB%B0%9C%EC%8A%A4%ED%82%AC%EC%9D%98-%EB%B6%80%EC%9E%AC">&#xC81C;&#xB300;&#xB85C;&#xB41C; &#xC544;&#xD0A4;&#xD14D;&#xCC98;, &#xAC1C;&#xBC1C;&#xC2A4;&#xD0AC;&#xC758; &#xBD80;&#xC7AC;</h3>
<p>&#xBF08;&#xB300;&#xAC00; &#xD6CC;&#xB96D;&#xD558;&#xAC8C; &#xC774;&#xB8E8;&#xC5B4;&#xC838; &#xC788;&#xB294; &#xD56D;&#xACF5;&#xBAA8;&#xD568;&#xC740; &#xBE44;&#xBC14;&#xB78C;&#xC774; &#xBAB0;&#xC544; &#xCCD0;&#xB3C4; &#xBA3C;&#xBC14;&#xB2E4;&#xC5D0;&#xC11C; &#xBB35;&#xBB35;&#xD788; &#xC784;&#xBB34;&#xB97C; &#xC218;&#xD589;&#xD574;&#xB0B8;&#xB2E4;. &#xD504;&#xB85C;&#xC81D;&#xD2B8;&#xB3C4; &#xB9C8;&#xCC2C;&#xAC00;&#xC9C0; &#xD504;&#xB85C;&#xC81D;&#xD2B8; &#xCD08;&#xAE30;&#xBD80;&#xD130; &#xACAC;&#xACE0;&#xD55C; &#xC544;&#xD0A4;&#xD14D;&#xCC98; &#xC124;&#xACC4;&#xC5D0; &#xD798;&#xC4F0;&#xACE0;, &#xBCC0;&#xACBD;&#xC5D0; &#xB2A5;&#xB3D9;&#xC801;&#xC73C;&#xB85C; &#xB300;&#xCC98;&#xD574;&#xC57C; &#xD55C;&#xB2E4;.</p>
<p>&#xD558;&#xC9C0;&#xB9CC; SI&#xD504;&#xB85C;&#xC81D;&#xD2B8;&#xC758; &#xD604;&#xC2E4;&#xC740; &#xADF8;&#xB807;&#xC9C0; &#xC54A;&#xB2E4;. &#xB300;&#xADDC;&#xBAA8; &#xB808;&#xAC70;&#xC2DC; &#xC2DC;&#xC2A4;&#xD15C;&#xC758; &#xC720;&#xC9C0;/&#xBCF4;&#xC218; &#xC0AC;&#xC5C5;&#xC774;&#xB77C;&#xB358;&#xC9C0; &#xC804;&#xC0AC;&#xC5C5;&#xC758; &#xB0A8;&#xAE30;&#xACE0;&#xAC04; &#xCC0C;&#xAEBC;&#xAE30;&#xB4E4; &#xB54C;&#xBB38;&#xC5D0; &#xC601;&#xB871;&#xD558;&#xACE0; &#xACAC;&#xACE0;&#xD55C; &#xC0C8;&#xB85C;&#xC6B4; &#xC544;&#xD0A4;&#xD14D;&#xCC98;&#xB97C; &#xC124;&#xACC4;&#xD558;&#xACE0; &#xC720;&#xC9C0;&#xD558;&#xAE30;&#xB780; &#xC815;&#xB9D0; &#xC27D;&#xC9C0; &#xC54A;&#xB2E4;.</p>
<p>&#xB9CC;&#xB4E4;&#xC5B4;&#xB0B4;&#xB294; &#xC11C;&#xBE44;&#xC2A4;&#xB098; &#xD504;&#xB7EC;&#xB355;&#xD2B8;&#xAC00; &#xC81C;&#xB300;&#xB85C; &#xB3D9;&#xC791;&#xD558;&#xB294; &#xAC83;&#xC5D0;&#xB294; &#xAD00;&#xC2EC; &#xBC16;&#xC778; &#xC0AC;&#xC5C5;&#xC758; PM&#xC774;&#xB098; &#xAD00;&#xB9AC;&#xC790;&#xC758; &#xC785;&#xC7A5;&#xC5D0;&#xC11C;&#xB294; &#xBB34;&#xC5C7;&#xBCF4;&#xB2E4; &#xC548;&#xC804;&#xD558;&#xAC8C; &#xD504;&#xB85C;&#xC81D;&#xD2B8;&#xB97C; &#xB9C8;&#xCE58;&#xB294; &#xAC83;&#xC774; &#xC9C0;&#xC0C1; &#xCD5C;&#xB300;&#xC758; &#xACFC;&#xC81C;&#xC774;&#xAE30; &#xB54C;&#xBB38;&#xC5D0; &#xB354;&#xB354;&#xC6B1; &#xC544;&#xD0A4;&#xD14D;&#xCC98;&#xC758; &#xBCC0;&#xACBD;&#xC740; &#xD798;&#xB4E4;&#xB2E4;.</p>
<p>&#xBA38;&#xB9BF;&#xC218; &#xCC44;&#xC6B0;&#xAE30;&#xC5D0; &#xAE09;&#xAE09;&#xD55C; &#xC678;&#xC8FC; &#xAC1C;&#xBC1C;&#xC790;&#xB4E4;&#xC758; &#xD22C;&#xC785;&#xACFC; &#xD22C;&#xC785; &#xB41C; &#xAC1C;&#xBC1C;&#xC790;&#xB4E4; &#xB610;&#xD55C; &#xC774;&#xC804; &#xC138;&#xB300;&#xC758; &#xAE30;&#xC220;&#xB85C;&#xB9CC; &#xACC4;&#xC18D; &#xAC1C;&#xBC1C;&#xD574; &#xC640;&#xC11C; &#xC0C8;&#xB85C;&#xC6B4; &#xAC1C;&#xBC1C; &#xD328;&#xB7EC;&#xB2E4;&#xC784;&#xC758; &#xBCC0;&#xD654;&#xC5D0; &#xC801;&#xC751;&#xD558;&#xC9C0; &#xBABB;&#xD558;&#xACE0; &#xAC16;&#xD600; &#xC788;&#xB294; &#xACBD;&#xC6B0;&#xAC00; &#xD5C8;&#xB2E4;&#xD558;&#xACE0;, &#xACC4;&#xC18D;&#xB418;&#xB294; &#xC57C;&#xADFC;&#xC5D0; &quot;&#xB354; &#xC774;&#xC0C1; &#xC774; &#xAE38;&#xC774; &#xB098;&#xC758; &#xAE38;&#xC778;&#xAC00;&quot; &#xD639;&#xC740; &quot;&#xC774; &#xC0DD;&#xD65C;&#xC774; &#xC6D0;&#xB798; &#xC774;&#xB807;&#xC9C0;&quot;&#xB77C;&#xB294; &#xACE0;&#xBBFC;&#xB9CC; &#xAE4A;&#xC5B4;&#xC838; &#xAC00;&#xB294; &#xAC83;&#xC774;&#xB2E4;.</p>
<h3 id="%EA%B7%B8%EB%9E%98%EC%84%9C-%EA%B2%B0%EA%B5%AD-%EC%82%AC%EB%9E%8C%EC%82%AC%EB%9E%8C%EA%B7%B8%EB%A6%AC%EA%B3%A0-%EC%82%AC%EB%9E%8C">&#xADF8;&#xB798;&#xC11C; &#xACB0;&#xAD6D; &#xC0AC;&#xB78C;..&#xC0AC;&#xB78C;..&#xADF8;&#xB9AC;&#xACE0; &#xC0AC;&#xB78C;..</h3>
<p>&#xD504;&#xB85C;&#xC81D;&#xD2B8;&#xAC00; &#xC0B0;&#xC73C;&#xB85C; &#xAC00;&#xB294; &#xC774;&#xC720;&#xC5D0; &#xB300;&#xD574;&#xC11C; &#xC8FC;&#xC800;&#xB9AC; &#xC8FC;&#xC800;&#xB9AC; &#xB9D0;&#xC774; &#xB9CE;&#xC558;&#xC9C0;&#xB9CC;, &#xACB0;&#xAD6D;&#xC5D4;</p>
<blockquote>
<p>&#xD504;&#xB85C;&#xC81D;&#xD2B8;&#xB3C4; &#xACB0;&#xAD6D;&#xC740; &#xC0AC;&#xB78C;&#xC774; &#xB9CC;&#xB4DC;&#xB294; &#xAC83;&#xC774;&#xB2E4;.</p>
</blockquote>
<p>&#xC6B0;&#xB9AC; &#xBAA8;&#xB450; &#xC288;&#xD37C;&#xD788;&#xC5B4;&#xB85C;&#xB294; &#xC544;&#xB2C8;&#xAE30; &#xB54C;&#xBB38;&#xC5D0; &#xC544;&#xB2C8; &#xC124;&#xB839; &#xC544;&#xC774;&#xC5B8;&#xB9E8;&#xC774;&#xB098; &#xCEA1;&#xD2F4; &#xC544;&#xBA54;&#xB9AC;&#xCE74;&#xB3C4; &#xC678;&#xACC4;&#xC778;&#xC758; &#xCE68;&#xACF5;&#xC5D4; &#xD63C;&#xC790;&#xC11C;&#xB294; &#xC5ED;&#xBD80;&#xC871;&#xC774;&#xC9C0; &#xC54A;&#xC744;&#xAE4C;.</p>
<p>&#xC694;&#xAD6C;&#xC0AC;&#xD56D; &#xD611;&#xC0C1; &#xC2E4;&#xD328;, &#xACE0;&#xAC1D;&#xC5D0;&#xAC8C; &#xB9E5; &#xC5C6;&#xC774; &#xB04C;&#xB824;&#xB2E4;&#xB2C8;&#xAE30;, &#xAC1C;&#xBC1C;&#xC790;&#xB4E4;&#xC758; &#xC6D0;&#xC131;, &#xD504;&#xB85C;&#xC81D;&#xD2B8; &#xAD00;&#xB9AC; &#xC2E4;&#xD328;...</p>
<p>&#xC774; &#xBAA8;&#xB4E0; &#xBB38;&#xC81C;&#xB294; &#xACB0;&#xAD6D; <mark><strong>&#xCEE4;&#xBBA4;&#xB2C8;&#xCF00;&#xC774;&#xC158;</strong></mark> &#xC758; &#xBD80;&#xC7AC;&#xB77C;&#xACE0; &#xC0DD;&#xAC01;&#xB41C;&#xB2E4;.</p>
<p>&#xC5B4;&#xB5BB;&#xAC8C; &#xD558;&#xBA74; &#xBB38;&#xC81C;&#xB97C; &#xD574;&#xACB0; &#xD560; &#xC218; &#xC788;&#xC744;&#xAE4C;? &#xCE58;&#xC5F4;&#xD558;&#xAC8C; &#xACE0;&#xBBFC;&#xD558;&#xACE0; &#xB610; &#xACE0;&#xBBFC;&#xD558;&#xACE0; &#xC194;&#xB8E8;&#xC158;&#xC744; &#xB9CC;&#xB4E4;&#xC5B4; &#xB0B4;&#xB294; &#xACE0;&#xD1B5;&#xC2A4;&#xB7EC;&#xC6B4; &#xC791;&#xC5C5;&#xB4E4;&#xC774; &#xACB0;&#xAD6D; &#xD504;&#xB85C;&#xC81D;&#xD2B8;&#xC758; &#xC131;&#xACF5;&#xC744; &#xC774;&#xB04C;&#xC5B4; &#xB0B4;&#xC9C0; &#xC54A;&#xB098; &#xC2F6;&#xB2E4;.</p>
<p>&#xC81C;&#xB300;&#xB85C;&#xB41C; RFP&#xC758; &#xC791;&#xC131;, &#xC694;&#xAD6C;&#xC0AC;&#xD56D;&#xC758; &#xAD00;&#xB9AC;, &#xACE0;&#xAC1D;&#xACFC;&#xC758; &#xD611;&#xC0C1;, &#xACAC;&#xACE0;&#xD55C; &#xC544;&#xD0A4;&#xD14D;&#xCC98; &#xC124;&#xACC4;, &#xB0B4;&#xBD80; &#xAC08;&#xB4F1; &#xAE30;&#xD0C0; &#xB4F1;&#xB4F1; &#xBAA8;&#xB4E0; &#xBB38;&#xC81C;&#xB294; &#xC0C1;&#xD669;&#xC5D0; &#xB9DE;&#xB294; &#xC801;&#xC808;&#xD55C; &#xB300;&#xD654;&#xB85C; &#xD574;&#xACB0;&#xC774; &#xAC00;&#xB2A5;&#xD558;&#xB2E4;&#xACE0; &#xC0DD;&#xAC01;&#xB418;&#xACE0;, &#xADF8; <code>&#xB300;&#xD654;</code>&#xB77C;&#xB294; &#xAC83;&#xC5D0; &#xC9D1;&#xC911;&#xD558;&#xACE0; &#xB098;&#xAC00;&#xC57C;&#xD560; &#xBAA9;&#xD45C;&#xC5D0; &#xD504;&#xB85C;&#xC81D;&#xD2B8; &#xAD6C;&#xC131;&#xC6D0; &#xBAA8;&#xB450;&#xAC00; &#xAC19;&#xC740; &#xADF8;&#xB9BC;&#xC744; &#xADF8;&#xB9B4; &#xC218; &#xC788;&#xB294; <code>&#xB9AC;&#xB354;&#xC27D;</code>.. &#xADF8;&#xAC83;&#xC774;&#xC57C; &#xB9D0;&#xB85C; &#xD504;&#xB85C;&#xC81D;&#xD2B8;&#xB97C; &#xC0B0;&#xC73C;&#xB85C; &#xBCF4;&#xB0B4;&#xC9C0; &#xC54A;&#xB294; &#xD0A4;&#xAC00; &#xC544;&#xB2D0;&#xAE4C; &#xC0DD;&#xAC01;&#xD55C;&#xB2E4;.</p>
<h2 id="%EA%B7%B8%EB%A0%87%EB%8B%A4%EB%A9%B4-%EA%B0%9C%EC%84%A0%EC%9D%98-%EC%97%AC%EC%A7%80%EB%8A%94-%EC%97%86%EB%82%98">&#xADF8;&#xB807;&#xB2E4;&#xBA74; &#xAC1C;&#xC120;&#xC758; &#xC5EC;&#xC9C0;&#xB294; &#xC5C6;&#xB098;?</h2>
<p>AA&#xD300; &#xD300;&#xC7A5;&#xC744; &#xD558;&#xAE30; &#xC774;&#xC804;&#xC5D0;&#xB294; &#xAC1C;&#xBC1C;&#xC790;&#xBD80;&#xD130; &#xAC1C;&#xBC1C;PL&#xAE4C;&#xC9C0; &#xC2ED;&#xC218;&#xB144;&#xAC04; &#xD504;&#xB85C;&#xC81D;&#xD2B8;&#xB97C; &#xACC4;&#xC18D; &#xD574;&#xC624;&#xACE0; &#xACAA;&#xC5B4;&#xC654;&#xC9C0;&#xB9CC; &#xD55C;&#xC0AC;&#xB78C; &#xAC1C;&#xC778;&#xC758; &#xD798;&#xC73C;&#xB85C;&#xB294; &#xC5B4;&#xB824;&#xC6B4; &#xC0C1;&#xD669;&#xC744; &#xC774;&#xACA8;&#xB0B4;&#xAE30; &#xC27D;&#xC9C0; &#xC54A;&#xB294; &#xAC83;&#xC774; &#xC0AC;&#xC2E4;&#xC774;&#xB2E4;.</p>
<p>&#xADF8;&#xB798;&#xC11C; &#xD544;&#xC694;&#xD55C; &#xAC83;&#xC774; &#xAC1C;&#xBC1C; &#xD504;&#xB85C;&#xC138;&#xC2A4;&#xACE0; &#xAC1C;&#xBC1C; &#xBB38;&#xD654;&#xB77C;&#xACE0; &#xC0DD;&#xAC01;&#xD55C;&#xB2E4;.</p>
<h3 id="%EC%A0%81%EC%A0%88%ED%95%9C-%EB%B0%A9%EB%B2%95%EB%A1%A0%EC%9D%98-%EC%84%A0%ED%83%9D">&#xC801;&#xC808;&#xD55C; &#xBC29;&#xBC95;&#xB860;&#xC758; &#xC120;&#xD0DD;</h3>
<p>&#xD55C;&#xBC88; &#xC131;&#xACF5;&#xD55C; &#xD504;&#xB85C;&#xC81D;&#xD2B8;&#xC758; &#xBC29;&#xBC95;&#xB860;&#xC774; &#xB2E4;&#xC74C; &#xD504;&#xB85C;&#xC81D;&#xD2B8;&#xC758; &#xC131;&#xACF5;&#xC744; 100% &#xC774;&#xB04C;&#xC5B4;&#xB0B4;&#xC9C4; &#xBABB;&#xD55C;&#xB2E4;. &#xD504;&#xB85C;&#xC81D;&#xD2B8;&#xB9C8;&#xB2E4; &#xACE0;&#xC720;&#xD55C; &#xC131;&#xACA9;&#xC744; &#xAC00;&#xC9C0;&#xACE0; &#xC788;&#xAE30; &#xB54C;&#xBB38;&#xC5D0; &#xADF8; &#xD504;&#xB85C;&#xC81D;&#xD2B8;&#xC5D0; &#xB9DE;&#xB294; &#xBC29;&#xBC95;&#xB860;&#xC744; &#xACE0;&#xBBFC;&#xD574;&#xC57C;&#xBD10;&#xC57C; &#xD55C;&#xB2E4;.</p>
<p>&#xC560;&#xC790;&#xC77C; &#xBC29;&#xBC95;&#xB860;&#xC774; &#xB9CC;&#xBCD1; &#xD1B5;&#xCE58;&#xC57D;&#xC740; &#xC544;&#xB2C8;&#xC9C0;&#xB9CC; &#xC801;&#xADF9;&#xC801;&#xC73C;&#xB85C; Best Practice&#xB4E4;&#xC744; &#xB3C4;&#xC785;&#xD574;&#xBCF4;&#xACE0; &#xC2E4;&#xD589;&#xD574; &#xBCF4;&#xB294; &#xAC83;&#xB3C4; &#xBC29;&#xBC95;&#xC774; &#xB420; &#xC218;&#xB3C4; &#xC788;&#xC744; &#xAC83; &#xAC19;&#xB2E4;.</p>
<h3 id="%EA%B0%9C%EB%B0%9C-%EB%AC%B8%ED%99%94%EC%9D%98-%EC%A0%95%EC%B0%A9">&#xAC1C;&#xBC1C; &#xBB38;&#xD654;&#xC758; &#xC815;&#xCC29;</h3>
<p>&#xD6A8;&#xC728;&#xC801;&#xC778; &#xAC1C;&#xBC1C; &#xBB38;&#xD654;&#xB77C;&#xB294;&#xAC74; &#xC0AC;&#xC2E4; &#xD68C;&#xC0AC;&#xAC00; &#xB9CC;&#xB4E4;&#xC5B4; &#xC8FC;&#xB294;&#xAC74; &#xC544;&#xB2C8;&#xB2E4;. &#xAD6C;&#xC131;&#xC6D0;&#xB4E4; &#xC2A4;&#xC2A4;&#xB85C;&#xAC00; &#xC790;&#xAC01;&#xD558;&#xACE0; &#xD611;&#xC2EC;&#xD558;&#xC5EC; &#xB9CC;&#xB4E4;&#xC5B4;&#xB0B4;&#xB294; &#xAC83;&#xC774;&#xB2E4;.</p>
<p>&#xADF8;&#xB7EC;&#xD55C; &#xD589;&#xB3D9;&#xB4E4;&#xC744; &#xBC1C;&#xD604;&#xD560; &#xC218; &#xC788;&#xB3C4;&#xB85D; &#xB9CC;&#xB4E4;&#xC5B4;&#xC8FC;&#xB294; &#xC7A5;&#xCE58;&#xB4E4;&#xC744; &#xACE0;&#xBBFC;&#xD574;&#xC57C; &#xD55C;&#xB2E4;.</p>
<p>&#xC0AC;&#xC2E4; &#xC694;&#xC0C8; &#xC2A4;&#xD0C0;&#xD2B8;&#xC5C5;&#xB4E4;&#xC774; &#xC774;&#xB7F0; &#xBB34;&#xAE30;(&#xAC1C;&#xBC1C; &#xBB38;&#xD654;)&#xB85C; &#xAC1C;&#xBC1C;&#xC790;&#xB4E4; &#xB9CE;&#xC774; &#xB04C;&#xC5B4;&#xBAA8;&#xC73C;&#xACE0; &#xC788;&#xB294; &#xAC83; &#xAC19;&#xC740;&#xB370; &#xC88B;&#xC740; &#xC544;&#xC774;&#xB514;&#xC5B4;&#xB294; &#xC0B4;&#xC9DD; &#xCC44;&#xC6A9; &#xD574; &#xBCF4;&#xB294; &#xAC83;&#xB3C4; &#xBC29;&#xBC95;&#xC77C; &#xAC83; &#xAC19;&#xB2E4;.</p>
<h3 id="%EB%AC%B4%EC%97%87%EB%B3%B4%EB%8B%A4-%EA%B3%B5%ED%86%B5%EC%9D%98-%EB%AA%A9%ED%91%9C%EB%A1%9C-%EC%9D%B4%EB%81%8C-%EC%88%98-%EC%9E%88%EB%8A%94-%EB%A6%AC%EB%8D%94%EC%89%BD">&#xBB34;&#xC5C7;&#xBCF4;&#xB2E4; &#xACF5;&#xD1B5;&#xC758; &#xBAA9;&#xD45C;&#xB85C; &#xC774;&#xB04C; &#xC218; &#xC788;&#xB294; &#xB9AC;&#xB354;&#xC27D;</h3>
<p>&#xC704;&#xC5D0;&#xC11C; &#xB9D0;&#xD55C; &#xADF8; &#xBB34;&#xC5C7;&#xBCF4;&#xB2E4; &#xD504;&#xB85C;&#xC81D;&#xD2B8; &#xAD6C;&#xC131;&#xC6D0;&#xC744; &#xD558;&#xB098;&#xC758; &#xBAA9;&#xD45C;&#xB85C; &#xC774;&#xB04C; &#xC218; &#xC788;&#xB294; &#xB9AC;&#xB354;&#xC27D; &#xB2A5;&#xB825; &#xD5A5;&#xC0C1;&#xC774; &#xAC00;&#xC7A5; &#xD544;&#xC694;&#xD560; &#xAC83; &#xAC19;&#xB2E4;.</p>
<p>&#xB098;&#xB294; <a href="https://www.ted.com/talks/simon_sinek_how_great_leaders_inspire_action?language=ko&amp;ref=blog.hkwon.me">&#xC0AC;&#xC774;&#xBA3C; &#xC2DC;&#xB125;&#xC758; TED &#xAC15;&#xC5F0;(&#xC704;&#xB300;&#xD55C; &#xB9AC;&#xB354;&#xB4E4;&#xC774; &#xD589;&#xB3D9;&#xC744; &#xC774;&#xB04C;&#xC5B4; &#xB0B4;&#xB294; &#xBC95;)</a>&#xC744; &#xC608;&#xC804;&#xC5D0; &#xBCF4;&#xBA74;&#xC11C; &#xAE4A;&#xC740; &#xAC10;&#xBA85;&#xAE4C;&#xC9C4; &#xC544;&#xB2C8;&#xC9C0;&#xB9CC;, &#xB098;&#xBD80;&#xD130; &#xBCC0;&#xD654;&#xAC00; &#xD544;&#xC694;&#xD558;&#xB2E4;&#xACE0; &#xB290;&#xAF08;&#xACE0;, &#xADF8;&#xB7F0; &#xB290;&#xB08C;&#xC744; &#xC8FC;&#xC704;&#xC5D0; &#xC804;&#xD30C;&#xD558;&#xB294; &#xAC83;&#xC5D0; &#xC8FC;&#xB825;&#xD588;&#xB358; &#xAC83; &#xAC19;&#xB2E4;.</p>
<iframe src="https://embed-ssl.ted.com/talks/lang/ko/simon_sinek_how_great_leaders_inspire_action.html" width="560" height="315" frameborder="0" scrolling="no" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>
<h2 id="%EB%A7%88%EB%AC%B4%EB%A6%AC">&#xB9C8;&#xBB34;&#xB9AC;</h2>
<p>&#xC8FC;&#xC800;&#xB9AC; &#xC8FC;&#xC800;&#xB9AC; &#xB9D0;&#xC774; &#xB9CE;&#xC558;&#xC9C0;&#xB9CC; &#xACB0;&#xB860;&#xC740; SI&#xB294; &#xC774;&#xC81C; &#xADF8;&#xB9CC;&#xB46C;&#xC57C; &#xD558;&#xB098;??? &#xADF8;&#xB7FC; &#xB09C; &#xBB50; &#xBA39;&#xACE0; &#xC0B4; &#xC218; &#xC788;&#xC744;&#xAE4C;?? &#x314E;&#x314E;&#x314E;&#x314E;&#x314E;&#x314E;</p>
<p>&#xC800; &#xC880; &#xB370;&#xB824;&#xAC00;&#xC8FC;&#xC2E4; &#xBD84; &#xC5C6;&#xC73C;&#xC2E0;&#xAC00;&#xC694;?</p>
]]></content:encoded></item></channel></rss>