<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" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
<channel>
<title><![CDATA[ 송성광 블로그 ]]></title>
<description><![CDATA[ Thoughts, stories and ideas. ]]></description>
<link>https://blog.sungkwang.me</link>
<image>
    <url>https://blog.sungkwang.me/favicon.png</url>
    <title>송성광 블로그</title>
    <link>https://blog.sungkwang.me</link>
</image>
<lastBuildDate>수, 06 5월 2026 19:49:58 +0900</lastBuildDate>
<atom:link href="https://blog.sungkwang.me" rel="self" type="application/rss+xml"/>
<ttl>60</ttl>

    <item>
        <title><![CDATA[ 스페이스워크에서 우주를 걷다 ]]></title>
        <description><![CDATA[ 스페이스워크의 높은 곡선 계단을 걷다보면 마치 우주를 걷고 있는것 같다. 가족과 함께 스페이스워크를 다녀왔다. ]]></description>
        <link>https://blog.sungkwang.me/walking-through-space-at-spacewalk/</link>
        <guid isPermaLink="false">696d8e6bbcbbf623948e20c7</guid>
        <category><![CDATA[ Story ]]></category>
        <dc:creator><![CDATA[ 송성광 ]]></dc:creator>
        <pubDate>월, 19 1월 2026 14:56:56 +0900</pubDate>
        <media:content url="https://s3.ap-northeast-2.amazonaws.com/hbn-user-sksong/2026/01/IMG_4651.jpeg" medium="image"/>
        <content:encoded><![CDATA[ <p>스페이스워크의 높은 곡선 계단을 걷다보면 마치 우주를 걷고 있는것 같다. 가족과 함께 스페이스워크를 다녀왔다.</p><p>한국인이 꼭 가봐야할 한국관광 100선에 등록되어 있는 스페이스워크(Spacewalk)에 다녀왔다. 곧 400만명 방문을 돌파한다고 하니, 포항의 랜드마크로 유명한 것을 넘어 명소로 자리를 잡은 것 같다. 스페이스워크는 포스코가 창단 50주년 기념으로 포항에게 기부한 작품이다. 위치는 포항의 유명한 영일대해수욕장 옆 환호공원에 위치하고 있다.</p>
<!--kg-card-begin: html-->
<iframe src="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d3225.16112162381!2d129.38771467557714!3d36.06517397246589!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x356703d98a6e96a1%3A0xdc74ccb479f603ad!2sHwanho%20Park%20Space%20Walk!5e0!3m2!1sen!2skr!4v1768789743511!5m2!1sen!2skr" width="100%" height="450" style="border:0;" allowfullscreen="" loading="lazy" referrerpolicy="no-referrer-when-downgrade"></iframe>
<!--kg-card-end: html-->
<p>오래전부터 아이와 함께 가려고 계획했지만, 그동안 어려서 데리고 가지 못했다가 10살이 넘어서 이젠 이정도 조형물은 혼자서도 잘 걷고 무서워하지 않을거라 생각하고 데리고 갔다. 스페이스워크는 사진으로 봐서는 그 웅장함을 다 알 수 없다.  360도 구간인 버티컬루프 코스를 제외하고는 아이도 보호자 손을 잡고 모두 걸을 수 있는데, 곳곳에서 포기하고 내려가는 사람들이 나온다. </p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://s3.ap-northeast-2.amazonaws.com/hbn-user-sksong/2026/01/IMG_1322.jpeg" class="kg-image" alt="" loading="lazy" width="4032" height="3024"><figcaption><span style="white-space: pre-wrap;">스페이스워크 버티컬루프 아래에서 360도 계단을 보고 있다.</span></figcaption></figure><p>스페이스워크는 시작부에 오른쪽(경사도는 낮지만 높이는 높은 곳), 왼쪽(경사도가 높지만 오른쪽 보다는 조금 낮은 곳)으로 갈림길이 있다. 아이 엄마는 이 갈림길에서 시작하기 전에 포기하고 내려갔다. 안전상 스페이스크워크는 흔들리는 구조를 가지고 있는데, 높은 곳을 무서워하는 사람에게는 아이나 어른이나 꽤 무서운 곳이라는 것을 알 수 있다.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://s3.ap-northeast-2.amazonaws.com/hbn-user-sksong/2026/01/IMG_1304.jpeg" class="kg-image" alt="" loading="lazy" width="3024" height="4032"><figcaption><span style="white-space: pre-wrap;">용감하게 시작하기 전, 아내는 곧 무서워서 먼저 내려왔다.</span></figcaption></figure><p>아들과 나는 수직 계단쪽을 먼저 올랐다. 아들은 비명을 지르면서도 즐겁게 올랐는데, 아들 앞에서 무섭지 않은척 하려고 진땀을 흘렸다. 수직계단은 오를때 보다 내려올 때 더 아찔하다. 스페이스워크는 원래 버티컬루프를 통해서 모두 연결되는 구간이지만, 이 구간은 출입이 통제된다. </p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://s3.ap-northeast-2.amazonaws.com/hbn-user-sksong/2026/01/IMG_1343.jpeg" class="kg-image" alt="" loading="lazy" width="3024" height="4032"><figcaption><span style="white-space: pre-wrap;">스페이스워크 버티컬 루프 통제구간 앞</span></figcaption></figure><p> 버티컬 루프에서 다른 구간까지 통제가 되기 때문에 수직계단을 올라서 왔던 부분을 다시 올라서 반대로 돌아서 가야한다. 이쯤되면 허벅지가 무거워진다. 스페이스워크는 모든 구간이 계단으로 되어있기 때문에 수십개의 계단을 오르락 내리락하다보면 허벅지가 곧 단단해진다.</p><p>가장 높은 구간에 올라가면 포항의 영일대해수욕장에 있는 영일교가 보인다. </p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://s3.ap-northeast-2.amazonaws.com/hbn-user-sksong/2026/01/IMG_1313.jpeg" class="kg-image" alt="" loading="lazy" width="4032" height="3024"><figcaption><span style="white-space: pre-wrap;">스페이스워크 정상에서</span></figcaption></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://s3.ap-northeast-2.amazonaws.com/hbn-user-sksong/2026/01/IMG_1335.jpeg" class="kg-image" alt="" loading="lazy" width="4032" height="3024"><figcaption><span style="white-space: pre-wrap;">스카이워크에서 보이는 영일교</span></figcaption></figure><p>스페이스워크는 아주 많이 흔들리지만, 강한 지진과 풍속에도 견딜수 있게 만들어졌으니 안심해도 된다. 입장하면 계속 안내가 나온다. 원래 흔들리는 것이 정상이니 당황하지 말고, 안전하게 즐기면 된다. 다만 철로된 구조물이라 추운 겨울에 날카로운 부분에 부딛히면 상처가 날 수 있어 아이들은 보호자의 보호가 필요하다. </p><p>스페이스워크는 2022년에 대통령 공간문화대상을 수상했다. </p><p>걸어서 우주를 유영하는 기분이 들기도 하고, 롤러코스트 같은 코스를 걸어서 갈 수 있어 스릴넘치는 경험을 할 수 있다. 무료로 멋진 조형물이자 건축물을 체험할 수 있고, 아이와 함께 즐거운 추억을 남길 수 있어 우리는 또 방문하자며 약속하며 내려왔다.</p><figure class="kg-card kg-image-card"><img src="https://s3.ap-northeast-2.amazonaws.com/hbn-user-sksong/2026/01/R0015547.jpeg" class="kg-image" alt="" loading="lazy" width="4000" height="6000"></figure> ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[ LEGO Education SPIKE Prime 으로 블록 코딩하기 ]]></title>
        <description><![CDATA[ 컴퓨터 전공하는 아빠가 요즘 아들에게 본업을 하고 있다. 이번 겨울 방학부터 3학년 아들과 함께 Scratch 블록 코딩을 본격적으로 가르쳐주고 있는데, 겨울방학 특강으로 LEGO Education SPIKE Prime을 이용해서 블록코딩을 체험할 수 있는 곳이 있어 다녀왔다. 아들은 5세부터 LEGO를 했기 때문에 Lego에 완전 푹빠져있다. 게다가 최근 배우는 블록코딩을 이용해서 자동차를 움직일 수 ]]></description>
        <link>https://blog.sungkwang.me/block-coding-with-lego-education-spike-prime/</link>
        <guid isPermaLink="false">69624e3597abb6bbac1f8ed3</guid>
        <category><![CDATA[ Story ]]></category>
        <dc:creator><![CDATA[ 송성광 ]]></dc:creator>
        <pubDate>일, 11 1월 2026 21:58:35 +0900</pubDate>
        <media:content url="https://s3.ap-northeast-2.amazonaws.com/hbn-user-sksong/2026/01/45678-1.jpg" medium="image"/>
        <content:encoded><![CDATA[ <p>컴퓨터 전공하는 아빠가 요즘 아들에게 본업을 하고 있다. 이번 겨울 방학부터 3학년 아들과 함께 <a href="https://blog.sungkwang.me/signing-up-for-scratch/" rel="noreferrer">Scratch</a> 블록 코딩을 본격적으로 가르쳐주고 있는데, 겨울방학 특강으로 LEGO Education SPIKE Prime을 이용해서 블록코딩을 체험할 수 있는 곳이 있어 다녀왔다. 아들은 5세부터 LEGO를 했기 때문에 Lego에 완전 푹빠져있다. 게다가 최근 배우는 블록코딩을 이용해서 자동차를 움직일 수 있다니!! LEGO + Coding 이 조합은 아이가 열광할 수 밖에 없을 것 같아서 서둘러 예약했다. </p><h2 id="lego-education-spike-prime">LEGO Education SPIKE Prime</h2><p>LEGO를 이용하여 과학 및 수학의 교육을 할 수 있게 만든 교보재 페키지이다. 예전에 LEGO MINDSTORMS 이 있었다면, 지금은 LEGO SPIKE 가 있다고 생각하면 된다. 공대생인 아빠가 진심으로 레고를 좋아하니 아들도 자연스럽게 레고에 빠져있는것 같다. 올해 최고의 선문을 Star Wards 의 Imperial Star Destoyer(75394) 였는데, 3학년이 되면서 1500 피스가 넘는 블록도 잘 조립하게 되었다. 그래서 이젠 레고에 코딩을 접목해서 컴퓨터학과 물리학을 같이 접하면 좋지 않을까 생각하고 있었는데 LEGO Education SPIKE Prime이 이런 요구를 잘 반영해서 접할 수 있는것 같다. 하지만 구매하긴 가격이 부담되기 때문에 과학관이나 수학관 등에서 물리학과 수학, 최근에는 코딩 수업을 위해서 무/유료 교육들이 있으니 활용하는 것을 추천한다.</p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://spike.legoeducation.com/?ref=blog.sungkwang.me"><div class="kg-bookmark-content"><div class="kg-bookmark-title">LEGO Education SPIKE</div><div class="kg-bookmark-description"></div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://static.ghost.org/v5.0.0/images/link-icon.svg" alt=""></div></div><div class="kg-bookmark-thumbnail"><img src="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTg4IiBoZWlnaHQ9IjQzNiIgdmlld0JveD0iMCAwIDU4OCA0MzYiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMF81MDAwXzIyNDU0KSI+CjxwYXRoIGQ9Ik0zMS4xOSAyODUuMDIzTDI4LjM5IDI4My41ODNDMjcuNjM0OSAyODQuOCAyNy4wNDM4IDI4Ni4xMTEgMjYuNjMyIDI4Ny40ODNMMjkuNjcyIDI4OC40NzNDMzAuMDU3MSAyODcuMjc0IDMwLjU2NTggMjg2LjExNyAzMS4xOSAyODUuMDIzWiIgZmlsbD0iIzE4MTcxNiIvPgo8cGF0aCBkPSJNMTAwLjYzOSAzNjYuNjIyQzk1LjQzOSAzNDUuMzUgODIuNzcyIDMzNS4zNzYgNzEuNTk3IDMyNi41NzVDNjIuMzA4IDMxOS4yNjEgNTQuMjg4IDMxMi45NDQgNTEuNDE3IDMwMS4xOTdDNDkuOTcxIDI5NS4yODYgNTMuNDM4IDI4OC4wMjUgNTYuNzkyIDI4MS4wMDVDNTkuNjEgMjc1LjEwNSA2Mi41MjUgMjY5LjAwNSA2Mi45MDkgMjYzLjAxNEM2My4zODggMjU1LjU4MyA1OS44OTcgMjQ5LjU0OCA1Mi41MzQgMjQ1LjA3OUM0My4wMzQgMjM5LjMwNyAzMS4yMTUgMjQwLjM2MyAyMC45MzQgMjQ3LjkwMUMxMy4yMDggMjUzLjU1MyA2Ljk4NTAyIDI2Mi4zMTMgMy40MDMwMiAyNzIuNTUzQy0wLjU1MzUzOSAyODQuMDY0IC0xLjA4MDkxIDI5Ni40NzYgMS44ODUwMiAzMDguMjhDNy43MTEwMiAzMzIuMTE0IDIyLjUyNSAzNDQuNjMxIDM0LjQyNiAzNTQuNjg5QzQyLjYwNSAzNjEuNjAxIDQ5LjY2NyAzNjcuNTY5IDUxLjU2MiAzNzUuMzE2QzUzLjQ0MyAzODMuMDE2IDUwLjMzMSAzODguMzE2IDQ2LjcyNiAzOTQuNDQxQzQxLjk3NCA0MDIuNTIyIDM2LjA1OSA0MTIuNTggNDcuMDI2IDQyN0M1My4xNDQgNDM1LjA0IDYyLjExOSA0MzcuODEzIDcxLjU3OCA0MzQuNzk0QzcyLjg2MSA0MzQuMzgzIDc0LjExNDMgNDMzLjg4NCA3NS4zMjkgNDMzLjMwMUM4NC40NSA0MjguOTUgOTIuNTIxIDQxOS44MzUgOTcuNDcgNDA4LjI5MkMxMDMuMDYxIDM5NS4xMjQgMTA0LjE3NCAzODAuNDg0IDEwMC42MzkgMzY2LjYyMlpNODkuMjU0IDQwNC43NjRDODUuMjA5IDQxNC4xOTggNzguNTY3IDQyMS44NDUgNzEuNDg0IDQyNS4yMjRDNjYuNjExIDQyNy41NDcgNTkuNjU0IDQyOC44MDIgNTQuMTU0IDQyMS41ODJDNDYuODE5IDQxMS45NCA0OS44NTQgNDA2Ljc4MiA1NC40NDEgMzk4Ljk4MkM1OC4yNTUgMzkyLjQ5NyA2MyAzODQuNDI1IDYwLjI1NiAzNzMuMTk0QzU3LjY3IDM2Mi42MTcgNDkuMTg2IDM1NS40NDggNDAuMjA0IDM0Ny44NTdDMjguNzI0IDMzOC4xNTcgMTUuNzE0IDMyNy4xNTcgMTAuNTggMzA2LjE1N0M0Ljk0NDAyIDI4My4wOTUgMTQuNzM2IDI2My41MzUgMjYuMjE5IDI1NS4xMkMyOC40NTU5IDI1My40NDUgMzAuOTQ5MSAyNTIuMTQzIDMzLjYwMiAyNTEuMjY0QzM1Ljk0NTEgMjUwLjQ0NSAzOC40Mzk2IDI1MC4xNTIgNDAuOTA4NyAyNTAuNDA1QzQzLjM3NzggMjUwLjY1OSA0NS43NjA5IDI1MS40NTIgNDcuODg5IDI1Mi43MjlDNTYuNzM3IDI1OC4xMDEgNTUuMTQyIDI2My42OTIgNDguNzE2IDI3Ny4xNDhDNDQuODc0IDI4NS4xOTIgNDAuNTE2IDI5NC4zMSA0Mi43MTYgMzAzLjMyMkM0Ni4zMjEgMzE4LjA2OCA1Ni4zNTMgMzI1Ljk2OSA2Ni4wNTQgMzMzLjYwOEM3Ni41ODUgMzQxLjkgODcuNDczIDM1MC40NzQgOTEuOTM5IDM2OC43NDhDOTUuMDEzIDM4MC43MjMgOTQuMDY5NyAzOTMuMzc3IDg5LjI1NCA0MDQuNzY0WiIgZmlsbD0iIzE4MTcxNiIvPgo8cGF0aCBkPSJNNDAuMzU0IDI3NS41ODlDNDIuMjk1IDI3NC45NyA0NC4wMDg3IDI3My43ODkgNDUuMjc4NSAyNzIuMTk2QzQ2LjU0ODIgMjcwLjYwMiA0Ny4zMTcgMjY4LjY2OCA0Ny40ODc2IDI2Ni42MzhDNDcuNjU4MSAyNjQuNjA4IDQ3LjIyMjggMjYyLjU3MyA0Ni4yMzY2IDI2MC43OUM0NS4yNTA0IDI1OS4wMDggNDMuNzU3NyAyNTcuNTU3IDQxLjk0NzMgMjU2LjYyM0M0MC4xMzY5IDI1NS42ODkgMzguMDkgMjU1LjMxMiAzNi4wNjU2IDI1NS41NDFDMzQuMDQxMyAyNTUuNzcgMzIuMTMwMyAyNTYuNTk1IDMwLjU3NDQgMjU3LjkxQzI5LjAxODUgMjU5LjIyNSAyNy44ODc2IDI2MC45NzIgMjcuMzI0NyAyNjIuOTNDMjYuNzYxOCAyNjQuODg4IDI2Ljc5MjIgMjY2Ljk2OSAyNy40MTIgMjY4LjkxQzI4LjI0MyAyNzEuNTEyIDMwLjA3MzEgMjczLjY3NyAzMi41MDAxIDI3NC45MjlDMzQuOTI3MSAyNzYuMTgyIDM3Ljc1MjEgMjc2LjQxOSA0MC4zNTQgMjc1LjU4OVoiIGZpbGw9IiMxODE3MTYiLz4KPHBhdGggZD0iTTY0LjMyMiAzOTkuODM3QzYyLjM4MTIgNDAwLjQ1NiA2MC42Njc2IDQwMS42MzcgNTkuMzk4MSA0MDMuMjMxQzU4LjEyODYgNDA0LjgyNCA1Ny4zNjAxIDQwNi43NTggNTcuMTg5OCA0MDguNzg4QzU3LjAxOTYgNDEwLjgxOSA1Ny40NTUyIDQxMi44NTQgNTguNDQxNyA0MTQuNjM2QzU5LjQyODEgNDE2LjQxOSA2MC45MjEgNDE3Ljg2OSA2Mi43MzE2IDQxOC44MDNDNjQuNTQyMiA0MTkuNzM3IDY2LjU4OTEgNDIwLjExMyA2OC42MTM1IDQxOS44ODRDNzAuNjM3OCA0MTkuNjU0IDcyLjU0ODcgNDE4LjgzIDc0LjEwNDQgNDE3LjUxNEM3NS42NjAxIDQxNi4xOTkgNzYuNzkwNyA0MTQuNDUyIDc3LjM1MzMgNDEyLjQ5M0M3Ny45MTU5IDQxMC41MzUgNzcuODg1MiA0MDguNDU0IDc3LjI2NSA0MDYuNTE0Qzc2LjQzMzcgNDAzLjkxMiA3NC42MDMyIDQwMS43NDggNzIuMTc2IDQwMC40OTVDNjkuNzQ4OSAzOTkuMjQzIDY2LjkyMzggMzk5LjAwNiA2NC4zMjIgMzk5LjgzN1oiIGZpbGw9IiMxODE3MTYiLz4KPHBhdGggZD0iTTc3LjQ3MSAzODUuOTg0TDc0LjMzIDM4NS4zODRDNzQuMTQxNSAzODYuNSA3My44MTc3IDM4Ny41OSA3My4zNjYgMzg4LjYyOEw3Ni4yMTggMzkwLjA3MUM3Ni44MTI5IDM4OC43NjkgNzcuMjM0MiAzODcuMzk1IDc3LjQ3MSAzODUuOTg0WiIgZmlsbD0iIzE4MTcxNiIvPgo8cGF0aCBkPSJNNzYuMDkgMzcwLjIwMUw3My4wNTEgMzcxLjE5Mkw3My4xNDEgMzcxLjQ3M0M3My44NTcyIDM3My42ODMgNzQuMzQwOCAzNzUuOTYyIDc0LjU4NCAzNzguMjczTDc3Ljc2NCAzNzcuOTU0Qzc3LjQ5OTcgMzc1LjQyMSA3Ni45NzA4IDM3Mi45MjMgNzYuMTg2IDM3MC41TDc2LjA5IDM3MC4yMDFaIiBmaWxsPSIjMTgxNzE2Ii8+CjxwYXRoIGQ9Ik02NC4xMzggMzUwLjIxNkM2Mi41MjIgMzQ4LjM0NCA2MC43MzggMzQ2LjQ0OCA1OC44NDggMzQ0LjU4Mkw1Ni42MDUgMzQ2Ljg1OUM1OC40MzcgMzQ4LjY2NiA2MC4xNTkgMzUwLjQ5OCA2MS43MjEgMzUyLjMwNUw2NC4xMzggMzUwLjIxNloiIGZpbGw9IiMxODE3MTYiLz4KPHBhdGggZD0iTTM1Ljc4NyAzMjQuMzk3QzM3LjIxMiAzMjYuNDE4IDM4Ljc5OCAzMjguNDc3IDQwLjUwNCAzMzAuNTJMNDIuOTU3IDMyOC40NzFDNDEuMzA3IDMyNi40OTUgMzkuNzc1IDMyNC41MDUgMzguNCAzMjIuNTU1TDM1Ljc4NyAzMjQuMzk3WiIgZmlsbD0iIzE4MTcxNiIvPgo8cGF0aCBkPSJNNzMuMDAzIDM2Mi45NzNDNzEuNzg2NCAzNjAuNjcxIDcwLjQyMyAzNTguNDUgNjguOTIxIDM1Ni4zMjNMNjYuMzA2IDM1OC4xNjFDNjcuNzI4OCAzNjAuMTc2IDY5LjAyMDUgMzYyLjI4IDcwLjE3MyAzNjQuNDYxTDczLjAwMyAzNjIuOTczWiIgZmlsbD0iIzE4MTcxNiIvPgo8cGF0aCBkPSJNMjguNjc1IDI5NS40NEwyNS40ODIgMjk1LjI2NEMyNS4zNTExIDI5Ny45MjggMjUuNTQ1MiAzMDAuNTk5IDI2LjA2IDMwMy4yMTZMMjkuMiAzMDIuNjE2QzI4LjczMjUgMzAwLjI1NSAyOC41NTYyIDI5Ny44NDUgMjguNjc1IDI5NS40NFoiIGZpbGw9IiMxODE3MTYiLz4KPHBhdGggZD0iTTI4LjI3OSAzMTAuNzgxQzI5LjIzNjggMzEzLjIwNiAzMC4zNTg3IDMxNS41NjMgMzEuNjM3IDMxNy44MzVMMzQuNDI3IDMxNi4yNzVDMzMuMjE5NyAzMTQuMTMxIDMyLjE2MDIgMzExLjkwNiAzMS4yNTYgMzA5LjYxN0wyOC4yNzkgMzEwLjc4MVoiIGZpbGw9IiMxODE3MTYiLz4KPHBhdGggZD0iTTQ3Ljk1NCAzMzQuMDZMNDUuNjM5IDMzNi4yNjVDNDcuMzQ1IDMzOC4wNTcgNDkuMTggMzM5Ljg4IDUxLjA4OCAzNDEuNjgzTDUzLjI4OCAzMzkuMzU5QzUxLjQxMSAzMzcuNTk1IDQ5LjYxOSAzMzUuODEyIDQ3Ljk1NCAzMzQuMDZaIiBmaWxsPSIjMTgxNzE2Ii8+CjxwYXRoIGQ9Ik0yNTUuNTk0IDI4Mi40MTZDMjU0LjQ0NiAyNzMuMTQ1IDI1MS40ODQgMjY0LjE5IDI0Ni44NzYgMjU2LjA2NEMyNDIuMjY4IDI0Ny45MzcgMjM2LjEwNCAyNDAuNzk4IDIyOC43MzcgMjM1LjA1NEMyMjEuMzY5IDIyOS4zMDkgMjEyLjk0MyAyMjUuMDcyIDIwMy45MzggMjIyLjU4NEMxOTQuOTMzIDIyMC4wOTcgMTg1LjUyNyAyMTkuNDA3IDE3Ni4yNTYgMjIwLjU1NEMxNjYuOTg0IDIyMS43MDIgMTU4LjAzIDIyNC42NjQgMTQ5LjkwMyAyMjkuMjczQzE0MS43NzcgMjMzLjg4MSAxMzQuNjM4IDI0MC4wNDQgMTI4Ljg5MyAyNDcuNDEyQzEyMy4xNDkgMjU0Ljc3OSAxMTguOTEyIDI2My4yMDYgMTE2LjQyNCAyNzIuMjFDMTEzLjkzNiAyODEuMjE1IDExMy4yNDYgMjkwLjYyMiAxMTQuMzk0IDI5OS44OTNMMTI4Ljg5NCA0MTYuOTQ2QzEyOS4wMjcgNDE4LjA0NSAxMjkuNTg4IDQxOS4wNDggMTMwLjQ1NSA0MTkuNzM3QzEzMS4zMjIgNDIwLjQyNiAxMzIuNDI1IDQyMC43NDYgMTMzLjUyNiA0MjAuNjI3QzEzNC42MjcgNDIwLjUwOSAxMzUuNjM4IDQxOS45NjIgMTM2LjMzOCA0MTkuMTA1QzEzNy4wMzkgNDE4LjI0NyAxMzcuMzc0IDQxNy4xNDggMTM3LjI3MSA0MTYuMDQ2SDEzNy4yOEwxMzcuMjcgNDE1Ljk2QzEzNy4yNyA0MTUuOTYgMTM3LjI3IDQxNS45NSAxMzcuMjcgNDE1Ljk0NVY0MTUuOTI4TDEzNS44MTUgNDA0LjIwN0wxNTEuNzIzIDQwMi4yMzlMMTUzLjE1NSA0MTMuNzk5QzE1My4yODggNDE0LjkwOSAxNTMuODU2IDQxNS45MjIgMTU0LjczNSA0MTYuNjEzQzE1NS42MTQgNDE3LjMwNSAxNTYuNzMyIDQxNy42MTkgMTU3Ljg0MyA0MTcuNDg2QzE1OC45NTMgNDE3LjM1NCAxNTkuOTY2IDQxNi43ODUgMTYwLjY1NyA0MTUuOTA2QzE2MS4zNDkgNDE1LjAyNyAxNjEuNjYzIDQxMy45MDkgMTYxLjUzIDQxMi43OTlMMTU0LjQwMyAzNTUuMzQ2QzE2NS45MTMgMzYwLjg0NCAxNzguNjkgMzYzLjE0NSAxOTEuMzk0IDM2Mi4wMDZDMjA0LjA5OSAzNjAuODY3IDIxNi4yNjMgMzU2LjMzMSAyMjYuNjExIDM0OC44NzNDMjM2Ljk1OSAzNDEuNDE2IDI0NS4xMSAzMzEuMzExIDI1MC4yMDkgMzE5LjYxOUMyNTUuMzA5IDMwNy45MjcgMjU3LjE2OCAyOTUuMDc5IDI1NS41OTMgMjgyLjQyMUwyNTUuNTk0IDI4Mi40MTZaTTI0Ni4yMjUgMzA0LjczOUwyMzAuNzAxIDMwMC41NThDMjMxLjU0MSAyOTYuNTAxIDIzMS44MzMgMjkyLjM1IDIzMS41NjkgMjg4LjIxNUwyNDcuNTIgMjg2LjI0QzI0OC4wMTIgMjkyLjQzNiAyNDcuNTc2IDI5OC42NzIgMjQ2LjIyNSAzMDQuNzM5Wk0xOTMuNSAzMzcuMDM5QzE5Ny43NzUgMzM2LjI1MSAyMDEuOTE4IDMzNC44NjYgMjA1LjgwNyAzMzIuOTI0TDIxMy44MjggMzQ2Ljg1OUMyMDguMDY3IDM0OS44NDYgMjAxLjg3NSAzNTEuOTE0IDE5NS40NzUgMzUyLjk5TDE5My41IDMzNy4wMzlaTTE4OS43IDMyOS4xMjZDMTc5LjYzNCAzMzAuMzYxIDE2OS40ODkgMzI3LjU1NCAxNjEuNDkgMzIxLjMyQzE1My40OTEgMzE1LjA4NiAxNDguMjkxIDMwNS45MzQgMTQ3LjAzMSAyOTUuODcxVjI5NS44NTZDMTQ2LjEwMSAyODguMzQ2IDE0Ny40MTkgMjgwLjcyOCAxNTAuODE4IDI3My45NjdDMTU0LjIxNyAyNjcuMjA2IDE1OS41NDUgMjYxLjYwNCAxNjYuMTI4IDI1Ny44NzFDMTcyLjcxMSAyNTQuMTM4IDE4MC4yNTMgMjUyLjQ0MSAxODcuOCAyNTIuOTk0QzE5NS4zNDcgMjUzLjU0NyAyMDIuNTYxIDI1Ni4zMjYgMjA4LjUyOSAyNjAuOTc5QzIxNC40OTcgMjY1LjYzMiAyMTguOTUxIDI3MS45NTEgMjIxLjMyOCAyNzkuMTM1QzIyMy43MDUgMjg2LjMyIDIyMy44OTkgMjk0LjA0OCAyMjEuODg0IDMwMS4zNDJDMjE5Ljg2OCAzMDguNjM3IDIxNS43MzUgMzE1LjE3IDIxMC4wMDcgMzIwLjExNUMyMDQuMjc5IDMyNS4wNiAxOTcuMjEzIDMyOC4xOTYgMTg5LjcwMyAzMjkuMTI2SDE4OS43Wk0xNDguNDc3IDM3NS45ODVMMTMyLjU1OSAzNzcuOTUzTDEzMC42NjggMzYyLjcwNkwxNDYuNTg0IDM2MC43MzZMMTQ4LjQ3NyAzNzUuOTg1Wk0xMjkuOTc3IDM1Ny4xNDJMMTI4LjI0IDM0My4xNDJMMTQ0LjE2MSAzNDEuMTcyTDE0NS44OTUgMzU1LjE3MkwxMjkuOTc3IDM1Ny4xNDJaTTEyMy43NjcgMjc3LjU3MUwxMzkuMjkxIDI4MS43NTFDMTM4LjQ1MSAyODUuODA4IDEzOC4xNTkgMjg5Ljk1OSAxMzguNDI0IDI5NC4wOTRMMTIyLjQ3MiAyOTYuMDY5QzEyMS45NzggMjg5Ljg3MiAxMjIuNDE1IDI4My42MzcgMTIzLjc2NyAyNzcuNTdWMjc3LjU3MVpNMTQwLjc0NCAyNzYuMzM1TDEyNS4yMzcgMjcyLjE1OUMxMjcuMjEgMjY1Ljk4MSAxMzAuMTI2IDI2MC4xNDYgMTMzLjg4MiAyNTQuODU5TDE0Ni41NTYgMjY0Ljc0MUMxNDQuMDkgMjY4LjMxNyAxNDIuMTM0IDI3Mi4yMTkgMTQwLjc0NCAyNzYuMzM0VjI3Ni4zMzVaTTEzOS4wMjEgMjk5LjY3MUwxNDAuOTA5IDMxNC45MThMMTI0Ljk4MyAzMTYuODg5TDEyMy4wOTEgMzAxLjY0MkwxMzkuMDIxIDI5OS42NzFaTTE0MS41OTkgMzIwLjQ4NEwxNDMuNDcyIDMzNS42MDZMMTI3LjU1NCAzMzcuNTc2TDEyNS42NzMgMzIyLjQ1M0wxNDEuNTk5IDMyMC40ODRaTTE1MC4zMSAzMjIuMzQzQzE1MS41MTkgMzIzLjY4MiAxNTIuODAzIDMyNC45NTEgMTU0LjE1OCAzMjYuMTQzTDE1MS4yNDYgMzI5Ljg3OEwxNTAuMzEgMzIyLjM0M1pNMTc2LjQ5MSAyNDUuMjcxQzE3Mi4yMTYgMjQ2LjA1OSAxNjguMDc0IDI0Ny40NDUgMTY0LjE4NSAyNDkuMzg3TDE1Ni4xNjQgMjM1LjQ1M0MxNjEuOTI1IDIzMi40NjYgMTY4LjExNyAyMzAuMzk4IDE3NC41MTcgMjI5LjMyMkwxNzYuNDkxIDI0NS4yNzFaTTE5OS44MTcgMjQ2LjkwM0wyMDMuOTkyIDIzMS4zOTdDMjEwLjE3IDIzMy4zNyAyMTYuMDA1IDIzNi4yODUgMjIxLjI5MiAyNDAuMDQxTDIxMS40MDkgMjUyLjcxNUMyMDcuODMzIDI1MC4yNDkgMjAzLjkzMiAyNDguMjkzIDE5OS44MTcgMjQ2LjkwMlYyNDYuOTAzWk0yMzAuODggMjgyLjY1M0MyMzAuMDkyIDI3OC4zNzkgMjI4LjcwNyAyNzQuMjM2IDIyNi43NjUgMjcwLjM0OEwyNDAuNjk5IDI2Mi4zMjZDMjQzLjY4NiAyNjguMDg3IDI0NS43NTUgMjc0LjI3OSAyNDYuODMxIDI4MC42NzlMMjMwLjg4IDI4Mi42NTNaTTIyOS4yNDggMzA1Ljk3OUwyNDQuNzU0IDMxMC4xNTNDMjQyLjc4MiAzMTYuMzMxIDIzOS44NjYgMzIyLjE2NiAyMzYuMTEgMzI3LjQ1M0wyMjMuNDM2IDMxNy41NzFDMjI1LjkwMiAzMTMuOTk0IDIyNy44NTggMzEwLjA5MSAyMjkuMjQ4IDMwNS45NzVWMzA1Ljk3OVpNMjM3Ljg5NSAyNTcuNDdMMjIzLjk2MSAyNjUuNDkxQzIyMS42NzcgMjYyLjAzNyAyMTguOTQ0IDI1OC45MDIgMjE1LjgzNSAyNTYuMTY3TDIyNS43MTcgMjQzLjQ5MkMyMzAuNDQ0IDI0Ny41MjMgMjM0LjU0NyAyNTIuMjMzIDIzNy44OTUgMjU3LjQ2NlYyNTcuNDdaTTE5OC41ODEgMjI5LjkyOUwxOTQuNCAyNDUuNDUzQzE5MC4zNDMgMjQ0LjYxNCAxODYuMTkyIDI0NC4zMjIgMTgyLjA1NyAyNDQuNTg1TDE4MC4wODIgMjI4LjYzNEMxODYuMjc4IDIyOC4xNCAxOTIuNTE0IDIyOC41NzUgMTk4LjU4MSAyMjkuOTI1VjIyOS45MjlaTTE1MS4zMDcgMjM4LjI1OUwxNTkuMzI5IDI1Mi4xOTNDMTU1Ljg3NSAyNTQuNDc4IDE1Mi43NCAyNTcuMjEgMTUwLjAwNCAyNjAuMzE5TDEzNy4zMyAyNTAuNDM3QzE0MS4zNjIgMjQ1LjcwOCAxNDYuMDcyIDI0MS42MDIgMTUxLjMwNyAyMzguMjUzVjIzOC4yNTlaTTEzNS4xMjYgMzk4LjY0TDEzMy4yNTQgMzgzLjUxOEwxNDkuMTY2IDM4MS41NDlMMTUxLjAzOSAzOTYuNjcyTDEzNS4xMjYgMzk4LjY0Wk0xNTIuMjI2IDMzNy43NDhMMTU4LjU4MyAzMjkuNTk0QzE2Mi4xNjEgMzMyLjA2IDE2Ni4wNjUgMzM0LjAxNyAxNzAuMTgzIDMzNS40MDdMMTY2LjAwNiAzNTAuOTE5QzE2MS41MTcgMzQ5LjQ4NCAxNTcuMjAzIDM0Ny41NDkgMTUzLjE0NyAzNDUuMTQ5TDE1Mi4yMjYgMzM3Ljc0OFpNMTcxLjQxNiAzNTIuMzgyTDE3NS41OTUgMzM2Ljg1OUMxNzkuNjUyIDMzNy42OTkgMTgzLjgwNCAzMzcuOTkxIDE4Ny45MzkgMzM3LjcyN0wxODkuOTE0IDM1My42ODJDMTgzLjcxNiAzNTQuMTc1IDE3Ny40OCAzNTMuNzM2IDE3MS40MTIgMzUyLjM4MkgxNzEuNDE2Wk0yMTguNjg5IDM0NC4wNTNMMjEwLjY2NyAzMzAuMTE5QzIxNC4xMjEgMzI3LjgzNCAyMTcuMjU3IDMyNS4xMDIgMjE5Ljk5MiAzMjEuOTkzTDIzMi42NjYgMzMxLjg3NUMyMjguNjMyIDMzNi42MDIgMjIzLjkyMSAzNDAuNzA2IDIxOC42ODUgMzQ0LjA1M0gyMTguNjg5WiIgZmlsbD0iIzE4MTcxNiIvPgo8cGF0aCBkPSJNMzI4LjQxMyAzMjQuMjUzQzMyNi44OTEgMzIxLjQ5NiAzMjQuNjk3IDMxOS4xNjggMzIyLjAzNSAzMTcuNDg1QzMxOS4zNzMgMzE1LjgwMiAzMTYuMzI5IDMxNC44MTkgMzEzLjE4NiAzMTQuNjI2QzMxMy4zMzkgMzEzLjU5OSAzMTMuNTQzIDMxMi41OCAzMTMuNzk4IDMxMS41NzNDMzE1LjQ2NyAzMDUuMDA2IDMxNi41MTIgMzAyLjEwNiAzMTcuODE1IDI5Ny40NDZDMzE5LjMyOCAyOTIuMDM2IDMxOS40MzQgMjkxLjc3IDMyMS4wNTMgMjg1LjQ3NEMzMjMuNDMyIDI3Ni4yMTcgMzIzLjU1MyAyNjUuMTE1IDMxOS40OTcgMjU2LjI4MkMzMTguMTE4IDI1My4yNDEgMzE2LjEyNyAyNTAuNTE2IDMxMy42NDcgMjQ4LjI4QzMxMS4xNjcgMjQ2LjA0MyAzMDguMjUzIDI0NC4zNDIgMzA1LjA4NiAyNDMuMjgyQzI5Ny42OTQgMjQxLjA1MSAyODcuMDAxIDI0Mi4xNjUgMjgxLjUzOSAyNDguM0MyNzguMTQ4IDI1Mi4xMDkgMjc2LjQyMiAyNTUuNDYgMjc2LjA4MSAyNjAuNzc2QzI3NS43OTIgMjY1LjI4MyAyNzcuNDQ5IDI3MC43OTYgMjgwLjYzMSAyNzQuMTE2QzI4Mi4xOTEgMjc1LjY2NyAyODMuOTQ1IDI3Ny4wMDggMjg1Ljg1IDI3OC4xMDdDMjg1LjYxNiAyODAuMDczIDI4NS4yNjMgMjgyLjAyMiAyODQuNzkzIDI4My45NDVDMjgwLjk5MyAyOTkuNTk3IDI3OC4xNTggMzAyLjg3NiAyNzYuNTE3IDMxMi42NDVDMjc0LjgxMSAzMjIuODA0IDI3OC4xNTYgMzM0LjU2OCAyODUuNjY4IDM0MS45ODVDMjk1LjA5IDM1MS4yODUgMzA3LjkwNyAzNTQuMzE0IDMyMC4yMDkgMzQ4Ljk3OUMzMjkuMDYzIDM0NS4xMyAzMzMuMDcgMzMyLjYwMiAzMjguNDEzIDMyNC4yNTNaTTMwNC44ODkgMjUwLjc1M0MzMDcuODU0IDI1Mi44OTIgMzExLjAwMSAyNTcuODA1IDMxMi40NiAyNjAuODg0QzMxNS4yNjkgMjY2LjU1IDMxNi40NzYgMjcyLjg3NSAzMTUuOTUyIDI3OS4xNzdDMzE1LjU0NSAyODUuMjI2IDMxMy45NTIgMjkyLjU2MyAzMTMuMjEyIDI5Mi40NTlDMzEyLjQ3MiAyOTIuMzU1IDMxNC4yNjYgMjc5LjI2OSAzMDguMTM1IDI2OC43NTlDMzAyLjU4MSAyNTkuMjM0IDI5NC40MTggMjU3LjExNiAyOTQuNjkgMjUxLjM3NUMyOTQuODYgMjQ3Ljc4IDI5OS45NDcgMjQ3LjE4MyAzMDQuODg5IDI1MC43NTNaIiBmaWxsPSIjMTgxNzE2Ii8+CjxwYXRoIGQ9Ik0zMjAuMjk2IDIxMi4yNjZDMzE5Ljg0OSAyMDIuMjg5IDMxMi4yMDUgMTkzLjg1MSAzMDEuODgxIDE5My44NTFDMjkyLjI0OSAxOTMuODUxIDI4My4wMjEgMjAyLjMyMSAyODMuNDY2IDIxMi4yNjZDMjgzLjkxMyAyMjIuMjQzIDI5MS41NTcgMjMwLjY4MSAzMDEuODgxIDIzMC42ODFDMzExLjUxMyAyMzAuNjgxIDMyMC43NDEgMjIyLjIxMSAzMjAuMjk2IDIxMi4yNjZaTTMxMi40ODIgMjIwLjI1NUMzMTEuMjc2IDIyMS45MTkgMzEyLjc4MiAyMTAuOTM1IDMwNS4xMTUgMjA3LjYyNEMzMDAuMTY3IDIwNS40ODcgMjk2LjA3MSAyMDUuMDQ4IDI5NS44MTUgMjAyLjE4NUMyOTUuNzMxIDIwMS43MTcgMjk1Ljc5OCAyMDEuMjMzIDI5Ni4wMDcgMjAwLjgwNkMyOTYuMjE2IDIwMC4zNzggMjk2LjU1NiAyMDAuMDI4IDI5Ni45NzggMTk5LjgwN0MyOTcuODU3IDE5OS4xNTQgMjk5LjE2OCAxOTguOTM4IDMwMS4yOTggMTk5LjEwN0MzMDMuOTk3IDE5OS4yNDggMzA2LjU5OSAyMDAuMTU1IDMwOC44MDEgMjAxLjcyMkMzMTEuMDAzIDIwMy4yODkgMzEyLjcxNCAyMDUuNDUgMzEzLjczMiAyMDcuOTUzQzMxNC41OTggMjA5LjkzOCAzMTQuOTM4IDIxMi4xMTIgMzE0LjcxOSAyMTQuMjY3QzMxNC41IDIxNi40MjEgMzEzLjcyOSAyMTguNDgzIDMxMi40ODIgMjIwLjI1M1YyMjAuMjU1WiIgZmlsbD0iIzE4MTcxNiIvPgo8cGF0aCBkPSJNMzc4Ljc2IDMyMy4xNjlDMzc2LjA2MSAzMjMuMTcxIDM3My40MjggMzIyLjMyOCAzNzEuMjMyIDMyMC43NThDMzY5LjAzNiAzMTkuMTg4IDM2Ny4zODcgMzE2Ljk3IDM2Ni41MTUgMzE0LjQxNUMzNjUuNjQ0IDMxMS44NiAzNjUuNTk0IDMwOS4wOTcgMzY2LjM3NCAzMDYuNTEyQzM2Ny4xNTMgMzAzLjkyNyAzNjguNzIyIDMwMS42NTIgMzcwLjg2IDMwMC4wMDRMMzU5LjE2IDI5MS42MDRWMzUxLjM5M0MzNTkuMTYgMzU2LjU5MSAzNjEuMjI1IDM2MS41NzcgMzY0LjkwMSAzNjUuMjUyQzM2OC41NzYgMzY4LjkyOCAzNzMuNTYyIDM3MC45OTMgMzc4Ljc2IDM3MC45OTNDMzgzLjk1OCAzNzAuOTkzIDM4OC45NDQgMzY4LjkyOCAzOTIuNjE5IDM2NS4yNTJDMzk2LjI5NSAzNjEuNTc3IDM5OC4zNiAzNTYuNTkxIDM5OC4zNiAzNTEuMzkzVjMxOS43NTNMMzkwLjk3OCAzMTQuNDUzQzM5MC4xMDEgMzE2Ljk5NiAzODguNDUzIDMxOS4yMDMgMzg2LjI2MyAzMjAuNzY1QzM4NC4wNzMgMzIyLjMyNyAzODEuNDUgMzIzLjE2OCAzNzguNzYgMzIzLjE2OVpNMzc4Ljc2IDM2Mi4zNjlDMzc2LjIwMSAzNjIuMzY5IDM3My43IDM2MS42MSAzNzEuNTczIDM2MC4xODlDMzY5LjQ0NiAzNTguNzY3IDM2Ny43ODggMzU2Ljc0NyAzNjYuODA5IDM1NC4zODNDMzY1LjgzIDM1Mi4wMiAzNjUuNTczIDM0OS40MTkgMzY2LjA3MyAzNDYuOTA5QzM2Ni41NzIgMzQ0LjQgMzY3LjgwNCAzNDIuMDk1IDM2OS42MTMgMzQwLjI4NkMzNzEuNDIyIDMzOC40NzcgMzczLjcyNyAzMzcuMjQ1IDM3Ni4yMzYgMzM2Ljc0NkMzNzguNzQ2IDMzNi4yNDYgMzgxLjM0NyAzMzYuNTAzIDM4My43MSAzMzcuNDgyQzM4Ni4wNzQgMzM4LjQ2MSAzODguMDk0IDM0MC4xMTkgMzg5LjUxNiAzNDIuMjQ2QzM5MC45MzcgMzQ0LjM3MyAzOTEuNjk2IDM0Ni44NzUgMzkxLjY5NiAzNDkuNDMzQzM5MS42OTYgMzUxLjEzMiAzOTEuMzYxIDM1Mi44MTQgMzkwLjcxMSAzNTQuMzgzQzM5MC4wNjEgMzU1Ljk1MiAzODkuMTA4IDM1Ny4zNzggMzg3LjkwNyAzNTguNTc5QzM4Ni43MDUgMzU5Ljc4IDM4NS4yNzkgMzYwLjczMyAzODMuNzEgMzYxLjM4M0MzODIuMTQxIDM2Mi4wMzMgMzgwLjQ1OSAzNjIuMzY3IDM3OC43NiAzNjIuMzY3VjM2Mi4zNjlaIiBmaWxsPSIjMTgxNzE2Ii8+CjxwYXRoIGQ9Ik0zNzEuMTA3IDE5Ni4xNzNDMzcxLjEwNiAxOTQuMTEgMzcxLjcxOCAxOTIuMDk0IDM3Mi44NjUgMTkwLjM3OUMzNzQuMDEyIDE4OC42NjUgMzc1LjY0MyAxODcuMzMgMzc3LjU1IDE4Ni41NDRDMzc5LjQ1NyAxODUuNzU4IDM4MS41NTUgMTg1LjU1NiAzODMuNTc3IDE4NS45NjVDMzg1LjU5OSAxODYuMzczIDM4Ny40NTQgMTg3LjM3MyAzODguOTA3IDE4OC44MzhDMzg4LjMxOCAxODcuNDE4IDM4Ny40MjIgMTg2LjE0NSAzODYuMjgyIDE4NS4xMTJDMzg1LjE0MyAxODQuMDggMzgzLjc4OSAxODMuMzEyIDM4Mi4zMTggMTgyLjg2NUMzODAuODQ3IDE4Mi40MTggMzc5LjI5NCAxODIuMzAyIDM3Ny43NzMgMTgyLjUyNkMzNzYuMjUyIDE4Mi43NSAzNzQuNzk5IDE4My4zMDkgMzczLjUxOSAxODQuMTYxQzM3Mi4yMzkgMTg1LjAxNCAzNzEuMTY0IDE4Ni4xNCAzNzAuMzcxIDE4Ny40NTdDMzY5LjU3OCAxODguNzc1IDM2OS4wODcgMTkwLjI1MSAzNjguOTMzIDE5MS43ODJDMzY4Ljc3OSAxOTMuMzEyIDM2OC45NjYgMTk0Ljg1NyAzNjkuNDggMTk2LjMwNkMzNjkuOTk0IDE5Ny43NTUgMzcwLjgyMyAxOTkuMDczIDM3MS45MDcgMjAwLjE2M0MzNzEuMzc5IDE5OC44OTkgMzcxLjEwNyAxOTcuNTQzIDM3MS4xMDcgMTk2LjE3M1oiIGZpbGw9IiMxODE3MTYiLz4KPHBhdGggZD0iTTM3MS4xMDcgMjM1LjIxMkMzNzEuMTA2IDIzMy4xNDkgMzcxLjcxOCAyMzEuMTMyIDM3Mi44NjUgMjI5LjQxOEMzNzQuMDEyIDIyNy43MDMgMzc1LjY0MyAyMjYuMzY4IDM3Ny41NSAyMjUuNTgyQzM3OS40NTcgMjI0Ljc5NiAzODEuNTU1IDIyNC41OTUgMzgzLjU3NyAyMjUuMDAzQzM4NS41OTkgMjI1LjQxMiAzODcuNDU0IDIyNi40MTIgMzg4LjkwNyAyMjcuODc3QzM4OC4zMTggMjI2LjQ1NiAzODcuNDIyIDIyNS4xODQgMzg2LjI4MiAyMjQuMTUxQzM4NS4xNDMgMjIzLjExOCAzODMuNzg5IDIyMi4zNTEgMzgyLjMxOCAyMjEuOTAzQzM4MC44NDcgMjIxLjQ1NiAzNzkuMjk0IDIyMS4zNDEgMzc3Ljc3MyAyMjEuNTY1QzM3Ni4yNTIgMjIxLjc4OSAzNzQuNzk5IDIyMi4zNDcgMzczLjUxOSAyMjMuMkMzNzIuMjM5IDIyNC4wNTMgMzcxLjE2NCAyMjUuMTc4IDM3MC4zNzEgMjI2LjQ5NkMzNjkuNTc4IDIyNy44MTMgMzY5LjA4NyAyMjkuMjkgMzY4LjkzMyAyMzAuODJDMzY4Ljc3OSAyMzIuMzUgMzY4Ljk2NiAyMzMuODk1IDM2OS40OCAyMzUuMzQ1QzM2OS45OTQgMjM2Ljc5NCAzNzAuODIzIDIzOC4xMTEgMzcxLjkwNyAyMzkuMjAyQzM3MS4zNzkgMjM3LjkzOCAzNzEuMTA3IDIzNi41ODIgMzcxLjEwNyAyMzUuMjEyWiIgZmlsbD0iIzE4MTcxNiIvPgo8cGF0aCBkPSJNMzcxLjEwNyAzNTMuNDQ2QzM3MS4xMDYgMzUxLjM4MyAzNzEuNzE3IDM0OS4zNjYgMzcyLjg2NSAzNDcuNjUyQzM3NC4wMTIgMzQ1LjkzNyAzNzUuNjQyIDM0NC42MDIgMzc3LjU1IDM0My44MTZDMzc5LjQ1NyAzNDMuMDMgMzgxLjU1NSAzNDIuODI4IDM4My41NzcgMzQzLjIzN0MzODUuNTk5IDM0My42NDUgMzg3LjQ1NCAzNDQuNjQ1IDM4OC45MDcgMzQ2LjExQzM4OC4zMTggMzQ0LjY5IDM4Ny40MjIgMzQzLjQxNyAzODYuMjgyIDM0Mi4zODRDMzg1LjE0MyAzNDEuMzUyIDM4My43ODkgMzQwLjU4NCAzODIuMzE4IDM0MC4xMzdDMzgwLjg0NyAzMzkuNjkgMzc5LjI5NCAzMzkuNTc0IDM3Ny43NzMgMzM5Ljc5OEMzNzYuMjUyIDM0MC4wMjIgMzc0Ljc5OSAzNDAuNTgxIDM3My41MTkgMzQxLjQzM0MzNzIuMjM5IDM0Mi4yODYgMzcxLjE2NCAzNDMuNDExIDM3MC4zNzEgMzQ0LjcyOUMzNjkuNTc4IDM0Ni4wNDcgMzY5LjA4NyAzNDcuNTIzIDM2OC45MzMgMzQ5LjA1NEMzNjguNzc5IDM1MC41ODQgMzY4Ljk2NiAzNTIuMTI5IDM2OS40OCAzNTMuNTc4QzM2OS45OTQgMzU1LjAyNyAzNzAuODIzIDM1Ni4zNDUgMzcxLjkwNyAzNTcuNDM1QzM3MS4zNzkgMzU2LjE3MiAzNzEuMTA3IDM1NC44MTYgMzcxLjEwNyAzNTMuNDQ2WiIgZmlsbD0iIzE4MTcxNiIvPgo8cGF0aCBkPSJNNDU0Ljc0NiAzMDMuNTE2TDQyMi4wNzUgMjc4Ljg5MUw0MTQuODI4IDI4Mi43MDVDNDE3LjI2IDI4My40NzYgNDE5LjQxIDI4NC45NDggNDIxLjAwNyAyODYuOTM4QzQyMi42MDQgMjg4LjkyNyA0MjMuNTc4IDI5MS4zNDUgNDIzLjgwNCAyOTMuODg2QzQyNC4wMyAyOTYuNDI3IDQyMy41IDI5OC45NzkgNDIyLjI4IDMwMS4yMTlDNDIxLjA1OSAzMDMuNDYgNDE5LjIwMyAzMDUuMjg5IDQxNi45NDYgMzA2LjQ3N0M0MTQuNjg4IDMwNy42NjUgNDEyLjEyOSAzMDguMTU5IDQwOS41OTIgMzA3Ljg5N0M0MDcuMDU0IDMwNy42MzQgNDA0LjY1IDMwNi42MjcgNDAyLjY4NCAzMDUuMDAxQzQwMC43MTcgMzAzLjM3NiAzOTkuMjc2IDMwMS4yMDUgMzk4LjU0IDI5OC43NjJDMzk3LjgwNCAyOTYuMzE5IDM5Ny44MDggMjkzLjcxMyAzOTguNTUgMjkxLjI3MkwzOTEuMDc3IDI5NS4yMDRDMzg4LjQxMiAyOTYuNTA0IDM4NS42MzQgMjk3LjU1OSAzODIuNzc3IDI5OC4zNTVMNDMxLjE1NCAzMzQuODE5QzQzMy4yMDYgMzM2LjQwOSA0MzUuNTUzIDMzNy41NzYgNDM4LjA2IDMzOC4yNTFDNDQwLjU2NiAzMzguOTI3IDQ0My4xODIgMzM5LjA5OCA0NDUuNzU1IDMzOC43NTRDNDQ4LjMyOCAzMzguNDEgNDUwLjgwNyAzMzcuNTU5IDQ1My4wNDggMzM2LjI0OUM0NTUuMjkgMzM0LjkzOSA0NTcuMjQ4IDMzMy4xOTcgNDU4LjgxMSAzMzEuMTI0QzQ2MC4zNzQgMzI5LjA1MiA0NjEuNTA5IDMyNi42ODkgNDYyLjE1MSAzMjQuMTc0QzQ2Mi43OTMgMzIxLjY1OCA0NjIuOTI5IDMxOS4wNDEgNDYyLjU1MSAzMTYuNDcyQzQ2Mi4xNzMgMzEzLjkwNCA0NjEuMjg4IDMxMS40MzcgNDU5Ljk0OSAzMDkuMjEzQzQ1OC42MDkgMzA2Ljk4OSA0NTYuODQyIDMwNS4wNTQgNDU0Ljc0OCAzMDMuNTE5TDQ1NC43NDYgMzAzLjUxNlpNNDUyLjU0NiAzMjYuNDAzQzQ1MS4wMDYgMzI4LjQ0NiA0NDguODk1IDMyOS45ODcgNDQ2LjQ4IDMzMC44M0M0NDQuMDY0IDMzMS42NzMgNDQxLjQ1MyAzMzEuNzgxIDQzOC45NzYgMzMxLjE0QzQzNi41IDMzMC40OTkgNDM0LjI2OSAzMjkuMTM5IDQzMi41NjUgMzI3LjIzQzQzMC44NjIgMzI1LjMyMSA0MjkuNzYzIDMyMi45NSA0MjkuNDA3IDMyMC40MTdDNDI5LjA1MSAzMTcuODgzIDQyOS40NTUgMzE1LjMwMSA0MzAuNTY2IDMxMi45OTdDNDMxLjY3OCAzMTAuNjkzIDQzMy40NDggMzA4Ljc3IDQzNS42NTMgMzA3LjQ3MkM0MzcuODU3IDMwNi4xNzQgNDQwLjM5NyAzMDUuNTU4IDQ0Mi45NTEgMzA1LjcwM0M0NDUuNTA1IDMwNS44NDkgNDQ3Ljk1OSAzMDYuNzQ4IDQ1MC4wMDIgMzA4LjI4OEM0NTEuMzU5IDMwOS4zMSA0NTIuNTAyIDMxMC41ODkgNDUzLjM2NSAzMTIuMDUyQzQ1NC4yMjcgMzEzLjUxNiA0NTQuNzkzIDMxNS4xMzUgNDU1LjAzIDMxNi44MTdDNDU1LjI2NyAzMTguNDk5IDQ1NS4xNzEgMzIwLjIxMiA0NTQuNzQ2IDMyMS44NTZDNDU0LjMyMSAzMjMuNTAxIDQ1My41NzYgMzI1LjA0NiA0NTIuNTU0IDMyNi40MDNINDUyLjU0NloiIGZpbGw9IiMxODE3MTYiLz4KPHBhdGggZD0iTTM4NC44NTQgMjg5LjY3MkMzODQuOTU0IDI4OS42MjIgMzg1LjA1NCAyODkuNTcyIDM4NS4xNiAyODkuNTI1TDQ1Ny40NDUgMjUxLjgyNUM0NTkuNzQgMjUwLjY0MiA0NjEuNzc5IDI0OS4wMTcgNDYzLjQ0NCAyNDcuMDQ0QzQ2NS4xMDkgMjQ1LjA3MSA0NjYuMzY4IDI0Mi43ODggNDY3LjE0OCAyNDAuMzI3QzQ2Ny45MjkgMjM3Ljg2NiA0NjguMjE1IDIzNS4yNzUgNDY3Ljk5MSAyMzIuNzAzQzQ2Ny43NjcgMjMwLjEzMSA0NjcuMDM3IDIyNy42MjggNDY1Ljg0MyAyMjUuMzM5QzQ2NC42NDkgMjIzLjA1IDQ2My4wMTUgMjIxLjAxOSA0NjEuMDM0IDIxOS4zNjNDNDU5LjA1MiAyMTcuNzA4IDQ1Ni43NjQgMjE2LjQ2IDQ1NC4yOTkgMjE1LjY5MUM0NTEuODM0IDIxNC45MjMgNDQ5LjI0MiAyMTQuNjQ5IDQ0Ni42NyAyMTQuODg1QzQ0NC4wOTkgMjE1LjEyMiA0NDEuNiAyMTUuODY0IDQzOS4zMTcgMjE3LjA2OUwzOTguMzYgMjM4LjQzMVYxOTEuNDYyQzM5OC4zNiAxODYuMjY0IDM5Ni4yOTUgMTgxLjI3OCAzOTIuNjE5IDE3Ny42MDNDMzg4Ljk0NCAxNzMuOTI3IDM4My45NTggMTcxLjg2MiAzNzguNzYgMTcxLjg2MkMzNzMuNTYyIDE3MS44NjIgMzY4LjU3NiAxNzMuOTI3IDM2NC45MDEgMTc3LjYwM0MzNjEuMjI1IDE4MS4yNzggMzU5LjE2IDE4Ni4yNjQgMzU5LjE2IDE5MS40NjJWMjYyLjI4NkMzNTcuNDkzIDI2NS4xNDYgMzU2LjU3OCAyNjguMzgyIDM1Ni41IDI3MS42OTFDMzU2LjQyMyAyNzUuMDAxIDM1Ny4xODUgMjc4LjI3NiAzNTguNzE3IDI4MS4yMTFDMzU4Ljg1NyAyODEuNDc4IDM1OS4wMSAyODEuNzMzIDM1OS4xNiAyODEuOTkxTDM1OS4zMjMgMjgyLjI3OUMzNjEuNzM5IDI4Ni4yOTQgMzY1LjUxNyAyODkuMzA4IDM2OS45NjkgMjkwLjc3MkMzNzQuNDIxIDI5Mi4yMzUgMzc5LjI1MSAyOTIuMDUxIDM4My41NzggMjkwLjI1M0wzODQuODU0IDI4OS42NzJaTTM3OC43NiAyODMuNzA4QzM3Ni4yMDEgMjgzLjcwOCAzNzMuNyAyODIuOTQ5IDM3MS41NzMgMjgxLjUyOEMzNjkuNDQ2IDI4MC4xMDYgMzY3Ljc4OCAyNzguMDg2IDM2Ni44MDkgMjc1LjcyMkMzNjUuODMgMjczLjM1OCAzNjUuNTczIDI3MC43NTcgMzY2LjA3MyAyNjguMjQ4QzM2Ni41NzIgMjY1LjczOCAzNjcuODA0IDI2My40MzMgMzY5LjYxMyAyNjEuNjI0QzM3MS40MjIgMjU5LjgxNSAzNzMuNzI3IDI1OC41ODMgMzc2LjIzNyAyNTguMDg0QzM3OC43NDYgMjU3LjU4NSAzODEuMzQ3IDI1Ny44NDIgMzgzLjcxMSAyNTguODIxQzM4Ni4wNzUgMjU5LjggMzg4LjA5NSAyNjEuNDU4IDM4OS41MTYgMjYzLjU4NkMzOTAuOTM4IDI2NS43MTMgMzkxLjY5NiAyNjguMjE0IDM5MS42OTYgMjcwLjc3M0MzOTEuNjk2IDI3Mi40NzIgMzkxLjM2MSAyNzQuMTU0IDM5MC43MTEgMjc1LjcyM0MzOTAuMDYxIDI3Ny4yOTIgMzg5LjEwOCAyNzguNzE4IDM4Ny45MDcgMjc5LjkyQzM4Ni43MDYgMjgxLjEyMSAzODUuMjggMjgyLjA3NCAzODMuNzEgMjgyLjcyM0MzODIuMTQxIDI4My4zNzMgMzgwLjQ1OSAyODMuNzA4IDM3OC43NiAyODMuNzA4Wk0zNzguNzYgMjQ0LjUwOEMzNzYuMjAxIDI0NC41MDggMzczLjcgMjQzLjc0OSAzNzEuNTczIDI0Mi4zMjhDMzY5LjQ0NiAyNDAuOTA2IDM2Ny43ODggMjM4Ljg4NiAzNjYuODA5IDIzNi41MjJDMzY1LjgzIDIzNC4xNTggMzY1LjU3MyAyMzEuNTU3IDM2Ni4wNzMgMjI5LjA0OEMzNjYuNTcyIDIyNi41MzkgMzY3LjgwNCAyMjQuMjM0IDM2OS42MTMgMjIyLjQyNUMzNzEuNDIyIDIyMC42MTYgMzczLjcyNyAyMTkuMzg0IDM3Ni4yMzYgMjE4Ljg4NEMzNzguNzQ2IDIxOC4zODUgMzgxLjM0NyAyMTguNjQxIDM4My43MSAyMTkuNjIxQzM4Ni4wNzQgMjIwLjYgMzg4LjA5NCAyMjIuMjU4IDM4OS41MTYgMjI0LjM4NUMzOTAuOTM3IDIyNi41MTIgMzkxLjY5NiAyMjkuMDEzIDM5MS42OTYgMjMxLjU3MkMzOTEuNjk2IDIzMy4yNzEgMzkxLjM2MiAyMzQuOTUzIDM5MC43MTIgMjM2LjUyM0MzOTAuMDYyIDIzOC4wOTMgMzg5LjEwOSAyMzkuNTE5IDM4Ny45MDggMjQwLjcyQzM4Ni43MDcgMjQxLjkyMiAzODUuMjggMjQyLjg3NSAzODMuNzExIDI0My41MjVDMzgyLjE0MSAyNDQuMTc1IDM4MC40NTkgMjQ0LjUxIDM3OC43NiAyNDQuNTFWMjQ0LjUwOFpNMzc4Ljc2IDIwNS4zMDhDMzc2LjIwMSAyMDUuMzA4IDM3My43IDIwNC41NDkgMzcxLjU3MyAyMDMuMTI4QzM2OS40NDYgMjAxLjcwNiAzNjcuNzg4IDE5OS42ODYgMzY2LjgwOSAxOTcuMzIyQzM2NS44MyAxOTQuOTU4IDM2NS41NzMgMTkyLjM1NyAzNjYuMDczIDE4OS44NDhDMzY2LjU3MiAxODcuMzM5IDM2Ny44MDQgMTg1LjAzNCAzNjkuNjEzIDE4My4yMjVDMzcxLjQyMiAxODEuNDE2IDM3My43MjcgMTgwLjE4NCAzNzYuMjM2IDE3OS42ODRDMzc4Ljc0NiAxNzkuMTg1IDM4MS4zNDcgMTc5LjQ0MSAzODMuNzEgMTgwLjQyMUMzODYuMDc0IDE4MS40IDM4OC4wOTQgMTgzLjA1OCAzODkuNTE2IDE4NS4xODVDMzkwLjkzNyAxODcuMzEyIDM5MS42OTYgMTg5LjgxMyAzOTEuNjk2IDE5Mi4zNzJDMzkxLjY5NyAxOTQuMDcxIDM5MS4zNjIgMTk1Ljc1MyAzOTAuNzEyIDE5Ny4zMjNDMzkwLjA2MyAxOTguODkzIDM4OS4xMSAyMDAuMzIgMzg3LjkwOCAyMDEuNTIxQzM4Ni43MDcgMjAyLjcyMyAzODUuMjgxIDIwMy42NzYgMzgzLjcxMSAyMDQuMzI2QzM4Mi4xNDIgMjA0Ljk3NiAzODAuNDU5IDIwNS4zMTEgMzc4Ljc2IDIwNS4zMTFWMjA1LjMwOFpNNDE4Ljc5OCAyNjQuNDYxQzQxNi41MyAyNjUuNjQ0IDQxMy45NjIgMjY2LjEyOCA0MTEuNDE4IDI2NS44NTFDNDA4Ljg3NSAyNjUuNTc1IDQwNi40NzEgMjY0LjU1IDQwNC41MSAyNjIuOTA3QzQwMi41NDkgMjYxLjI2NCA0MDEuMTE5IDI1OS4wNzcgNDAwLjQwMSAyNTYuNjIxQzM5OS42ODMgMjU0LjE2NiAzOTkuNzEgMjUxLjU1MyA0MDAuNDc3IDI0OS4xMTJDNDAxLjI0NCAyNDYuNjcyIDQwMi43MTggMjQ0LjUxNCA0MDQuNzEyIDI0Mi45MTFDNDA2LjcwNiAyNDEuMzA4IDQwOS4xMyAyNDAuMzMyIDQxMS42NzkgMjQwLjEwN0M0MTQuMjI3IDIzOS44ODIgNDE2Ljc4NSAyNDAuNDE4IDQxOS4wMjkgMjQxLjY0NkM0MjEuMjczIDI0Mi44NzUgNDIzLjEwMiAyNDQuNzQyIDQyNC4yODUgMjQ3LjAxQzQyNS4wNzEgMjQ4LjUxNiA0MjUuNTUyIDI1MC4xNjIgNDI1LjcwMiAyNTEuODU1QzQyNS44NTIgMjUzLjU0NyA0MjUuNjY2IDI1NS4yNTMgNDI1LjE1NyAyNTYuODczQzQyNC42NDcgMjU4LjQ5NCA0MjMuODI0IDI1OS45OTkgNDIyLjczMiAyNjEuMzAxQzQyMS42NDEgMjYyLjYwMyA0MjAuMzA0IDI2My42NzggNDE4Ljc5OCAyNjQuNDY0VjI2NC40NjFaTTQ1My41NTQgMjQ2LjMzN0M0NTEuMjg1IDI0Ny41MiA0NDguNzE3IDI0OC4wMDQgNDQ2LjE3MyAyNDcuNzI3QzQ0My42MyAyNDcuNDUxIDQ0MS4yMjYgMjQ2LjQyNiA0MzkuMjY0IDI0NC43ODNDNDM3LjMwMyAyNDMuMTQgNDM1Ljg3MyAyNDAuOTUyIDQzNS4xNTUgMjM4LjQ5NkM0MzQuNDM4IDIzNi4wNDEgNDM0LjQ2NCAyMzMuNDI3IDQzNS4yMzIgMjMwLjk4NkM0MzUuOTk5IDIyOC41NDYgNDM3LjQ3MyAyMjYuMzg3IDQzOS40NjcgMjI0Ljc4NEM0NDEuNDYyIDIyMy4xODIgNDQzLjg4NiAyMjIuMjA2IDQ0Ni40MzUgMjIxLjk4MUM0NDguOTg0IDIyMS43NTYgNDUxLjU0MiAyMjIuMjkyIDQ1My43ODYgMjIzLjUyMUM0NTYuMDMgMjI0Ljc1IDQ1Ny44NTkgMjI2LjYxNyA0NTkuMDQyIDIyOC44ODZDNDU5LjgyOCAyMzAuMzkyIDQ2MC4zMDkgMjMyLjAzOCA0NjAuNDU4IDIzMy43M0M0NjAuNjA3IDIzNS40MjIgNDYwLjQyMiAyMzcuMTI3IDQ1OS45MTIgMjM4Ljc0OEM0NTkuNDAzIDI0MC4zNjggNDU4LjU3OSAyNDEuODczIDQ1Ny40ODggMjQzLjE3NUM0NTYuMzk3IDI0NC40NzcgNDU1LjA2IDI0NS41NTEgNDUzLjU1NCAyNDYuMzM3WiIgZmlsbD0iIzE4MTcxNiIvPgo8cGF0aCBkPSJNMzcxLjEwNyAyNzQuMzQ1QzM3MS4xMDYgMjcyLjI4MiAzNzEuNzE3IDI3MC4yNjUgMzcyLjg2NSAyNjguNTUxQzM3NC4wMTIgMjY2LjgzNiAzNzUuNjQyIDI2NS41MDEgMzc3LjU1IDI2NC43MTVDMzc5LjQ1NyAyNjMuOTI5IDM4MS41NTUgMjYzLjcyNyAzODMuNTc3IDI2NC4xMzZDMzg1LjU5OSAyNjQuNTQ0IDM4Ny40NTQgMjY1LjU0NCAzODguOTA3IDI2Ny4wMDlDMzg4LjMxOCAyNjUuNTg5IDM4Ny40MjIgMjY0LjMxNiAzODYuMjgyIDI2My4yODNDMzg1LjE0MyAyNjIuMjUxIDM4My43ODkgMjYxLjQ4MyAzODIuMzE4IDI2MS4wMzZDMzgwLjg0NyAyNjAuNTg5IDM3OS4yOTQgMjYwLjQ3MyAzNzcuNzczIDI2MC42OTdDMzc2LjI1MiAyNjAuOTIxIDM3NC43OTkgMjYxLjQ4IDM3My41MTkgMjYyLjMzMkMzNzIuMjM5IDI2My4xODUgMzcxLjE2NCAyNjQuMzEgMzcwLjM3MSAyNjUuNjI4QzM2OS41NzggMjY2Ljk0NiAzNjkuMDg3IDI2OC40MjIgMzY4LjkzMyAyNjkuOTUyQzM2OC43NzkgMjcxLjQ4MiAzNjguOTY2IDI3My4wMjggMzY5LjQ4IDI3NC40NzdDMzY5Ljk5NCAyNzUuOTI2IDM3MC44MjMgMjc3LjI0MyAzNzEuOTA3IDI3OC4zMzRDMzcxLjM3OSAyNzcuMDcgMzcxLjEwNyAyNzUuNzE1IDM3MS4xMDcgMjc0LjM0NVoiIGZpbGw9IiMxODE3MTYiLz4KPHBhdGggZD0iTTQwNS4zMTMgMjU2LjkxNkM0MDUuMzEyIDI1NC44NTMgNDA1LjkyNCAyNTIuODM2IDQwNy4wNzEgMjUxLjEyMkM0MDguMjE4IDI0OS40MDcgNDA5Ljg0OSAyNDguMDcyIDQxMS43NTYgMjQ3LjI4NkM0MTMuNjY0IDI0Ni41IDQxNS43NjEgMjQ2LjI5OSA0MTcuNzgzIDI0Ni43MDdDNDE5LjgwNSAyNDcuMTE2IDQyMS42NiAyNDguMTE2IDQyMy4xMTMgMjQ5LjU4MUM0MjIuNTI0IDI0OC4xNiA0MjEuNjI4IDI0Ni44ODggNDIwLjQ4OCAyNDUuODU1QzQxOS4zNDkgMjQ0LjgyMiA0MTcuOTk1IDI0NC4wNTUgNDE2LjUyNCAyNDMuNjA4QzQxNS4wNTMgMjQzLjE2IDQxMy41IDI0My4wNDUgNDExLjk3OSAyNDMuMjY5QzQxMC40NTggMjQzLjQ5MyA0MDkuMDA1IDI0NC4wNTIgNDA3LjcyNSAyNDQuOTA0QzQwNi40NDUgMjQ1Ljc1NyA0MDUuMzcgMjQ2Ljg4MiA0MDQuNTc3IDI0OC4yQzQwMy43ODQgMjQ5LjUxNyA0MDMuMjkzIDI1MC45OTQgNDAzLjEzOSAyNTIuNTI0QzQwMi45ODUgMjU0LjA1NCA0MDMuMTcyIDI1NS41OTkgNDAzLjY4NiAyNTcuMDQ5QzQwNC4yIDI1OC40OTggNDA1LjAyOSAyNTkuODE1IDQwNi4xMTMgMjYwLjkwNkM0MDUuNTg1IDI1OS42NDIgNDA1LjMxMyAyNTguMjg2IDQwNS4zMTMgMjU2LjkxNloiIGZpbGw9IiMxODE3MTYiLz4KPHBhdGggZD0iTTQzOS44MjEgMjM4Ljg2MUM0MzkuODIgMjM2Ljc5OCA0NDAuNDMxIDIzNC43ODEgNDQxLjU3OSAyMzMuMDY2QzQ0Mi43MjYgMjMxLjM1MiA0NDQuMzU2IDIzMC4wMTcgNDQ2LjI2NCAyMjkuMjNDNDQ4LjE3MSAyMjguNDQ0IDQ1MC4yNjkgMjI4LjI0MyA0NTIuMjkxIDIyOC42NTFDNDU0LjMxMyAyMjkuMDYgNDU2LjE2OCAyMzAuMDYgNDU3LjYyMSAyMzEuNTI1QzQ1Ny4wMzIgMjMwLjEwNCA0NTYuMTM2IDIyOC44MzIgNDU0Ljk5NiAyMjcuNzk5QzQ1My44NTcgMjI2Ljc2NiA0NTIuNTAzIDIyNS45OTkgNDUxLjAzMiAyMjUuNTUxQzQ0OS41NjEgMjI1LjEwNCA0NDguMDA4IDIyNC45ODkgNDQ2LjQ4NyAyMjUuMjEzQzQ0NC45NjYgMjI1LjQzNyA0NDMuNTEzIDIyNS45OTUgNDQyLjIzMyAyMjYuODQ4QzQ0MC45NTMgMjI3LjcwMSA0MzkuODc4IDIyOC44MjYgNDM5LjA4NSAyMzAuMTQ0QzQzOC4yOTIgMjMxLjQ2MSA0MzcuODAxIDIzMi45MzggNDM3LjY0NyAyMzQuNDY4QzQzNy40OTMgMjM1Ljk5OCA0MzcuNjggMjM3LjU0MyA0MzguMTk0IDIzOC45OTJDNDM4LjcwOCAyNDAuNDQyIDQzOS41MzcgMjQxLjc1OSA0NDAuNjIxIDI0Mi44NUM0NDAuMDkzIDI0MS41ODYgNDM5LjgyMSAyNDAuMjMgNDM5LjgyMSAyMzguODYxWiIgZmlsbD0iIzE4MTcxNiIvPgo8cGF0aCBkPSJNNDM0LjgwMiAzMjIuNTE2QzQzNC44MDIgMzIwLjQ1NCA0MzUuNDE0IDMxOC40MzkgNDM2LjU2MSAzMTYuNzI1QzQzNy43MDggMzE1LjAxMiA0MzkuMzM4IDMxMy42NzggNDQxLjI0NCAzMTIuODkyQzQ0My4xNTEgMzEyLjEwNiA0NDUuMjQ3IDMxMS45MDQgNDQ3LjI2OCAzMTIuMzEyQzQ0OS4yOSAzMTIuNzE5IDQ1MS4xNDQgMzEzLjcxOCA0NTIuNTk3IDMxNS4xODFDNDUyLjAwOCAzMTMuNzYxIDQ1MS4xMTIgMzEyLjQ4OCA0NDkuOTcyIDMxMS40NTVDNDQ4LjgzMyAzMTAuNDIyIDQ0Ny40NzkgMzA5LjY1NSA0NDYuMDA4IDMwOS4yMDhDNDQ0LjUzNyAzMDguNzYxIDQ0Mi45ODQgMzA4LjY0NSA0NDEuNDYzIDMwOC44NjlDNDM5Ljk0MiAzMDkuMDkzIDQzOC40ODkgMzA5LjY1MiA0MzcuMjA5IDMxMC41MDRDNDM1LjkyOSAzMTEuMzU3IDQzNC44NTQgMzEyLjQ4MiA0MzQuMDYxIDMxMy44QzQzMy4yNjggMzE1LjExNyA0MzIuNzc3IDMxNi41OTQgNDMyLjYyMyAzMTguMTI0QzQzMi40NjkgMzE5LjY1NCA0MzIuNjU2IDMyMS4xOTkgNDMzLjE3IDMyMi42NDlDNDMzLjY4NCAzMjQuMDk4IDQzNC41MTMgMzI1LjQxNSA0MzUuNTk3IDMyNi41MDZDNDM1LjA3MiAzMjUuMjQxIDQzNC44MDEgMzIzLjg4NSA0MzQuODAyIDMyMi41MTZaIiBmaWxsPSIjMTgxNzE2Ii8+CjxwYXRoIGQ9Ik00MDMuMDgzIDI5OC43NDRDNDAzLjA4MiAyOTYuNjgxIDQwMy42OTQgMjk0LjY2NCA0MDQuODQxIDI5Mi45NUM0MDUuOTg4IDI5MS4yMzUgNDA3LjYxOSAyODkuOTAxIDQwOS41MjYgMjg5LjExNUM0MTEuNDMzIDI4OC4zMjkgNDEzLjUzMSAyODguMTI3IDQxNS41NTMgMjg4LjUzNkM0MTcuNTc1IDI4OC45NDQgNDE5LjQzIDI4OS45NDQgNDIwLjg4MyAyOTEuNDA5QzQyMC4yOTQgMjg5Ljk4OSA0MTkuMzk4IDI4OC43MTYgNDE4LjI1OCAyODcuNjgzQzQxNy4xMTkgMjg2LjY1IDQxNS43NjUgMjg1Ljg4MyA0MTQuMjk0IDI4NS40MzZDNDEyLjgyMyAyODQuOTg5IDQxMS4yNyAyODQuODczIDQwOS43NDkgMjg1LjA5N0M0MDguMjI4IDI4NS4zMjEgNDA2Ljc3NSAyODUuODggNDA1LjQ5NSAyODYuNzMyQzQwNC4yMTUgMjg3LjU4NSA0MDMuMTQgMjg4LjcxIDQwMi4zNDcgMjkwLjAyOEM0MDEuNTU0IDI5MS4zNDUgNDAxLjA2MyAyOTIuODIyIDQwMC45MDkgMjk0LjM1MkM0MDAuNzU1IDI5NS44ODIgNDAwLjk0MiAyOTcuNDI3IDQwMS40NTYgMjk4Ljg3N0M0MDEuOTcgMzAwLjMyNiA0MDIuNzk5IDMwMS42NDMgNDAzLjg4MyAzMDIuNzM0QzQwMy4zNTUgMzAxLjQ3IDQwMy4wODMgMzAwLjExNCA0MDMuMDgzIDI5OC43NDRaIiBmaWxsPSIjMTgxNzE2Ii8+CjxwYXRoIGQ9Ik0zNzYuNjcgMzA0LjE3NUwzNzMuMTQ2IDMwMS42NDVDMzcxLjkzNSAzMDIuNTI4IDM3MC45MyAzMDMuNjYzIDM3MC4xOTggMzA0Ljk3MUMzNjkuNDY3IDMwNi4yNzkgMzY5LjAyNyAzMDcuNzMgMzY4LjkwOSAzMDkuMjI0QzM2OC43OTEgMzEwLjcxOCAzNjguOTk4IDMxMi4yMiAzNjkuNTE0IDMxMy42MjZDMzcwLjAzMSAzMTUuMDMzIDM3MC44NDYgMzE2LjMxMiAzNzEuOTAzIDMxNy4zNzRDMzcwLjkwNiAzMTQuOTc2IDM3MC44NDIgMzEyLjI5MSAzNzEuNzI0IDMwOS44NDlDMzcyLjYwNiAzMDcuNDA2IDM3NC4zNzEgMzA1LjM4MiAzNzYuNjcgMzA0LjE3NFYzMDQuMTc1WiIgZmlsbD0iIzE4MTcxNiIvPgo8cGF0aCBkPSJNNTY3Ljg0NSAyNjYuNDkxVjI3OC43MDdINTY2LjE1NFYyNjYuNDkxSDU2MS44MVYyNjQuODc4SDU3Mi4xOTJWMjY2LjQ5MUg1NjcuODQ1WiIgZmlsbD0iIzE4MTcxNiIvPgo8cGF0aCBkPSJNNTg3LjQ0IDI3OC43MDdINTg1Ljc0NlYyNjcuMTI5TDU4MS43IDI3OC43MDdINTc5Ljg4N0w1NzUuODQxIDI2Ny4xMjlWMjc4LjcwN0g1NzQuMTQ4VjI2NC44NzhINTc2LjczOEw1ODAuODAzIDI3Ni41MzVMNTg0Ljg2OSAyNjQuODc4SDU4Ny40NFYyNzguNzA3WiIgZmlsbD0iIzE4MTcxNiIvPgo8cGF0aCBkPSJNNTg2Ljg2OSAzMTguODI0TDU4Ni4yNDUgMzE3LjM3M0M1ODYuMjM1IDMxNy4zNTEgNTg2LjIyIDMxNy4zMzMgNTg2LjIxIDMxNy4zMUM1ODMuMTI3IDMxMC4yODUgNTc4LjY5MSAzMDMuOTM2IDU3My4xNTUgMjk4LjYyNkM1NjcuNjE5IDI5My4zMTYgNTYxLjA5MSAyODkuMTQ4IDU1My45NDQgMjg2LjM2QzU0Ni43OTYgMjgzLjU3MyA1MzkuMTcgMjgyLjIyMSA1MzEuNTAxIDI4Mi4zOEM1MjMuODMxIDI4Mi41NCA1MTYuMjY4IDI4NC4yMDkgNTA5LjI0MyAyODcuMjkyTDUwOS4xODYgMjg3LjMxN0M0OTUuMTUgMjkzLjQ4NiA0ODQuMTAyIDMwNC45MjcgNDc4LjQyOCAzMTkuMTdDNDcyLjc1MyAzMzMuNDE0IDQ3Mi45MDcgMzQ5LjMxNyA0NzguODU1IDM2My40NDhDNDg0LjgwMyAzNzcuNTc5IDQ5Ni4wNyAzODguODA1IDUxMC4yMjIgMzk0LjcwMkM1MjQuMzc0IDQwMC42IDU0MC4yNzggNDAwLjY5NiA1NTQuNTAxIDM5NC45N0w1NTMuNTkxIDM5Ny4yN0M1NTMuNDI3IDM5Ny43MDIgNTUzLjQ0IDM5OC4xODEgNTUzLjYyNiAzOTguNjA0QzU1My44MTMgMzk5LjAyNyA1NTQuMTU5IDM5OS4zNiA1NTQuNTg4IDM5OS41M0M1NTUuMDE4IDM5OS43IDU1NS40OTggMzk5LjY5NCA1NTUuOTIzIDM5OS41MTNDNTU2LjM0OSAzOTkuMzMyIDU1Ni42ODYgMzk4Ljk5MSA1NTYuODYyIDM5OC41NjRMNTYxLjU2MiAzODYuNjgzQzU2MS42NDcgMzg2LjQ2NyA1NjEuNjg5IDM4Ni4yMzcgNTYxLjY4NSAzODYuMDA1QzU2MS42OCAzODUuNzczIDU2MS42MyAzODUuNTQ0IDU2MS41MzcgMzg1LjMzMkM1NjEuNDQ1IDM4NS4xMiA1NjEuMzEgMzg0LjkyOCA1NjEuMTQzIDM4NC43NjdDNTYwLjk3NiAzODQuNjA3IDU2MC43NzggMzg0LjQ4MSA1NjAuNTYyIDM4NC4zOTdMNTQ4LjcyNyAzNzkuODA0QzU0OC41MSAzNzkuNzIgNTQ4LjI3OCAzNzkuNjc5IDU0OC4wNDUgMzc5LjY4NUM1NDcuODEzIDM3OS42OTEgNTQ3LjU4MyAzNzkuNzQ0IDU0Ny4zNzEgMzc5LjgzOUg1NDcuMzU4QzU0Ny4wNDEgMzc5Ljk4MSA1NDYuNzc0IDM4MC4yMTMgNTQ2LjU4OSAzODAuNTA3QzU0Ni40MDQgMzgwLjggNTQ2LjMxIDM4MS4xNDIgNTQ2LjMxOSAzODEuNDg5QzU0Ni4zMjggMzgxLjgzNiA1NDYuNDM5IDM4Mi4xNzIgNTQ2LjYzOSAzODIuNDU2QzU0Ni44MzggMzgyLjc0IDU0Ny4xMTcgMzgyLjk1OCA1NDcuNDQxIDM4My4wODRMNTUwLjEwOSAzODQuMTJDNTQ1LjMyNyAzODYuMDQ5IDU0MC4yNTggMzg3LjE3MSA1MzUuMTA5IDM4Ny40NDFMNTM0LjkzNCAzODEuMjg3TDUzMy4wMTggMzgxLjM0TDUzMy4xOTQgMzg3LjUwM0M1MjcuNTc1IDM4Ny41NTUgNTIxLjk5MiAzODYuNTg5IDUxNi43MTcgMzg0LjY1M0w1MTguOTU2IDM3OC45MUw1MTcuMTczIDM3OC4yMUw1MTQuOTQgMzgzLjkzOEM1MDkuOTY2IDM4MS44OTUgNTA1LjM4NCAzNzkuMDA3IDUwMS4zOTUgMzc1LjQwMUw1MDUuNjM5IDM3MC45MDlMNTA0LjI0NyAzNjkuNTk0TDQ5OS45ODcgMzc0LjEwNkM0OTUuOTgyIDM3MC4xNTcgNDkyLjcyNSAzNjUuNTE2IDQ5MC4zNzUgMzYwLjQwNkw0OTYuMDI5IDM1Ny45MjZMNDk1LjI1OSAzNTYuMTc0TDQ4OS41ODUgMzU4LjY2M0M0ODcuNTE0IDM1My42OTUgNDg2LjMyIDM0OC40MDYgNDg2LjA1NCAzNDMuMDMxTDQ5Mi4yNjggMzQyLjg1M0w0OTIuMjEyIDM0MC45MzlMNDg1Ljk5OCAzNDEuMTE4QzQ4NS45NjIgMzM1LjQ5NSA0ODYuOTQ1IDMyOS45MTEgNDg4Ljg5OCAzMjQuNjM4TDQ5NC42NTQgMzI2Ljg4NUw0OTUuMzU0IDMyNS4xMDNMNDg5LjYzMiAzMjIuODY5QzQ5MS42ODYgMzE3LjkwNCA0OTQuNTg0IDMxMy4zMzIgNDk4LjE5OCAzMDkuMzU1TDUwMi42NTYgMzEzLjU2N0w1MDMuOTY5IDMxMi4xNzVMNDk5LjUwNCAzMDcuOTU3QzUwMy40NTQgMzAzLjk3IDUwOC4wOTEgMzAwLjczIDUxMy4xOTIgMjk4LjM5MUw1MTUuNjM0IDMwMy45NThMNTE3LjM4NyAzMDMuMTg4TDUxNC45MzkgMjk3LjYwOUM1MTkuODk3IDI5NS41NTQgNTI1LjE3MiAyOTQuMzcgNTMwLjUzMyAyOTQuMTA5TDUzMC43MDYgMzAwLjE5MUw1MzIuNjIgMzAwLjEzNkw1MzIuNDQ3IDI5NC4wNTZDNTM4LjA1MSAyOTQuMDI3IDU0My42MTQgMjk1LjAxIDU0OC44NjkgMjk2Ljk1Nkw1NDYuNjggMzAyLjU3TDU0OC40NjIgMzAzLjI2NUw1NTAuNjQxIDI5Ny42NzhDNTU1LjU4OSAyOTkuNzI1IDU2MC4xNDcgMzAyLjYxMSA1NjQuMTE1IDMwNi4yMDdMNTU5Ljk5NyAzMTAuNTY4TDU2MS4zODkgMzExLjg4MUw1NjUuNTE4IDMwNy41MDlDNTY4LjI5NyAzMTAuMjYyIDU3MC43MTYgMzEzLjM1NSA1NzIuNzE4IDMxNi43MTVMNTM5LjY1MyAzMzAuODIzQzUzNy40OTEgMzI5LjQ2NiA1MzQuOTUyIDMyOC44MzcgNTMyLjQwNiAzMjkuMDI5QzUyOS44NjEgMzI5LjIyMSA1MjcuNDQ1IDMzMC4yMjQgNTI1LjUxMSAzMzEuODlDNTIzLjU3OCAzMzMuNTU2IDUyMi4yMjkgMzM1Ljc5OSA1MjEuNjY0IDMzOC4yODhDNTIxLjA5OCAzNDAuNzc2IDUyMS4zNDUgMzQzLjM4MSA1MjIuMzY4IDM0NS43MTlDNTIzLjM5MiAzNDguMDU4IDUyNS4xMzcgMzUwLjAwNiA1MjcuMzUgMzUxLjI4QzUyOS41NjIgMzUyLjU1MyA1MzIuMTI0IDM1My4wODQgNTM0LjY2IDM1Mi43OTRDNTM3LjE5NiAzNTIuNTA0IDUzOS41NzIgMzUxLjQxIDU0MS40NCAzNDkuNjdDNTQzLjMwOCAzNDcuOTMxIDU0NC41NjkgMzQ1LjYzOSA1NDUuMDM5IDM0My4xM0w1ODMuNzc0IDMyNi42MDFDNTg1LjIxNCAzMjUuOTc5IDU4Ni4zNDkgMzI0LjgxIDU4Ni45MjkgMzIzLjM1MkM1ODcuNTEgMzIxLjg5NCA1ODcuNDg4IDMyMC4yNjYgNTg2Ljg2OSAzMTguODI0WiIgZmlsbD0iIzE4MTcxNiIvPgo8cGF0aCBkPSJNNTg3LjQ0IDBIMTcwLjA2VjUuNjY5SDU4Ny40NFYwWiIgZmlsbD0iIzAwNkNCNyIvPgo8cGF0aCBkPSJNNDU4LjM0MSAxMzYuMDYySDE3MC4wNlYxNDEuNzMxSDQ1OC4zNDFWMTM2LjA2MloiIGZpbGw9IiMwMDZDQjciLz4KPHBhdGggZD0iTTU4Ny40MzkgMTM2LjA2Mkg0OTYuMTQ3VjE0MS43MzFINTg3LjQzOVYxMzYuMDYyWiIgZmlsbD0iIzAwNkNCNyIvPgo8cGF0aCBkPSJNMjAxLjYwNCA4MS44NDUxSDIxMi44OThDMjEyLjg5OCA4OC41NjcxIDIxMC45MyA5Mi45NjcxIDIwNi45OTMgOTUuMDQ1MUMyMDQuMTkzIDk2LjUzNTEgMTk4Ljg1MyA5Ny4yNzg0IDE5MC45NzIgOTcuMjc1MUMxODIuMTQ3IDk3LjI3NTEgMTc2LjI0MSA5NS40NTgxIDE3My4yNTYgOTEuODI0MUMxNzAuNjI4IDg4LjY3MDcgMTY5LjMxNiA4Mi41Mzc0IDE2OS4zMjEgNzMuNDI0MUMxNjkuMzIxIDY0LjM4MDcgMTcwLjU3NCA1OC4yNDkxIDE3My4wODEgNTUuMDI5MUMxNzUuOTk5IDUxLjIxMzcgMTgxLjk2MyA0OS4zMDc0IDE5MC45NzIgNDkuMzEwMUMyMDAuMzk5IDQ5LjMxMDEgMjA2LjQ4NyA1MS4wOTI3IDIwOS4yMzUgNTQuNjU4MUMyMTEuNjc3IDU3LjgwNjEgMjEyLjg5OCA2NC42OTM3IDIxMi44OTggNzUuMzIxMUgxODAuNTM1QzE4MC41MzUgODAuODEzNyAxODEuMDE0IDg0LjMwNDcgMTgxLjk3MiA4NS43OTQxQzE4My4yMjkgODcuNzAwNyAxODYuMjE3IDg4LjY1NDQgMTkwLjkzNyA4OC42NTUxQzE5NC44NzYgODguNjU1MSAxOTcuNDQ2IDg4LjM4ODQgMTk4LjY0NyA4Ny44NTUxQzIwMC42MTkgODYuOTc4NCAyMDEuNjA1IDg0Ljk3NTEgMjAxLjYwNCA4MS44NDUxWk0xODAuNTM1IDY4LjE3OTFIMjAxLjYyMkMyMDEuNjIyIDYzLjU4NjQgMjAxLjAyNCA2MC43MzA3IDE5OS44MjkgNTkuNjEyMUMxOTguNjM0IDU4LjQ5MzQgMTk1LjY3MiA1Ny45MzQ0IDE5MC45NDUgNTcuOTM1MUMxODYuMjc4IDU3LjkzNTEgMTgzLjMxOCA1OC42MTExIDE4Mi4wNjUgNTkuOTYzMUMxODEuMDQ1IDYxLjA4OTcgMTgwLjUzNSA2My44Mjg0IDE4MC41MzUgNjguMTc5MVoiIGZpbGw9IiMxODE3MTYiLz4KPHBhdGggZD0iTTI1NC40ODIgOTYuNzkyMUwyNTQuODI1IDg5LjcxOTFIMjU0LjQ4MkMyNTIuMTU0IDk0Ljc2MTggMjQ3LjI1OSA5Ny4yODE0IDIzOS43OTYgOTcuMjc4MUMyMzEuOTE4IDk3LjI3ODEgMjI2LjcyNyA5NC44MzY0IDIyNC4yMjQgODkuOTUzMUMyMjIuNjA4IDg2LjgwMzEgMjIxLjgwMSA4MC43ODk4IDIyMS44MDIgNzEuOTEzMUMyMjEuODAyIDY0LjExMzEgMjIyLjc5IDU4LjYzNDggMjI0Ljc2NSA1NS40NzgxQzIyNy4zNCA1MS4zNjg4IDIzMi4zNjggNDkuMzE0OCAyMzkuODQ5IDQ5LjMxNjFDMjQ3LjM4NyA0OS4zMTYxIDI1Mi4xMTUgNTEuNTY4NCAyNTQuMDM0IDU2LjA3MzFIMjU0LjQ4MlYyOS42NDExSDI2NS42OThWOTYuNzkyMUgyNTQuNDgyWk0yNDMuMjA1IDU3LjkzNTFDMjM4LjY2MSA1Ny45MzUxIDIzNS43MjEgNTkuMjEyNCAyMzQuMzg2IDYxLjc2NzFDMjMzLjQ3NiA2My40ODkxIDIzMy4wMjEgNjYuODczNCAyMzMuMDIyIDcxLjkyMDFDMjMzLjAyMiA3OC4zMjk0IDIzMy40MTYgODIuNDU1OCAyMzQuMjAzIDg0LjI5OTFDMjM1LjQ3NCA4Ny4yMDkxIDIzOC40NzQgODguNjYzMSAyNDMuMjAzIDg4LjY2MTFDMjQ4LjUzNiA4OC42NjExIDI1MS44NyA4Ny4yNjYxIDI1My4yMDMgODQuNDc2MUMyNTQuMDU2IDgyLjY5NTQgMjU0LjQ4MiA3OC41MTAxIDI1NC40OCA3MS45MjAxQzI1NC40OCA2Ni44MTYxIDI1My45MDQgNjMuMzcyMSAyNTIuNzUyIDYxLjU4ODFDMjUxLjIzNSA1OS4xNTM0IDI0OC4wNTMgNTcuOTM1OCAyNDMuMjA1IDU3LjkzNTFaIiBmaWxsPSIjMTgxNzE2Ii8+CjxwYXRoIGQ9Ik0zMTcuODY1IDk2Ljc5MjFIMzA2Ljk3NFY4OS41NDQxSDMwNi42NDhDMzA0LjQ5MyA5NC43MDAxIDI5OS41MiA5Ny4yNzgxIDI5MS43MyA5Ny4yNzgxQzI4MS4xODkgOTcuMjc4MSAyNzUuOTE5IDkyLjc3ODEgMjc1LjkyMiA4My43NzgxVjQ5LjgwNzFIMjg3LjEzMlY3OS4zNzAxQzI4Ny4xMzIgODMuMDA3NSAyODcuNTUzIDg1LjM5MDUgMjg4LjM5NCA4Ni41MTkxQzI4OS40MTEgODcuOTQ4MSAyOTEuNjE5IDg4LjY2MTEgMjk1LjAzNyA4OC42NjExQzI5OS4yMjYgODguNjYxMSAzMDIuMTg3IDg3Ljc1NDUgMzAzLjkyIDg1Ljk0MTFDMzA1LjY1MyA4NC4xMjc4IDMwNi41MjIgODEuMTAzNSAzMDYuNTI4IDc2Ljg2ODFMMzA2LjY0OCA0OS44MDcxSDMxNy44NjVWOTYuNzkyMVoiIGZpbGw9IiMxODE3MTYiLz4KPHBhdGggZD0iTTM1OC4yODUgNzguODk1OUgzNjkuNTg1QzM2OS41ODUgODYuNDUxMiAzNjcuODU0IDkxLjUwNzYgMzY0LjM5MyA5NC4wNjQ5QzM2MS41MjYgOTYuMjA1NiAzNTYuMTI2IDk3LjI3NjYgMzQ4LjE5MyA5Ny4yNzc5QzMzOS40MiA5Ny4yNzc5IDMzMy42MzIgOTUuNDMxOSAzMzAuODI5IDkxLjczOTlDMzI4LjM4OCA4OC41ODY2IDMyNy4xNjYgODIuNDU1MiAzMjcuMTYxIDczLjM0NTlDMzI3LjE2MSA2NC4zNTUzIDMyOC4zNTMgNTguMjgwOSAzMzAuNzM4IDU1LjEyMjlDMzMzLjY2NSA1MS4yNTI5IDMzOS40ODQgNDkuMzE3MyAzNDguMTkzIDQ5LjMxNTlDMzU1LjgyOSA0OS4zMTU5IDM2MS4xMzkgNTAuMjk3NiAzNjQuMTI0IDUyLjI2MDlDMzY3Ljc1OSA1NC42NDgzIDM2OS41NzggNTkuMzE4NiAzNjkuNTgyIDY2LjI3MTlIMzU4LjI4MkMzNTguMjgyIDYyLjY3MTkgMzU3LjQ3NSA2MC4zMzg2IDM1NS44NiA1OS4yNzE5QzM1NC42MDQgNTguMzgyNiAzNTIuMDMzIDU3LjkzODYgMzQ4LjE0OCA1Ny45Mzk5QzM0My42MDggNTcuOTM5OSAzNDAuNzcgNTkuMDA4OSAzMzkuNjMzIDYxLjE0NjlDMzM4Ljc5IDYyLjc1MTYgMzM4LjM3MSA2Ni44MTgyIDMzOC4zNzYgNzMuMzQ2OUMzMzguMzc2IDc5LjgxODIgMzM4Ljc2NSA4My44MjUyIDMzOS41NDIgODUuMzY3OUMzNDAuNjE2IDg3LjU2NzkgMzQzLjQ4NSA4OC42NjU5IDM0OC4xNDggODguNjYxOUMzNTIuNDUyIDg4LjY2MTkgMzU1LjIxNyA4OC4wODQ5IDM1Ni40NDMgODYuOTMwOUMzNTcuNjY5IDg1Ljc3NjkgMzU4LjI4MyA4My4wOTg2IDM1OC4yODUgNzguODk1OVoiIGZpbGw9IiMxODE3MTYiLz4KPHBhdGggZD0iTTQwOC4xNDggOTYuNzkyTDQwOC41MTIgOTAuODg0SDQwOC4yNDVDNDA3Ljc1IDkyLjIyMzMgNDA2LjkzOCA5My40MjMgNDA1Ljg3OSA5NC4zODA3QzQwNC44MTkgOTUuMzM4NCA0MDMuNTQ0IDk2LjAyNTcgNDAyLjE2MiA5Ni4zODRDMzk5LjM4NSA5Ny4wNzk1IDM5Ni41MjMgOTcuMzc5OCAzOTMuNjYyIDk3LjI3NkMzODcuNjMzIDk3LjI3NiAzODMuMzA3IDk2LjMyNDMgMzgwLjY4NCA5NC40MjFDMzc3LjY0IDkyLjIxNyAzNzYuMTE5IDg4LjIwMiAzNzYuMTIgODIuMzc2QzM3Ni4xMiA3Ni43ODczIDM3Ny43MDQgNzIuODkyMyAzODAuODczIDcwLjY5MUMzODMuNTA5IDY4LjkwNTYgMzg3Ljc4NiA2OC4wMTIzIDM5My43MDUgNjguMDExQzM5Ni40NDUgNjcuOTExNCAzOTkuMTg3IDY4LjE1MDkgNDAxLjg2OSA2OC43MjRDNDAzLjEyOCA2OS4wMjcgNDA0LjMwOCA2OS41OTYgNDA1LjMyOSA3MC4zOTI5QzQwNi4zNSA3MS4xODk4IDQwNy4xODkgNzIuMTk2IDQwNy43ODkgNzMuMzQ0SDQwOC4xNDhWNjcuMjUzQzQwOC4xNDggNjMuMTk3IDQwNy42NCA2MC41NDA2IDQwNi42MjUgNTkuMjg0QzQwNS4zNjQgNTcuNzM1MyA0MDIuNTIxIDU2Ljk1OTYgMzk4LjA5NiA1Ni45NTdDMzk1LjEwNSA1Ni45NTcgMzkzLjAxMiA1Ny4yODU2IDM5MS44MTYgNTcuOTQzQzM5MC4wODMgNTguODk5NiAzODkuMjE2IDYwLjc1MiAzODkuMjE2IDYzLjVIMzc3LjkxNkMzNzcuOTE2IDU3LjM3NCAzNzkuOTQ3IDUzLjI5OTYgMzg0LjAwOSA1MS4yNzdDMzg2LjYzNCA0OS45NjcgMzkxLjMxOSA0OS4zMTI2IDM5OC4wNjIgNDkuMzE0QzQwNi4xMTYgNDkuMzE0IDQxMS41NDcgNTAuMzU2NiA0MTQuMzU1IDUyLjQ0MkM0MTcuNjk4IDU0Ljg4OTMgNDE5LjM3IDU5Ljg2NjYgNDE5LjM3MSA2Ny4zNzRWOTYuNzlMNDA4LjE0OCA5Ni43OTJaTTM5Ny42OTkgNzUuNjUzQzM5My45NzEgNzUuNjUzIDM5MS41MzggNzUuOTIzMyAzOTAuMzk5IDc2LjQ2NEMzODguMzU4IDc3LjQyMDYgMzg3LjMzNyA3OS4zOTEgMzg3LjMzOCA4Mi4zNzVDMzg3LjMzOCA4NS41NDUgMzg4LjExOSA4Ny41NzYzIDM4OS42ODIgODguNDY5QzM5MS4wMDEgODkuMjQ2MyAzOTMuNjczIDg5LjYzNiAzOTcuNyA4OS42MzhDNDAxLjM2MiA4OS42MzggNDAzLjg1NCA4OS4yOCA0MDUuMTc3IDg4LjU2NEM0MDcuMTU2IDg3LjQ4OCA0MDguMTQ3IDg1LjQyNSA0MDguMTQ5IDgyLjM3NUM0MDguMTQ5IDc5LjQ0OSA0MDcuMDk4IDc3LjUwOTMgNDA0Ljk5NyA3Ni41NTZDNDAzLjY3MiA3NS45NTQgNDAxLjI0IDc1LjY1MyAzOTcuNjk5IDc1LjY1M1oiIGZpbGw9IiMxODE3MTYiLz4KPHBhdGggZD0iTTQyNC42OTMgNTguNDIyOVY0OS44MDY5SDQzMC41NTRWMzkuMjMzOUg0NDEuNzczVjQ5LjgwNjlINDU5Ljg2N1Y1OC40MjI5SDQ0MS43NjhWODIuNDE2OUM0NDEuNzY4IDg0Ljg1NTkgNDQxLjk3NSA4Ni40MzA5IDQ0Mi4zOTggODcuMTQzOUM0NDIuOTk4IDg4LjE1NTkgNDQ0LjQwOCA4OC42NjE2IDQ0Ni42MjcgODguNjYwOUM0NDkuNDQzIDg4LjY2MDkgNDUxLjE4NCA4Ny42MTgyIDQ1MS44NSA4NS41MzI5QzQ1Mi4yNDkgODMuMjk0IDQ1Mi4zOTcgODEuMDE3NiA0NTIuMjkxIDc4Ljc0NTlINDYyLjI4MUM0NjIuNDAyIDg1LjQyNzkgNDYxLjUwNSA5MC4wODI2IDQ1OS41OTIgOTIuNzA5OUM0NTcuMzc4IDk1Ljc1NjUgNDUzLjA3NSA5Ny4yNzkyIDQ0Ni42ODIgOTcuMjc3OUM0NDAuNTg5IDk3LjI3NzkgNDM2LjQzNyA5Ni4zNTQyIDQzNC4yMjUgOTQuNTA2OUM0MzEuNzc0IDkyLjQyNjkgNDMwLjU0OCA4OC40Mzg2IDQzMC41NDkgODIuNTQxOVY1OC40MjI5SDQyNC42OTNaIiBmaWxsPSIjMTgxNzE2Ii8+CjxwYXRoIGQ9Ik00ODIuMzIzIDI5LjY0MTFWMzkuMjM0MUg0NzEuMTAzVjI5LjY0MTFINDgyLjMyM1pNNDgyLjMyMyA0OS44MDcxVjk2Ljc5MjFINDcxLjEwM1Y0OS44MDcxSDQ4Mi4zMjNaIiBmaWxsPSIjMTgxNzE2Ii8+CjxwYXRoIGQ9Ik01MTMuMzU0IDQ5LjMxNTlDNTIyLjc4NCA0OS4zMTU5IDUyOC45MyA1MS4wNDQyIDUzMS43OTEgNTQuNTAwOUM1MzQuMjM5IDU3LjQ3NTYgNTM1LjQ2MyA2My43NTcyIDUzNS40NjMgNzMuMzQ1OUM1MzUuNDYzIDgyLjg2ODYgNTM0LjIzOSA4OS4xMTk2IDUzMS43OTEgOTIuMDk4OUM1MjguOTI0IDk1LjU1MDkgNTIyLjc3OSA5Ny4yNzcyIDUxMy4zNTQgOTcuMjc3OUM1MDMuOTI5IDk3LjI3ODYgNDk3Ljc4MiA5NS41NTIyIDQ5NC45MTMgOTIuMDk4OUM0OTIuNDY1IDg5LjEyNDIgNDkxLjI0MSA4Mi44NzMyIDQ5MS4yNDIgNzMuMzQ1OUM0OTEuMjQyIDYzLjc1NTkgNDkyLjQ2NiA1Ny40NzQyIDQ5NC45MTMgNTQuNTAwOUM0OTcuNzc4IDUxLjA0NDIgNTAzLjkyNSA0OS4zMTU5IDUxMy4zNTQgNDkuMzE1OVpNNTEzLjM1NCA1Ny45MzQ5QzUwOC41NSA1Ny45MzQ5IDUwNS40ODkgNTguOTQ0MiA1MDQuMTcxIDYwLjk2MjlDNTAzLjAyOCA2Mi43NDY5IDUwMi40NTkgNjYuOTAyNiA1MDIuNDYzIDczLjQyOTlDNTAyLjQ2MyA3OS45MDM5IDUwMy4wMzIgODQuMDAzOSA1MDQuMTcxIDg1LjcyOTlDNTA1LjQyOCA4Ny42ODU5IDUwOC40ODkgODguNjY0NiA1MTMuMzU0IDg4LjY2NTlDNTE4LjI3NiA4OC42NjU5IDUyMS4zNjUgODcuNjg3MyA1MjIuNjIyIDg1LjcyOTlDNTIzLjcwMiA4NC4wNjMzIDUyNC4yNDUgNzkuOTYzMiA1MjQuMjUgNzMuNDI5OUM1MjQuMjUgNjYuNzgyNiA1MjMuNzA3IDYyLjYyNjkgNTIyLjYyMiA2MC45NjI5QzUyMS4zMDYgNTguOTQ4MiA1MTguMjE3IDU3LjkzODkgNTEzLjM1NCA1Ny45MzQ5WiIgZmlsbD0iIzE4MTcxNiIvPgo8cGF0aCBkPSJNNTQ0Ljk1NCA0OS44MDY5SDU1Ni4xNjVWNTYuODc3OUg1NTYuNTI0QzU1Ni45ODggNTUuNDU2OCA1NTcuNzU4IDU0LjE1NDggNTU4Ljc3OSA1My4wNjM1QzU1OS44MDEgNTEuOTcyMyA1NjEuMDUgNTEuMTE4MyA1NjIuNDM3IDUwLjU2MTlDNTY1LjI4NSA0OS42MDU0IDU2OC4yODUgNDkuMTgyOSA1NzEuMjg2IDQ5LjMxNTlDNTc3LjI0NiA0OS4zMTU5IDU4MS40MTkgNTAuNTgyNiA1ODMuODA1IDUzLjExNTlDNTg2LjE5MSA1NS42NDkyIDU4Ny4zODQgNTkuODk1OSA1ODcuMzgzIDY1Ljg1NTlWOTYuNzg5OUg1NzYuMTY5VjY3LjA0NjlDNTc2LjE2OSA2My41MzM2IDU3NS41NzIgNjEuMTM2NiA1NzQuMzc4IDU5Ljg1NTlDNTczLjE4NCA1OC41NzUyIDU3MC44NTMgNTcuOTM0OSA1NjcuMzg1IDU3LjkzNDlDNTYyLjgzOCA1Ny45MzQ5IDU1OS43NTggNTkuMDM0OSA1NTguMTQ3IDYxLjIzNDlDNTU2LjgyNiA2My4wMjU2IDU1Ni4xNjcgNjYuMjcyMiA1NTYuMTY4IDcwLjk3NDlWOTYuNzg3OUg1NDQuOTU0VjQ5LjgwNjlaIiBmaWxsPSIjMTgxNzE2Ii8+CjxwYXRoIGQ9Ik01NzYuMzMzIDQ0Ljk4MzJWMzguNjcwMkg1NzMuOTc0VjM3LjgyNTJINTc5LjY0OFYzOC42NzAySDU3Ny4yOFY0NC45ODMySDU3Ni4zMzNaIiBmaWxsPSIjMTgxNzE2Ii8+CjxwYXRoIGQ9Ik01ODAuNTkxIDQ0Ljk4MzJWMzcuODI1Mkg1ODIuMDE2TDU4My43MTYgNDIuODkzMkM1ODMuODcyIDQzLjM2NjIgNTgzLjk4NiA0My43MTgyIDU4NC4wNTggNDMuOTUzMkM1ODQuMTM5IDQzLjY5MzIgNTg0LjI2NiA0My4zMTA1IDU4NC40MzggNDIuODA1Mkw1ODYuMTUyIDM3LjgyNTJINTg3LjQyN1Y0NC45ODMySDU4Ni41MTRWMzguOTkyMkw1ODQuNDMzIDQ0Ljk4MzJINTgzLjU3OUw1ODEuNTA5IDM4Ljg4OTJWNDQuOTgzMkg1ODAuNTkxWiIgZmlsbD0iIzE4MTcxNiIvPgo8cGF0aCBkPSJNMC45NjE5NzUgMC45NDQ4MjRWMTQwLjc4NkgxNDAuODAyVjAuOTQ0ODI0SDAuOTYxOTc1WiIgZmlsbD0id2hpdGUiLz4KPHBhdGggZD0iTTAuOTYxOTc1IDAuOTQ0ODI0VjE0MC43ODZIMTQwLjgwMlYwLjk0NDgyNEgwLjk2MTk3NVpNMTMxLjQ5OCA1OS4wNzM4QzEzMS4xMDMgNjMuNjQzNCAxMzAuMTUgNjguMTQ3NCAxMjguNjU5IDcyLjQ4NDhDMTIzLjc0MiA4Ny4wOTY4IDExOC4wNDEgOTYuMTUyOCAxMDQuODM3IDk2LjE1MjhDMTAwLjk1MSA5Ni4xNTI4IDk0LjA1NCA5NS4xMTk4IDkxLjUxNCA4OC4yMDM4TDkwLjkxNCA4Ni41NjQ4TDg5LjgzMSA4Ny45MzY4Qzg3LjgzMzQgOTAuNDk4NiA4NS4yODEzIDkyLjU3NDQgODIuMzY2NCA5NC4wMDgzQzc5LjQ1MTQgOTUuNDQyMiA3Ni4yNDk1IDk2LjE5NyA3My4wMDEgOTYuMjE1OEM2Ny45NjIgOTYuMjM5OCA2My45MTUgOTQuNTUwOCA2MS4zMDEgOTEuMzMyOEw2MC41ODIgOTAuNDQ5OEw1OS44MTggOTEuMjkzOEM1Ny4wMTggOTQuMzgxOCA1Mi4xNSA5Ni4xNTI4IDQ2LjQ1NCA5Ni4xNTI4QzQxLjk4MSA5Ni4xNTI4IDM4LjExOSA5NC42MzM4IDM1LjU3OCA5MS44NzU4TDM0Ljg4NSA5MS4xMjE4TDM0LjE2NSA5MS44NTA4QzMxLjM0IDk0LjcwMTggMjYuODg5IDk2LjEzOTggMjEuMjkzIDk2LjAwNzhDMTQuNTAzIDk1Ljg0NjggMTAuMzY5IDkyLjA1NzggMTAuMjM3IDg1Ljg2NzhDMTAuMDMxIDc2LjMyNDggMTkuMjY4IDU2LjI0ODggMjMuMDg5IDUwLjE0MzhDMjUuNTcyIDQ2LjA2NTggMjguOTg5IDQ0LjA4ODggMzMuNTI3IDQ0LjA4ODhDMzYuNjE5IDQ0LjA4ODggMzguNzMzIDQ0LjczNTggMzkuOTkgNDYuMDY1OEM0MS4xMzMgNDcuMjc1OCA0MS4zNiA0OC4yOTc4IDQxLjQ2MSA1MC43NTI4TDQxLjU5MiA1My45Mjc4TDQzLjI2NyA1MS4yMjc4QzQ3LjMyMiA0NC42OTM4IDU0LjA0MSA0My43OTM4IDYwLjY5OCA0My43OTM4QzY1LjMyNyA0My43OTM4IDY5LjM2NSA0NS40OTM4IDcwLjk4NyA0OC4xMjk4TDcxLjU4NyA0OS4xMDA4TDcyLjQ1NSA0OC4zNjI4Qzc2LjMyMzUgNDUuMjk3MiA4MS4xNTAxIDQzLjY5NTcgODYuMDg0IDQzLjg0MDhDOTEuOTMxIDQzLjg0MDggOTYuMTg0IDQ1LjI5NDggOTguNzE3IDQ4LjE2MThDOTkuMzMxOCA0OC44MTQ5IDk5LjgzNDUgNDkuNTY1IDEwMC4yMDUgNTAuMzgxOEwxMDAuODU2IDUxLjc0NzhMMTAxLjgzMiA1MC41OTI4QzEwNS41NDIgNDYuMjAyOCAxMTAuNjExIDQzLjk3NzggMTE2Ljg5OSA0My45Nzc4QzEyMS44NzkgNDMuOTc3OCAxMjUuNjYgNDUuMzAwOCAxMjguMTM1IDQ3LjkxMDhDMTMxLjIyOSA1MS4xODM4IDEzMS42NzIgNTUuNzg3OCAxMzEuNDk4IDU5LjA3MzhaIiBmaWxsPSIjRkZFRDAwIi8+CjxwYXRoIGQ9Ik0wLjk2MTk3NSAwLjk0NDgyNFYxNDAuNzg2SDE0MC44MDJWMC45NDQ4MjRIMC45NjE5NzVaTTEzNS40MzYgNjQuNDM4OEMxMzQuODAyIDY5LjUyNTggMTMxLjM2MyA3OC45NTQ4IDEyOS41MzYgODIuNzIzOEMxMjQuNjM2IDkyLjgyMzggMTE4LjA4MyAxMDAuNTg3IDEwNS40NjIgMTAwLjU4N0M5OC43MiAxMDAuNTg3IDkzLjE3NCA5OC40MzY4IDg5LjkzMSA5NC4zMDM4Qzg1LjI1MDggOTguNDI5OCA3OS4yMTUgMTAwLjY4NyA3Mi45NzYgMTAwLjY0NkM2OC40ODM5IDEwMC43NjEgNjQuMDg2MSA5OS4zNDU5IDYwLjUwNCA5Ni42MzI4QzU2LjM3MTYgOTkuMzUxOSA1MS41MDYgMTAwLjc0MSA0Ni41NjEgMTAwLjYxNEM0Mi4zNTMgMTAwLjcwNCAzOC4yMjM4IDk5LjQ2NDMgMzQuNzYxIDk3LjA3MThDMzEuMjMzIDk5LjQxMzggMjYuNjA4IDEwMC41NzIgMjEuMTc4IDEwMC40NDdDMTIuMTQ1IDEwMC4yMzQgNS45MDc5OCA5NC41MDM4IDUuNzI4OTggODYuMTg3OEM1LjQ5MDk4IDc1LjEzNzggMTQuOCA1NC45MTE4IDE5LjE4NSA0Ny45MDc4QzIwLjYyMTQgNDUuMzU0NCAyMi43MTk5IDQzLjIzNTcgMjUuMjU5NSA0MS43NzVDMjcuNzk5IDQwLjMxNDMgMzAuNjg1NiAzOS41NjU2IDMzLjYxNSAzOS42MDc4QzQwLjI3OCAzOS42MDc4IDQyLjY5MyA0MS41MTM4IDQzLjg4MSA0My45MzY4QzQ5LjAyMiAzOS41Njg4IDU1LjgzNyAzOS4zMTg4IDYwLjY4OSAzOS4zMTg4QzY2LjA0NSAzOS4zMTg4IDY5LjQwNCA0MC43Mzk4IDcyLjI2NCA0My4wMTg4Qzc2LjQ2MzYgNDAuNTUzOSA4MS4yNjY3IDM5LjMwNzMgODYuMTM1IDM5LjQxODhDOTMuMDM1IDM5LjQxODggOTguMTU2IDQxLjAxODggMTAxLjcyOSA0NC41NTU4QzEwNS44OTggNDEuMDg3OCAxMTEuMTE2IDM5LjUwNTggMTE2Ljk2MSAzOS41MDU4QzEyNC42ODUgMzkuNTA1OCAxMjkuNzY4IDQyLjI5MjggMTMyLjc1MyA0Ni40NDY4QzEzNi45NjMgNTIuMzA1OCAxMzYuMjExIDU4LjIwNDggMTM1LjQzNiA2NC40Mzg4WiIgZmlsbD0iI0UzMDAwQiIvPgo8cGF0aCBkPSJNMC4wMDA5NzY1NjIgMFYxNDEuNzMzSDE0MS43MzNWMEgwLjAwMDk3NjU2MlpNMTM5Ljc4MiAxLjk1M1YxMzkuNzgxSDEuOTUzOThWMS45NTNIMTM5Ljc4MloiIGZpbGw9IiMxODE3MTYiLz4KPHBhdGggZD0iTTEzNC43NTQgNDIuNTI3OVY0MS41NjM5SDEzNS40MDlDMTM1Ljg4OCA0MS41NjM5IDEzNi4xMzYgNDEuNzMxOSAxMzYuMTM2IDQyLjA0MTlDMTM2LjEzNiA0Mi4yODg5IDEzNS45NzYgNDIuNTI3OSAxMzUuNDg5IDQyLjUyNzlIMTM0Ljc1NFpNMTM3LjEwNCA0NC41Mjc5TDEzNi42OTYgNDMuODE5OUMxMzYuMzQxIDQzLjIwMTkgMTM2LjI0MyA0My4xMDQ5IDEzNS45NDIgNDIuOTk3OVY0Mi45Nzk5QzEzNi4xOTggNDIuOTczNCAxMzYuNDQxIDQyLjg2NjQgMTM2LjYxOSA0Mi42ODJDMTM2Ljc5NiA0Mi40OTc3IDEzNi44OTQgNDIuMjUwOSAxMzYuODkxIDQxLjk5NDlDMTM2Ljg5MSA0MS40MzY5IDEzNi41MzYgNDEuMDEwOSAxMzUuNzgyIDQxLjAxMDlIMTM0LjAyOFY0NC41Mjc5SDEzNC43NTRWNDMuMDg3OUgxMzQuODg2QzEzNC45ODkgNDMuMDcxIDEzNS4wOTUgNDMuMDc4MiAxMzUuMTk1IDQzLjEwODlDMTM1LjI5NSA0My4xMzk2IDEzNS4zODcgNDMuMTkzIDEzNS40NjMgNDMuMjY0OUMxMzUuNjUzIDQzLjQ3MjMgMTM1LjgxNCA0My43MDQ0IDEzNS45NDIgNDMuOTU0OUwxMzYuMjI1IDQ0LjUyOTlMMTM3LjEwNCA0NC41Mjc5Wk0xMzUuMzczIDQwLjAyNzlDMTM1LjkxMyA0MC4wMjYgMTM2LjQ0MiA0MC4xODQzIDEzNi44OTIgNDAuNDgyOEMxMzcuMzQyIDQwLjc4MTQgMTM3LjY5MyA0MS4yMDY4IDEzNy45MDEgNDEuNzA1MkMxMzguMTA5IDQyLjIwMzUgMTM4LjE2NSA0Mi43NTI1IDEzOC4wNjEgNDMuMjgyNEMxMzcuOTU3IDQzLjgxMjQgMTM3LjY5OCA0NC4yOTk2IDEzNy4zMTcgNDQuNjgyNEMxMzYuOTM2IDQ1LjA2NTEgMTM2LjQ1IDQ1LjMyNjIgMTM1LjkyIDQ1LjQzMjVDMTM1LjM5MSA0NS41Mzg4IDEzNC44NDIgNDUuNDg1NyAxMzQuMzQyIDQ1LjI3OTdDMTMzLjg0MyA0NS4wNzM4IDEzMy40MTYgNDQuNzI0MyAxMzMuMTE2IDQ0LjI3NTZDMTMyLjgxNSA0My44MjY4IDEzMi42NTQgNDMuMjk5IDEzMi42NTQgNDIuNzU4OUMxMzIuNjU1IDQyLjAzNzcgMTMyLjk0MiA0MS4zNDYzIDEzMy40NTEgNDAuODM1NkMxMzMuOTYgNDAuMzI0OSAxMzQuNjUxIDQwLjAzNjQgMTM1LjM3MiA0MC4wMzI5TDEzNS4zNzMgNDAuMDI3OVpNMTM1LjM3MyAzOS4zNTY5QzEzNC43MDIgMzkuMzU3OSAxMzQuMDQ2IDM5LjU1NzcgMTMzLjQ4OSAzOS45MzEyQzEzMi45MzEgNDAuMzA0NiAxMzIuNDk3IDQwLjgzNDkgMTMyLjI0MSA0MS40NTVDMTMxLjk4NCA0Mi4wNzUyIDEzMS45MTcgNDIuNzU3NCAxMzIuMDQ5IDQzLjQxNTVDMTMyLjE4IDQ0LjA3MzYgMTMyLjUwMyA0NC42NzgxIDEzMi45NzcgNDUuMTUyNkMxMzMuNDUyIDQ1LjYyNzEgMTM0LjA1NiA0NS45NTAzIDEzNC43MTQgNDYuMDgxNUMxMzUuMzczIDQ2LjIxMjYgMTM2LjA1NSA0Ni4xNDU4IDEzNi42NzUgNDUuODg5NUMxMzcuMjk1IDQ1LjYzMzEgMTM3LjgyNSA0NS4xOTg3IDEzOC4xOTkgNDQuNjQxMkMxMzguNTcyIDQ0LjA4MzcgMTM4Ljc3MiA0My40MjggMTM4Ljc3MyA0Mi43NTY5QzEzOC43NzQgNDIuMzEwMyAxMzguNjg3IDQxLjg2NzkgMTM4LjUxNiA0MS40NTUyQzEzOC4zNDUgNDEuMDQyNSAxMzguMDk1IDQwLjY2NzYgMTM3Ljc3OSA0MC4zNTIxQzEzNy40NjMgNDAuMDM2NiAxMzcuMDg3IDM5Ljc4NjcgMTM2LjY3NCAzOS42MTY4QzEzNi4yNjEgMzkuNDQ2OCAxMzUuODE5IDM5LjM2MDIgMTM1LjM3MiAzOS4zNjE5TDEzNS4zNzMgMzkuMzU2OVoiIGZpbGw9IiMxODE3MTYiLz4KPHBhdGggZD0iTTExNi44ODkgNDMuMDAwOUMxMDkuNTY0IDQzLjAwMDkgMTA0LjUwNCA0NS45MDA5IDEwMS4wNzYgNDkuOTYxOUMxMDAuNjY3IDQ5LjA2MjQgMTAwLjExNCA0OC4yMzU4IDk5LjQzOSA0Ny41MTQ5Qzk2LjYzOSA0NC4zNDM5IDkyLjEyNSA0Mi44NjM5IDg2LjA3NCA0Mi44NjM5QzgwLjkwNyA0Mi43MDc2IDc1Ljg1MjcgNDQuMzkyNSA3MS44MTMgNDcuNjE3OUM3MC4wMzQgNDQuNzI5OSA2NS43OTkgNDIuODE3OSA2MC42OTEgNDIuODE3OUM1NC4wMTcgNDIuODE3OSA0Ni43NDQgNDMuNzYxOSA0Mi40MyA1MC43MTI5QzQyLjMzIDQ4LjIxMjkgNDIuMSA0Ni44ODU5IDQwLjY5MyA0NS4zOTU5QzM4Ljk4MyA0My41ODU5IDM2LjIxNiA0My4xMTI5IDMzLjUyIDQzLjExMjlDMjguNjA4IDQzLjExMjkgMjQuOTE0IDQ1LjI1NzkgMjIuMjU0IDQ5LjYyNjlDMTguMzk0IDU1Ljc5MDkgOS4wNDEwMSA3Ni4wNjc5IDkuMjU0MDEgODUuODg5OUM5LjM5MDAxIDkyLjIzMzkgMTMuNjQ2IDk2LjgwNjkgMjEuMjY0IDk2Ljk4MzlDMjcuMjE1IDk3LjEyNjkgMzEuODgzIDk1LjUzNjkgMzQuODU0IDkyLjUzODlDMzcuNTE5IDk1LjQzMjkgNDEuNTg1IDk3LjEzMDkgNDYuNDQ4IDk3LjEzMDlDNTEuODY1IDk3LjEzMDkgNTcuMzE3IDk1LjUwNDkgNjAuNTM3IDkxLjk0ODlDNjMuMjQ5IDk1LjI4MjkgNjcuNTE4IDk3LjIxOTkgNzMuMDA1IDk3LjE5MjlDNzYuNDAwMiA5Ny4xNzM2IDc5Ljc0NyA5Ni4zODUzIDgyLjc5MzkgOTQuODg3MUM4NS44NDA3IDkzLjM4ODkgODguNTA4NiA5MS4yMTk5IDkwLjU5NyA4OC41NDI5QzkyLjg1NiA5NC42OTE5IDk4LjU4NCA5Ny4xMzA5IDEwNC44MzggOTcuMTMwOUMxMTguNTQ4IDk3LjEzMDkgMTI0LjU2OSA4Ny43MDQ5IDEyOS41ODYgNzIuNzk3OUMxMzEuMTA1IDY4LjM3NjQgMTMyLjA3NiA2My43ODUgMTMyLjQ3NSA1OS4xMjY5QzEzMi44OSA1MS4yOTE5IDEyOS41NzQgNDMuMDAwOSAxMTYuODg5IDQzLjAwMDlaTTI1LjY3MiA4MC40NzQ5QzMyLjc2NSA3OS4yNDI5IDM0LjU0OSA4MS44MDc5IDM0LjMyNSA4NC4xODE5QzMzLjY1NiA5MS4yOTA5IDI3LjEzNCA5Mi44ODE5IDIxLjQ3MiA5Mi43NDc5QzE3LjM2NSA5Mi42NDc5IDEzLjY3MiA5MC43NzA5IDEzLjU3MiA4Ni4wMDA5QzEzLjM5MyA3Ny42NTg5IDIxLjkwMSA1OC4zNjA5IDI1LjkwNiA1MS45NjI5QzI3Ljc1NSA0OC45Mjc5IDMwLjAwNiA0Ny40MjQ5IDMzLjYwNiA0Ny40MjQ5QzM3LjAxMiA0Ny40MjQ5IDM3Ljg1NiA0OS4xNzM5IDM3LjgwNiA1MS4yNjg5QzM3LjY2NSA1Ni44NTI5IDI4LjYzNSA3My44Mzk5IDI1LjY3MiA4MC40NzQ5Wk00OC43NzIgNzMuOTIyOUM0OC4zMDMgNzUuMTkxOSA0Ny40MTQgNzcuODUyOSA0Ni42OTcgODAuNjczOUM0OC45OTAxIDgwLjAwNTEgNTEuMzczMiA3OS42OTY0IDUzLjc2MSA3OS43NTg5QzU3LjE2OSA3OS44NDI5IDU5LjM0NyA4MS4yNTg5IDU5LjM0NyA4NC4wNzI5QzU5LjM0NyA5MC45MDM5IDUxLjc5NyA5Mi45MTA5IDQ2LjU1OSA5Mi45MTA5QzQwLjgwNyA5Mi45MTA5IDM1Ljc1OSA4OS42MzU5IDM1Ljc1OSA4My4zNDY5QzM1Ljc1OSA3NS45NzM5IDM5Ljc1OSA2NC43OTI5IDQzLjUwNyA1Ny4zNDY5QzQ4LjExNCA0OC4yMDE5IDUyLjgxOSA0Ni45ODQ5IDYwLjkyNSA0Ni45ODQ5QzY0LjQ4OSA0Ni45ODQ5IDY4LjU5MyA0OC41MDg5IDY4LjU5MyA1MS44Njk5QzY4LjU5MyA1Ni41MzI5IDY0LjY0MyA1OC4zMTI5IDYwLjcyNiA1OC41MzY5QzU4LjggNTguNjY0IDU2Ljg2ODcgNTguNjkgNTQuOTQgNTguNjE0OUM1My44NzMxIDYwLjM2ODIgNTIuOTcyOCA2Mi4yMTc2IDUyLjI1MSA2NC4xMzg5QzU5LjUwMyA2My4xMTg5IDYyLjU3NyA2NC43NjQ5IDYxLjM1MSA2OC45NTg5QzU5LjY5NSA3NC42MjU5IDU0Ljc4NCA3NC45OTg5IDQ4Ljc3IDczLjkyMjlINDguNzcyWk04NC40NDEgNTYuMjkxOUM4My41ODA5IDU2LjMzOCA4Mi43NDYxIDU2LjU5ODYgODIuMDEyNSA1Ny4wNDk5QzgxLjI3ODkgNTcuNTAxMiA4MC42Njk5IDU4LjEyOSA4MC4yNDEgNTguODc1OUM3OC4xNDEgNjEuODI1OSA3My41ODUgNzMuNjU0OSA3Mi44NzYgNzguNTEzOUM3Mi4zOSA4MS44NDI5IDczLjgyNyA4Mi41MjA5IDc1LjM5OSA4Mi41MjA5Qzc3LjkxOCA4Mi41MjA5IDgwLjc0MiA3OS44NTQ5IDgxLjcwNyA3NS40NTM5QzgxLjcwNyA3NS40NTM5IDc2LjkwNyA3NS4zMzc5IDc4LjIzNCA3MS4wODQ5Qzc5LjUxOCA2Ni45NTY5IDgxLjk1NSA2Ni4wNjI5IDg1Ljk5NiA2NS44OTY5QzkzLjk1NyA2NS41NzA5IDkzLjE3MSA3MS40NDk5IDkyLjUzMyA3NC41ODQ5QzkwLjQ2NSA4NC43NjM5IDgzLjIyIDkyLjk0MTkgNzIuOTcyIDkyLjk0MTlDNjUuOTU2IDkyLjk0MTkgNjEuNiA4OS4wNjE5IDYxLjYgODEuOTA0OUM2MS42IDc2LjgwNDkgNjQuMTI5IDY4LjgwNDkgNjYuMTM0IDY0LjEyMjlDNzAuNDAyIDU0LjE1NDkgNzQuODc2IDQ3LjE3NzkgODYuMjc3IDQ3LjE3NzlDOTMuMTE3IDQ3LjE3NzkgOTguNTEzIDQ5LjYzNDkgOTcuNzIyIDU2LjA0MzlDOTcuMTQxIDYwLjc0MzkgOTQuNzg3IDYzLjUwODkgOTAuNTExIDYzLjg0MzlDODkuMzE2IDYzLjkzNzkgODQuNDIzIDYzLjgxNDkgODYuMDQ2IDU5LjE4NDlDODYuNjExIDU3LjU2NDkgODYuODQ0IDU2LjI5MTkgODQuNDM5IDU2LjI5MTlIODQuNDQxWk0xMjcuNDk4IDY0LjcwNDlDMTI2LjEwMiA3MS4xMzE4IDEyMy43OTIgNzcuMzI1NCAxMjAuNjM4IDgzLjA5NjlDMTE1LjgzOCA5MS43MzA5IDExMC4wMDYgOTIuOTM4OSAxMDQuOTE1IDkyLjg3ODlDOTkuODI0IDkyLjgxODkgOTQuMDg1IDkwLjkzNzkgOTQuMDQyIDgzLjA3ODlDOTQuMDEgNzcuNDM5OSA5Ni40NDIgNjkuNDc4OSA5OC41MDggNjQuMjYzOUMxMDIuMTA4IDU0LjgwNTkgMTA1Ljc4NSA0Ny4wOTQ5IDExNy40MDggNDcuMjMyOUMxMzAuOTY5IDQ3LjM5NzkgMTI4LjU1NCA1OS40NTI5IDEyNy40OTYgNjQuNzA0OUgxMjcuNDk4Wk0xMTcuODMgNTguNzkyOUMxMTcuNjg2IDYyLjQxMzkgMTEyLjM3OCA3Ni44OTI5IDExMC40OTIgODAuMDkyOUMxMDkuNjc1IDgxLjQ3NzkgMTA4Ljc1NCA4Mi42MjI5IDEwNy4wOTIgODIuNjIyOUMxMDYuODAzIDgyLjYzNDYgMTA2LjUxNSA4Mi41ODUyIDEwNi4yNDYgODIuNDc3OEMxMDUuOTc4IDgyLjM3MDUgMTA1LjczNSA4Mi4yMDc3IDEwNS41MzQgODJDMTA1LjMzMiA4MS43OTIzIDEwNS4xNzcgODEuNTQ0NSAxMDUuMDc4IDgxLjI3MjdDMTA0Ljk4IDgxLjAwMDkgMTA0LjkzOSA4MC43MTEzIDEwNC45NiA4MC40MjI5QzEwNC44NTUgNzcuMTU1OSAxMTAuODUxIDYwLjc3MDkgMTEyLjkwMiA1OC4xMTI5QzExMy4yMDQgNTcuNTcxNSAxMTMuNjU3IDU3LjEzIDExNC4yMDYgNTYuODQyNEMxMTQuNzU1IDU2LjU1NDggMTE1LjM3NiA1Ni40MzM3IDExNS45OTMgNTYuNDkzOUMxMTcuNjk1IDU2LjUwOTkgMTE3Ljg3IDU3LjczNzkgMTE3LjgyOCA1OC43OTI5SDExNy44M1oiIGZpbGw9IiMxODE3MTYiLz4KPC9nPgo8ZGVmcz4KPGNsaXBQYXRoIGlkPSJjbGlwMF81MDAwXzIyNDU0Ij4KPHJlY3Qgd2lkdGg9IjU4Ny40NDEiIGhlaWdodD0iNDM1Ljk4NSIgZmlsbD0id2hpdGUiLz4KPC9jbGlwUGF0aD4KPC9kZWZzPgo8L3N2Zz4K" alt="" onerror="this.style.display = 'none'"></div></a></figure><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://education.lego.com/ko-kr/products/-/45678/?ref=blog.sungkwang.me"><div class="kg-bookmark-content"><div class="kg-bookmark-title">레고 스파이크 프라임 생활 코딩 | LEGO® Education</div><div class="kg-bookmark-description">생활 코딩 및 레고 Ai를 활용한 추상적 사고와 비판적 사고 능력을 개발하는 레고 에듀케이션 스파이크 프라임 코딩 수업 계획을 만나보세요.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://static.ghost.org/v5.0.0/images/link-icon.svg" alt=""><span class="kg-bookmark-author">LEGO® Education</span><span class="kg-bookmark-publisher">LEGO® Education</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://assets.education.lego.com/v3/assets/blt293eea581807678a/blt96801dfdfb5b7521/627118b9941a2939d3d00593/45678_prod_packaging_SPIKE_PRIME_Set_01.png?locale=ko-kr&amp;auto=webp&amp;format=jpeg&amp;width=216&amp;height=124&amp;quality=90&amp;fit=bounds" alt="" onerror="this.style.display = 'none'"></div></a></figure><p><a href="https://www.lego.com/ko-kr/product/lego-education-spike-prime-set-45678?ref=blog.sungkwang.me">https://www.lego.com/ko-kr/product/lego-education-spike-prime-set-45678</a></p><h2 id="scratch-coding">Scratch Coding</h2><p>요즘은 블록코딩 플랫폼이 많다. 네이버에서 만든 것도 있고, 마이크로소프트에서 만든 것도 있지만 가장 보편적으로 많이 사용하는 Scratch 를 추천 한다.</p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://scratch.mit.edu/?ref=blog.sungkwang.me"><div class="kg-bookmark-content"><div class="kg-bookmark-title">Scratch - Imagine, Program, Share</div><div class="kg-bookmark-description">Scratch is a free programming language and online community where you can create your own interactive stories, games, and animations.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://static.ghost.org/v5.0.0/images/link-icon.svg" alt=""><span class="kg-bookmark-author">Imagine, Program, Share</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://scratch.mit.edu/images/scratch-og.png" alt="" onerror="this.style.display = 'none'"></div></a></figure><p><a href="https://blog.sungkwang.me/signing-up-for-scratch/" rel="noreferrer">Scratch를 시작하는 방법</a>은 블로그에서 소개한 적이 있으니 참조하면 도움이 될 것 같다.</p><p>블록코딩은 초등학교 3학년초에 시작했는데,  여러 일정 때문에 초등학교 3학년 겨울방학에 본격적으로 가르쳐주고 있다. 개인적으로는 3학년 겨울 방학에 배우는 것이 최적으로 보인다. 훨씬 이해도 빠르고, 배운 내용을 스스로 다양하게 응용하면서 즐기는 것 같다. 파이썬 코딩 보다 블록코딩이 훨씬 직관적이고 재밌다. 학생들에게 두가지 모두 가려쳐본 입장에서 반드시 블록 코딩을 경험하는 것을 권하고 싶다. 너무 재밌다. 이번 LEGO Education SPIKE Prime 교육에 가서 컴퓨터 전공자인 아빠가 아들보다 더 신나서 이것 저것 물어봤으니.. 블록코딩이 얼마나 재밌는지 따로 설명 하지 않아도 될 것 같다. (강사분께서 많이 놀라신듯 했지만, 우리는 거리 센스를 이용해 장애물을 감지하는 코드까지 추가했다)</p><h2 id="differential">Differential</h2><p>이번 교육은 LEGO Education SPIKE Prime 교육은 2개의 모터를 회전 반경에 따라 다른 속도로 동작하게 코딩하여 자동차의 "차동장치(Differential)"의 원리를 이해하고 직접 코딩하는 것을 배웠다.</p><figure class="kg-card kg-embed-card"><iframe width="200" height="113" src="https://www.youtube.com/embed/nC6fsNXdcMQ?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" title="Differential | How does it work?"></iframe></figure><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://www.tec-science.com/mechanical-power-transmission/planetary-gear/how-does-a-differential-gear-work/?ref=blog.sungkwang.me"><div class="kg-bookmark-content"><div class="kg-bookmark-title">How does a differential gear work? | tec-science</div><div class="kg-bookmark-description"></div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://static.ghost.org/v5.0.0/images/link-icon.svg" alt=""><span class="kg-bookmark-author">logo tec-science</span><span class="kg-bookmark-publisher">tec-science</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://www.tec-science.com/wp-content/uploads/2021/03/en-differential-gear-from-to-05-pinion-bevel-gears.jpg" alt="" onerror="this.style.display = 'none'"></div></a></figure><p>레고 조립은 익숙해서 너무 쉽게 진행되었다. 코딩도 Scratch 에 센서가 추가되어 블록코딩을 할 수 있게 만들어져 있어서 익숙하게 따라할 수 있었다. </p><p>LEGO Education SPIKE Prime은 코어 패키지 안에 전력을 공급하는 Hub와 모터, 그리고 각종 센스가 있다. 이 것을 사용해서 차동장치 매커니즘을 알고리즘으로 코딩할 수 있다.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://s3.ap-northeast-2.amazonaws.com/hbn-user-sksong/2026/01/Testing-the-Spike-Prime-Motors-and-Sensors-Facebook-no-text.jpg" class="kg-image" alt="" loading="lazy" width="1200" height="628"><figcaption><span style="white-space: pre-wrap;">credit: PESEARCH PARENT</span></figcaption></figure><p>차동장치에 알고리즘은 초등학생에게는 조금 어려운 원리였는데, 블록코딩에서 알고리즘을 블록으로 만드는 부분을 진행할 때는 부모님들의 도움이 필요했다. 그외 다른 코딩은 3학년 아들이 따라가면서 잘 해낼수 있었다. </p><figure class="kg-card kg-image-card"><img src="https://s3.ap-northeast-2.amazonaws.com/hbn-user-sksong/2026/01/IMG_1259-1.JPG" class="kg-image" alt="" loading="lazy" width="4032" height="3024"></figure><p>LEGO Education SPIKE Prime의 최고 장점은 블록코딩을 블루투스로 바로 실행할 수 있는 것이다. 이전에는 (레고 마인드스톰 같은) USB 케이블을 연결하던지, 유선 인터페이스를 연겨래서 코드를 실행했기 때문에 실행 반경이나 여러가지 제한 사항이 많았다. 하지만 블루투스로 원격에서 코드를 바로 실행하니 컴퓨터 연결된 제한에서 벗어나 다양한 명령어를 실행할 수 있다.</p><figure class="kg-card kg-video-card kg-width-regular" data-kg-thumbnail="https://s3.ap-northeast-2.amazonaws.com/hbn-user-sksong/hbn-user-sksong/2026/01/lego_spike_prime_tutorial_thumb.jpg" data-kg-custom-thumbnail="">
            <div class="kg-video-container">
                <video src="https://s3.ap-northeast-2.amazonaws.com/hbn-user-sksong/2026/01/lego_spike_prime_tutorial.mp4" poster="https://img.spacergif.org/v1/1920x1080/0a/spacer.png" width="1920" height="1080" playsinline="" preload="metadata" style="background: transparent url('https://s3.ap-northeast-2.amazonaws.com/hbn-user-sksong/hbn-user-sksong/2026/01/lego_spike_prime_tutorial_thumb.jpg') 50% 50% / cover no-repeat;"></video>
                <div class="kg-video-overlay">
                    <button class="kg-video-large-play-icon" aria-label="Play video">
                        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                            <path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"></path>
                        </svg>
                    </button>
                </div>
                <div class="kg-video-player-container">
                    <div class="kg-video-player">
                        <button class="kg-video-play-icon" aria-label="Play video">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"></path>
                            </svg>
                        </button>
                        <button class="kg-video-pause-icon kg-video-hide" aria-label="Pause video">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <rect x="3" y="1" width="7" height="22" rx="1.5" ry="1.5"></rect>
                                <rect x="14" y="1" width="7" height="22" rx="1.5" ry="1.5"></rect>
                            </svg>
                        </button>
                        <span class="kg-video-current-time">0:00</span>
                        <div class="kg-video-time">
                            /<span class="kg-video-duration">0:02</span>
                        </div>
                        <input type="range" class="kg-video-seek-slider" max="100" value="0">
                        <button class="kg-video-playback-rate" aria-label="Adjust playback speed">1×</button>
                        <button class="kg-video-unmute-icon" aria-label="Unmute">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M15.189 2.021a9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h1.794a.249.249 0 0 1 .221.133 9.73 9.73 0 0 0 7.924 4.85h.06a1 1 0 0 0 1-1V3.02a1 1 0 0 0-1.06-.998Z"></path>
                            </svg>
                        </button>
                        <button class="kg-video-mute-icon kg-video-hide" aria-label="Mute">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M16.177 4.3a.248.248 0 0 0 .073-.176v-1.1a1 1 0 0 0-1.061-1 9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h.114a.251.251 0 0 0 .177-.073ZM23.707 1.706A1 1 0 0 0 22.293.292l-22 22a1 1 0 0 0 0 1.414l.009.009a1 1 0 0 0 1.405-.009l6.63-6.631A.251.251 0 0 1 8.515 17a.245.245 0 0 1 .177.075 10.081 10.081 0 0 0 6.5 2.92 1 1 0 0 0 1.061-1V9.266a.247.247 0 0 1 .073-.176Z"></path>
                            </svg>
                        </button>
                        <input type="range" class="kg-video-volume-slider" max="100" value="100">
                    </div>
                </div>
            </div>
            
        </figure><p>좁은 책상에서만 코드를 실행하는 것이 아니라, 실제 넓은 필드에서 내가 작성한 코드를 실행할 수 있다. 차동장치와 거리센서를 이용하여 충돌을 회피하는 코드를 작성했는데 실제 동작하는 것을 보면서 코드의 동작을 확인할 수 있었다.</p><figure class="kg-card kg-video-card kg-width-regular" data-kg-thumbnail="https://s3.ap-northeast-2.amazonaws.com/hbn-user-sksong/hbn-user-sksong/2026/01/lego_spike_prime_car2_thumb.jpg" data-kg-custom-thumbnail="">
            <div class="kg-video-container">
                <video src="https://s3.ap-northeast-2.amazonaws.com/hbn-user-sksong/2026/01/lego_spike_prime_car2.mp4" poster="https://img.spacergif.org/v1/1920x1080/0a/spacer.png" width="1920" height="1080" playsinline="" preload="metadata" style="background: transparent url('https://s3.ap-northeast-2.amazonaws.com/hbn-user-sksong/hbn-user-sksong/2026/01/lego_spike_prime_car2_thumb.jpg') 50% 50% / cover no-repeat;"></video>
                <div class="kg-video-overlay">
                    <button class="kg-video-large-play-icon" aria-label="Play video">
                        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                            <path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"></path>
                        </svg>
                    </button>
                </div>
                <div class="kg-video-player-container">
                    <div class="kg-video-player">
                        <button class="kg-video-play-icon" aria-label="Play video">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"></path>
                            </svg>
                        </button>
                        <button class="kg-video-pause-icon kg-video-hide" aria-label="Pause video">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <rect x="3" y="1" width="7" height="22" rx="1.5" ry="1.5"></rect>
                                <rect x="14" y="1" width="7" height="22" rx="1.5" ry="1.5"></rect>
                            </svg>
                        </button>
                        <span class="kg-video-current-time">0:00</span>
                        <div class="kg-video-time">
                            /<span class="kg-video-duration">0:04</span>
                        </div>
                        <input type="range" class="kg-video-seek-slider" max="100" value="0">
                        <button class="kg-video-playback-rate" aria-label="Adjust playback speed">1×</button>
                        <button class="kg-video-unmute-icon" aria-label="Unmute">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M15.189 2.021a9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h1.794a.249.249 0 0 1 .221.133 9.73 9.73 0 0 0 7.924 4.85h.06a1 1 0 0 0 1-1V3.02a1 1 0 0 0-1.06-.998Z"></path>
                            </svg>
                        </button>
                        <button class="kg-video-mute-icon kg-video-hide" aria-label="Mute">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M16.177 4.3a.248.248 0 0 0 .073-.176v-1.1a1 1 0 0 0-1.061-1 9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h.114a.251.251 0 0 0 .177-.073ZM23.707 1.706A1 1 0 0 0 22.293.292l-22 22a1 1 0 0 0 0 1.414l.009.009a1 1 0 0 0 1.405-.009l6.63-6.631A.251.251 0 0 1 8.515 17a.245.245 0 0 1 .177.075 10.081 10.081 0 0 0 6.5 2.92 1 1 0 0 0 1.061-1V9.266a.247.247 0 0 1 .073-.176Z"></path>
                            </svg>
                        </button>
                        <input type="range" class="kg-video-volume-slider" max="100" value="100">
                    </div>
                </div>
            </div>
            
        </figure><p>초등학교 3학년 블록코딩을 하면서 코드가 화면에서만 동작하는 것만 봤었는데, 이렇게 물리적으로 기계를 움직이게 만드는 경험을 하면서 코딩에 대해 더 흥미를 가질 수 있게 되었다.</p><p>짧은 교육 시간으로 센서에 대해 충분히 경험할 수 없었지만 아이에게 충분히 유익한 시간이였다.</p> ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[ Zootopia 2 ]]></title>
        <description><![CDATA[ 2026년 첫 시작을 가족과 함께 조조영화 감상으로 시작하였다. 아이부터 어른까지 모두 너무 재밌고 따뜻하게 볼 수 있는 주토피아2를 관람했다. ]]></description>
        <link>https://blog.sungkwang.me/zootopia-2/</link>
        <guid isPermaLink="false">6959991997abb6bbac1f8e77</guid>
        <category><![CDATA[ Story ]]></category>
        <dc:creator><![CDATA[ 송성광 ]]></dc:creator>
        <pubDate>일, 04 1월 2026 09:13:06 +0900</pubDate>
        <media:content url="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2026/01/IMG_0849-1.jpeg" medium="image"/>
        <content:encoded><![CDATA[ <p>2026년 첫 시작을 가족과 함께 조조영화 감상으로 시작하였다. 아들의 겨울방학이 일주일 밖에 되지 않아서 여행할 시간이 되지 않고, 계속되는 추위에 야외활동이 어려워 영화를 선택했다. (물론, 내가 디즈니 에니메이션을 좋아하는 것도 큰 이유였다.)</p><p>아직 초등 저학년인 아들 때문에 자막보다 더빙으로 봤다. 개인적으로 이 영화는 자봐도 좋지만 더빙으로 보는게 좋다고 생각된다. 이 영화는 워낙 대화가 빠르게 진행되어서 자막속도 빠르고, 무엇보다 주토피아의 매력은 영화 화면 구석구석 표현한 재밌는 요소들을 자막을 보면 놓치기 때문이다. 가끔 미국 특유의 유머가 한국식 유머로 의역되어서 어색하긴 하지만 성우 연기들이 꽤 좋다. 그래서 원래는 항상 원어로 보는 것을 좋아하지만, 이 영화만큼은 자막을 추천한다.</p><p>이 에니메이션이 영화였다면 주토피아 첫편 이후로 시간이 꽤 흘러 Judy와 Nick이 나이가 느껴질수 있지만, 에니메이션은 항상 그대로의 모습을 유지해서 좋은것 같다. 헤리포터는 1편과 3편의 느낌이 다르지만, 주토피아는 첫 느낌 그대로 계속 진행형으로 보게되어 좋은것 같다.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2026/01/IMG_0848.jpeg" class="kg-image" alt="" loading="lazy" width="3840" height="2159"><figcaption><span style="white-space: pre-wrap;">Zootopia2, credit: Diseny</span></figcaption></figure><p>원래 속편은 자칫 잘못하면 반복되는 캐릭터 때문에 지루할 수 있는데, 새로운 캐릭터 등장으로 조화롭게 이야기를 펼쳐나간다. 그래도 역시나 Judy와 Nick은 너무 귀엽고 사랑스럽기만 하다.</p><p>2026년 첫날, 가족과 함께 아침도 먹지 않고 달려가 팝콘을 먹으며 조조영화를 봤다. 평범하지만 소소로운 즐거움으로 시작하는 우리 가족. 영화도 따뜻했지만, 하루종일 종알종알 주토피아 이야기를 하면서 웃음을 가질 수 있어서 감사한 하루의 시작이였다.</p><p>지난해는 논문 준비로 가족들과 많은 시간을 보내지 못해서 미안하고 아쉬웠는데, 올해는 열심히 연구하면서 가족과 함께 따뜻한 한해를 보내고 싶다.  </p> ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[ 크리스마스 선물 대작전 ]]></title>
        <description><![CDATA[ 아직 산타를 믿는(?) 아들을 위해 2025년 크리스마스 선물 대작전을 펼쳤다. 아들의 10번째 크리스마스 이야기를 기록한다. ]]></description>
        <link>https://blog.sungkwang.me/the-christmas-story-of-2025/</link>
        <guid isPermaLink="false">694c148697abb6bbac1f8df9</guid>
        <category><![CDATA[ Story ]]></category>
        <dc:creator><![CDATA[ 송성광 ]]></dc:creator>
        <pubDate>금, 26 12월 2025 09:41:16 +0900</pubDate>
        <media:content url="https://images.unsplash.com/photo-1576344333162-f83e5e18902e?crop&#x3D;entropy&amp;cs&#x3D;tinysrgb&amp;fit&#x3D;max&amp;fm&#x3D;jpg&amp;ixid&#x3D;M3wxMTc3M3wwfDF8c2VhcmNofDE0MXx8Y2hyaXN0bWFzfGVufDB8fHx8MTc2NjU5MzYxOXww&amp;ixlib&#x3D;rb-4.1.0&amp;q&#x3D;80&amp;w&#x3D;2000" medium="image"/>
        <content:encoded><![CDATA[ <p>아직 산타를 믿는(?) 아들을 위해 올해도 선물 대작전이 펼쳐졌다. 우리집에 찾아온 감기 때문에 크리스마스 이브를 그냥 지나칠뻔 했지만, 우리 가족이 매년 연말에 가던 파스타집에서 소소하게 성탄을 기념하며 식사를 했다.</p><p>우리는 식사를 마치고 팝콘을 사서 크리스마스 영화를 함께 보며 크리스마스를 기다렸다. 크리스마스에는 "나홀로 집에" 영화가 정석이지만 이미 작년까지 모든 시리즈를 봤기 때문에 올해는 Christmas Chronicles 영화를 선택했다. 아직 산타를 믿는 아들에게 어쩌면 마지막으로 같이 산타할아버지 이야기를 나눌수 있을것 같은 생각에 선택한 영화이다. 11살이 되면 아들은 더이상 산타를 믿지 않겠지... 이런 생각을하면 왠지 슬프네... </p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://www.imdb.com/title/tt2990140/?ref=blog.sungkwang.me"><div class="kg-bookmark-content"><div class="kg-bookmark-title">크리스마스 연대기 (2018) ⭐ 7.0 | Adventure, Comedy, Family</div><div class="kg-bookmark-description">1h 44m | All</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://static.ghost.org/v5.0.0/images/link-icon.svg" alt=""><span class="kg-bookmark-author">IMDb</span><span class="kg-bookmark-publisher">vikingsjas12</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://m.media-amazon.com/images/M/MV5BNTA3NjU3OTM2MV5BMl5BanBnXkFtZTgwNjQ2MzE1NjM@._V1_FMjpg_UX1000_.jpg" alt="" onerror="this.style.display = 'none'"></div></a></figure><figure class="kg-card kg-embed-card"><iframe width="200" height="113" src="https://www.youtube.com/embed/YaeDa_Uempk?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" title="The Christmas Chronicles | Official Trailer | Netflix"></iframe></figure><p>이 영화는 어른이 봐도 정말 재밌는 영화이다. 왠지 진짜 산타는 이러지 않을까? 하는 상상을 할 수 있게 해줬다. 이 영화를 보는 시간 동안 잠시 동심으로 돌아갔던것 같다. 특히 Kurt Russell 이 산타역을 맡았는데 너무 멋진 산타로 나와서 깜짝 놀랐다. 이 배우는 분노의 질주의 Nobody역을 맡은 배우이다. 그 때도 멋있다고 생각했는데 이 영화에서 정말 찰떡같이 산타역을 연기했다.</p><p>문제는 지금부터이다. 아들은 산타 영화까지 봤겠다... 산타가 오는 시간만 기다린다. 잠도 오지 않고, 5분마다 몇시냐고 물어본다. ㅠㅠ </p><p>네가 자야 산타가 오지 </p><p>아들이 잠들지 못해서 크리스마스 선물 대작전이 실패로 돌아갈까 마음이 급해진다. 늦은 시간 아들이 잠들고 나서 이젠 산타가 활동하는 시간이다. 미리 준비했던 선물을 꺼내고 포장을 하려는데 포장지가 없다. 아내는 아들이 이제 산타가 아빠인지 안다면서 그냥 종이봉투에 넣어서 직접 주라고 했지만, 아빠에겐 10살의 마지막 산타를 지켜주고 싶은 마음이 가득하다. 집에 있는 종이 봉투를 잘라 포장지를 만들어서 포장했다. 아들이 포장지를 뜯을때, "아빠, 산타할아버지가 환경을 위해서 재활용 포장지를 사용한것 같아요" 라고 하는데 ㅋㅋ </p><p>산타할아버지는 잠을 자야 온다고 몇번이나 말해도 5분마다 계속 물어보는 아들, 새벽에 겨우 포장완료 했고 이제 자려고 하는데, 아들은 새벽 5시부터 일어나서 또 하염없이 해뜨기를 기다린다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/12/IMG_F6ACCFFF4D06-1.jpeg" class="kg-image" alt="" loading="lazy" width="1255" height="710"></figure><p> 2025년 아들의 10번째 크리스마스, 올해도 무사히 크리스마스 선물 대작전은 성공했다.</p><p>어쩌면... 너는 이미 산타가 아빠인지도 알고 있겠지? 하지만 우리는 누구도 산타가 누구인지 말하지 않았다. 너는 아직 10살이 너로, 아빠는 아직 동심의 너로 우리는 그렇게 2025년 크리스마스를 맞이했다. 어쩌면 11살에 너는 더이상 산타가 없다고 생각할지 모르겠지만, 아빠 마음속에서 크리스마스에서 너는 항상 아빠 산타를 기다리는 아들로 기억될거야.</p><p>사랑해 아들</p><p>그리고, 아내에게 받은 깜짝 크리스마스 카드~</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/12/IMG_1032_.png" class="kg-image" alt="" loading="lazy" width="4031" height="3023"></figure><p>아기 예수님의 탄생을 찬양합니다. 메리크리스마스~ 기쁜 성탄절입니다.</p> ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[ Ghost 블로그 도메인 변경 ]]></title>
        <description><![CDATA[ Ghost 블로그 운영중 도메인을 변경하게 되었다. AWS 환경에서 새로운 도메인을 적용하기 위해 어떤 과정으로 완전히 도메인 마이그레이션 했는지 소개한다. ]]></description>
        <link>https://blog.sungkwang.me/ghost-blog-migrate-to-a-new-domain/</link>
        <guid isPermaLink="false">694b827d97abb6bbac1f8d79</guid>
        <category><![CDATA[ Tech ]]></category>
        <dc:creator><![CDATA[ 송성광 ]]></dc:creator>
        <pubDate>수, 24 12월 2025 16:21:48 +0900</pubDate>
        <media:content url="https://images.unsplash.com/photo-1687524690542-2659f268cde8?crop&#x3D;entropy&amp;cs&#x3D;tinysrgb&amp;fit&#x3D;max&amp;fm&#x3D;jpg&amp;ixid&#x3D;M3wxMTc3M3wwfDF8c2VhcmNofDF8fGhvbWVwYWdlJTIwZG9tYWlufGVufDB8fHx8MTc2NjU1NjI2Nnww&amp;ixlib&#x3D;rb-4.1.0&amp;q&#x3D;80&amp;w&#x3D;2000" medium="image"/>
        <content:encoded><![CDATA[ <p>블로그 도메인 변경을 했다. 기존에는 blog.sungkwang.dev 였는데, 블로그가 너무 기술적인 내용만 가지고 있는 느낌을 줘서 좀 더 개인 사이트적인 느낌이 나도록 blog.sungkwang.me 도메인으로 변경했다. .com 이나 .net 으로 만들고 싶기도 했지만 회사규모도 아니고 개이적인 온라인 공간으로 .me 가 적당하다고 생각했다.</p><p>도메인을 변경하면 해야할 일들이 많다. 인터넷에서 도메인 기반으로 사이트를 찾을 수 있기 때문에 관련된 부분을 모두 변경해야한다. 우선 검색엔진에 등록된 부분들은 향후 검색엔진에서 제거될 것으로 위임했다. 명시적으로 삭제 요구를 해도 되지만... 개인 블로그가 뭐 그렇게 영향력 있는것도 아니고 시간이 지나면 자연적으로 인덱스에서 제외될 것이다. 몇 달 후에도 여전히 검색이 된다면 삭제 요청을 할 예정이다.</p><p>문제는 서버에 설정된 도메인 정보를 모두 수정해야한다. 수정해야할 부분은 크게 다음과 같다.</p><ul><li>변경할 도메인 구입</li><li>네임서버 지정</li><li>Domain Name Server 에 도메인 등록</li><li>SSL 인증서 생성</li><li>Ghost 설정에서 도메인 변경</li></ul><h2 id="%EB%8F%84%EB%A9%94%EC%9D%B8-%EA%B5%AC%EC%9E%85">도메인 구입</h2><p>도메인 구임은 간단하다. 국내에서 구매할 경우 가장 인지도 있는 후이즈나 가비아에서 구입하면 된다. 최근에는 AWS Route53에서도 바로 구입할 수 있다. 나는 기존에 가비아를 사용하고 있어서 가비아를 통해 sungkwang.me 도메인을 구매했다. </p><h2 id="%EB%84%A4%EC%9E%84%EB%B2%84%EC%84%9C-%EC%A7%80%EC%A0%95">네임버서 지정</h2><p>가비아를 통해 도메인을 구매했지만 운영은 AWS에서 운영하기 위해서 AWS Name Server를 가비아 NS에 등록했다. 가비아와 AWS Route53 과 연동하는 블로그 글이 많기 때문에 내용은 생략한다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/12/Screenshot-2025-12-24-at-3.19.09---PM.png" class="kg-image" alt="" loading="lazy" width="1940" height="1452"></figure><h2 id="domain-name-server-%EC%97%90-%EB%8F%84%EB%A9%94%EC%9D%B8-%EB%93%B1%EB%A1%9D">Domain Name Server 에 도메인 등록</h2><p>가비아와 AWS Route53 연동을 했다면 앞으로 Route53을 통해서 도메인을 관리하면 된다. Ghost를 운영하는 서버는 AWS Lightsail 인데 Route53에 Lightsail의 static IP를 바로 등록해도 된다. 기존에 블로그는 이렇게 사용했는데, 이번 아키텍처는 AWS WAF를 이용한 보안과 캐싱에 대해서 추가적인 구성을 만들었다. 그래서 AWS Cloudfront를 사용하기로 했다.</p><h3 id="aws-cloudfront-%EC%97%90-distribution-%EB%93%B1%EB%A1%9D">AWS Cloudfront 에 Distribution 등록</h3><p>예전에는 AWS WAF는 유료로 사용만 되었는데 지금은 무료로 사용하는 플랜이 생겼다. 포함된 항목을 보면 안할 이유가 전혀없다. 실제 사이트를 운영할 때 필요한 보안 항목이 모두 포함되어 있는데 무료로 시작할 수 있다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/12/Screenshot-2025-12-24-at-3.29.36---PM.png" class="kg-image" alt="" loading="lazy" width="2742" height="1538"></figure><p>AWS Lightsail에서 AWS WAF를 바로 사용할 수 없다. 그래서 반드시 Cloudfront의 Origin으로 등록해서 사용해야한다. 이번에 설정에서 Free Plan을 사용해보기 위해서 Free Plan을 설정했다. </p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/12/Screenshot-2025-12-24-at-3.33.29---PM.png" class="kg-image" alt="" loading="lazy" width="3286" height="1372"></figure><p>이렇게 설정하면 무료이지만 아래와 같이 무료로 웹 공격을 확인할 수 있다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/12/Screenshot-2025-12-24-at-3.36.48---PM.png" class="kg-image" alt="" loading="lazy" width="3188" height="1164"></figure><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/12/Screenshot-2025-12-24-at-3.36.58---PM.png" class="kg-image" alt="" loading="lazy" width="3194" height="654"></figure><h3 id="ssl-%EC%9D%B8%EC%A6%9D%EC%84%9C">SSL 인증서</h3><p>AWS Lightsail에 운영할 때는 https 서비스를 위해서 Let's encrypt의 무료 인증서를 사용했었는데 매년 갱신해야하는 번거러움이 있고 AWS 서비스에 인증서 관리 기능이 있어서 <strong>AWS Certificate Manager</strong>를 이용하여 인증서를 만들어서 AWS Cloudfront 에 연결했다. AWS 인증서는 자동으로 갱신되기 때문에 한번 인증서를 만들어서 연결하면 계속 사용할 수 있다.</p><h2 id="ghost-%EC%84%A4%EC%A0%95-%ED%8C%8C%EC%9D%BC-%EC%88%98%EC%A0%95">Ghost 설정 파일 수정</h2><p>새로운 도메인을 적용하기 위해서 Ghost의 설정파일에 도메인 주소를 수정한다. Ghost 디렉토리에 있는 config.production.json 파일의 url 속성을 수정한다.</p><pre><code>{
  "url": "https://blog.sungkwang.me",
  ...,
}</code></pre><p>만약에 데이터베이스 이름이 도메인으로 되어 있을 경우는 데이터베이스 명을 변경하고 데이터베이스 명도 수정한다. 아마 최초 Ghost를 설치할 경우 도메인 기반으로 데이터베이스가 만들어지기 때문에 blog_sungkwang_dev_prod 라는 데이터베이스가 만들어진 것을 확인할 수 있다. 데이터베이스명을 변경하기 위해서 blog_sungkwnag_dev_prod를 덤프로 백업 받고 새로운 blog_sungkwang_me 데이터베이스를 만들어서 임포트 했다.</p><pre><code>sudo mysqldump -u root -p blog_sungkwang_dev_prod &gt; /tmp/ghost_backup.sql
sudo mysql -u root -p blog_sungkwang_me &lt; /tmp/ghost_backup.sql</code></pre><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/12/Screenshot-2025-12-24-at-4.05.35---PM.png" class="kg-image" alt="" loading="lazy" width="1104" height="438"></figure><p>다음은 데이터베이스에 저장된 데이터에 안에서 blog.sungkwang.dev의 도메인을 blog.sungkwang.me 로 업데이트를 한다.</p><pre><code>UPDATE posts SET html = REPLACE(html, 'blog.sungkwang.dev', 'blog.sungkwang.me') WHERE html LIKE '%blog.sungkwang.dev%';
UPDATE posts SET feature_image = REPLACE(feature_image, 'blog.sungkwang.dev', 'blog.sungkwang.me') WHERE feature_image LIKE '%blog.sungkwang.dev%';
UPDATE posts SET canonical_url = REPLACE(canonical_url, 'blog.sungkwang.dev', 'blog.sungkwang.me') WHERE canonical_url LIKE '%blog.sungkwang.dev%';
</code></pre><p> 이제 모든 설정이 끝났다. 마지막으로 Ghost 를 재시작한다.</p><pre><code>ghost restart</code></pre><p>이렇게 블로그 도메인을 변경한 이후, 네이버 서치 콘솔과 구글 서치 콘솔에 검색엔진에서 내 블로그를 수집할 수 있게 설정한다. 이 내용은 다음 포스팅에서 작성할 예정이다.</p> ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[ Ghost 블로그 로그인 되지 않은 문제 해결 ]]></title>
        <description><![CDATA[ Ghost의 staffDeviceVerification 속성에 의해 로그인 되지 않는 문제를 경험했다. 이 속성은 관리자가 새로운 디바이스에서 로그인할 때 알림 메일을 발송하는 속성인데 이 속성으로 로그인에 문제가 발생할 수 있다. ]]></description>
        <link>https://blog.sungkwang.me/ghost-staffdeviceverification-login-problem/</link>
        <guid isPermaLink="false">694b438994d766b92ad36062</guid>
        <category><![CDATA[ Tech ]]></category>
        <dc:creator><![CDATA[ 송성광 ]]></dc:creator>
        <pubDate>수, 24 12월 2025 14:47:32 +0900</pubDate>
        <media:content url="https://images.unsplash.com/photo-1623018035782-b269248df916?crop&#x3D;entropy&amp;cs&#x3D;tinysrgb&amp;fit&#x3D;max&amp;fm&#x3D;jpg&amp;ixid&#x3D;M3wxMTc3M3wwfDF8c2VhcmNofDF8fGVycm9yfGVufDB8fHx8MTc2NjQ4NTk5M3ww&amp;ixlib&#x3D;rb-4.1.0&amp;q&#x3D;80&amp;w&#x3D;2000" medium="image"/>
        <content:encoded><![CDATA[ <p>한해를 돌아보며 다시 블로그에 글을 작성하기 위해서 오랫만에 블로그에 접속했는데 도메인 연장 기간이 지나 도메인을 바꿔야 했다. 도메인을 바꾸면서 기존의 블로그 플랫폼을 다른 곳으로 사용하려고 했지만, 역시나 마땅히 마음에 드는 프랫폼이 없어 ghost 블로그 플랫폼을 그대로 사용하기로 했다. 그동안 업그레이드된 버전이 출시 되어 ghost cli로 업데이트를 진행하고, 변경된 도메인을 적용하기 위해서 설정 파일과 데이터베이스에 접근해 데이터를 수정했다.</p><p>기존에는 AWS Lightsail 만 사용했었는데, 이번에는 AWS Certificate + WAF + Cloudfront + Lightsail 구성으로 방화벽과 엣지를 추가해서 구성했다. 이와 관련된 자료는 자세하게 포스팅할 예정이다.</p><p>전체적인 설정을 모두 마친 후 새로운 도메인으로 접속해서 사이트가 정상적으로 서비스 되는 것을 확인했다. 모든 설정 확인 후, 글을 작성하기 위해  ghost에 로그인을 시도했지만 로그인이 되지 않는 문제를 발생했다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/12/SCR-20251224-lzfd.png" class="kg-image" alt="" loading="lazy" width="2362" height="1222"></figure><p> 이때부터 여러가지 이유들을 생각했다.</p><ul><li>비밀번호 불일치</li><li>도메인 변경으로 인한 Cookie 문제</li><li>AWS Cloudfront Cache 설정</li></ul><p>우선 비밀번호 불일치를 예상하고 데이터베이스에 패스워드를 업데이트 했지만 문제는 해결되지 않았다. 여러가지 자료를 찾아보며 ghost 버전이 올라가면서 관리자 인증 방식 때문인데 <a href="https://docs.ghost.org/config?ref=blog.sungkwang.me#security" rel="noreferrer"><strong>staffDeviceVerification</strong></a> 설정 때문에 인증이 완료되지 않는 문제 때문이였다. 이 속성은 새로운 디바이스에서 로그인을 할 경우 관리자에게 이메일로 알림을 전송하는 속성이다. 그런데 Ghost 에 이메일 설정을 제대로 하지 않았거나, email 속성을 <strong>Direct</strong> 로 설정한 경우 서버 자체 메일 시스템으로 발송을 하는 메커니즘으로 동작하는데 설정이 제대로 되어 있지 않아서 메일 발송에 문제가 생겨 응답시간이 길어지면서 자동으로 타임아웃이 되어 버린다. 그래서 가장 빠른 방법은 <strong>staffDeviceVerficiation</strong> 속성을 false 로 수정하는 것이다. 기본적으로 아무런 설정을 하지 않으면 내부적으로 <strong>true</strong>가 기본값이기 때문에 반드시 <strong>false</strong>로 명시적 설정을 해야한다. </p><p>Ghost 홈 디렉토리 안에서 <code>config.production.json</code> 파일을 열어서 다음 내용을 추가한다.</p><pre><code>vi config.production.json</code></pre><pre><code>{
  "url": "https://blog.sungkwang.me",
  "security": {
    "staffDeviceVerification": false
  },
  ...
}</code></pre><p>설정 파일을 수정한 다음 ghost를 재시작 한다.</p><pre><code>ghost restart</code></pre><p>다시 사이트에 로그인하면 세션 문제 없이 로그인이 잘 되는 것을 확인할 수 있다.</p> ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[ iPad + Raspberry Pi 기반 개발환경 구축 #5.  USB-C로 라즈베리파이 다이렉트 접속하기 ]]></title>
        <description><![CDATA[ iPad에서 USB-C를 이용하여 라즈베리파이의 전원과 이더넷 네트워크 데이터 전송을 한번에 처리하는 내용을 소개한다. ]]></description>
        <link>https://blog.sungkwang.me/building-an-ipad-and-raspberry-pi-based-development-environment-5-establishing-a-direct-usb-c-ethernet-connection-to-raspberry-pi/</link>
        <guid isPermaLink="false">67d7da00f6146c71a6f527fb</guid>
        <category><![CDATA[ Tech ]]></category>
        <dc:creator><![CDATA[ 송성광 ]]></dc:creator>
        <pubDate>월, 24 3월 2025 13:27:07 +0900</pubDate>
        <media:content url="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/03/IMG_7855-1.jpeg" medium="image"/>
        <content:encoded><![CDATA[ <p>iPad와Raspberry Pi 개발환경 구축 시리즈 글을 연재한 최종 목적은 iPad와 라즈베리파이 기기 2개만 간단히 휴대하면서 언제 어디서나 개발환경을 가질수 있는 것이다. 휴대성을 높이기 위해서 라즈베리파이를 위해 따로 전원 어댑터를 가지지 않게 했고, 접근성은 높이기 위해서 Wi-Fi 없이도 Ethernet을 사용하여 다이렉트로 연결할 수 있는 환경을 구축했었다. </p><p>iPad에서 이더넷을 이용해서 라즈베리파이로 다이렉트로 연결할 때 USB-C to Ethernet Adapter가 필요하고 두 기기가 서로 네트워크를 위해서 이더넷선이 필요하다. 라즈베리파이의 전원 어댑터 휴대 문제는 USB-C to Ethernet + Charge Adapter로 해결할 수 있지만, 휴대성 목적에 Ethernet 어댑터와 랜선을 모두 들고 다닌다는 것은 꽤 번거러운 일이다.</p><p>이번 포스팅에서는 iPad에서 Raspberry Pi 로 USB-C 케이블 하나만 가지고 전원도 공급하면서 동시에 Ethernet 네트워크 연결까지 한번에 해결할 수 있는 방법을 소개한다.</p><h2 id="rasberry-pi%EC%9D%98-usb-c-gadget%EC%84%A4%EC%A0%95">Rasberry Pi의 USB-C Gadget설정</h2><p>USB-C 타입은 구조자체가에 전원과 데이터를 전송할 수 있는 회로가 설계되어 있다. 라즈베리파이는 기본적으로 USB-C를 전원포트로 사용하게 되어 있는데 USB-C를 데이터통신도 같이 할 수 있게 커널을 변경하는 작업을 해서 전원과 데이터를 동시에 처리할 수 있게 하는 것이 핵심이다.</p><p>우선 Raspberry Pi로 접속한다. 이더넷선을 이용해서 접속해도 되고, 모니터를 연결해서 작업해도 된다. 나는 이더넷으로 연결해서 작업을 진행한다.</p><pre><code>ssh pi@raspberrypi</code></pre><h3 id="raspberry-pi-%EB%B6%80%ED%8A%B8-cmdlinetxt-%ED%8C%8C%EC%9D%BC-%EC%88%98%EC%A0%95">Raspberry Pi 부트 cmdline.txt 파일 수정</h3><p>가정 먼저 라즈베리파이의 부트 파일 중 cmdline.txt 파일을 수정한다. </p><pre><code>sudo vi /boot/firmeare/cmdline.txt</code></pre><p>파일을 열면 다음 내용이 있다.</p><pre><code>console=serial0,115200 console=tty1 root=PARTUUID=39fb6a92-02 rootfstype=ext4 fsck.repair=yes rootwait quiet splash plymouth.ignore-serial-consoles cfg80211.ieee80211_regdom=GB</code></pre><p>여기서 <code>rootwait</code> 바로 뒤에 <code>modules-load=dwc2,g_ether</code> 내용을 추가해서 수정한다.</p><pre><code>console=serial0,115200 console=tty1 root=PARTUUID=39fb6a92-02 rootfstype=ext4 fsck.repair=yes rootwait modules-load=dwc2,g_ether quiet splash plymouth.ignore-serial-consoles cfg80211.ieee80211_regdom=GB</code></pre><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/03/Screenshot-2025-03-24-at-10.44.40-AM.png" class="kg-image" alt="" loading="lazy" width="2420" height="210"></figure><h3 id="raspberry-pi-%EB%B6%80%ED%8A%B8-configtxt-%ED%8C%8C%EC%9D%BC-%EC%88%98%EC%A0%95">Raspberry Pi 부트 config.txt 파일 수정</h3><p>다음은 라즈베리파이 부트 파일 중 config.txt 파일을 수정한다.</p><pre><code>sudo vi /boot/firmware/config.txt</code></pre><p>파일을 열어서 <code>otg_mode=1</code> 을 찾아서 주석이 되어 있으면 주석을 풀어준다. 그리고 파일 가장 아래에 있는 <code>[all]</code> 섹션 밑에 <code>dtoverlay=dwc2</code> 를 추가한다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/03/Screenshot-2025-03-24-at-10.50.16-AM.png" class="kg-image" alt="" loading="lazy" width="2420" height="696"></figure><h3 id="raspberry-pi-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC%EC%97%90-ethernet-usb0-%EC%9D%B4%EB%8D%94%EB%84%B7-%EC%B6%94%EA%B0%80">Raspberry Pi 네트워크에 ethernet-usb0 이더넷 추가 </h3><p>라즈베리파이에서 <code>nmcli</code> 명령어를 사용하여 새로운 이더넷 네트워크를 추가한다.</p><pre><code>sudo nmcli con add type ethernet con-name ethernet-usb0</code></pre><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/03/Screenshot-2025-03-24-at-10.56.21-AM.png" class="kg-image" alt="" loading="lazy" width="1853" height="149"></figure><p> 위 명령러를 실행하면 라즈베리파이 운영체제의 네트워크 메니저 설정 디렉토리 밑에 새로운 <code>ethernet-usb0.connection</code> 파일이 생성된다. 이 파일을 다음 내용으로 수정한다.</p><pre><code>sudo vi /etc/NetworkManager/system-connections/ethernet-usb0.nmconnection</code></pre><p>수정할 때 주의 사항은 <strong>uuid</strong>는 생성되는 시점마다 다르게 발생하기 때문에 자신이 생성한 uuid 그대로 두고 나머지를 수정한다. IP 정보는 <strong>192.168.2.3</strong> 으로 지정했다. 앞에 글들에서 iPad와 라즈베리파이의 네트워크를 <strong>192.168.2.x</strong> 로 정의해서 설정했고, Ethernet 포트에 할당되어 있는 192.168.2.2 와 중복되지 않게 설정했다.</p><pre><code>[connection]
id=ethernet-usb0
uuid=자신의 UUID
type=ethernet
autoconnect=true
interface-name=usb0

[ethernet]

[ipv4]
address1=192.168.2.3/24
method=manual

[ipv6]
addr-gen-mode=default
method=auto

[proxy]</code></pre><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/03/Screenshot-2025-03-24-at-2.09.06-PM.png" class="kg-image" alt="" loading="lazy" width="2420" height="785"></figure><h2 id="raspberry-pi-%EC%9D%B4%EB%8D%94%EB%84%B7-%EA%B0%80%EC%A0%AF%EC%9D%84-%EC%8B%9C%EC%8A%A4%ED%85%9C-%EC%84%9C%EB%B9%84%EC%8A%A4-%EB%93%B1%EB%A1%9D">Raspberry Pi 이더넷 가젯을 시스템 서비스 등록</h2><p>앞에서 라즈베리파이에서 USB-C로 이더넷을 사용하는 설정을 추가했고, 이 설정을 시스템 서비스에서 자동으로 실행하고 관리할 수 있게 시스템 서비스로 등록한다.</p><h3 id="ethernet-usb-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC-%EC%84%A4%EC%A0%95-%ED%99%9C%EC%84%B1%ED%99%94-usb-gagdetsh-%ED%8C%8C%EC%9D%BC-%EC%B6%94%EA%B0%80">ethernet-usb 네트워크 설정 활성화 usb-gagdet.sh 파일 추가</h3><p>라즈베리파이 운영체제에 앞에서 추가한 ethernet-usb0 네트워크를 활성화하는 쉘 파일을 추가한다.</p><pre><code>sudo vi /usr/local/sbin/usb-gadget.sh</code></pre><pre><code>#!/bin/bash

nmcli con up ethernet-usb0</code></pre><p>이 파일은 시스템 서비스로 등록해서 실행하기 위해서 실행 권한을 파일에 추가한다.</p><pre><code>sudo chmod a+rx /usr/local/sbin/usb-gadget.sh</code></pre><h3 id="%EC%8B%9C%EC%8A%A4%ED%85%9C-%EC%84%9C%EB%B9%84%EC%8A%A4-%ED%8C%8C%EC%9D%BC-usbgadgetservice-%EC%B6%94%EA%B0%80">시스템 서비스 파일 usbgadget.service 추가</h3><p>위 네트워크 활성화 파일을 서비스 파일로 등록해 운영체제에서 서비스로 관리할 수 있게 다음 내용을 <code>usbgadget.service</code>  파일을 추가한다.</p><pre><code>sudo vi /lib/systemd/system/usbgadget.service</code></pre><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/03/Screenshot-2025-03-24-at-11.19.49-AM.png" class="kg-image" alt="" loading="lazy" width="1872" height="563"></figure><p>마지막으로 추가한 서비스 파일을 활성화 한다.</p><pre><code>systemctl enable usbgadget.service</code></pre><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/03/Screenshot-2025-03-24-at-11.21.33-AM.png" class="kg-image" alt="" loading="lazy" width="2141" height="147"></figure><p>이제 모든 설정이 끝났다. 라즈베리파이를 완전히 전원을 종료한다.</p><pre><code>sudo shutdown -h now</code></pre><h2 id="ipad-%EC%99%80-raspberry-pi-usb-c-%EC%97%B0%EA%B2%B0-%EC%84%A4%EC%A0%95">iPad 와 Raspberry Pi USB-C 연결 설정</h2><h3 id="usb-c-to-ethernet-%EC%96%B4%EB%8C%91%ED%84%B0%EC%99%80-%EB%9E%9C%EC%84%A0-%EC%A0%9C%EA%B1%B0">USB-C to Ethernet 어댑터와 랜선 제거</h3><p>USB-C to Ethernet Adapter와 랜선을 제거한다. 오직 iPad에 USB-C 선만 Raspberry Pi에 연결해서 다시 라즈베리파이를 부팅한다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/03/IMG_7855.jpeg" class="kg-image" alt="" loading="lazy" width="4032" height="3024"></figure><h3 id="ipad-%EC%97%90%EC%84%9C-ethernet-%EC%84%A4%EC%A0%95">iPad 에서 Ethernet 설정</h3><p>기존에 USB-C to Ethernet으로 라즈베리파이와 연결할 때는 iPad의 Ethernet 인터페이스에 Belkin Ethernet 어댑터 또는 10/100/1000 Ethernet 어댑터와 같이 설정이 나왔다. 라즈베리파이 USB-C에 gadget설정 추가한 뒤 USB-C만 가지고 iPad와 연결하면, iPad의 Ethernet 인터페이스에 다음과 같이 <strong>RNDIS/Ethernet Gadget</strong>이라고 나타난다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/03/Screenshot-2025-03-24-at-11.29.45-AM.png" class="kg-image" alt="" loading="lazy" width="2420" height="1097"></figure><p>iPad 이더넷을 192.168.2.x 대역으로 설정한다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/03/Screenshot-2025-03-24-at-11.37.25-AM.png" class="kg-image" alt="" loading="lazy" width="2420" height="1366"></figure><h3 id="ipad%EC%97%90%EC%84%9C-usb-c-%EC%9D%B4%EB%8D%94%EB%84%B7%EC%9C%BC%EB%A1%9C-raspberry-pi-%EC%A0%91%EC%86%8D">iPad에서 USB-C 이더넷으로 Raspberry Pi 접속</h3><p>iPad에서 Blink 앱을 열어 SSH로 라즈베리파이에 설정한 USB-C 이더넷에 설정한 192.168.2.3으로 접속한다.</p><pre><code>ssh pi@192.168.2.3</code></pre><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/03/Screenshot-2025-03-24-at-1.00.51-PM.png" class="kg-image" alt="" loading="lazy" width="2420" height="745"></figure><p>이젠 iPad에서 USB-C 선 하나로 Raspberry Pi에 연결해서 전원과 네트워크 데이터를 전송할 수 있게 되었다. 라즈베리파이에 설정된 네트워크 인터페이서를 살펴보면 <strong>usb0</strong> 인터페이스가 새롭게 추가된 것을 확인할 수 있다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/03/Screenshot-2025-03-24-at-12.54.06-PM.png" class="kg-image" alt="" loading="lazy" width="2420" height="1571"></figure><h2 id="%EA%B2%B0%EB%A1%A0">결론</h2><p>지금까지 iPad + Raspberry Pi 개발환경 구축하는 방법을 소개했다. 라즈베리파이에 VSCode Server remote 를 사용하여 iPad 에서 VSCode로 코딩을 하고 node.js나 Python  같은 런타임을 라즈베리파이 운영체제(리눅스 기반) 위에서 동작할 수 있다. 라즈베에파이 운영체제에 Python3.11 버전이 기본적으로 설치되어 있어 아래와 같이 최신 머신러닝 작업도 iPad에서 라즈베리파이를 통해서 테스트해볼 수 있다. </p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/03/Screenshot-2025-03-24-at-2.20.40-PM.png" class="kg-image" alt="" loading="lazy" width="2420" height="1668"></figure><p>라즈베리파이 기기 크기는 손바닥보다 작기 때문에 가볍고 항상 휴대할 수 있다. 라즈베리파이 4 전원은 USB-C 공급이 가능하기 때문에 따로 전원 어댑터 없이 iPad에 바로 연결해서 전원 공급을 할 수 있고, USB-C ethernet gadget 설정을 커널에 추가해서 따로 이더넷 어댑터나 랜선없이 USB-C선 하나로 전원공급과 네트워크 데이터 전송을 처리할 수 있어 휴대성을 극대화 할 수 있다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/03/IMG_7856.jpeg" class="kg-image" alt="" loading="lazy" width="4026" height="3019"></figure><h3 id="%EC%B0%B8%EA%B3%A0">참고</h3><ul><li><a href="https://www.andreagrandi.it/posts/howto-configure-ethernet-connection-ipad-raspberrypi-usbc/?ref=blog.sungkwang.me" rel="noreferrer">How to configure an Ethernet connection between iPad and RaspberryPi through USB-C</a></li></ul> ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[ Raspberry Pi 기반 개발환경 구축 #4 - macOS 인터넷 공유로 라즈베리파이 Wi-Fi 없이 인터넷 사용하기 ]]></title>
        <description><![CDATA[ Wi-Fi를 사용할 수 없는 공간이나 인터넷을 물리적으로 한대만 사용할 수 있는 상황에서 macOS의 인터넷 공유 기능을 이용하여 라즈베리파이에서 Wi-Fi 없이 인터넷을 사용할 수 있는 방법을 소개한다. ]]></description>
        <link>https://blog.sungkwang.me/building-an-ipad-and-raspberry-pi-based-development-environment-4-enabling-internet-access-on-raspberry-pi-without-wi-fi-using-macos-internet-sharing/</link>
        <guid isPermaLink="false">67dcf1d3f6146c71a6f52b67</guid>
        <category><![CDATA[ Tech ]]></category>
        <dc:creator><![CDATA[ 송성광 ]]></dc:creator>
        <pubDate>금, 21 3월 2025 16:25:08 +0900</pubDate>
        <media:content url="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/03/IMG_7711-1.jpg" medium="image"/>
        <content:encoded><![CDATA[ <p>요즘은 어딜가나 Wi-Fi를 사용할 수 있다. 공공 Wi-Fi 부터 개인 공유기까지 무료로 쉽게 사용할 수 있다. 가끔 Wi-Fi 공유기가 없는 곳이나 아니면 디바이스 접속 갯수를 제한하는 곳도 있다. 또한 갑자기 무선인터넷 공유기가 고장이 나는 상황이 발생할수도 있다. 모니터 사용하는 Raspberry Pi에 이런 상황이 발생하면 라즈베리파이에서 인터넷을 사용할 수 없는 문제가 발생한다. 만약 컴퓨터에서 인터넷을 사용할 수 있다면 "인터넷공유" 기능을 사용하여 이더넷으로 컴퓨터와 라즈베리파이를 연결해서 라즈베리파이에서 인터넷을 사용할 수 있다. 이번 포스팅에서는 macOS에서 인터넷공유 기능을 사용하여 Raspberry Pi에서 Wi-Fi 를 사용하지 않고 인터넷을 사용할 수 있는 방법을 소개한다.</p><h2 id="rasberry-pi-%EC%9D%B4%EB%8D%94%EB%84%B7%EC%9C%BC%EB%A1%9C-macbook%EC%97%90-%EC%97%B0%EA%B2%B0">Rasberry Pi 이더넷으로 MacBook에 연결</h2><p>가장 먼저 라즈베리파이를 MacBook에 연결한다. 라즈베리파이는 이더넷 포트가 있어 바로 연결되고 MacBook 에는 USB-C to Ethernet Adapter 를 이용해서 이더넷을 연결할 수 있다.</p><p>USB-C to Ethernet Adapter를 사용할 경우 라즈베리파이로 전원 공급이 안되기 때문에 따로 USB-C 케이블을 연결해서 전원 공급을 해줘야한다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/03/IMG_7703.jpg" class="kg-image" alt="" loading="lazy" width="4026" height="3019"></figure><p>USB-C to Ethernet + Charge Adapter를 사용할 경우 USB-C 전원선을 MacBook 포트에 하나 더 연결하지 않고 어댑터에서 전원을 공급하게 할 수 있다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/03/IMG_7704.jpg" class="kg-image" alt="" loading="lazy" width="4027" height="3020"></figure><p>두 가지 어댑터 중에 자신이 원하는 것을 사용하면 된다. </p><h2 id="macos-%EC%9D%B8%ED%84%B0%EB%84%B7-%EA%B3%B5%EC%9C%A0-%EC%84%A4%EC%A0%95">macOS 인터넷 공유 설정</h2><p>macOS에서 MacBook을 인터넷공유기 모드로 만들어서 다른 주변 기기와 인터넷을 공유할 수 있는 기능을 제공한다.</p><p>macOS 의 System Settings 을 열어서 검색창에 Sharing 이라고 검색하면 Sharing 메뉴가 나타난다. 한국어 버전에서는 "공유"라고 표현될 것이다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/03/Screenshot-2025-03-20-at-4.41.45-PM.png" class="kg-image" alt="" loading="lazy" width="1654" height="1474"></figure><p>우리는 인터넷 공유를 설정하기 위해 Internet Sharing 옆에 i 표시를 클릭한다. Internet Sharing 화면이 나타난다. </p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/03/Screenshot-2025-03-20-at-4.40.39-PM.png" class="kg-image" alt="" loading="lazy" width="1654" height="1474"></figure><p>인터넷을 어떤 연결로 공유할 것인지를 선택한다. Belkin USB-C LAN 을 사용하고 있다면 활성화 시키고 Internet Sharing:On 으로 인터넷 공유를 켠다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/03/Screenshot-2025-03-20-at-4.41.30-PM.png" class="kg-image" alt="" loading="lazy" width="1654" height="1474"></figure><p>인터넷 공유를 활성화시킨 다음 Network 설정 메뉴로 가서 MacBook에서 사용하는 네트워크 서비스를 확인할 수 있다. USB-C LAN 어댑터의 네트워크 상태는 경고등이 들어와 있는 것을 확인할 수 있다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/03/Screenshot-2025-03-20-at-4.54.38-PM.png" class="kg-image" alt="" loading="lazy" width="1654" height="1474"></figure><p>네트워크 목록에 USB-C LAN 어댑터가 보이고 기본 설정은 DHCP로 되어 있어 임의의 IP가 할당된 것을 확인할 수 있다. 지금 상태는 네트워크 설정이 올바르게 되어 있지 않아서 네트워크가 되지 않아 경고등이 들어와 있다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/03/Screenshot-2025-03-20-at-4.54.47-PM.png" class="kg-image" alt="" loading="lazy" width="1654" height="1474"></figure><p>우리는 Raspberry Pi와 같은 네트워크로 구성을 하기 위해, MacBook을 라우터로 사용하기 위해서 네트워크 설정을 다음과 같이 수정한다. IP 주소는 내가 사용하는 임의 네트워크 주소이다. 각자 자신이 사용하는 네트워크 주소 범위를 사용하면 된다.</p><ul><li>IP address : 192.168.9.2 (라즈베리파이와 네트워크는 임의로  192.168.2.x를 사용한다)</li><li>Subnet mask : 255.255.255.0</li></ul><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/03/Screenshot-2025-03-20-at-4.55.58-PM.png" class="kg-image" alt="" loading="lazy" width="1654" height="1474"></figure><p>USB-C LAN 의 설정을 마치면 네트워크 메뉴에서 이더넷 설정에 변경되어 네트워크가 문제 없이 동작하는 것을 확인할 수 있다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/03/Screenshot-2025-03-20-at-4.56.14-PM.png" class="kg-image" alt="" loading="lazy" width="1654" height="1474"></figure><p>MacBook에서 터미널을 열어서 SSH 로 Raspberry Pi 로 접속해보자. 기존에 블로그 글에 따라 진행했다면 라즈베리파이의 IP 주소가 192.168.2.2로 등록되어 있다.  라즈베리파 이더넷 IP 주소 설정에 관한 글은 글에서 소개하고 있으니 참조하면 된다.</p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://blog.sungkwang.me/building-an-ipad-and-raspberry-pi-based-development-environment-3-establishing-a-direct-ethernet-connection-to-raspberry-pi/"><div class="kg-bookmark-content"><div class="kg-bookmark-title">iPad + Raspberry Pi 기반 개발환경 구축 #3. 이더넷을 이용하여 다이렉트 접속하기</div><div class="kg-bookmark-description">인터넷이 되지 않는 곳에서 iPad와 Raspberry Pi가 이더넷을 이용하여 다이렉트 접속하는 방법을 소개한다. iPad에서 라즈베리 파이로 접속해 터미널 환경에서 라즈베리파이 Wi-Fi를 설정하는 방법을 소개한다.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://static.ghost.org/v5.0.0/images/link-icon.svg" alt=""><span class="kg-bookmark-author">송성광 블로그</span><span class="kg-bookmark-publisher">송성광</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/03/IMG_0751.png" alt="" onerror="this.style.display = 'none'"></div></a></figure><p> 다음과 같이 접속한다.</p><pre><code>ssh pi@192.168.2.2</code></pre><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/03/Screenshot-2025-03-20-at-5.01.15-PM.png" class="kg-image" alt="" loading="lazy" width="1910" height="1356"></figure><p>MacBook에서 Raspberry Pi로 성공적으로 접속이 되면 라즈베리파이에서 인터넷 공유를 통해 외부 네트워크에 인터넷이 되는지 확인하기 위해서 다음과 같이 웹 페이지를 요청해보자.</p><pre><code>curl https://blog.sungkwang.me/</code></pre><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/03/Screenshot-2025-03-21-at-4.12.05-PM.png" class="kg-image" alt="" loading="lazy" width="1910" height="1344"></figure><p>이렇게 Raspberry Pi에서 웹 페이지까지 정상적으로 요청된다면 라즈베리파이에서 인터넷을 사용할 수 있는 설정이 완료되었다.</p><p>Raspberry Pi 에서 Wi-Fi 사용할 수 없을 경우 macOS의 인터넷 공유를 통해서 인터넷을 사용할 수 있다. </p> ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[ iPad + Raspberry Pi 기반 개발환경 구축 #3.  이더넷을 이용하여 다이렉트 접속하기 ]]></title>
        <description><![CDATA[ 인터넷이 되지 않는 곳에서 iPad와 Raspberry Pi가 이더넷을 이용하여 다이렉트 접속하는 방법을 소개한다. iPad에서 라즈베리 파이로 접속해 터미널 환경에서 라즈베리파이 Wi-Fi를 설정하는 방법을 소개한다. ]]></description>
        <link>https://blog.sungkwang.me/building-an-ipad-and-raspberry-pi-based-development-environment-3-establishing-a-direct-ethernet-connection-to-raspberry-pi/</link>
        <guid isPermaLink="false">67d7d90df6146c71a6f527f4</guid>
        <category><![CDATA[ Tech ]]></category>
        <dc:creator><![CDATA[ 송성광 ]]></dc:creator>
        <pubDate>금, 21 3월 2025 13:02:54 +0900</pubDate>
        <media:content url="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/03/IMG_0751.png" medium="image"/>
        <content:encoded><![CDATA[ <p>Raspberry Pi는 기본적으로 보드에 Wi-Fi 칩셋이 있어 따로 무선랜 카드나 동글 없이 자체로 무선인터넷을 사용할 수 있다. 무선공유기만 근처에 있다면 Wi-Fi 공유기에 접속해서 인터넷을 할 수 있다. 이 때 SSID 를 확인하고 비밀번호를 입력해서 접속한다. Wi-Fi 접속은 최초 첫번째 접속시 한번 인증이 필요하며 이후 자동으로 접속이 가능하다. 우리가 사용하는 무선 기기들은 대부분 사용자 인터페이스로 화면을 통해 SSID를 확인하고 입력할 수 있다.</p><p>라즈베리파이를 간편하게 사용하기 위해 모니터 없이 설치하는 Raspberry Pi는 wifi에 접속되지 않는한 원격으로 접속을 할 수 없는 문제가 있다. 인증 받지 않는 Wi-Fi 존에 가서 라즈베리파이    무선 네트워크 설정을 하기 어렵게 된다. 이동할때 공용 wifi 같은 것을 사용하기 위해서는 라즈베리파이에 Wi-Fi 없어도 접속할 수 있는 방법이 필요하다. 이런 경우 Raspberry Pi 와 iPad의  Ethenert 환경으로 다이렉트로 접속할 수 있는 방법으로 접속할 수 있다. 이 글에서는 이더넷을 통해 iPad에서 Raspberry Pi로 접속하는 방법을 소개한다.</p><p>모니터 없이 라즈베리파이 설치할 때 (headless 방식) 라즈베리파이 운영체제를 설치하는 과정에서 무선 네트워크 설정하고 운영체제 이미지를 만든다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/03/IMG_0752.png" class="kg-image" alt="" loading="lazy" width="1302" height="1532"></figure><p>설치할 때 설정한 wifi 접속 정보는 다른 Wi-Fi 존으로 가면 사용할 수 없기 때문에 접속할 수 없게 된다. Raspberry Pi 는 Wi-Fi에 접속할 수 없기 때문에 앞서 소개한 내용에서 SSH로 라즈베리파이로 접근을 할 수 없는 문제가 발생한다. 이러한 문제를 해결하기 위해서 이더넷(Ethernet)을 이용하여 라즈베리파에 다이렉트로 접속하는 방법과 Raspberry Pi 에서 Wi-Fi 접속에 필요한 SSID를 등록하는 방법을 소개한다.</p><h2 id="ipad%EC%97%90%EC%84%9C-ethernet-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0">iPad에서 ethernet 사용하기</h2><p>iPad에서 인터넷을 사용하려면 흔히 iPad에 기본 제공하는 Wi-Fi 접속 방법을 사용하거나 셀룰러 모델인 경우 e-sim을 등록해서 사용하는 방법으로 인터넷을 사용한다. iPad 에서는 기본적으로 Ethernet를 사용할 수 있는 기능을 가지고 있다. USB-C 이더넷 어댑터를 iPad에 꽂게 되면 랜선을 이용해서 이더넷을 사용할 수 있다. iPad 기본 구성품에는 포함되어 있지 않지만 아래 그림과 같이 MacBook 에서도 같이 사용할 수 있는 USB-C 이더넷 어댑터를 사용해서 이더넷 연결이 가능하다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/03/IMG_0753-1.jpeg" class="kg-image" alt="" loading="lazy" width="1000" height="277"></figure><p>만약 USB-C 포트를 사용하기 이전의 라이트닝 포트 iPad 모델을 사용한다면 다음과 같이 라이트닝용 이더넷 어댑터를 사용하면 iPad에서이더넷을 사용할 수 있다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/03/IMG_0754.jpeg" class="kg-image" alt="" loading="lazy" width="820" height="461"></figure><h2 id="ipad%EC%99%80-raspberry-pi-%EC%9D%B4%EB%8D%94%EB%84%B7-%EC%97%B0%EA%B2%B0">iPad와 Raspberry Pi 이더넷 연결</h2><p>라즈베이파이는 기본적으로 이더넷 캐이블을 연결할 수 있는 포트를 지원한다. </p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/03/IMG_0758.png" class="kg-image" alt="" loading="lazy" width="843" height="534"></figure><p>이렇게 iPad 와 Raspberry Pi 두 디바이스를 이더넷 케이블을 이용해서 연결하면 두 디바이스 간에 이더넷 네트워크를 만들 수 있고, 각각 네트워크를 통해 접근이 가능하다. </p><p>iPad 에는 Belkin 의 USB-C to Ethernet Adapter를 이해하여 이더넷 케이블을 연결했고, Raspberry Pi 에는 기본적으로 이더넷 포트를 지원해서 이더넷 케이블을 연결할 수 있다. 이 때, iPad에서 라즈베리파이의 전원으로 공급하던 USB-C 케이블 대신에 이더넷 어댑터를 연결해야 한다. 그래서 라즈베리파이에 따로 외부 전원공급 장치로부터 전원을 공급해줘야 한다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/03/IMG_7708-1.jpeg" class="kg-image" alt="" loading="lazy" width="4032" height="3024"></figure><p>라즈베리파이를 사용하려는 목적은 간편한 휴대가 목적인데, 이렇게 이더넷 환경을 구성하면 항상 전원공급장치(전원 어댑터)를 따로 들고 다녀야한다. 이런 문제를 해결하기 위해서는 iPad 의 USB-C포트를 허브기 또는 전원공급을 같이 처리할 수 있는 이더넷 어댑터를 사용해야한다.</p><p>Belkin 의 USB-C to Ethernet + Charge Adapter를 사용하면 iPad에 이더넷 케이블을 연결하는 동시에 iPad에서 Rasbperry Pi로 USB-C를 통한 전원 공급을 함께 할 수 있게 된다. 그래서 따로 전원공급장치를 들고 다니지 않고 이 어댑터 하나만 있으면 간편하게 휴대하는 목적을 이룰 수 있다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/03/IMG_0759.jpeg" class="kg-image" alt="" loading="lazy" width="1000" height="1000"></figure><p>iPad에서 외부장치를 사용하기 위해서는 USB-C포트 하나 밖에 없기 때문에 이런 구성을 할 수 밖에 없다. 동시에 더 많은 커넥션을 처리하기 위해서는 USB-C 포터 허브기를 사용해서 여러가지 외부장치를 동시에 사용할 수 있다. 우리는 간편하게 휴대할 수 있는 리눅스 환경을 목표하고 있기 때문에 가볍고 휴대하기 좋은 크기의 어댑터 하나를 사용하기로 한다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/03/IMG_7709.jpeg" class="kg-image" alt="" loading="lazy" width="4032" height="3024"></figure><h2 id="ipad-%EC%9D%B4%EB%8D%94%EB%84%B7-%EC%84%A4%EC%A0%95">iPad 이더넷 설정</h2><p>iPad에 이더넷 어댑터를 연결하면 설정화면에서 Ethernet 항목이 나타나게 된다. Etherner 메뉴를 눌러 확인하면 iPad에 연결되어 있는 이더넷 어댑터가 보인다. Belkin USB-C to Ethernet Adapater를 사용할 경우 아래 그림과 같이 보이게 되고, USB-C to Ethernet + Charget Adapter 경우에는 또 다른 이름으로 보일 수 있다. 다른 써더파티 이더넷 어댑터를 사용하면 또 다른 이름으로 보일 수 있지만, 설정하는 방법은 모두 같다. </p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/03/IMG_0745.jpeg" class="kg-image" alt="" loading="lazy" width="2420" height="1668"></figure><p>iPad에 연결되어 있는 어댑터 목록을 보고 선택해서 이더넷 설정을 하면 된다. 기본적으로 Configure IP 방식이 Aotomatic으로 되어 있는데, Raspberry Pi 와 이더넷 환경을 만들기 위해서 고정 IP 방식으로 설정을 변경하고 IP Address 와 Subnet Mask 속성에 값을 아래와 같이 입력하고 저장한다. IP Address는  자신이 원하는 네트워크 주소를 지정하면 된다. 이 자료에서는 192.168.2.x 로 저장했지만, 10.0.0.x 또는 123.0.0.x 등 사설망으로 사용하기 때문에 어떤 IP를 지정해도 상관없다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/03/Screenshot-2025-03-20-at-9.34.02-PM.png" class="kg-image" alt="" loading="lazy" width="2420" height="1668"></figure><h2 id="raspberry-pi-%EC%9D%B4%EB%8D%94%EB%84%B7-%EC%84%A4%EC%A0%95">Raspberry Pi 이더넷 설정</h2><p>라즈베리파이 이더넷 설정은 조금 더 복잡하긴 하지만 한번 설정하면 다음 설정부터는 라즈베리파이로 다이렉트로 접속하기 때문에 간편해진다. 소개하는 방법은 라즈베리파이에 모니터를 연결하지 않고 headless 방법으로 설정하는 방법을 소개한다. (만약 라즈베리에 모니터를 연결하고 물리적 키보드와 마우스를 가지고 설치한다면 그렇게 진행해도 된다)</p><p>우선 라즈베리파이에 Wi-Fi 로 접속할 수 있는 공간에서 작업을 해야한다. </p><p>라즈베리파이의 이더넷 설정을 하기 위해서 라즈베리파이에 접속해야하는데, 최초 설치때 Wi-Fi  설정을 한 곳에서 무선 인터넷을 통해 SSH를 이용해서 접하해야하기 때문이다. Blink 앱을 열어서 SSH 로 라즈베리파이로 접속한다.</p><pre><code>ssh pi@raspberrypi</code></pre><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/03/IMG_0761.jpeg" class="kg-image" alt="" loading="lazy" width="2420" height="545"></figure><p>라즈베리파이에 이더넷 케이블이 연결된 상태에서 현재 라즈베리파이의 네트워크 인터페이스 설정이 어떻게 되어 있는지 확인하기 위해서 다음 명령어를 입력해서 확인한다.</p><pre><code class="language- ">ifconfig</code></pre><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/03/IMG_0762.jpeg" class="kg-image" alt="" loading="lazy" width="2420" height="1668"></figure><p>라즈베리파이에서 기본적으로 이더넷 설정은 자동으로 되어 있다. 라즈베리와 iPad가같은 네트워크에 연결하기 위해 이더넷 설정을 iPad와 같은 네트워크 주소 범위로 수정해야한다. 라즈베리파이에서 NetworkManager Terminal UI로 설정하기 위해  다음 명령어를 입력한다.</p><pre><code>sudo nmtui</code></pre><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/03/IMG_0763.png" class="kg-image" alt="" loading="lazy" width="2420" height="1668"></figure><p>Edit a connection을 선택한다. 화면이 전환되면서 Ethernet 과 Wi-Fi 메뉴가 나타난다. Ethernet에 기본적으로 생성된 Wired connection 1 이라고 등록된 프로파일을 선택하고 Edit를 선택한다. 만약 이더넷 프로필이 다른 이름이거나 보이지 않을 경우 Add를 선택해서 이더넷 프로필을 새로 만들고 진행하면 된다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/03/IMG_0766.png" class="kg-image" alt="" loading="lazy" width="2420" height="1668"></figure><p></p><p>Edit Connection 네트워크 프로필 수정창이 나타난다. 이 때 IPv4 CONFIGURATION 항목을 보면 Automatic 으로 되어 있는것을 확인할 수 있다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/03/IMG_0768.jpeg" class="kg-image" alt="" loading="lazy" width="2420" height="1668"></figure><p>IPv4 CONFIGURATION에서 Automatic이 선택되게 이동후 엔터를 치면 다음과 같이 IP를 설정하는 방법이 나오는데 Manual로 선택한다. 그리고 옆에 Show를 선택해서 IP 정보를 입력하면 된다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/03/IMG_0770.jpeg" class="kg-image" alt="" loading="lazy" width="2418" height="771"></figure><p>네트워크 정보는 iPad와 동일한 네트워크로 설정한다. iPad에서 192.168.2.1 로 네트워크를 설정했기 때문에 라즈베리파이 네트워크는 다음과 같이 설정한다.</p><ul><li>Addresses : 192.168.2.2/24</li><li>Gateway : 192.168.2.1</li><li>DNS Severs: 8.8.8.8, 8.8.4.4</li></ul><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/03/IMG_0772.jpeg" class="kg-image" alt="" loading="lazy" width="2420" height="1668"></figure><p>모든 설정을 저장하고 터미널로 돌아가서 네트워크 인터페이스가 제대로 설정되었는지 <code>ifconfig</code> 명령어를 사용해서 확인한다. </p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/03/IMG_0773.jpeg" class="kg-image" alt="" loading="lazy" width="2419" height="1251"></figure><p>네트워크 정보 설정이 제대로 된 것을 확인하면 이제 이더넷 장치가 제대로 동작하도록 내렸다가 올려야 한다. 이 과정 대신에 라즈베리파이를 재부팅해도 되지만 간단하게 이더넷 서비스를 내렸다가 올리면 재부팅 없이 바로 적용이 가능하다.</p><pre><code>sudo ifconfig eth0 down
sleep 10
sudo ifconfig eth0 up</code></pre><p>이더넷 장치가 내렸다가 올라오면 iPad 기기로 ping을 보내어서 라즈베리파이와 iPad가 서로 네트워크 패킷을 주고 받을 수 있는지 확인한다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/03/IMG_0775.jpeg" class="kg-image" alt="" loading="lazy" width="2420" height="483"></figure><h2 id="ipad-%EC%97%90%EC%84%9C-raspberry-pi%EC%97%90-%EC%9D%B4%EB%8D%94%EB%84%B7%EC%9C%BC%EB%A1%9C-%EC%A0%91%EC%86%8D%ED%95%98%EA%B8%B0">iPad 에서 Raspberry Pi에 이더넷으로 접속하기</h2><p>이제 iPad에서 라즈베리파이의 이더넷 IP로 접속이 가능한지 확인한다. iPad에서 Blink 앱을열어서 SSH로 라즈베리파이 이더넷 IP로 접속해보자</p><pre><code>ssh pi@192.168.2.2</code></pre><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/03/IMG_0776.jpeg" class="kg-image" alt="" loading="lazy" width="2420" height="628"></figure><h2 id="raspberry-pi-%EC%97%90%EC%84%9C-%ED%84%B0%EB%AF%B8%EB%84%90%EB%A1%9C-wi-fi-%EC%84%A4%EC%A0%95%ED%95%98%EA%B8%B0">Raspberry Pi 에서 터미널로 Wi-Fi 설정하기</h2><p>앞의 이더넷 설정으로 이젠 iPad와 라즈베리파이는 인터넷이 없는 공간에서도 서로 네트워크가 가능하다. 만약 Wi-Fi 존에서 라즈베리파이가 Wi-Fi를 사용하게 만들기 위해서는 SSID와 Password를 설정해야한다. 설정하는 방법은 앞에서 이더넷 설정을 하기 위해 사용한 <code>sudo nmtui</code> 명령어를 사용하면 된다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/03/IMG_0779.jpeg" class="kg-image" alt="" loading="lazy" width="2420" height="1668"></figure><h2 id="%EA%B2%B0%EB%A1%A0">결론</h2><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/03/IMG_7709-1.jpeg" class="kg-image" alt="" loading="lazy" width="4032" height="3024"></figure><p>이젠 iPad 와 Raspberry Pi 만 있으면 어디에서도 인터넷을 사용할 수 있게 되었다. Wi-Fi 설정이 필요하면 이데넷으로 접속해서 SSID와 Password를 설정하고 Wi-Fi를 사용할 수 있고, iPad에서 전원까지 공급 가능해서 따로 전원공급 어댑터를 들고 다니지 않아도 된다.</p><h2 id="%EC%B0%B8%EA%B3%A0">참고</h2><p>이 포스팅은 iPad와 Raspberry Pi 두 기기 사이의 네트워크 환경을 소개한 것이다. <strong>이더넷 네트워크를 구성한다고 라즈베리파이에서 Wi-Fi 없이 iPad를 통해서 인터넷을 공유할 수 없음을 주의해야한다. </strong></p><p>MacBook 에서는 <strong>인터넷 공유</strong>라는 기능이 있어 라즈베리파이에서 Wi-Fi 없이 이더넷 네트워크를 통해 MacBook 인터넷 공유를 사용해서 인터넷을 할 수 있지만, iPad에서는 네트워크 공유 기능을 지원하지 않는다. 다시 말해서 Raspberry Pi에서 Wi-Fi 기능을 사용해서 인터넷을 할 수 있으니, Wi-Fi 설정 변경할 때 iPad에서 라즈베리파이로 접속해서 라즈베리파이의 Wi-Fi 설정을 켜고 wlan0 인터페이스르 down/up해서줘 Wi-Fi를 사용할 수 있게 해줘 인터넷을 사용할 수 있다.</p><p>이젠 Wi-Fi 또는 인터넷이 안되는 곳에 가더라도 이젠 iPad에서 Raspberry Pi로 바로 접속해서 VSCode를 실행하고,  Python 이나  Node.js 그리고 와서버와 데이터베이스를 라즈베리파이에서 바로 실행할 수 있거 오프라인 로컬 개발이 가능하게 되었다. </p><p>다음 포스팅에서 MacBook의 인터넷 공유 기능을 통해서 Raspberry Pi 에서 Wi-Fi 없이 인터넷을 사용하는 방법을 소개할 예정이다.</p> ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[ iPad + Raspberry Pi 기반 개발환경 구축 #2.  iPad에서 VSCode 사용하기 ]]></title>
        <description><![CDATA[ iPad에서 VSCode를 이용하여 개발할 수 있는 환경을 구축한 사례를 소개한다. iPad 자체에 VSCode를 설치할 수  없기 때문에 Raspberry Pi를 이용하여 개발환경을 구축하고 iPad에서 VSCode Remote Server 기능을 사용하여 리눅스 환경으로 개발할 수 있다. ]]></description>
        <link>https://blog.sungkwang.me/building-an-ipad-and-raspberry-pi-based-development-environment-2-utilizing-vscode-for-development-on-ipad/</link>
        <guid isPermaLink="false">67d7bf4df6146c71a6f527b9</guid>
        <category><![CDATA[ Tech ]]></category>
        <dc:creator><![CDATA[ 송성광 ]]></dc:creator>
        <pubDate>화, 18 3월 2025 16:10:22 +0900</pubDate>
        <media:content url="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/03/IMG_0740-1.jpeg" medium="image"/>
        <content:encoded><![CDATA[ <p></p><h2 id="%EC%84%9C%EB%A1%A0">서론</h2><p>Raspberry Pi를 개발환경으로 구축하는 하는 가장 큰 목적은 iPad를 개발환경으로 만드는 것이다.  MacBook Pro M4 16인치를 사용하여 연구하고 개발하고 있지만 무게 때문에 쉽게 들고 다닐수 없다. 그래서 iPad Pro 11인치를 이동용 개발 환경으로 만들기 위해 라즈베리파이를 활용한다.</p><p>라즈베리파이 운영체제는 데비안 리눅스 계열이다. 그래서 iPad와 Raspberry Pi를 들고 다닌다면 항상 리눅스 개발환경으로 연구와 개발을 할 수 있게 된다.</p><p>"iPad + 라즈베리파이 기반 개발환경 구축" 첫 번째 글에서 macOS에서 모니터 없이 라즈베리파이를 설치하는 글을 소개했다. 이 글에서 wifi를 설정하여 macOS 와 Raspberry Pi 가 같은 네트워크에 존재하기 때문에 SSH 접속으로 라즈베리파이 운영체제에 접속할 수 있는 것을 확인했다. 이번 글에서는 iPad를 이용하여 Raspberry Pi 에 SSH 로 접속하고 Visual Studio Code Remote 개발 환경을 구축하는 방법을 소개한다.</p><h2 id="ipad-%EC%97%90-raspberry-pi-%EC%97%B0%EA%B2%B0%ED%95%98%EC%97%AC-%EC%A0%84%EC%9B%90-%EA%B3%B5%EA%B8%89">iPad 에 Raspberry Pi 연결하여 전원 공급</h2><p>Raspberry Pi 4는 USB-C 케이블만 있으면 iPad에 연결해서 따로 전원 어댑터 없이 사용 가능하다. 이 부분 때문에 라즈베리파이 4를 선택했다. 단 iPad 전원 포트가 USB-C 타입만 가능하고 라이트닝 포트를 가진 아이패드는 이런 구성을 만들 수 없다. 이 구성만 있으면 아이패드와 라즈베리파이만 가지고 어디서든지 리눅스 개발 환경을 가질 수 있게 된다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/03/IMG_7640.jpeg" class="kg-image" alt="" loading="lazy" width="4027" height="3020"></figure><h2 id="ipad-ssh-%EC%95%B1-blink-shell-%EC%84%A4%EC%B9%98">iPad SSH 앱 Blink Shell 설치</h2><p>iPad에서 SSH를 사용할 때 사용하는 SSH 클라이언트 앱 종류가 많이 있다. 그 중에서 Blink 앱은 VSCode를 내장하고 있고, 원격 서버에 code-server 를 이용하여 VS Code Remote 개발 환경을 사용할 수 있다. </p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/03/Screenshot-2025-03-17-at-7.21.28-PM.png" class="kg-image" alt="" loading="lazy" width="2420" height="1668"></figure><p> Blink 앱을 설치했으면 실행해서 SSH로 Raspberry Pi로 접속해보자. </p><h2 id="blink-%EC%95%B1%EC%9D%98-%ED%98%B8%EC%8A%A4%ED%8A%B8-%EC%84%A4%EC%A0%95">Blink 앱의 호스트 설정</h2><p>우선 무선공유기에 Raspberry Pi의 IP를 확인한다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/03/IMG_7642.jpeg" class="kg-image" alt="" loading="lazy" width="1284" height="2778"></figure><p>라즈베리파이의 IP를 확인했으면 Blank 앱을 열어서 <strong>Settings</strong> 을 연다. 키보드를 사용하고 있으면 <code>cmd + ,</code>  를 사용해서 열수도 있고 Blank 앱의 프롬프트에서 <code>config</code> 를 입력하고 엔터를 친다.</p><p><strong>Settins</strong>가 열리면 <strong>Hosts</strong>를 선택한다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/03/Screenshot-2025-03-17-at-9.27.31-PM.png" class="kg-image" alt="" loading="lazy" width="2420" height="1668"></figure><p>Hosts 설정 화면이 나오면 Add new Host 를 선택해서 공유기에서 확인한 Raspberry Pi의 IP 를 입력한다. IP 부분은 개인마다 다르기 때문에 자신이 라즈베리파이 디바이스의 IP를 등록하도록 한다. HostName에 IP 정보를 넣고 Alias에 호스트 이름 raspberrypi를 입력한다. </p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/03/Screenshot-2025-03-17-at-9.32.55-PM.png" class="kg-image" alt="" loading="lazy" width="2420" height="1668"></figure><p>라즈베리파이를 새로운 호스트로 등록했으면 이제 blink 프롬프트에서 SSH를 사용하여 Raspberry Pi로 접속이 가능하다.</p><pre><code>ssh pi@raspberrypi</code></pre><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/03/Screenshot-2025-03-17-at-9.37.37-PM.png" class="kg-image" alt="" loading="lazy" width="2420" height="1668"></figure><h2 id="blink-%EC%97%90%EC%84%9C-vscode-%EC%97%B4%EA%B8%B0">Blink 에서 VSCode 열기</h2><p>Blink를 사용하는 가장 큰 이유는 Blink에서 VSCode 사용할 수 있기 때문이다. blink 프롬프트에서 <code>code</code> 라고 입력하고 엔터를 치면 VSCode 가 열리게 된다. (데스크탑에서 사용하는 VSCode 같이 보이지만 사실은 오픈소스 VSCode Web 버전인 code-server 이다.)</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/03/Screenshot-2025-03-17-at-10.13.39-PM.png" class="kg-image" alt="" loading="lazy" width="2420" height="1668"></figure><p>Blink 앱 내부에서 VSCode를  사용할 수 있다는 말은 iPad에서 VSCode로 개발이 가능하다는 말이 된다. 지금가지 iPad를 데스크탑 대신해서 사용하려고 해도 IDE툴이 제대로 지원되지 않아서 절대 데스크탑을 대신할 수 없었는데, 이젠 iPad만 있으면 언제 어디서 바로 개발을 할 수 있다. </p><p>실제 Visual Studio Code 프로젝트에서 Windows, macOS, Linux 용으로 VSCode IDE를다운 받을 수 있고, 웹 버전인 <a href="https://vscode.dev/?ref=blog.sungkwang.me">https://vscode.dev</a> 에 접속해서 웹에서 VSCode를 사용할 수 있다. iPad 에서 웹 브라우저를 열어 VSCode 웹 버전을 통해 개발이 가능하다. 물론 VSCode 웹 버전은 데스크탑의 모든 기능을 사용할 수 없지만 대부분의 기능을 사용할 수 있다.</p><p>Blink에서 <code>code</code> 명령어로 VSCode를 열어서 코딩은 가능하지만 VSCode에서 코드를 실행하거나 터미널을 기능을 사용할 수 없다. 에디터와 터미널 기능을 함께 사용하기 위해서는 code-server를 서버에 설치해서 사용해야한다.</p><h2 id="raspberry-pi%EC%97%90-code-server-%EC%84%A4%EC%B9%98">Raspberry Pi에 code-server 설치</h2><p>라즈베리파이에 code-server를 설치하기 위해서 라즈베리파이에 SSH로 접속해서 실행한다. blink 앱을 열고 blink 프롬프트에서 <code>ssh pi@raspberrypi</code> 로 접속한다.</p><pre><code>ssh pi@raspberrpi</code></pre><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/03/Screenshot-2025-03-18-at-10.37.22-AM.png" class="kg-image" alt="" loading="lazy" width="2420" height="623"></figure><p>code-server는node.js가 필요하다. 프로젝트 개발할 때 node.js를 사용하여 개발을 많이 하고 있는데 이 때 다양한 버전의 node.js가 필요하여 <a href="https://github.com/nvm-sh/nvm?ref=blog.sungkwang.me" rel="noreferrer">nvm</a> 을 설치하고 최신 LTS 버전 node.js를 설치한다.</p><h3 id="nvm-%EC%84%A4%EC%B9%98">nvm 설치</h3><p>nvm 자세한 설치 방법은 공식 문서를 참조해서 설치하면 된다. SSH로 라즈베리파이에 접해한 상태에서 다음 명령어를 실행한다.</p><pre><code>curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.2/install.sh | bash</code></pre><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/03/IMG_0668.jpeg" class="kg-image" alt="" loading="lazy" width="2420" height="665"></figure><p>위 명령어를 입력하고 실행하면 nvm 소스를 받아서 라즈베리파이에 설치한다. 그리고 <code>$HOME/.bashrc</code> 파일안에 다음 내용을 자동으로 저장하게 되는데 파일을 확인해보고 없으면 코드를 추가한다.</p><pre><code>vi $HOME/.bashrc</code></pre><p><code>$HOME/.bashrc</code> 파일에 다음 내용이 하단에 있어야 한다.</p><pre><code class="language-bash">export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] &amp;&amp; \. "$NVM_DIR/nvm.sh"  # This loads nvm
[ -s "$NVM_DIR/bash_completion" ] &amp;&amp; \. "$NVM_DIR/bash_completion"  # This loads nvm bash_completion</code></pre><p>nvm 설치가 완료되면 nvm으로 node.js LTS 버전을 설치한다. 현재 가장 최근의 LTS 버전을 확인해보자. nvm 에서 설치 가능한 node.js의 모든 버전을 확인하는 명령어는 <code>ls-remote</code> 이다.</p><pre><code>nvm ls-remote</code></pre><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/03/Screenshot-2025-03-18-at-11.28.02-AM.png" class="kg-image" alt="" loading="lazy" width="2420" height="819"></figure><p>현재 가장 최근의 LTS버전은 v22.14.0 으로 확인된다. <code>nvm install</code> 명령어를 사용하여 설치한다.</p><pre><code>nvm install 22.14.0</code></pre><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/03/IMG_0679-1.jpeg" class="kg-image" alt="" loading="lazy" width="2419" height="440"></figure><h3 id="code-server-%EC%84%A4%EC%B9%98">code-server 설치</h3><p>VSCode 의 공식 웹 버전은 https://vscode.dev/ 인데, 여기에 사용된 VSCode Server 버전은 오픈소스가 아니라 공개되지 않았다. 대신 code-server 라는 VSCode Server 버전은 오픈소스이다. code-sever를 라즈베리파이에 설치한다.</p><pre><code>curl -fsSL https://code-server.dev/install.sh | sh</code></pre><p>code-server가 설치되면 debian계열 리눅스에서 사용하는 systemctl 을 이용하여 부팅이나 재부팅시 자동으로 code-server 가 실행될 수 있도록 다음 명령어를 입력한다.</p><pre><code>sudo systemctl enable --now code-server@$USER</code></pre><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/03/Screenshot-2025-03-18-at-2.02.19-PM.png" class="kg-image" alt="" loading="lazy" width="2420" height="1153"></figure><h3 id="configyaml-%EC%88%98%EC%A0%95">config.yaml 수정</h3><p>code-server를 설치하면 code-server 설정 파일이 <code>$HOME/.config/code-server/config.yml</code> 경로에 저장된다. 이 파일을 열어서 다음과 같이 수정한다.</p><p>기본 값은 <strong>bind-addr</strong>이 <code>127.0.0.1:8080</code> 으로 되어 있고, <strong>cert</strong>는 <code>true</code>로 되어 있다. bind-addr을 127.0.0.1 에서 0.0.0.0 으로 하는 이유는 로컬호스트가 아니라 iPad 에서 code-server에 요청하기 위해서이다. 그리고 https를 사용할때는 cert를 true로 설해하지만 지금은 https설정은 소개하지 않는다. 이 부분은 따로 정리해서 포스팅을 할 예정이다.</p><pre><code>bind-addr: 0.0.0.0:8080
auth: password
password: abcdefg1234566890
cert: false</code></pre><p>이제 code-server의 모든 설정이 끝났다. config.yaml  수정사항을 적용하기 위해서 다음 명령어로 code-server 재시작 한다.</p><pre><code>sudo systemctl restart code-server@$USER</code></pre><p>iPad에서 웹 브라우저를 실행해서  https://raspberrypi:8080/를 열어보자.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/03/code-server-login.png" class="kg-image" alt="" loading="lazy" width="2420" height="1668"></figure><p>비밀번호는 <code>$HOME/.config/code-server/config.yaml</code> 파일에 있는 <strong>passsword</strong> 항목 값을 입력하면 된다. 비밀번호 인증후 웹에서 동작하는 VSCode를 브라우저에서 확인할 수 있다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/03/httpraspberrypi8080.png" class="kg-image" alt="" loading="lazy" width="2420" height="1668"></figure><p>우리가 데스크탑에서 사용하는 VSCode 테마는 Dark 테마가 기본인데 웹 버전에서는 Lite 버전이 기본이다. Choose your theme에서 Browse Color Themes 버튼을 누르면 테마를 선택할 수 있다. Dark(Visual Studio Dark) 테마를 선택하면 우리가 흔히 보던 VSCode와 같은 컬러테마가 적용된다. </p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/03/httpraspberrypi80801.png" class="kg-image" alt="" loading="lazy" width="2420" height="1668"></figure><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/03/Welcome---code-server.png" class="kg-image" alt="" loading="lazy" width="2420" height="1668"></figure><h2 id="blink-%EC%97%90%EC%84%9C-vscode-remote-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0">Blink 에서 VSCode remote 사용하기</h2><p>위 code-server를 설치한 후 브라우저에서 접속했는데 Blink에 내장되어 있는 VSCode를 사용하여 VSCode remote 환경으로 code-server를 사용할 수 있다.</p><h3 id="ipad%EC%97%90%EC%84%9C-blink-fs%EB%A5%BC-%EC%9D%B4%EC%9A%A9%ED%95%98%EC%97%AC-raspberry-pi%EC%99%80-%ED%8C%8C%EC%9D%BC-%EA%B3%B5%EC%9C%A0">iPad에서 Blink-FS를 이용하여 Raspberry Pi와  파일 공유</h3><p>우선 Blink 프롬프트에서 <code>code</code> 라고 명령어를 실행해서 Blink의 VSCode를 실행한다. Blink의 VSVode 가 실행되면 왼쪽 네비게이션에서 <strong>Extensions</strong> 메뉴를 선택한다. 그리고 <strong>Blink-FS</strong> 라는 VSCode Extension을 설치한다. 이 엑스텐션은 iPad의 <strong>Files</strong> 앱에 Blink 앱을 통해 Raspberry Pi 디바이스에 물리적으로 마운트하여 iPad와 Raspberry Pi 디바이스간 서로 파일을 쉽게 공유할 수 있다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/03/Screenshot-2025-03-18-at-2.39.28-PM.png" class="kg-image" alt="" loading="lazy" width="2420" height="1668"></figure><p>Blink 앱에서 <code>config</code> 명령어를 사용하여 호스트의 설정 창을 열어서 등록해둔 raspberrypi 호스트 설정을 연다. 설정 화면 가장 아래에 보면 <strong>Files.APP</strong> 항목이 있다. <strong>Add Location</strong> 을 선택한다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/03/Screenshot-2025-03-18-at-2.50.42-PM.png" class="kg-image" alt="" loading="lazy" width="2420" height="1668"></figure><p>Files.app 에서 Add Location을 선택하면 rasberrypi 라는 호스트명과 같은 항목이 생기고 ~ 표시가 생기는데 이 항목을 선택하면 상세 화면으로 이동된다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/03/Screenshot-2025-03-18-at-2.51.33-PM.png" class="kg-image" alt="" loading="lazy" width="2420" height="1668"></figure><p>이제 Raspberry Pi에서 공유하고 싶은 디렉토리 경로를 Path에 넣어준다. 나는 pi 의 홈디렉토리 경로를 넣어줬다. 그리고 가장 아래 Validate Connection 을 눌러 정상적으로 커넥션이 문제가 없는지 확인한다. 혹시 커넥션이 문제가 발생하면 경로 또는 사용자 인증 문제가 있으니 호스트 설정의 username 과 password를 다시 확인해본다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/03/Screenshot-2025-03-18-at-2.52.28-PM.png" class="kg-image" alt="" loading="lazy" width="2420" height="1668"></figure><p>이제 iPad의 Files 앱을 열어보면 Blink 항목이 생겨있고, 이 항목을 눌서서 확인하면 Blink-FS설정으로 Raspberry Pi 와 디렉토리가 공유되고 있는 것을 확인할 수 있다. </p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/03/Screenshot-2025-03-18-at-2.55.20-PM.png" class="kg-image" alt="" loading="lazy" width="2420" height="1668"></figure><p>이제 라즈베리파이로 코드 또는 파일을 쉽게 전송해서 VSCode Remote 기능을 사용해서 리눅스 환경에서 코드를 실행할 수 있게 되었다.</p><h3 id="blink-%EC%97%90%EC%84%9C-vscode-server-remote-%EC%82%AC%EA%B0%80%ED%95%98%EA%B8%B0">Blink 에서 VSCode Server remote 사가하기</h3><p>이젠 모든 설정이 끝났다. 마지막으로 Blink에서 VSCode를 실행할 때 우리가 Raspberry Pi에 설치한 code-server를 실행하도록 하겠다. Blink 프롬프트에서 code http://raspberrypi:8080 을 입력하여 실행한다.</p><pre><code>code http://raspberrypi:8080</code></pre><p>우리는 code-server 의 설정파일 config.yaml 파일에서 비밀번호 인증을 사용한다고 정의했기 때문에 비밀번호 항목이 나온다. 이 부분은 이후 https 설정과 함께 비밀번호 인증을 생략하도록 설정하면 된다. config.yaml 에 설정되어 있는 passwor를 입력한다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/03/IMG_0711.png" class="kg-image" alt="" loading="lazy" width="2420" height="1668"></figure><p>비밀번호 인증을 통과하면 Raspberry Pi 의 code-server가 Blink VSCode 에서 동작하는 것을 확인할 수 있다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/03/Screenshot-2025-03-18-at-3.22.33-PM.png" class="kg-image" alt="" loading="lazy" width="2420" height="1668"></figure><h2 id="ipad%EC%99%80-raspberry-pi%EC%9D%98-%ED%8C%8C%EC%9D%BC-%EA%B3%B5%EC%9C%A0-%ED%85%8C%EC%8A%A4%ED%8A%B8">iPad와 Raspberry Pi의 파일 공유 테스트</h2><p>실제 코드를 테스트 해보자.</p><ol><li>iPad 에서 Files 앱으로 Raspberry Pi 디바이스에 Workspces라는 디렉토리를 만든다.</li><li>VSCode 에서 iPad에서 만든 Worspaces 디렉토리로 접근해서 디렉토리 안에 test.js 파일을 만든다.</li><li>VSCode 에서 test.js 파일을 실행해본다.</li></ol><p>먼저 iPad에서 Files앱을 사용하여 Raspberry Pi 디렉토리 안에 Workspaces 디렉토리를 생성한다.  </p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/03/Screenshot-2025-03-18-at-3.26.54-PM.png" class="kg-image" alt="" loading="lazy" width="2420" height="1668"></figure><p>다음은 Blink 프롬프트에서  code https://raspberrypi:8080 으로 VSCode Sever Remote로 라즈베리파이 디바이스 환경에서 VSCode를 연다. </p><p>그리고 iPad 에서 생성한 Workspaces 디렉토리를 연다. VSCode에서  <code>/home/pi/Workspaces</code>  경로의 폴더를 연다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/03/Screenshot-2025-03-18-at-3.35.30-PM.png" class="kg-image" alt="" loading="lazy" width="2420" height="1668"></figure><p>test.js 파일을 열어서 다음 내용을 입력하고 저장한다.</p><pre><code>console.log('Hello Raspberry Pi, VSCode Sever Remote from iPad')
console.log(process.env)</code></pre><p>VSCode 터미널을 열어서 node.js 를 이용하여 코드를 실행한다.</p><pre><code>nvm use 22.14.10
node test.js</code></pre><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/03/Screenshot-2025-03-18-at-3.34.24-PM.png" class="kg-image" alt="" loading="lazy" width="2420" height="1668"></figure><p></p><h2 id=""></h2> ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[ iPad + Raspberry Pi 기반 개발환경 구축 #1. 라즈베리파이 모니터 없이 macOS에서 설치하기 ]]></title>
        <description><![CDATA[ 이 글은 macOS 환경에서 Raspberry Pi 4 디바이스에 Raspberry Pi OS 운영체제를 모니터 없이 설치하는 방법(headless setup)을 소개한다. ]]></description>
        <link>https://blog.sungkwang.me/building-a-raspberry-pi-based-development-environment-1-headless-setup-of-raspberry-pi-4-using-macos/</link>
        <guid isPermaLink="false">67d4d61af6146c71a6f52642</guid>
        <category><![CDATA[ Tech ]]></category>
        <dc:creator><![CDATA[ 송성광 ]]></dc:creator>
        <pubDate>월, 17 3월 2025 15:00:21 +0900</pubDate>
        <media:content url="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/03/Untitled--1--1.png" medium="image"/>
        <content:encoded><![CDATA[ <h2 id="%EC%84%9C%EB%A1%A0">서론</h2><p>라즈베리파이(Raspberry Pi)를 처음 관심을 가지게 된 것은 iPad에서 리눅스 계열 서버를 사용하기 위한 방법을 찾다가 라즈베리파이를 사용하면 장소와 인터넷 환경에 제한없이 사용할 수 있다는 것을 알게 되면서이다. </p><p>이미 국내외 많은 개발자들이 라즈베리파이를 사용해서 개발환경을 구축하고 실제 개발에 사용하는 사례를 개인 블로그를 통해 공유하고 있다. Raspberry Pi에 대한 스펙이나 설명은 구글링으로 쉽게 찾아볼 수 있어 생략한다. 국내 자료는 대부분 윈도우 환경으로 되어 있어 애플 환경에서 자료는 부족해서 내가 사용하고 있는 방법을 라즈베리파이 관련 시리즈 글로 블로그를 통해 공유하려고 한다. </p><h2 id="raspberry-pi-4">Raspberry Pi 4</h2><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/03/IMG_0648.jpeg" class="kg-image" alt="" loading="lazy" width="2420" height="1133"></figure><p>우선 내가 선택한 라즈베이파이 디바이스는 Raspberry Pi 4 이다. 현재는 물리적인 성능이 더 좋은 Raspberry Pi 5 디바이스도 출시 되었다. 하지만  Pi 5 부터는 물리적인 성능이 좋아진만큼 더 많은 전압이 필요해서 전용 어댑터가 필요하고  발열이 심해졌기 때문에 쿨러가 반드시 필요하게 되었다. 라즈베리파이를 개발용 환경으로 이유는 iPad + Raspberry Pi 이렇게 가볍게 항상 들고 다니고 싶어서인데 부피가 큰 전원어댑터와 쿨러가 든 케이스까지 들고 다니고 싶지 않아서 Raspberry Pi 4를 선택했다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/03/IMG_0647.png" class="kg-image" alt="" loading="lazy" width="1141" height="680"></figure><p>라즈베리파이 4에서는 따로 전원 어댑터 필요 없이 MacBook이나 iPad에서 USB-C 선으로 전원공급을 할 수 있다. Pi 4 에서도 발열을 잡기 위해서 쿨러를 사용하기도 하는데 나는 그냥 라즈베일파이 구매할 때 주는 냉각판만 가지고 사용하고 있다.</p><h2 id="raspberry-pi-os">Raspberry Pi OS</h2><p>라즈베리파이 운영체제 Raspberry Pi OS는 이전에 Raspbian 이라고도 불렸는데 리눅스 데비안(Debian)을 가지고 만들어진 운영체제이다. 그래서 데비안 리눅스와 명령어가 같아서 데비안 계열(또는 Ubuntu) 운영체제를 사용한적이 있다면 아주 익숙한 환경으로 사용할 수 있다. </p><h2 id="raspberry-pi-imager%EB%A5%BC-%EC%9D%B4%EC%9A%A9%ED%95%98%EC%97%AC-os-%EC%84%A4%EC%B9%98">Raspberry Pi Imager를 이용하여 OS 설치</h2><p>라즈베리파이 운영체제를 설치하는 방법은 공식사이트에서 <a href="https://www.raspberrypi.com/software/?ref=blog.sungkwang.me" rel="noreferrer">Raspberry Pi Imager</a>를 다운받아서 설치 하는 것이다. Windows 또는 Ubuntu 운영체제에서도 Rasberry Pi Imager를 설치해서 라즈베리파이 운영체제를 설치할 수 있다. 맥 사용자는 다운받으면 다음과 같이 macOS 용 받아서 Applications 디렉토리로 넣어주면 된다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/03/Screenshot-2025-03-03-at-10.03.11-AM.png" class="kg-image" alt="" loading="lazy" width="1544" height="1068"></figure><p>라즈베리파이에서 운영체제를 설치 또는 동작하는 방식은 MacBook 이나 Windows PC 에서 micro SD 카드 USB 메모리 카드에 라즈베리파이 운영체제를 이미지로 만들어 설치한 다음 그 저장소를 Raspberry Pi 에 삽입해서 부팅하면 라즈베리파이 운영체제를 사용할 수 있게 되는 방식이다. 그래서 Rasberry Pi OS를 설치할 때 사전에 필요한 것이 Raspberry Pi와 micro SD 또는 USB 메모리 카드가 필요하다. 이 글에서는 micro SD 카드를 가지고 진행하다.</p><p>micro SD 카드를 MacBook 에 연결한다. 최신 MacBook Pro 모델에는 SD 카드 슬롯이 있어서 SD 카드 어댑터를 사용하면 되고, USB-C 포트만 있는 경우는 SD 카드 리더기나 micro SD 카드 리더기 젠더를 사용해서 연결한다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/03/summary-how-to-find-sd-card-on-mac.jpg-copy.png" class="kg-image" alt="" loading="lazy" width="1190" height="454"></figure><p>다운받은 Raspberry Pi Imager를 실행시키면 다음과 같은 화면이 나타난다. 화면에는 3가지 버튼이 있는데 각각 라즈베리파이 디바이스에 운영체제를 설치하는 옵션이다.</p><ul><li>Raspberry Pi Device : 라즈베리파이 운영체제를 설치할 물리적인 디바이스 모델을 선택한다. </li><li>Operation System : 라즈베리파이에 설치할 운영체제를 선택한다. Raspberry Pi OS, Unbuntu, Booter 등 다양한 운영체제와 설치할 소프트웨어를 보여주고 선택할 수 있다.</li><li>Storage : 라즈베리파이 운영체제(또는 소프트웨어)를 설치할 물리적인 저장소를 선택한다. 기본적으로 micro SD 카드를 사용하지만 이 글을 작성하는 시점에서는 USB 부팅이 지원되어 USB를 사용해서 설치할 수 있다.  </li></ul><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/03/Screenshot-2025-03-03-at-10.03.24-AM.png" class="kg-image" alt="" loading="lazy" width="1584" height="1180"></figure><p>우선 Raspberry Pi Device를 클릭하면 현재 라즈베리파이에서 공식적으로 지원하는 디바이스 목록이 보여진다. 여러가지 모델 중에 Raspberry Pi 4 모델을 선택한다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/03/Screenshot-2025-03-17-at-9.51.19-AM.png" class="kg-image" alt="" loading="lazy" width="1584" height="1180"></figure><p>다음 Operating System 에서 Raspberry Pi OS  (64-BIT) 를 선택한다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/03/Screenshot-2025-03-03-at-10.12.44-AM.png" class="kg-image" alt="" loading="lazy" width="1584" height="1180"></figure><p>Storeage를 클릭해서 현재 MacBook 에 연결된 micro SD 카드를 선택한다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/03/Screenshot-2025-03-03-at-10.26.11-AM.png" class="kg-image" alt="" loading="lazy" width="1584" height="1180"></figure><h3 id="os-customization">OS Customization</h3><p>앞의 단계가 끝나면 바로 이미지를 micro SD 카드에 저장하게 되는데 모니터 없이 Raspberry Pi에 OS 설치하려면 라즈베리파이가 사용할 wifi를 설정을 Raspberry Pi Imager 에서 진행해야한다. </p><p>만약 위 단계가 끝나고 설치하기 전에 다음과 같은 화면이 나오지 않으면 macOS 에서는 단축키로 열수 있다. <code>Shift + control + x</code> 키를 누려면 다음과 같이 사용자 설정 화면이 나타난다. 설치되는 OS에 미리 설정할 수 있는 화면인데 wifi 설정을 미리 해야 이후에 Raspberry Pi를 연결해서 모니터 없이 wifi로 잡은 IP 주소로 SSH로 접속할 수 있다.</p><p>라즈베리파이의 기본 호스트명은 raspberrypi이 된다. 라즈베리파이 설치 후 같은 네트워크 상에서 라즈베리파이 디바이스를 찾기 위해서는 ip 정보를 알지 못해도 raspberrypi 호스트명으로 찾을 수 있게 된다.</p><p>라즈베리파이 운영체제의 기본 username 은 pi 가 되고 password 는 raspberry가 된다. 개인 네트워크에서는 기본 설정 그대로 사용해도 문제없지만 공용 네트워크에서 사용할 때는 비밀번호를 수정해야 보안상 문제가 없다.</p><p>Configure wireless LAN 무선공유기 SSID와 비밀번호를 입력후 Wireless LAN country가 있는데 한국이라고 KR 을 설정하면 인터넷 연결이 안된다는 글들이 있어서 GB 기본 설정 그대로 둔다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/03/Screenshot-2025-03-03-at-10.10.32-PM.png" class="kg-image" alt="" loading="lazy" width="1302" height="1532"></figure><p>이제 Raspberry Pi OS 운영체제 이미지를 만드는 모든 설정이 끝났다. 설치를 진행하면 이비지 Verify를 진행후 저장소에 이미지를 저장한다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/03/Screenshot-2025-03-03-at-10.48.04-AM.png" class="kg-image" alt="" loading="lazy" width="1584" height="1180"></figure><p>운영체제 이미지가 저장소에 정상적으로 저장되면 다음과 같이 성공적으로 젖아되었다는 메세지가 출력된다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/03/Screenshot-2025-03-03-at-10.54.45-AM.png" class="kg-image" alt="" loading="lazy" width="1584" height="1180"></figure><p>이제 Raspberry Pi 에 저장된 micro SD 카드를 삽입한다. micro SD 포트는 라즈베리파이 하단에 위치한다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/03/sd-card.png" class="kg-image" alt="" loading="lazy" width="700" height="467"></figure><h2 id="raspberry-pi-%EC%A0%84%EC%9B%90-%EC%97%B0%EA%B2%B0">Raspberry Pi 전원 연결</h2><p>이제 전원을 연결할 차례이다. Raspberry Pi 4를 선택한 이유는 따로 외장 전원 어댑터를 사용하지 않고 USB-C 포트로 바로 연결해서 전원을 공급할 수 있기 때문이다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/03/IMG_7639.JPG" class="kg-image" alt="" loading="lazy" width="4032" height="3024"></figure><p>라즈베리파이에 전원이 공급되면 빨간색 LED 등이 켜지고 초록색 LED 등이 점멸하다 멈춘다. 부팅과정이 끝나면 초록색 점멸등이 멈추게 되는데 이후로 설정한대로 wifi에 접속이 된 상태가 된다. </p><p>공유기에 접속해서 확인하면 Raspberry Pi가 공유기에 접속한 것을 확인할 수 있다. 이 디바이스의 IP 정보를 확인해서 라즈베리파이로 접속하면 된다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/03/IMG_7496-1.PNG" class="kg-image" alt="" loading="lazy" width="1284" height="2778"></figure><p>앞에서 OS Customization 에서 hostname을 raspberrypi로 기본설정대로 설정되어 있다면 네트워크 같은 네트워크 상에서 pi@raspberrypi 와 같이 호스트명으로 접속을 할 수 있다. macOS 에서 터미널을 열어서 ssh로 접속해보자.</p><pre><code>ssh pi@raspberrypi</code></pre><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/03/Screenshot-2025-03-17-at-2.38.42-PM.png" class="kg-image" alt="" loading="lazy" width="1714" height="834"></figure><h2 id="%EA%B2%B0%EB%A1%A0">결론</h2><p>이동식 리눅스 개발 환경 서버가 필요해서 Raspberry Pi 4에 데비안 리눅스 기반 Raspberry Pi OS를 설치했다. 연구개발할 때 Apple MacBook Pro를 사용하고 있어 macOS에서 라즈베리파이를 설치를 진행했다.  Raspberry Pi Imager를 이용하여 micro SD 카드에 라즈베리파이OS 이미지를 저장 후 라즈베리파이 4에 연결했다. 모니터 없이 설치하기 위해서 설지과정에서 OS Customization 설정으로 wifi 연결 설정과 라즈베리파이 운영체제의 계정 설정을 했다. 라즈베리파이에 운영체제 설치를 완료한 후 MacBook에 USB-C로 연결하여 전원을 공급하고 SSH를 이용해서 라즈베이파이 디바이스로 접속하는 것을 테스트 했다.</p><h2 id="%ED%96%A5%ED%9B%84%EC%97%B0%EA%B5%AC">향후연구</h2><ul><li>iPad와 Raspberry Pi 를 이용한 VS Code Remote 개발환경 구축하기</li></ul> ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[ Apple Silicon macOS에서 elasticsearch 설치하기 ]]></title>
        <description><![CDATA[ 연구 내용중 검색관련 실험에 Elasticsearch 사용이 필요하게 되었다. Apple Silicon macOS에서 Homebrew를 이용하여 Elasticsearch를 설치하는 내용을 소개한다. ]]></description>
        <link>https://blog.sungkwang.me/install-elasticsearch-on-apple-silicon-macos/</link>
        <guid isPermaLink="false">679cd9da6704ca6b89f4a365</guid>
        <category><![CDATA[ Tech ]]></category>
        <dc:creator><![CDATA[ 송성광 ]]></dc:creator>
        <pubDate>토, 01 2월 2025 15:51:56 +0900</pubDate>
        <media:content url="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/02/elasticsearch-logo.png" medium="image"/>
        <content:encoded><![CDATA[ <p>연구를 진행하다 Elasticsearch를 사용이 필요해졌다. 지금까지 검색엔진으로 Elasticsearch를 많이 들어왔지만 실제 업무에 직접적으로 사용할 일은 없었는데, 이번 연구내용에서 Elasticsearch를 사용해서 테스트하는 기회가 생겨 앞으로 관련 내용을 포스팅할 것 같다.</p><p>Elasticsearch 소개는 <a href="https://www.elastic.co/kr/elasticsearch?ref=blog.sungkwang.me" rel="noreferrer">공식문서</a>를 참고하는게 가장 좋다.</p><p>Elasticsearch를 MacOS에 설치하는 방법은 여러가지가 있다. 가장 쉽게 빠르게 사용하는 방법은 docker를 이용하는 방법이다. tar를 이용하여 설치할 수 있지만, macOS에서 <a href="https://docs.brew.sh/Taps?ref=blog.sungkwang.me" rel="noreferrer">Homebrew Taps</a>를 사용하여 설치할 수 있다. Homebrew는 macOS용 누락 패키지 관리자이다. Homebrew는 macOS에서 유연하고 손쉽게 소프트웨어 설치를 관리할 관리할 수 있는 방법을 제공하고 있다. Homebrew의 Tap을 이용하여 써드파티 소프트웨어를 추가할 수 있는데 Elastic에서 <a href="https://github.com/elastic/homebrew-tap?ref=blog.sungkwang.me" rel="noreferrer">Elastic Homebrew Taps</a>을 통해 elastic 패키지를 관리할 수 있게 제공하고 있다.</p><p>Homebrew 에서 elasticsearch를 찾아보기 위해서 <code>brew search</code> 명령어로 찾아볼 수 있다.</p><pre><code>brew search elasticsearch-full</code></pre><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/01/Screenshot-2025-01-31-at-11.36.30-PM.png" class="kg-image" alt="" loading="lazy" width="1560" height="426"></figure><p><code>brew tap</code> 명령어로 원하는 tap을 선택할 수 있다.</p><pre><code>brew tap elastic/tap</code></pre><p>이 글을 작성할 때 Elasticsearch 가장 최신버전은 8.17 버전인데 8.17 버전은 공식적으로 Homebrew에서 설치하는 방법을 제공하지 않고 있다. 그래서 우리는 7.17 버전을 <a href="https://www.elastic.co/guide/en/elasticsearch/reference/7.17/brew.html?ref=blog.sungkwang.me" rel="noreferrer">공식문서</a>를 참고하여 설치하도록 한다. </p><pre><code>brew install elastic/tap/elasticsearch-full</code></pre><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/02/Screenshot-2025-02-01-at-3.15.54-PM.png" class="kg-image" alt="" loading="lazy" width="2036" height="1480"></figure><p>Elasticsearch 는 Java를 사용하는데 이미 Java를 설치했다면 설치된 JDK을 사용하고 아닐 경우 번들로 들어있는 JDK를 사용한다. elasticsearch 번들 JDK는 OpenJDK를 사용하는데 기존에 <a href="https://blog.sungkwang.me/setting-up-java-and-konlpy-on-apple-silicon-macbook-pro/" rel="noreferrer">macOS에 Oracle Java를 설치</a>했기 때문에 Oracle JDK를 사용한다. 다음 명령어를 이용하여 Elasticsearch를 실행하면 환경설정과 필요한 모듈을  로드하는 것을 볼 수 있다.</p><pre><code>elasticsearch</code></pre><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/02/Screenshot-2025-02-01-at-3.18.00-PM.png" class="kg-image" alt="" loading="lazy" width="2000" height="1155"></figure><p>여러가지 필요한 모듈을 로드하는 과정에서 다음과 같이 에러를 발생하면서 실행되지 않는다.</p><pre><code>org.elasticsearch.bootstrap.StartupException: ElasticsearchException[Failure running machine learning native code. This could be due to running on an unsupported OS or distribution, missing OS libraries, or a problem with the temp directory. To bypass this problem by running Elasticsearch without machine learning functionality set [xpack.ml.enabled: false].]</code></pre><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/02/Screenshot-2025-02-01-at-3.27.10-PM.png" class="kg-image" alt="" loading="lazy" width="2000" height="1298"></figure><p>Elasticsearch는 단순 검색엔진 기능외 여러가지 모듈을 추가해서 다양한 기능을 제공하는데 이 에러는 macOS 운영체제에 사용할 수 없는 라이브러리가 있다고 에러가 발생했다. 문제되는 패키지는 머신러닝 관련 ML 패키지이다. 이 모듈을 사용하여 <a href="https://www.elastic.co/guide/en/elasticsearch/reference/7.17/ml-apis.html?ref=blog.sungkwang.me" rel="noreferrer">elasticsearch ML API</a>를 사용할 수 있다. 이 문제를 해결하는 방법은 macOS에서 ML 확장팩을 사용하지 않도록 하는 것이다.</p><p>Homebrew로 설치된 elasticsearch의 설정 파일은 <code>/opt/homebrew/etc/elasticsearch/elasticsearch.yml</code> 경로에 존재하기 때문에 이 파일을 열어서 <code>xpack.ml.enabled:false</code> 를 추가한다.</p><pre><code>vi /opt/homebrew/etc/elasticsearch/elasticsearch.yml</code></pre><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/02/Screenshot-2025-02-01-at-3.37.35-PM.png" class="kg-image" alt="" loading="lazy" width="2000" height="1298"></figure><p>다시 <code>elasticsearch</code> 명령어를 사용하여 실행하면 ml 패키지외 문제 없이 모든 확장패키지가 로드되고 정상적으로 실행이 된다.</p><p>정상적으로 실행된 것을 확인하기 위해서 다른 터미널을 열어서 <code>curl</code>을 사용하여 확인하거나 브라우저로 바로 확인할 수 있다.</p><pre><code>curl -s http://localhost:9200</code></pre><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/02/Screenshot-2025-02-01-at-3.40.35-PM.png" class="kg-image" alt="" loading="lazy" width="1658" height="982"></figure><p>브라우저에서 확인할 때는 <a href="http://localhost:9200/?ref=blog.sungkwang.me">http://localhost:9200</a> 로 접속하면 된다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/02/Screenshot-2025-02-01-at-3.43.13-PM.png" class="kg-image" alt="" loading="lazy" width="1502" height="1058"></figure><p>하지만 머신러닝 확장 모듈 ML을 비활성화 사용하는 것에 대해 이 기능을 사용할 수 없기 때문에 이 문제를 해결하기 위한 방법을 앞으로 찾아볼 예정이다. </p><p>Elasticsearch를 사용하고자 하는 이유가 Vector 검색 기능을 사용하기 위함이라 ML 비활성화로 벡터검색에 영향이 있는지 확인이 필요하다. 앞으로 Elasticsearch 를 사용해서 연구하면서 관련 내용을 포스팅할 예정인데, 벡터검색과 ML에 대한 기능을 사용해보고 포스팅할 예정이다.</p> ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[ AWS Beanstalk (Node.js 22 on Amazon Linux 2023) + yarn ]]></title>
        <description><![CDATA[ AWS Beanstalk 에서 Node.js 기반 웹서비스를 운영중인데 Node.js 18 LTS 지원 만료에 앞서 22 LTS 로 업그레이드하기 위해 Amazon Linux 에서 Amazon Linux 2023에 Yarn을 설정하는 방법을 소개한다. ]]></description>
        <link>https://blog.sungkwang.me/aws-beanstalk-node-js-22-on-amazon-linux-2023-yarn/</link>
        <guid isPermaLink="false">679098496704ca6b89f4a2f0</guid>
        <category><![CDATA[ Tech ]]></category>
        <dc:creator><![CDATA[ 송성광 ]]></dc:creator>
        <pubDate>수, 22 1월 2025 16:48:19 +0900</pubDate>
        <media:content url="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/01/yarn.png" medium="image"/>
        <content:encoded><![CDATA[ <p>AWS 클라우드 서비스중 Beanastalk를 사용하여 무중단 웹 서비스를 운영중이다. Beanstalk는 로더밸런스를 포함한 웹 서비스에 필요한 서비스들을 완전 관리형으로 제공하고 있어 개발에만 집중할 수 있기 때문에 처음부터 Beanstalk를 이용하여 웹 서비스를 운영하고 있다. 현재 사용하고 있는 Node.js 버전은 LTS 버전 중에 18을 사용하고 있었는데 2025년 상반기에 공식적인 유지보수 지원이 끝나기 때문에 상위 버전 LTS를 사용하여 마이그레이션을 진행해야한다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/01/Screenshot-2025-01-22-at-4.08.18-PM.png" class="kg-image" alt="" loading="lazy" width="1318" height="710"></figure><p>AWS Beanstalk 에서 Node.js 18 버전까지는 기존의 Amazon Linux를 사용하기 때문에 플랫폼 자체를 업그레이드할 필요는 없었는데, Node.js 20 이상 사용하기 위해서는 Amazon Linux 2023 플랫폼을 사용해야한다. Amazon Linux 와 Amazon Linux 2023의 호환성 문제 때문에 그동안 플랫폼 업그레이드를 하지 않았지만, 이젠 더이상 미룰수만 없기 때문에 Amazon Linux 2023 플랫폼에 Node.js 22 환경으로 마이그레이션을 진행하기로 했다.</p><p>지금 운영중인 웹 서비스는 TypeScript 기반으로 yarn 패키지메니저를 사용하고 있다. AWS Code Commit + AWS Code Build + AWS Code Deploy를 모두 파이프로 연결한 AWS Code Pipeline 을 사용하여 소스관리, 빌드와 자동 배포까지 자동화시켜 운영하고 있다.</p><p>AWS Beanstalk 에서 yarn 을 사용하여 패키지를 자동으로 설치하는 설정을 소개한다. Amazon Linux 에서는 corepack 이라는 것이 설치되어 있기 때문에 기존에는 yarn 을 사용하여 패키지를 설치하기 위해서 corepack enable 만 .platform 에 추가해서 자동설치를 진행했다. 하지만 Amazon Linux 2023에서는 corepack이라는 것이 설치되어 있지 않기 때문에 설치하는 환경을 추가해야 한다.</p><p>AWS Beanstalk를 플랫폼 설정을 위해서는 프로젝트 루트 디렉토리에 <code>.platform</code> 디렉토리를 만들어서 필요한 hooks 디렉토리를 만들어서 이벤트가 발생할 때 스크립트를 자동 실행하게 만들 수 있다. AWS Beanstalk에서 인스턴스의 워크플로우는 다음과 같다.  자세한 설명은 <a href="https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/platforms-linux-extend.workflow.html?ref=blog.sungkwang.me" rel="noreferrer">Instance deployment workflow </a>글을 참조하면 된다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/01/platforms-linux-extend-order.png" class="kg-image" alt="" loading="lazy" width="566" height="1175"></figure><p>우리는 yarn을 사용하기 위해서 인스턴스가 빌드되기 전에 corepack을 설치하는 처리를 추가하려고 한다. 2가지 스크립트를 추가할 것이다. 하나는 npm 설치를 예방하기 위한 스크립트와 다른 하나는 corepack을 설치하는 스크립트 이다.</p><h3 id="config-hook-%EC%97%90-npm-%EC%84%A4%EC%B9%98-%EC%B0%A8%EB%8B%A8%ED%95%98%EA%B8%B0">config hook 에 npm 설치 차단하기</h3><p> <code>.platform/confighooks/prebuild/01_prevent-npm.sh</code> 파일에 다음 내용을 저장한다. npm 프로젝트에서 node_modules 라는 디렉토리가 있으면 npm install 실행을 하지 않기 때문에 디렉토리를 만들어둔다.</p><pre><code class="language-`">#!/bin/bash
mkdir node_modules</code></pre><h3 id="config-hook-%EC%97%90-corepack-%EC%84%A4%EC%B9%98%ED%95%98%EA%B8%B0">config hook 에 corepack 설치하기</h3><p><code>.platform/confighooks/prebuild/02_corepack.sh</code> 파일에 다음 내용을 저장한다.</p><pre><code>#!/bin/bash
npm i -g corepack</code></pre><h3 id="config-hook-%EC%97%90-yarn-%EC%9D%84-%EC%9D%B4%EC%9A%A9%ED%95%B4%EC%84%9C-%ED%8C%A8%ED%82%A4%EC%A7%80%EB%A5%BC-%EC%84%A4%EC%B9%98%ED%95%98%EA%B8%B0">config hook 에 yarn 을 이용해서 패키지를 설치하기</h3><p><code>.platform/confighooks/predploy/01_yarn.sh</code> 파일에 다음 내용을 저장한다.</p><pre><code>#!/bin/bash

corepack yarn</code></pre><p>config hook에 관한 플랫폼 스크립트를 추가하면 이젠 hook 스크립트를 추가한다. hooks에 들어갈 내용은 config hook 의 내용과 같다. 앞서 만든 파일을 hook으로 복사한다.</p><h3 id="hook-%EC%97%90-npm-%EC%84%A4%EC%B9%98-%EC%B0%A8%EB%8B%A8%ED%95%98%EA%B8%B0">hook 에 npm 설치 차단하기</h3><p><code>cp .platform/confighooks/prebuild/01_prevent-npm.sh .platform/hooks/prebuild/01_prevent-npm.sh</code> </p><h3 id="hook-%EC%97%90-corepack-%EC%84%A4%EC%B9%98%ED%95%98%EA%B8%B0">hook 에 corepack 설치하기</h3><p><code>cp .platform/confighooks/prebuild/02_corepack.sh .platform/confighooks/hooks/02_corepack.sh</code></p><h3 id="hook-%EC%97%90-yarn-%EC%9D%84-%EC%9D%B4%EC%9A%A9%ED%95%98%EC%97%AC-%ED%8C%A8%ED%82%A4%EC%A7%80-%EC%84%A4%EC%B9%98%ED%95%98%EA%B8%B0">hook 에 yarn 을 이용하여 패키지 설치하기</h3><p><code>cp .platform/confighooks/predeploy/01_yarn.sh .platform/hooks/predeploy/01_yarn.sh</code></p><p>이렇게 <code>.platform</code> 설정 디렉토리 안에 <code>confighooks</code> 과 <code>hooks</code> 디렉토리가 있게 되고 각각 <code>prebuild</code>, <code>redeploy</code> 디렉토리가 그 아래 있게 되고 스크립트 파일들이 존재하게 된다. <code>.platform</code> 디렉토리는 프로젝트 루트 디렉토리에 있고 이 디렉토리의 파일 구조는 아래 그림과 같다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/01/Screenshot-2025-01-22-at-4.43.18-PM.png" class="kg-image" alt="" loading="lazy" width="612" height="634"></figure><p>이제 AWS Code Pipeline 을 이용해서 소스코드를 빌드, 배포하면 자동으로 AWS Beanstalk (Node.js 22 on Amazon Linux 2023) 플랫폼에 웹 프로젝트가 배포되면서 yarn을 이용하여 자동으로 패키지를 설치하게 된다. </p> ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[ MacBook Pro M4 애플실리콘 Java 설치, KoNLPy 사용하기 ]]></title>
        <description><![CDATA[ Apple Silicon MacBook 모델에서 한글 자연어 처리를 위해 KoNLPy를 사용하려면 Java 환경이 필요하다. Apple Silicon MacBook에서 Java를 설치하고 KoNLPy를 간단히 사용하는 방법을 소개한다. ]]></description>
        <link>https://blog.sungkwang.me/setting-up-java-and-konlpy-on-apple-silicon-macbook-pro/</link>
        <guid isPermaLink="false">678f277e6704ca6b89f4a261</guid>
        <category><![CDATA[ Tech ]]></category>
        <dc:creator><![CDATA[ 송성광 ]]></dc:creator>
        <pubDate>화, 21 1월 2025 14:44:27 +0900</pubDate>
        <media:content url="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/01/img.png" medium="image"/>
        <content:encoded><![CDATA[ <blockquote>MacOS 에 원래 Java가 설치 되어 있지 않았던가?</blockquote><p>연구소에서 인공지능 관련 프로젝트를 진행하면서 기존의 Intel 기반의 MacBook Pro 16인치 모델에서 Apple silicon  기반 MacBook Pro M4 MAX 16인치 모델을 새로 구입했다.</p><p>MacBook Pro M4 Max 모델에서 한글 문장 분석을 위해서 KoNLP 실행하여 다음과 같은 에러가 발생했다. </p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/01/Screenshot-2025-01-21-at-1.44.37-PM.png" class="kg-image" alt="" loading="lazy" width="2490" height="552"></figure><p>KoNLP 는 Java 환경이 필요한데 MacOS은 Java가 기본적으로 설치 되어 있지 않다.</p><h2 id="homebrew%EB%A5%BC-%EC%9D%B4%EC%9A%A9%ED%95%98%EC%97%AC-java-%EC%84%A4%EC%B9%98">Homebrew를 이용하여 Java 설치</h2><p>Homebrew를 사용하면 쉽게 Java를 설치할 수 있다. brew로 설치하는 Java는 OpenJDK 이다. </p><pre><code>brew install java</code></pre><p>Homebrew의 Java 정보를 확인하기 위해서 brew info 명령어를 사용한다.</p><pre><code>brew info java</code></pre><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/01/Screenshot-2025-01-21-at-2.08.51-PM.png" class="kg-image" alt="" loading="lazy" width="2050" height="1412"></figure><p>이 글을 작성할 때 brew 로 설치하는 OpenJDK의 버전은 23이다. 만약 zsh 이 실행될 때 자동으로 Java PATH를 설정하기 위해서는 ~/.zshrc 파일에 brew로 설치된 Java의 경로를 추가한다.</p><pre><code>export PATH="/opt/homebrew/opt/openjdk/bin:$PATH"</code></pre><p>Java가 잘 설치되었다면 java --version 명령어를 입력해서 설치된 Java 버전을 확인할 수 있다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/01/Screenshot-2025-01-21-at-2.13.50-PM.png" class="kg-image" alt="" loading="lazy" width="1574" height="460"></figure><h2 id="oracle-jdk-%EC%84%A4%EC%B9%98">Oracle JDK 설치</h2><p>OpenJDK가 아닌 Oracle Java SE를 설치하기 위해서는 Oracle 사이트에서 설치 파일을 다운받아 설치하면 된다. 우선 현재 가장 최근의 LTS 버전은 JDK21 이다. 2028년까지  Premier Support를 지원하니 가장 안정화된 버전으로 오래 사용할 수 있을것 같다. 다음 LTS는 2025년 9월 JDK25 버전이 LTS로 받을 수 있지만 이 글을 작성하는 시점에서는 21버전을 선택했다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/01/Screenshot-2025-01-21-at-2.15.30-PM.png" class="kg-image" alt="" loading="lazy" width="2000" height="597"></figure><p>다음 링크를 클릭하면 JDK21 MacOS 용 설치파일 .dmg 파일을 다운 받을 수 있다. 이 때 주의할 점은 MacBook Pro M4 MAX는 Apple Silicon 으로 ARM64 버전을 다운 받아야 한다. Intel 용은 x64 버전을 다운받으면 된다.</p><p><a href="https://www.oracle.com/kr/java/technologies/downloads/?ref=blog.sungkwang.me#jdk21-mac">https://www.oracle.com/kr/java/technologies/downloads/#jdk21-mac</a></p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/01/Screenshot-2025-01-21-at-1.42.42-PM.png" class="kg-image" alt="" loading="lazy" width="2000" height="1352"></figure><p>ARM64 DMG Installer 파일을 다운받아서 간단하게 설치하면 된다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/01/Screenshot-2025-01-21-at-1.44.58-PM.png" class="kg-image" alt="" loading="lazy" width="1144" height="776"></figure><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/01/Screenshot-2025-01-21-at-1.45.03-PM.png" class="kg-image" alt="" loading="lazy" width="1464" height="1112"></figure><p>DMG 설치 파일은 따로 환경변수 설정할 것도 없이 그냥 인스톨러 순서대로 설치하면 된다. 인스톨러 설치가 끝난 후 터미널을 열어서 Java가 잘 설치 되었는지 확인해보자.</p><pre><code>java --version</code></pre><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/01/Screenshot-2025-01-21-at-1.45.49-PM.png" class="kg-image" alt="" loading="lazy" width="1518" height="460"></figure><p>Java 21 LTS 버전이 설치된 것을 확인할 수 있다. JAVA_HOME 환경변수를 설정하기 원한다면 다음 경로에 Java가 설치되어 있으니 JAVA_HOME을 다음과 같이 .zshrc 파일에 추가하면 된다.</p><pre><code>export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk-21.jdk/Contents/Home
export PATH="$JAVA_HOME/bin:$PATH"</code></pre><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/01/Screenshot-2025-01-21-at-2.27.16-PM.png" class="kg-image" alt="" loading="lazy" width="1462" height="732"></figure><p>Java를 제대로 설치하면 KoNLPy를 제대로 사용할 수 있다. KoNLPy로 간단히 형태소를 확인해보자.</p><pre><code class="language-python">from konlpy.tag import Okt
okt = Okt()
okt.pos('Java 설치 완료, KoNLPy 사용 가능')</code></pre><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/01/Screenshot-2025-01-21-at-2.33.11-PM.png" class="kg-image" alt="" loading="lazy" width="2238" height="236"></figure> ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[ Scratch 코딩하기 #1. 가입 및 계정 생성 ]]></title>
        <description><![CDATA[ 초등학교 3학년 올라가는 아들과 함께 Scratch 코딩을 시작하기로 했다. HTML5 기술로 만들어진 Scratch는 브라우저만 있으면 어떤 기기에서 쉽게 코딩을 할 수 있다. 앞으로 아들과 코딩하는 글을 기록할 예정이다. Scratch 가입 및 계정 생성하는 방법을 소개한다. ]]></description>
        <link>https://blog.sungkwang.me/signing-up-for-scratch/</link>
        <guid isPermaLink="false">678deda26704ca6b89f4a19d</guid>
        <category><![CDATA[ Tech ]]></category>
        <dc:creator><![CDATA[ 송성광 ]]></dc:creator>
        <pubDate>월, 20 1월 2025 18:30:29 +0900</pubDate>
        <media:content url="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/01/Screenshot-2025-01-20-at-3.30.43-PM.png" medium="image"/>
        <content:encoded><![CDATA[ <blockquote>초등학교 3학년 올라가는 아들과 함께 코딩을 시작하기로 했다. </blockquote><p>요즘은 정말 다양한 코딩 서비스들이 있기 때문에 자신에 맞는 것을 선택해서 코딩을 배우면 되는것 같다. 우리는 Scratch를 선택했다. Scratch(스크래치)는 <a href="https://www.media.mit.edu/projects/scratch/overview/?ref=blog.sungkwang.me" rel="noreferrer">MIT(Massachusetts Institute of Technology) 미디어 랩에서 8세~16세 아이들을 대상으로 만든 교육용, 블록형 프로그래밍 언어이다</a>. 전 세계 유저들이 자신의 아이디어를 Scratch 로 만들어서 공유하고 리믹스하며 프로그래밍을 접하고 있다. 이런 스크래치를 통해서 활동하는 사람들을 스크래처(Scratcher)라고 한다. 2024년 1월 기준으로 공유된 프로젝트가 15,929,322개, 등록된 계정은 100,411,828개 라고 하니 Scratch의 인기는 정말 대단하다.</p><p>참고로 네이버에서도 블록코딩 프로그래밍 플랫폼을 개발했는데 <a href="https://playentry.org/?ref=blog.sungkwang.me" rel="noreferrer">entry</a> 라는 서비스를 이용하여 블록코딩을 할 수 있다.</p><p>Scratch는 따로 프로그램을 설치하지 않아도 HTML5 기술로 만들어져 브라우저만 있으면 어디서든 가능하다. MacOS에 설치형 프로그램도 있어 인터넷이 없는 오프라인에서 개발도 가능하다. 다만 MacOS 에서 설치형 Scratch에서 만든 프로그램을 웹에서 공유하는 것은 불가능하니 자신이 만든 프로젝트를 온라인으로 관리하거나 스크래처들과 커뮤니케이션을 하고 싶을 경우 <a href="https://scratch.mit.edu/?ref=blog.sungkwang.me" rel="noreferrer">Scatch 공식 사이트</a>에서 시작하는 것을 추천한다. </p><p>Scratch 공식 사이트에서 튜토리얼도 제공하고 있지만, 아들과 좀 더 체계적으로 진행하기 위해서 교제를 하나 선택했다. 지금은 워낙 코딩에 대한 인식들이 높고 교과과정에 포함되어 있어 정말 많은 책들이 있으니 아이에게 맞는 책을 선택하면 될 것 같다. 이 책을 선택한 이유는 우리가 송씨라서 송쌤을 선택한 것은 아니고, 초등학교 코딩 교과 선생님이 책을 만들었다고해서 내용을 보니 아이들에게 체계적으로 어렵지 않게 자연스럽게 코딩의 원리를 알 수 있게 해주는것 같아서 선택했다. 어떤 책들은 무조건 따라하면 게임을 만들거나 에니메이션을 만들 수 있는것처럼 진행하는데 이 책과 같이 이론적인 내용도 어렵지 않게 소개해주는 책이 좋은 것 같다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/01/IMG_6208-1.JPG" class="kg-image" alt="" loading="lazy" width="2000" height="1500"></figure><p>아이에게 노트북을 선물한 것은 아니지만 개인이 관리할 수 있는 MacBook Pro를 줬다. 사실은 2015년형으로 내가 예전에 연구용으로 사용하던 랩탑인데, 이젠 더이상 MacOS를 업데이트할 수 없어 다른 MacBook을 사용하면서 퇴역했다가 다시 전원을 넣어 살렸다. Scratch는 브라우저만 있으면 어떤 기계든 상관이 없다. Scratch는 고성능이 필요하지 않기 때문에 오래된 노트북도 충분히 가능하다. 운영체제 버전도 중요하지 않고 브라우저만 있으면 된다. </p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/01/IMG_0823.JPG" class="kg-image" alt="" loading="lazy" width="2000" height="1333"></figure><p>아주 어렸을 때는 화면도 나오지 않는 노프북을 열어서 아빠 따라하기를 했다면 이젠 자기 컴퓨터가 진짜 생긴것이라 정말 좋아했다.</p><h2 id="scratch-%EC%82%AC%EC%9D%B4%ED%8A%B8%EC%97%90-%EC%A0%91%EC%86%8D">Scratch 사이트에 접속</h2><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://scratch.mit.edu/?ref=blog.sungkwang.me"><div class="kg-bookmark-content"><div class="kg-bookmark-title">Scratch - Imagine, Program, Share</div><div class="kg-bookmark-description">Scratch is a free programming language and online community where you can create your own interactive stories, games, and animations.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://scratch.mit.edu/favicon.ico" alt=""><span class="kg-bookmark-author">Imagine, Program, Share</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://scratch.mit.edu/images/scratch-og.png" alt="" onerror="this.style.display = 'none'"></div></a></figure><p>노트북 언어 설정이나 시스템 위치 설정 때문에 자동으로 영문으로 나오기도하는데 당황하지말고 사이트 가장 밑으로 스크롤해서 내려가서 언어를 한국어로 변경하면 된다. 개인적으로 개발자 원어를 사용하는 것을 좋아하지만 아이와 함께 활동하기 위해서 나도 환경을 한국어로 모두 수정하였다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/01/Screenshot-2025-01-20-at-4.13.02-PM.png" class="kg-image" alt="" loading="lazy" width="2302" height="1678"></figure><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/01/Screenshot-2025-01-20-at-4.16.35-PM.png" class="kg-image" alt="" loading="lazy" width="2248" height="1868"></figure><h2 id="%EA%B3%84%EC%A0%95%EC%83%9D%EC%84%B1">계정생성</h2><p>컴퓨터를 시작한지 얼마 되지 않아 아직 모든게 낯설기 때문에 옆에 꼭 붙어서 하나씩 알려줘야한다. 앞으로 자기가 만든 Scratch 프로그램을 직접 저장도하고 관리도 하기 위해서 공식 사이트에서 계정을 만든다. 계정생성도 어렵지 않기 때문에 스스로 할 수 있게 옆에서 도와준다. </p><h3 id="%EC%9D%B4%EB%A9%94%EC%9D%BC-%EC%A3%BC%EC%86%8C-%ED%95%84%EC%9A%94">이메일 주소 필요 </h3><p>우선 계정을 생성하기 위해서 이메일 주소가 필요하다. 국내 서비스는 개인정보보호 정책 때문에 본인확인을 해야하는데, 아이는 아직 본인확인을 핸드폰과 같은 명의로 할 수 없기 때문에 Apple 에서 자녀 계정을 생성하거나 Google 에서 자녀 계정을 생성하면 된다. 아이에게 MacBook Pro를 주면서 자녀계정을 만들어서 그 때 생성한 애플계정 이메일 주소를 사용했다. Google 계정도 자녀 계정을 만들었는데 부모 인증을 핸드폰이나 이메일로 하기 때문에 자녀계정을 쉽게 만들 수 있으니 이메일 계정을 만들고 진행하면 된다. </p><h3 id="%EC%82%AC%EC%9A%A9%EC%9E%90-%EC%9D%B4%EB%A6%84-%EB%B0%8F-%EB%B9%84%EB%B0%80%EB%B2%88%ED%98%B8-%EC%83%9D%EC%84%B1">사용자 이름 및 비밀번호 생성</h3><p>이메일 주소가 있으면 사이트 상단에 <a href="https://scratch.mit.edu/join?ref=blog.sungkwang.me" rel="noreferrer">스래치 가입</a> 링크를 클릭 한다. </p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/01/Screenshot-2025-01-20-at-4.15.13-PM.png" class="kg-image" alt="" loading="lazy" width="2222" height="1346"></figure><p>간단하게 사용자 이름과 비밀번호를 입력하고 다음을 클릭하면 된다. Scratch는 개인정보 유출에 대한 경고를 많이 한다. 실명을 사용하지 말라는 가이드를 볼 수 있다. 뿐만 아니라 생일이나 개인정보를 연상하는 내용을 사용하는 것도 추천하지 않는다. 사용자 이름은 전세계에서 유일하게 만들어야하기 때문에 이미 너무도 많은 사용자들이 가입해서 중복되는 이름이 많으니 중복되지 않게 만들어야 한다. 우리는 아들이 좋아하는 우리집 아기펭귄 애칭을 사용했다. </p><h3 id="%EA%B5%AD%EA%B0%80-%EC%84%A0%ED%83%9D">국가 선택</h3><p>이름과 비밀번호 입력후 다음은 국가를 선택하는데 대한민국은 South Korea 라 아니라 Korea, Republic of 로 되어 있으니 대한민국을 선택한다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/01/Screenshot-2025-01-20-at-4.22.33-PM.png" class="kg-image" alt="" loading="lazy" width="2044" height="1346"></figure><h3 id="%EC%83%9D%EB%85%84%EC%9B%94-%EC%84%A0%ED%83%9D">생년월 선택</h3><p>스크래처 활동을 위해서인지는 아직 커뮤니티 활동을 하지 않아서 알 수 없지만 회원 가입시 생년월까지 입력을 받는다. 정보는 비공개로 유지된다고 한다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/01/Screenshot-2025-01-20-at-4.24.00-PM.png" class="kg-image" alt="" loading="lazy" width="2000" height="1286"></figure><h3 id="%EC%84%B1%EB%B3%84-%EC%84%A0%ED%83%9D">성별 선택</h3><p>다양한 국가, 다양한 문화가 세계에 존재하는데 성별 선택도 다양하게 할 수 있다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/01/Screenshot-2025-01-20-at-4.45.34-PM.png" class="kg-image" alt="" loading="lazy" width="2210" height="1382"></figure><h3 id="%EC%9D%B4%EB%A9%94%EC%9D%BC-%EC%A3%BC%EC%86%8C-%EC%9E%85%EB%A0%A5">이메일 주소 입력</h3><p>개인 이메일 주소를 입력하면 된다. 아들은 앞서 가족계정으로 만들어줬던 이메일 주소를 입력해서 진행했다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/01/Screenshot-2025-01-20-at-4.46.46-PM.png" class="kg-image" alt="" loading="lazy" width="2104" height="1348"></figure><p>이메일 주소까지 입력하면 회원 가입이 완료된다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/01/SCR-20250120-ouim.png" class="kg-image" alt="" loading="lazy" width="2140" height="1330"></figure><p>회원가입시 입력했던 이메일로 확인 메일이 도착한다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/01/SCR-20250120-ovam.png" class="kg-image" alt="" loading="lazy" width="1548" height="1894"></figure><p>confirm my account 버튼을 클릭하거나 아래 링크를 클릭하면 Scratch 공식사이트가 열리면서 모든 과정이 끝나고 가입이 완료된다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/01/SCR-20250120-ovmk.png" class="kg-image" alt="" loading="lazy" width="2172" height="1229"></figure><p>이제 앞으로 아들과 함께 코딩을 하면 된다.</p> ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[ iPad 셀룰러 eSIM 간편하게 비대면으로 개통하기 (SKT) ]]></title>
        <description><![CDATA[ iPad Pro M4 셀룰러 모델을 구입후 셀룰러 데이터를 사용하려면 eSIM 개통을 해야한다. SKT 통신사 오프라인 매장에 방문하지 않고 비대면으로 간편하게 개통하여 셀룰러 &quot;데이터함께쓰기&quot; 사용하는 방법을 소개한다. ]]></description>
        <link>https://blog.sungkwang.me/activate-an-ipad-cellular-esim-remotely/</link>
        <guid isPermaLink="false">6789ce4fd1e3a00849e507d2</guid>
        <category><![CDATA[ Tech ]]></category>
        <dc:creator><![CDATA[ 송성광 ]]></dc:creator>
        <pubDate>금, 17 1월 2025 19:37:04 +0900</pubDate>
        <media:content url="https://images.unsplash.com/photo-1707388864998-9cafd9b812e8?crop&#x3D;entropy&amp;cs&#x3D;tinysrgb&amp;fit&#x3D;max&amp;fm&#x3D;jpg&amp;ixid&#x3D;M3wxMTc3M3wwfDF8c2VhcmNofDExNHx8YW50ZW5hJTIwaXBhZHxlbnwwfHx8fDE3MzcwODQ0NTN8MA&amp;ixlib&#x3D;rb-4.0.3&amp;q&#x3D;80&amp;w&#x3D;2000" medium="image"/>
        <content:encoded><![CDATA[ <p>연구소에서 서비스 관리와 개발을 위해 언제 어디서나 클라우드에 접속하기 위한 iPad Pro M4를 지원해줬다. <a href="https://blog.sungkwang.me/start-blogging-with-ipad/" rel="noreferrer">블로그를 다시 시작하게된 이유도 iPad 때문이다</a>. iPad 11인치는 크기가 휴대하기 좋아 항상 휴대하기 때문에 조금만 신경쓰면 글을 작성할 수 있는 시간을 만들수 있다.</p><p>국내에서는 wifi가 안되는 곳이 거의 없다. 집, 회사, 학교, 도서관, 카페 등 어딜 가도 wifi를 사용할 수 있다. 심지어 이동하는 버스에서도 wifi를 사용할 수 있으니 데이터걱정없이 어디서나 사용할 수 있어서 iPad 셀룰러 모델을 구입하는 경우는 많지 않을것 같다. 블로그 <a href="https://blog.sungkwang.me/start-blogging-with-ipad/" rel="noreferrer">첫 글</a>에서도 잠시 언급했지만 외국에서는 wifi 를 국내만큼 편하게 사용할 수 있는 환경은 아니다. 국내에서도 특별히 wifi를 사용할 수 없는 경우 데더링을 사용해야하는데 배터리 문제도 있고 몇 가지 이유로 셀룰러 모델을 구입했다.</p><p>iPad에서 셀룰러 데이터를 사용하기 위해서 iPad 에서 사용하는 eSIM을 개통해서 사용하면 된다. 핸드폰 번호 개통하는 것과 같이 번호가 하나 개통되고 데이터 사용료를 내고 사용하면 된다. iPad Pro M4 모델 같은 경우는 우리가 흔히 말하는 USIM 꼽는 곳이 없다. 즉, eSIM 을 사용하는 모델인데 통신사에서 eSIM을 개통하고 다운받아서 사용하는 개념이다. 외국에 여행갈때 신청하는 eSIM 방식과 같다.</p><p>나는 SKT 통신사를 사용하고 있고, LTE Family 요금제를 사용하고 있다. SKT 에서는 "데이터함께쓰기"라는 것이 있는데 이것은 스마트폰 1개의 회선에서 데이터를 다른 기기와 나눠서 사용하는 개념이다. 즉, 하나의 데이터 요금제를 공유해서 무료로 사용이 가능하다.(eSIM 개통비는 첫달 1회 2천원정도 나간다)</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/01/SCR-20250117-ppvh.png" class="kg-image" alt="" loading="lazy" width="2420" height="1668"></figure><p>처음에는 인터넷을 찾아보니 SKT에서 eSIM을 개통 하려면 오프라인 매장에 가서 개통가능하다는 글을 보며 인공지능시대에 이게 무슨말도 안되는... 이라고 생각했지만, 막상 SKT 사이트에서 개통 하려니 정말 안되었다. 정말 어이없고 이상했지만... 바쁜 직장인이라 언제 매장에 방문하고 언제 개통을... 그렇게 몇 달 시간이 지난것 같다. 그렇게 시간이 지나 지금은 전화로 개통을 할 수 있게 되었다.</p><blockquote>지금은 SKT 다이렉트샵 고객센터에 전화하면 전화로 본인 인증 후 30분 내로 개통이 가능하다.</blockquote><p>상담사와 연결후 본인 인증후 iPad 에서 eSIM을 개통하기 위한 정보를 확인하는데, iPad 모델, IMEI, IMID 를 확인해서 상담사가 eSIM을 등록해서 개통한다. 그리고 QR코드를 통해 iPad에서 eSIM을 다운받아서 활성화 한다.</p><p>개통을 신청하기 위해서 전화한 폰으로(본인 회선)으로 신규로 개통할 eSIM 을 다운받는 QR코드 링크를 문자로 받게 된다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/01/SCR-20250117-prkq.png" class="kg-image" alt="" loading="lazy" width="1092" height="1184"></figure><p>링크를 클릭하면 QRCode가 보이는데 iPad를 이용해서 QRCode를 촬영해서 eSIM을 다운받아서 활성화를 진행한다. 이 때, iPad가 wifi에 연결되어 있어야 진행이 된다. </p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/01/SCR-20250117-poat-2.png" class="kg-image" alt="" loading="lazy" width="1284" height="2778"></figure><p>eSIM이 개통되어 설치전까지 iPad 는 wifi 연결없이는 아무것도 할 수 없으니 꼭 wifi를 연결해서 진행해야한다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/01/IMG_6296-1.JPG" class="kg-image" alt="" loading="lazy" width="2048" height="2731"></figure><p>매장에 방문하지 않고 고객센터와 전화로 IMEI, IMID를 확인하기 때문에 고객센터에서 등록할 때 정보를 잘못 들어서 입력하게 되면 eSIM이 제대로 활성화가 되지 않는다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/01/IMG_6297.JPG" class="kg-image" alt="" loading="lazy" width="2048" height="2731"></figure><p>이렇게 eSIM이 제대로 활성화되지 않으면 반드시 다시 고객센터에 전화해서 정보를 확인해서 수정해야한다. 정상적으로 등록이 되어 있다면 이런 화면이 보이지 않고 eSIM이 바로 활성화가 된다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/01/SCR-20250117-qagk.png" class="kg-image" alt="" loading="lazy" width="2420" height="1668"></figure><p>정상적으로 eSIM이 iPad에 등록이 되면 셀룰러 설정이 완료되고 오른쪽 상단에 wifi 안테나가 보이는 부분에 셀룰러 안테나도 같이 보이게 된다. 이제 iPad에서도 wifi 없이 통신사를 이용해서 셀룰러 데이터를 사용할 수 있다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/01/SCR-20250117-qbaw.png" class="kg-image" alt="" loading="lazy" width="2420" height="1668"></figure><p>iPad 정보에 들어가면 네트워크 정보에 SK Telecom 할당된 것을 확인할 수 있고 번호도 할당 받은 것을 확인할 수 있다. 이젠 iPad 네트워크를 테더링으로 사용하기 위해서 iPhone 을 같이 들고다녀야할 이유 한가지는 사라졌다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/01/SCR-20250117-qdbn.png" class="kg-image" alt="" loading="lazy" width="2420" height="1668"></figure><p>이제 진짜 언제 어디서나 바로 사용 가능한 iPad가 되었다. 좀 더 다양한 환경에서 적극적으로 iPad를 사용할 수 있게 되었으니 앞으로 더 잘 활용할 수 있을 것 같다.</p> ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[ 독감으로 잠시 멈춤 ]]></title>
        <description><![CDATA[ 새해 시작이 얼마 되었다고. 올해는 여러 계획을 만들고 잘 지켜가고 있었는데 갑자기 계획에 없던 빨간불이 들어왔다.

처음 시작은 아이가 갑자기 밤에 아빠를 찾았다.

“아빠, 나 어지러워요...”

아이 이마에 손을 얹어보니 심상치 않았다. 체온계를 급하게 찾아서 체온을 확인하니 40도가 넘었다. 시간은 새벽 3시쯤 이었는데 응급실에 가야할지 빨리 결정해야했다. 집에는 이기때 이후로 ]]></description>
        <link>https://blog.sungkwang.me/paused-for-a-while-with-the-flu/</link>
        <guid isPermaLink="false">6788a229d1e3a00849e50774</guid>
        <category><![CDATA[ Story ]]></category>
        <dc:creator><![CDATA[ 송성광 ]]></dc:creator>
        <pubDate>목, 16 1월 2025 18:00:40 +0900</pubDate>
        <media:content url="https://images.unsplash.com/photo-1585207693488-a903901c1274?crop&#x3D;entropy&amp;cs&#x3D;tinysrgb&amp;fit&#x3D;max&amp;fm&#x3D;jpg&amp;ixid&#x3D;M3wxMTc3M3wwfDF8c2VhcmNofDE2fHxmbHV8ZW58MHx8fHwxNzM3MDA3NTM5fDA&amp;ixlib&#x3D;rb-4.0.3&amp;q&#x3D;80&amp;w&#x3D;2000" medium="image"/>
        <content:encoded><![CDATA[ <p>새해 시작이 얼마 되었다고. 올해는 여러 계획을 만들고 잘 지켜가고 있었는데 갑자기 계획에 없던 빨간불이 들어왔다. </p><p>처음 시작은 아이가 갑자기 밤에 아빠를 찾았다.</p><p>“아빠, 나 어지러워요...”</p><p>아이 이마에 손을 얹어보니 심상치 않았다. 체온계를 급하게 찾아서 체온을 확인하니 40도가 넘었다. 시간은 새벽 3시쯤 이었는데 응급실에 가야할지 빨리 결정해야했다. 집에는 이기때 이후로 항상 아세트아미노펜과 이부프로펜 계열 해열제를 상비하고 있어 우선 해열제를 복용시켜보고 열이 떨어지지 않으면 가기로 했다. 먼저 아세트아미노펜을 복용했지만 2시간이 지나도 체온은 계속 고온을 유지하고 있었다. 이 때, 나는 독감인 것을 예감했다. 일반적으로 열이 날때는 1시간 이내로 열이 내리는데 열이 내리지 않았다. 그래서 2시간이 넘어 이부프로펜을 교차로 복용시켰다. 새벽 5시가 넘은 시간에 2차 복용하고 한 시간이 조금 넘으니 체온이 조금 떨어졌다. </p><p>주일 아침이라 소아과 진료가 오전만 가능해서 사람이 많을것 같아 병원 오픈시간 30분전에 아이를 데리고 병원에 서둘러 갔다. 그런데, 병원은 완전히 무슨 전쟁터 같았다. 아이를 업고, 안고 그렇게 대기하는 줄이 얼마나 많은지 병원 복도를 줄지어 엘리베이터 입구까지 쭉 대기를 하고 있었다. 아이가 아프니 발길을 돌릴수도 없고 그렇게 한시간쯤 지나 겨우 진료를 받았다. 독감검사가 진행되었고 바로 A형 독감 확진 결과가 나왔다. 독감은 다행이 코로나와 달라서 독감치료제 수액을 맞으면 빨리 호전된다. 가격은 많이 비싸지만 아이가 너무 아파해서 솔직히 가격 같은건 신경도 쓰지 않는다. 빨리 아이가 열이 내려서 웃는 얼굴을 보고 싶은게 부모 마음이니까.</p><p>마법같이 해열진통제와 독감치료제를 수액 맞고 아이가 컨디션이 바로 좋아졌다. 그렇게 집에 돌아와서 잘 먹고 잘 놀다가... 이런 해열진통제 효과가 사라지니까 다시 고열 때문에 축쳐져있다. 독감치료제를 맞아도 2~3일간은 열과 몸살기운이 계속 있다가 3일 이후로 좋아진다. 그동안은 병원에서 처방해준 증상완화 약을 먹으면서 견뎌야한다.</p><p>그런데 다음날.. 갑자기 내가 몸이 심상치 않다..아들녀석과 같은 증상이다. 병원에 가서 검사하니 나도 A형 독감.. 타미플루 약을 먹으려하다가 회사에 빨리 복귀하기 위해서 나도 수액으로 치료제를 맞았다. </p><p>나는 3일이 지나고 연구소로 마스크를 쓰고 출근했다. 아들녀석은 아직도 기운이 없다며 간간히 낮잠도 자고 좀 더 쉬고 있다. 아마도 이렇게 잠시 멈춤 상태로 일주일은 지나갈것 같다. </p><p></p> ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[ 아들의 컴퓨터 시작 이야기 ]]></title>
        <description><![CDATA[ 컴퓨터를 전공하는 아빠 때문에 어릴적부터 항상 컴퓨터가 있는 환경에서 자란 아들이 이제는 자기 컴퓨터로 자신의 생각을 표현하고 상상을 구체화할 준비가 되었다. ]]></description>
        <link>https://blog.sungkwang.me/my-son-starts-his-computer/</link>
        <guid isPermaLink="false">677f667bd1e3a00849e506e5</guid>
        <category><![CDATA[ Story ]]></category>
        <dc:creator><![CDATA[ 송성광 ]]></dc:creator>
        <pubDate>금, 10 1월 2025 18:00:06 +0900</pubDate>
        <media:content url="https://images.unsplash.com/photo-1603354350317-6f7aaa5911c5?crop&#x3D;entropy&amp;cs&#x3D;tinysrgb&amp;fit&#x3D;max&amp;fm&#x3D;jpg&amp;ixid&#x3D;M3wxMTc3M3wwfDF8c2VhcmNofDN8fGNoaWxkcmVuJTIwY29tcHV0ZXJ8ZW58MHx8fHwxNzM2NDkwMDMzfDA&amp;ixlib&#x3D;rb-4.0.3&amp;q&#x3D;80&amp;w&#x3D;2000" medium="image"/>
        <content:encoded><![CDATA[ <p>아들이 보는 아빠는 어떤 모습 일까?</p><p>아이는 어릴적부터항상 랩탑을 들고 있는 아빠의 모습을 보면서 이 조그만 물건이 무엇인지 궁금했을것 같다. 이 노트북만한 하나의 기계로 세계를 넘어다니면서 자료를 보고 대부분의 일을 할 수 있다는 사실을 아이는 전혀 알 수 없었을것 같다. 요즘 아이들은 스마트폰을 빨리 접하게 되면서 인터넷이라는 것을 이전 세대와 다르게 빨리 알고 있을지도 모른다. 하지만 아직 스마트폰도 없고 매일 아빠가 조금만 화면을 보면서 이리저리 일하는 것을 보면서 아이는 이 물건에 대한 상상을 계속 했을것 같다. </p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/01/IMG_3319.jpg" class="kg-image" alt="" loading="lazy" width="2000" height="2000"></figure><p>아들이 태어나서 처음 일식이 있는 날 달이 태양을 가리는 놀라운 순간을 보여주고 싶었다. 아들은 달이 태양을 가리는 것보다 아빠가 일 하는 사각형 기계에서 태양을 볼 수 있고 일식이 일어나는 마법 같은 순간을 볼 수 있는 것이 더 신비로워 했다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/01/IMG_8437.JPG" class="kg-image" alt="" loading="lazy" width="2000" height="1333"></figure><p>전 세계적으로 코로나 영향으로 약 2년간 재택근무를 하면서 아이든 좀 더 아빠가 하는 일을 밀착해서 볼 수 있었다. 그 시간 아이에게 컴퓨터는 마술상자와 같았을 것이다. 하늘을, 우주를 볼 수 있을뿐만 아니라 뉴스가 나오며, 사람들이 서로 얼굴을 보며 이야기도 하고 예배도 드릴 수 있는 모든 것을 다 할 수 있는 기계라고 생각했다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/01/IMG_0698.jpg" class="kg-image" alt="" loading="lazy" width="2000" height="1500"></figure><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/01/IMG_0110.JPG" class="kg-image" alt="" loading="lazy" width="2000" height="2000"></figure><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/01/IMG_9947.JPG" class="kg-image" alt="" loading="lazy" width="2000" height="1500"></figure><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/01/IMG_9185.jpg" class="kg-image" alt="" loading="lazy" width="2000" height="1500"></figure><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/01/IMG_0919.jpg" class="kg-image" alt="" loading="lazy" width="2000" height="1500"></figure><p>항상 눈에 보이는 곳에 컴퓨터가 있으니 자연스럽게 아이에게 컴퓨터는 좋은 장남감이 되었다. 퇴근하고 돌아오거나 아이가 보이지 않고 조용하면 어김없이 아빠방에 들어가서 아빠 물건을 모두 꺼내어서 상상놀이를 했는데, 빠짐없이 컴퓨터가 등장을 했다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/01/IMG_3535.jpg" class="kg-image" alt="" loading="lazy" width="2000" height="2667"></figure><p>요즘은 초등학교에 코딩 과목이 있다. 초등학교에서 말하는 코딩이라는 것은 어떻게 보면 꼭 컴퓨터가 필요한 것은 아니다. 데이터가 입력되고 처리를 한뒤 결과를 보여주는 일종의 알고리즘 같은 것을 배우는 것인데, 개발자들이 흔히 말하는 코딩과 같이 고수준 프로그래밍 언어로 만드는 것이 아니라 블록을 통해 생각을 순서대로 나열하여 결과를 얻는 방법이다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/01/IMG_6208.JPG" class="kg-image" alt="" loading="lazy" width="2000" height="1500"></figure><p>컴퓨터를 전공하고 있는 아빠가 아들에게 컴퓨터에 대해서 어떻게 얼마나 알려줘야할까 고민을 많이 했다. 앞으로 블록 코딩도 함께 할 계획이지만 가장 중요한 것은 배움이라는 것은 즐거운 일이라는 것을 느끼게 해주고 싶다.</p><p>컴퓨터 시작이 언제부터 시작하면 좋은가? 라는 질문에 꼭 어떤 시기에 시작하는 것이 좋은지 정해진 정답은 없다고 말하고 싶다. 다만 한국어와 영어에 익숙해진 시기면 좋겠다고 생각한다. 자신의 생각을 잘 정리하고 표현할 수 있는 나이에 손글씨 대신에 컴퓨터 인터페이스를 사용해서 컴퓨터를 통해 처리를 할 수 있는 나이에 시작하면 좋을것 같다고 생각했다. 아마 그래서 초등학교 과정중에 코딩과목이 3학년 이상부터 과정에 들어가는 것 같다.</p><p>컴퓨터를 켜고 키보드와 마우스를 사용하는 방법부터 시작한다. 조그만 손으로 네 생각을 잘 표현하고 상상을 구체적으로 만들어내는 그 순간을 위해 아빠가 도와주고 응원해.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2025/01/IMG_6291-1.JPG" class="kg-image" alt="" loading="lazy" width="2000" height="1500"></figure> ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[ 2025. 1. 1 ]]></title>
        <description><![CDATA[ 새로운 달력 첫 장이 시작되는 새해 첫 날이다. 2024년 마지막에 여러가지 사건들이 있어 (사회적으로, 개인적으로) 정신없이 한 해가 마무리된 것 같다. 그래서 올해는 새해 맞을 준비를 제대로 하지 못했다. 매년 한 해를 돌아보는 송별의 시간도 없었고, 새해를 다짐하는 신년의 시간도 없이 시작되었다.

새해의 시작은 평범한 하루와 같이 시작했다. 요즘같은 시기에는 ]]></description>
        <link>https://blog.sungkwang.me/2025-1-1/</link>
        <guid isPermaLink="false">6774f982d1e3a00849e50632</guid>
        <category><![CDATA[ Story ]]></category>
        <dc:creator><![CDATA[ 송성광 ]]></dc:creator>
        <pubDate>수, 01 1월 2025 21:20:28 +0900</pubDate>
        <media:content url="https://images.unsplash.com/photo-1731322903257-04eca2b45852?crop&#x3D;entropy&amp;cs&#x3D;tinysrgb&amp;fit&#x3D;max&amp;fm&#x3D;jpg&amp;ixid&#x3D;M3wxMTc3M3wwfDF8c2VhcmNofDIxMnx8MjAyNXxlbnwwfHx8fDE3MzU3MTkxODZ8MA&amp;ixlib&#x3D;rb-4.0.3&amp;q&#x3D;80&amp;w&#x3D;2000" medium="image"/>
        <content:encoded><![CDATA[ <p>새로운 달력 첫 장이 시작되는 새해 첫 날이다. 2024년 마지막에 여러가지 사건들이 있어 (사회적으로, 개인적으로) 정신없이 한 해가 마무리된 것 같다. 그래서 올해는 새해 맞을 준비를 제대로 하지 못했다. 매년 한 해를 돌아보는 송별의 시간도 없었고, 새해를 다짐하는 신년의 시간도 없이 시작되었다.</p><p>새해의 시작은 평범한 하루와 같이 시작했다. 요즘같은 시기에는 평범한 것이 감사한 일인것다같다. 아내도 아이도 감기 기운 때문에 힘이 없었지만, 새해 첫 식사를 아내가 수고스럽게 떡국을 준비했다. 가족들과 함께 식탁에 앉아 2025년을 위한 기도를 했고 우리는 그렇게 소소하게 새해를 맞이 했다. </p><p>연말에 논문준비로 정말 너무 많이 바빴는다. 새해가 되어도 당분간 계속 논문 준비로 정신없이 지나갈 것 같다. 내가 있는 연구소 역시 여느 직장과 같이 연말과 새해는 바쁜데 새해에 논문을 투고하는 일정이 있기 때문에 유난히 더 바쁜것 같다. 항상 연말이되면 연초에 세운 계획을 이루지 못해서 후회와 반성을 하는데,  2024년은 너무 많은 일들이 있어서 아쉬운 생각이 들지 않는다. 오히려 이렇게 정신없이 한해를 보내버린 것이 다행으로 생각된다. 한가지 아쉬운 것이 있다면 매년 아쉬운 것과 동일하게 아이와 더 많이 시간을 보내지 못한 것 아닐까?</p><p>2025년은 연말에는 한 해를 돌며보면서 후회하고 싶지 않다. 그래서 올해는 꼭 이루고 싶은 일을 기록해서 이루어 갈 것이다.</p><ul><li>논문 투고</li><li>자전거 국토종주 </li><li>해외여행</li></ul><h2 id="%EB%85%BC%EB%AC%B8%ED%88%AC%EA%B3%A0">논문투고</h2><p>부설연구소에서 서비스 개발, 운영, 관리를 하면서 연구를 지속적으로 해왔는데 올해는 결실을마맺을 시간이다. 작년 후반기부터 논문투고에 대한 구체적인 이야기가 나왔고, 길다면 길었던 박사과정도 마침표를 찍을 때가 된 것 같다. 사실 이 번에 연구하는 분야는 내가 지금까지 연구해오던 것과는 많이 다른 방향이라서 실험 자체부터 쉽지는 않지만 업무외 시간에 많은 시간을 들여가며 연구하고 있다. 연구라는 것이 꼭 성과가 잘 나오는 것은 아닌데, 이번에 연구는 논문을 목표로 하고 있기 때문에 꼭 투고를 하고 싶다.</p><h2 id="%EC%9E%90%EC%A0%84%EA%B1%B0-%EA%B5%AD%ED%86%A0%EC%A2%85%EC%A3%BC">자전거 국토종주</h2><p>내 젊음의 로망은 자전거 국토종주인데 결혼과 육아로 이 꿈을 실현하는 시간을 많이 미룰 수 밖에 없었다. 더구나 박사학위를 위해 주말도 시간이 없으니 연차 며칠을 내어 국토종주를 하기 힘들었다. 그러다가 나이가 들어가니 이젠 체력이 허락할까?하는 걱정이 든다. 2024년에는 여러가지 이유로 특히 자전거 탈 시간이 없어서 체력이 많이 내려가 있는 상태이다. 올해는 새해 자전거 국토종주를 목표로 시간이 날 때 체력을 올리고 자전거 마일리지를 많이 쌓아서 꼭 목표를 이루고 싶다. 자전거 국토종주는 시간만 있다고 해낼 수 없기 때문에 훈련하면서 잘 계획을 해야한다. 상반기 논문투고를 마치는대로 구체적인 계획을 세워서 올 해 꼭 이루고 싶다.</p><h2 id="%ED%95%B4%EC%99%B8%EC%97%AC%ED%96%89">해외여행</h2><p>연구소에서 컨퍼런스를 참석하기 위해서 해외에 나갔던 경험말고 가족과 함께 해외여행을 다녀왔던적은 없다. 아내와 아들에게 미국과 유럽에서 경험을 많이 이야기 해줬지만 정작 가족들은 보지고 경험하지도 못해 상상만 할뿐이다.  지금까지는 아이가 어리다는 핑계로 구체적인 계획을 세우지 않았지만, 사실은 가장 큰 이유는 비용 문제가 아니였나 생각된다. 최상의 조건으로 갈 수 없겠지만 지혜롭게 준비해서 가족과 많은 곳을 다녀보고 싶다. </p><p>기록하지 않은 크고 작은 계획들이 지지만 이렇게 구체적으로  기록을 하는 이유는 꼭 지켜내기 위해서다. </p><p>마지막으로 한 가지 더</p><h2 id="%EB%B8%94%EB%A1%9C%EA%B9%85">블로깅</h2><p>2025년에는 블로그를 적극적으로 운영할 계획을 하고 있다. 도메인을 구매하고 클라우드에 서비스 환경을 구축하면서 열의가 있었는데 바쁜이유를 핑계삼아 너무 글을 남기지 못 했다. 블로그를 작성할 때 뭔가 아주 심각하게 정성을 가지고 글을 쓰려고 하니 여러가지 부담이 되었던것 같다. 그래서 2025년에는 좀 더 가볍고 적극적으로 작성하기로 마음을 먹었다. 그래서 1월 1일 첫 글을 이렇게 포스팅한다. 항상 내 전공이나 연구분야에 대해서만 글을 적는 곳이 아니라 내 생각과 추억도 남겨둘 수 있는 그런 공간을 만들고 싶다.</p><p>내 모든 계획이 어쩌면 점점 나이 들어가는 내 모습을 보면서 더 굳은 다짐으로 나온게 아닌가 생각된다. 나이가 들면 여러가지 자신이 없어진다. 하지만 그 속에서 나를 지켜가고 단련하며 삶을 행복하기 살기 위해서는 의지가 반드시 필요하다. 난 그 동기와 의지를 내 글로 동력을 내보려고 한다. </p><blockquote>더 건강하게, 더 열심히, 더 행복하고 더 의미 있게 살아가기 위해서 </blockquote> ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[ Mac OS 에서 PyTorch 사용할 때 NumPy 에러 해결 ]]></title>
        <description><![CDATA[ Mac OS 에서 PyTorch를 사용할 때 NumPy 호환성 문제로 에러를 만났을 때, 호환성에 맞는 버전을 설치해서 해결할 수 있다. ]]></description>
        <link>https://blog.sungkwang.me/troubleshooting-numpy-errors-when-using-pytorch-on-mac-os/</link>
        <guid isPermaLink="false">672048e0d1e3a00849e505dc</guid>
        <category><![CDATA[ Tech ]]></category>
        <dc:creator><![CDATA[ 송성광 ]]></dc:creator>
        <pubDate>화, 29 10월 2024 16:32:51 +0900</pubDate>
        <media:content url="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2024/10/Screenshot-2024-10-29-at-1.03.18-PM.png" medium="image"/>
        <content:encoded><![CDATA[ <p>Huggping Face를 사용하기 위해서 <a href="https://pytorch.org/?ref=blog.sungkwang.me" rel="noreferrer">PyTorch</a>가 필요해서 <strong>MacOS</strong>에서 설치를 해보려했다. 현재 사용중인  우선 <strong>virtualenv</strong> 를 사용하여 테스트할 공간을 만들어서 진행한다.</p><pre><code>virtualenv huggingface</code></pre><p>테스트할 디렉토리가 만들어지면 virtualenv activate로 가상환경을 활성화 한다.</p><pre><code>source ./bin/activate</code></pre><p>PyTorch를 설치한다.</p><pre><code>pip install torch torchvision torchaudio</code></pre><p>가상환경이 활성화되면 Python 인터프리터로 들어가기 위해서 python 을 실행한다.</p><pre><code>python
</code></pre><p>앞에서 설치한 torch가 정상적으로 잘 설치되고 사용 가능한지 알아보기 위해서 다음 코드를 입력한다.</p><pre><code>import torch</code></pre><p>정상적인 실행 결과는 torch를 임포트하고 다음 프롬프트가 나와야 하지만 NumPy 관련 에러가 발생했다.</p><pre><code>A module that was compiled using NumPy 1.x cannot be run in
NumPy 2.1.2 as it may crash. To support both 1.x and 2.x
versions of NumPy, modules must be compiled with NumPy 2.0.
Some module may need to rebuild instead e.g. with 'pybind11&gt;=2.12'.

If you are a user of the module, the easiest solution will be to
downgrade to 'numpy&lt;2' or try to upgrade the affected module.
We expect that some modules will need time to support NumPy 2.</code></pre><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2024/10/Screenshot-2024-10-29-at-11.30.51-AM.png" class="kg-image" alt="" loading="lazy" width="2244" height="1480"></figure><p>이 에러는 NumPy 2.x 버전 보다 낮은 버전이 사용하는데 현재 설치되어 있는 NumPy가 2.1.2가 설치되어 있어 발생하는 에러이다. </p><p>NumPy를 2.0 이하로 다시 설치한다.</p><pre><code>pip install "numpy&lt;2.0"</code></pre><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2024/10/Screenshot-2024-10-29-at-4.26.03-PM.png" class="kg-image" alt="" loading="lazy" width="2244" height="664"></figure><p>NumPy를 호환성에 맞게 2.0 보다 낮은 버전을 설치한 후 다시 python 인터프리터로 들어가서 확인하면 torch를 정상적으로 사용할 수 있는 것을 확인할 수 있다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2024/10/Screenshot-2024-10-29-at-4.27.22-PM.png" class="kg-image" alt="" loading="lazy" width="2244" height="630"></figure> ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[ Amazon Lightsail 에서 Ghost 블로그 운영하기 #4. Amazon S3 연동 외부저장소 설정 ]]></title>
        <description><![CDATA[ Ghost를 운영할 때 Amazon S3를 이용하여 외부 저장소 환경을 만들어 안전하고 유연한 저장소 환경을 설정하는 방법을 소개한다. ]]></description>
        <link>https://blog.sungkwang.me/integrating-ghost-with-s3-to-create-an-external-storage/</link>
        <guid isPermaLink="false">66dbe864d1e3a00849e504c3</guid>
        <category><![CDATA[ AWS ]]></category>
        <dc:creator><![CDATA[ 송성광 ]]></dc:creator>
        <pubDate>화, 10 9월 2024 12:14:30 +0900</pubDate>
        <media:content url="https://images.unsplash.com/photo-1704265586128-7fc54dcc774f?crop&#x3D;entropy&amp;cs&#x3D;tinysrgb&amp;fit&#x3D;max&amp;fm&#x3D;jpg&amp;ixid&#x3D;M3wxMTc3M3wwfDF8c2VhcmNofDI1Nnx8c3RvcmFnZSUyMHMzfGVufDB8fHx8MTcyNTY4ODQ3OHww&amp;ixlib&#x3D;rb-4.0.3&amp;q&#x3D;80&amp;w&#x3D;2000" medium="image"/>
        <content:encoded><![CDATA[ <p>Amazon Ligtsail 을 사용하면 정해진 금액에 정해진 용량을 사용해야한다. 만약 $7 사이즈를 선택해서 서버를 구축했다면 스토리지 공간이 40GB 이다. 운영체제 기본 사이즈가 약 2GB 정도 되니 38GB 정도만 사용할 수 있다. 만약 Ghost에 사진을 올린다면 요즘처럼 고화질 사진을 올리게 될 때, 저장공간은 금방 부족해질 것이다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2024/09/IMG_0491.png" class="kg-image" alt="" loading="lazy" width="2420" height="1668"></figure><p>그래서 저장공간을 확보하기 위해서 파일첨부가 되는 저장공간을 AWS S3를 사용하기로 한다. Ghost 공식 사이트에서 AWS S3 와 Ghost 의 연동에 관련된 내용을 소개하고 있다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2024/09/IMG_0492.jpeg" class="kg-image" alt="" loading="lazy" width="2000" height="664"></figure><p>공식 문서에서는 Amazon S3저장소를 연동하는 2가지 어댑터를 소개한다.</p><ul><li><a href="https://github.com/spanishdict/ghost-s3-compat?ref=blog.sungkwang.me" rel="noreferrer">ghost-s3-compat</a></li><li><a href="https://github.com/colinmeinke/ghost-storage-adapter-s3?ref=blog.sungkwang.me" rel="noreferrer">ghost-storage-adapter-s3</a></li></ul><p>두가지 어댑터 중에 2번째 어댑터를 사용하는 방법을 소개한다. 첫번째 어댑터는 최근 Ghost 에서 연동하는데 adapter 인식을 하지 못하는 이슈가 있기 때문이다.</p><h2 id="amazon-s3-%EB%B2%84%ED%82%B7-%EC%83%9D%EC%84%B1-%EB%B0%8F-%EC%84%A4%EC%A0%95">Amazon S3 버킷 생성 및 설정</h2><p>Amazon S3를 저장소로 사용하려면 Amazon S3 에 접근 가능한 credentials 이 필요하고 S3 버킷이 필요하다. AWS 에 가입을 했고 S3에 접근 가능한 credentials 이 있다고 생각하고 진행하도록 하겠다.</p><p>Amazon S3 에서 Create bucket 버튼을 선택하여 Ghost 저장소로 사용할 새로운 버킷을 만들자. 혹시 기존의 버킷을 그대로 사용해도 상관없다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2024/09/IMG_0496.jpeg" class="kg-image" alt="" loading="lazy" width="2000" height="1379"></figure><p>새로 생성할 버킷 이름은 각자 원하는 이름으로 입력한다. 나는 ghostblog-sungkwang-dev라고 생성할 예정이다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2024/09/IMG_0497.jpeg" class="kg-image" alt="" loading="lazy" width="2000" height="1379"></figure><p>다른 설정은 기본으로 그대로 두고 Block Public Access settings for this bucket 에 대한 설정을 모두 체크하지 않도록 한다. 이렇게 모두 체크하지 않으면 public 으로 접근 가능한 버킷이 된다. Amazon S3 보안에 관해서는 따로 소개할 예정이다. 지금 주제는 Ghost 저장소로 S3를 사용하기 위한 public 접근 가능한 저장소를 만드는데 목적을 둔다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2024/09/IMG_0498.jpeg" class="kg-image" alt="" loading="lazy" width="2000" height="1379"></figure><p>다음은 Object Ownership을 설정하는데 기본값은 ACLs disabled(recommended)로되 설정되어 있다. 이것을 ACLs enabled로 수정한다. 그리고 동의항목에 체크를 한다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2024/09/IMG_0511.jpeg" class="kg-image" alt="" loading="lazy" width="2420" height="1668"></figure><p>다른 설정은 모두 그대로 두고 마지막으로 Create bucket 버튼을 선택한다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2024/09/IMG_0499.jpeg" class="kg-image" alt="" loading="lazy" width="2420" height="1668"></figure><p>Create bucket  버튼을 선택하면 다음과 같이 S3 에 새로운 버킷이 생성된다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2024/09/IMG_0500.jpeg" class="kg-image" alt="" loading="lazy" width="2420" height="1668"></figure><p>이제 S3의 권한을 설정한다. AWS 사용자 credentials을 가지고 접근할 경우 S3 의 모든 액션을 사용할 수 있는 권한을 지정하고, 그 외 GetObject 액션만 허용해서 파일을 읽어가는 권한만 주도록 한다.</p><p>방금 생성한 버킷을 선택하면 Permissions 링크가 보이는데 선택한다. 버킷을 생성할 때 Block access에 관한건 모두 체크를 해지해서 넘어가고 Buket policy 의 Edit를 선택한다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2024/09/IMG_0503.jpeg" class="kg-image" alt="" loading="lazy" width="2420" height="1668"></figure><p>Policy 의 Edit  버튼을 선택하면 에디터가 나오는데 여기에 JSON 타입으로 Policy 를 정의할 수 있다. 오른쪽에 문법을 도와주는 리소스가 있으니 선택해서 하나씩 추가해도 된다. Add new statement 를 선택하면 새로운 statement가 추가된다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2024/09/IMG_0504.jpeg" class="kg-image" alt="" loading="lazy" width="2420" height="1668"></figure><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2024/09/IMG_0505.jpeg" class="kg-image" alt="" loading="lazy" width="2420" height="1668"></figure><p>다음 내용을 참조해서 입력하면 된다.</p><ul><li><strong>Principal</strong>: 접근하는 대상을 선택한다. AWS S3에 접근할 수 있는 credentials을 만들었다면 arn 으로 참조 가능하다. 아래 stmt-1 의 Principal의 AWS 를 참조해서 입력한다.</li><li><strong>Action</strong>: 정의한 리소스의 액션에 대한 범위를 정의한다. 모두 선택할 때는 * 를 사용한다. </li><li><strong>Resource</strong>: 사용할 리소스를 정의한다. arn 으로 S3에 생성한 버킷이름을 지정하는데 아래 코드를 참조해서 입력하면 된다. 새로 생성한 s3 의 버킷은 ghostblog-sungkwang-dev 이고 이를 리소스로 정의할 때는 arn으로 아래와 같이 정의한다.</li></ul><pre><code class="language-JSON">{
    "Version": "2012-10-17",
    "Id": "20240910",
    "Statement": [
        {
            "Sid": "stmt-1",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::1234567890:user/user-ghostblog-sungkwang-dev"
            },
            "Action": "s3:*",
            "Resource": [
                "arn:aws:s3:::ghostblog-sungkwang-dev",
                "arn:aws:s3:::ghostblog-sungkwang-dev/*"
            ]
        },
        {
            "Sid": "stmt-2",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": [
                "arn:aws:s3:::ghostblog-sungkwang-dev",
                "arn:aws:s3:::ghostblog-sungkwang-dev/*"
            ]
        }
    ]
}</code></pre><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2024/09/IMG_0502.jpeg" class="kg-image" alt="" loading="lazy" width="2420" height="1668"></figure><h2 id="ghost%EC%97%90-ghost-storage-adapter-s3-%EC%84%A4%EC%B9%98">Ghost에 ghost-storage-adapter-s3 설치</h2><p>Amazon S3에 버킷을 생성했으면 이제 서버에 접속해서 ghost-storage-adapter-s3를 설치한다. </p><pre><code class="language-`">cd /var/www/ghostblog.sungkwang.me</code></pre><pre><code>npm install ghost-storage-adapter-s3</code></pre><pre><code>sudo mkdir -p ./content/adapters/storage</code></pre><pre><code>sudo cp -r ./node_modules/ghost-storage-adapter-s3 ./content/adapters/storage/s3</code></pre><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2024/09/IMG_0506.jpeg" class="kg-image" alt="" loading="lazy" width="2420" height="551"></figure><h2 id="ghost-%EC%84%A4%EC%A0%95%EC%97%90-s3-%EC%96%B4%EB%8C%91%ED%84%B0-%EC%84%A4%EC%A0%95-%EC%B6%94%EA%B0%80">Ghost 설정에 S3 어댑터 설정 추가</h2><p>Ghost 디렉토리 안에 Ghost 설정을 담당하는 파일은 <code>config.production.json</code> 파일이다. 설정 파일에 S3 어댑터에 대한 내용을 추가한다. 설정파일에 아무런 추가 설정을 하지 않을 경우 S3 어댑터는 storage 속성으로 정의한다. </p><ul><li>accessKeyId와 secretAccessKey는각자의 credentials로 입력하면 된다. </li><li><strong>bucket</strong>: 앞에서 생성한 Ghost 의 저장소가 될 S3 버킷 이름을 입력한다.</li><li><strong>region</strong>: AWS S3를 생성할 때 정의한 지역인데 대한민국은 ap-northeast-2  이다.</li></ul><pre><code>  "storage": {
    "active": "s3",
    "s3": {
      "accessKeyId": "{{AWS IAM credential accessKeyId}}",
      "secretAccessKey": "{{AWS IAM credential secretAccessKey}}",
      "bucket": "ghostblog-sungkwang-dev",
      "region": "ap-northeast-2",
      "forcePathStyle": true
    }
  }</code></pre><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2024/09/IMG_0508.jpeg" class="kg-image" alt="" loading="lazy" width="2000" height="1379"></figure><p>이제 모든 설정이 끝났다 Ghost를 ghost-cli를 이용하여 재시작 한다.</p><pre><code>ghost restart</code></pre><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2024/09/IMG_0509.jpeg" class="kg-image" alt="" loading="lazy" width="2419" height="448"></figure><p>이제 실제 업로드한 파일이 S3 에 저장이 되는지 확인해보자. Ghost 블로그 Dashboard에 로그인해서 글을 작성할 때 이미지를 업로드해보자. Ghost Dashboard 주소는 도메인뒤에 <code>/ghost</code> 를 추가한다.</p><p>https://ghostblog.sungkwang.me/ghost</p><p>처음 관리자 계정을 만들었다면 로그인 후 Dashboard로 바로 접근 가능하고, 만약 블로그 포스팅을 순서를 따라왔다면 관리자 계정을 만들지 않아서 아래와 같이 관리자 계정을 생성하는 화면이 나온다. 정보를 입력하고 가입하면 된다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2024/09/IMG_0510.jpeg" class="kg-image" alt="" loading="lazy" width="2420" height="1448"></figure><p>새로운 Post를 추가하고 사진을 올려보자</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2024/09/IMG_0512.png" class="kg-image" alt="" loading="lazy" width="2420" height="1668"></figure><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2024/09/IMG_0515.png" class="kg-image" alt="" loading="lazy" width="2420" height="1668"></figure><p>사진이 정상적으로 업로드가 된 것을 확인할 수 있다. 사진이 우리가 설정한 Amazon S3에 저장되었는지 AWS Console 에서 확인해보자.</p><p>Ghost 에서 업로드한 사진이 S3 버킷 안에 2024/09/ 패스 안에 만들어진 것을 확인할 수 있다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2024/09/IMG_0516.jpeg" class="kg-image" alt="" loading="lazy" width="2420" height="1668"></figure><p>이번 포스팅에서는 Ghost 의 저장소를 서버 인스턴스가 아닌 Amazon S3를 연동해서 외부에 파일을 저장하는 저장소를 구축하는 방법을 소개했다. Amazon Lightsail은 매달 일정금액에 대해서 제한적인 용량을 사용하기 때문에 용량을 많이 찾이하는 첨부파일 저장소를 S3를 이용해서 외부에 운영하게되면 제한적인 저장소 용량을 안전하게 확장해서 운영할 수 있다. </p><p>다만, 이렇게 운영할 경우 S3의 비용이 추가적으로 발생할 수 있다. 처음 AWS를 시작할때 Free Tier를 가지고 운영할 수 있겠지만 Free Tier 서비스가 만료되면 S3의 과금이 추가적으로 발생할 수 있으니 실제 운영시에는 자신의 운영정책에 맞게 운영해야 한다는 것을 주의하자.</p> ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[ Ghost 태그 수정하기 ]]></title>
        <description><![CDATA[ Ghost 에서 Tag를 수정하는 메뉴가 없어 MySQL 데이터베이스에 접속하여 태그를 수정하는 방법을 소개한다. ]]></description>
        <link>https://blog.sungkwang.me/update-tag-in-the-ghost/</link>
        <guid isPermaLink="false">66da939980d9c8e9fda81521</guid>
        <category><![CDATA[ Ghost ]]></category>
        <dc:creator><![CDATA[ 송성광 ]]></dc:creator>
        <pubDate>금, 06 9월 2024 15:26:41 +0900</pubDate>
        <media:content url="https://images.unsplash.com/photo-1526031294500-869c7416f3eb?crop&#x3D;entropy&amp;cs&#x3D;tinysrgb&amp;fit&#x3D;max&amp;fm&#x3D;jpg&amp;ixid&#x3D;M3wxMTc3M3wwfDF8c2VhcmNofDI5fHx0YWd8ZW58MHx8fHwxNzI1NjAwNjk5fDA&amp;ixlib&#x3D;rb-4.0.3&amp;q&#x3D;80&amp;w&#x3D;2000" medium="image"/>
        <content:encoded><![CDATA[ <blockquote>Ghost 는 Ghost 일까? ghost 일까?</blockquote><p>Ghost 블로그 로고 이미지는 ghost  로 소문자로 표시하고 있고 사이트에서는 Ghost로 표기하고 있다.  도대체 뭐가 맞는걸까?</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2024/09/IMG_0474.png" class="kg-image" alt="" loading="lazy" width="2000" height="1379"></figure><p>블로그에 Ghost에 관련된 글을 작성하면서 모두 ghost로 작성했는데, 브랜드 이름은 Ghost인것을 확인하고 포스팅 했던 글에서 ghost를 모두 찾아서 Ghost 로 변경하는 작업을 했다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2024/09/IMG_0469.png" class="kg-image" alt="" loading="lazy" width="2000" height="1379"></figure><p>그런데 문제를 하나 발견했다. 내가 작성한 글은 에디터에서 글을 수정하면 되는데, 포스팅에 Tag로 등록했던 단어는 수정이 되지 않는것이다.</p><p>Ghost의 Dashboard 에서 Tag를 관리하는 메뉴로 들어가 보았지만 역시나 태그 수정기능은 없었다.</p><p>나는 태그를 외부에 노출될 때 ghost가 아닌 Ghost로 출력하고 싶은데 이미 한번 생성된 태그의 이름을 수정할 수 없는것이다. SLUG야 어차피 URL 로 사용하기 때문에 모두 소문자로 저장되지만 외부에서 노출되는 태그는 Ghost로 출력하고 싶었다.</p><p>그래서 Ghost의 데이터베이스인 MySQL 에 접속해서 직접 고치기로 한다.</p><p>SSH  클라이언트로 서버에 접속한 뒤 MySQL로 접속한다. 이 블로그를 통해서 Amazon Lightsail 과 iPad 에서 Termius 앱으로 SSH 접속하는 방법을 소개했으니 필요하면 앞의 포스팅을 참조하면 된다.</p><pre><code>mysql -u root -p</code></pre><p>현재 MySQL 에서 사용중인 데이터베이스 목록을 살펴보자</p><pre><code>show databases;</code></pre><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2024/09/IMG_0475.jpeg" class="kg-image" alt="" loading="lazy" width="2000" height="735"></figure><p>Ghost를 설치할 때 ghost-cli 로 설치 했다면 설치하는 과정에서 database 이름을 지정하는 프롬프트가 나왔을것인데 그 때 입력한 데이터베이스가 보일 것이다. MySQL 에서 데이터베이스를 사용할 때는 use 명령어를 사용한다.</p><pre><code>use blog_sungkwang_dev_prod</code></pre><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2024/09/IMG_0476.jpeg" class="kg-image" alt="" loading="lazy" width="2000" height="509"></figure><p>이제 Ghost 에서 사용하는 테이블을 모두 살펴보자. 데이터베이스 내부의 모든 테이블을 조회하기 위해서 다음 명령어를 사용한다.</p><pre><code>show tables;</code></pre><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2024/09/IMG_0477.png" class="kg-image" alt="" loading="lazy" width="2420" height="1668"></figure><p>Ghost 에서 정말 많은 테이블을 사용하고 있다는 것을 확인할 수 있다. 여기서 우리는 태그에 관련된 테이블 tags 테이블을 살펴볼 것이다. 테이블의 데이터를 조회하기 위해서 우리는 select 문을 사용하여 살펴볼 것이다.</p><pre><code>select * from tags;</code></pre><p>복잡하고 긴 컴럼명과 데이터 때문에 작은 화면에 모두 출력하면 아래 이미지처럼 필요한 데이터를 살펴보기 어렵게 된다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2024/09/IMG_0478.jpeg" class="kg-image" alt="" loading="lazy" width="2000" height="1217"></figure><p>우선 tags 테이블의 구조를 살펴보자.</p><pre><code>desc tags;</code></pre><p>테이블 스키마를 보고 우리가 필요한 컬럼만 확인하면 된다. Ghost에서 태그의 이름은 tags테이블의 name 으로 슬러그는 slug 컬럼에 저장된다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2024/09/IMG_0479.jpeg" class="kg-image" alt="" loading="lazy" width="2000" height="836"></figure><p>태그 테이블의 name과 slug만 다시 조회해보자.</p><pre><code>select name, slug from tags;</code></pre><p>이제 잘 볼 수 있게 데이터가 출력된다. 그리고 내가 수정하고 싶어하는 ghost 태그도 보인다. </p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2024/09/IMG_0480.jpeg" class="kg-image" alt="" loading="lazy" width="2000" height="515"></figure><p>이제 ghost 태그 이름을 Ghost 로 업데이트 한다.</p><pre><code>update tags set name='Ghost' where slug='ghost';</code></pre><p>tags 테이블의 데이터를 업데이트 한 후 테이블을 조회하면 아래와 같이 Ghost로 이름이 변경된 것을 확인할 수 있다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2024/09/IMG_0481.jpeg" class="kg-image" alt="" loading="lazy" width="2000" height="613"></figure><p>테이블의 내용이 정상적으로 확인되었으면 데이터베이스에 완전히 반영하기 위해서 commit 명령어를 입력하고 종료하면 된다.</p><pre><code>commit;</code></pre><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2024/09/IMG_0482.jpeg" class="kg-image" alt="" loading="lazy" width="2000" height="161"></figure><p>데이터베이스 데이터를 수정했으니 다시 Ghost Dashboard 를 살펴보면 반영된 사실을 확인할 수 있다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2024/09/IMG_0471.jpeg" class="kg-image" alt="" loading="lazy" width="2000" height="1379"></figure><p>에디터에서 태그를 입력하는 부분을 살펴보면 태그가 수정되어 있는것을 확인할 수 있다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2024/09/IMG_0483.jpeg" class="kg-image" alt="" loading="lazy" width="2000" height="1379"></figure><p>사용자들이 블로그 태그를 검색해서 확인할 수 있는 https://blog.sungkwang.me/tag/ghost 로 접근해보면 태그 이름이 Ghost로 적용된 것을 확인할 수 있다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2024/09/IMG_0485.jpeg" class="kg-image" alt="" loading="lazy" width="2000" height="1379"></figure> ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[ Amazon Lightsail 에서 Ghost 블로그 운영하기 #3. Ghost 설치 ]]></title>
        <description><![CDATA[ 이번 포스팅은 Amazon Lightsail Ubuntu 인스턴스에 NGINX와 MySQL을 설치하고 ghost-cli를 이용하여 Ghost를 설치하는 방법을 소개한다. ]]></description>
        <link>https://blog.sungkwang.me/installing-and-setting-up-ghost-on-the-amazon-lightsail/</link>
        <guid isPermaLink="false">66d815d180d9c8e9fda813d6</guid>
        <category><![CDATA[ AWS ]]></category>
        <dc:creator><![CDATA[ 송성광 ]]></dc:creator>
        <pubDate>목, 05 9월 2024 17:06:51 +0900</pubDate>
        <media:content url="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2024/09/IMG_0444.png" medium="image"/>
        <content:encoded><![CDATA[ <p>앞에서 우리는 Amazon Lightsail 을 이용하여 ubuntu 인스턴스를 설치했고, iPad에서 Termius를 이용하여  SSH 접속을 할 수 있는 환경을 만들었다.이번 포스팅에서는 앞에서 설치한 인스턴스에 Ghost를 설치하는 내용을 다룬다.</p><p>Ghost 공식 문서는 <a href="https://ghost.org/docs/install/?ref=blog.sungkwang.me">https://ghost.org/docs/install/</a> 에서 확인 가능하다.</p><h2 id="ubuntu-%EC%84%9C%EB%B2%84-%EC%8B%9C%EA%B0%84-%EB%8F%99%EA%B8%B0%ED%99%94">Ubuntu 서버 시간 동기화</h2><p>Amazon Lightsail에서 인스턴스를 생성하면 서버 시간이 UTC로 표기된다. 우리는 대한민국 시간으로 시간을 표기할 수 있게 한다.</p><pre><code>sudo timedatectl set-timezone Asia/Seoul</code></pre><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2024/09/IMG_0435.jpeg" class="kg-image" alt="" loading="lazy" width="2000" height="207"></figure><h2 id="ubuntu-%ED%8C%A8%ED%82%A4%EC%A7%80-%EC%97%85%EB%8D%B0%EC%9D%B4%ED%8A%B8">Ubuntu 패키지 업데이트</h2><p>Ghost 설치 이전에 ubuntu 패키지를 최신버전으로 모두 업데이트한다.</p><pre><code>sudo apt update</code></pre><pre><code>sudo apt upgrade</code></pre><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2024/09/IMG_0430.jpeg" class="kg-image" alt="" loading="lazy" width="2000" height="1379"></figure><h2 id="nodejs-%EC%84%A4%EC%B9%98">Node.js 설치</h2><p>다음은 Ubuntu에 Node.js를 설치한다. 우분투에서 apt 명령어로 설치할 수 있지만 Ubuntu 기본 패키지의 Node.js 버전은 낮기 때문에 직접 설치해주는 것이 좋다. Node.js를 설치하는 여러 방법 중에 apt install을 사용하여 설치하는 방법으로 설치한다. 이 방법을 사용하기 전에 ca-certificates, gnupg, curl  패키지가 필요해서 먼저 설치한다.</p><pre><code>sudo apt install  ca-certificates gnupg curl</code></pre><p>만약 설치가 되어 있으면 아래 이미지와 같이 이미 설치되어 있다는 메세지를 출력해준다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2024/09/IMG_0431.jpeg" class="kg-image" alt="" loading="lazy" width="2000" height="457"></figure><p>다음은 nodesource의 key가 저장되는 디렉토리를 생성한다.</p><pre><code>sudo mkdir -p /etc/apt/keyrings</code></pre><p>이제  nodesource 의 키를 가져온다.</p><pre><code>curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | sudo gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg</code></pre><p>이제 Node.js 가 설치될 버전을 지정한다. 우리는 Ghost 에서 추천하는 18.x 버전을 사용할 것이기 때문에 18버전을 설치한다.</p><pre><code>NODE_MAJOR=18</code></pre><p>Ubuntu 패키지 리스트에 설치할 Node.js 패키지 항목을 추가한다.</p><pre><code> echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_$NODE_MAJOR.x nodistro main" | sudo tee /etc/apt/sources.list.d/nodesource.list
</code></pre><p>Ubuntu 패키지를 업데이트 한다.</p><pre><code>sudo apt update</code></pre><p>apt install 명령어를 사용하여 nodejs 패키지를 설치한다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2024/09/IMG_0432.jpeg" class="kg-image" alt="" loading="lazy" width="2000" height="1379"></figure><p>이제 모든 설치가 끝났다. 우리는 Node.js 18 버전을 설치했고 확인할 수 있다.</p><pre><code>node -v</code></pre><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2024/09/IMG_0433.jpeg" class="kg-image" alt="" loading="lazy" width="2000" height="131"></figure><h2 id="mysql-%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%B2%A0%EC%9D%B4%EC%8A%A4-%EC%84%A4%EC%B9%98">MySQL 데이터베이스 설치</h2><p>Ghost 블로그 플랫폼은 기본적으로 MySQL 데이터베이스를 사용하도록 추천하고 있어 Ubuntu 패키지의 MySQL 서버를 설치한다.</p><pre><code>sudo apt install mysql-server</code></pre><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2024/09/IMG_0436.jpeg" class="kg-image" alt="" loading="lazy" width="2000" height="1253"></figure><p>MySQL 서버를 설치하면 mysql root 유저로 접속할 수 있도록 데이터베이스에 root 유저를 추가한다. </p><pre><code>sudo mysql</code></pre><pre><code>ALTER USER 'root'@'localhost' IDENTIFIED WITH 
'mysql_native_password' BY '비밀번호를 입력한다';</code></pre><pre><code>FLUSH PRIVILEGES;</code></pre><pre><code>exit;</code></pre><p>위 명령어를 입력한 후 mysql -u root -p 명령어를 사용해서 MySQL 서버에 접속할 수 있다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2024/09/IMG_0437.jpeg" class="kg-image" alt="" loading="lazy" width="2000" height="949"></figure><h2 id="nginx-%EC%84%9C%EB%B2%84-%EC%84%A4%EC%B9%98">NGINX 서버 설치</h2><p>HTTP 요청 프록시 및 웹 서버를 담당할 NGINX 서버를 설치한다.</p><pre><code>sudo apt install nginx</code></pre><p>설치가 완료되면 방화벽에 NGINX 접근을 추가한다.</p><pre><code>sudo ufw allow 'Nginx Full'</code></pre><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2024/09/IMG_0438.jpeg" class="kg-image" alt="" loading="lazy" width="2000" height="410"></figure><h2 id="ghost-cli-%EC%84%A4%EC%B9%98">ghost-cli 설치</h2><p>이제 우리는 Ghost를 설치하고 관리하는 ghost-cli 를 사용할 것이다. npm 으로 ghost-cli 를 설치한다.</p><pre><code>sudo npm install ghost-cli@latest</code></pre><h2 id="ghost-%EC%84%A4%EC%B9%98">ghost 설치</h2><p>이제 Ghost 블로그 플랫폼을 설치하는 모든 패키지가 설치 되었다. 지금부터는 ghost-cli를 사용하여 Ghost 를 설치한다.</p><p>가장 먼저 Ghost가 설치될 디렉토리를 만든다. 예제로 만들 Ghost 블로그는 ghostblog.sungkwang.me 라는 도메인으로 만들려고 한다. 디렉토리 이름도 같은 이름으로 생성한다. 다른 이름으로 생성해도 상관없는데 사이트 이름으로 생성해야 나중에 다른 디렉토리와 구분하기 쉽다.</p><pre><code>sudo mkdir -p /var/www/ghostblog.sungkwang.me</code></pre><p>생성한 디렉토리에 소유주를 Amazon Lightsail 의 유저인 ubuntu 로 변경한다.</p><pre><code>sudo chown ubuntu:ubuntu /var/www/ghostblog.sungkwang.me</code></pre><p>웹 서비스를 위한 접근 권한을 설정한다.</p><pre><code class="language- ">sudo chmod 755 /var/www/ghostblog.sungkwang.me</code></pre><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2024/09/IMG_0443.jpeg" class="kg-image" alt="" loading="lazy" width="2000" height="282"></figure><p>디렉토리 생성이 끝나면 디렉토리 내부로 들어가서 Ghost 설치를 진행한다.</p><pre><code>ghost install</code></pre><p>설치 도중에 몇 가지 입력 프롬프트가 나타난다.</p><ul><li><strong>Enter your blog URL</strong> : 도메인을 입력한다. 앞에서 설정한 https://ghostblog.sungkwang.me를 입력한다.</li><li><strong>Enter you MySQL hostname</strong>: MySQL 주소를 입력하는데 내부적으로 사용할 것이기 때문에 127.0.0.1 그대로 입력한다.</li><li><strong>Enter your MySQL username</strong>: root, MySQL 에 접속하기 위한 유저인데 우리는 root 입력한다.</li><li><strong>Enter your MySQL password</strong>: MySQL에 접속하기 위한 유저 비밀번호를 입력한다.</li><li><strong>Enter your Ghost database name</strong>: ghostblog_sungkwang_dev_prod, MySQL 서버 안에 생성될 데이터베이스 이름을 입력한다. </li><li><strong>Do you with to set up "ghost" mysql user?</strong>: Yes, MySQL  유저로 Ghost유저를 추가한다.</li><li><strong>Do you wish to set up Nginx?</strong>: Yes, NGINX 서버 자동으로 설정한다.</li><li><strong>Do you wish to set up SSL?</strong>: Yes, SSL 인증서 발급 및 https 웹서버 환경을 설정한다.</li><li><strong>Enter your email(For SSL Certificate)</strong>: sungkwang.dev@gmail.com 인증서 발급에 필요한 이메일 주소를 입력한다. 개인 이메일 주소를 입력하면 된다.</li></ul><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2024/09/IMG_0461.jpeg" class="kg-image" alt="" loading="lazy" width="2000" height="1379"></figure><p>Ghost cli를 사용하여 설치하면 Ghost 설치뿐만 아니라 NGINX, MySQL, SSL 인증서까지 한번에 설치가 된다. </p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2024/09/IMG_0462.jpeg" class="kg-image" alt="" loading="lazy" width="2000" height="198"></figure><p>Ghost 설치가 완료되었다. </p><h2 id="amazon-lightsail-%EB%B0%A9%ED%99%94%EB%B2%BD-https-%ED%8F%AC%ED%8A%B8-%EC%B6%94%EA%B0%80">Amazon Lightsail 방화벽 HTTPS 포트 추가</h2><p>마지막으로 Lightsail인스턴스의 방화벽에 HTTPS 포트를 추가아야한다. 기본적으로 HTTPS포트가 추가되어 있지 않기 때문에 Ligtsail 인스턴스 상세보기에서 들어가서 네트워크 탭을 선택한다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2024/09/IMG_0449-1.jpeg" class="kg-image" alt="" loading="lazy" width="2000" height="1379"></figure><p>IPv4 Firewall 아래 Add rule 을 선택하여 HTTPS포트를 추가한다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2024/09/IMG_0464.png" class="kg-image" alt="" loading="lazy" width="2420" height="1668"></figure><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2024/09/IMG_0465.png" class="kg-image" alt="" loading="lazy" width="2420" height="1668"></figure><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2024/09/IMG_0466.png" class="kg-image" alt="" loading="lazy" width="2420" height="1668"></figure><p>이제 모든 설정이 끝났다. 브라우저가서 https://ghostblog.sungkwang.me/ 로 접속하면 아래와 같이 Ghost 블로그가 정상적으로 설치된 것을 확인할 수 있다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2024/09/IMG_0467.png" class="kg-image" alt="" loading="lazy" width="2000" height="1379"></figure> ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[ Amazon Lightsail 에서 Ghost 블로그 운영하기 #2. AWS Route53 도메인 연결 ]]></title>
        <description><![CDATA[ 이번 포스팅에서는 AWS 네임서버를 가비아에 네임서버로 등록한 후 Route53을 이용하여 Amazon Lightsail 인스턴스를 도메인과 연결하는 방법을 소개한다. ]]></description>
        <link>https://blog.sungkwang.me/aws-route53-domain-to-amazon-lightsail-instance/</link>
        <guid isPermaLink="false">66d94daa80d9c8e9fda8145f</guid>
        <category><![CDATA[ AWS ]]></category>
        <dc:creator><![CDATA[ 송성광 ]]></dc:creator>
        <pubDate>목, 05 9월 2024 16:19:21 +0900</pubDate>
        <media:content url="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2024/09/IMG_0460.jpeg" medium="image"/>
        <content:encoded><![CDATA[ <p>웹 서비스를 위해서 반드시 필요한 것이 도메인이다. 개발자라면 개인적으로 관리하는 도메인을 하나 정도 가지고 있을 것으로 생각된다. 블로그 서비스를 위해서 도메인이 필요하니 <a href="https://www.gabia.com/?ref=blog.sungkwang.me" rel="noreferrer">가비아</a>, 후이즈 같은 곳에서 구입하면 된다. AWS에서 자체에서도 도메인을 구입하고 바로 등록하는 메뉴가 있지만 나는 기존에 가비아에서 도메인을 구입해서 관리하고 있기 때문에 가비아 기준으로 설명을 한다. 도메인 구매와 연장만 가비아에서 진행하고 네임서버 관리는 AWS 의 Route53으로 운영하고 하고 있다.</p><p>도메인 구입하는 방법과 같은 기본적인 내용은 다루지 않겠다. </p><h2 id="%EA%B0%80%EB%B9%84%EC%95%84%EC%97%90-aws-route53-%EB%84%A4%EC%9E%84%EC%84%9C%EB%B2%84-%EB%93%B1%EB%A1%9D">가비아에 AWS Route53 네임서버 등록</h2><p>다만 가비아의 네입서버를 사용하지 않고 AWS 의 Route53을 사용하기 위해서는 가비아의 네임서버 변경을 진행해야한다.  아래 이미지에서 가비아 네임서버에 AWS Route53 네임서버를 등록한 설정을 확인할 수 있다. </p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2024/09/IMG_0445.jpeg" class="kg-image" alt="" loading="lazy" width="2000" height="1379"></figure><p>위와 같이 AWS Route53으로 도메인을 관리하고 싶으면 AWS Route53에 도메인을 등록하고 네임서버를 참조할 수 있도록 가비아에 등록해줘야 한다. </p><h2 id="route53-%ED%98%B8%EC%8A%A4%ED%8A%B8-zone-%EB%93%B1%EB%A1%9D">Route53 호스트 Zone 등록</h2><p>AWS 콘솔에서 Route53 에 들어가 가비아에서 구입한 도메인을 등록한다. 나는 sungkwang.dev라는 도메인을 구입했기 때문에 AWS Route53에 sungkwang.dev라는 호스트 zone을 등록했다. </p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2024/09/IMG_0447.jpeg" class="kg-image" alt="" loading="lazy" width="2000" height="1379"></figure><p>sungkwang.dev 호스트 Zone을 선택하면 네임서버 4개가 보인다. 이 정보를 가비아 네임서버 등록하는 곳에서 등록하면 된다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2024/09/IMG_0448.jpeg" class="kg-image" alt="" loading="lazy" width="2000" height="1379"></figure><h2 id="amazon-lightsail-ip-%EB%8F%84%EB%A9%94%EC%9D%B8%EA%B3%BC-%EC%97%B0%EA%B2%B0">Amazon Lightsail IP 도메인과 연결</h2><p>이제 Ghost블로그를 운영할 인스턴스와 도메인을 연결할 레코드를 추가할 것이다. 앞 포스팅에서 생성했던 Amazon Lightsail의 인스턴스를 확인해서 Public IPv4 address 정보를 확인한다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2024/09/IMG_0449.jpeg" class="kg-image" alt="" loading="lazy" width="2000" height="1379"></figure><p>다시 Route53 화면으로 돌아가서 Create record 버튼을 클릭해서 새로운 레코드를 추가한다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2024/09/IMG_0448.jpeg" class="kg-image" alt="" loading="lazy" width="2000" height="1379"></figure><p>우리는 이 ghost블로그 설치 및 운용에 관련된 포스팅을 하는 동안 ghostblog.sungkwang.me 도메인을 사용할 예정이다. 그래서 아래와 같이 ghostblog 레코드를 sungkwang.dev 호스트 zone파일에 추가한다. 이 때, IP 정보는 앞에서 Amazon Lightsail의  Public IPv4 주소를 입력한다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2024/09/IMG_0450.jpeg" class="kg-image" alt="" loading="lazy" width="2000" height="1379"></figure><p>모든 내용을 입려후 Add another rocord 버튼을 클릭하면 등록이 완료된다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2024/09/IMG_0452.jpeg" class="kg-image" alt="" loading="lazy" width="2000" height="1379"></figure><p>약 몇분 후 도메인 연결이 잘 되었는지 확인할 수 있다. AWS 네임서버는 굉장히 빠르게 반영되어 거의 바로 확인할 수 있는데, 만약 가비아에 AWS네임서버 적용이 되어 있지 않으면 시간이 많이 소요된다. 가비아에 AWS 네임서버로 변경하고 하루정도는 시간을 갖고 작업하는게 좋다.</p><h2 id="%EB%8F%84%EB%A9%94%EC%9D%B8-%EC%97%B0%EA%B2%B0-%ED%99%95%EC%9D%B8">도메인 연결 확인</h2><p>우리는 아직 Amazon Lightsail 에 웹 서버를 설치하지 않았기 때문에 브라우저로 도메인 연결을 확인할 수 없다. 앞 포스팅에서 SSH 클라이언트를 이용하여 인스턴스에 접속할 때 IP를 사용했었다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2024/09/IMG_0455.jpeg" class="kg-image" alt="" loading="lazy" width="2000" height="1379"></figure><p>여기 호스트 정보를 이제 도메인으로 변경하여 접속하면 된다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2024/09/IMG_0456.png" class="kg-image" alt="" loading="lazy" width="2420" height="1668"></figure><p>라벨과 IP 정보 대신 도메인 이름으로 변경하고 Termius 에서 SSH 접속을 하게 되면 핑거프린트 확인 후 호스트가 추가되고 SSH 접속이 성공적으로 진행된다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2024/09/IMG_0458.jpeg" class="kg-image" alt="" loading="lazy" width="2000" height="1379"></figure><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2024/09/IMG_0459.jpeg" class="kg-image" alt="" loading="lazy" width="2000" height="1379"></figure><p>이번 포스팅에서는 Amazon Lightsail에서 생성한 인스턴스에 도메인을 연결하는 방법을 소개했다. 도메인 구입은 가비아에서 진행했고, 네임서버는 AWS Route53 의 네임서버를 사용했다. 도메인 연결을 위해 sungkwang.dev 도메인을 가지는 호스트 Zone 을 생성했고 그곳에 사용하는 네임서버 정보를 가비아 네임서버에 등록했다. 마지막으로 Lightsail의  IP를 ghostblog.sungkwang.me 도메인과 연결하기 위해서 Zone의 레코드에 추가했다.</p><p>다음 포스팅은 앞에서 생성한 Amazon Lightsail 인스턴스에 NGINX, MySQL, ghost를 설치하는 내용을 포스팅한다. ghost cli를 사용해서 설치할 때 https설정을 할 때  도메인이 필요하기 때문에 이번 포스팅에서 인스턴스와 도메인을 연결하는 내용을 잘 참조하길 바란다.</p> ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[ Amazon Lightsail 에서 Ghost 블로그 운영하기 #1. 인스턴스 설치와 iPad 에서 SSH 접속환경 설정 ]]></title>
        <description><![CDATA[ Amazon Lightsail에서 Ghost 블로그 운영하기 위한 첫번째 단계로 인스턴스를 설치하고 iPad에서 SSH 터미널 접속환경을 설정하는 방법을 소개한다. ]]></description>
        <link>https://blog.sungkwang.me/installing-aws-lightsail-an-ubuntu-instance-and-setting-up-ssh-terminal-on-the-ipad/</link>
        <guid isPermaLink="false">66d32db9df0048b4d86b6cc5</guid>
        <category><![CDATA[ AWS ]]></category>
        <dc:creator><![CDATA[ 송성광 ]]></dc:creator>
        <pubDate>수, 04 9월 2024 10:29:44 +0900</pubDate>
        <media:content url="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2024/09/IMG_0148.webp" medium="image"/>
        <content:encoded><![CDATA[ <p>유연하고 강력한 기능을 가진 Ghost 블로그 플랫폼을 AWS 서비스 중에서 개인이 쉽고 편리하게 관리할 수 있는 Lightsail 에서 운영하는 방법을 시리즈로 포스팅할 예정이다. 블로그 첫 포스팅에서도 소개했듯이 iPad에서 운영 및 관리 그리고 포스팅까지 진행한다.</p><p>우선 블로그 플랫폼으로 Ghost를 선택한 이유는 기존에 개인 블로그를 운영할 때 사용했던 플랫폼이기도 하고 사실상 현존하는 블로그 플랫폼 중에서 WordPress 다음으로 다른 대안이 없다고 생각한다. 개인적으로 PHP 환경보다 Node.js 환경을 선호하기 때문에 Ghost를 선택했다. 노션을 사용하고 있어 노션 페이지를 이용하여 블로그 환경을 만들 수 있지만 SSO 관점에서는 내가 원하는 방향은 아니라고 생각한다. 관리형 블로그로 네이버 블로그를 선택할지도 고민했지만 네이버에서 블로그 이미지 처리를 개선해주지 않아서 (고화질 이미지를 올리면 해상도를 자동으로 줄여서 이미지 선명도가 치명적으로 좋지 않게 올라간다) 네이버 블로그는 항상 후보에서 탈락이 되는것 같다. 이 문제만 해결해주면 관리형 블로그라 더이상 고민할 필요도 없을텐데 말이다. 암튼 Ghost 블로그 플랫폼은 기능도 너무 많아서 블로그 플랫폼만 소개해도 몇 개의 포스팅을 작성할 정도인데 기능 소개는 생략하니 다른 블로그를 참조하길 바란다.</p><p>AWS 는 이제 더이상 할 필요 없을만큼 대부분 사람들이 알고 있으니 소개가 의미 없다고 생각된다. 다만, AWS Lightsail 에 대해서 간략하게 소개하면 가벼운 서비스나 개인이 정해진 금액 안에서 많은 고민없이 바로 서비스를 운영할 수 있는 인프라를 쉽고 빠르게 구축할 수 있는 서비스이다. 단 클릭 몇 번만으로 바로 프로덕션 레벨의 서비스까지 만들 수 있으니 사이드 프로젝트나 개인 블로그 운영에 최고 적합한 서비스라고 생각한다. 가격도 저렴하다. 사실 AWS 서비스를 운영하면 가격 예측이 쉽지 않다 서비스마다 환경마다 가격 정책이 다르기 때문에 빌링정보를 따로 관리할 정도로 비용을 관리하는게 쉽지 않다. 그래서 그냥 AWS에 아무런 고민 없이 바로 시작해보고 싶은 딱 정해진 금액 안에서 사용할 수 있는 AWS Lightsail로 바로 시작하면 된다. 커피 한잔의 가격부터 있으니 필요한 리소스 정량제를 선택하면 된다. AWS 가입과 같은 기본적인 내용은 소개하지 않으니 다른 블로그를 참조하길 바란다. 이 글은 AWS 계정을 가지고 있는 사용자를 대상으로 진행한다.</p><p>항상 그렇지만 내가 생각한 것은 이미 누군가 생각하고 같은 주제의 블로그 글들이 많이 공유되고 있지만 조금씩 접근하는 방식이 다르니 이 포스팅도 누군가에게 도움이 되길 바란다.</p><h2 id="amazon-lightsail-%EC%8B%9C%EC%9E%91%EA%B3%BC-%EC%9D%B8%EC%8A%A4%ED%84%B4%EC%8A%A4-%EC%83%9D%EC%84%B1">Amazon Lightsail 시작과 인스턴스 생성</h2><p>AWS 콘솔에 접속한다. 아래 이미지는 iPad 로 AWS 웹 콘솔에 접속한 모습이다. 업무관계로 주로 사용하는 서비스들이 보이는데 Lightsail 주로 사용하는 서비스로 화면에서 보인다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2024/09/IMG_0409.jpeg" class="kg-image" alt="" loading="lazy" width="2000" height="1379"></figure><p>Amazon Lightsail 서비스에 들어가서 새로운 인스턴스를 생성한다. 기본적으로 내 로컬리전에 인스턴스를 생성할 수 있게 다음과 같이 Instance location 이 지정되어 있고 AWS Region 과 가용영역 Availability Zone 이 설정되어 있다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2024/09/IMG_0410.png" class="kg-image" alt="" loading="lazy" width="2420" height="1668"></figure><p>Change AWS Region and Availability Zone 링크를 클릭하면 대한민국 서울 말고 다른 국가로 리전을 변경할 수 있고 가용영역도 희망하는 곳으로 지정이 가능하다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2024/09/IMG_0411.png" class="kg-image" alt="" loading="lazy" width="2420" height="1668"></figure><h2 id="amazon-lightsail-app-%EC%9C%BC%EB%A1%9C-ghost-%EC%84%A4%EC%B9%98">Amazon Lightsail app 으로 Ghost 설치</h2><p>Lightsail 에서 Ghost를 설치하는 방법은 크게 두가지로 나눌 수 있는데 첫번째 방법은 Lightsail의 블루프린트 앱을 사용하여 설치하는 것이다.  아래 이미지는 Lightsail 의 블루프린트 목록이다. 여러가지 서버를 포함한 서비스 환경을 운영체제와 함께 패키지로 바로 설치할 수 있는 블루프린트이다. Ghost 항목을 선택하고 인스턴스를 생성하면 몇 분내 인터넷에서 바로 접속할 수 있는 Ghost가 설치된 서버 인스턴스를 바로 생성할 수 있다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2024/09/IMG_0412.png" class="kg-image" alt="" loading="lazy" width="2420" height="1668"></figure><p>초창기 Ghost 운영할 때는 나도 이 블루프린트를 사용했는데 이번에는 운영체제만 설치한 후 나머지는 직접 설치를 진행했다. 따로 특별한 이유는 없다. 블루프린트 방식으로 사용해도 충분히 서비스 운영에 문제되는 것도 없고 오히려 웹 서버나 https 설정 같은 것을 아주 쉽게 할 수 있는 장점이 많다.</p><h2 id="amazon-lightsail-operating-systemos-only-%EB%A1%9C-%EC%9A%B4%EC%98%81%EC%B2%B4%EC%A0%9C-%EC%84%A4%EC%B9%98">Amazon Lightsail Operating System(OS) only 로 운영체제 설치 </h2><p>나는 운영체제만 설치하는 인스턴스를 선택해서 Ghost 명령어를 사용하여 설치했다. Lightsail에서  운영체제 플랫폼을 선택한 후 Operating System (OS) only 탭을 선택하면 여러가지 운영체제와 버전별 인스턴스를 설치할 수 있다. AWS 에서 지원하는 Amazon Linux 를 설치하면 좀 더 안정적이지만 커뮤니티 호환성을 위해서 Ubuntu를 선택했다. 버전은 LTS 버전 중 최신버전인 22.04 를 선택했다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2024/09/IMG_0413.png" class="kg-image" alt="" loading="lazy" width="2420" height="1668"></figure><p>원하는 운영체제와 버전을 선택하면 다음으로 인스턴스에 접속할 SSH key를 선택한다. 처음 Lightsail를 사용하는 사용라라면 SSH key가 하나일 경우가 많겠지만 이미 여러 인스턴스를 다양한 방법으로 운영하고 있다면 SSH key가 여러개 있을 경우가 있다. 그럴때는 Change SSH key pair 를 선택해서 원하는 키를 선택한다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2024/09/IMG_0414.jpeg" class="kg-image" alt="" loading="lazy" width="2000" height="1379"></figure><p>다음은 네트워크 타입과 인스턴스의 사이즈를 선택한다. 네트워크 타입은 IPv4와 IPv6 같이 지원하는 Dual-stack 과 IPv6-only  타입 두가지가 있다. 특별한 이유가 아니면 Dual-stack 그대로 선택하면 된다. 인스턴스 사이즈는 필요에 맞게 선택하면 된다. 나는 보통 2GB 메모리와 2VCPU를 사용한다. 대용량 이미지 저장을 인스턴스 내부에 한다면 SSD Storage 사이즈도 고려해야한다. 나는 이미지를 AWS S3로 저장하도록 환경을 만들어서 운영하고 있기 때문에 로컬 스토리지에 큰 비중을 두지 않지만 Lightsail 만 운영한다면 반드시 용량을 생각해야한다. 데이터베이스와 로그 파일 등이 물리적으로 인스턴스 안에 저장하게 되고 무엇보다 이미지를 S3로 분리하지 않는 이상 틀림 없이 용량은 빠르게 줄어들 것이기 때문이다. 나중에 원격저장소를 따로 attach 하는 방법도 있지만 여러가지 상황을 잘 고려해서 용량을 선택하면 된다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2024/09/IMG_0415.png" class="kg-image" alt="" loading="lazy" width="2420" height="1668"></figure><p>마지막으로 인스턴스의 이름을 지정한다. 그리고 Create instance 버튼을 클릭하면 몇 분도 지나지 않아서 위에서 선택한 인스턴스가 인터넷이 가능한 상태로 자동으로 만들어지게 된다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2024/09/IMG_0416.png" class="kg-image" alt="" loading="lazy" width="2420" height="1668"></figure><p>이제 인스턴스를 만드는 1분 내외 기다리면 된다. Pending 상태는 현재 인스턴스를 만들고 있는 상태이다. 인스턴스가 생성되면서 내부적으로 IP를 할당받고 인터넷이 연결될 수 있는 준비를 한다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2024/09/IMG_0418.jpeg" class="kg-image" alt="" loading="lazy" width="2000" height="1379"></figure><p>인스턴스가 정상적으로 생성되면 아래 이미지와 같이 인스턴스가 생성되고 IP도 활성화된 것을 확인할 수 있다. 이제 생성된 인스턴스 링크를 클릭한다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2024/09/IMG_0419.jpeg" class="kg-image" alt="" loading="lazy" width="2000" height="1379"></figure><p>인스턴스 링크를 크릭하면 생성된 인스턴스의 상세 정보를 확인할 수 있다. Instance status 도 Running 으로 확인 가능하다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2024/09/IMG_0420.jpeg" class="kg-image" alt="" loading="lazy" width="2000" height="1379"></figure><h2 id="%EC%83%9D%EC%84%B1%EB%90%9C-%EC%9D%B8%EC%8A%A4%ED%84%B4%EC%8A%A4-ssh-%EC%A0%91%EC%86%8D">생성된 인스턴스 SSH 접속</h2><p>인스턴스에 접근하기 위해서 2가지 방법으로 접근 가능하다. 하나는 AWS에서 제공하는 브라우저 클라이언트를 통해서 접근하는 방법이고 하나는 직접 SSH 클라이언트를 이용해서 접근하는 방법이다. 먼저 웹에서 접근하려면 Connect using SSH 버튼을 클릭만하면 된다. 다른 로그인 정보없이 웹 세션을 통해 바로 SSH 터미널이 웹에서 나타난다. 자동으로 로그인된 인스턴스 정보를 살펴보면 앞에서 생성한 인스턴스와 동일한 정보를 확인 할 수 있다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2024/09/IMG_0422.jpeg" class="kg-image" alt="" loading="lazy" width="2000" height="1379"></figure><p>두번째 방법은 SSH 클라이언트로 접속하는 방법이다. 앞에서 Lightsail 인스턴스를 생성할 때 사용한 SSH Key가 필요하다. 아마 생성할 때 각자 PC 또는 다른 저장소에 저장했을텐데 키가 꼭 필요하다. Lightsail 에서 Ubuntu 인스턴스를 생성하면 기본적으로 ubuntu라는 유저가 생성된다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2024/09/IMG_0421.jpeg" class="kg-image" alt="" loading="lazy" width="2000" height="1379"></figure><p>iPad 에서 SSH 클라리언트로 유명한 Termius를 사용하여 접속해보자. 유료 앱이지만 충분한 가치가 있는 앱으로 적극 추천한다. </p><p>먼저 Hosts에서 + 버튼을 클릭해서 새로운 호스트를 추가한다. 이 때 Lightsail의 퍼블릭 IP 정보를 입력한다. Username 에는 ubuntu를 입력한다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2024/09/IMG_0424.jpeg" class="kg-image" alt="" loading="lazy" width="2000" height="1379"></figure><p>Lightsail의 인스턴스는 비밀번호로 접속하지 않고 SSH key를 가지고 접속한다. 인스턴스를 만들때 사용한 SSH key를 Termius의 Keychain에 등록한다. Lightsail에서 다운받다던 SSH key를 복사한 뒤 Paste Key를 이용해서 붙여넣기 하면 된다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2024/09/IMG_0428.jpeg" class="kg-image" alt="" loading="lazy" width="2000" height="1379"></figure><p>아래 이미지와 같이 Private Key에 복사된 키를 붙여넣으면 된다. 아래 이미지 키는 임의로 예제로 생성된 키이다. 각자 자신의 키를 저장하면 된다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2024/09/IMG_0429.png" class="kg-image" alt="" loading="lazy" width="2000" height="1379"></figure><p>SSH key 등록 후 Host를 추가하면 Termius 의  Host 에 추가한 인스턴스가 새로운 호스트로 등록된 것이 보인다. </p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2024/09/IMG_0427.jpeg" class="kg-image" alt="" loading="lazy" width="2000" height="1379"></figure><p>새로 추가된 호스트를 선택하면 터미널이 실행된다.</p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2024/09/IMG_0426.jpeg" class="kg-image" alt="" loading="lazy" width="2000" height="1379"></figure><p>iPad에서 서버 운영 및 관리하기 위해서 SSH 터미널 앱이 반드시 필요한데 Termius 앱이 가장 좋은 것 같다. 멀티 터미널도 지원하고, 키 관리도 지원하고, 동기화도 지원하고 안정속도와 반응성도 매우 좋다.  iPadOS 특성 때문에 백그라운드로 앱이 들어가면 세션이 끊어지는데 이것을 보안하기 위해 몇 가지 대안을 제공하고 있어 세션 끊어짐 없이 작어도 가능하다. </p><p>이제 인스턴스 설치와 접속 과정의 설명은 모두 끝났다. 처음부터 iPad 에서 블로그를 운영하려는 포스팅을 작성하려고 한 것은 아니다. 하지만 iPad 를 현재 주력으로 사용하고 있는 서브 디바이스로 랩탑이 없을 경우, 또는 이동중 어디서나 iPad를 사용해야하는 상황이 발생하면 주저없이 사용기 위해서 대부분의 작업은 iPad에서 진행하려고 한다. 테스트 결과 iPad 는 원격 터미널 디바이스로 충분하다. 현재 블로그 역시 포스팅한 예제와 같이 AWS 를 이용하여 블로그를 운영하는 모든 과정을 iPad로 처리했다. </p><p>다음 포스팅은 실제 Ghost블로그 플랫폼을 ghost명령어를 사용하여 새로 생성한 인스턴스에 설치하는 방법을 소개한다.</p> ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[ iPad Pro M4 로 블로그 시작 ]]></title>
        <description><![CDATA[ 모든 책의 첫 장은 항상 임펙트있게 시작해야하는데 블로그 첫 글을 어떤것을 작성할지 고민했다. 너무 길면 지루하고, 너무 짧으면 성의없어 보이는 첫 장. 나는 내 블로그 첫 장에 왜 블로그를 다시 시작하게 된건지 기록하려고 한다.

내가 연구소에서 지원받은 분신과 같은 랩탑은 MacBook Pro 16인치 마지막 인텔칩셋 모델이다. 솔직히 코드를 작성할 때는 ]]></description>
        <link>https://blog.sungkwang.me/start-blogging-with-ipad/</link>
        <guid isPermaLink="false">66c6ac3dcaba3c3b3f708d22</guid>
        <category><![CDATA[ iPad ]]></category>
        <dc:creator><![CDATA[ 송성광 ]]></dc:creator>
        <pubDate>토, 31 8월 2024 20:12:21 +0900</pubDate>
        <media:content url="https://images.unsplash.com/photo-1607292803026-3b9d9b3d0fe7?crop&#x3D;entropy&amp;cs&#x3D;tinysrgb&amp;fit&#x3D;max&amp;fm&#x3D;jpg&amp;ixid&#x3D;M3wxMTc3M3wwfDF8c2VhcmNofDR8fGlwYWQlMjB8ZW58MHx8fHwxNzI0MzA4Mjk0fDA&amp;ixlib&#x3D;rb-4.0.3&amp;q&#x3D;80&amp;w&#x3D;2000" medium="image"/>
        <content:encoded><![CDATA[ <p>모든 책의 첫 장은 항상 임펙트있게 시작해야하는데 블로그 첫 글을 어떤것을 작성할지 고민했다. 너무 길면 지루하고, 너무 짧으면 성의없어 보이는 첫 장. 나는 내 블로그 첫 장에 왜 블로그를  다시 시작하게 된건지 기록하려고 한다.</p><p>내가 연구소에서 지원받은 분신과 같은 랩탑은 MacBook Pro 16인치 마지막 인텔칩셋 모델이다. 솔직히 코드를 작성할 때는 데스크탑이 필요없을 만큼 시원하게 큰 화면이 좋았지만, 출장 한번 다녀오면 어깨가 너무 아팠다. 이럴때는 아무리 성능이 좋아도 출장에서는 코딩을 하는것도 아니라 굳이 이렇게 크고 무거운 랩탑을 둘러매고 다녀야하는게 너무 불편했다. AWS Summit 에 참석할때는 하루에 만보이상 걸어 다니는데, 하루종일 랩탑을 매고 다니다보면 금방 지쳐서 세션 이동을 하고 싶지 않기도 했다. </p><p>나는 현재 연구소에서 클라우드 서비스 관리 및 운영 롤을 맡고 있어 365일 언제 어디서나 인터넷에 접속할 수 있어야 한다. 클라우드서비스 특성상 어디서든지 인터서에 접속만 할 수 있으면 빠르게 처리될 일이 물리적이나 지리적 이유로 곧바로 접속할 수 없게 되면 클라우드서비스 이점을 누리지 못할뿐 아니라 서비스 지연에 문제가 발생한다. 한번은 아들의 태권도 시범을 보이는 날에 랩탑을 두고 갔던적이 있다. 한참 시범이 진행되고 있었는데 연구소에서 연락이 왔다. 당장 서버가 이상해서 클라우드에 접속해야하는데 랩탑이 없어서 급하게 집으로 이동해서 아이의 시범을 제대로 관람하지 못했었던 날이였다. 또 한번은, 해외 출장중에서 일어난 일이다. 출장 중에 룩셈부르크를 잠시 거쳐가면서 세계에서 가장 아름다운 성 비안덴 성을 방문하는 일정이 있었다. 하지만 비안덴  성에 들어가자말자 서비스 장애가 발생했다. 급하게 스마트폰으로 AWS console에 접속했는데 너무 화면이 좁아서 장애 대처를 할 수 없어 세계의 가장 아름다운 성 비안덴 성을 구경하지 못하고 랩탑을 두고왔던 이동차량에 급하게 뛰어 내려가서 장애를 처리해야했다. </p><figure class="kg-card kg-image-card"><img src="https://s3-ap-northeast-2.amazonaws.com/hbn-user-sksong/2024/08/IMG_4263.jpeg" class="kg-image" alt="" loading="lazy" width="2000" height="1125"></figure><p>만약 이때 아이패드가 있었더라면 어땠을까? 해외출장 중에 이런 일을 겪으면서 나뿐만 아니라 연구소에서 아이패드 지원에 대해 도입이 필요하다는 피드백이 있었다. 결국 회사에서 아이패드 지원이 승인되면서 iPad Pro M4 구입이 확정되고 지금 이 글도 아이패드로 작성하고 있다.</p><p>아이패드 구입 후 랩탑으로 할 수 있는 일들을 이동중에 처리할 수 있는 고민을 많이 했다. iPad Pro는 상당히 고가의 디바이스이다. 사람들은 이돈이면 맥북에어 13인치를 산다며 아이패드는 가격에 비해 실용성이 적다는 이야기들이 많았는데, 결론적으로 실제 사용해보니 어떻게 활용하는지에 따라 다르다고 생각된다. 나는 이제 항상 아이패드를 가지고 다닌다. 맥북프로 16인치 모델을 더이상 무겁게 들고 다니지 않아도 된다. 지금까지 맥북으로 했던 모든 것을 아이패드로 할 수 있게 되었기 때문이다. 어떻게 사용하기에 개발부터 관리까지 모든것을 아이패드로 할 수 있는지에 대한 소개는 다른 포스팅을 통해서 소개할 예정이다.</p><p>중요한건 다시 블로그를 시작했다는 것이다. 꼭 아이패드를 구입해서 블로그를 다시 시작한 것은 아니다. 기존에 블로그에 개발과 연구에 관한 내용을 공유하고 있었는데 도메인 만료 시점으로거여러가지 일들이 겹치면서 한동안 블로그 운영을 할 수 없었다. 그동안 도메인 소유가 다른 누군가에게 넘어갔고 도메인을 잃고난 뒤 블로그를 잊고 지내고 있었다. 아이패드 구입후 노션앱으로 기록을 하고 있었는데 개인적으로 노션보다는 블로그에 글을 작성하는 것이 좀 더 구체적으로 정리되는 기분이 들어 블로그를 다시 시작하게 되었다. </p><p>앞으로 대부분의 블로그 포스팅은 아마도 iPad Pro M4 모델을 이용해서 작성할 것 같다. 왜냐면 나는 지금도, 어디서든지 늘 이 디바이스를 가지고 있기 때문일 것이다. </p> ]]></content:encoded>
    </item>

</channel>
</rss>
