<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>Joo's Story</title>
    <link>https://blog.joostory.net/</link>
    <description>개인적인 관심사에 관해서 이런저런 이야기를 하고 있습니다.
#집밥 #개발자 #Ubuntu</description>
    <language>ko</language>
    <pubDate>Thu, 9 Apr 2026 08:51:55 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>Joo</managingEditor>
    <image>
      <title>Joo's Story</title>
      <url>https://tistory1.daumcdn.net/tistory/22084/attach/1bf82392adaf49edaeab476e2ba6e9bb</url>
      <link>https://blog.joostory.net</link>
    </image>
    <item>
      <title>이것이 vibe 코딩인가</title>
      <link>https://blog.joostory.net/626</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;그동안 AI 서비스가 계속 발전해서 chatgpt, copilot, grok, gemini 등이 나왔고 이것이 개발도구에 들어오기 시작했다. 많은 사람들이 너무 좋다고 계속 추천을 하는데 나는 유료버전을 안써서 그런지 별로 좋은 경험은 아니었다. intelliJ, vscode에서 copilot agent, gemini agent를 사용했었는데 ide 문제인지 내가 익숙하지 않아서 그런지 모르겠지만 뭔가 모르게 불편했고 그냥 내가 원하는대로 되지가 않았다. 그래서 좋다는 사람들은 어떻게 쓰나 궁금했는데 vibe코딩이라는 말이 나오기 시작했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;vibe코딩은 뭔가 정확한 지시를 하는게 아니라 기획초기 아이디어 던지듯이 요구사항을 툭툭 던지면서 하는 코딩을 말하는 것 같았다. (사람들이 하는거 보니까 그렇게 하더라) 사실 이것도 그냥 그러려니 했는데 gemini-cli를 소개하는 영상을 보면서 조금 끌리기 시작했다. 그동안의 ai 코딩은 ide와 통합이 필요했고, 그래서 뭐 cursor니 뭐니 잔뜩 나왔었다. 그런데 gemini-cli는 달랐다. ide는 상관없다. 그 안에 터미널만 열면 됐다. 아니 ide 내부 터미널이 아니라도 된다. 아무 터미널이면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;project 디렉토리에서 터미널을 열고 이것저것 요구사항을 말하면 뚝딱뚝딱 만들어서 diff를 보여주면서 코드를 막 수정한다. 아주 간단한 작업을 시켜보니까... 어라? 굉장히 깔끔하게 작업을 마무리 한다. 뭔가 원하는대로 동작을 안하고 있어서 해결해달라고 했는데 코드를 쭉 읽어보더니 문제점을 찾아서 해결해주었다. 단순히 알려주는 것만이 아니고 파일 수정까지도 한다. 무엇보다도 그 과정에서 나에게 설명해주는 부분이 좋았다. 개요, 본론, 결론 나눠서 군더더기 없는 커뮤니케이션을 한다. 마치 굉장히 똑똑한 동료와 페어코딩하는 느낌. 때마침 성경앱에 검색기능이 필요한 상황이어서 gemini-cli를 사용해서 해결해보기로 했다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;검색기능 해줘&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음엔 어떻게 시작해야할지 몰라서 최대한 자세히 설명했던 것 같다. (터미널 기록이 없네 ;;;)&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;nextjs로 github page로 publish를 하고 있어. data/bible.json을 읽어서 페이지에 표시하고 있는데 모든 페이지에서 이 성경책을 검색하도록 하고 싶어. ctrl+k, 맥에선 cmd+k로 검색하고 header에도 검색버튼을 추가해줘. ui는 dialog로 표시하고 검색어를 입력하면 리스트가 나오도록 하면 좋겠어.&amp;nbsp;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이정도 느낌이었다. 여기서 첫번째 감동을 받았다. 바로 실행하지 않고 분석을 한 후에 실행계획을 순서대로 알려주고 이후에 순서대로 수행을 하는데 이 부분이 뭔가 나에게 믿음을 주는 행동이었다. 뭐랄까 회사에서 동료에게 뭔가를 부탁했을때 이런 응답이 오기를 바랬는데 완벽한 응답이었다. 이제 계획을 읽고 나는 ok만 하면 되는거였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;수행과정도 아주 맘에 든다. 뭔가를 할때마다 '하겠습니다', '하고 있습니다', '했습니다' 이런식으로 알려주면서 한다. 실제 동료와 페어로 일을 하면 커뮤니케이션에 말로, 화면으로 여러가지 수단을 활용해야하는데 gemini-cli는 한 화면에서 수행과정까지 보고서 형식으로 하니 정말 편했다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1764&quot; data-origin-height=&quot;723&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/6YwyW/btsO5eQiqvt/3KcGSw7RfViXxZ1Xmu8fPK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/6YwyW/btsO5eQiqvt/3KcGSw7RfViXxZ1Xmu8fPK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/6YwyW/btsO5eQiqvt/3KcGSw7RfViXxZ1Xmu8fPK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F6YwyW%2FbtsO5eQiqvt%2F3KcGSw7RfViXxZ1Xmu8fPK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1764&quot; height=&quot;723&quot; data-origin-width=&quot;1764&quot; data-origin-height=&quot;723&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;새로운 기능을 만들어달라는 요구였기 때문에 다소 작업이 많았는데 수행과정은 자세히 설명하고 계획 설명, 수행 결과 요약은 간결했다. 이건 뭐 너무나 완벽한 동료개발자의 모습이다. 심지어 내가 직접했다면 한시간은 걸렸을 작업을 몇마디 말에 몇분만에 완료했다. 물론 100% 완벽한 것은 아니다 ui 작업이기 때문에 실제로 결과를 눈으로 확인하고 조정해야하는 것은 내 몫이었다. 개발 과정이 완벽했다는 뜻이다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;고쳐줘&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결과를 확인해보니 오류가 발생하고 있다. 흠... 이제 두번째 요구인데 어떻게 말할까 하다가 간략하게 상황만 설명하기로 했다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1705&quot; data-origin-height=&quot;502&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xmC5E/btsO7yTus6O/mmqLOJLkXUEQlMxwZp0PG0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xmC5E/btsO7yTus6O/mmqLOJLkXUEQlMxwZp0PG0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xmC5E/btsO7yTus6O/mmqLOJLkXUEQlMxwZp0PG0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxmC5E%2FbtsO7yTus6O%2FmmqLOJLkXUEQlMxwZp0PG0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1705&quot; height=&quot;502&quot; data-origin-width=&quot;1705&quot; data-origin-height=&quot;502&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;세상에. 원인파악, 해결계획, 수행 모두 완벽하다. 저렇게 잘 알면서 왜 처음부터 잘 만들지 않았지라는 생각은 뒤로 하고 다음 요구를 말했다. daisyui를 쓰고 있는데 radix dialog를 쓰고 있어서 이걸 바꿔달라는 말이었다. 이제 진짜 동료대하듯 친철하게 말한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1759&quot; data-origin-height=&quot;522&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ZlQLP/btsO5x9TFHJ/xZ3DR2Xjs0Ygufh9WcuAYk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ZlQLP/btsO5x9TFHJ/xZ3DR2Xjs0Ygufh9WcuAYk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ZlQLP/btsO5x9TFHJ/xZ3DR2Xjs0Ygufh9WcuAYk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FZlQLP%2FbtsO5x9TFHJ%2FxZ3DR2Xjs0Ygufh9WcuAYk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1759&quot; height=&quot;522&quot; data-origin-width=&quot;1759&quot; data-origin-height=&quot;522&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ref를 사용해서 브라우저 api를 직접 사용하는 부분은 귀찮은 작업인데 이것도 별문제 아니라는 듯 뚝딱해결해주었다. 이젠 좀 더 친근하게 다른 문제의 해결을 말하기 시작했다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1707&quot; data-origin-height=&quot;287&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/0zez9/btsO5lWaxHz/sL6ks0z7XsN51Vo7KxNvJ0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/0zez9/btsO5lWaxHz/sL6ks0z7XsN51Vo7KxNvJ0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/0zez9/btsO5lWaxHz/sL6ks0z7XsN51Vo7KxNvJ0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F0zez9%2FbtsO5lWaxHz%2FsL6ks0z7XsN51Vo7KxNvJ0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1707&quot; height=&quot;287&quot; data-origin-width=&quot;1707&quot; data-origin-height=&quot;287&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구조에 대한 조언과 함께 은근히 변경해주기를 돌려말해도 해준다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1733&quot; data-origin-height=&quot;679&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bxJj5B/btsO5l9JpPM/YhpLYfe3766FDKPpx0tkk0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bxJj5B/btsO5l9JpPM/YhpLYfe3766FDKPpx0tkk0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bxJj5B/btsO5l9JpPM/YhpLYfe3766FDKPpx0tkk0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbxJj5B%2FbtsO5l9JpPM%2FYhpLYfe3766FDKPpx0tkk0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1733&quot; height=&quot;679&quot; data-origin-width=&quot;1733&quot; data-origin-height=&quot;679&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;얘도 날 칭찬해준다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1695&quot; data-origin-height=&quot;209&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/duZQd3/btsO55SwsJt/lp3kTtKV3wVqU6pyszme11/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/duZQd3/btsO55SwsJt/lp3kTtKV3wVqU6pyszme11/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/duZQd3/btsO55SwsJt/lp3kTtKV3wVqU6pyszme11/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FduZQd3%2FbtsO55SwsJt%2Flp3kTtKV3wVqU6pyszme11%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1695&quot; height=&quot;209&quot; data-origin-width=&quot;1695&quot; data-origin-height=&quot;209&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;추가 요구사항도 말해본다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1657&quot; data-origin-height=&quot;395&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lB1Hg/btsO688A0Z4/kcaiExGvFDNKj7HCOyaH8K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lB1Hg/btsO688A0Z4/kcaiExGvFDNKj7HCOyaH8K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lB1Hg/btsO688A0Z4/kcaiExGvFDNKj7HCOyaH8K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlB1Hg%2FbtsO688A0Z4%2FkcaiExGvFDNKj7HCOyaH8K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1657&quot; height=&quot;395&quot; data-origin-width=&quot;1657&quot; data-origin-height=&quot;395&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지적하면 또 귀신같이 원인을 파악해서 고친다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1739&quot; data-origin-height=&quot;504&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/5HsNO/btsO67u4E2l/eL8ZU7fGr3P1eRBL2YKma0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/5HsNO/btsO67u4E2l/eL8ZU7fGr3P1eRBL2YKma0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/5HsNO/btsO67u4E2l/eL8ZU7fGr3P1eRBL2YKma0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F5HsNO%2FbtsO67u4E2l%2FeL8ZU7fGr3P1eRBL2YKma0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1739&quot; height=&quot;504&quot; data-origin-width=&quot;1739&quot; data-origin-height=&quot;504&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 몇몇 핑퐁을 거치긴 했지만 나는 요구사항 전달과 코드리뷰한 것만으로도 새로운 기능을 얻게 되었다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;결과물&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;수행한 commit: &lt;a href=&quot;https://github.com/joostory/holybible/commit/2679783dd1e37a55e046652ca38a0517636f5eaf&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://github.com/joostory/holybible/commit/2679783dd1e37a55e046652ca38a0517636f5eaf&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1878&quot; data-origin-height=&quot;587&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ekESCz/btsO5dw8rGh/sJW8rU97LkdNy7RUkv9kxk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ekESCz/btsO5dw8rGh/sJW8rU97LkdNy7RUkv9kxk/img.png&quot; data-alt=&quot;gemini agent 사용 요약&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ekESCz/btsO5dw8rGh/sJW8rU97LkdNy7RUkv9kxk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FekESCz%2FbtsO5dw8rGh%2FsJW8rU97LkdNy7RUkv9kxk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1878&quot; height=&quot;587&quot; data-origin-width=&quot;1878&quot; data-origin-height=&quot;587&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;gemini agent 사용 요약&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;vibe코딩&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 걸 vibe코딩이라고 하는거겠지? 요구사항을 툭툭 던지고 개발은 ai가 하고 나는 그저 검토만 하는 것. ai가 코딩을 한다고 해서 개발자가 할 일이 없어지는 것은 아닌 것 같다. 내가 모르는 코드에 대해서 ai가 개발을 해준다고 했을때 나는 아무런 조언을 할 수가 없었을 것이다. 이 작업은 나도 익숙하게 할 수 있는 작업이고 한눈에 작업상황 파악, 코드리뷰가 가능했기때문에 무리없이 가능했던 것 같다. (내가 모르는 분야에 대해서도 이렇게 한번 해보면 확실히 알 수 있겠지.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어쨌든 이번 기회에 ai로 개발하는 것이 어떤 것인지 잘 알았고 ai는 훌륭한 개발동료가 될 수 있다는 생각이 들었다. 자주 보자. gemini.&lt;/p&gt;</description>
      <category>Dev</category>
      <category>gemini-cli</category>
      <category>vibe코딩</category>
      <author>Joo</author>
      <guid isPermaLink="true">https://blog.joostory.net/626</guid>
      <comments>https://blog.joostory.net/626#entry626comment</comments>
      <pubDate>Sun, 6 Jul 2025 10:17:04 +0900</pubDate>
    </item>
    <item>
      <title>Ubuntu grub 복구</title>
      <link>https://blog.joostory.net/625</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;갑자기 Ubuntu로 부팅이 되지 않는 문제가 생겼다. 먼저 내 상황을 설명하자면... 오래 전에 고장나버린 노트북이 고장나서 거기서 SSD를 뽑아두었다. 그걸 게임하려고 산 노트북에 넣어서 우분투를 쓰고 싶을때 사용하고 있었다.&lt;/p&gt;
