<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>Jaranun 개발자</title>
    <link>https://sslblog.tistory.com/</link>
    <description></description>
    <language>ko</language>
    <pubDate>Sun, 28 Jun 2026 18:10:25 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>닉Nick</managingEditor>
    <image>
      <title>Jaranun 개발자</title>
      <url>https://tistory1.daumcdn.net/tistory/5171852/attach/ca8dc6179f314acb9636e95824a08f11</url>
      <link>https://sslblog.tistory.com</link>
    </image>
    <item>
      <title>우리 블로그 정상영업합니다... 아니 유튜브</title>
      <link>https://sslblog.tistory.com/225</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&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;최근에 유튜브를 운영하고 있어요. 여러가지 생각들, 공부하는 것들을 나누고 있습니다. 블로그 대신 운영하고 있는 것이죠.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://youtube.com/@aka-nick&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;채널링크&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1702537333092&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;profile&quot; data-og-title=&quot;닉nick&quot; data-og-description=&quot;개발을 꾸준하게 즐기기.&quot; data-og-host=&quot;www.youtube.com&quot; data-og-source-url=&quot;https://youtube.com/@aka-nick&quot; data-og-url=&quot;https://www.youtube.com/channel/UCq4o5oOK6umMRhfdb8NiwyA&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/ttw7B/hyUL0w1NF5/wni0hfXVprhx12tbaJFWZ1/img.jpg?width=900&amp;amp;height=900&amp;amp;face=0_0_900_900,https://scrap.kakaocdn.net/dn/bG10nE/hyULV3yfpm/oC4cAP4zQdPLbr1WoZkA4K/img.jpg?width=900&amp;amp;height=900&amp;amp;face=0_0_900_900&quot;&gt;&lt;a href=&quot;https://youtube.com/@aka-nick&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://youtube.com/@aka-nick&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/ttw7B/hyUL0w1NF5/wni0hfXVprhx12tbaJFWZ1/img.jpg?width=900&amp;amp;height=900&amp;amp;face=0_0_900_900,https://scrap.kakaocdn.net/dn/bG10nE/hyULV3yfpm/oC4cAP4zQdPLbr1WoZkA4K/img.jpg?width=900&amp;amp;height=900&amp;amp;face=0_0_900_900');&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;닉nick&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;개발을 꾸준하게 즐기기.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.youtube.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&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;(작년부터)블로그가 자꾸 다운되어서 불안하기도 했고요. 가끔은 불펌된 글때문에 현타가 오기도 했습니다. 다른 매체로 정보를 공유해보고 싶다는 호기심도 컸네요.&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;굳이 못 해볼 이유도 없으니, 해보고 싶다는 생각이 들었을때 해보자. 그런 생각이었어요.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;재밌게 해보려고요  &lt;/p&gt;</description>
      <author>닉Nick</author>
      <guid isPermaLink="true">https://sslblog.tistory.com/225</guid>
      <comments>https://sslblog.tistory.com/225#entry225comment</comments>
      <pubDate>Thu, 14 Dec 2023 21:59:52 +0900</pubDate>
    </item>
    <item>
      <title>감사하게도 꾸준히 방문해주시는 이웃분들에게</title>
      <link>https://sslblog.tistory.com/223</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;최근에 블로그에 신경을 쓰지 못하고 있어서(그리고 당분간은 계속 그럴 것 같아서)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;꾸준히 방문해주시고, 댓글 남겨 주시는 동료분들께 감사의 인사 겸 연말인사 겸... 아마도 새해인사를 남깁니다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&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;제 블로그 이웃분들이란 함께 공부를 열심히 해주셨던 동료분들이죠&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;함께 해주신 분들이 있어서 여기까지 온 것에 항상 감사하고 있습니다(그만두려는 것 아님)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;매일...까진 솔직히 아니고 매주 한 번 정도씩 한 분 씩 떠올리면서 고마운 마음을 가지고 있습니다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;많은 공부를 배우고, 또 외적으로도 많은 걸 본받을 수 있어서 즐거웠습니다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&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;저도 요즘은 제 블로그에는 가끔 애드센스 광고에 몇 달러나 더 쌓였나 보러 들어오며 체크 하는 정도로만 보고 있습니다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;블로그를 완전히 손 놓으려는 건 아닌데&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 당분간 조금 더 열심히 달릴 예정인 것(그래서 시간이 조금 많이 부족한 것)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 티스토리 블로그 서비스가 계속해서 불안정한 것&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;때문에 포스팅은 개인 에디터에만 낙서처럼 쌓이고 있습니다 개인 공부한 것도 깃헙에 private으로만 정리하고 있고요&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&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;약간 졸려서 횡설수설 했네요&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;갑자기 드는 생각인데, 언제 한 번 뵐 기회가 주어지면 좋겠네요&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이만 줄이겠습니다 우리 존재 화이팅&lt;/p&gt;</description>
      <author>닉Nick</author>
      <guid isPermaLink="true">https://sslblog.tistory.com/223</guid>
      <comments>https://sslblog.tistory.com/223#entry223comment</comments>
      <pubDate>Tue, 5 Sep 2023 23:27:48 +0900</pubDate>
    </item>
    <item>
      <title>no main manifest attribute - Java 어플리케이션 실행 시 메인클래스를 못 찾을 때</title>
      <link>https://sslblog.tistory.com/222</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;간단한 대응 이력&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;간단한 Java 어플리케이션 작성 후 &lt;code&gt;java -jar&lt;/code&gt;로 실행하려고 했더니 'no main manifest attribute'라는 오류와 만났다.&lt;br /&gt;맨날 인텔리제이 안에서만 생활(?)하다 보니 간과하던 사실인데, 생각해보니 엔트리포인트가 어딘지 알려줘야 할 필요가 있었다.&lt;br /&gt;MANIFEST.MF 파일을 작성하든지, 아니면 내가 한 것처럼 build.gradle에 엔트리포인트를 알려줘야 한다.&lt;/p&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;jar {  
  manifest {  
    attributes(  
      'Main-Class': 'org.preonboarding.docker.Main'  
    )  
  }  
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 에러에 관한 키워드를 가지고 구글링 해보면 build.gradle에 작성하면 여전히 &lt;code&gt;ClassNotFoundException&lt;/code&gt;이 발생한다는 글이 많은데, 그건 gradle로 설정이 안되는 거라서가 아니라, 예시가 잘못 작성되어서 그런 것이다(괄호를 빼먹었더라).&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;출처 및 참고문헌&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;'no main manifest attribute' 에러 메시지 : &lt;a href=&quot;https://www.javatpoint.com/no-main-manifest-attribute&quot;&gt;https://www.javatpoint.com/no-main-manifest-attribute&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>이슈핸들링</category>
      <author>닉Nick</author>
      <guid isPermaLink="true">https://sslblog.tistory.com/222</guid>
      <comments>https://sslblog.tistory.com/222#entry222comment</comments>
      <pubDate>Wed, 2 Aug 2023 22:15:41 +0900</pubDate>
    </item>
    <item>
      <title>mysql-server-8.0 설치 후 mysql.service 실행 안됨</title>
      <link>https://sslblog.tistory.com/219</link>
      <description>&lt;h2&gt;서론&lt;/h2&gt;
