<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>나에게 남기는 지식</title>
    <link>https://smallgiant.tistory.com/</link>
    <description>Baby steps to giant strides</description>
    <language>ko</language>
    <pubDate>Fri, 10 Jul 2026 22:00:17 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>작은 거인</managingEditor>
    <item>
      <title>Nuxt 3는 현재 시점에서 프로덕트 수준으로 사용할만 할까?</title>
      <link>https://smallgiant.tistory.com/108</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;최근 Nuxt 3가 정식 버전이 공개됐다. rc7쯤부터인가, 개인 영문 블로그를 만들려고 계속 테스트해오고 있었는데, 여전히 불안정한 부분이 있는것 같다. 그래서 결론부터 먼저 말하자면, 현 시점에 프로덕트 수준으로 사용하는 것은 No다. &lt;span style=&quot;color: #9d9d9d;&quot;&gt;필자는 지금 개인 영문 블로그를 Nuxt3로 운영중이기 때문에 불가능하다는 이야기는 아니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개인적으로 생각하는 이유는 많지만, 너무 주관적이라는 생각이 들어서 딱 하나만 짚어보려고 한다. Vue3 생테계 자체가 불안정하다는 점이다. 2020년 9월 19일, 원피스라는 이름으로 Vue3가 공개된 뒤 장기간에 걸쳐 Vue2에서 Vue3로 생태계가 바뀌어 왔음에도, 정식 버전으로 Vue3가 채택되기 전까지 이를 지원하지 않는 라이브러리가 꽤 많았다. &lt;span style=&quot;color: #9d9d9d;&quot;&gt;지원했더라도, 발생한 이슈를 적극적으로 대처하는 라이브러리가 많지 않았다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;왜 그랬을까 뇌피셜을 굴려보자면, 프론트엔드 개발 기조가 SPA에서 SSR 지원으로 옮겨가면서 Next, Nuxt, Svelte kit등 SSR 프레임워크로 개발하는 사람들이 많아지다보니, Nuxt가 Vue3를 지원하지 않는 시점에 굳이 일을 만들어서 할필요가 없던 것이 아닐까 생각해본다. 현재로 넘어와서, Vue3가 이전부터 갖고 있던 이슈가, 활발히 사용되기 시작하는 지금에 와서야 알려지다보니 생테계가 전반적으로 불안정하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한가지 예로, Nuxt3로 onMouted()에서 Dom에 접근하는데, nextTick()이 작동을 안해서 undefined가 반환됐다. API가 Vue3에서 바뀌었나 싶어서 찾아보니 Nuxt3가 아닌 upstream 이슈로, &lt;a href=&quot;https://github.com/vuejs/core/issues/5148&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Vue3에서 Suspend+Transition을 사용하면 문제&lt;/a&gt;가 생기는 것이었다. 지금도 해당 이슈로 인해, nextTick()을 사용하는 부분에는 setTimeout()을 사용해서 트랜지션을 사용 유무에 따라 여유 시간을 줘야한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Nuxt2에서 사용하던 공식 라이브러리들도 아직 열심히 개발 단계이거나, 이슈를 묵혀둔채 Nuxt3쪽으로 인력이 몰려있는 것으로 보인다. 덕분에 블로그 개발하다가 몇번을 '그냥 만들어진 플랫폼 써야겠다'라고 생각하며 도망갔는지 기억이 나지 않는다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;816&quot; data-origin-height=&quot;705&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bt4ERf/btrTaB1TPuv/QOy0nNZHdMIQR5gcgjffw0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bt4ERf/btrTaB1TPuv/QOy0nNZHdMIQR5gcgjffw0/img.png&quot; data-alt=&quot;주요 라이브러리 로드맵&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bt4ERf/btrTaB1TPuv/QOy0nNZHdMIQR5gcgjffw0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbt4ERf%2FbtrTaB1TPuv%2FQOy0nNZHdMIQR5gcgjffw0%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;816&quot; height=&quot;705&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;816&quot; data-origin-height=&quot;705&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;주요 라이브러리 로드맵&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;물론 필자와 달리, 이슈 자체에 대해 내성이 강한 개발자들은 본인이 직접 개발해서 대처할 수 있으니 크게 관련없는 이야기일 수 있다. 필자는 휘몰아치는 프론트엔드 기술 폭풍속에서 '이게 Vite 문제인지, Nuxt3 문제인지, Vue3문제인지' 파악하는 과정이 너무도 고통스럽기 때문에, 공감하는 개발자가 있다면 &lt;span&gt;당분간은 Nuxt2 기반으로 프로젝트를 진행하되, Nuxt3 변경점은 계속 주시하라고 권하고 싶다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사례가 많지는 않은데, Svelte로 넘어가는 사례가 보여서 이를 공부하고 정리해보고자 한다.&lt;/p&gt;</description>
      <author>작은 거인</author>
      <guid isPermaLink="true">https://smallgiant.tistory.com/108</guid>
      <comments>https://smallgiant.tistory.com/108#entry108comment</comments>
      <pubDate>Fri, 9 Dec 2022 12:14:34 +0900</pubDate>
    </item>
    <item>
      <title>스프링 네이티브 이미지를 사용해봤다.</title>
      <link>https://smallgiant.tistory.com/107</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;최근, 스프링 부트 3 버전이 출시됐다. 메이저 버전이 바뀐 만큼 다양한 변화가 있겠지만 그 중에서도 AOT 엔진을 사용한 스프링 네이티브 이미지가 가장 많이 언급되는 것 같다. 공식 문서에 따르면, 네이티브 이미지를 사용하는 것은 빠른 시작, 준수한 성능, 그리고 메모리 사용량 감소와 같은 장점을 제공한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;새 프로젝트에 적용이 가능할 정도인가 싶어, 바로 테스트를 해봤다.&lt;br /&gt;내 환경은 아래와 같다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;M1 Mac&lt;/li&gt;