&lt;pre id=&quot;code_1732421517246&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/dev/nvmen1n1 - Windows
- /dev/nvmen1n1p1 : Windows Boot Manager (UEFI partition)
- /dev/nvmen1n1p2
- /dev/nvmen1n1p3 : Windows
- /dev/nvmen1n1p4
/dev/nvmen0n1 - Ubuntu
- /dev/nvmen0n1p1 : Ubuntu&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 상태다. Windows의 부트매니저가 window, ubuntu중 선택하도록 하고 ubuntu의 grub이 다시 뭘로 부팅할지 물어보는 두번에 걸친 과정을 거친다. 우분투는 어찌되었든 메인이 아니고 기본값을 윈도우로 두고 싶어서였다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;첫번째 문제 - grub 진입 안됨&lt;/h3&gt;
&lt;pre id=&quot;code_1732421740321&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Failed to open \EFI\UBUNTU\grubx64.efi - Not Found  
Failed to load image \EFI\UBUNTU\grubx64.efi: Not Found    
start_image() returned Not Found&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;윈도우 부트매니저에서 우분투를 선택하면 이런 메시지만 나오고 더이상 진행이 되지 않았다. 이건 윈도우 업데이트를 할 때 생길 수 있는 문제라고 했다. 그리고 EFI/UBUNTU 에 grubx64.efi 라는 것을 복사만 하면 해결된다고 했다. 실제로 이게 맞다. 하지만 나는 여기서 고생을 많이 했는데 왜냐하면 저 복사해야할 디렉토리가 어디인지를 못찾았기 때문이다. 지금은 알고 있어서 허탈하지만 몇시간을 고생한지 모르겠다.&lt;/p&gt;
&lt;figure id=&quot;og_1732421996069&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Failed to open \EFI\BOOT\grubx64.efi - Not Found (Dual Boot Ubuntu with Windows 10)&quot; data-og-description=&quot;Background I have a Windows 10 machine with a SSD where I have installed Ubuntu LTS 20.04. This setup worked wonderfully for months. When I turn my machine on I get to choose which operative system...&quot; data-og-host=&quot;askubuntu.com&quot; data-og-source-url=&quot;https://askubuntu.com/questions/1356544/failed-to-open-efi-boot-grubx64-efi-not-found-dual-boot-ubuntu-with-windows&quot; data-og-url=&quot;https://askubuntu.com/questions/1356544/failed-to-open-efi-boot-grubx64-efi-not-found-dual-boot-ubuntu-with-windows&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bFEGqJ/hyXzMYjibZ/CicUOWp01eclutT52Mj5b0/img.png?width=316&amp;amp;height=316&amp;amp;face=0_0_316_316&quot;&gt;&lt;a href=&quot;https://askubuntu.com/questions/1356544/failed-to-open-efi-boot-grubx64-efi-not-found-dual-boot-ubuntu-with-windows&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://askubuntu.com/questions/1356544/failed-to-open-efi-boot-grubx64-efi-not-found-dual-boot-ubuntu-with-windows&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bFEGqJ/hyXzMYjibZ/CicUOWp01eclutT52Mj5b0/img.png?width=316&amp;amp;height=316&amp;amp;face=0_0_316_316');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Failed to open \EFI\BOOT\grubx64.efi - Not Found (Dual Boot Ubuntu with Windows 10)&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Background I have a Windows 10 machine with a SSD where I have installed Ubuntu LTS 20.04. This setup worked wonderfully for months. When I turn my machine on I get to choose which operative system...&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;askubuntu.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 문서에 설명한 것처럼 우분투 설치 usb같은 것으로 부팅한 후에 UEFI 파티션의 디렉토리에 복사를 하면 된다. 그 UEFI 파티션은 바로 윈도우 부트매니저가 있는 곳을 말한다. 그러니까 나의 경우는 /dev/nvme1n1p1 이다. 이걸 이해 못해서 너무 고생했다. 심지어 다시 설치하려고 usb 메모리까지 구매했었다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;두번째 문제 - grub console&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 grub으로 진입은 했지만 문제가 있었다. grub 메뉴가 안나오고 console만 나오는거다. grub 환경설정을 정상적으로 불러오지 못하는 것 같았다. grub... 을 진작에 좀 공부해서 알고 있었으면 좋았으련만 그동안 직접 설정을 만지거나하지를 않아서 몰랐다. 이제 어떻게 해야하는지를...&lt;/p&gt;
&lt;figure id=&quot;og_1732422375658&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;Classic SysAdmin: How to Rescue a Non-booting GRUB 2 on Linux - Linux Foundation&quot; data-og-description=&quot;Once upon a time we had legacy GRUB, the Grand Unified Linux Bootloader version 0.97. Learn how to rescue a non-booting GRUB 2 on Linux.&quot; data-og-host=&quot;www.linuxfoundation.org&quot; data-og-source-url=&quot;https://www.linuxfoundation.org/blog/blog/classic-sysadmin-how-to-rescue-a-non-booting-grub-2-on-linux&quot; data-og-url=&quot;https://www.linuxfoundation.org/blog/blog/classic-sysadmin-how-to-rescue-a-non-booting-grub-2-on-linux&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/cEHzUc/hyXDeFzvrI/qTS7aHGCFCiv5SA842Dtf1/img.jpg?width=1200&amp;amp;height=628&amp;amp;face=0_0_1200_628,https://scrap.kakaocdn.net/dn/buDeGP/hyXDhoLN9D/v57HRIZ7pgiTiVFnUkVFEk/img.jpg?width=1200&amp;amp;height=628&amp;amp;face=0_0_1200_628,https://scrap.kakaocdn.net/dn/eSaawY/hyXDdzTtSm/Gvm5jh3lQFOTR0dIqkQR60/img.jpg?width=550&amp;amp;height=282&amp;amp;face=0_0_550_282&quot;&gt;&lt;a href=&quot;https://www.linuxfoundation.org/blog/blog/classic-sysadmin-how-to-rescue-a-non-booting-grub-2-on-linux&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.linuxfoundation.org/blog/blog/classic-sysadmin-how-to-rescue-a-non-booting-grub-2-on-linux&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/cEHzUc/hyXDeFzvrI/qTS7aHGCFCiv5SA842Dtf1/img.jpg?width=1200&amp;amp;height=628&amp;amp;face=0_0_1200_628,https://scrap.kakaocdn.net/dn/buDeGP/hyXDhoLN9D/v57HRIZ7pgiTiVFnUkVFEk/img.jpg?width=1200&amp;amp;height=628&amp;amp;face=0_0_1200_628,https://scrap.kakaocdn.net/dn/eSaawY/hyXDdzTtSm/Gvm5jh3lQFOTR0dIqkQR60/img.jpg?width=550&amp;amp;height=282&amp;amp;face=0_0_550_282');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Classic SysAdmin: How to Rescue a Non-booting GRUB 2 on Linux - Linux Foundation&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Once upon a time we had legacy GRUB, the Grand Unified Linux Bootloader version 0.97. Learn how to rescue a non-booting GRUB 2 on Linux.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.linuxfoundation.org&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여러가지 방법이 제시되는데 나에게는 이 방법으로 해결이 되었다.&lt;/p&gt;
&lt;pre id=&quot;code_1732422466562&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;gt; ls
(hd0) (hd0,gpt1) (hd1) (hd1,gpt1) (hd1,gpt2) (hd1,gpt3)
&amp;gt; set prefix=(hd0,gpt1)/boot/grub
&amp;gt; set root=(hd0,gpt1)
&amp;gt; insmod linux
&amp;gt; insmod normal
&amp;gt; normal&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이것으로 며칠동안 고생하며 보지 못했던 우분투의 화면을 만났다. 그리고 이 설정은 저장되는 것이 아니라서 매번 이렇게 실행을 해야하는데 다시 grub의 설정을 정상적으로 복구하려면 우분투로 부팅한 후에 update-grub을 실행하면 된다.&lt;/p&gt;
&lt;pre id=&quot;code_1732422553114&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ sudo update-grub&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우분투를 새로 다시 설치해야하나 고민도 하고 너무 괴로웠는데 다행히 해결되었다. ㅠㅠ 정말 다행이다.&lt;/p&gt;</description>
      <category>잡담</category>
      <author>Joo</author>
      <guid isPermaLink="true">https://blog.joostory.net/625</guid>
      <comments>https://blog.joostory.net/625#entry625comment</comments>
      <pubDate>Sun, 24 Nov 2024 13:30:29 +0900</pubDate>
    </item>
    <item>
      <title>@types/axios deprecated</title>
      <link>https://blog.joostory.net/624</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;오랜동안 업데이트하지 않았던 fe 프로젝트의 라이브러리를 최신화하는 작업을 했는데 이상한게 보였다. @types/axios를 0.14.0 버전을 사용하고 있는데 0.9.36이 최신버전이라며 업데이트를 하라는거다. 업데이트 가능 목록에 계속 나오는게 싫어서 별차이 있겠나 싶어 0.9.36으로 재설치를 했다. 그랬더니 axios를 사용하는 모든 부분에서 에러가 발생하기 시작했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한참을 이랬다 저랬다 하다가 npm 사이트에 들어가서야 발견했다. axios 자체에서 type을 제공하니 0.14.x 를 deprecated 시켜버렸던 것이다. 아마도 이렇게 잘못 설치하도록 해서 사용하면 안된다는 것을 알게해주려고 이렇게 한 것 같다는 생각이다. 물론 이걸 찾기 전까지는 조금 짜증났지만...&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2388&quot; data-origin-height=&quot;1744&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/9VjiR/btsKM4PYxhD/E1RtH8v9lCQcKklYkVhENK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/9VjiR/btsKM4PYxhD/E1RtH8v9lCQcKklYkVhENK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/9VjiR/btsKM4PYxhD/E1RtH8v9lCQcKklYkVhENK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F9VjiR%2FbtsKM4PYxhD%2FE1RtH8v9lCQcKklYkVhENK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2388&quot; height=&quot;1744&quot; data-origin-width=&quot;2388&quot; data-origin-height=&quot;1744&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Dev</category>
      <author>Joo</author>
      <guid isPermaLink="true">https://blog.joostory.net/624</guid>
      <comments>https://blog.joostory.net/624#entry624comment</comments>
      <pubDate>Sun, 17 Nov 2024 09:13:44 +0900</pubDate>
    </item>
    <item>
      <title>pyenv 설정</title>
      <link>https://blog.joostory.net/623</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;python3이면 다 똑같은 줄 알았는데 3.10, 3.11, 3.12, 3.13까지 조금 다른 부분이 있었다. 이미 만들어진 어떤 모듈을 사용하려고 보니 python 3.13에서는 동작하지 않았다. 뭔가가 바뀌었다보다. 그래서 여러가지 버전의 python을 사용할 수 있도록 pyenv을 사용하려고 한다. 현재 맥OS에는 기본적으로 python3.11.1이 설치되어 있다. 기본 버전은 그대로 두고 pyenv로 원하는 python을 설치해서 사용하도록 설정했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 &lt;a href=&quot;https://github.com/pyenv/pyenv?tab=readme-ov-file&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;pyenv&lt;/a&gt;를 설치해야한다. 여러가지 방법이 있는데 homebrew로 설치하기로 했다.&lt;/p&gt;