&lt;p&gt;MySQL에 대해 잘 알고 싶어서 저장해둔 책이 있다. &lt;a href=&quot;https://product.kyobobook.co.kr/detail/S000001766482&quot;&gt;Real MySQL 8.0&lt;/a&gt;이라는 책이다.&lt;br&gt;언젠가는 이 책을 가지고 스터디를 수행해보고 싶은 마음으로, 이 책의 저자분이 만드신 카카오톡 오픈채팅에도 들어가 있다.&lt;/p&gt;
&lt;p&gt;오픈채팅에는 주로 DBA 분들이 많아서 DBMS에 대한 깊은 대화가 주로 오가기 때문에, 사실 내가 알아들을 수 있는 말이 많지는 않다. 그래도 &amp;#39;관련된 키워드에 익숙해지기 위해서&amp;#39;라는 목적으로 계속해서 눈팅을 이어나가고 있긴 하다.&lt;/p&gt;
&lt;p&gt;위와 같은 이유로 눈팅을 이어가고 있던 어느날,  &amp;quot;제발 8.0&amp;quot;을 사용해달라&amp;quot;는 채팅을 읽게 되었다. 깊은 히스토리는 이해하지 못했지만, 대강 이해하기로는 기능 상의 개선이 대폭 이루어졌기 때문에 버전업이 가능한 상황이라면 무조건 8.0 버전을 쓰는게 이득이라는 것이 주 메시지였다. &lt;/p&gt;
&lt;p&gt;당시에는 &amp;#39;음 그렇구나&amp;#39; 정도로 넘어갔었다.&lt;br&gt;오늘은 사이드 프로젝트를 하나 배포하기 위해 서버의 환경을 구성하는 날이었는데, 마침 그 이야기가 떠올랐다. 그래서 &lt;code&gt;sudo apt install mysql-server-core-8.0&lt;/code&gt;을 입력했다.&lt;/p&gt;
&lt;h2&gt;본론&lt;/h2&gt;
&lt;p&gt;그리고 이어서 &lt;code&gt;sudo service mysql start&lt;/code&gt;를 입력했다. 시작이 안되었다.&lt;/p&gt;
&lt;h3&gt;문제 1.  service.mysql is masked&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;Unit mysql.service is masked.&lt;/code&gt;라는 에러 메시지와 함께 실행이 안됐다. mask라는게 무슨 뜻인지 정확히 몰랐지만, 메시지 맥락 상 &amp;#39;mysql 서비스가 실행할 수 없는 상태에 있다&amp;#39;로 해석하면 될 것 같았다.&lt;br&gt;왜지? 지금 막 설치한 건데 왜 닫혀있을까, 그것도 mysql이?&lt;/p&gt;
&lt;p&gt;구글링 해서 쉽게 답을 찾을 수 있었다. 낮은 버전에서 8.0으로 올라가고 있는 중에 생긴 이슈라고 한다. &lt;/p&gt;
&lt;p&gt;언젠가 처리가 되겠지만 그 언젠가를 기다릴 수는 없겠지. 해제를 해주자.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;systemctl unmask mysql.service&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;``&lt;br&gt;이 문제는 간단히 해결.&lt;/p&gt;
&lt;h3&gt;문제2. Job for mysql.service failed because the control process exited with error code.&lt;/h3&gt;
&lt;p&gt;외 게속 않되는대요? 알 수가 없었다. unmask되어있는지 확인해보았는데 그건 확실했다(일단 에러메시지가 이전과 달랐다).&lt;br&gt;이 역시 이유를 알 수는 없었지만 &lt;code&gt;journalctl -xeu mysql.service&lt;/code&gt;라는 걸 입력하면 에러메시지를 자세히 볼 수 있다고 시스템이 안내해줬다. 그래서 읽어보았다.&lt;/p&gt;
&lt;p&gt;service를 시작시키기 위해 내부적으로 여러번 수행했는지 같은 에러메시지가 여러번 반복되어 있었다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;mysql.service: Control process exited, code=exited, status=1/FAILURE&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;음..... 그래... 실패한 건 알겠어. 그런데 왜 실패했는지를 알려주겠니?... 친절하게 알려줬다면 좋았겠지만 위 메시지만 수없이 반복되어 있을 뿐... 해당 메시지로는 찾을 수 있는 게 없었다.&lt;/p&gt;
&lt;p&gt;같은 메시지만 계속 읽으면서 멍을 때리다가 나는 생각했다. &amp;#39;최초로 실패한 부분에는 뭔가 다른 로그가 남아있을지도?&amp;#39;&lt;/p&gt;
&lt;p&gt;스크롤을 올리고 올리고... 올리고 올리고... 또 올리고 올리고...&lt;br&gt;비슷한 메시지가 너무 많아서 다른 오류메시지까지 올라간걸 깨닫고... 내리고 내리고...&lt;br&gt;찾았다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;/etc/init.d/mysql: line 75: /usr/bin/mysqladmin: No such file or directory&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;mysqladmin이라는게 없었다. 이게 뭔 파일인지는 모르겠어서 chatGPT에게 물어봤더니, MySQL의 유틸리티라고 설명해줬다(서버 시작/정지, 사용자 관리, DB관리 등...). 근데 왜 없지? 이것도 &amp;#39;문제1&amp;#39;과 같은 이유인건지... 모르겠지만 어쨌든 해결해주자.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;vi /usr/bin/mysqladmin #만들어주고 저장만 한다.&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;전에 다른 트러블슈팅 포스팅에서, 이것과 동일한 문제는 아니었지만, 어떤 실행파일이 없어서 실행이 안되는 경우에 그냥 파일을 생성만 해줘도 문제가 해결되었다는 문제를 본 기억이 남아있었다.&lt;/p&gt;
&lt;p&gt;그래서 같은 방법을 시도했다. 결과적으로...&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;$ netstat -tnlp
tcp6    0   0    :::3306    :::*    LISTEN    2157/mysqld&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;잘 실행됐다.&lt;/p&gt;
&lt;h2&gt;결론&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;에러 메시지를 잘 보자.&lt;/li&gt;
&lt;li&gt;에러 메시지가 답을 주지 않는다면, 에러 메시지를 더 자세히 보자.&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2&gt;출처 및 참고문헌&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://stackoverflow.com/questions/65092669/failed-to-restart-mysql-service-unit-mysql-service-is-masked-in-ubuntu-20-04-af&quot;&gt;StackOverflow - Unit mysql.service is masked&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>이슈핸들링</category>
      <author>닉Nick</author>
      <guid isPermaLink="true">https://sslblog.tistory.com/219</guid>
      <comments>https://sslblog.tistory.com/219#entry219comment</comments>
      <pubDate>Fri, 28 Jul 2023 17:07:38 +0900</pubDate>
    </item>
    <item>
      <title>리눅스 가상메모리 켜기</title>
      <link>https://sslblog.tistory.com/218</link>
      <description>&lt;h2&gt;내용&lt;/h2&gt;
&lt;hr&gt;
&lt;p&gt;보통 aws 프리티어를 처음 사용해보게 되면 거기에 웹서버도 올리고, 어플리케이션 서버도 돌려보고, rdb도 돌려보고 이것저것 시도하게 된다. 여기까진 괜찮을 수도 있다.&lt;br&gt;하지만 프로젝트를 빌드하거나, 도커를 올리게 되면 100% 멈춰있는 터미널을 만나게 될 것이다.&lt;/p&gt;
&lt;p&gt;메모리 부족 문제다. 가상메모리(swap)를 설정해보자.&lt;/p&gt;
&lt;h3&gt;언제 가상메모리를 구성할까&lt;/h3&gt;
&lt;p&gt;부족할때 하면 된다. 그런데 메모리가 4G 미만이라면, 그냥 기본적으로 해두면 좋다고 생각하면 될 것 같다.&lt;/p&gt;
&lt;h3&gt;메모리 확인하기&lt;/h3&gt;
&lt;p&gt;다음과 같이 해본다&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;free -m&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;실 메모리 정보 밑에 &lt;code&gt;swap 0 0 0&lt;/code&gt; 과 같이 나오면 스왑메모리가 없는 것이다. 만약에 있다면 또 만들 필요는 없다. 여러개의 스왑파일을 만들어놔도 동작하는 데에는 무방하지만, 보통은 그렇게 할 이유가 없기 때문이다.&lt;/p&gt;
&lt;p&gt;그럼에도 계속 진행해보고자 한다면 아래처럼 입력해서 가상메모리의 작동을 멈춰주자.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;swapoff -a&lt;/code&gt;&lt;/pre&gt;&lt;h3&gt;swapfile 생성&lt;/h3&gt;
&lt;p&gt;아래와 같이 입력하면 된다.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;fallocate -l 2G /swapfile&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;위의 구문은 2G 크기의 가상메모리 파일(&lt;code&gt;/swapfile&lt;/code&gt;)을 생성하는 내용이다.&lt;br&gt;누구나 알고 있듯 가상메모리는 보조기억장치의 일부를 똑 떼어서 마치 주기억장치인 것처럼 활용하는 기술이다. &lt;/p&gt;
&lt;p&gt;그러다보니 마냥 커도 좋을게 없다. 왜냐면 현저히 느리고, 디스크 수명과도 연관이 있기 때문이다.&lt;br&gt;정답이 있는 건 아니다. 하지만 보통은 실 메모리의 2배 정도로 잡되, 4gb 미만이라면 2gb 정도는 기본으로 잡아주는 듯하다.&lt;br&gt;최소 256mb 이상으로 설정해야 한다. 당연히 디스크 크기보다 크게 잡을 수 없다.&lt;br&gt;리눅스 배포판마다 권고안이 있는 것 같으니 필요하다면 찾아보자.&lt;/p&gt;
&lt;p&gt;생성된 파일의 권한을 조정하자.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;chmod 600 /swapfile
mkswap /swapfile
swapon /swapfile&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;시스템 리부팅 후에도 유지될 수 있도록 해주자.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;vi /etc/fstab&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;기존의 내용에 추가해주자.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;/swapfile swap swap 0 0&lt;/code&gt;&lt;/pre&gt;&lt;h3&gt;정리&lt;/h3&gt;
&lt;p&gt;끝이다. 삭제는 조립의 역순이다(?).&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;출처 및 참고문헌&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://shanepark.tistory.com/378&quot;&gt;https://shanepark.tistory.com/378&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://lovedh.tistory.com/entry/Ubuntu-2004%EC%97%90%EC%84%9C-swap-%EB%A9%94%EB%AA%A8%EB%A6%AC-%EC%84%A4%EC%A0%95%ED%95%98%EA%B8%B0&quot;&gt;https://lovedh.tistory.com/entry/Ubuntu-2004%EC%97%90%EC%84%9C-swap-%EB%A9%94%EB%AA%A8%EB%A6%AC-%EC%84%A4%EC%A0%95%ED%95%98%EA%B8%B0&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>각종 학습 요약/Web</category>
      <author>닉Nick</author>
      <guid isPermaLink="true">https://sslblog.tistory.com/218</guid>
      <comments>https://sslblog.tistory.com/218#entry218comment</comments>
      <pubDate>Thu, 6 Jul 2023 13:19:27 +0900</pubDate>
    </item>
    <item>
      <title>프론트엔드(웹서버)와 백엔드(WAS)를 나눈 리버스 프록시 구성해보기(w/ubuntu, nginx)</title>
      <link>https://sslblog.tistory.com/217</link>
      <description>&lt;h3&gt;상황과 필요&lt;/h3&gt;