&lt;li&gt;Graalvm CE 19&lt;/li&gt;
&lt;li&gt;Gradle&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;어떤 방법으로 네이티브 이미지를 빌드할까?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스프링 네이티브 이미지를 빌드하는 방법에는 두 가지가 있다. 하나는 도커 이미지를 사용하는 것, 다른 하나는 Graalvm을 통해 바이너리 파일을 직접 빌드하는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;도커를 사용하면 간단하겠지만, 신기술의 경우 내가 개발하는 환경에서는 작동하지 않는 경우가 생각보다 많아서 도커 없이도 쉽게 사용가능한지 직접 바이너리 파일을 빌드해서 테스트해봤다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;GraalVM 설치&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;IntelliJ에서 Graalvm 다운로드를 제공하기에 다른 특별한 설정없이 다운로드 받기만 했다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;install graalvm.png&quot; data-origin-width=&quot;778&quot; data-origin-height=&quot;537&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/NwifX/btrTefJwBhF/SDP0kRvjBR9ftMqhNCc3Ik/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/NwifX/btrTefJwBhF/SDP0kRvjBR9ftMqhNCc3Ik/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/NwifX/btrTefJwBhF/SDP0kRvjBR9ftMqhNCc3Ik/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FNwifX%2FbtrTefJwBhF%2FSDP0kRvjBR9ftMqhNCc3Ik%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;778&quot; height=&quot;537&quot; data-filename=&quot;install graalvm.png&quot; data-origin-width=&quot;778&quot; data-origin-height=&quot;537&quot;/&gt;&lt;/span&gt;&lt;/figure&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;IntelliJ를 통해 Spring boot 3 간단한 프로젝트를 생성했다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;create springboot3 project.png&quot; data-origin-width=&quot;811&quot; data-origin-height=&quot;648&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/brIo8u/btrTbVZkaHR/YjTXSJIooBiNkcdiiE5WLk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/brIo8u/btrTbVZkaHR/YjTXSJIooBiNkcdiiE5WLk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/brIo8u/btrTbVZkaHR/YjTXSJIooBiNkcdiiE5WLk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbrIo8u%2FbtrTbVZkaHR%2FYjTXSJIooBiNkcdiiE5WLk%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;811&quot; height=&quot;648&quot; data-filename=&quot;create springboot3 project.png&quot; data-origin-width=&quot;811&quot; data-origin-height=&quot;648&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;달리 설정할 것이 없이, 바로 빌드해봤다. 바이너리 파일로 빌드하려면 gradle에서 &lt;code&gt;nativeCompile&lt;/code&gt; task를 실행하면 된다. 비교를 위해 executable jar도 빌드했다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;역시 한번에 빌드가 되지는 않는다.&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;nativeCompile&lt;/code&gt; 테스크에서 Graalvm을 찾지 못하고, &lt;code&gt;Cannot query the value of property 'javaLauncher' because it has no value available.&lt;/code&gt;&lt;br /&gt;에러가 발생했다. 이 &lt;a href=&quot;https://github.com/spring-projects-experimental/spring-native/issues/1655&quot;&gt;Github Issue&lt;/a&gt;를 보니 JAVA_HOME이 설정되지 않아서 발생한 문제로 보여서, Run/Debug Configuration에서 설정한 뒤에는 빌드가 잘 됐다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;set JAVA_HOME.png&quot; data-origin-width=&quot;1049&quot; data-origin-height=&quot;394&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b5fPDg/btrTbUF5OPE/a21p1RwvbsuZ5IEHr82gK1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b5fPDg/btrTbUF5OPE/a21p1RwvbsuZ5IEHr82gK1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b5fPDg/btrTbUF5OPE/a21p1RwvbsuZ5IEHr82gK1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb5fPDg%2FbtrTbUF5OPE%2Fa21p1RwvbsuZ5IEHr82gK1%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;1049&quot; height=&quot;394&quot; data-filename=&quot;set JAVA_HOME.png&quot; data-origin-width=&quot;1049&quot; data-origin-height=&quot;394&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;빌드하는데만 약 3분 17초 정도 소요됐다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;환경변수 말고 다른 방법이 없을까?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Run/Debug Configuration에서 환경변수를 설정하게 되면, 테스트를 돌려야해서 실행 환경을 바꾸게 되면 또 다시 설정해줘야 하고 사소한 일로도 해당 설정이 지워질수 있다. 또한 같은 프로젝트를 공유하는 사람들에게 같은 실수를 방지하기 위해서 이 이슈가 있음을 &lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;반드시 &lt;/span&gt;공유해야 하는 점이 불편하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Gradle로 처리할 수 있는 방법이 있나 찾아보니,&lt;a href=&quot;https://graalvm.github.io/native-build-tools/latest/gradle-plugin.html#configuration-toolchains&quot;&gt; Native build plugin 문서&lt;/a&gt;에서 설명하는 toolchain 설정하니, 환경변수 없이도 작동했다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;gradle graalvm native plugin setting.png&quot; data-origin-width=&quot;712&quot; data-origin-height=&quot;484&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bZI0SD/btrS9PTE0Qp/FDLtrSYRezsJZPxhnS0hE0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bZI0SD/btrS9PTE0Qp/FDLtrSYRezsJZPxhnS0hE0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bZI0SD/btrS9PTE0Qp/FDLtrSYRezsJZPxhnS0hE0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbZI0SD%2FbtrS9PTE0Qp%2FFDLtrSYRezsJZPxhnS0hE0%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;712&quot; height=&quot;484&quot; data-filename=&quot;gradle graalvm native plugin setting.png&quot; data-origin-width=&quot;712&quot; data-origin-height=&quot;484&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;테스트 결과&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;summary-jar.png&quot; data-origin-width=&quot;632&quot; data-origin-height=&quot;187&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dKPIBR/btrTeNlN4xh/4zhOGwwNIJnI09MBUZkkY0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dKPIBR/btrTeNlN4xh/4zhOGwwNIJnI09MBUZkkY0/img.png&quot; data-alt=&quot;Jar 패키지 실행 결과&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dKPIBR/btrTeNlN4xh/4zhOGwwNIJnI09MBUZkkY0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdKPIBR%2FbtrTeNlN4xh%2F4zhOGwwNIJnI09MBUZkkY0%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;632&quot; height=&quot;187&quot; data-filename=&quot;summary-jar.png&quot; data-origin-width=&quot;632&quot; data-origin-height=&quot;187&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Jar 패키지 실행 결과&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;summary-native.png&quot; data-origin-width=&quot;637&quot; data-origin-height=&quot;138&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/EJzP1/btrS7JlBMFR/kVx6CFiQ3XmHEp6GOob711/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/EJzP1/btrS7JlBMFR/kVx6CFiQ3XmHEp6GOob711/img.png&quot; data-alt=&quot;네이티브 이미지 실행 결과&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/EJzP1/btrS7JlBMFR/kVx6CFiQ3XmHEp6GOob711/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FEJzP1%2FbtrS7JlBMFR%2FkVx6CFiQ3XmHEp6GOob711%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;637&quot; height=&quot;138&quot; data-filename=&quot;summary-native.png&quot; data-origin-width=&quot;637&quot; data-origin-height=&quot;138&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;네이티브 이미지 실행 결과&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Image size comparison.png&quot; data-origin-width=&quot;752&quot; data-origin-height=&quot;128&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/tpQq6/btrS9qlR1ek/L7bE1M4E8psGQXlxAOoP90/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/tpQq6/btrS9qlR1ek/L7bE1M4E8psGQXlxAOoP90/img.png&quot; data-alt=&quot;빌드 결과물 사이즈&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/tpQq6/btrS9qlR1ek/L7bE1M4E8psGQXlxAOoP90/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FtpQq6%2FbtrS9qlR1ek%2FL7bE1M4E8psGQXlxAOoP90%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;752&quot; height=&quot;128&quot; data-filename=&quot;Image size comparison.png&quot; data-origin-width=&quot;752&quot; data-origin-height=&quot;128&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;빌드 결과물 사이즈&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Startup time은 약 5.5배 감소했고 메모리 사용량은 약 4배 감소했으며, 용량의 경우 약 3.6배 증가했다. 여러 블로그를 보면 이미지 사이즈가 감소한다고 하던데, 도커 이미지 이야기인건지 아니면 내가 뭘 잘못한지 모르겠다. 생각해보면 native 빌드할때 byte code metadata나, JVM 없이 자체 실행이 가능하게 하는 유틸리티 등이 포함됨을 고려하면 용량이 커지는게 이상하진 않은 것 같다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;정리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음 프로젝트부터 적용해볼 예정인데 한가지, Golang처럼 환경변수로 크로스 플랫폼 빌드를 할 수 없는게 솔직히 많이 아쉽다. 그러나 도커로 대체할 수 있고, 바이너리 빌드시에는 Github action에서 OS를 선택해서 빌드하면 배포 OS에도 맞출 수 있으니 사용하는데는 무리가 없을 것 같다.&lt;/p&gt;</description>
      <category>GraalVM</category>
      <category>native image</category>
      <category>Spring</category>
      <author>작은 거인</author>
      <guid isPermaLink="true">https://smallgiant.tistory.com/107</guid>
      <comments>https://smallgiant.tistory.com/107#entry107comment</comments>
      <pubDate>Fri, 9 Dec 2022 11:04:39 +0900</pubDate>
    </item>
    <item>
      <title>nuxt.js: vue packages version mismatch</title>
      <link>https://smallgiant.tistory.com/105</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;배경&lt;/h2&gt;