&lt;pre id=&quot;code_1731494410082&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;❯ brew install pyenv&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;pyenv만 설치하면 설치된 python은 없는 상태다. python 3.11.10을 설치하려면 homebrew처럼 install 만 하면 된다.&lt;/p&gt;
&lt;pre id=&quot;code_1731494532874&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;❯ pyenv install 3.11.10

❯ pyenv versions
  system
* 3.11.10 (set by /Users/joo.yoon/.pyenv/version)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데 이렇게만 하면 python의 경로를 찾지 못한다. PATH에 추가를 해줘야 한다.&lt;/p&gt;
&lt;pre id=&quot;code_1731494586299&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;export PATH=&quot;/opt/homebrew/bin:$HOME/.bin:$PATH&quot;
export PATH=&quot;$(pyenv root)/shims:$PATH&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;주의할 점은 homebrew로 설치한 pyenv를 실행해서 경로를 찾아야 하기 때문에 homebrew를 PATH에 넣은 후 다시 한번 PATH를 만들어야 한다는 것이다. 이렇게 하면 pyenv로 설정한 python을 사용할 수 있게 된다.&lt;/p&gt;
&lt;pre id=&quot;code_1731494875281&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;❯ python --version
Python 3.11.10

❯ pyenv versions
  system
* 3.11.10 (set by /Users/joo.yoon/.pyenv/version)
  3.13.0