&lt;p&gt;ubuntu 22.04에서 web server로 nginx를, WAS로 tomcat(springboot의 embedded tomcat)을 사용하는 상황으로 가정한다.&lt;br&gt;프론트는 react나 vue 등이 대응하고, api 호출만 백엔드가 호출되도록 하고 싶다.&lt;/p&gt;
&lt;p&gt;쉽게 말해, 프론트와 백엔드 서버를 나눈 리버스 프록시 구성이다.&lt;/p&gt;
&lt;p&gt;이때 https를 어떤 식으로 적용하면 좋을지 생각해보자.&lt;/p&gt;
&lt;p&gt;가장 간단한 생각으로, &amp;#39;인증서를 p12 방식으로 변환하여 내장 톰캣 안에 넣어두면 되지 않나? 그러면 WAS만 띄우면 되는데&amp;#39;라고 생각이 들 수 있다.&lt;/p&gt;
&lt;p&gt;하지만 그건 몇 가지 불편한 점이 있다고 생각한다. &lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;어플리케이션 서버가 클라이언트에게 노출된다.&lt;/li&gt;
&lt;li&gt;어플리케이션 서버의 컴퓨팅 파워는 어플리케이션을 구동하는데만 힘을 쏟는게 바람직하다. 암복호화는 무겁다.&lt;/li&gt;
&lt;li&gt;certbot이 발급해준 인증서를 굳이 .p12로 변환해둬야 한다.&lt;/li&gt;
&lt;li&gt;프론트 작업의 산출물이 어플리케이션 프로젝트 안에 포함되어, 빌드 과정을 구성하기가 애매.&lt;/li&gt;
&lt;li&gt;분리하는게 딱히 어렵지도 않다. 아무리 간단하게 구축을 하기로 해도, 정적 리소스 서빙과 어플리케이션 정도는 구분해두면 좋을 거라고 생각했다.&lt;br&gt;그밖에도 여러 이유가 있을 수 있겠지만 바로 떠오른 생각은 이 정도였다.&lt;br&gt;물론 그냥 WAS만 띄워도 무방하다. 뭔가 큰 일이 일어나지 않는다. 몇 가지 귀찮은 일이나, 일어나면 안되는 일이 일어나지 않도록 평소에 좀 더 기도를 하면 해결될 일이다.&lt;br&gt;하지만 &amp;#39;나는 좀 더 구성해보고 싶다&amp;#39;는 생각이 든다면 아래의 내용을 따라가보는 것도 괜찮다.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;nginx 설치와 설정&lt;/h3&gt;
&lt;p&gt;곧 나오겠지만, 도메인과 네임서버(A레코드) 설정이 준비되어야 한다. certbot으로 인증을 진행할 때, 도메인을 사용할 것이기 때문이다. &lt;/p&gt;
&lt;p&gt;일단 사용할 nginx부터 설치해보자.&lt;br&gt;나는 학습 목적으로 진행한 것이라, 좀 더 편하게 진행할 수 있도록 root 권한을 획득해놓고 진행했으니, 권한 문제가 생긴다면 &lt;code&gt;sudo&lt;/code&gt;를 앞에 붙여서 해결하자. 우분투가 아닌 아마존 리눅스를 사용한다면 yum을 활용하자.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;apt install nginx&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;설정 파일을 찾아가보자. 우분투 배포판의 apache2처럼, &lt;code&gt;/etc/nginx/sites-available&lt;/code&gt;에 설정파일을 작성하고 사용해도 되지만, 다음의 경로(&lt;code&gt;/etc/nginx/conf.d/&lt;/code&gt;)에서 설정하는 것이 권장된다고 한다.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;cd /etc/nginx/conf.d
vi default.conf&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;설정파일이 열렸다. 크게 할 건 없다. 아래와 같이 고쳐주자.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;server {
    listen 80;
    server_name 도메인네임.com;

    location / {
        proxy_pass http://어플리케이션ip:어플리케이션port
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-Host $host;
        proxy_set_header X-Forwarded-Port $server_port;
    }
}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;도메인네임 부분에 구매한 도메인을 넣으면 된다. 어플리케이션 ip, port 부분에도 알맞게 넣자. private ip를 넣고 8080이 아닌 다른 포트를 넣으면 좋겠지만, &amp;#39;publicIP:8080&amp;#39; 같은 식으로 넣어도 동작은 잘 될 것이다.&lt;/p&gt;
&lt;p&gt;만약 프론트와 어플리케이션을 나누고 싶다면 &lt;code&gt;location&lt;/code&gt; 부분을 다음처럼 나누면 된다.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    location / {
        root   /home/project/프론트디렉토리;
        index  index.html index.htm;
        try_files $uri $uri/ /index.html;
    }

    location ~ ^(/api|/oauth2|/login/oauth2) {
        proxy_pass http://어플리케이션ip:어플리케이션port
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-Host $host;
        proxy_set_header X-Forwarded-Port $server_port;
    }&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;프론트, 예를 들어 리액트 빌드 결과물 디렉토리가 &lt;code&gt;location /&lt;/code&gt;의 root 부분에 들어가게 되면, nginx는 먼저 해당 경로에서 자원들을 찾을 것이다.&lt;br&gt;api 요청(&lt;code&gt;/api&lt;/code&gt;), 그리고 oauth2 인증을 위한 요청(&lt;code&gt;/oauth2, /login/oauth2&lt;/code&gt;)인 경우에만 업스트림으로 향할 수 있도록 한다.&lt;/p&gt;