&lt;p&gt;git에서 샘플 프로젝트를 복사해서 인스톨 했는데, 완료는 됐으나 오류가 검출되 audit fix로 수정.&lt;/p&gt;
&lt;p&gt;이후 프로젝트를 실행했더니, 아래와 같이 버전이 일치하지 않는 오류가 발생.&lt;/p&gt;
&lt;pre id=&quot;code_1581568827406&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;  - vue@2.6.10
  - vue-server-renderer@2.6.11&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;해결&lt;/h2&gt;
&lt;p&gt;아래 커맨드로 패키지 관련 파일 삭제 후 다시 인스톨.&lt;/p&gt;
&lt;pre id=&quot;code_1581569000008&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;rm -rf node_modules/ package-lock.json
npm i&lt;/code&gt;&lt;/pre&gt;</description>
      <author>작은 거인</author>
      <guid isPermaLink="true">https://smallgiant.tistory.com/105</guid>
      <comments>https://smallgiant.tistory.com/105#entry105comment</comments>
      <pubDate>Thu, 13 Feb 2020 13:44:17 +0900</pubDate>
    </item>
    <item>
      <title>Spring Boot Test 에서 yml 읽어오기</title>
      <link>https://smallgiant.tistory.com/104</link>
      <description>&lt;p&gt;&lt;span&gt;@SpringBootTest&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;properties &lt;/span&gt;= &lt;span&gt;{&lt;/span&gt;&lt;span&gt;&quot;spring.config.location=classpath:application-test.yml&quot;&lt;/span&gt;&lt;span&gt;})&lt;/span&gt;&lt;/p&gt;</description>
      <author>작은 거인</author>
      <guid isPermaLink="true">https://smallgiant.tistory.com/104</guid>
      <comments>https://smallgiant.tistory.com/104#entry104comment</comments>
      <pubDate>Fri, 3 Jan 2020 15:41:18 +0900</pubDate>
    </item>
    <item>
      <title>내가 사용하는 live template</title>
      <link>https://smallgiant.tistory.com/103</link>
      <description>&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-style=&quot;style9&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 30.6976%;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;abbreviation&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 69.3024%;&quot;&gt;&lt;b&gt;Template text&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 30.6976%;&quot;&gt;assertthat&lt;/td&gt;