❯ pyenv global 3.13.0

❯ python --version
Python 3.13.0&lt;/code&gt;&lt;/pre&gt;</description>
      <category>Dev</category>
      <author>Joo</author>
      <guid isPermaLink="true">https://blog.joostory.net/623</guid>
      <comments>https://blog.joostory.net/623#entry623comment</comments>
      <pubDate>Wed, 13 Nov 2024 19:53:39 +0900</pubDate>
    </item>
    <item>
      <title>MacOS java 설치</title>
      <link>https://blog.joostory.net/622</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;회사에서는 java를 많이 쓰지만 집에선 거의 java를 쓰지 않는다. 그래도 ubuntu나 mac에는 기본으로 설치가 되어 있으니 그냥 썼는데 최근 mac에는 java가 없다. 그래서 설치하면서 설치방법을 정리해본다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;다운로드&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단 openjdk를 설치하려고 하는데 어디서 설치를 해야하는지 찾아봤다. 먼저 &lt;a href=&quot;https://openjdk.org/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;openjdk 웹사이트&lt;/a&gt;에서 시작했다. 다운로드 하려면 jdk.java.net으로 가라고 한다. 지금은 23이 GA 상태지만 가장 최근 버전인 것 같고 &lt;a href=&quot;https://jdk.java.net/archive/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;archive 페이지&lt;/a&gt;에 모든 버전이 다 있다. lts 버전인 21이랑 23을 써보기로 한다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;설치&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;mac에서는 /usr/libexec/java_home 을 통해서 java 위치를 결정한다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1731104306556&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;❯ /usr/libexec/java_home
The operation couldn&amp;rsquo;t be completed. Unable to locate a Java Runtime.
Please visit http://www.java.com for information on installing Java.&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 java_home은 /Library/Java/JavaVirtualMachines 에서 사용할 jvm을 선택한다.&lt;/p&gt;
&lt;pre id=&quot;code_1731104544545&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/Library/Java/JavaVirtualMachines 
❯ ls -l
total 0
drwxr-xr-x@ 3 joo.yoon  staff  96 12  8  2021 jdk-17.0.2.jdk
drwxr-xr-x@ 3 joo.yoon  staff  96  1  6  2024 jdk-21.0.2.jdk
drwxr-xr-x@ 3 joo.yoon  staff  96  9 30 22:25 jdk-23.0.1.jdk&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;굉장히 편하게 디렉토리에 넣어두기만 하면 java_home이 알아서 경로를 찾는다.&lt;/p&gt;
&lt;pre id=&quot;code_1731104691068&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;❯ /usr/libexec/java_home -v 17
/Library/Java/JavaVirtualMachines/jdk-17.0.2.jdk/Contents/Home