&lt;p&gt;위의 설정파일은 매우 간단한 형태이다. 여러 upstream의 정보를 기록해두고 활용하거나, 원하는 정보를 프록시헤더를 덧붙이거나, 어플리케이션의 안정성을 위해 업스트림으로 향하는 요청의 개수를 제한할 수도 있다. &lt;/p&gt;
&lt;p&gt;하지만 지금은 간단한 형태로 가고, 각자의 필요에 따라 추후 더해보자.&lt;/p&gt;
&lt;h3&gt;certbot 설치와 https 인증서 발급&lt;/h3&gt;
&lt;p&gt;그럼 이제 사용할 certbot을 설치해보자. certbot은 apt가 아닌 snap을 통해 설치하는 것을 권장한다.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;snap install certbot --classic&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;설치가 끝났다면 바로 실행하기만 하면 된다.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;certbot --nginx&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;몇몇 도메인에 한해서 인증을 받고 싶다면 이렇게 하면 된다.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;certbot --nginx -d 인증받을거1.com -d 인증받을거2.co.kr -d www.인증받을거1.com&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;인증에 필요한 email(만료 알림 등이 여기로 온다), 그리고 동의 여부 몇 가지를 물어보고 곧바로 인증서가 설치된다. 다시 nginx 설정파일을 열어보면 변경된 것을 확인할 수 있을 것이다.&lt;/p&gt;
&lt;p&gt;브라우저를 열어서 ssl 인증서가 제대로 설치되었는지 살펴보자. 확인이 잘 될 것이다.&lt;/p&gt;
&lt;p&gt;하지만 이 인증서의 문제는, 타 인증기관들의 비싼 인증서보다 기간이 짧다는 것이다.&lt;/p&gt;
&lt;h3&gt;crontab, 인증서 갱신해줘&lt;/h3&gt;
&lt;p&gt;https 인증서는 만료 30일을 남기고부터 갱신이 가능하다. 만약 갱신하고 싶다면 이런 식으로 하면 된다.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;certbot renew&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;그런데 오늘이 며칠인지 무슨 요일인지도 깜빡거리는 사람이 제대로 갱신을 챙길 거라고 확신할 수 있다면 그건 만용이거나 안전불감증이거나 면허취소의 음주 상태일 수 있다.&lt;/p&gt;
&lt;p&gt;crontab을 이용해서 매일 매일 갱신을 체크하자.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;crontab -e&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;새로운 cron을 install 하는 명령어다.&lt;/p&gt;
&lt;p&gt;만약 크론을 처음 열어본다면 &amp;#39;어떤 에디터로 열래?&amp;#39;&amp;#39; 같은 질문이 나올 수도 있는데, 그냥 마음에 드는 걸로 열면 된다.&lt;/p&gt;
&lt;p&gt;열었으면 아래와 같이 입력하자.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;0 3 * * * certbot renew --quiet --post-hook &amp;quot;sudo service nginx reload&amp;quot;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;매일 03:00에 &amp;#39;certbot renew 어쩌구&amp;#39;&amp;#39; 하는 명령어를 실행하는 구문이다. 뒤의 옵션은, 말 그대로 출력없이 조용히 갱신만 해달란거, 그리고 끝나면 nginx를 reload 해달라는 말이다.&lt;/p&gt;
&lt;h3&gt;정리&lt;/h3&gt;
&lt;p&gt;끝이다. 나중에 시간이 되면, 이 포스팅을 활용해서 구성한 기본적인 형태의 어플리케이션을 구성해보도록 하겠다.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;출처 및 참고문헌&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;오늘의 주제를 처음 도전할 때, &lt;a href=&quot;https://hudi.blog/https-with-nginx-and-lets-encrypt/&quot;&gt;nginx와 https 설치 포스팅&lt;/a&gt;의 글에서 도움을 많이 받았습니다. 위 내용을 토대로 제가 알고 있는 것들을 추가했습니다. 좋은 글을 써주셔서 감사합니다.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=3yMY5phIaDc&quot;&gt;nginx의 리버스 프록시 설정&lt;/a&gt;을 처음 공부할 때 이 영상의 도움을 많이 받았습니다. 그밖에도 유익한 정보를 얻을 수 있는 채널이니 한번 둘러보시는 것도 좋겠습니다.&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>각종 학습 요약/Web</category>
      <category>nginx</category>
      <category>WAS</category>
      <category>리버스프록시</category>
      <author>닉Nick</author>
      <guid isPermaLink="true">https://sslblog.tistory.com/217</guid>
      <comments>https://sslblog.tistory.com/217#entry217comment</comments>
      <pubDate>Tue, 20 Jun 2023 11:11:03 +0900</pubDate>
    </item>
    <item>
      <title>우아한 테크캠프 6기 코딩테스트 후기 및 팁</title>
      <link>https://sslblog.tistory.com/216</link>
      <description>&lt;h1&gt;2023 우아한 테크캠프 6기 코딩테스트 후기 및 팁&lt;/h1&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;기존에 우아한 테크코스에 대해서는 알고 있었는데요. 우아한 테크캠프는 잘 몰랐습니다. 들어본 적은 있지만, '우아한 테크캠프가 진화(?)해서 우아한 테크코스가 된 거 아냐?' 정도로 생각하고 있었어요. 근데 알고 보니 인턴쉽이었습니다. &lt;br /&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;조건 같은 것은 딱히 없어서(학생이라면 졸업예정자, 해외여행에 결격사유가 없는 자(왜요? )라면 누구나 신청 가능) 과정에 대해서만 잘 알아두면 됩니다.&lt;br /&gt;우테캠은 1차 테스트(코테) - 2차 테스트(과테) - 서류 - 면접의 총 4단계로 진행되고, 각 단계마다 합/불이 있어서 패스된 인원만이 다음 테스트로 넘어가는 식입니다.&lt;br /&gt;그럼 각 단계의 결과는 언제 나오냐. 저도 1차만 보고 아직 결과가 나오지 않은 시점입니다. 수집한 정보 상으로는, 3-4일이 걸렸다고도 하고 2주가 넘게 걸렸다는 분도 계셨습니다.&lt;br /&gt;하지만 1차만큼은 3-4일이면 나오는게 맞는 것 같아요. 왜냐면 1차와 2차 사이의 기간이 일주일 밖에 안되는데, 결과를 안 알려주면 시험을 볼 수가 없게 될 테니 말이죠! &lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;그래서 1차 시험은 어땠고 어떤 내용들이 나왔나&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제를 자세히 읊게 되면 바로 소송을 당할 수 있기 때문에  카테고리와 특징, 주의사항 정도만 적어두려고 합니다.&lt;br /&gt;문제는 총 네 문제, 3시간 동안 진행됐습니다. IDE, 공식문서, 구글링, 안돼요. 손노트 활용만 가능합니다. 테케 통과 여부는 알려주지만, 정답 여부는 알려주지 않습니다.&lt;br /&gt;1번부터 차례로 정리해 볼게요.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;문제 1&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;카테고리 : 그리디...라고 하기에도 민망할 정도로 매우 간단한 수준.&lt;/li&gt;
&lt;li&gt;난이도 : 백준 실버4 / 플그 Lv1&lt;/li&gt;
&lt;li&gt;특징 : 그냥 요구사항대로 정렬하여 값을 꺼내주면 되는 매우 간단한 문제. 플그의 수많은 Lv1 문제들을 만나보셨다면 어렵지 않게 푸셨을 것 같습니다.&lt;/li&gt;
&lt;li&gt;주의할 점 : 문제 이해하는 데에 오래 걸리는 사람들은 힘들었을 듯 합니다. 왜냐면 그게 바로 나예요 ... 문제 읽는데 30분, 푸는데 5분... 그런 문제였습니다. 대다수는 아무리 길게 잡아도 10분 컷 하셨을 것 같아요. 달리 말하면, 실버4 정도의 문제는 그냥 보고 바로 적어내실 수 있는 수준만 되시면 됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;문제 2&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;카테고리 : DP&lt;/li&gt;
&lt;li&gt;난이도 : 골드3 / Lv3(또는 어려운 Lv2)&lt;/li&gt;
&lt;li&gt;특징 : 누가 봐도 DP라는 것을 알기 쉽게 던져주었습니다. 진짜 전형적인 DP인데, 그래도 조금 더 복잡했습니다. 지금 생각나는 비슷한 문제는, 백준 DDR 문제를 푸실 정도면 쉽게 푸셨을 것 같습니다.&lt;/li&gt;
&lt;li&gt;주의할 점 : 어떤 문제든 일단 먼저 완탐으로 풀고보는 분들이 계신데(부분점수라도 받으려는 목적으로) 아마 그러신 분들은 시간 낭비를 하지 않으셨을까 싶습니다. 완탐으로는 절대 풀리지 않을 문제였습니다. 거꾸로 말해서, 문제를 읽고 원하는 바를 유추할 수 있을 정도로 준비를 했나 보는 것처럼 느꼈습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;문제3&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;카테고리 : 시뮬레이션&lt;/li&gt;
&lt;li&gt;난이도 : 골드5 / Lv3(또는 어려운 Lv2)&lt;/li&gt;
&lt;li&gt;특징 : 무난한 구현 문제였습니다. 준비했다면 누구나 '한번쯤은' 접해봤을 법한... 비슷한 문제를 풀어보고 싶다면 백준 문제집에서 삼성a형 쪽을 뒤져보시면 될 것 같습니다.&lt;/li&gt;
&lt;li&gt;주의할 점 : 흔히 말하는 '빡구현' 문제의 쉬운 버전 같은 느낌입니다. 구현 로직의 난이도 자체는 낮지만, 빡구현 문제를 싫어하셔서 준비를 많이 안해보신 분들은 무참히 맞을 수밖에 없습니다. 네. 그게 바로 나예요 ...... 못 풀 정도는 아니기 때문에, 다른 문제들을 빨리 풀고 시간을 최대한 확보해서 이런 유형의 문제로 진입하시면 되겠습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;문제4&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;카테고리 : MST...라고 하더라고요? 크루스칼 어쩌구... 저는 그런 어려운 용어는 몰라서... 평범한 탐색으로 풀었습니다.&lt;/li&gt;
&lt;li&gt;난이도 : 사람마다 난이도 체감이 컸던 문제. 그러나 저는 실1-골5 / Lv2 정도로 느꼈습니다. 어렵게 느끼신 분들은 골3-4 정도로 보셨던 것 같아요.&lt;/li&gt;
&lt;li&gt;특징 : 탐색으로 안 풀린다고 하시는 분들이 계시던데 저는 탐색으로 풀었습니다(왜 안풀리지?...아직도 모르겠습니다). 유니온파인드를 알고 계신 분은 아주 쉽게 효율적으로 푸셨을 것 같습니다. 포멀한 최소신장트리 문제들을 많이 접해보셨다면 무난하셨을 것 같습니다. 기존에 접해보았던 코테 문제들에 비해 테케가 그렇게 빡세지 않았어요(히든케이스가 있다면 그건 모르겠지만).&lt;/li&gt;
&lt;li&gt;주의할 점 : 딱히요. 문제 자체도 많이 볼 수 있었던 유형이고, 지문 자체도 원하는 바를 확실히 전달해줬습니다.&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;문제를 풀다 보면서 생각난 것들인데, 혹시나 우테캠 7기가 열려서 지원하시는 분들이 계시다면 꼭 적용했음 좋겠다 싶은 팁이 있었습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;첫째. 로그 읽기 연습&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제가 생겼을 때 IDE가 떠먹여주지 않아도 어디서 뭐가 문제였는지 로그 텍스트만 읽고서 찾을 수 있어야 합니다. 로그가 영어 메시지이고, 사람에 따라 불친절하게 느낄 수도 있죠. 저도 영어 1도 못합니다. 하지만 평소에 로그 메시지를 읽어보려고 했다면 절대 낯선 문구들이 아닙니다. 메시지가 정확히 어떤 의미인지는 몰라도, 오타 때문인지 import문 누락인지 로직 오류인지 바로 깨달을 수는 있어야 합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;둘째. 빨리 쓰기 &amp;amp; 빨리 찾기 연습&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;당연한 소리를 한다고 생각하실 수 있는데, 맞습니다. 타자 빠르면 당연히 좋죠. 근데 저처럼 손이 느린 분이라면, 모든 문제에서 반복적으로 사용할 만한 문장은 손에 완전히 새겨두시는게 좋습니다. 적어도 아래의 문구 정도는 말이죠.&lt;/p&gt;
&lt;pre class=&quot;swift&quot;&gt;&lt;code&gt;import java.util.*;
import java.util.stream.*;