&lt;td style=&quot;width: 69.3024%;&quot;&gt;org.assertj.core.api.Assertions.assertThat($END$);&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 30.6976%;&quot;&gt;assertthrows&lt;/td&gt;
&lt;td style=&quot;width: 69.3024%;&quot;&gt;org.junit.jupiter.api.Assertions.assertThrows($EXCEPTION$.class,&lt;span style=&quot;color: #333333;&quot;&gt;&amp;nbsp;()&amp;nbsp;-&amp;gt;&amp;nbsp;$END$);&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 30.6976%;&quot;&gt;tdd&lt;/td&gt;
&lt;td style=&quot;width: 69.3024%;&quot;&gt;@org.junit.jupiter.api.Test&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #333333;&quot;&gt;public void $methodName$() throws Exception {&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//given&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$END$&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//when&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//then&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #333333;&quot;&gt;}&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 30.6976%;&quot;&gt;todo&lt;/td&gt;
&lt;td style=&quot;width: 69.3024%;&quot;&gt;
  &lt;span style=&quot;color: #333333;&quot;&gt;// TODO $DATE$ $END$ $USER$&lt;/span&gt;&lt;br&gt;
&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;DATE와 USER 변수는 Edit variables에서 각각 expression을 date()와 user()로 한다.&lt;/span&gt;&lt;/span&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 30.6976%;&quot;&gt;when&lt;/td&gt;
&lt;td style=&quot;width: 69.3024%;&quot;&gt;org.mockito.Mockito.when($WHEN$).thenReturn($RETURN$);&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.25em;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;등록 순서&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;1. abbreviation 입력(실제 템플릿을 불러올 명령어)&lt;/p&gt;
&lt;p&gt;2. Template text에 입력될 내용 작성&lt;/p&gt;
&lt;p&gt;3. application context Define 눌러서 해당 템플릿을 사용 가능한 app 환경 설정.&lt;/p&gt;
&lt;p&gt;4. use static import of possible 체크. (2번에서 패키지명을 풀로 입력하면 알아서 import 시켜줌)&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>IDE/IntelliJ</category>
      <author>작은 거인</author>
      <guid isPermaLink="true">https://smallgiant.tistory.com/103</guid>
      <comments>https://smallgiant.tistory.com/103#entry103comment</comments>
      <pubDate>Wed, 1 Jan 2020 20:45:40 +0900</pubDate>
    </item>
    <item>
      <title>생성자 주입 사용시 순환 참조가 발생할 때</title>
      <link>https://smallgiant.tistory.com/101</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;배경&lt;/h2&gt;
&lt;p&gt;스프링 커뮤니티에서 필드 주입보다는 생성자 주입을 권장하기 때문에 생성자 주입을 아무런 생각없이 쓰고 있었다. 그런데 오늘 jwt 토이 프로젝트를 하다가 순환 참조가 발생해서 해당 내용을 기록한다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;문제&lt;/h2&gt;
&lt;pre id=&quot;code_1577541119790&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;   jwtRequestFilter defined in file [xx\IdeaProjects\study\simple_shopping_mall\out\production\classes\com\ssmallgiant\simple_shopping_mall\filter\JwtRequestFilter.class]
┌─────┐
|  memberService defined in file [xx\IdeaProjects\study\simple_shopping_mall\out\production\classes\com\ssmallgiant\simple_shopping_mall\service\MemberService.class]
&amp;uarr;     &amp;darr;
|  securityConfig defined in file [xx\IdeaProjects\study\simple_shopping_mall\out\production\classes\com\ssmallgiant\simple_shopping_mall\config\SecurityConfig.class]
└─────┘&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;위와 같은 순환참조 에러가 발생해서 코드를 다시 보니, jwtRequestFilter와 securityConfig 에서 memberService를 사용하는데, memberService에서는 또 securityConfig에 정의한 passwordEncoder를 사용해서 생성자 주입이 순환참조가 되고 있었다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;해결&lt;/h2&gt;
&lt;p&gt;jwtRequestFilter와 securityConfig의 생성자에서 memberService 파라미터 앞에 @Lazy를 붙여 해결했다. 이 어노테이션은 빈 초기화 시점에는 프록시를 주입하고, 처음 실행될 때 진짜 객체를 주입한다고 한다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;ps. memberService에 어노테이션을 붙인 이유는, 이 클래스가 온전히 빈이 된 시점에서 다른 곳에 주입이 되야 한다고 생각해 가장 사이드 이펙트가 적을 것으로 예상되는 빈에 작업한 것.&lt;/p&gt;</description>
      <category>Java/Spring</category>
      <author>작은 거인</author>
      <guid isPermaLink="true">https://smallgiant.tistory.com/101</guid>
      <comments>https://smallgiant.tistory.com/101#entry101comment</comments>
      <pubDate>Sat, 28 Dec 2019 23:03:37 +0900</pubDate>
    </item>
    <item>
      <title>SpringBoot2 + jdk 11 + gradle. NoClassDefFoundError 뜰 때</title>
      <link>https://smallgiant.tistory.com/99</link>
      <description>&lt;pre id=&quot;code_1574303193320&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;implementation 'javax.xml.bind:jaxb-api'
implementation 'org.glassfish.jaxb:jaxb-runtime'
implementation 'javax.activation:activation:1.1.1'&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;위 의존성을 추가하면 기능함.&lt;/p&gt;</description>
      <author>작은 거인</author>
      <guid isPermaLink="true">https://smallgiant.tistory.com/99</guid>
      <comments>https://smallgiant.tistory.com/99#entry99comment</comments>
      <pubDate>Thu, 21 Nov 2019 11:27:01 +0900</pubDate>
    </item>
    <item>
      <title>Putty 자동 로그인</title>
      <link>https://smallgiant.tistory.com/98</link>
      <description>&lt;h1&gt;Putty 자동 로그인&lt;/h1&gt;
&lt;ol&gt;
&lt;li&gt;인증키 생성&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;ssh-keygen -t rsa&lt;/code&gt;&lt;/pre&gt;
접속한 계정의 홈 경로의 .ssh 에 생성됨.  &lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;생성할때 passpharse를 입력하면 자동 로그인이 안됨!!!&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;ex) /home/me/.ssh/&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;&lt;p&gt;공개키의 이름을 authorized_keys로 바꿔줌. (백업 목적으로 복사를 추천)&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;cp id_rsa.pub authorized_keys&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;로컬에 개인키를 복사, puttygen으로 load.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Save private key를 누르면, 아래와 같은 비번이 없는데 괜찮냐는 경고 메시지 뜨고 &lt;code&gt;예&lt;/code&gt;를 눌러 ppk 파일을 저장하고 완료.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Are you sure you want ot save this key without a passpharse protect it?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;putty에서 Connection&amp;gt;Data 에서 Auto-login username에 유저명 입력&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Connection&amp;gt;SSH&amp;gt;Auth에서 private key file for authertication 항목에 아까 저장한 ppk 파일을 지정.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;제일 중요한 저장!&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;끝&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;</description>
      <category>Linux</category>
      <author>작은 거인</author>
      <guid isPermaLink="true">https://smallgiant.tistory.com/98</guid>
      <comments>https://smallgiant.tistory.com/98#entry98comment</comments>
      <pubDate>Fri, 8 Nov 2019 10:27:44 +0900</pubDate>
    </item>
    <item>
      <title>classpath 접두사에 관한 간단한 정리</title>
      <link>https://smallgiant.tistory.com/97</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;배경&lt;/h2&gt;