❯ /usr/libexec/java_home -v 21
/Library/Java/JavaVirtualMachines/jdk-21.0.2.jdk/Contents/Home

❯ /usr/libexec/java_home -v 23
/Library/Java/JavaVirtualMachines/jdk-23.0.1.jdk/Contents/Home&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 원하는 java 버전을 선택하는 일만 남았다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;사용&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본으로 가장 최근 버전을 선택하나 JAVA_HOME을 지정하면 버전이 변경된다. shell에서는 .zshrc 같은 곳에서 원하는 java 버전을 선택해서 사용하면 된다.&lt;/p&gt;
&lt;pre id=&quot;code_1731104815876&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;❯ java -version
openjdk version &quot;23.0.1&quot; 2024-10-15
OpenJDK Runtime Environment (build 23.0.1+11-39)
OpenJDK 64-Bit Server VM (build 23.0.1+11-39, mixed mode, sharing)

❯ echo $JAVA_HOME

❯ export JAVA_HOME=`/usr/libexec/java_home -v 17`

❯ echo $JAVA_HOME
/Library/Java/JavaVirtualMachines/jdk-17.0.2.jdk/Contents/Home

❯ java -version
openjdk version &quot;17.0.2&quot; 2022-01-18
OpenJDK Runtime Environment (build 17.0.2+8-86)
OpenJDK 64-Bit Server VM (build 17.0.2+8-86, mixed mode, sharing)&lt;/code&gt;&lt;/pre&gt;</description>
      <category>Dev</category>
      <category>java</category>
      <author>Joo</author>
      <guid isPermaLink="true">https://blog.joostory.net/622</guid>
      <comments>https://blog.joostory.net/622#entry622comment</comments>
      <pubDate>Sat, 9 Nov 2024 07:30:28 +0900</pubDate>
    </item>
    <item>
      <title>Ubuntu 24.10, 20주년 버전</title>
      <link>https://blog.joostory.net/621</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;Ubuntu의 20주년 버전인 24.10이 나왔다. 24.04 버전이 lts라서 라이브러리 몇개 업그레이드하고 넘어갈 수도 있는데 이번엔 20주년이라서 뭔가 많다.&lt;/p&gt;
&lt;figure id=&quot;og_1728692923559&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;Ubuntu 24.10 is Now Available to Download&quot; data-og-description=&quot;Ubuntu 24.10 is now available for download after six months of dedicated development. The latest release offers plenty of changes and new features,&quot; data-og-host=&quot;www.omgubuntu.co.uk&quot; data-og-source-url=&quot;https://www.omgubuntu.co.uk/2024/10/ubuntu-24-10-now-available-to-download&quot; data-og-url=&quot;https://www.omgubuntu.co.uk/2024/10/ubuntu-24-10-now-available-to-download&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bJ4iDa/hyXhRwUB4g/hzXQ7x0RvLdAMTMeuV1Huk/img.jpg?width=1920&amp;amp;height=1008&amp;amp;face=0_0_1920_1008,https://scrap.kakaocdn.net/dn/ClCEb/hyXd8G52SJ/ejzkjkNbJOXSOfYNwNWum0/img.jpg?width=1920&amp;amp;height=1080&amp;amp;face=0_0_1920_1080,https://scrap.kakaocdn.net/dn/dyDB4q/hyXd36QYPZ/4GRPi2utp8njSgSCWaSHs0/img.jpg?width=840&amp;amp;height=473&amp;amp;face=0_0_840_473&quot;&gt;&lt;a href=&quot;https://www.omgubuntu.co.uk/2024/10/ubuntu-24-10-now-available-to-download&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.omgubuntu.co.uk/2024/10/ubuntu-24-10-now-available-to-download&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bJ4iDa/hyXhRwUB4g/hzXQ7x0RvLdAMTMeuV1Huk/img.jpg?width=1920&amp;amp;height=1008&amp;amp;face=0_0_1920_1008,https://scrap.kakaocdn.net/dn/ClCEb/hyXd8G52SJ/ejzkjkNbJOXSOfYNwNWum0/img.jpg?width=1920&amp;amp;height=1080&amp;amp;face=0_0_1920_1080,https://scrap.kakaocdn.net/dn/dyDB4q/hyXd36QYPZ/4GRPi2utp8njSgSCWaSHs0/img.jpg?width=840&amp;amp;height=473&amp;amp;face=0_0_840_473');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Ubuntu 24.10 is Now Available to Download&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Ubuntu 24.10 is now available for download after six months of dedicated development. The latest release offers plenty of changes and new features,&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.omgubuntu.co.uk&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;제일 눈에 띄는건 아무래도 20주년 기념 이미지인데 부트화면에도 이 이미지가 들어가고 20주년을 기념한 wallpaper에도 들어갔다. 10년 단위 로고를 보니 정말 감회가 새롭다. 조금씩 변해왔는데 그래도 처음의 형태를 거의 그대로 유지하고 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kPg8a/btsJ20a3Tfm/fb0OOPA7Hkg8IzwPOZgII0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kPg8a/btsJ20a3Tfm/fb0OOPA7Hkg8IzwPOZgII0/img.png&quot; data-is-animation=&quot;false&quot; data-origin-width=&quot;3840&quot; data-origin-height=&quot;2160&quot; data-filename=&quot;Ubuntu_Legacy_by_Aaron_J_Prisk_dark.png&quot; style=&quot;width: 49.4186%; margin-right: 10px;&quot; data-widthpercent=&quot;50&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kPg8a/btsJ20a3Tfm/fb0OOPA7Hkg8IzwPOZgII0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkPg8a%2FbtsJ20a3Tfm%2Ffb0OOPA7Hkg8IzwPOZgII0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;3840&quot; height=&quot;2160&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/zyNjp/btsJ4gcBHyC/dfcke0OU4HKkubMpOkMGVk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/zyNjp/btsJ4gcBHyC/dfcke0OU4HKkubMpOkMGVk/img.png&quot; data-origin-width=&quot;7680&quot; data-origin-height=&quot;4320&quot; data-is-animation=&quot;false&quot; data-filename=&quot;Warty_remastered_by_Romactu.png&quot; style=&quot;width: 49.4186%;&quot; data-widthpercent=&quot;50&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/zyNjp/btsJ4gcBHyC/dfcke0OU4HKkubMpOkMGVk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FzyNjp%2FbtsJ4gcBHyC%2Fdfcke0OU4HKkubMpOkMGVk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;7680&quot; height=&quot;4320&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;버전이 올라가면 대부분 바로 업데이트를 하는 편인데 이번엔 업데이트하고나서 너무 좋았다. 가장 좋았던 점은 디스플레이 지원이 좋아졌다는거다. 30인치 모니터를 4k로 쓰면서 125%로 쓰는게 적당하고 좋았는데 이게 제대로 동작을 안하다가 이번 버전에서는 잘 동작한다. 게다가 멀티스크린 상황에서도 문제가 없었다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-10-12 09-18-01.png&quot; data-origin-width=&quot;860&quot; data-origin-height=&quot;587&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bzuoxg/btsJ4pAqnAR/MRLiNTX7o7ZvcFw0dKanAk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bzuoxg/btsJ4pAqnAR/MRLiNTX7o7ZvcFw0dKanAk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bzuoxg/btsJ4pAqnAR/MRLiNTX7o7ZvcFw0dKanAk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbzuoxg%2FbtsJ4pAqnAR%2FMRLiNTX7o7ZvcFw0dKanAk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;860&quot; height=&quot;587&quot; data-filename=&quot;스크린샷 2024-10-12 09-18-01.png&quot; data-origin-width=&quot;860&quot; data-origin-height=&quot;587&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데스크탑 리눅스의 가장 큰 문제가 별거 아닌거 같지만 소소한 설정들이 제대로 동작을 안하는 경우가 있는 건데 이번엔 대부분의 기능이 별다른 문제없이 동작한다. 이런걸로 좋아해야하나 싶긴하지만 그래도 좋은 건 좋은 거니까... 한동안은 또 이걸 기본으로 써야겠다.&lt;/p&gt;</description>
      <category>Dev</category>
      <category>ubuntu</category>
      <author>Joo</author>
      <guid isPermaLink="true">https://blog.joostory.net/621</guid>
      <comments>https://blog.joostory.net/621#entry621comment</comments>
      <pubDate>Sat, 12 Oct 2024 09:42:48 +0900</pubDate>
    </item>
    <item>
      <title>오랜만에 블로그 스킨 관리</title>
      <link>https://blog.joostory.net/620</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;블로그를 한동안 안쓰다가 다시 써볼까 싶어서 들어왔더니 서비스들이 이것저것 바뀌어 있었다. 티스토리는... 크게 바뀐건 없지만 내부적으로 약간씩 디테일이 달라졌다. 텀블러는 충격적이게도 커스텀 도메인이 유료화되었다. 그리고 테마 변수에 조금 변경이 있다. NPF 가 추가되었다. 아무래도 javascript로 컨트롤하는 테마들이 많아서 추가된 것 같다. 하는김에 summary, 대표이미지 같은 것도 좀 해주지 그런건 아직도 없다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어쨌거나 이제 어디다가 글을 쓰나 고민을 하다가 joo.joohana.net은 그대로 살리고 예전에 개발관련 내용을 쓰려고 했던 지금은 joo-yoon.tumblr.com이 된 곳은... 버리기로 했다. 너무 황당하게도 텀블러엔 이제 코드블럭이 안된다. 모바일과의 통일성을 위해서 과감하게 버린 것 같다. 그럼 이제 변화를 따라갈 시간이다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;텀블러 summary&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;텀블러에는 말했듯 리스트에서 사용할 대표이미지, summary에 대한 변수를 제공하지 않는다. 그런데 이번에 NPF 변수가 생겼으니 javascript로 이걸 사용하면 되겠구나 싶었다. npf는 &lt;a href=&quot;https://github.com/tumblr/docs/blob/master/npf-spec.md&quot;&gt;docs/npf-spec.md at master &amp;middot; tumblr/docs (github.com)&lt;/a&gt; 에 설명이 되어 있는데 실제로 내려오는 값을 보니 content의 image 타입중 첫번째를 대표이미지로, content의 text 타입 중 subtype이 없는 것을 summary로 사용하면 될 것 같았다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1726581657849&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function makeSummaryFromNpf(contentId, npf) {
  let content = &quot;&quot;
  const img = npf.content.find(it =&amp;gt; it.type == 'image')
  if (img) {
    let imgSrc = img['media'][1]['url']
    content = &quot;&amp;lt;div class='npf_row'&amp;gt;&amp;lt;div class='npf_col'&amp;gt;&amp;lt;img src='&quot; + imgSrc + &quot;' /&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;/div&amp;gt;&quot;
  }

  const summary = npf.content.find(it =&amp;gt; it['type'] == 'text' &amp;amp;&amp;amp; !it['subtype'])
  if (summary) {
    let text = summary['text']
    if (text.length &amp;gt; 100) {
      text = text.substr(0, 100) + &quot;...&quot;
    }
    content += &quot;&amp;lt;p&amp;gt;&quot; + text + &quot;&amp;lt;/p&amp;gt;&quot;
  }

  document.getElementById(contentId).innerHTML = content
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1726582053422&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;{block:IndexPage}
&amp;lt;div id=&quot;summary-{PostId}&quot; class=&quot;post-text&quot; style=&quot;margin-bottom: 15px&quot;&amp;gt;&amp;lt;/div&amp;gt;
&amp;lt;script&amp;gt;
    const contentId = &quot;summary-{PostId}&quot;
    makeSummaryFromNpf(contentId, {NPF});