// 그리고

System.out.println(&quot;value: &quot; + value);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;디버깅툴이 제공되지 않기 때문에 입출력 손버깅을 해야 합니다. 그렇다고 값만 찍으면, 찍어야 할 값이 여러개가 되는 순간 뭐가 뭔지 모르게 됩니다. 그래서 '라벨 + 변수'과 같은 식으로 출력을 해주시면 손버깅에 이롭습니다.&lt;br /&gt;그럼에도 손이 정 느리신 분은 이런 식으로 메서드를 빼두시면 유용합니다(저는 이렇게 했어요).&lt;/p&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;void test(String label, Object value) {
    System.out.println(label + &quot;&amp;gt;&amp;gt;&amp;gt; &quot; + value);
}
void testArray(int[] value) { // 문제에 주로 int배열이 나오기 때문에 int[] 타입을 썼습니다.
    System.out.println(Arrays.toString(value));
}
// 또는 탐색 문제에 자주 쓰이는 2d array
void testArray2(int[][] value) {
    // 여러 배열을 찍으면 매우 헷갈립니다. 구분선을 넣어주면 손버깅 가독성이 좋아집니다.
    System.out.println(&quot;--------------------&quot;); 
    for (int[] v : value)
        System.out.println(Arrays.toString(v);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 식으로, 자신만의 손버깅 전략 &amp;amp; 시간 단축 전략이 필요합니다.&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;br /&gt;플그는 테스트케이스를 사용자가 추가할 수 있습니다. 물론 숨겨진 히든 엣지케이스를 찾는건 많이 풀어본 사람의 머리에서만 튀어나오는 것이고, 그런걸 찾아야 한다는 당연한 말을 하는 건 아닙니다(저도 그런건 잘 못해요).&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러나 요구사항대로 잘 짠 것 같은데도 아주 작은 넘버의 테케부터 통과가 안된다면, 주어진 조건의 최소조건들을 가지고 임의의 테케를 추가해보세요. 아주 작은 코너케이스에서 걸리고 있을 확률이 있습니다.&lt;br /&gt;테케 중~후반에서 통과가 안된다면 주어진 조건의 최대조건들을 입력값으로 넣고 돌려보세요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본으로 주어지는 테케들은 '통상적으로 떠올릴 랜덤값을 입력했을 때 나올만한 결과들'뿐입니다. 예를 들어 '1 &amp;lt;= 파라미터 &amp;lt; 100,000'와 같은 입력조건이 있다면, 테케로 주어지는 파라미터는 아마 37, 52, 1004, 3306 따위가 될 겁니다. 이번 문제 중에도 그런 문제가 있었는데요. IDE를 돌렸거나 정답여부를 알려줬다면 누구나 쉽게 통과했을 문제가 있습니다. 하지만 코너케이스를 넣어보지 않은 분이라면 아마 높은 확률로 해당 문제는 틀리셨을 거라고 생각합니다.&lt;br /&gt;마지막으로 다시 한 번, 잘 돌아간다고 제출하고 끝내지 마시고 코너케이스를 꼭 직접 돌려보세요!&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;br /&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;이렇게 보면 '뭐야? 쉽나 보네?'란 생각이 드실 수 있어요. 하지만 현명한 여러분들께서는 타이슨 선생님이 전해주신 교훈을 잊어선 안되겠습니다. 누구나 처맞기 전까진 그럴 듯한 계획이 있죠 ...&lt;br /&gt;한 문제(1번)를 제외하고서는 지문도 요구하는 바를 명확하게 표현해주는 편이었습니다. 그래서 더욱, 문제를 많이 접해본 사람과 아닌 사람의 난이도 체감 차이가 극명했겠단 생각을 했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저는 문제 풀이를 따로 충분히 풀어보지 못했고, 또 시간 분배에도 실패를 해서 반타작 밖에 못했습니다(두 문제 제출하고 한 문제 풀다 제출했습니다).&lt;br /&gt;하지만 열심히 하시는 분들에게 더욱 좋은 결과가 있었음 해서 조금이나마 도움될 만한 부분들을 모아 이렇게 정리를 해보았어요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개인적으로 'DP 점화식을 진짜 기계처럼 주루룩 짤 정도로 연습을 해둘걸' || '빡구현 문제를 좀 열심히 해둘걸'이라는 후회를 하긴 했지만, 게으름 피워서 안한게 아니고 다른 공부들과의 순위에서 밀려 소홀했던 것이기 때문에 엄청나게 아쉽지는 않습니다. 가진 것에서 최선을 다했다! 그런 느낌이네요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개인적인 &lt;b&gt;예상 합격솔은 3솔&lt;/b&gt;입니다. 혹은 문제의 의도를 잘 알고 푸셨다면 2솔합도 있지 않을까? 하는 생각이 드는 정도입니다. 코테 직후 대화 나누면서 보니 2솔 하셨다는 분이 많았습니다(음... 아마... 위의 코너케이스...를 걸리신 분들이 꽤 되시지 않을까...싶지만...). 1솔은 확실히 좀 어려울 수 있겠다 싶습니다.&lt;br /&gt;코테 결과가 아닌 다른 무엇을 함께 판단기준에 넣는지는 모르겠지만, 문제 난이도와 결과만 생각해보면 그럴 것 같다 싶었어요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;말이 자꾸 길어져서 그만 줄여야겠네요. 저나 여러분이나 합격되면 당연히 좋겠지만 이곳이 아니더라도 열심히 해서 목표에 한걸음씩 나아가면 좋겠습니다!&lt;br /&gt;&lt;b&gt;어찌됐든 즐겁게 개발을 하는 것이 중요한 거 아니겠어요?!&lt;/b&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;추가 : 3솔?... 응 올솔합  ......&lt;/p&gt;</description>
      <category>기타</category>
      <author>닉Nick</author>
      <guid isPermaLink="true">https://sslblog.tistory.com/216</guid>
      <comments>https://sslblog.tistory.com/216#entry216comment</comments>
      <pubDate>Tue, 9 May 2023 16:15:35 +0900</pubDate>
    </item>
    <item>
      <title>4월 간단 회고</title>
      <link>https://sslblog.tistory.com/215</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;천천히&amp;nbsp;내용을&amp;nbsp;정리하고&amp;nbsp;싶지만,&amp;nbsp;오늘도&amp;nbsp;밀린&amp;nbsp;공부가&amp;nbsp;산더미기&amp;nbsp;때문에&amp;nbsp;빠르게&amp;nbsp;정리를&amp;nbsp;하고자&amp;nbsp;옵시디언을&amp;nbsp;켜본다.&lt;br /&gt;&lt;br /&gt;3월과&amp;nbsp;마찬가지로&amp;nbsp;4월도&amp;nbsp;열심히&amp;nbsp;공부하면서&amp;nbsp;보냈지만&amp;nbsp;그럼에도&amp;nbsp;4월은&amp;nbsp;조금&amp;nbsp;뜻깊었다.&lt;br /&gt;백엔드&amp;nbsp;개발자가&amp;nbsp;되고&amp;nbsp;싶어서&amp;nbsp;부트캠프를&amp;nbsp;시작한게&amp;nbsp;작년&amp;nbsp;4월&amp;nbsp;25일이기&amp;nbsp;때문이다.&lt;br /&gt;&lt;br /&gt;본래&amp;nbsp;월말&amp;nbsp;즈음이면&amp;nbsp;회고도&amp;nbsp;적을&amp;nbsp;겸&amp;nbsp;한&amp;nbsp;달의&amp;nbsp;일을&amp;nbsp;정리해보곤&amp;nbsp;하는데,&amp;nbsp;이번엔&amp;nbsp;어쩐지&amp;nbsp;자꾸만&amp;nbsp;지난&amp;nbsp;1년을&amp;nbsp;되돌아보게&amp;nbsp;되더라.&lt;br /&gt;그리고&amp;nbsp;한편으론&amp;nbsp;취준&amp;nbsp;시작한지&amp;nbsp;1년이&amp;nbsp;넘어가는&amp;nbsp;구나...라는&amp;nbsp;생각에&amp;nbsp;원치&amp;nbsp;않았던&amp;nbsp;조급함이&amp;nbsp;조금씩&amp;nbsp;생기는&amp;nbsp;것도&amp;nbsp;느껴졌다.&amp;nbsp;어쩌면&amp;nbsp;조급함이&amp;nbsp;아니라&amp;nbsp;취준을&amp;nbsp;끝낼&amp;nbsp;시기가&amp;nbsp;다가온&amp;nbsp;것&amp;nbsp;뿐일지도&amp;nbsp;모르지만.&lt;br /&gt;&lt;br /&gt;최근에는&amp;nbsp;조금&amp;nbsp;색다른&amp;nbsp;공부를&amp;nbsp;했다.&amp;nbsp;리액트를&amp;nbsp;조금&amp;nbsp;만져봤다.&amp;nbsp;&lt;br /&gt;기존에&amp;nbsp;진행했던&amp;nbsp;프로젝트의&amp;nbsp;기능을&amp;nbsp;개선하고&amp;nbsp;싶은데&amp;nbsp;프론트엔드를&amp;nbsp;전혀&amp;nbsp;모르니까&amp;nbsp;뭐&amp;nbsp;어떻게&amp;nbsp;할&amp;nbsp;수가&amp;nbsp;없더라.&amp;nbsp;백엔드에서&amp;nbsp;아무리&amp;nbsp;수정하고&amp;nbsp;기능을&amp;nbsp;붙여도&amp;nbsp;앞에서&amp;nbsp;불러주질&amp;nbsp;않으면&amp;nbsp;어쩔&amp;nbsp;도리가&amp;nbsp;없으니까.&lt;br /&gt;결과적으로&amp;nbsp;게시판&amp;nbsp;형태의&amp;nbsp;일기장을&amp;nbsp;CSR로&amp;nbsp;완성했다.&lt;br /&gt;진짜&amp;nbsp;어려웠다.&amp;nbsp;프론트엔드&amp;nbsp;선생님들은&amp;nbsp;정말...&amp;nbsp;대단하다.&lt;br /&gt;&lt;br /&gt;컨디션이&amp;nbsp;오르락&amp;nbsp;내리락&amp;nbsp;해서&amp;nbsp;조금&amp;nbsp;고생을&amp;nbsp;했다.&amp;nbsp;날씨에&amp;nbsp;영향을&amp;nbsp;많이&amp;nbsp;받는&amp;nbsp;체질인데,&amp;nbsp;올&amp;nbsp;봄의&amp;nbsp;환경은&amp;nbsp;진짜&amp;nbsp;다이나믹&amp;nbsp;한&amp;nbsp;것&amp;nbsp;같다.&amp;nbsp;꽃가루가&amp;nbsp;펑펑&amp;nbsp;날리던&amp;nbsp;날은&amp;nbsp;진짜&amp;nbsp;하루종일&amp;nbsp;코에서...&amp;nbsp;여기까지만&amp;nbsp;하겠다.&lt;br /&gt;하여튼&amp;nbsp;쉽지&amp;nbsp;않았는데&amp;nbsp;5월은&amp;nbsp;덥든지&amp;nbsp;춥든지&amp;nbsp;하나만&amp;nbsp;했으면&amp;nbsp;좋겠다.&amp;nbsp;지금&amp;nbsp;창밖엔&amp;nbsp;장마철처럼&amp;nbsp;비가&amp;nbsp;오고있긴&amp;nbsp;하지만...&lt;br /&gt;&lt;br /&gt;4월&amp;nbsp;마지막&amp;nbsp;주~5월&amp;nbsp;첫주&amp;nbsp;부터는&amp;nbsp;한&amp;nbsp;주에&amp;nbsp;하나씩&amp;nbsp;간단하게나마&amp;nbsp;프로젝트를&amp;nbsp;해볼까&amp;nbsp;한다.&amp;nbsp;공부한&amp;nbsp;것들&amp;nbsp;총&amp;nbsp;정리,&amp;nbsp;그리고&amp;nbsp;이제&amp;nbsp;일&amp;nbsp;할&amp;nbsp;준비를&amp;nbsp;겸해서.&lt;br /&gt;&lt;br /&gt;이것저것&amp;nbsp;공부는&amp;nbsp;많이&amp;nbsp;했는데&amp;nbsp;늘어놓을&amp;nbsp;시간이&amp;nbsp;없네.&amp;nbsp;뭐&amp;nbsp;어쨌든.&lt;br /&gt;5월도&amp;nbsp;힘내보자.&amp;nbsp;이제&amp;nbsp;일&amp;nbsp;좀&amp;nbsp;해보자,&amp;nbsp;나도.&lt;/p&gt;</description>
      <category>회고</category>
      <category>회고</category>
      <author>닉Nick</author>
      <guid isPermaLink="true">https://sslblog.tistory.com/215</guid>
      <comments>https://sslblog.tistory.com/215#entry215comment</comments>
      <pubDate>Sat, 29 Apr 2023 11:08:06 +0900</pubDate>
    </item>
    <item>
      <title>3월을 돌아보는 회고</title>
      <link>https://sslblog.tistory.com/214</link>
      <description>&lt;p&gt;3월 한 달은 기본기를 위해 인풋을 최대화 하려고 노력한 시간이었다.&lt;br&gt;시간의 양적으로 부족함 없이 열심히 꾸준히 하려고 했다.&lt;br&gt;시간의 질적 향상을 위해서도, 쓸 데 없는 거 하면서 열심히 보냈다는 느낌만 받는게 아닌지 계속 검토를 했다. 가급적 의미있는 활동 시간을 채우기 위해 노력했다.&lt;/p&gt;
&lt;p&gt;의미 있는 반복은 의미 있는 결과로 이어진다.&lt;br&gt;...는 말을 사실이라고 믿으면서 보내기로 했다.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;계획&lt;/h2&gt;
&lt;p&gt;3월의 일과 계획은 이랬다. &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;일어나서 영어 공부&lt;/li&gt;
&lt;li&gt;씻고 아침에 산책(하면서 샌드위치 &amp;amp; 커피 사오기)&lt;/li&gt;
&lt;li&gt;9 to 6 학습 스케줄 진행 (메인 학습 시간에는 인강을 주로 진행하고, 마치면 프로젝트를 진행할 계획이었다)&lt;/li&gt;
&lt;li&gt;스터디 있는 날은 오전 스터디 진행&lt;/li&gt;
&lt;li&gt;6~7시 동안 집안일&lt;/li&gt;
&lt;li&gt;7~8 저녁먹고 산책&lt;/li&gt;
&lt;li&gt;8~11 저녁 공부 || 개발 자료 서칭&lt;/li&gt;
&lt;li&gt;주말에는 평일에 모아놨던 궁금한 부분 || 필요한 부분 보충학습 || 영어 공부&lt;/li&gt;
&lt;li&gt;남는 시간 활용해서 책 읽기&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;실천&lt;/h2&gt;
&lt;p&gt;일과 계획 중에서 잘했던 것, 좋았던 것을 돌아보면&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;일단 그대로 실행은 했다.&lt;/li&gt;
&lt;li&gt;강의는 총 여덟 과정을 시작하고 끝냈다. &lt;ul&gt;
&lt;li&gt;기본기를 다지는 좋은 내용들이어서 알맞게 도움이 되었다.&lt;/li&gt;
&lt;li&gt;뭘 계속 만들어보는 편이 확실히 집중도 높게 공부가 된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;산책을 꾸준히 하려고 노력했다.&lt;ul&gt;
&lt;li&gt;사실 산책은 처음부터 계획에 있진 않았는데, 말 그대로 &amp;#39;하루 종일&amp;#39; 공부만 하다 보니 잠 잘 때 빠르게 잠들지를 못했다.&lt;/li&gt;
&lt;li&gt;확실히, 30분 이상의 신체활동은 수면의 질에 긍정적인 영향을 주었다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;영어 공부&lt;ul&gt;
&lt;li&gt;지난 달의 감상과 마찬가지로 그냥 꾸준히 하고는 있다.&lt;/li&gt;
&lt;li&gt;워낙 영알못이라 이게 잘 하고 있는 건지 아닌지는 아직 감이 없다.&lt;/li&gt;
&lt;li&gt;근데 확실히 익숙해진다는 느낌은 든다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;보완할 점&lt;/h2&gt;
&lt;p&gt;개선할 점을 돌아보면&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;책 읽기(&lt;a href=&quot;http://www.yes24.com/Product/Goods/18249021&quot;&gt;객체지향의 사실과 오해&lt;/a&gt;)는 거의 진행이 안 되었다. &lt;ul&gt;
&lt;li&gt;책 읽을 시간이 많이 없기도 했고, 한 파트마다 생각할 여지가 많아서 빠르게 책장이 넘어가는 스타일의 책이 아니기도 했다.&lt;/li&gt;
&lt;li&gt;그럼에도 빠르게 한 번 훑어보았으면 좋았을 걸 하는 생각이 든다. 시간 없을 때는 일단 빠르게 한 번 훑고, 여유가 나면 다시 정독하는 식으로 읽는 전략이 좋겠다. 그러지 않고서는 &amp;quot;바빠서 책 읽을 시간이 없어&amp;quot;라는 변명을 할 수 밖에 없을 것 같다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;알고리즘은 진짜 빠르게 녹이 슨다.&lt;ul&gt;
&lt;li&gt;내가 PS 쪽에 재능이 없어서이기도 하지만, 조금만 손을 놓고 있어도 실력이 쭉쭉 떨어진다.&lt;/li&gt;
&lt;li&gt;최근에 본 코딩테스트에서 털렸기 때문에 그런 생각이 든 것이기도 하다.&lt;/li&gt;
&lt;li&gt;알고리즘이 진짜 딜레마다... 대기업 코테를 뚫을 것인가 아니면 적당히 꾸준히만 할 것인가... 평범한 스펙만 되었어도 닥전으로 갈 것 같은데, 난 그렇질 못해서 말이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;프로젝트는 시작도 못했다.&lt;ul&gt;
&lt;li&gt;사실 시작도 못한 건 아니고, 구현할 내용들을 노트에 정리하고 있다.&lt;/li&gt;
&lt;li&gt;기본기만 다시 한번 다져놓고 프로젝트 시작해야지. 그런데 한 달이 걸렸다. 더 빠르게 하는건 무리였다. 그냥 물리적으로 시간이 부족했다.&lt;/li&gt;
&lt;li&gt;사실 프로젝트 보다는 &lt;strong&gt;계획&lt;/strong&gt;에 대한 생각을 다시 하게 되는 계기였다.&lt;/li&gt;
&lt;li&gt;그냥 무리한 계획을 세운 거였는데, 어쩐지 &amp;#39;목표를 달성하지 못했다&amp;#39;는 부분만 뇌리에 남아 일말의 실패감을 느끼게 되었다. 그게 아니란 걸 알면서도. &lt;/li&gt;
&lt;li&gt;적당한 계획을 세우는 것은 일정대로 실행하는 것 이상의 의미가 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;마무리 중얼중얼&lt;/h2&gt;
&lt;p&gt;1.&lt;br&gt;&lt;strong&gt;&amp;#39;사실 좀 더 열심히 할 수 있었던 건 아닐까?&amp;#39;&lt;/strong&gt;&lt;br&gt;아무리 알차게 보내도 이 생각이 드는 건 어쩔 수가 없나 보다. 딱히 불안감 때문도 아닌 것 같다.&lt;/p&gt;
&lt;p&gt;어제(31일) 마지막 일정을 마치고, 운동 같이 하던 형님들 만나서 식사를 하는데, 형들이 다 &amp;quot;쟤는 운동할때 완전 눈 돌아가잖어. ㅋㅋ&amp;quot;라고 했다.&lt;br&gt;나도 인정했다. &amp;quot;아니 시작했으면 끝 볼 때까지 최선은 다해봐야죠, 안 그래도 약골인데.&amp;quot;&lt;br&gt;그런걸 보면 그냥 나란 인간 자체가, 이거다 싶으면 한계치까지 가는 걸 좋아하는 듯.&lt;/p&gt;
&lt;p&gt;사실 취준생의 입장으로서도 다르지 않다. 스펙이랄게 전무한 스펙. 보여줄 거라곤 퍼포먼스 뿐이다. 그럼 뭐라도 보여줄 수 있게 움직여야지.&lt;br&gt;그래도.&lt;br&gt;나 스스로가 무리하지 않는 선에서 최대치로 노력하고 있다는 걸 잘 안다. 잘 하고 있으니 하던 대로 하면 된다.&lt;br&gt;결과는 내가 선택하는 게 아니니 가급적 신경을 끄면 좋다. 조급한 마음은 하등 득될 것이 없다.&lt;/p&gt;
&lt;p&gt;2.&lt;br&gt;&lt;strong&gt;&amp;#39;아무 회사나 가지 말자.&amp;#39;&lt;/strong&gt;&lt;br&gt;아무리 감추더라도 스스로 느끼기에 &lt;strong&gt;&amp;#39;아무 회사나&amp;#39;&lt;/strong&gt; 가야 한다면, 결국 장기적으로 커리어를 가져가진 못할 거라고 생각했다. 난 월급만 받고 다니는 생활에 만족하는 인간이 아니고, 월급 의존적인 삶에 금세 회의감을 느낄 것이 뻔하니까.&lt;br&gt;결국 스스로의 동기부여를 해칠 정도로 타협하지는 말자는 결론을 내려서 아직까지도 취준을 하고 있지만, 사실 욕심을 조금만 버렸어도 이렇게까지 취준이 길어질 일은 없었을 것 같다. &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;선택지는 좁고 허들이 높은 시기인 건 사실&lt;/strong&gt;이다.&lt;br&gt;그래도 반대로 생각하면, &lt;strong&gt;짧은 시간을 더욱 밀도 높게 준비하면서 기본을 더욱 갖추는 기회가 되었다&lt;/strong&gt;고 볼 수도 있을 것 같다. 이력서만 내면 취직 되는 시장이었으면, 이렇게까지 준비를 했을까?&lt;br&gt;어찌 됐든 성장에 긍정적으로 뽑아먹을 수 있는 부분은 뽑아 먹었고, 또 위기 상황의 운용에도 나름 경험이 되고 있다.&lt;/p&gt;
&lt;p&gt;4월부터는 프로젝트와 이력서에 시간의 비중을 많이 둘 것 같다. 하루 하루를 충실하게 보내보자.&lt;/p&gt;
&lt;p&gt;길고 긴 취준도 슬슬 끝이 보인다.&lt;/p&gt;</description>
      <category>회고</category>
      <author>닉Nick</author>
      <guid isPermaLink="true">https://sslblog.tistory.com/214</guid>
      <comments>https://sslblog.tistory.com/214#entry214comment</comments>
      <pubDate>Sat, 1 Apr 2023 13:01:19 +0900</pubDate>
    </item>
    <item>
      <title>API 호출을 위한 세 가지 Spring 도구(Spring 6에서 새롭게 지원하는 HttpInterface)</title>
      <link>https://sslblog.tistory.com/213</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;개요&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오늘 포스팅은 &lt;a href=&quot;https://www.youtube.com/@tobyspring&quot;&gt;토비&lt;/a&gt;님의 '&lt;a href=&quot;https://www.youtube.com/watch?v=Kb37Q5GCyZs&quot;&gt;Spring 6의 새로운 HTTP Interface와 3 가지 REST Clients 라이브 코딩&lt;/a&gt;' 영상을 보고 나서 작성하는 글입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Spring에서 제공하는 &lt;code&gt;RestTemplate&lt;/code&gt;과 &lt;code&gt;WebClient&lt;/code&gt;, 그리고 Spring 6에서 새롭게 제공하게 된 &lt;code&gt;HttpInterface&lt;/code&gt;를 간단히 살펴봅니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어떻게 사용되는지 하나씩 코드로 살펴보겠습니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. RestTemplate&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-03-17 오전 9.57.12.png&quot; data-origin-width=&quot;1858&quot; data-origin-height=&quot;950&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bgKbzH/btr4qzYG2hF/ZKI8WBfEuMDnFr5XyKErTk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bgKbzH/btr4qzYG2hF/ZKI8WBfEuMDnFr5XyKErTk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bgKbzH/btr4qzYG2hF/ZKI8WBfEuMDnFr5XyKErTk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbgKbzH%2Fbtr4qzYG2hF%2FZKI8WBfEuMDnFr5XyKErTk%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;440&quot; data-filename=&quot;스크린샷 2023-03-17 오전 9.57.12.png&quot; data-origin-width=&quot;1858&quot; data-origin-height=&quot;950&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;간단히 실행 결과 확인을 위해 &lt;code&gt;ApplicationRunner&lt;/code&gt;를 사용합니다. &lt;code&gt;RestTemplate&lt;/code&gt;은 Spring3.0 부터 사용되어온 동기 방식의 클라이언트입니다. Spring Web 프로젝트를 사용하면서 외부의 api를 호출할 일이 있으면 가장 편하게 선택할 수 있는 방법인 것 같아요.&lt;br /&gt;사용 방법 자체는 크게 어려울 것이 없습니다. &lt;code&gt;RestTemplate&lt;/code&gt;을 생성해서 &lt;code&gt;getFor~~~()&lt;/code&gt;로 결과를 받을 수 있습니다. json string으로 받을 수도 있고, 객체를 매핑할 수도 있습니다.&lt;br /&gt;위의 예제에서는 환율을 달러 기준으로 조회할 수 있는 api인데요, 결과값을 Map으로 받고 있네요. base_code가 USD로, USD에 대비하여 KRW이 얼마인지가 잘 출력되는 모습을 볼 수 있습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2. WebClient&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-03-17 오전 10.09.07.png&quot; data-origin-width=&quot;2128&quot; data-origin-height=&quot;1368&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/coVIBu/btr4tqzUaDT/k2vCpl2Dy1snklGuk0Yvs0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/coVIBu/btr4tqzUaDT/k2vCpl2Dy1snklGuk0Yvs0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/coVIBu/btr4tqzUaDT/k2vCpl2Dy1snklGuk0Yvs0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcoVIBu%2Fbtr4tqzUaDT%2Fk2vCpl2Dy1snklGuk0Yvs0%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;2128&quot; height=&quot;1368&quot; data-filename=&quot;스크린샷 2023-03-17 오전 10.09.07.png&quot; data-origin-width=&quot;2128&quot; data-origin-height=&quot;1368&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;Spring Webflux 의존성을 추가하면 &lt;code&gt;WebClient&lt;/code&gt;를 api client로 사용할 수 있습니다. Webflux 프로젝트를 사용하고 있지 않았다면, &lt;code&gt;WebClient&lt;/code&gt;를 위해 Webflux를 추가해야 한다는 점, 그리고 비동기가 기본 동작 방식이기 때문에, &lt;code&gt;block()&lt;/code&gt;을 사용해야 한다는 점에서 사용이 꺼려질 수도 있겠습니다.&lt;br /&gt;하지만 반대로 Webflux 프로젝트 중이라면 &lt;code&gt;WebClient&lt;/code&gt;를 사용하지 않을 이유가 없겠죠? &lt;code&gt;WebClient&lt;/code&gt;는 비동기와 fluent API, 스트리밍까지 지원하기 때문에 Spring 커뮤니티에서도 사용을 권장하고 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 특별한 기능이 필요하다면 &lt;code&gt;WebClient&lt;/code&gt;를, 간단한 api call만 필요하다면 &lt;code&gt;RestTemplate&lt;/code&gt;을 선택할 수 있겠네요. 여기에 사족을 하나 덧붙이자면, &lt;code&gt;RestTemplate&lt;/code&gt;이 Deprecated 되었기 때문에(혹은 될 것이기 때문에) &lt;code&gt;WebClient&lt;/code&gt;를 사용하라고 권장하는 경우가 많은데, 현재로서는 정해진 Deprecated 계획을 없다고 합니다. 아주 예전에 언젠가 &lt;code&gt;RestTemplate&lt;/code&gt;의 JavaDoc에서 '미래에 Deprecated 될 것이다'라는 문구가 쓰여있었던 적이 있어서 그런 이야기가 퍼진 것 같지만, 현재는 해당 문구는 삭제되어 'Deprecated'라는 표현은 볼 수 없게 된 상태입니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3. HttpInterface&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-03-17 오전 10.15.13.png&quot; data-origin-width=&quot;2194&quot; data-origin-height=&quot;1824&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/1LFRS/btr4kQtbysY/eHKAJM6BVZiJ12tuPMWaO0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/1LFRS/btr4kQtbysY/eHKAJM6BVZiJ12tuPMWaO0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/1LFRS/btr4kQtbysY/eHKAJM6BVZiJ12tuPMWaO0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F1LFRS%2Fbtr4kQtbysY%2FeHKAJM6BVZiJ12tuPMWaO0%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;2194&quot; height=&quot;1824&quot; data-filename=&quot;스크린샷 2023-03-17 오전 10.15.13.png&quot; data-origin-width=&quot;2194&quot; data-origin-height=&quot;1824&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;마지막으로 소개할 것은 &lt;code&gt;HttpInterface&lt;/code&gt;입니다. Spring 6에서 새롭게 지원하게 된 따끈따끈한 피쳐입니다. &lt;code&gt;HttpInterface&lt;/code&gt;를 사용하기 위해서는 그 이름답게 interface 구현이 필요합니다. 위 코드에서는 &lt;code&gt;ErApi&lt;/code&gt;라는 이름의 인터페이스를 만들어서, 43~47 라인처럼 어노테이션을 붙여서 정의했습니다. 만들어진 인터페이스 타입을 &lt;code&gt;HttpServiceProxyFactory#createClient()&lt;/code&gt;의 인자로 넘겨주면 인스턴스를 얻을 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-03-17 오전 10.24.51.png&quot; data-origin-width=&quot;2154&quot; data-origin-height=&quot;1766&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/brbqcr/btr4sUVDTvF/ke23X0gA58Q4PKKkSiM6G1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/brbqcr/btr4sUVDTvF/ke23X0gA58Q4PKKkSiM6G1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/brbqcr/btr4sUVDTvF/ke23X0gA58Q4PKKkSiM6G1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbrbqcr%2Fbtr4sUVDTvF%2Fke23X0gA58Q4PKKkSiM6G1%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;2154&quot; height=&quot;1766&quot; data-filename=&quot;스크린샷 2023-03-17 오전 10.24.51.png&quot; data-origin-width=&quot;2154&quot; data-origin-height=&quot;1766&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;code&gt;ErApi&lt;/code&gt;를 빈으로 등록하게 되면 사용하는 쪽의 코드가 좀 더 간결해집니다. 빈을 등록하는 쪽에 &lt;code&gt;HttpServiceProxyFactory&lt;/code&gt;를 빌드하여 api client를 반환하는 코드가 들어가 있습니다(자세한 코드는 &lt;a href=&quot;https://github.com/aka-nick/http-interface-practice/blob/a9b22898ccf3647391bbda08530d9741a806c1f0/src/main/java/springclient/apicall/ApicallApplication.java&quot;&gt;깃헙&lt;/a&gt;을 확인해주세요.).&lt;br /&gt;이렇게 사용하는 쪽에서 구체적인 구현이 어떻게 되는지 기술할 필요가 없게 되면, 비즈니스 로직에만 집중할 수 있게 되고, 결과적으로는 코드의 의미가 더 명확해집니다. 좀 더 Spring스럽다고 할 수 있겠네요.  &lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;결론&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처리할 트래픽이 매우 높은 상황이 아니라면, 성능에 있어서 유의미한 차이를 느끼기는 어려울 것 같습니다. '편리한 도구'라는 점과 '깔끔한 코드'의 사이에서 적절한 선택을 하면 될 것 같습니다. 만약 Spring 6를 사용할 수 있는 환경이 주어진다면, HttpInterface의 사용도 고려할 것 같네요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실은 직접 사용할 어떤 도구가 필요해서 구현하려던 차에 마침 토비님의 영상을 보게 된 것이라, HttpInterface를 바로 적용해볼 것 같아요. 다음에는 해당 도구를 만들고 사용한 기록을 남겨봐도 재밌겠네요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;긴 글 읽어주셔서 감사합니다.  &lt;/p&gt;</description>
      <category>각종 학습 요약/Spring</category>
      <category>Api 호출</category>
      <category>HttpInterface</category>
      <category>Spring 6</category>
      <author>닉Nick</author>
      <guid isPermaLink="true">https://sslblog.tistory.com/213</guid>
      <comments>https://sslblog.tistory.com/213#entry213comment</comments>
      <pubDate>Fri, 17 Mar 2023 14:12:17 +0900</pubDate>
    </item>
  </channel>
</rss>