&lt;p&gt;&lt;b&gt;스프링 프레임워크 기준&lt;/b&gt;으로 resources 경로에 있는 파일들에 접근할 때 classpath라는 키워드를 사용하곤 하는데, 전부터 이게 뭔지 궁금했다. 우연히 해당 내용에 대해 정리되있는 블로그를 알게되 해당 내용과 실제 프로젝트를 빌드해서 비교해봤다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;본문&lt;/h2&gt;
&lt;p&gt;classpath가 가리키는 경로부터 말하자면 빌드된 &lt;b&gt;classes&lt;/b&gt; 경로를 가리킨다. 그렇다면, classes 경로를 가리키는데 어떻게 개발시 resources 밑에 있던 파일들이 불러와 질까?&lt;/p&gt;
&lt;p&gt;war나 jar로 빌드되면 resources 경로 하위에 있던 파일들이 WEB-INF\classes 밑으로 이동하게 된다.&lt;/p&gt;
&lt;p&gt;bootJar나 bootWar를 이용하면 비슷하지만 BOOT-INF\classes 밑으로 이동한 것으로 확인된다.&lt;/p&gt;</description>
      <category>Java/Spring</category>
      <author>작은 거인</author>
      <guid isPermaLink="true">https://smallgiant.tistory.com/97</guid>
      <comments>https://smallgiant.tistory.com/97#entry97comment</comments>
      <pubDate>Wed, 6 Nov 2019 09:28:49 +0900</pubDate>
    </item>
    <item>
      <title>https 사용시 ajax 처리할 때 http로 요청하면 문제점.</title>
      <link>https://smallgiant.tistory.com/96</link>
      <description>&lt;h2&gt;환경&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;hr&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p&gt;모든 http 8080 요청을 https 8443으로 리다이렉트&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2&gt;문제 상황&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;hr&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p&gt;기존 뷰 템블릿 코드를 수정하기 귀찮아서 기존과 똑같이 http 8080 포트로 &lt;span style=&quot;color: #333333;&quot;&gt;ajax 요청을 하&lt;/span&gt;고 있었다. 당연히 8443으로 리다이렉트 될 줄 알았는데, 이상하게 계속 오류가 발생.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2&gt;해결&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;hr&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p&gt;ajax 요청을 8443으로 해봤더니 정상 작동.&lt;/p&gt;</description>
      <category>Java/Spring</category>
      <author>작은 거인</author>
      <guid isPermaLink="true">https://smallgiant.tistory.com/96</guid>
      <comments>https://smallgiant.tistory.com/96#entry96comment</comments>
      <pubDate>Tue, 9 Jul 2019 21:47:29 +0900</pubDate>
    </item>
  </channel>
</rss>