&amp;lt;/script&amp;gt;
{/block:IndexPage}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;적당히 만들어보니 그럴듯하게 만들어지는 것 같아서 요정도로만 하기로 했다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;티스토리 댓글&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;티스토리는 크게 달라진 점이 없어서 그냥 놔두려다가 아무래도 커스텀 도메인에서의 댓글이 너무 이상해서 이걸 좀 바꿔보고 싶었다. 일단 티스토리 댓글은 못쓴다. 그래서 다시 한번 disqus를 써볼까 했는데 disqus는 역시 무료플랜에서는 광고가 너무너무너무 많이 나와서 부담스럽다. 누가 댓글을 잘 쓰지도 않는데 혹시나 하고 달아둔 댓글에 돈을 내기도 뭣하고 그렇다고 광고가 한 화면 가득 나오는건 참을 수가 없었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대체재를 찾아봤는데 결국 &lt;a href=&quot;https://utteranc.es/&quot;&gt;utterances&lt;/a&gt; 와 &lt;a href=&quot;https://giscus.app/ko&quot;&gt;giscus&lt;/a&gt; 로 돌아가게 되었다. 이 둘의 문제는 github repo가 필요하다는 것인데 다행히 여러 사이트를 한 곳에서 관리할 수 있는 옵션이 가능했다. 카테고리별로 웹사이트를 관리할 수 있다. 그래서 그동안 쓰던 repo에서 사용하기로 했다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;간단했지만 오랜만에 또 보다보니 익숙해지는데 시간도 필요해서 약간은 시간이 걸렸다. 일단락되었으니 이제 글을 쓰는 일만 남았다. 공부한 것, 읽은 책, 영화 등등 잘 써봐야겠다.&lt;/p&gt;</description>
      <category>Dev</category>
      <category>블로그</category>
      <author>Joo</author>
      <guid isPermaLink="true">https://blog.joostory.net/620</guid>
      <comments>https://blog.joostory.net/620#entry620comment</comments>
      <pubDate>Tue, 17 Sep 2024 23:28:05 +0900</pubDate>
    </item>
    <item>
      <title>Tauri 체험</title>
      <link>https://blog.joostory.net/619</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;Rust 좋다좋다 이야기만 들었지 써볼 기회가 없었는데 electron이랑 비슷한 느낌으로 개발이 가능한게 있다고 해서 체험을 해보았다. 이름은 &lt;a href=&quot;https://tauri.app/ko/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;tauri&lt;/a&gt; 다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;828&quot; data-origin-height=&quot;666&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kLuYo/btsys6fWfvy/UoKO0jnHNSrpiyRgKHPzRK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kLuYo/btsys6fWfvy/UoKO0jnHNSrpiyRgKHPzRK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kLuYo/btsys6fWfvy/UoKO0jnHNSrpiyRgKHPzRK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkLuYo%2Fbtsys6fWfvy%2FUoKO0jnHNSrpiyRgKHPzRK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;828&quot; height=&quot;666&quot; data-origin-width=&quot;828&quot; data-origin-height=&quot;666&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;설치는 하라는대로 하면 되긴했는데 아무래도 ubuntu에서 하다보니 한방에 설치가 되지는 않았다. gtk관련해서 라이브러리 설치가 필요한게 몇개 필요했다. 설치과정에서 필요한 라이브러리를 확인하고 알아서 설치해주는 그런 친절함은 없었다. 어쨌든 설치해서 실행하면 요런 sample UI를 보여준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드 구조는 UI와 앱으로 나뉘어 있다. src에는 UI 관련코드, src-tauri 에는 앱을 관리하는 rust 코드가 들어있다. electron이 main process, renderer process로 나뉘어있는 것과 비슷하다. ui도 rust로 만들수 있다고는 하는데 일단 웹이다. rust로 웹UI, 그러니까 webgl 같은걸로 사용하는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;잠시 코드를 살펴보니 rust로는 tauri command를 handler로 등록하고..&lt;/p&gt;
&lt;pre id=&quot;code_1697379222785&quot; class=&quot;rust&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;#[tauri::command]
fn hello(name: &amp;amp;str) -&amp;gt; String {
    format!(&quot;Hello, {}!&quot;, name)
}

tauri::Builder::default()
        .invoke_handler(tauri::generate_handler![hello])&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;javascript로는 이걸 invoke라는 것으로 사용하는 방식이다. electron에서는 어떻게 했더라 ;;; 까먹었는데 event를 주고받는 방식이었던 것 같은데 어쨌든 여긴 이렇게 한다.&lt;/p&gt;
&lt;pre id=&quot;code_1697379380662&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const { invoke } = window.__TAURI__.tauri;

let greetInputEl;
let greetMsgEl;

async function hello() {
  greetMsgEl.textContent = await invoke(&quot;hello&quot;, {
    name: greetInputEl.value
  })
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;뭘 더 해보고 싶어도 rust를 아직 모르는 상태라 뭘 더 해볼 수가 없다. 그래서 체험은 일단 여기서 끝!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아! 결국 UI는 브라우저와 같은 상태인 것이라서 확인해보니 Chromium이나 Chrome은 아니고 Webkit 자체를 가져다쓴다. 그래서 뭔가 safari 느낌이 난다. 진짜 체험 끝. 담에 기운이 또 생기면 더 파봐야지.&lt;/p&gt;</description>
      <category>Dev</category>
      <category>Rust</category>
      <category>Tauri</category>
      <author>Joo</author>
      <guid isPermaLink="true">https://blog.joostory.net/619</guid>
      <comments>https://blog.joostory.net/619#entry619comment</comments>
      <pubDate>Sun, 15 Oct 2023 23:19:45 +0900</pubDate>
    </item>
    <item>
      <title>대형마트 의무규제 폐지</title>
      <link>https://blog.joostory.net/618</link>
      <description>&lt;p&gt;&lt;iframe src=&quot;https://www.youtube.com/embed/hDSw7K4awoU?feature=oembed&quot; width=&quot;560&quot; height=&quot;315&quot; frameborder=&quot;&quot; allowfullscreen=&quot;true&quot;&gt;&lt;/iframe&gt;&lt;/p&gt;
&lt;p&gt;대형마트 근처의 소상공인을 보호하기 위해 대형마트에게 의무휴업을 강제한 이 정책은 박근혜 정부가 어처구니없이 만든 규제정책이라고 생각한다. 몇몇 곳은 대형마트가 나머지 상권을 죽이기도 했겠지. 하지만 대형마트가 무슨 동네마다 있는 것도 아니고 대부분의 사람들은 차를 타고 갈텐데 몇몇 사례를 가지고서 전체에 적용하는 말도 안되는 정책이라고 생각한다.&lt;/p&gt;
&lt;p&gt;만약 이 정책이 효과가 있었다면 분명히 얼마나 효과가 있었는지 대형마트와 그 상권의 매출변화를 비교해가며 분명히 리포트가 발표되었을 것이다. 이런것을 안했을리가 없다. 하지만 그런 리포트는 본 적이 없고, 오히려 쿠팡이나 마켓컬리같은 마트를 대체하는 당일배송, 로켓배송 업체만 더 커졌다는 뉴스만 본 것 같다.&lt;/p&gt;
&lt;p&gt;대형마트, 시장 모두 손해인데다 심지어 소비자인 나같은 사람에게도 손해다. 내가 사는 곳 주변에는 재래시장이 전혀 없다. 아파트 단지 사이 상가에 자그마한 야채가게와 반찬가게, 정육점이 있을 뿐이다. 심지어 일요일에는 모두 문을 닫는다. 대형마트에서만 장을 볼 수 있다. 제법 큰 규모의 마트가 있긴한데 대부분 대형마트의 분점같은 것들이어서 이들도 모두 대형마트 규제에 영향을 받는다. (홈플러스 익스프레스, GS 마트 등)&lt;/p&gt;
&lt;p&gt;이 정책때문에 나는 격주 일요일에는 어떤 곳에서도 장을 볼 수 없는 상태가 된다. 이제는 익숙해져서 미리미리 준비를 하는데 초반에는 격주로 찾아오는 이 공백이 너무나 당황스러웠다. 일요일에 장볼 생각에 토요일까지 모든 재료를 소진했는데 일요일이 되니 아무 것도 살 수 없어서 어쩔 수 없이 규제에 영향을 받지 않는 백화점 식품관에서 장을 봤다. (와... 비싸더라)&lt;/p&gt;
&lt;p&gt;불평을 하자면 끝도 없으니 이쯤에서 정리하면 1. 의도했던 효과가 없고, 2. 소비자를 불편하게 하는 이 정책은 폐지를 진작에 했어야 했다고 본다. 그런데 뉴스를 보니 반대하는 의견이 몇몇 소개된다.&lt;/p&gt;
&lt;p&gt;여전히 전통시장에 도움이 된다는 의견이다. 만약 이 것이 사실이라면 난 그 동네만 전통시장을 위해 휴업을 하도록 하면 된다고 생각한다. 왜 우리 동네같이 상관없는 곳도 영향을 받아야 하는지 이해할 수 없다. 그리고 말만 그렇게 하지말고 데이터를 좀 제시하면 좋겠다.&lt;/p&gt;
&lt;p&gt;두번째는 대형마트 근로자의 휴식 보장을 위해 휴업이 필요하다는 의견이다. 이건 이해할 수 있다. 그러나 방법이 그것뿐인가? 정부가 해야할 일은 휴업을 해라마라가 아니라 근로자의 근로여건 개선을 관리 감독해야한다고 생각한다. 휴업을 하던지 말던지 모르겠지만 휴업을 할 때와 같은 수준으로 근로자 휴식권을 보장하라는 요구를 해야한다. 그 결과로서 휴업이 결정된다면 어쩔 수 없겠지만 그게 아니라면 굳이 휴업을 할 이유는 없다고 본다.&lt;/p&gt;
&lt;p&gt;아무쪼록 이 정책의 폐지도 부드럽게 좀 진행되면 좋겠다. 서로 의견을 듣고 데이터를 비교해가며 서로에게 이익이 되는 방향으로 나가면 좋겠다. 그런데 안타깝게도 그런걸 못하는 정부다. 박근혜도 윤석열도... 한숨난다.&lt;/p&gt;</description>
      <category>잡담</category>
      <author>Joo</author>
      <guid isPermaLink="true">https://blog.joostory.net/618</guid>
      <comments>https://blog.joostory.net/618#entry618comment</comments>
      <pubDate>Thu, 28 Jul 2022 23:09:16 +0900</pubDate>
    </item>
    <item>
      <title>tinymce 6</title>
      <link>https://blog.joostory.net/617</link>
      <description>&lt;p&gt;tinymce 4에서 5까지는 상당히 시간이 걸렸던 것 같은데 최근에 6버전이 나왔다. 5가 나온지 3년만이다. 새로운 버전이 나온 걸 알았으니 바로 적용해주는게 좋겠다는 생각이 들었다. tinymce 관련 프로덕트들에 묵혀둔 보안 이슈들도 이참에 해결을 해야겠다는 생각이었다.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.tiny.cloud/docs/tinymce/6/migration-from-5x/&quot;&gt;Migrating from TinyMCE 5 to TinyMCE 6 | TinyMCE Documentation&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;DomQuery&lt;/h2&gt;
&lt;p&gt;변경 중에서 가장 영향이 큰 부분이다. &lt;code&gt;editor.$('#id').addClass(&quot;selected&quot;)&lt;/code&gt;와 같이 jQuery와 비슷한 방식의 dom처리가 가능했는데 이제 사용할 수 없다. &lt;code&gt;editor.dom: DomUtils&lt;/code&gt; 을 사용해서 직접 html element에 접근해야한다. &lt;code&gt;editor.dom.addClass(editor.dom.select('#id', node), 'selected')&lt;/code&gt; 이런 식이다. 아무래도 커스터마이징을 할때 가장 많이 쓰게 되는 기능인데 약간은 귀찮다.&lt;/p&gt;
&lt;p&gt;어쩌면 이제 ie11지원을 드롭했으니 굳이 이런 래핑이 필요없다는 뜻일지도 모른다. 사실 대부분의 프론트엔드 분기는 ie를 위한 것이었다. 크롬이나 파이어폭스의 분기는 특수한 경우만 제외하면 없는거나 마찬가지다. editor.dom도 사실 쓰지 않아도 될 것 같은데 혹시나 몰라서 썼다. 저것마다 deprecated되면 그때 바꿔야지.&lt;/p&gt;
&lt;h2&gt;Plugin Option&lt;/h2&gt;
&lt;p&gt;tinymce를 init할때 option을 넘겨주는데 이때 plugin에서 사용할 값도 같이 넘겨주고 plugin에서 사용하는 경우가 있다.&amp;nbsp;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;tinymce.init({
  codeblock_theme: 'material-darker',
  opengraph: {
  	fetch_handler: () =&amp;gt; { ... }
  }
})&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;이런 식으로 설정하는데 사용할때는 &lt;code&gt;editor.settings.codeblock_theme&lt;/code&gt;, &lt;code&gt;editor.settings.opengraph.fetch_handler&lt;/code&gt; 와 같이 &lt;code&gt;editor.settings&lt;/code&gt;에서 바로 빼서 사용했다. 그런데 이게 완전히 바뀌었다. 사용할 option을 등록하고 그 후에 사용할 수 있다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;javascript&quot;&gt;editor.options.register(&quot;codeblock_theme&quot;, {
  processor: 'string',
  default: 'default'
})

const theme = editor.options.get(&quot;codeblock_theme&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;options.register로 등록, options.get으로 빼서 쓴다. 편리한 점은 default 값을 설정해서 귀찮은 null 처리를 안해도 된다는 점이다. 다만 opengraph.fetch_handler와 같이 flat하지 않은 경우 processor를 object로 하고 settings를 쓸 때처럼 null 처리를 해줘야한다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;javascript&quot;&gt;const DEFAULT_OPTIONS = {
  fetch_handler: () =&amp;gt; {}
}

let options = null

export function registerOptions(editor) {
  const register = editor.options.register
  register('opengraph', {
    processor: 'object',
    default: DEFAULT_OPTIONS
  })
}

export function getOption(editor, key) {
  if (!options) {
    options = editor.options.get('opengraph')
  }
  return options[key] || DEFAULT_OPTIONS[key]
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;안타깝게도 이 부분에 대해선 별다른 가이드문서가 없다. 알아서 찾아서 해결해야한다. &lt;a href=&quot;https://www.tiny.cloud/docs/tinymce/6/creating-a-plugin/&quot;&gt;Create a plugin for TinyMCE | TinyMCE Documentation&lt;/a&gt; 에는 간단한 생성 예제만 있다. editor.options는 EditorOptions다. &lt;a href=&quot;https://www.tiny.cloud/docs/tinymce/6/apis/tinymce.editoroptions/&quot;&gt;tinymce.EditorOptions | TinyMCE Documentation&lt;/a&gt; 를 참고해서 적절히 사용해보면 된다. 유료화를 하는 상황에서 너무 자세한 가이드 공개는 자신들에게 좋지 않다고 생각한 것 같다.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;다른 부분을 별로 사용하지 않아서 이 정도이지 만약 좀 더 많은 기능을 사용했다면 그만큼 더 많은 부분을 수정해야할 것 같다. 플러그인 2개와 에디터 내부 플러그인 하나를 수정했다. 아! 그리고 플러그인 없어진 것이 몇개 있고 이름 바뀐 것이 좀 있었다. style도 조금 바뀌고. 뭐 그런건 차차 더 알아보기로 하자.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/joostory/tinymce-plugin-opengraph/compare/v2.0.8...v3.0.1&quot;&gt;Comparing v2.0.8...v3.0.1 &amp;middot; joostory/tinymce-plugin-opengraph (github.com)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/joostory/tinymce-plugin-codeblock/compare/v2.3.1...v3.0.2&quot;&gt;Comparing v2.3.1...v3.0.2 &amp;middot; joostory/tinymce-plugin-codeblock (github.com)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/joostory/tistory-editor/compare/v1.5.0...v1.6.0&quot;&gt;Comparing v1.5.0...v1.6.0 &amp;middot; joostory/tistory-editor (github.com)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;그러고보니 tinymce로 만들던 keditor는 어떻게 되었는지 문득 궁금하다. 아직 4버전을 쓰고 있을텐데... 언젠간 이걸 버리고 자체적으로 개발을 할지도 모르겠다.&lt;/p&gt;</description>
      <category>Dev</category>
      <category>tinymce</category>
      <author>Joo</author>
      <guid isPermaLink="true">https://blog.joostory.net/617</guid>
      <comments>https://blog.joostory.net/617#entry617comment</comments>
      <pubDate>Sun, 1 May 2022 22:22:34 +0900</pubDate>
    </item>
  </channel>
</rss>