<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>성장하는 맛이 있지</title>
    <link>https://this-is-another-one.tistory.com/</link>
    <description>배우는게 즐거운 사람의 로그입니다.</description>
    <language>ko</language>
    <pubDate>Mon, 15 Jun 2026 09:40:06 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>J_yoonS</managingEditor>
    <image>
      <title>성장하는 맛이 있지</title>
      <url>https://tistory1.daumcdn.net/tistory/6851118/attach/6d0bf3507b62481587a49b4ac2f54a04</url>
      <link>https://this-is-another-one.tistory.com</link>
    </image>
    <item>
      <title>[코드트리 후기] 북마크 학습 루틴 만들기</title>
      <link>https://this-is-another-one.tistory.com/entry/%EC%BD%94%EB%93%9C%ED%8A%B8%EB%A6%AC-%ED%9B%84%EA%B8%B0-%EB%B6%81%EB%A7%88%ED%81%AC-%ED%95%99%EC%8A%B5-%EB%A3%A8%ED%8B%B4-%EB%A7%8C%EB%93%A4%EA%B8%B0</link>
      <description>&lt;p data-path-to-node=&quot;5&quot; data-ke-size=&quot;size16&quot;&gt;코딩 테스트 플랫폼을 이용하다 보면 학업 스케줄로 인해 학습 흐름이 자주 끊겼다. 며칠 만에 다시 접속하면 이전에 어디까지 공부했는지, 어떤 부분에서 막혔었는지 기억이 나지 않아 감을 잡는 데 시간을 허비했다.&lt;/p&gt;
&lt;p data-path-to-node=&quot;5&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-path-to-node=&quot;4&quot; data-ke-size=&quot;size16&quot;&gt;코드트리의 &lt;b data-index-in-node=&quot;6&quot; data-path-to-node=&quot;4&quot;&gt;북마크 기능&lt;/b&gt;은 끊어진 학습 흐름을 바로 연결해주는 시스템적 도구였다.&lt;/p&gt;
&lt;p data-path-to-node=&quot;4&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-path-to-node=&quot;5&quot; data-ke-size=&quot;size16&quot;&gt;학습 도중 완벽히 이해하지 못했거나 나중에 다시 봐야 할 문제를 폴더별로 즉시 지정해 저장했다. 이 방식을 통해 시간이 부족한 평일에는 취약 지점을 마킹만 해두고, 여유가 생기는 시점에 북마크 대시보드만 열어 곧바로 복습을 재개할 수 있었다.&lt;/p&gt;
&lt;p data-path-to-node=&quot;5&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-path-to-node=&quot;5&quot; data-ke-size=&quot;size23&quot;&gt;효율적인 복습을 위한 북마크 분류 기준&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2075&quot; data-origin-height=&quot;327&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/DROlv/dJMcacciIYw/LqwzrB2rnujJk0sH4QTgs0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/DROlv/dJMcacciIYw/LqwzrB2rnujJk0sH4QTgs0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/DROlv/dJMcacciIYw/LqwzrB2rnujJk0sH4QTgs0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FDROlv%2FdJMcacciIYw%2FLqwzrB2rnujJk0sH4QTgs0%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;2075&quot; height=&quot;327&quot; data-origin-width=&quot;2075&quot; data-origin-height=&quot;327&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2077&quot; data-origin-height=&quot;341&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/WQyWa/dJMcadoFW2X/Vqkujt28p7OTxiGt6tR1b0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/WQyWa/dJMcadoFW2X/Vqkujt28p7OTxiGt6tR1b0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/WQyWa/dJMcadoFW2X/Vqkujt28p7OTxiGt6tR1b0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FWQyWa%2FdJMcadoFW2X%2FVqkujt28p7OTxiGt6tR1b0%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;2077&quot; height=&quot;341&quot; data-origin-width=&quot;2077&quot; data-origin-height=&quot;341&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;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;9,0,0&quot;&gt;완벽하지 않은 문제&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;9,0,1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;겨우 맞혔거나 구현 시간이 오래 걸려 추후 재도전이 필요한 문제&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;다시 풀기&lt;/b&gt;&lt;br /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;9,2,1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;시간적 여유가 있을 때 타이머를 켜고 혼자 힘으로 다시 풀어볼 문제&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-path-to-node=&quot;11&quot; data-ke-size=&quot;size16&quot;&gt;시간이 부족할 때는 새로운 문제를 무리하게 풀기보다, 북마크 폴더에 모아둔 문제들을 나란히 열어두고 구조적 차이점만 직관적으로 비교했다. 시스템의 모아보기 기능을 활용하는 것만으로도 복습의 밀도가 높아졌다.&lt;/p&gt;
&lt;p data-path-to-node=&quot;11&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-path-to-node=&quot;12&quot; data-ke-size=&quot;size23&quot;&gt;시스템 기반의 유연한 복습 루틴&lt;/h3&gt;
&lt;p data-path-to-node=&quot;13&quot; data-ke-size=&quot;size16&quot;&gt;매일 일정량의 진도를 나가야 한다는 압박감에서 벗어나, 학업 일정에 맞춘 유연한 프로세스를 정립했다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-path-to-node=&quot;14&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;14,0,0&quot;&gt;트레일 학습 및 마킹 (평일)&lt;/b&gt; : 새로운 개념을 학습하며 정체되었던 문제를 예외 없이 북마크에 저장했다.&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;14,1,0&quot;&gt;북마크 대시보드 체크 (공백기)&lt;/b&gt; : 풀이 시간이 부족한 날에는 새로운 문제를 푸는 대신 북마크된 취약점 리스트를 눈으로 검토했다.&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;14,2,0&quot;&gt;집중 복습 및 해결 (주말)&lt;/b&gt; : 학업 과제가 끝난 여유 시간에 북마크 시스템을 열어 저장된 문제들을 집중적으로 풀었다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-path-to-node=&quot;15&quot; data-ke-size=&quot;size16&quot;&gt;이번 주는 학업 스케줄로 인해 목표 XP를 채우지 못하는 날이 많았다. 하지만 북마크 시스템에 취약 문제들이 시각화되어 저장되어 있었기 때문에, 진도가 멈춘 상태에서도 불안감 없이 효율적으로 복습을 진행할 수 있었다.&lt;/p&gt;
&lt;p data-path-to-node=&quot;15&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-path-to-node=&quot;15&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;깃허브 연동을 통한 학습 기록&lt;/h3&gt;
&lt;p data-path-to-node=&quot;18&quot; data-ke-size=&quot;size16&quot;&gt;매일매일 빈틈없이 잔디를 심는 연속성 시스템에 얽매이지 않았다. 대신 연동해둔 &lt;b data-index-in-node=&quot;44&quot; data-path-to-node=&quot;18&quot;&gt;깃허브(GitHub) 자동 기록 기능&lt;/b&gt;을 통해, 간헐적으로 공부하더라도 학습 흔적이 누적되는 것에 의미를 두었다.&lt;/p&gt;
&lt;p data-path-to-node=&quot;19&quot; data-ke-size=&quot;size16&quot;&gt;주말이나 여유 시간에 몰아서 해결한 문제들이 깃허브에 한꺼번에 기록되는 것을 보며 나름의 학업 밸런스를 확인했다. 스트릭 기능에 스트레스를 받기보다, 코드트리의 시스템을 개인 라이프스타일에 맞춰 유연하게 변형하여 활용했다.&lt;/p&gt;
&lt;h4 data-path-to-node=&quot;19&quot; data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h3 data-path-to-node=&quot;19&quot; data-ke-size=&quot;size23&quot;&gt;총평&lt;/h3&gt;
&lt;p data-path-to-node=&quot;22&quot; data-ke-size=&quot;size16&quot;&gt;코드트리는 매일 꾸준히 풀 수 있는 사용자뿐만 아니라, 학업 등으로 인해 간헐적으로 공부할 수밖에 없는 환경에서도 유용한 시스템을 제공했다.&lt;/p&gt;
&lt;p data-path-to-node=&quot;23&quot; data-ke-size=&quot;size16&quot;&gt;내가 멈춘 지점을 기억해주는 &lt;b data-index-in-node=&quot;16&quot; data-path-to-node=&quot;23&quot;&gt;트레일&lt;/b&gt;, 끊어진 흐름을 이어주는 &lt;b data-index-in-node=&quot;34&quot; data-path-to-node=&quot;23&quot;&gt;북마크&lt;/b&gt;, 속도에 맞춰 누적되는 &lt;b data-index-in-node=&quot;51&quot; data-path-to-node=&quot;23&quot;&gt;깃 연동&lt;/b&gt; 기능이 유기적으로 맞물려 독학 페이스를 유지하는 데 도움이 되었다. 앞으로도 시스템 기능을 적극 활용하여 나만의 속도로 학습을 이어갈 계획이다.&lt;/p&gt;
&lt;p data-path-to-node=&quot;23&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-path-to-node=&quot;23&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.codetree.ai/ko/no-free-lunch-2026/?ref=5R8GAC&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.codetree.ai/ko/no-free-lunch-2026/?ref=5R8GAC&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1780790999682&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;3년 만에 돌아온, 코드트리 청약 통장 챌린지 | 코드트리&quot; data-og-description=&quot;매주 학습 납입하고 7주 만기 채우면 코드트리 8월까지 무료. 매주 추첨권을 모아 맥북&amp;middot;에어팟&amp;middot;애플워치 응모까지. 신청 인원에 따라 조기마감될 수 있어요.&quot; data-og-host=&quot;www.codetree.ai&quot; data-og-source-url=&quot;https://www.codetree.ai/ko/no-free-lunch-2026/?ref=5R8GAC&quot; data-og-url=&quot;https://www.codetree.ai/ko/no-free-lunch-2026/?ref=5R8GAC&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/cd9PK3/dJMb83SqKhi/WrZdMkDFsdTvViPlCPscfk/img.png?width=3600&amp;amp;height=1890&amp;amp;face=0_0_3600_1890,https://scrap.kakaocdn.net/dn/buhj6O/dJMb82eUK6r/nBroWH7S0fDRtwsX99kqrK/img.png?width=3600&amp;amp;height=1890&amp;amp;face=0_0_3600_1890&quot;&gt;&lt;a href=&quot;https://www.codetree.ai/ko/no-free-lunch-2026/?ref=5R8GAC&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.codetree.ai/ko/no-free-lunch-2026/?ref=5R8GAC&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/cd9PK3/dJMb83SqKhi/WrZdMkDFsdTvViPlCPscfk/img.png?width=3600&amp;amp;height=1890&amp;amp;face=0_0_3600_1890,https://scrap.kakaocdn.net/dn/buhj6O/dJMb82eUK6r/nBroWH7S0fDRtwsX99kqrK/img.png?width=3600&amp;amp;height=1890&amp;amp;face=0_0_3600_1890');&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;3년 만에 돌아온, 코드트리 청약 통장 챌린지 | 코드트리&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;매주 학습 납입하고 7주 만기 채우면 코드트리 8월까지 무료. 매주 추첨권을 모아 맥북&amp;middot;에어팟&amp;middot;애플워치 응모까지. 신청 인원에 따라 조기마감될 수 있어요.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.codetree.ai&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 링크로 코드트리 통약 챌린지 참여하기!&lt;/p&gt;</description>
      <category>개발/코딩테스트</category>
      <category>공부습관</category>
      <category>오답노트</category>
      <category>코드트리</category>
      <category>코딩테스트</category>
      <category>코테공부</category>
      <author>J_yoonS</author>
      <guid isPermaLink="true">https://this-is-another-one.tistory.com/18</guid>
      <comments>https://this-is-another-one.tistory.com/entry/%EC%BD%94%EB%93%9C%ED%8A%B8%EB%A6%AC-%ED%9B%84%EA%B8%B0-%EB%B6%81%EB%A7%88%ED%81%AC-%ED%95%99%EC%8A%B5-%EB%A3%A8%ED%8B%B4-%EB%A7%8C%EB%93%A4%EA%B8%B0#entry18comment</comments>
      <pubDate>Sun, 7 Jun 2026 09:11:04 +0900</pubDate>
    </item>
    <item>
      <title>[코테 공부] 잔디 심기로 코딩테스트 1일 1문제 습관 형성하기 (feat. 코드트리)</title>
      <link>https://this-is-another-one.tistory.com/entry/%EC%BD%94%ED%85%8C-%EA%B3%B5%EB%B6%80-%EC%9E%94%EB%94%94-%EC%8B%AC%EA%B8%B0%EB%A1%9C-%EC%BD%94%EB%94%A9%ED%85%8C%EC%8A%A4%ED%8A%B8-1%EC%9D%BC-1%EB%AC%B8%EC%A0%9C-%EC%8A%B5%EA%B4%80-%ED%98%95%EC%84%B1%ED%95%98%EA%B8%B0-feat-%EC%BD%94%EB%93%9C%ED%8A%B8%EB%A6%AC</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;청약챌린지 3주차이다. 3회차 미션을 진행하며 가장 크게 느낀 점은, 코딩테스트 공부에서 중요한 것은 '매일 엄청난 양을 푸는 것'이 아니라 '흐름이 끊기더라도 다시 공부방으로 돌아오는 루틴을 만드는 것'이다. 그리고 코드트리가 제공하는 여러 동기부여 장치들이 이 루틴을 유지하는 데 매우 현실적인 도움이 되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;1. 학습 의지를 깨우는 카톡 리마인더&lt;/h4&gt;
&lt;p data-path-to-node=&quot;9&quot; data-ke-size=&quot;size16&quot;&gt;일과가 바쁘다 보면 &quot;오늘 알고리즘 문제 풀어야지&quot; 하는 생각조차 잊어버릴 때가 많다. 그때 도착하는 코드트리의 알림톡 리마인더는 공부 흐름이 완전히 끊기지 않도록 붙잡아주는 역할을 해준다.&lt;/p&gt;
&lt;p data-path-to-node=&quot;9&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-path-to-node=&quot;10&quot; data-ke-size=&quot;size16&quot;&gt;설령 시간이 부족해 문제를 직접 풀지 못하는 날이더라도, 알림을 보고 접속하여 개념 설명을 다시 읽거나 이전 오답 해설을 복기하는 식으로 학습 밀도를 유지할 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-path-to-node=&quot;10&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;491&quot; data-origin-height=&quot;715&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b3DC3v/dJMb997EGAl/nKVEk9dU6bb1WOzlRxKT7k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b3DC3v/dJMb997EGAl/nKVEk9dU6bb1WOzlRxKT7k/img.png&quot; data-alt=&quot;이런식으로 알림이 온다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b3DC3v/dJMb997EGAl/nKVEk9dU6bb1WOzlRxKT7k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb3DC3v%2FdJMb997EGAl%2FnKVEk9dU6bb1WOzlRxKT7k%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;287&quot; height=&quot;418&quot; data-origin-width=&quot;491&quot; data-origin-height=&quot;715&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;h4 data-ke-size=&quot;size20&quot;&gt;2. 깃허브(GitHub) 잔디 심기 공식 연동&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개발자로서 기술 역량을 기록하고 꾸준함을 증명하는 데 있어 GitHub의 초록색 잔디는 매우 직관적인 지표이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기존에는 외부 확장 프로그램을 사용하여 풀이를 연동하곤 했는데, 코드트리는 플랫폼 내부에서 공식적으로 Repository 연동 및 폴더명 커스텀 설정을 지원하여 굉장히 편리하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;503&quot; data-origin-height=&quot;219&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bXxlGZ/dJMcadB7EmN/uM3TrZ2lZpNGc7IJvOdB10/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bXxlGZ/dJMcadB7EmN/uM3TrZ2lZpNGc7IJvOdB10/img.png&quot; data-alt=&quot;5월달은 코드트리 덕분이라 해도 과언이 아니다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bXxlGZ/dJMcadB7EmN/uM3TrZ2lZpNGc7IJvOdB10/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbXxlGZ%2FdJMcadB7EmN%2FuM3TrZ2lZpNGc7IJvOdB10%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;411&quot; height=&quot;179&quot; data-origin-width=&quot;503&quot; data-origin-height=&quot;219&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;5월달은 코드트리 덕분이라 해도 과언이 아니다.&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;&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;제출한 정답 코드가 자동으로 GitHub에 커밋되는 것을 보며, 내가 투자한 시간이 증발하지 않고 기록으로 남는다는 것을 확실히 느낄 수 있었다. 가장 좋은 점은 문제가 폴더별로 깔끔히 정리되어 내가 풀었던 문제들을 직관적으로 볼 수 있다는 점이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&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/b1Pozr/dJMcabj9pRH/dyDRKKc4y51wpWcS3mIbEK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b1Pozr/dJMcabj9pRH/dyDRKKc4y51wpWcS3mIbEK/img.png&quot; data-origin-width=&quot;335&quot; data-origin-height=&quot;730&quot; data-is-animation=&quot;false&quot; data-widthpercent=&quot;21.06&quot; style=&quot;width: 20.8176%; margin-right: 10px;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b1Pozr/dJMcabj9pRH/dyDRKKc4y51wpWcS3mIbEK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb1Pozr%2FdJMcabj9pRH%2FdyDRKKc4y51wpWcS3mIbEK%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;335&quot; height=&quot;730&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/G3sr4/dJMcad3eSfF/6yoksX9ItEv0DqGaTqhsW1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/G3sr4/dJMcad3eSfF/6yoksX9ItEv0DqGaTqhsW1/img.png&quot; data-origin-width=&quot;1013&quot; data-origin-height=&quot;589&quot; data-is-animation=&quot;false&quot; style=&quot;width: 78.0196%;&quot; data-widthpercent=&quot;78.94&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/G3sr4/dJMcad3eSfF/6yoksX9ItEv0DqGaTqhsW1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FG3sr4%2FdJMcad3eSfF%2F6yoksX9ItEv0DqGaTqhsW1%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;1013&quot; height=&quot;589&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;맨 왼쪽 사진처럼 문제가 폴더별로 정리되고, 해당 폴더에 들어가면 자동으로 README에 남겨진다.&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;811&quot; data-origin-height=&quot;1240&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bckydq/dJMcabYJXyG/F57AUiFVPWSj6CAPHuBgdK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bckydq/dJMcabYJXyG/F57AUiFVPWSj6CAPHuBgdK/img.png&quot; data-alt=&quot;내가 어떻게 풀었는지 자동으로 기록된다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bckydq/dJMcabYJXyG/F57AUiFVPWSj6CAPHuBgdK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbckydq%2FdJMcabYJXyG%2FF57AUiFVPWSj6CAPHuBgdK%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;389&quot; height=&quot;595&quot; data-origin-width=&quot;811&quot; data-origin-height=&quot;1240&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;내가 어떻게 풀었는지 자동으로 기록된다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-path-to-node=&quot;15&quot; data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-path-to-node=&quot;15&quot; data-ke-size=&quot;size20&quot;&gt;3. 고립감을 해소하는 라이브 챌린지 현황 및 단체 미션&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-path-to-node=&quot;16&quot; data-ke-size=&quot;size16&quot;&gt;혼자서 문제를 풀다 보면 쉽게 지치기 마련이다. 하지만 코드트리 대시보드에서는 다른 참여자들이 실시간으로 문제를 풀고 학습하는 현황이 라이브로 업데이트되어 자연스러운 자극을 받을 수 있다.&lt;/p&gt;
&lt;p data-path-to-node=&quot;17&quot; data-ke-size=&quot;size16&quot;&gt;특히 이번 3회차에는 공동 경험치 10만을 모아 함께 보상을 받는 단체 미션이 존재하여, 개인 학습임에도 불구하고 '다 함께 참여하고 있다'는 유대감을 느낄 수 있었다.&lt;/p&gt;
&lt;p data-path-to-node=&quot;17&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1003&quot; data-origin-height=&quot;408&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xs1XB/dJMcahEAjHt/9pRXHekUFwxYGr3aKLFIW1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xs1XB/dJMcahEAjHt/9pRXHekUFwxYGr3aKLFIW1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xs1XB/dJMcahEAjHt/9pRXHekUFwxYGr3aKLFIW1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fxs1XB%2FdJMcahEAjHt%2F9pRXHekUFwxYGr3aKLFIW1%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;1003&quot; height=&quot;408&quot; data-origin-width=&quot;1003&quot; data-origin-height=&quot;408&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;
&lt;p data-path-to-node=&quot;31&quot; data-ke-size=&quot;size16&quot;&gt;이번 3회차를 하면서 느낀점은 &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;코드트리의 시스템이 &lt;/span&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;꾸준한 학습 습관을 유지하는데 분명히 도움되는 플랫폼이라는 점이다&lt;/span&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-path-to-node=&quot;31&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;학업과 과제, 프로젝트를 병행하다 보면 현실적으로 변수가 많아서 &lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;쉽지 않겠지만, 코드트리의 알림톡과 동기부여 장치들을 활용해 매일 작은 문제라도 풀어나가며 문제 푸는 습관을 형성할 계획이다. 4주차까지 아자아자!&lt;/span&gt;&lt;/p&gt;
&lt;p data-path-to-node=&quot;31&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-path-to-node=&quot;31&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;&lt;a href=&quot;https://www.codetree.ai/ko/no-free-lunch-2026/?ref=5R8GAC&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.codetree.ai/ko/no-free-lunch-2026/?ref=5R8GAC&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1780305814586&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;3년 만에 돌아온, 코드트리 청약 통장 챌린지 | 코드트리&quot; data-og-description=&quot;매주 학습 납입하고 7주 만기 채우면 코드트리 8월까지 무료. 매주 추첨권을 모아 맥북&amp;middot;에어팟&amp;middot;애플워치 응모까지. 신청 인원에 따라 조기마감될 수 있어요.&quot; data-og-host=&quot;www.codetree.ai&quot; data-og-source-url=&quot;https://www.codetree.ai/ko/no-free-lunch-2026/?ref=5R8GAC&quot; data-og-url=&quot;https://www.codetree.ai/ko/no-free-lunch-2026/?ref=5R8GAC&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/oAX3m/dJMb8Rj9bg6/MhrAomzH4vpfuGGUd7Rkwk/img.png?width=3600&amp;amp;height=1890&amp;amp;face=0_0_3600_1890,https://scrap.kakaocdn.net/dn/bZbfVS/dJMb9cBO56O/k1ZlIt0Iw6TZANxbkUKvO0/img.png?width=3600&amp;amp;height=1890&amp;amp;face=0_0_3600_1890&quot;&gt;&lt;a href=&quot;https://www.codetree.ai/ko/no-free-lunch-2026/?ref=5R8GAC&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.codetree.ai/ko/no-free-lunch-2026/?ref=5R8GAC&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/oAX3m/dJMb8Rj9bg6/MhrAomzH4vpfuGGUd7Rkwk/img.png?width=3600&amp;amp;height=1890&amp;amp;face=0_0_3600_1890,https://scrap.kakaocdn.net/dn/bZbfVS/dJMb9cBO56O/k1ZlIt0Iw6TZANxbkUKvO0/img.png?width=3600&amp;amp;height=1890&amp;amp;face=0_0_3600_1890');&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;3년 만에 돌아온, 코드트리 청약 통장 챌린지 | 코드트리&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;매주 학습 납입하고 7주 만기 채우면 코드트리 8월까지 무료. 매주 추첨권을 모아 맥북&amp;middot;에어팟&amp;middot;애플워치 응모까지. 신청 인원에 따라 조기마감될 수 있어요.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.codetree.ai&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt; 상기 링크로 코드트리 이용이 가능합니다!&lt;/p&gt;</description>
      <category>개발/코딩테스트</category>
      <category>1일1코테</category>
      <category>개발자루틴</category>
      <category>코드트리</category>
      <category>코딩테스트</category>
      <category>코테공부</category>
      <category>코테독학</category>
      <author>J_yoonS</author>
      <guid isPermaLink="true">https://this-is-another-one.tistory.com/17</guid>
      <comments>https://this-is-another-one.tistory.com/entry/%EC%BD%94%ED%85%8C-%EA%B3%B5%EB%B6%80-%EC%9E%94%EB%94%94-%EC%8B%AC%EA%B8%B0%EB%A1%9C-%EC%BD%94%EB%94%A9%ED%85%8C%EC%8A%A4%ED%8A%B8-1%EC%9D%BC-1%EB%AC%B8%EC%A0%9C-%EC%8A%B5%EA%B4%80-%ED%98%95%EC%84%B1%ED%95%98%EA%B8%B0-feat-%EC%BD%94%EB%93%9C%ED%8A%B8%EB%A6%AC#entry17comment</comments>
      <pubDate>Mon, 1 Jun 2026 18:24:48 +0900</pubDate>
    </item>
    <item>
      <title>[코드트리] Sorting(정렬) 알고리즘 약점 극복 학습 후기</title>
      <link>https://this-is-another-one.tistory.com/entry/%EC%BD%94%EB%93%9C%ED%8A%B8%EB%A6%AC-Sorting%EC%A0%95%EB%A0%AC-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%EC%95%BD%EC%A0%90-%EA%B7%B9%EB%B3%B5-%ED%95%99%EC%8A%B5-%ED%9B%84%EA%B8%B0</link>
      <description>&lt;p data-ke-size=&quot;size18&quot;&gt;코드트리 챌린지를 시작하면서 Sorting 챕터부터 학습을 진행했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;솔직히 정렬은 쉬울 거라 생각했는데 생각보다 챙겨야 할 게 많았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;코드트리 커리큘럼 구조&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;Trail 2. 여기서부터 알고리즘 학습이다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;Functions부터 시작해서 Recursive Functions &amp;rarr; Sorting &amp;rarr; Simulation &amp;rarr; Exhaustive Search &amp;rarr; Case Work &amp;rarr; Ad-Hoc 순서로 이어진다.&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/v2RcC/dJMcabj2fuD/ovOXHQo8MN86lKS8YnKjRK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/v2RcC/dJMcabj2fuD/ovOXHQo8MN86lKS8YnKjRK/img.png&quot; data-origin-width=&quot;273&quot; data-origin-height=&quot;630&quot; data-is-animation=&quot;false&quot; width=&quot;162&quot; data-widthpercent=&quot;33.9&quot; style=&quot;width: 33.5016%; margin-right: 10px;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/v2RcC/dJMcabj2fuD/ovOXHQo8MN86lKS8YnKjRK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fv2RcC%2FdJMcabj2fuD%2FovOXHQo8MN86lKS8YnKjRK%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;273&quot; height=&quot;630&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b9OMBj/dJMcah5B6VD/QHpNyuDozOAnHxDKWOkw9k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b9OMBj/dJMcah5B6VD/QHpNyuDozOAnHxDKWOkw9k/img.png&quot; data-origin-width=&quot;862&quot; data-origin-height=&quot;1020&quot; data-is-animation=&quot;false&quot; style=&quot;width: 65.3356%;&quot; data-widthpercent=&quot;66.1&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b9OMBj/dJMcah5B6VD/QHpNyuDozOAnHxDKWOkw9k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb9OMBj%2FdJMcah5B6VD%2FQHpNyuDozOAnHxDKWOkw9k%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;862&quot; height=&quot;1020&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;Trail은 선택할 수 있어서 자신의 수준이나 목표에 맞게 시작점을 고를 수 있다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;단순히 문제만 나열하는 방식이 아니라, 각 챕터 안에서 &lt;b&gt;기본 &amp;rarr; 연습 &amp;rarr; 테스트 순서로 문제가 구성&lt;/b&gt;되어 있어서 개념을 익히고 바로 적용해보는 흐름이 자연스럽게 만들어진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;처음에는 이 구조가 그냥 문제 묶음처럼 보였는데, 직접 따라가보니 기본 문제에서 개념을 잡고, 연습 문제에서 조건이 조금씩 붙고, 테스트 문제에서 내가 진짜 이해했는지 확인하는 흐름이 꽤 잘 설계되어 있다는 걸 느꼈다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Sorting 학습에서 달라진 풀이 감각&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1910&quot; data-origin-height=&quot;995&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bLUeOS/dJMcajoHKzb/ZKGjsJKQOVtQtpvaaM1aJ0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bLUeOS/dJMcajoHKzb/ZKGjsJKQOVtQtpvaaM1aJ0/img.png&quot; data-alt=&quot;실제 학습 화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bLUeOS/dJMcajoHKzb/ZKGjsJKQOVtQtpvaaM1aJ0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbLUeOS%2FdJMcajoHKzb%2FZKGjsJKQOVtQtpvaaM1aJ0%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;1910&quot; height=&quot;995&quot; data-origin-width=&quot;1910&quot; data-origin-height=&quot;995&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;실제 학습 화면&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;기본 문제에서 Arrays.sort() 감각을 익혔다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;예를 들어 기본 문제인 오름내림차순 정렬은 이렇게 풀었다.&lt;/p&gt;
&lt;pre id=&quot;code_1779414307081&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Arrays.sort(arr);
for (int i = 0; i &amp;lt; n; i++) {
    System.out.print(arr[i] + &quot; &quot;);
}
System.out.println();

for (int i = n - 1; i &amp;gt;= 0; i--) {
    System.out.print(arr[i] + &quot; &quot;);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;처음엔 내림차순을 따로 다시 정렬해야 하는 줄 알았는데,&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;오름차순 정렬 후 역순으로 출력하면 된다는 걸 이때 정리했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;정렬은 쉬워 보이지만 막상 문제에 적용하려고 하면 헷갈리는 부분이 생겼다. 단순히 오름차순, 내림차순 정렬만 하면 되는 줄 알았는데, 기준이 두 개 이상이거나 특정 조건에 따라 정렬 방식이 바뀌는 경우에는 처음 접근 자체가 달라져야 했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;기본 문제에서는 Arrays.sort() 같은 내장 함수를 활용하는 감각을 익혔고, 연습 문제로 넘어가면서 comparator를 직접 구현하거나 정렬 기준을 세분화하는 연습을 했다. 테스트 문제에서는 정렬만으로 해결이 되는 문제인지, 아니면 정렬 이후 추가 처리가 필요한지를 판단하는 게 중요했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;이 과정에서 정렬 문제를 볼 때 &lt;b&gt;&quot;뭘 기준으로 정렬할 것인가&quot;를 먼저 정리하고 코드를 작성하는 습관이 조금씩 생겼다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;기본 &amp;rarr; 연습 &amp;rarr; 테스트를 따라가며&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;코드트리에서 좋았던 점은 같은 개념을 반복하되, 매번 조금씩 다른 방식으로 적용해볼 수 있다는 점이었다. 기본 문제만 풀었을 때는 &quot;이거 알겠는데?&quot; 싶었는데, 테스트 문제에서 막히는 경우가 있었다. 그때 내가 개념을 몰라서 틀린 건지, 구현을 실수한 건지를 구분할 수 있어서 다음에 뭘 보완해야 할지가 명확해졌다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;해설과 모범코드를 내 코드랑 비교해보는 것도 도움이 됐다. 같은 결과를 내더라도 훨씬 간결하게 쓰는 방식을 보면서 내 풀이에서 불필요한 부분이 어디인지 확인할 수 있었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;다른 서비스와 비교했을 때&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;백준이나 프로그래머스는 문제는 많지만 내가 뭘 먼저 풀어야 할지 기준이 없어서, 결국 아무 문제나 풀다가 방향을 잃는 경우가 많았다. 코드트리는 커리큘럼 순서가 잡혀 있어서 일단 따라가기만 하면 된다는 점이 달랐다. 특히 어떤 유형이 약한지 갭체크로 확인하고 거기서부터 시작할 수 있다는 게 실질적으로 도움이 됐다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;a href=&quot;https://www.codetree.ai/ko/no-free-lunch-2026/?ref=5R8GAC&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.codetree.ai/ko/no-free-lunch-2026/?ref=5R8GAC&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1779414434146&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;3년 만에 돌아온, 코드트리 청약 통장 챌린지 | 코드트리&quot; data-og-description=&quot;매주 학습 납입하고 7주 만기 채우면 코드트리 8월까지 무료. 매주 추첨권을 모아 맥북&amp;middot;에어팟&amp;middot;애플워치 응모까지. 신청 인원에 따라 조기마감될 수 있어요.&quot; data-og-host=&quot;www.codetree.ai&quot; data-og-source-url=&quot;https://www.codetree.ai/ko/no-free-lunch-2026/?ref=5R8GAC&quot; data-og-url=&quot;https://www.codetree.ai/ko/no-free-lunch-2026/?ref=5R8GAC&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/elgjci/dJMb89yjxuQ/Jk4RfJETgwKS0C10rbTck1/img.png?width=3600&amp;amp;height=1890&amp;amp;face=0_0_3600_1890,https://scrap.kakaocdn.net/dn/ebTSV7/dJMb88GaUlr/yRqJp0TfQ0jH90UZqXFHx0/img.png?width=3600&amp;amp;height=1890&amp;amp;face=0_0_3600_1890&quot;&gt;&lt;a href=&quot;https://www.codetree.ai/ko/no-free-lunch-2026/?ref=5R8GAC&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.codetree.ai/ko/no-free-lunch-2026/?ref=5R8GAC&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/elgjci/dJMb89yjxuQ/Jk4RfJETgwKS0C10rbTck1/img.png?width=3600&amp;amp;height=1890&amp;amp;face=0_0_3600_1890,https://scrap.kakaocdn.net/dn/ebTSV7/dJMb88GaUlr/yRqJp0TfQ0jH90UZqXFHx0/img.png?width=3600&amp;amp;height=1890&amp;amp;face=0_0_3600_1890');&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;3년 만에 돌아온, 코드트리 청약 통장 챌린지 | 코드트리&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;매주 학습 납입하고 7주 만기 채우면 코드트리 8월까지 무료. 매주 추첨권을 모아 맥북&amp;middot;에어팟&amp;middot;애플워치 응모까지. 신청 인원에 따라 조기마감될 수 있어요.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.codetree.ai&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 링크를 통해 갭체크 테스트가 가능하다.  &lt;/p&gt;</description>
      <category>개발/코딩테스트</category>
      <category>Sorting</category>
      <category>솔직후기</category>
      <category>알고리즘기초</category>
      <category>정렬</category>
      <category>코드트리</category>
      <category>코딩테스트</category>
      <category>코테공부</category>
      <author>J_yoonS</author>
      <guid isPermaLink="true">https://this-is-another-one.tistory.com/16</guid>
      <comments>https://this-is-another-one.tistory.com/entry/%EC%BD%94%EB%93%9C%ED%8A%B8%EB%A6%AC-Sorting%EC%A0%95%EB%A0%AC-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%EC%95%BD%EC%A0%90-%EA%B7%B9%EB%B3%B5-%ED%95%99%EC%8A%B5-%ED%9B%84%EA%B8%B0#entry16comment</comments>
      <pubDate>Fri, 22 May 2026 10:49:19 +0900</pubDate>
    </item>
    <item>
      <title>[코드트리 솔직후기] 왕초보의 코딩테스트, 갭체크로 실력 진단받기</title>
      <link>https://this-is-another-one.tistory.com/entry/%EC%BD%94%EB%93%9C%ED%8A%B8%EB%A6%AC-%EC%86%94%EC%A7%81%ED%9B%84%EA%B8%B0-%EC%99%95%EC%B4%88%EB%B3%B4%EC%9D%98-%EC%BD%94%EB%94%A9%ED%85%8C%EC%8A%A4%ED%8A%B8-%EA%B0%AD%EC%B2%B4%ED%81%AC%EB%A1%9C-%EC%8B%A4%EB%A0%A5-%EC%A7%84%EB%8B%A8%EB%B0%9B%EA%B8%B0</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;a href=&quot;https://www.codetree.ai/ko&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.codetree.ai/ko&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1778891013501&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;Codetree: Master Coding Interviews - Data Structures &amp;amp; Algorithms&quot; data-og-description=&quot;Master algorithms, ace tech interviews, and elevate your coding skills with Codetree's systematic curriculum and expert-crafted problem sets.&quot; data-og-host=&quot;www.codetree.ai&quot; data-og-source-url=&quot;https://www.codetree.ai/ko&quot; data-og-url=&quot;https://www.codetree.ai/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/QwjGV/dJMb9llchtt/rib2DTKpkeLltgIoE9KexK/img.png?width=1400&amp;amp;height=1400&amp;amp;face=0_0_1400_1400,https://scrap.kakaocdn.net/dn/bfCyel/dJMb9dHtjpD/0w0R42BDyN8UMpH2BjewKK/img.png?width=1400&amp;amp;height=1400&amp;amp;face=0_0_1400_1400&quot;&gt;&lt;a href=&quot;https://www.codetree.ai/ko&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.codetree.ai/ko&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/QwjGV/dJMb9llchtt/rib2DTKpkeLltgIoE9KexK/img.png?width=1400&amp;amp;height=1400&amp;amp;face=0_0_1400_1400,https://scrap.kakaocdn.net/dn/bfCyel/dJMb9dHtjpD/0w0R42BDyN8UMpH2BjewKK/img.png?width=1400&amp;amp;height=1400&amp;amp;face=0_0_1400_1400');&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;Codetree: Master Coding Interviews - Data Structures &amp;amp; Algorithms&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Master algorithms, ace tech interviews, and elevate your coding skills with Codetree's systematic curriculum and expert-crafted problem sets.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.codetree.ai&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;UI도 깔끔하고 무엇보다 들어가자마자 눈에 띈 &lt;b&gt;'갭 체크 진단'&amp;nbsp;&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;코딩테스트는 1년전에 부트캠프 다닐때 테스트 겸 봤던게 처음이자 마지막이었던지라 내 (처참한)실력이 어느정도인지&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;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2536&quot; data-origin-height=&quot;1348&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bnxWxR/dJMcabYyaff/5Zy0Dylk3bYPuxi9yl40iK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bnxWxR/dJMcabYyaff/5Zy0Dylk3bYPuxi9yl40iK/img.png&quot; data-alt=&quot;첫번째 문제&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bnxWxR/dJMcabYyaff/5Zy0Dylk3bYPuxi9yl40iK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbnxWxR%2FdJMcabYyaff%2F5Zy0Dylk3bYPuxi9yl40iK%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;687&quot; height=&quot;365&quot; data-origin-width=&quot;2536&quot; data-origin-height=&quot;1348&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;본인의 실력, 어떤 방향으로 향상시키고자 하는 방향을 선택 한 후 화면을 넘기면&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;&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;&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1509&quot; data-origin-height=&quot;1150&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cCKfaD/dJMb99TV85J/G5Sd5R9v7l1UGYkrHvqmCK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cCKfaD/dJMb99TV85J/G5Sd5R9v7l1UGYkrHvqmCK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cCKfaD/dJMb99TV85J/G5Sd5R9v7l1UGYkrHvqmCK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcCKfaD%2FdJMb99TV85J%2FG5Sd5R9v7l1UGYkrHvqmCK%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;666&quot; height=&quot;508&quot; data-origin-width=&quot;1509&quot; data-origin-height=&quot;1150&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;
&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;논리적 사고가 부족한 나는 3번째 문제부터 어려워져서 뭐.. 결국 거의 포기한 것과 다름 없고 결과는!..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1398&quot; data-origin-height=&quot;1099&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bcGsRE/dJMcagldpra/K8LZ0w6TOqUTrHiOWiTlEk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bcGsRE/dJMcagldpra/K8LZ0w6TOqUTrHiOWiTlEk/img.png&quot; data-alt=&quot;네,,그래요 놀랍지 않군요&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bcGsRE/dJMcagldpra/K8LZ0w6TOqUTrHiOWiTlEk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbcGsRE%2FdJMcagldpra%2FK8LZ0w6TOqUTrHiOWiTlEk%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;746&quot; height=&quot;586&quot; data-origin-width=&quot;1398&quot; data-origin-height=&quot;1099&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;이런식으로 적나라하게(?) 내가 무엇이 부족하고 어떤 개념을 길러야하는지 가감없이 코멘트를 달아준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1243&quot; data-origin-height=&quot;1101&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cp6Tym/dJMb997tHIE/RJZBgnkXJgAI3IVbatk3u1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cp6Tym/dJMb997tHIE/RJZBgnkXJgAI3IVbatk3u1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cp6Tym/dJMb997tHIE/RJZBgnkXJgAI3IVbatk3u1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcp6Tym%2FdJMb997tHIE%2FRJZBgnkXJgAI3IVbatk3u1%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;620&quot; height=&quot;549&quot; data-origin-width=&quot;1243&quot; data-origin-height=&quot;1101&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;
&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1465&quot; data-origin-height=&quot;1197&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bbZRuW/dJMcaiJ4xhY/BafkTODfWFANy4r2a1KAy1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bbZRuW/dJMcaiJ4xhY/BafkTODfWFANy4r2a1KAy1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bbZRuW/dJMcaiJ4xhY/BafkTODfWFANy4r2a1KAy1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbbZRuW%2FdJMcaiJ4xhY%2FBafkTODfWFANy4r2a1KAy1%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;650&quot; height=&quot;531&quot; data-origin-width=&quot;1465&quot; data-origin-height=&quot;1197&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;
&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;874&quot; data-origin-height=&quot;1014&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/byhThz/dJMcahdnGOB/fw4ev2rkCTniB5KAaQrcz1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/byhThz/dJMcahdnGOB/fw4ev2rkCTniB5KAaQrcz1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/byhThz/dJMcahdnGOB/fw4ev2rkCTniB5KAaQrcz1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbyhThz%2FdJMcahdnGOB%2Ffw4ev2rkCTniB5KAaQrcz1%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;551&quot; height=&quot;639&quot; data-origin-width=&quot;874&quot; data-origin-height=&quot;1014&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;
&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;물론 그 개념이 if 문부터 시작이라 스스로 회의감이 들기는 하지만 ㅎㅎ..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런들 어찌하리 &lt;b&gt;어제보다 더 나은 내일&lt;/b&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;
&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1240&quot; data-origin-height=&quot;682&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cux6dY/dJMcaffBj6m/2IKtHUb49iXZpJ6510tky0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cux6dY/dJMcaffBj6m/2IKtHUb49iXZpJ6510tky0/img.png&quot; data-alt=&quot;이런식으로 풀더별로 문제를 모아볼 수 있다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cux6dY/dJMcaffBj6m/2IKtHUb49iXZpJ6510tky0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcux6dY%2FdJMcaffBj6m%2F2IKtHUb49iXZpJ6510tky0%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;695&quot; height=&quot;382&quot; data-origin-width=&quot;1240&quot; data-origin-height=&quot;682&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;이런식으로 풀더별로 문제를 모아볼 수 있다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;무엇보다.. 깃허브 커밋까지 지원하여 내가 맞춘 문제만 자동커밋할 수 있다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;즉 꾸준히 문제만 풀면&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;깃허브 잔디로 내 성실함까지 증명이 가능하다!&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1261&quot; data-origin-height=&quot;313&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bVKISn/dJMb99M8FNR/sVZUrXnbre5ko5DyQp6b7K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bVKISn/dJMb99M8FNR/sVZUrXnbre5ko5DyQp6b7K/img.png&quot; data-alt=&quot;정확히 4일전 부터 코드트리를 시작하여..&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bVKISn/dJMb99M8FNR/sVZUrXnbre5ko5DyQp6b7K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbVKISn%2FdJMb99M8FNR%2FsVZUrXnbre5ko5DyQp6b7K%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;662&quot; height=&quot;164&quot; data-origin-width=&quot;1261&quot; data-origin-height=&quot;313&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;정확히 4일전 부터 코드트리를 시작하여..&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;개발자라면 알것이다.. 깃허브에 잔디가 쌓일때 느끼는 그 뿌듯함이란..ㅎㅎ&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.codetree.ai/ko/no-free-lunch-2026/?ref=5R8GAC&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.codetree.ai/ko/no-free-lunch-2026/?ref=5R8GAC&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1778893514880&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;3년 만에 돌아온, 코드트리 청약 통장 챌린지 | 코드트리&quot; data-og-description=&quot;매주 학습 납입하고 7주 만기 채우면 코드트리 8월까지 무료. 매주 추첨권을 모아 맥북&amp;middot;에어팟&amp;middot;애플워치 응모까지. 신청 인원에 따라 조기마감될 수 있어요.&quot; data-og-host=&quot;www.codetree.ai&quot; data-og-source-url=&quot;https://www.codetree.ai/ko/no-free-lunch-2026/?ref=5R8GAC&quot; data-og-url=&quot;https://www.codetree.ai/ko/no-free-lunch-2026/?ref=5R8GAC&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/99ffQ/dJMb8TCeTkH/FMJ0MEZ8ykjYOCgfu4p2o1/img.png?width=3600&amp;amp;height=1890&amp;amp;face=0_0_3600_1890,https://scrap.kakaocdn.net/dn/cNO9Ya/dJMb8RRW4u2/zf5DfhuJvsX7P4iVATuhRK/img.png?width=3600&amp;amp;height=1890&amp;amp;face=0_0_3600_1890&quot;&gt;&lt;a href=&quot;https://www.codetree.ai/ko/no-free-lunch-2026/?ref=5R8GAC&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.codetree.ai/ko/no-free-lunch-2026/?ref=5R8GAC&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/99ffQ/dJMb8TCeTkH/FMJ0MEZ8ykjYOCgfu4p2o1/img.png?width=3600&amp;amp;height=1890&amp;amp;face=0_0_3600_1890,https://scrap.kakaocdn.net/dn/cNO9Ya/dJMb8RRW4u2/zf5DfhuJvsX7P4iVATuhRK/img.png?width=3600&amp;amp;height=1890&amp;amp;face=0_0_3600_1890');&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;3년 만에 돌아온, 코드트리 청약 통장 챌린지 | 코드트리&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;매주 학습 납입하고 7주 만기 채우면 코드트리 8월까지 무료. 매주 추첨권을 모아 맥북&amp;middot;에어팟&amp;middot;애플워치 응모까지. 신청 인원에 따라 조기마감될 수 있어요.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.codetree.ai&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;b&gt;추천코드: 5R8GAC&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;링크를 통해 가입하고 &lt;b&gt;추천코드를 입력하면 500포인트를 얻을 수 있습니다.&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #3f3f3f;&quot;&gt;추가로 문제를 풀때마다 추천인과 가입자 모두 +5 포인트를 받을 수 있는데,&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #3f3f3f;&quot;&gt;전 매일 같이 문제를 풀고 있기 때문에 &lt;/span&gt;&lt;span style=&quot;color: #3f3f3f;&quot;&gt;가입자에게도 좋은 추천인 제도입니다!&lt;/span&gt;&lt;b&gt;&lt;span style=&quot;color: #3f3f3f;&quot;&gt; ☺️&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&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/Ll9tk/dJMcabxtjvh/DAXmuqSHMuT4aJVs9FZjek/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Ll9tk/dJMcabxtjvh/DAXmuqSHMuT4aJVs9FZjek/img.png&quot; width=&quot;252&quot; height=&quot;465&quot; data-origin-width=&quot;358&quot; data-origin-height=&quot;660&quot; data-is-animation=&quot;false&quot; data-widthpercent=&quot;32.87&quot; data-filename=&quot;blob&quot; style=&quot;width: 32.1072%; margin-right: 10px;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Ll9tk/dJMcabxtjvh/DAXmuqSHMuT4aJVs9FZjek/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FLl9tk%2FdJMcabxtjvh%2FDAXmuqSHMuT4aJVs9FZjek%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;358&quot; height=&quot;660&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/vfKg0/dJMcabK5fmc/Gv9X7rEnQLuNasXeY9LMqk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/vfKg0/dJMcabK5fmc/Gv9X7rEnQLuNasXeY9LMqk/img.png&quot; data-origin-width=&quot;375&quot; data-origin-height=&quot;664&quot; data-is-animation=&quot;false&quot; data-widthpercent=&quot;34.23&quot; data-filename=&quot;blob&quot; style=&quot;width: 33.4292%; margin-right: 10px;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/vfKg0/dJMcabK5fmc/Gv9X7rEnQLuNasXeY9LMqk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FvfKg0%2FdJMcabK5fmc%2FGv9X7rEnQLuNasXeY9LMqk%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;375&quot; height=&quot;664&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bH1txN/dJMcadIKK9p/wbKPwlnvkaKl7JlDgzmOV1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bH1txN/dJMcadIKK9p/wbKPwlnvkaKl7JlDgzmOV1/img.png&quot; data-origin-width=&quot;354&quot; data-origin-height=&quot;652&quot; data-is-animation=&quot;false&quot; data-widthpercent=&quot;32.9&quot; data-filename=&quot;blob&quot; style=&quot;width: 32.138%;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bH1txN/dJMcadIKK9p/wbKPwlnvkaKl7JlDgzmOV1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbH1txN%2FdJMcadIKK9p%2FwbKPwlnvkaKl7JlDgzmOV1%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;354&quot; height=&quot;652&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;매일 출석체크 인증!&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #3f3f3f; letter-spacing: 0px;&quot;&gt;이 글을 읽고 온 초보개발자, 취업준비생, &lt;/span&gt;&lt;span style=&quot;color: #3f3f3f; text-align: start;&quot;&gt;신입개발자 혹은 성장하길 바라길 누군가!&lt;/span&gt;&lt;/p&gt;
&lt;div style=&quot;color: #2c2c2c; text-align: start;&quot;&gt;
&lt;p style=&quot;color: #3f3f3f;&quot; data-ke-size=&quot;size16&quot;&gt;모두 같이 열심히 준비하여 꼭 원하는 목표를 이루길 바랍니다 :)&lt;/p&gt;
&lt;figure contenteditable=&quot;false&quot; data-ke-type=&quot;emoticon&quot; data-ke-align=&quot;alignCenter&quot; data-emoticon-type=&quot;friends2&quot; data-emoticon-name=&quot;034&quot; data-emoticon-isanimation=&quot;false&quot; data-emoticon-src=&quot;https://t1.daumcdn.net/axz_keditor/emoticon/friends2/large/034.png&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/axz_keditor/emoticon/friends2/large/034.png&quot; width=&quot;150&quot; /&gt;&lt;/figure&gt;
&lt;p style=&quot;color: #3f3f3f;&quot; data-ke-size=&quot;size16&quot;&gt;어제보다 더 나은 내일의 나를 꿈꾸며&lt;/p&gt;
&lt;p style=&quot;color: #3f3f3f;&quot; data-ke-size=&quot;size16&quot;&gt;앞으로도 꾸준히 코딩테스트 공부한 내용을 적도록 하겠습니다!&lt;/p&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>개발/코딩테스트</category>
      <category>개발일지</category>
      <category>개발자기본기쌓기</category>
      <category>백준서비스종료</category>
      <category>알고리즘공부</category>
      <category>코드트리</category>
      <category>코딩테스트</category>
      <category>코테공부</category>
      <category>코테준비</category>
      <author>J_yoonS</author>
      <guid isPermaLink="true">https://this-is-another-one.tistory.com/15</guid>
      <comments>https://this-is-another-one.tistory.com/entry/%EC%BD%94%EB%93%9C%ED%8A%B8%EB%A6%AC-%EC%86%94%EC%A7%81%ED%9B%84%EA%B8%B0-%EC%99%95%EC%B4%88%EB%B3%B4%EC%9D%98-%EC%BD%94%EB%94%A9%ED%85%8C%EC%8A%A4%ED%8A%B8-%EA%B0%AD%EC%B2%B4%ED%81%AC%EB%A1%9C-%EC%8B%A4%EB%A0%A5-%EC%A7%84%EB%8B%A8%EB%B0%9B%EA%B8%B0#entry15comment</comments>
      <pubDate>Sat, 16 May 2026 10:09:04 +0900</pubDate>
    </item>
    <item>
      <title>개인프로젝트 AWS EC2 배포 후기 (Spring Boot + React)</title>
      <link>https://this-is-another-one.tistory.com/entry/%EA%B0%9C%EC%9D%B8%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-AWS-EC2-%EB%B2%A0%ED%8F%AC-%ED%9B%84%EA%B8%B0-Spring-Boot-React</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;배포경험은 처음이기에 초보자가 접근하기 쉽다는 AWS EC2로 개인프로젝트를 배포했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://aws.amazon.com/ec2/&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://aws.amazon.com/ec2/&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1778632006664&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;Amazon EC2 - 클라우드 컴퓨팅 용량 - AWS&quot; data-og-description=&quot;Amazon EC2는 프로세서, 스토리지, 네트워킹, OS 및 구매 모델의 다양한 옵션을 제공하며, 클라우드에서 안전하고 크기 조정 가능한 컴퓨팅을 제공합니다.&quot; data-og-host=&quot;aws.amazon.com&quot; data-og-source-url=&quot;https://aws.amazon.com/ec2/&quot; data-og-url=&quot;https://aws.amazon.com/ko/ec2/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/b4sBIL/dJMb8WeEukB/sm0ZE3MusSFwtBX3ML0BKK/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=900_124_984_216&quot;&gt;&lt;a href=&quot;https://aws.amazon.com/ec2/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://aws.amazon.com/ec2/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/b4sBIL/dJMb8WeEukB/sm0ZE3MusSFwtBX3ML0BKK/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=900_124_984_216');&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;Amazon EC2 - 클라우드 컴퓨팅 용량 - AWS&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Amazon EC2는 프로세서, 스토리지, 네트워킹, OS 및 구매 모델의 다양한 옵션을 제공하며, 클라우드에서 안전하고 크기 조정 가능한 컴퓨팅을 제공합니다.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;aws.amazon.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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt; 1. AWS EC2 인스턴스 생성&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;AWS EC2 인스턴스 생성 (t2.micro, Ubuntu, 서울 리전)&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;보안 그룹 포트 오픈: 22(SSH), 80(HTTP), 443(HTTPS), 8080(Spring Boot)&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1) AWS EC2 인스턴스 생성&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;6개월간은 Free plan이 가능하여 새로 가입을 했는데 region을 잘못보고 Sydney 로 설정하여&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다시 Seoul로 설정한 뒤 재포를 했다. 헛수고 하지 않기 위해 꼭 &lt;b&gt;&lt;span style=&quot;background-color: #fffacd;&quot;&gt;Region 확인 후 'Launch instance'&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1249&quot; data-origin-height=&quot;682&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/y8gfj/dJMcabjURbZ/4mXBiloYJCtnJv1eCutGeK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/y8gfj/dJMcabjURbZ/4mXBiloYJCtnJv1eCutGeK/img.png&quot; data-alt=&quot;상단에 있는 'Asia Pacific(Seoul)&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/y8gfj/dJMcabjURbZ/4mXBiloYJCtnJv1eCutGeK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fy8gfj%2FdJMcabjURbZ%2F4mXBiloYJCtnJv1eCutGeK%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;664&quot; height=&quot;682&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1249&quot; data-origin-height=&quot;682&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;상단에 있는 'Asia Pacific(Seoul)&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;Instance Luanch 과정에서 생성된 .pem키는 꼭 잘 저장해놓도록 하자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;EC2 환경에 빌드할때 필요하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Public IP 또한 EC2에 올릴때 필요하다.&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;b&gt;2) 인바운드 규칙 탭 추가하기&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;HTTPS&lt;/b&gt; 포트 443 &amp;rarr; 0.0.0.0/0&lt;/li&gt;
&lt;li&gt;&lt;b&gt;HTTP&lt;/b&gt; 포트 80 &amp;rarr; 0.0.0.0/0&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Custom TCP&lt;/b&gt; 포트 8080 &amp;rarr; 0.0.0.0/0&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt; 2. EC2 환경 설정&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;SWAP 메모리 설정 (t2.micro 메모리 부족 대비)&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Java 17 설치&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;MySQL 설치 및 DB 생성, 비밀번호 설정&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최대한 free plan 한도에서 진행하려 하니 터미널이 자주 멈추는 현상이 발생했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #fffacd;&quot;&gt;찾아보니 &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;t2.micro 메모리가 1GB밖에 안 돼서 Spring Boot를 띄우는 것만으로도 벅찬 것 같아 &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #fffacd;&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;SWAP 메모리를 띠로 설정해 주었다.&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;*SWAP은 EC2 안에 있는 디스크를 메모리처럼 쓰는 것.&lt;/span&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1) SWAP 메모리 설정&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1778632951651&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sudo fallocate -l 1G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile&lt;/code&gt;&lt;/pre&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;b&gt;2) 프로젝트는 Java17 과 MySQL 로 설정 했기때문에 클라우드 환경에도 동일하게 설치해준다.&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1778633561486&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sudo apt update
sudo apt install -y openjdk-17-jdk
sudo apt install -y mysql-server&lt;/code&gt;&lt;/pre&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;b&gt;3) MySQL 접속하여 DB와 유저 설정을 한다.&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1778633661142&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sudo mysql&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;접속되면, root 비밀번호 설정&lt;/p&gt;
&lt;pre id=&quot;code_1778633682942&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;CREATE DATABASE workout_diary;
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'yourpassword';
FLUSH PRIVILEGES;
EXIT;&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;3. DB 마이그레이션&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;MySQL Workbench로 로컬 DB export&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;scp로 EC2에 업로드&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;EC2에서 import&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #fffacd;&quot;&gt; Windows에서 SQL 파일을 export하면 파일 앞에 보이지 않는 특수문자가 붙는다. MySQL이 이걸 읽으면 에러가 난다.&lt;/span&gt; mysqldump 명령어로 해결하려 했지만 계속 실패해서 결국 &lt;span style=&quot;background-color: #fffacd;&quot;&gt;&lt;b&gt;MySQL Workbench로 export하니 해결됐다&lt;/b&gt;. &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;&lt;b&gt; 1) DB export&lt;/b&gt; -&amp;gt; 파일을 export 해서 EC2 환경에 올린다. (MySQL Workbench 접속)&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;Dump Data Only &amp;rarr; &lt;b&gt;Dump Structure and Data&lt;/b&gt; 로 변경&lt;/li&gt;
&lt;li&gt;Export to Self-Contained File 선택 (단일 파일로)&lt;/li&gt;
&lt;li&gt;Include Create Schema 체크&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Start Export&lt;/b&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt; 클릭!&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;2) scp로 EC2에 올리기&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1778634376974&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;scp -i &quot;C:\Users\dhwkd\workout server.pem&quot; &quot;C:\Users\dhwkd\OneDrive\문서\dumps\Dump20260511.sql&quot; ubuntu@your-ec2-ip:~&lt;/code&gt;&lt;/pre&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;b&gt;3) EC2 터미널에서 DB import&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1778634615453&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;mysql -u root -p'your-password' workout_diary &amp;lt; ~/Dump20260512.sql&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;4. Spring Boot 배포&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;application.properties 수정 (SSL 비활성화, 포트 8080)&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;CORS 설정 (배포 URL 추가)&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;mvnw clean package -DskipTests 빌드&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;scp로 jar 파일 업로드&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;nohup java -jar 백그라운드 실행&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Spring Boot 배포전에 application.properties 포트번호 변경, CORS 설정에 배포 URL을 추가한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;b&gt;*도메인은 Duck DNS 의 무료 도메인을 이용했다. (계정 한개당 1개 무료 도메인 가능)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1) 포트번호, 배포 URL 추가&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1778634841832&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# Server web port
server.port=8080&lt;/code&gt;&lt;/pre&gt;
&lt;div style=&quot;background-color: #fdf6e3; color: #657b83;&quot;&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;configuration.setAllowedOrigins(Arrays.asList(
        &quot;https://localhost:3000&quot;,
        &quot;https://dailylift.duckdns.org&quot;
));&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div style=&quot;background-color: #fdf6e3; color: #657b83;&quot;&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;private String[] theAllowedOrigins = {
        &quot;https://localhost:3000&quot;,
        &quot;https://dailylift.duckdns.org&quot;
};&lt;/code&gt;&lt;/pre&gt;
&lt;/div&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;b&gt;2) Spring Boot 빌드 &amp;gt;&amp;nbsp;&lt;/b&gt; &lt;b&gt;jar파일 EC2에 업로드&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1778635329784&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;cd C:\exercise-library\02-backend\workout-diary\workout-diary
.\mvnw.cmd clean package -DskipTests&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_1778635373697&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;scp -i &quot;C:\Users\dhwkd\gymrat server.pem&quot; &quot;C:\exercise-library\02-backend\workout-diary\workout-diary\target\diary-0.0.1-SNAPSHOT.jar&quot; ubuntu@your-ec2-ip:~&lt;/code&gt;&lt;/pre&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;b&gt;3) nohup java -jar 백그라운드 실행&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1778635523997&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sudo cp -r ~/build/* /var/www/html/
nohup java -jar ~/diary-0.0.1-SNAPSHOT.jar &amp;gt; ~/app.log 2&amp;gt;&amp;amp;1 &amp;amp;&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;5. React 배포&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;.env.production 생성 (배포 API URL)&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;npm run build 빌드&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;scp로 build 폴더 업로드&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Nginx로 정적 파일 서빙&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1) .env.production 생성&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #fffacd;&quot;&gt;기존에 .env 파일만 존재했는데, 이럴 경우 &lt;b&gt;배포 주소와 local 환경 테스트를 분리&lt;/b&gt;할 수가 없어서&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #fffacd;&quot;&gt;매번 포트번호를 수정하는게 불편하여 &lt;b&gt;.env.production 과 .env 파일로 나누었다.&lt;/b&gt;&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;size14&quot;&gt;&lt;b&gt;[React 환경 변수 우선순위]&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;npm start (로컬) &amp;rarr; .env.local &amp;gt; .env&lt;/li&gt;
&lt;li&gt;npm run build (빌드) &amp;rarr; .env.production &amp;gt; .env&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;b&gt;따라서 파일을 나눠서 관리한다&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;.env &amp;rarr; REACT_APP_API='http://localhost:8080/api' (로컬용)&lt;/li&gt;
&lt;li&gt;.env.production &amp;rarr; REACT_APP_API='&lt;a href=&quot;https://jane-workout.duckdns.org/api'&quot;&gt;https://dailylift.duckdns.org/api'&lt;/a&gt; (배포용)&lt;/li&gt;
&lt;/ul&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;b&gt;2) npm run build 빌드 &amp;gt; PowerShell-EC2에 업로드&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1778637027288&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;cd C:\exercise-library\03-frontend\react-library
npm run build&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1778637062203&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;scp -i &quot;C:\Users\dhwkd\workout server.pem&quot; -r &quot;C:\exercise-library\03-frontend\react-library\build&quot; ubuntu@52.64.44.192:~&lt;/code&gt;&lt;/pre&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;b&gt;3) Nginx 설치 &amp;gt; React 파일 복사 &amp;gt; Nginx 설정&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1778636838358&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sudo apt install -y nginx&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1778636913440&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sudo cp -r ~/build/* /var/www/html/&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1778636921914&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sudo tee /etc/nginx/sites-available/default &amp;lt;&amp;lt; 'EOF'
server {
    listen 80;
    server_name gymrat.duckdns.org;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    server_name gymrat.duckdns.org;

    ssl_certificate /etc/letsencrypt/live/gymrat.duckdns.org/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/gymrat.duckdns.org/privkey.pem;

    location / {
        root /var/www/html;
        index index.html;
        try_files $uri $uri/ /index.html;
    }

    location /api {
        proxy_pass http://localhost:8080;
    }
}
EOF&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;6. 도메인 &amp;amp; HTTPS&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;DuckDNS 무료 도메인 생성&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Let's Encrypt SSL 인증서 발급 (certbot)&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Nginx 설정 (HTTP &amp;rarr; HTTPS 리다이렉트, API 프록시)&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1) DuckDNS 무료 도메인 생성&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;a href=&quot;https://www.duckdns.org/&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.duckdns.org/&lt;/a&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;gt; 도메인 설정 후, EC2 IP 주소를 입력한다.&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;span style=&quot;background-color: #fffacd;&quot;&gt;&lt;b&gt; DuckDNS는 certbot 자동 인증이 안 돼서&lt;/b&gt; &lt;b&gt;수동으로 TXT 레코드를 등록해서 인증했다. &lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;certbot이 알려주는 값을 DuckDNS URL에 직접 입력하는 방식이다.&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;b&gt;2) SSL 인증서 받기 &amp;gt; certbot이 TXT레코드 값 알려주면 이메일 주소 입력 &amp;gt; Y&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1778637467755&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sudo apt install -y certbot python3-certbot-nginx
sudo systemctl stop nginx
sudo certbot certonly --manual --preferred-challenges dns -d dailylift.duckdns.org&lt;/code&gt;&lt;/pre&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;b&gt;3) DuckDNS에 TXT 레코드 추가하기 &amp;gt; URL에 입력 후 OK 뜨면 bash Enter 누르기&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1778637615990&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;https://www.duckdns.org/update?domains=dailylift&amp;amp;token=여기에토큰&amp;amp;txt=여기에TXT레코드&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;7. Auth0 설정&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Allowed Callback URLs 추가&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Allowed Logout URLs 추가&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Allowed Web Origins 추가&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;배포하면서 okta.oauth2.audience 를 배포 도메인으로 바꿨더니 401 에러가 발생했다. Auth0 API의 Identifier(http://localhost:8080)와 설정값이 달라서 토큰 검증이 실패한 것이었다. Identifier는 변경이 불가능하므로 Spring Boot와 &lt;b&gt;&lt;span style=&quot;background-color: #fffacd;&quot;&gt;React 설정을 다시 http://localhost:8080 으로 맞춰서 해결했다. &lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;8. 트러블슈팅&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 과정에서 겪은 주요 이슈들은 각 단계에 기재했으나 한눈에 보기 위해 정리했다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;SWAP 없으면 Spring Boot 실행 중 멈춤 (2번 참고)&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;BOM&amp;nbsp;문제로&amp;nbsp;SQL&amp;nbsp;import&amp;nbsp;실패&amp;nbsp;&amp;rarr;&amp;nbsp;Workbench&amp;nbsp;export로&amp;nbsp;해결&amp;nbsp;(3번&amp;nbsp;참고)&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;.env.production&amp;nbsp;vs&amp;nbsp;.env.local&amp;nbsp;우선순위&amp;nbsp;문제&amp;nbsp;(5번&amp;nbsp;참고)&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;SSL&amp;nbsp;인증서는&amp;nbsp;DuckDNS&amp;nbsp;CAA&amp;nbsp;문제로&amp;nbsp;manual&amp;nbsp;DNS&amp;nbsp;방식&amp;nbsp;사용&amp;nbsp;(6번&amp;nbsp;참고)&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Auth0 audience 불일치 &amp;rarr; http://localhost:8080 으로 맞춤 (7번 참고)&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>개발/배포</category>
      <category>AWS</category>
      <category>DuckDNS</category>
      <category>E2C</category>
      <category>https</category>
      <category>nginx</category>
      <category>React</category>
      <category>springboot</category>
      <category>ssl</category>
      <category>개발일지</category>
      <category>배포</category>
      <author>J_yoonS</author>
      <guid isPermaLink="true">https://this-is-another-one.tistory.com/14</guid>
      <comments>https://this-is-another-one.tistory.com/entry/%EA%B0%9C%EC%9D%B8%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-AWS-EC2-%EB%B2%A0%ED%8F%AC-%ED%9B%84%EA%B8%B0-Spring-Boot-React#entry14comment</comments>
      <pubDate>Wed, 13 May 2026 11:43:32 +0900</pubDate>
    </item>
    <item>
      <title>HTTP 와 REST 컨트롤러 (REST API 구현)</title>
      <link>https://this-is-another-one.tistory.com/entry/HTTP-%EC%99%80-REST-%EC%BB%A8%ED%8A%B8%EB%A1%A4%EB%9F%AC-REST-API-%EA%B5%AC%ED%98%84</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;HTTP 요청코드&lt;/b&gt;&lt;br /&gt;- 클라이언트가 보낸 요청이 성공했는지 실패했는지 알려주는 코드.&lt;br /&gt;- 응답은 100~500번대까지 5개의 그룹으로 나뉘어져 있다.&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 147px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 21px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 21px;&quot;&gt;&lt;b&gt;상태 코드&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 21px;&quot;&gt;&lt;b&gt;설명&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 21px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 21px;&quot;&gt;1XX(정보)&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 21px;&quot;&gt;요청이 수신돼 처리 중입니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 21px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 21px;&quot;&gt;2XX(성공)&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 21px;&quot;&gt;요청이 정상적으로 처리됐습니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 21px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 21px;&quot;&gt;3XX(리다이렉션 메시지)&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 21px;&quot;&gt;요청을 완료하려면 추가 행동이 필요합니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 21px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 21px;&quot;&gt;4XX(클라이언트 요청 오류)&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 21px;&quot;&gt;클라이언트의 요청이 잘못돼 서버가 요청을 수행할 수 없습니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 42px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 42px;&quot;&gt;5XX(서버 응답 오류)&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 42px;&quot;&gt;서버 내부에 에러가 발생해 클라이언트 요청에 대해 적절히&lt;br /&gt;수행하지 못했습니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;요청이 &lt;b&gt;성공했을 때 200&lt;/b&gt;, 데이터 &lt;b&gt;생성을 완료했을 때는 201 &lt;/b&gt;을 반환&lt;b&gt;.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;요청한 &lt;b&gt;정보를 찾을 수 없을 때 404, 서버에 오류가 났을 때 500&lt;/b&gt; 을 반환.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서버는 클랄이언트의 요청에 대한 응답으로 화면(view)가 아닌 데이터(data)를 사용하는데,&lt;br /&gt;이때 사용하는 응답 데이터가 &lt;b&gt;JSON(JavaScript Object Notation) &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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[JSON 데이터 예시]&lt;/p&gt;
&lt;pre id=&quot;code_1742430553203&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;{
    &quot;id&quot; : 1,
    &quot;name&quot; : &quot;Park&quot;,
    // 키 값으로 또 다른 JSON 데이터와 배열 사용 가능
    address : {
    		&quot;Street&quot;: &quot;Nambu Street 151&quot;,
            &quot;suite&quot;: &quot;Central Villat 301&quot;,
              ...
  	},
    &quot;likes&quot; : {&quot;singing&quot;, &quot;reading&quot;, &quot;writing&quot;}
}&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;REST API 의 응답 표준으로 사용하는 JSON 은 키와 값의 쌍으로 된 속성으로 데이터를 표현한다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;JSON 의 값으로 또 다른 JSON 데이터나 배열을 넣을 수 있다.&lt;/b&gt;&lt;/li&gt;
&lt;/ul&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;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;REST API 의 구현 과정&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;REST :&lt;/b&gt; HTTP URL로 서버의 자원(resource) 을 명시하고, &lt;b&gt;HTTP 메서드(POST, GET, PATCH/PUT, DELETE)&lt;/b&gt; 로 해당 자원에 대해 CRUD(생성, 조회, 수정, 삭제) 하는 것을 의미한다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;API :&lt;/b&gt; 클라이언트가 서버의 자원을 요청할 수 있도록 서버에서 제공하는 인터페이스(interface).&lt;/li&gt;
&lt;li&gt;&lt;b&gt;REST API :&lt;/b&gt; REST 기반으로 API를 구현한 것. -&amp;gt; &lt;b&gt;클라이언트가 기기에 구애받지 않고 서버의 자원을 이용할 수 있다.&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;REST API 를 구현하려면 URL (REST API의 주소) 을 설계해야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앞서 만든 Article 데이터를 CRUD(생성, 조회, 수정, 삭제) 하기 위해 &lt;u&gt;REST API 주소를 다음과 같이 설계한다.&lt;/u&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[REST API 설계]&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;&lt;b&gt;HTTP Method&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;&lt;b&gt; REST API URL &lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;GET (목록조회)&lt;/td&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;/api/articles&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;GET (단일조회)&lt;/td&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;/api/articles/{id}&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;POST (생성)&lt;/td&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;/api/articles&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;PATCH (수정)&lt;/td&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;/api/articles/{id}&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;DELETE (삭제)&lt;/td&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;/api/articles/{id}&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;설계를 끝냈다면, RestController를 생성한다.&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;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[api/ArticleApiController]&lt;/p&gt;
&lt;pre id=&quot;code_1742431754183&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@RestController
public class ArticleApiController {
    @Autowired
    private ArticleRepository articleRepository;
    // GET
    @GetMapping(&quot;/api/articles&quot;) 
    public List&amp;lt;Article&amp;gt; index() {
        return articleRepository.findAll();
    }&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Article 묶음을 반환하므로 반환형이 List&amp;lt;Article&amp;gt;인 index() 메서드를 정의한다.&lt;/li&gt;
&lt;li&gt;return 문에는 articleRepository 의 findAll() 메서드를 사용해 DB 에 저장된 모든 Article을 가져와 반환한다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;@Autowired :&lt;/b&gt; articleRepository 를 선언하기 위해 의존성을 주입한다.&lt;/li&gt;
&lt;/ul&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;[API tester]&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1437&quot; data-origin-height=&quot;251&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/HS5Kz/btsMPsisHJ3/ZAyvHkS0KqN9tuNJHlLG61/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/HS5Kz/btsMPsisHJ3/ZAyvHkS0KqN9tuNJHlLG61/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/HS5Kz/btsMPsisHJ3/ZAyvHkS0KqN9tuNJHlLG61/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FHS5Kz%2FbtsMPsisHJ3%2FZAyvHkS0KqN9tuNJHlLG61%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;654&quot; height=&quot;114&quot; data-origin-width=&quot;1437&quot; data-origin-height=&quot;251&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1359&quot; data-origin-height=&quot;1035&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bG0Q6T/btsMO85EeWR/6LIvrmSagKZPulUFKRgeXk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bG0Q6T/btsMO85EeWR/6LIvrmSagKZPulUFKRgeXk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bG0Q6T/btsMO85EeWR/6LIvrmSagKZPulUFKRgeXk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbG0Q6T%2FbtsMO85EeWR%2F6LIvrmSagKZPulUFKRgeXk%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;664&quot; height=&quot;506&quot; data-origin-width=&quot;1359&quot; data-origin-height=&quot;1035&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;GET 요청과 해당 URL 주소로 요청하면 JSON 형식으로 목록값이 잘 반환된다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[api/Article/ApiController]&lt;/p&gt;
&lt;pre id=&quot;code_1742432332442&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;    // POST
    @GetMapping(&quot;api/articles/{id}&quot;)
    public Article show(@PathVariable long id) {
        return articleRepostory.findById(id).orElse(null);
    }&lt;/code&gt;&lt;/pre&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;br /&gt;[API tester]&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1483&quot; data-origin-height=&quot;738&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bsgHXA/btsMQgnS09U/OyuT0sqdF7DBDbceTjaKDK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bsgHXA/btsMQgnS09U/OyuT0sqdF7DBDbceTjaKDK/img.png&quot; data-alt=&quot;단일값 조회 성공&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bsgHXA/btsMQgnS09U/OyuT0sqdF7DBDbceTjaKDK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbsgHXA%2FbtsMQgnS09U%2FOyuT0sqdF7DBDbceTjaKDK%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;1483&quot; height=&quot;738&quot; data-origin-width=&quot;1483&quot; data-origin-height=&quot;738&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;&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;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;조회에 이어 POST를 RestController에 구현해보자.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[api/ArticleApiController]&lt;/p&gt;
&lt;pre id=&quot;code_1742433105659&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;    @PostMapping(&quot;api/articles&quot;)
    public Article create(@RequestBody ArticleForm dto) {
        Article article = dto.toEntity();
        return articleRepository.save(article);
    }&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;@RequestBody :&lt;/b&gt; 요청 시 본문(Body)에 실어 보내는 데이터를 create() 메서드의 매개변수로 받기위해 선언.&lt;/li&gt;
&lt;li&gt;받은 dto를 DB에서 활용할 수 있도록 Entity로 변환해 article 에 넣고, articleRepository를 통해 DB에 저장.&lt;/li&gt;
&lt;/ul&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;[API tester]&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1365&quot; data-origin-height=&quot;963&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dVOKU4/btsMQByCoiU/g5WFn9sJjtL1IKSf4ZA5L1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dVOKU4/btsMQByCoiU/g5WFn9sJjtL1IKSf4ZA5L1/img.png&quot; data-alt=&quot;POST 요청 성공.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dVOKU4/btsMQByCoiU/g5WFn9sJjtL1IKSf4ZA5L1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdVOKU4%2FbtsMQByCoiU%2Fg5WFn9sJjtL1IKSf4ZA5L1%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;1365&quot; height=&quot;963&quot; data-origin-width=&quot;1365&quot; data-origin-height=&quot;963&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;POST 요청 성공.&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;&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;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PATCH, 수정 구현은 아래와 같다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[api/ArticleApiController]&lt;/p&gt;
&lt;div style=&quot;background-color: #1e1f22; color: #bcbec4;&quot;&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;// PATCH
@PatchMapping(&quot;api/articles/{id}&quot;)
public ResponseEntity&amp;lt;Article&amp;gt; update (@PathVariable long id, @RequestBody ArticleForm dto) {
    // 1. DTO -&amp;gt; Entity 변환하기
    Article article = articleRepository.toEntity(); // 서비스 통해 게시글 수정
    // 2. 타깃 조회하기
    Article target = articleRepository.findById(id).orElse(null);
    // 3. 잘못된 요청 처리하기
    if (target == null || id !=article.getId()) {
             return ResponseEntity.status(HttpStatus.BAD_REQUEST).build(null);
    // 4. 업데이트 및 정상 응답(200) 하기
    target.patch(article)
    Article updated = articleRepository.save(target);
    return ResponseEntity.status(HttpStatus.OK).body(updated);
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;ReponseEntity :&lt;/b&gt; Rest 컨트롤러의 반환형, 즉 RESP API 의 응답을 위해 사용하는 클래스이다.&lt;br /&gt;- REST API 요청을 받아 응답할 때 이 클래스에 HTTP 상태코드, 헤더, 본문을 실어 보낼 수 있다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;HTTPStatus :&lt;/b&gt; HTTP 상태 코드를 관리하는 클래스로, 다양한 Enum 타입과 관련한 메서드를 가진다.&lt;br /&gt;- 열거형으로, 여러 상수로 이루어진 고정 집합을 가진다.&lt;br /&gt;&lt;b&gt;- 200 : HTTPStatus.OK, &lt;br /&gt;- 201 : HTTPStatus.CREATED&lt;br /&gt;- 400 : HTTPStatus.BAD_REQUEST&amp;nbsp;&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;수정할 내용이 있는 경우에만 수정 가능하도록 patch() 메서드를 만들어준다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[entity/Article]&lt;/p&gt;
&lt;pre id=&quot;code_1742435666202&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public void patch(Article article) {
    if (article.getTitle() != null) {
        this.title = article.title;
    if  (article.getContent() != null) {
        this.content = article.content;
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;if 문으로 article(수정 Entity) 의 title 이 null 이 아닐 경우에만, this(target) 의 title을 갱신해 준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;*content 또한 동일.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[API tester]&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1450&quot; data-origin-height=&quot;957&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/RuEl3/btsMQzHwMCZ/t5boNtkzfFoLoAX0G5MSZk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/RuEl3/btsMQzHwMCZ/t5boNtkzfFoLoAX0G5MSZk/img.png&quot; data-alt=&quot;PATCH 요청 성공.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/RuEl3/btsMQzHwMCZ/t5boNtkzfFoLoAX0G5MSZk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FRuEl3%2FbtsMQzHwMCZ%2Ft5boNtkzfFoLoAX0G5MSZk%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;1450&quot; height=&quot;957&quot; data-origin-width=&quot;1450&quot; data-origin-height=&quot;957&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;PATCH 요청 성공.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;PATCH URL 의 id('1') 변수와 BODY 부분의 id ('1')&amp;nbsp; 요청이 일치해야 한다.&lt;/li&gt;
&lt;/ul&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;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마지막으로 DELETE 이다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[api/ArticleController]&lt;/p&gt;
&lt;pre id=&quot;code_1742436429026&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;    // DELETE
    @DeleteMapping(&quot;/api/articles/{id}&quot;)
    public ResponseEntity&amp;lt;Article&amp;gt; delete (@PathVariable long id) {
        // 1. 대상 찾기
        Article target = articleRepository.findById(id).orElse(null);
        // 2. 잘못된 요청 처리하기
        if (target == null) {
        return ResponseEntity.status(HTTPStatus.BAD_REQUEST).body(null);
        }
        // 3. 대상 삭제하기
        articleRepository.delete(target);
        return ReponseEntity.status(HTTPStatus.OK).build();
    }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;잘못된 요청일 경우 ResponseEntity 에 BAD_REQUEST, 본문(body) 에는 null 을 실어보낸다.&lt;/li&gt;
&lt;li&gt;잘못된 요청이 아닐 경우 대상 Entity 를 삭제한다.&lt;/li&gt;
&lt;li&gt;그리고 HTTPStatus.OK, 본문(body) 에는 null 대신 body 응답이 없는 객체를 생성한다. (즉, null과 동일)&lt;/li&gt;
&lt;/ul&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[API tester]&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1369&quot; data-origin-height=&quot;697&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bUTyiL/btsMPuN5D61/9oS68uDlb5NlrQhQs9Boz1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bUTyiL/btsMPuN5D61/9oS68uDlb5NlrQhQs9Boz1/img.png&quot; data-alt=&quot;DELETE 요청 완료.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bUTyiL/btsMPuN5D61/9oS68uDlb5NlrQhQs9Boz1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbUTyiL%2FbtsMPuN5D61%2F9oS68uDlb5NlrQhQs9Boz1%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;1369&quot; height=&quot;697&quot; data-origin-width=&quot;1369&quot; data-origin-height=&quot;697&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;DELETE 요청 완료.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;897&quot; data-origin-height=&quot;634&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b4HgIw/btsMPjeYNp8/Y2hawVD2O1KohKd8iCmh1k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b4HgIw/btsMPjeYNp8/Y2hawVD2O1KohKd8iCmh1k/img.png&quot; data-alt=&quot;DB 조회&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b4HgIw/btsMPjeYNp8/Y2hawVD2O1KohKd8iCmh1k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb4HgIw%2FbtsMPjeYNp8%2FY2hawVD2O1KohKd8iCmh1k%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;601&quot; height=&quot;425&quot; data-origin-width=&quot;897&quot; data-origin-height=&quot;634&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;DB 조회&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;DB 조회를 통해, id = 1 번열이 성공적으로 삭제 되었음을 확인할 수 있다.&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;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p style=&quot;text-align: right;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: right;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #222222; text-align: right;&quot;&gt;**출처 : 스프링부트3 자바 백엔드 개발 입문 (홍팍 지음)&amp;nbsp;&lt;/span&gt;&lt;/p&gt;</description>
      <category>개발/Spring boot</category>
      <author>J_yoonS</author>
      <guid isPermaLink="true">https://this-is-another-one.tistory.com/13</guid>
      <comments>https://this-is-another-one.tistory.com/entry/HTTP-%EC%99%80-REST-%EC%BB%A8%ED%8A%B8%EB%A1%A4%EB%9F%AC-REST-API-%EA%B5%AC%ED%98%84#entry13comment</comments>
      <pubDate>Thu, 20 Mar 2025 11:18:11 +0900</pubDate>
    </item>
    <item>
      <title>[게시판/삭제] 게시글 삭제하기</title>
      <link>https://this-is-another-one.tistory.com/entry/%EA%B2%8C%EC%8B%9C%ED%8C%90%EC%82%AD%EC%A0%9C-%EA%B2%8C%EC%8B%9C%EA%B8%80-%EC%82%AD%EC%A0%9C%ED%95%98%EA%B8%B0</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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;366&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cp5IJS/btsMP0xNZpm/v7yOV5LziyBO9LZouqskS1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cp5IJS/btsMP0xNZpm/v7yOV5LziyBO9LZouqskS1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cp5IJS/btsMP0xNZpm/v7yOV5LziyBO9LZouqskS1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcp5IJS%2FbtsMP0xNZpm%2Fv7yOV5LziyBO9LZouqskS1%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;1280&quot; height=&quot;366&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;366&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;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;클라이언트가 HTTP 메서드로 특정 게시글의 삭제를 요청한다.&lt;/li&gt;
&lt;li&gt;삭제 요청을 받은 컨트롤러는 repostiory를 통해 DB에 저장된 데이터를 찾아 삭제한다.(데이터가 있는 경우)&lt;/li&gt;
&lt;li&gt;삭제가 완료됐다면 클라이언트를 결과 페이지로 리다이렉트 한다.&lt;br /&gt;- 클라이언트에 삭제 완료 메시지도 띄어주기 위해 &lt;b&gt;RedirectAttributes 클래스&lt;/b&gt;를 사용한다.&lt;br /&gt;- 해당 클래스의 &lt;b&gt;addFlashAttribute()&lt;/b&gt;&amp;nbsp;메서드는 &lt;b&gt;리다이렉트 된 페이지에서 사용할 &lt;u&gt;일회성 데이터&lt;/u&gt;를 등록할 수 있다.&lt;br /&gt;&lt;br /&gt;&lt;/b&gt;&lt;/li&gt;
&lt;/ol&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;[articles/show.mustache]&lt;/p&gt;
&lt;pre id=&quot;code_1742350388790&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;a href=&quot;/articles/{{article.id}}/edit&quot; class=&quot;btn btn-primary&quot;&amp;gt;Edit&amp;lt;/a&amp;gt;
&amp;lt;a href=&quot;/articles/{{article.id}}/delete&quot; class=&quot;btn btn-danger&quot;&amp;gt;Delete&amp;lt;/a&amp;gt;
&amp;lt;a href=&quot;/articles&quot;&amp;gt;Go to Article List&amp;lt;/a&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;삭제 링크 URL를 추가한다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[controller/ArticleController]&lt;/p&gt;
&lt;pre id=&quot;code_1742350521962&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@GetMapping(&quot;/articles/{id}/delete&quot;)
    public String delete(@PathVariable Long id, RedirectAttributes rttr) {
        log.info(&quot;삭제 요청이 들어왔습니다&quot;);
        // 1. 삭제할 대상 가져오기
        Article target = articleRepository.findById(id).orElse(null);
        log.info(target.toString());
        // 2. 대상 엔터티 삭제하기
        if (target != null) {
            articleRepository.delete(target);
            rttr.addFlashAttribute(&quot;msg&quot;, &quot;삭제됐습니다!&quot;);
        }
        // 3. 결과 페이지로 리다이렉트하기
        return &quot;redirect:/articles&quot;;
    }&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;@PathVariable :&lt;/b&gt; 특정 게시글을 삭제하기 위해 대표값인 id 를 사용하기 위해 매개변수로 가져온다.&lt;/li&gt;
&lt;li&gt;articleRepository.findById(id) : DB에 해당 id를 가진 데이터를 찾는다.&lt;br /&gt;- 찾으면 Article 타입의 target 변수에 저장하고, 못 찾으면 null을 반환한다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;articleRepository.delete(target) :&lt;/b&gt; 메서드로 대상을 삭제한다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;RedirectAttributes&lt;/b&gt; 객체의 addFlashAttribute() 메서드를 활용하여 리다이렉트 시점에 한번에 사용할 데이터를 등록.&lt;br /&gt;- 객체명.addFlashAttributes(넘겨_주려는_키_문자열, 넘겨_주려는_값_객체)&lt;/li&gt;
&lt;/ul&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[layouts/header.mustache]&lt;/p&gt;
&lt;pre id=&quot;code_1742350962981&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;{{#msg}}
&amp;lt;div class=&quot;alert alert-primary alert-dismissible&quot;&amp;gt;
    {{msg}}
    &amp;lt;button type=&quot;button&quot; class=&quot;btn-close&quot; data-bs-dismiss=&quot;alert&quot; aria-label=&quot;Close&quot;&amp;gt;&amp;lt;/button&amp;gt;
&amp;lt;/div&amp;gt;
{{/msg}}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;{{#msg}} , {{/msg}} : msg 창 사용범위 지정.&lt;/li&gt;
&lt;li&gt;&amp;lt;div&amp;gt; 태그 : 메시지 창 작성.&lt;/li&gt;
&lt;/ul&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2072&quot; data-origin-height=&quot;561&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/s9cUi/btsMOifI9d2/rPNQZsiHaWOA84kkZkwUH1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/s9cUi/btsMOifI9d2/rPNQZsiHaWOA84kkZkwUH1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/s9cUi/btsMOifI9d2/rPNQZsiHaWOA84kkZkwUH1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fs9cUi%2FbtsMOifI9d2%2FrPNQZsiHaWOA84kkZkwUH1%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;2072&quot; height=&quot;561&quot; data-origin-width=&quot;2072&quot; data-origin-height=&quot;561&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;
&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;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p style=&quot;text-align: right;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #222222; text-align: right;&quot;&gt;**출처 : 스프링부트3 자바 백엔드 개발 입문 (홍팍 지음)&amp;nbsp;&lt;/span&gt;&lt;/p&gt;</description>
      <category>개발/Spring boot</category>
      <author>J_yoonS</author>
      <guid isPermaLink="true">https://this-is-another-one.tistory.com/12</guid>
      <comments>https://this-is-another-one.tistory.com/entry/%EA%B2%8C%EC%8B%9C%ED%8C%90%EC%82%AD%EC%A0%9C-%EA%B2%8C%EC%8B%9C%EA%B8%80-%EC%82%AD%EC%A0%9C%ED%95%98%EA%B8%B0#entry12comment</comments>
      <pubDate>Wed, 19 Mar 2025 11:30:18 +0900</pubDate>
    </item>
    <item>
      <title>[게시판/수정] 게시글 수정하기</title>
      <link>https://this-is-another-one.tistory.com/entry/%EA%B2%8C%EC%8B%9C%ED%8C%90%EC%88%98%EC%A0%95-%EA%B2%8C%EC%8B%9C%EA%B8%80-%EC%88%98%EC%A0%95%ED%95%98%EA%B8%B0</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. &amp;lt;수정 페이지&amp;gt; 만들고 기존 데이터 불러오기&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. 데이터를 수정해 DB 에 반영한 후 결과를 볼 수 있게 &amp;lt;상세 페이지&amp;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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1522&quot; data-origin-height=&quot;455&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/pT75q/btsMOO6f0Xr/3Oy8qxymyrHdJC3czoOucK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/pT75q/btsMOO6f0Xr/3Oy8qxymyrHdJC3czoOucK/img.png&quot; data-alt=&quot;1딘계 동작원리&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/pT75q/btsMOO6f0Xr/3Oy8qxymyrHdJC3czoOucK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FpT75q%2FbtsMOO6f0Xr%2F3Oy8qxymyrHdJC3czoOucK%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;1522&quot; height=&quot;455&quot; data-origin-width=&quot;1522&quot; data-origin-height=&quot;455&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;1딘계 동작원리&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1487&quot; data-origin-height=&quot;460&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dKckET/btsMP3gXJMs/UlJEvy4W7epIeSwraz3YN1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dKckET/btsMP3gXJMs/UlJEvy4W7epIeSwraz3YN1/img.png&quot; data-alt=&quot;2단계 동작원리&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dKckET/btsMP3gXJMs/UlJEvy4W7epIeSwraz3YN1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdKckET%2FbtsMP3gXJMs%2FUlJEvy4W7epIeSwraz3YN1%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;1487&quot; height=&quot;460&quot; data-origin-width=&quot;1487&quot; data-origin-height=&quot;460&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;2단계 동작원리&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1단계부터 구현해보자.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;상세페이지에 edit(수정) 으로 이동하는 링크를 연결한다.&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;[articles/show.mustahce]&lt;/p&gt;
&lt;pre id=&quot;code_1742344398546&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;a href=&quot;/articles/{{article.id}}/edit&quot; class=&quot;btn btn-primary&quot;&amp;gt;Edit&amp;lt;/a&amp;gt;
&amp;lt;a href=&quot;/articles&quot;&amp;gt;Go to Article List&amp;lt;/a&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&amp;nbsp;href 속성 값의 URL을 보면 id가 article의 속성이므로 {{article.id}} 로 표시했다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;{{#article}, {{/article}} 형식으로 지정한 경우 -&amp;gt; {{id}} 만 써도 되지만 그게 아니므로 '.' (점)을 사용하여 표시한다.&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;이제 Edit 요청을 받을 컨트롤러를 연결한다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[controller/ArticleController]&lt;/p&gt;
&lt;pre id=&quot;code_1742344737658&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;    @GetMapping(&quot;/articles/{id}/edit&quot;)
    public String edit(@PathVariable Long id, Model model) {
        // 수정할 데이터 가져오기
        Article articleEntity = articleRepository.findById(id).orElse(null);
        // 모델에 데이터 등록하기
        model.addAttribute(&quot;article&quot;, articleEntity);
        // 뷰 페이지 생성하기
        return &quot;articles/edit&quot;;
    }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;@PathVariable : id 값을 변수로 사용하여 가져오기 위해 annotation 설정.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Model : 객체를 담을 모델을 사용하기 위해 메서드의 매개변수로 설정.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;수정할 데이터 가져오기 : articleRepository의 findById(id) 메서드로 데이터를 찾아 가져온다.&lt;br /&gt;- 만약 데이터를 찾지 못하면 null을 반환하고, 데이터를 찾았다면 Aticle 타입의 articleEntity 로 저장한다.&lt;/li&gt;
&lt;li&gt;모델에 데이터 등록하기 : articleEntity를 article로 등록.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;controller 를 생성했으니 이제 DB 에 저장된 데이터를 &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;수정페이지로 &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;&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;[articles/new.mustache]&lt;/p&gt;
&lt;pre id=&quot;code_1742345375442&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;{{#article}} &amp;lt;!--article 사용범위 지정 --&amp;gt;
&amp;lt;form class=&quot;container&quot; action=&quot;/articles/update&quot; method=&quot;post&quot;&amp;gt;
    &amp;lt;div class=&quot;mb-3&quot;&amp;gt;
        &amp;lt;label Class=&quot;form-label&quot;&amp;gt;제목&amp;lt;/label&amp;gt;
        &amp;lt;input type=&quot;text&quot; class=&quot;form-control&quot; name=&quot;title&quot; value=&quot;{{title}}&quot;&amp;gt;
    &amp;lt;/div&amp;gt;
    &amp;lt;div class=&quot;mb-3&quot;&amp;gt;
        &amp;lt;label Class=&quot;form-label&quot;&amp;gt;내용&amp;lt;/label&amp;gt;
        &amp;lt;textarea class=&quot;form-control&quot; rows=&quot;3&quot; name=&quot;content&quot;&amp;gt;{{content}}&amp;lt;/textarea&amp;gt;
    &amp;lt;/div&amp;gt;
    &amp;lt;a href=&quot;/articles/{{id}}&quot;&amp;gt;Back&amp;lt;/a&amp;gt;
&amp;lt;/form&amp;gt;
{{/article}}&lt;/code&gt;&lt;/pre&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;b&gt;&amp;lt;input&amp;gt; 태그로 생성한 입력 요소의 초기값은 value 속성&lt;/b&gt;으로 정의하지만, &lt;b&gt;&amp;lt;textarea&amp;gt; 태그&lt;/b&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;797&quot; data-origin-height=&quot;611&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eiI4EF/btsMPt1wwDS/gIwEKH6yZBslsp44DWbxGK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eiI4EF/btsMPt1wwDS/gIwEKH6yZBslsp44DWbxGK/img.png&quot; data-alt=&quot;화면 출력 모습 (title, content 가 정상 출력된다.)&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eiI4EF/btsMPt1wwDS/gIwEKH6yZBslsp44DWbxGK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FeiI4EF%2FbtsMPt1wwDS%2FgIwEKH6yZBslsp44DWbxGK%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;427&quot; height=&quot;327&quot; data-origin-width=&quot;797&quot; data-origin-height=&quot;611&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;화면 출력 모습 (title, content 가 정상 출력된다.)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클라이언트와 서버 간 처리 흐름을 4가지로 나누어 생각해보자.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;MVC(Model-View-Controller) :&lt;/b&gt; 서버 역할을 분담해 처리하는 기법&lt;/li&gt;
&lt;li&gt;&lt;b&gt;JPA(java Persistence API) :&lt;/b&gt; 서버와 DB 간 소통에 관여하는 기술&lt;/li&gt;
&lt;li&gt;&lt;b&gt;SQL(Structured Query Language) :&lt;/b&gt; DB 데이터를 관리하는 언어&lt;/li&gt;
&lt;li&gt;&lt;b&gt;HTTP(HyperText Transfer Protocol) :&lt;/b&gt; 데이터를 주고받기 위한 통신 규약&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1587&quot; data-origin-height=&quot;499&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/AOhAy/btsMPqqi4Xc/gsZ3ZQoqzTUEi7kKcy9C0k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/AOhAy/btsMPqqi4Xc/gsZ3ZQoqzTUEi7kKcy9C0k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/AOhAy/btsMPqqi4Xc/gsZ3ZQoqzTUEi7kKcy9C0k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FAOhAy%2FbtsMPqqi4Xc%2FgsZ3ZQoqzTUEi7kKcy9C0k%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;1587&quot; height=&quot;499&quot; data-origin-width=&quot;1587&quot; data-origin-height=&quot;499&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;HTTP 메서드&lt;/b&gt;&lt;b&gt;&lt;/b&gt;- 클라이언트와 서버 간에 데이터를 전송할 때는 통신 규약 즉, 프로토콜을 따른다.&lt;br /&gt;&lt;b&gt;-&lt;/b&gt; 프로토콜(protocol) 은 기기 간에 각종 신호 처리 방법, 오류 처리, 인증 방식 등을 규정하고 있다.&lt;br /&gt;- 그 중 HTTP는 웹 서비스에 사용하는 프로토콜로, 클라이언트의 다양한 요청을 메서드를 통해 서버로 보낸다.&lt;br /&gt;- 대표적인 메서드는 &lt;b&gt;POST(데이터 생성 요청), GET(조회), PATCH/PUT(수정), DELETE(삭제)&lt;/b&gt; 이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;데이터 관리&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;SQL&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;HTTP&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;데이터 생성(Create)&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;INSERT&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;POST&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;데이터 조회(Read)&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;SELECT&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;GET&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;데이터 수정(Update)&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;UPDATE&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;PATCH(PUT)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;데이터 삭제(Delete)&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;DELETE&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;DELETE&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&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;hr contenteditable=&quot;false&quot; data-ke-style=&quot;style3&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이제 2단계이다.&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;2단계는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;데이터를 수정해 DB 에 반영한 후 결과를 볼 수 있게 &amp;lt;상세 페이지&amp;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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[articles/edit.mustache]&lt;/p&gt;
&lt;pre id=&quot;code_1742347424774&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;{{#article}} &amp;lt;!--article 사용범위 지정 --&amp;gt;
&amp;lt;form class=&quot;container&quot; action=&quot;/articles/update&quot; method=&quot;post&quot;&amp;gt;
    &amp;lt;input name=&quot;id&quot; type=&quot;hidden&quot; value=&quot;{{id}}&quot;&amp;gt;
    &amp;lt;div class=&quot;mb-3&quot;&amp;gt;
        &amp;lt;label Class=&quot;form-label&quot;&amp;gt;제목&amp;lt;/label&amp;gt;
        &amp;lt;input type=&quot;text&quot; class=&quot;form-control&quot; name=&quot;title&quot; value=&quot;{{title}}&quot;&amp;gt;
    &amp;lt;/div&amp;gt;
    &amp;lt;div class=&quot;mb-3&quot;&amp;gt;
        &amp;lt;label Class=&quot;form-label&quot;&amp;gt;내용&amp;lt;/label&amp;gt;
        &amp;lt;textarea class=&quot;form-control&quot; rows=&quot;3&quot; name=&quot;content&quot;&amp;gt;{{content}}&amp;lt;/textarea&amp;gt;
    &amp;lt;/div&amp;gt;
    &amp;lt;button type=&quot;submit&quot; class=&quot;btn btn-primary&quot;&amp;gt;Submit&amp;lt;/button&amp;gt;
    &amp;lt;a href=&quot;/articles/{{id}}&quot;&amp;gt;Back&amp;lt;/a&amp;gt;
&amp;lt;/form&amp;gt;
{{/article}}&lt;/code&gt;&lt;/pre&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;lt;form&amp;gt; 태그는 옛날에 만들어진 규격이라 PATCH 메서드를 지원하지 않기 때문에 POST로 요청한다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;수정 폼에서 서버로 보낼 때는 id 값을 보내야 하므로 type=&quot;hidden&quot; 속성으로 숨겨서 전송한다.&lt;/b&gt;&lt;/li&gt;
&lt;/ul&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[dto/ArticleForm]&lt;/p&gt;
&lt;pre id=&quot;code_1742348460724&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@AllArgsConstructor
@ToString
public class ArticleForm {
    private Long id;
    private String title; // 제목을 받을 필드
    private String content; // 내용을 받을 필드

    public Article toEntity() {
        return new Article(id, title, content);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;수정 폼에서 id를 추가했으므로, DTO에도 id를 추가한다.&lt;/li&gt;
&lt;/ul&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[controller/Articlecontroller]&lt;/p&gt;
&lt;pre id=&quot;code_1742347666294&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@PostMapping(&quot;/articles/update&quot;)
    public String updateArticle(ArticleForm form) {
        log.info(form.toString());
        // 1. DTO를 엔터티로 변환하기
        Article articleEntity = form.toEntity();
        log.info(articleEntity.toString());
        // 2. 엔터티를 DB에 저장하기
        // 2.1 DB에서 기존 데이터 가져오기
        Article target = articleRepository.findById(articleEntity.getId()).orElse(null);
        // 2.2 기존 데이터값 갱신하기
        if (target != null) {
            articleRepository.save(articleEntity); // 엔터티를 DB에 저장(갱신)
        }
        // 3. 수정 결과 페이지로 리다이렉트하기
        return &quot;redirect:/articles/&quot; + articleEntity.getId();
    }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;수정 폼에서 전송한 데이터는 DTO로 받기 때문에&lt;/b&gt;, ArticleForm을 매개변수로 추가한다.&lt;/li&gt;
&lt;li&gt;DTO-&amp;gt; Entity로 변환하는 form.toEntity() 메서드를 호출해 반환값을 articleEntity 이름으로 받는다.&lt;/li&gt;
&lt;li&gt;데이터 생성이 아닌, &lt;b&gt;수정하기 위해 기존 데이터를 가져온다.&lt;/b&gt;&lt;br /&gt;- 이때는 리파지토리를 이용하여 articleRepository.findById() 메서드를 호출한다.&lt;br /&gt;- findById() 메서드는 repository에서 자동 제공하는 메서드로, 괄호 안에는 찾는 id값을 작성한다.&lt;br /&gt;- findById(articleEntity.getId()) 메서드를 호출해 반환받은 데이터를 Article 타입의 target 변수에 저장한다.&lt;br /&gt;- 데이터가 없다면 null 을 반환한다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;기존 데이터를 가져오고 나면 articleRepository.save() 메서드로 기존 데이터를 갱신한다.&lt;br /&gt;&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;데이터를 수정하면 수정된 내용이 반영된 상세 페이지로 이동하도록 redirect 시켜준다.&lt;br /&gt;&lt;/b&gt;-URL의 id 부분은 Entity에 따라 매번 바뀌어야 하므로, articleEntity의 getId() 메서드를 호출한다.&lt;/li&gt;
&lt;/ul&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1040&quot; data-origin-height=&quot;437&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bg1zof/btsMNs4jsE6/mIjXtV51KWYSLkumtVYUJK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bg1zof/btsMNs4jsE6/mIjXtV51KWYSLkumtVYUJK/img.png&quot; data-alt=&quot;디버깅 로그&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bg1zof/btsMNs4jsE6/mIjXtV51KWYSLkumtVYUJK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbg1zof%2FbtsMNs4jsE6%2FmIjXtV51KWYSLkumtVYUJK%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;1040&quot; height=&quot;437&quot; data-origin-width=&quot;1040&quot; data-origin-height=&quot;437&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;디버깅 로그&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignRight&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1730&quot; data-origin-height=&quot;303&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/daWxO1/btsMPvLMPVd/iAKnzh8U8I50kpk02e19i0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/daWxO1/btsMPvLMPVd/iAKnzh8U8I50kpk02e19i0/img.png&quot; data-alt=&quot;'가가가가' -&amp;amp;gt; '가나다라' 수정.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/daWxO1/btsMPvLMPVd/iAKnzh8U8I50kpk02e19i0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdaWxO1%2FbtsMPvLMPVd%2FiAKnzh8U8I50kpk02e19i0%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;1730&quot; height=&quot;303&quot; data-origin-width=&quot;1730&quot; data-origin-height=&quot;303&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;'가가가가' -&amp;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;redirect 페이지인 /articles/1 로 이동하고, 제목과 내용도 수정한 대로 잘 바뀌었다. 성공!&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;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p style=&quot;text-align: right;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: right;&quot; data-ke-size=&quot;size16&quot;&gt;**출처 : 스프링부트3 자바 백엔드 개발 입문 (홍팍 지음)&amp;nbsp;&lt;/p&gt;</description>
      <category>개발/Spring boot</category>
      <author>J_yoonS</author>
      <guid isPermaLink="true">https://this-is-another-one.tistory.com/11</guid>
      <comments>https://this-is-another-one.tistory.com/entry/%EA%B2%8C%EC%8B%9C%ED%8C%90%EC%88%98%EC%A0%95-%EA%B2%8C%EC%8B%9C%EA%B8%80-%EC%88%98%EC%A0%95%ED%95%98%EA%B8%B0#entry11comment</comments>
      <pubDate>Wed, 19 Mar 2025 10:47:27 +0900</pubDate>
    </item>
    <item>
      <title>[게시판/조회] 게시글 읽기 (단건, 목록)</title>
      <link>https://this-is-another-one.tistory.com/entry/%EA%B2%8C%EC%8B%9C%EA%B8%80-%EC%9D%BD%EA%B8%B0-%EB%8B%A8%EA%B1%B4-%EB%AA%A9%EB%A1%9D-%EC%A1%B0%ED%9A%8C-CRUD-R</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;웹 페이지에서 게시글을 등록하면 서버를 통해 DB 에 저장된다.&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;1592&quot; data-origin-height=&quot;388&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/d7jsSr/btsMNNe0MXu/Js6De47lduf0BVGHSmWLG0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/d7jsSr/btsMNNe0MXu/Js6De47lduf0BVGHSmWLG0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/d7jsSr/btsMNNe0MXu/Js6De47lduf0BVGHSmWLG0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fd7jsSr%2FbtsMNNe0MXu%2FJs6De47lduf0BVGHSmWLG0%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;1592&quot; height=&quot;388&quot; data-origin-width=&quot;1592&quot; data-origin-height=&quot;388&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;
&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[cotroller/ArticleController]&lt;/p&gt;
&lt;pre id=&quot;code_1742260136997&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;    @GetMapping(&quot;/articles/{id}&quot;)
    public String show(@PathVariable Long id, Model model) { // 매개변수로 id 받아오기
        log.info(&quot;id = &quot; + id); // id 잘 받아오는지 확인&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;@PathVariable :&amp;nbsp;&lt;/b&gt;URL 요청으로 들어온 전달값을 컨트롤러의 매개변수로 가져온다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1575&quot; data-origin-height=&quot;384&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/oJs1H/btsMOdkkmdh/S2S07CykUQ7oIST4aiA3ok/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/oJs1H/btsMOdkkmdh/S2S07CykUQ7oIST4aiA3ok/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/oJs1H/btsMOdkkmdh/S2S07CykUQ7oIST4aiA3ok/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FoJs1H%2FbtsMOdkkmdh%2FS2S07CykUQ7oIST4aiA3ok%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;1575&quot; height=&quot;384&quot; data-origin-width=&quot;1575&quot; data-origin-height=&quot;384&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1742260515848&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	// 1. id를 조회해 데이터 가져오기
       Article articleEntity = articleRepository.findById(id).orElse(null);&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;findById(id).orElse(null) :&lt;/b&gt; id 값으로 데이터를 찾을때 id값이 없으면 null을 반환.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1547&quot; data-origin-height=&quot;373&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/1ovKD/btsMMJLgVZl/RWqa1MBkj60OTUWxncLJD0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/1ovKD/btsMMJLgVZl/RWqa1MBkj60OTUWxncLJD0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/1ovKD/btsMMJLgVZl/RWqa1MBkj60OTUWxncLJD0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F1ovKD%2FbtsMMJLgVZl%2FRWqa1MBkj60OTUWxncLJD0%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;1547&quot; height=&quot;373&quot; data-origin-width=&quot;1547&quot; data-origin-height=&quot;373&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1742260835727&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@GetMapping(&quot;/articles/{id}&quot;)
    public String show(@PathVariable Long id, Model model) { // 매개변수로 id 받아오기
        log.info(&quot;id = &quot; + id); // id 잘 받아오는지 확인

        // 1. id를 조회해 데이터 가져오기
        Article articleEntity = articleRepository.findById(id).orElse(null); 
        // 2. 모델에 데이터 등록하기
        model.addAttribute(&quot;article&quot;, articleEntity);&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Model :&lt;/b&gt; MVC 패턴에 따라 조회한 데이터를 뷰 페이지에서 사용하기 위해 객체로 받는다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;model.addAttribute :&lt;/b&gt; 모델에 데이터를 등록한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1580&quot; data-origin-height=&quot;373&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/EkWQG/btsMNK3FrGg/0b91O5loIgVBOWK4M5agck/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/EkWQG/btsMNK3FrGg/0b91O5loIgVBOWK4M5agck/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/EkWQG/btsMNK3FrGg/0b91O5loIgVBOWK4M5agck/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FEkWQG%2FbtsMNK3FrGg%2F0b91O5loIgVBOWK4M5agck%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;1580&quot; height=&quot;373&quot; data-origin-width=&quot;1580&quot; data-origin-height=&quot;373&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;
&lt;pre id=&quot;code_1742261108387&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@GetMapping(&quot;/articles/{id}&quot;)
    public String show(@PathVariable Long id, Model model) { // 매개변수로 id 받아오기
        log.info(&quot;id = &quot; + id); // id 잘 받아오는지 확인

        // 1. id를 조회해 데이터 가져오기
        Article articleEntity = articleRepository.findById(id).orElse(null); 
        // 2. 모델에 데이터 등록하기
        model.addAttribute(&quot;article&quot;, articleEntity);
        // 3. 뷰 페이지 반환하기
        return &quot;articles/show&quot;;
    }&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;return &quot;articles/show&quot;;&lt;/b&gt;&lt;/li&gt;
&lt;/ul&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;1538&quot; data-origin-height=&quot;353&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/B1DLy/btsMMKi7SJA/hmnS3GOkIkHaY7hKeb99k1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/B1DLy/btsMMKi7SJA/hmnS3GOkIkHaY7hKeb99k1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/B1DLy/btsMMKi7SJA/hmnS3GOkIkHaY7hKeb99k1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FB1DLy%2FbtsMMKi7SJA%2FhmnS3GOkIkHaY7hKeb99k1%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;1538&quot; height=&quot;353&quot; data-origin-width=&quot;1538&quot; data-origin-height=&quot;353&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[articles/show.mustache]&lt;/p&gt;
&lt;div style=&quot;background-color: #1e1f22; color: #bcbec4;&quot;&gt;
&lt;pre class=&quot;handlebars&quot;&gt;&lt;code&gt;{{#article}}
&amp;lt;tr&amp;gt;
    &amp;lt;th&amp;gt;{{id}}&amp;lt;/th&amp;gt;
    &amp;lt;td&amp;gt;{{title}}&amp;lt;/td&amp;gt;
    &amp;lt;td&amp;gt;{{content}}&amp;lt;/td&amp;gt;
&amp;lt;/tr&amp;gt;
{{/article}}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;'#' 과 '/' 로 범위를 정하고, 모델 article에 담긴 객체를 클라이언트에서 출력하기 위해 '{{}}' 를 사용한다.&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;model 에 데이터가 담겨있다는 가정하에 해당 controller URL 로 조회하면&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1667&quot; data-origin-height=&quot;321&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bFXxKE/btsMN7dmjtS/MwbV0QXHPyb7y8bK3dsOWK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bFXxKE/btsMN7dmjtS/MwbV0QXHPyb7y8bK3dsOWK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bFXxKE/btsMN7dmjtS/MwbV0QXHPyb7y8bK3dsOWK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbFXxKE%2FbtsMN7dmjtS%2FMwbV0QXHPyb7y8bK3dsOWK%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;1667&quot; height=&quot;321&quot; data-origin-width=&quot;1667&quot; data-origin-height=&quot;321&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;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 단일값이 아닌 list를 조회해보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위에서는 Entity를 반환했다면, 목록을 조회할 때는 엔티티의 묶음인 list를 반환한다.&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;[controller/ArticleController]&lt;/p&gt;
&lt;pre id=&quot;code_1742262017371&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;    @GetMapping(&quot;/articles&quot;) // 다중데이터 목록 조회
    public String index(Model model) {

        // 1. 모든 데이터 가져오기
        ArrayList&amp;lt;Article&amp;gt; articleEntityList = articleRepository.findAll();
        // 2. 모델에 데이터 등록하기
        model.addAttribute(&quot;articleList&quot;, articleEntityList);
        return &quot;articles/index&quot;;
    }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;※ List 를 사용할 경우, findAll() 메서드가 반환하는 데이터 타입은 Iterable 이기 때문에 오류 메시지가 발생한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;351&quot; data-origin-height=&quot;445&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/oqybX/btsMOuF3Gp9/Xp1R7ncnA6HeqgrpBbdcr0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/oqybX/btsMOuF3Gp9/Xp1R7ncnA6HeqgrpBbdcr0/img.png&quot; data-alt=&quot;Iterable, Collection, List 인터페이스의 관계.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/oqybX/btsMOuF3Gp9/Xp1R7ncnA6HeqgrpBbdcr0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FoqybX%2FbtsMOuF3Gp9%2FXp1R7ncnA6HeqgrpBbdcr0%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;249&quot; height=&quot;316&quot; data-origin-width=&quot;351&quot; data-origin-height=&quot;445&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Iterable, Collection, List 인터페이스의 관계.&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;따라서 익숙치 않은 Iterable 대신, ArrayList를 사용하기 위해 &lt;b&gt;articleRepository 의 부모인 &lt;/b&gt;&lt;br /&gt;&lt;b&gt;CurdRepository의 메서드를 오버라이딩 해준다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[repository/ArticleRepository]&lt;/p&gt;
&lt;pre id=&quot;code_1742262656705&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public interface ArticleRepository extends CrudRepository&amp;lt;Article, Long&amp;gt; {

    @Override
    ArrayList&amp;lt;Article&amp;gt; findAll();
}&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[articles/index/mustache]&lt;/p&gt;
&lt;pre id=&quot;code_1742262826984&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;    {{#articleList}}
        &amp;lt;tr&amp;gt;
            &amp;lt;th&amp;gt;{{id}}&amp;lt;/th&amp;gt;
            &amp;lt;td&amp;gt;&amp;lt;a href=&quot;/articles/{{id}}&quot;&amp;gt;{{title}}&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;
            &amp;lt;td&amp;gt;{{content}}&amp;lt;/td&amp;gt;
        &amp;lt;/tr&amp;gt;
    {{/articleList}}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단일 조회와 마찬가지로 model 에 담긴 객체를 클라이언트에서 출력한다.&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1148&quot; data-origin-height=&quot;259&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cAaoyL/btsMMKpRKof/CeHz70QC7mchDxXMYnB4hk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cAaoyL/btsMMKpRKof/CeHz70QC7mchDxXMYnB4hk/img.png&quot; data-alt=&quot;임시로 data.sql 에 담긴 객체들&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cAaoyL/btsMMKpRKof/CeHz70QC7mchDxXMYnB4hk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcAaoyL%2FbtsMMKpRKof%2FCeHz70QC7mchDxXMYnB4hk%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;1148&quot; height=&quot;259&quot; data-origin-width=&quot;1148&quot; data-origin-height=&quot;259&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;임시로 data.sql 에 담긴 객체들&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1982&quot; data-origin-height=&quot;643&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bVygWN/btsMMyDePt1/aqP1CHKzbP8WdqpvLtagm0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bVygWN/btsMMyDePt1/aqP1CHKzbP8WdqpvLtagm0/img.png&quot; data-alt=&quot;목록 조회 성공!&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bVygWN/btsMMyDePt1/aqP1CHKzbP8WdqpvLtagm0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbVygWN%2FbtsMMyDePt1%2FaqP1CHKzbP8WdqpvLtagm0%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;1982&quot; height=&quot;643&quot; data-origin-width=&quot;1982&quot; data-origin-height=&quot;643&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;목록 조회 성공!&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p style=&quot;text-align: right;&quot; data-ke-size=&quot;size16&quot;&gt;**출처 : 스프링부트3 자바 백엔드 개발 입문 (홍팍 지음)&amp;nbsp;&lt;/p&gt;</description>
      <category>개발/Spring boot</category>
      <author>J_yoonS</author>
      <guid isPermaLink="true">https://this-is-another-one.tistory.com/10</guid>
      <comments>https://this-is-another-one.tistory.com/entry/%EA%B2%8C%EC%8B%9C%EA%B8%80-%EC%9D%BD%EA%B8%B0-%EB%8B%A8%EA%B1%B4-%EB%AA%A9%EB%A1%9D-%EC%A1%B0%ED%9A%8C-CRUD-R#entry10comment</comments>
      <pubDate>Tue, 18 Mar 2025 11:02:38 +0900</pubDate>
    </item>
    <item>
      <title>롬복(lombok)을 이용한 리팩터링(refactoring)</title>
      <link>https://this-is-another-one.tistory.com/entry/%EB%A1%AC%EB%B3%B5lombok%EC%9D%84-%EC%9D%B4%EC%9A%A9%ED%95%9C-%EB%A6%AC%ED%8C%A9%ED%84%B0%EB%A7%81refactoring</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;Lombok을 추가함으로써 getter(), setter(), construction(), toString() 과 같은 메서드를 간소화할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한 로깅 기능을 통해 println() 을 log()로 대체하여 수행 과정을 기록으로 남길 수 있다.&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;Lombok을 사용하기 위해 하기 사진과 같이 lombok을 gradle에 추가한다.&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;[build.gradle]&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;921&quot; data-origin-height=&quot;363&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/utGWD/btsMMmXdOWr/JEWxSqnI3nK2Sd5ud4UZnk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/utGWD/btsMMmXdOWr/JEWxSqnI3nK2Sd5ud4UZnk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/utGWD/btsMMmXdOWr/JEWxSqnI3nK2Sd5ud4UZnk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FutGWD%2FbtsMMmXdOWr%2FJEWxSqnI3nK2Sd5ud4UZnk%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;921&quot; height=&quot;363&quot; data-origin-width=&quot;921&quot; data-origin-height=&quot;363&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;룸북으로 코드를 &lt;b&gt;리팩터링&lt;/b&gt; 하여 코드의 구조와 성능을 개선해보자.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;리팩터링(refactoring) : 코드의 기능에는 변함이 없이 코드의 구조 또는 성능을 개선하는 작업.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 구조를 개선할 대상은 DTO 이다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[dto/ArticleForm]&lt;/p&gt;
&lt;pre id=&quot;code_1742257818338&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@AllArgsConstructor
@ToString
public class ArticleForm {
    private Long id;
    private String title; // 제목을 받을 필드
    private String content; // 내용을 받을 필드

    public Article toEntity() {
        return new Article(id, title, content);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;@AllArgsConstructor&lt;/b&gt; &lt;b&gt;: &lt;/b&gt;title, content 를 매개변수로 하는 생성자가 자동으로 만들어진다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;@Tostring :&lt;/b&gt; toString() 메서드를 사용하는 것과 같은 효과가 나타난다.&lt;/li&gt;
&lt;/ul&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[entity/Article]&lt;/p&gt;
&lt;pre id=&quot;code_1742258482640&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@AllArgsConstructor
@ToString
@Entity // DB테이블 생성.
public class Article {
    @Id // 대표값 선언
    @GeneratedValue(strategy = GenerationType.IDENTITY) // DB가 id 자동 생성
    private Long id;

    @Column
    private String title;

    @Column
    private String content;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Entity 또한 DTO와 같이 @AllArgsConstructor &amp;amp; @Tostring을 추가하여 코드구조를 개선한다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[controller/ArticleController]&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;732&quot; data-origin-height=&quot;957&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/quJh3/btsMN75tHif/Qt72DRC7sbo8Crk7GZvm30/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/quJh3/btsMN75tHif/Qt72DRC7sbo8Crk7GZvm30/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/quJh3/btsMN75tHif/Qt72DRC7sbo8Crk7GZvm30/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FquJh3%2FbtsMN75tHif%2FQt72DRC7sbo8Crk7GZvm30%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;361&quot; height=&quot;472&quot; data-origin-width=&quot;732&quot; data-origin-height=&quot;957&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;println() 문으로 데이터를 검증하면 기록에 남지 않을뿐더러 서버 성능에도 악영향을 끼친다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;@S1f4j :&lt;/b&gt; 로깅 기능을 위한 어노테이션. 디버깅 기록을 남길 수 있다.&lt;/li&gt;
&lt;li&gt;println() 대신 -&amp;gt; &lt;b&gt;log.info()&lt;/b&gt; 형태로 디버깅한다.&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>개발/Spring boot</category>
      <author>J_yoonS</author>
      <guid isPermaLink="true">https://this-is-another-one.tistory.com/9</guid>
      <comments>https://this-is-another-one.tistory.com/entry/%EB%A1%AC%EB%B3%B5lombok%EC%9D%84-%EC%9D%B4%EC%9A%A9%ED%95%9C-%EB%A6%AC%ED%8C%A9%ED%84%B0%EB%A7%81refactoring#entry9comment</comments>
      <pubDate>Tue, 18 Mar 2025 09:49:46 +0900</pubDate>
    </item>
    <item>
      <title>[게시판/생성] 새 글 작성하기</title>
      <link>https://this-is-another-one.tistory.com/entry/%EA%B2%8C%EC%8B%9C%ED%8C%90-%EC%83%88-%EA%B8%80-%EC%9E%91%EC%84%B1%ED%95%98%EA%B8%B0-%ED%8F%BC-%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%A5%BC-DTO%EB%A1%9C-%EB%B0%9B%EC%95%84-DB%EC%97%90-%EC%A0%80%EC%9E%A5%ED%95%98%EA%B8%B0</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;815&quot; data-origin-height=&quot;345&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b0ktY6/btsMLYVVojG/lF4MKCgHbdO97tDKgyJJPK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b0ktY6/btsMLYVVojG/lF4MKCgHbdO97tDKgyJJPK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b0ktY6/btsMLYVVojG/lF4MKCgHbdO97tDKgyJJPK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb0ktY6%2FbtsMLYVVojG%2FlF4MKCgHbdO97tDKgyJJPK%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;591&quot; height=&quot;250&quot; data-origin-width=&quot;815&quot; data-origin-height=&quot;345&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;form&gt;&lt;/form&gt;&lt;form&gt;&lt;/form&gt;&lt;form&gt;&lt;/form&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;lt;form&amp;gt; 태그를 택배와 비유하여 송장에 &lt;b&gt;수령자&lt;/b&gt;와 &lt;b&gt;배송형태&lt;/b&gt;(Get, Post) 를&amp;nbsp; 적어 서버에 전송한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1388&quot; data-origin-height=&quot;462&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b5HPgg/btsMMd6b7d8/ikMZ810LZkUknI4UpKY7P1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b5HPgg/btsMMd6b7d8/ikMZ810LZkUknI4UpKY7P1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b5HPgg/btsMMd6b7d8/ikMZ810LZkUknI4UpKY7P1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb5HPgg%2FbtsMMd6b7d8%2FikMZ810LZkUknI4UpKY7P1%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;1388&quot; height=&quot;462&quot; data-origin-width=&quot;1388&quot; data-origin-height=&quot;462&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&amp;lt;form&amp;gt; 태그에 실어 보낸 데이터는 서버의 컨트롤러가 객체에 담아 받는다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이 객체를 DTO(Data Transfer Object) 로 받은 데이터는 최종적으로 DB(Database) 에 저장된다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;[ArticleController]&lt;/p&gt;
&lt;pre id=&quot;code_1742173667358&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Controller
 public class ArticleController {
     @Autowired
     private ArticleRepository articleRepository;

     @GetMapping(&quot;/articles/new&quot;)
     public String newArticleForm() {
         return &quot;articles/new&quot;;
     }
     
@PostMapping(&quot;/articles/create&quot;)
     public String createArticle() {
         return &quot;&quot;;
     }
 }&lt;/code&gt;&lt;/pre&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[articles/new.mustache]&lt;/p&gt;
&lt;pre id=&quot;code_1742173847681&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;form class=&quot;container&quot; action=&quot;/articles/create&quot; method=&quot;post&quot;&amp;gt;
     &amp;lt;div class=&quot;mb-3&quot;&amp;gt;
         &amp;lt;label Class=&quot;form-label&quot;&amp;gt;제목&amp;lt;/label&amp;gt;
         &amp;lt;input type=&quot;text&quot; class=&quot;form-control&quot; name=&quot;title&quot;&amp;gt;
     &amp;lt;/div&amp;gt;
     &amp;lt;div class=&quot;mb-3&quot;&amp;gt;
         &amp;lt;label Class=&quot;form-label&quot;&amp;gt;내용&amp;lt;/label&amp;gt;
         &amp;lt;textarea class=&quot;form-control&quot; rows=&quot;3&quot; name=&quot;content&quot;&amp;gt;&amp;lt;/textarea&amp;gt;
     &amp;lt;/div&amp;gt;
     &amp;lt;button type=&quot;submit&quot; class=&quot;btn btn-primary&quot;&amp;gt;Submit&amp;lt;/button&amp;gt;
 &amp;lt;/form&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;● action: URL 연결 주소를 적는다. action=&quot;/articles/create&quot; : 페이지로 폼 데이터를 전송한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;● method: 속상 값으로 get, post 2가지로 설정할 수 있다.&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;폼 데이터를 받을때 DTO 에 담아 받으니 이제 DTO를 만든다. (그릇 역할)&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[dto/ArticleForm]&lt;/p&gt;
&lt;pre id=&quot;code_1742174104658&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class ArticleForm {
     private String title; // 제목을 받을 필드
     private String content; // 내용을 받을 필드
 
     // 전송받은 제목과 내용을 필드에 저장하는 생성자 추가
     public ArticleForm(String title, String content) {
         this.title = title;
         this.content = content;
     }
 
     // 데이터를 잘 받았는지 확인할 toString() 메서드 추가
     @Override
     public String toString() {
         return &quot;ArticleForm{&quot; +
                 &quot;title='&quot; + title + '\'' +
                 &quot;, content='&quot; + content + '\'' +
                 '}';
     }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. &lt;b&gt;제목과 내용을 전송할 필드&lt;/b&gt; 2개(title, content) 를 선언한 후&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 전송받은 &lt;b&gt;제목과 내용을 필드에 저장&lt;/b&gt;하는 &lt;b&gt;생성자를 추가&lt;/b&gt;한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. &lt;b&gt;폼 데이터를 잘 받았는지 확인&lt;/b&gt;하기 위해 &lt;b&gt;toString() 메서드를 추가&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[ArticleController]&lt;/p&gt;
&lt;pre id=&quot;code_1742174379769&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt; @Controller
 public class ArticleController {
     @Autowired
     private ArticleRepository articleRepository;
 
     @GetMapping(&quot;/articles/new&quot;)
     public String newArticleForm() {
         return &quot;articles/new&quot;;
     }
 
     @PostMapping(&quot;/articles/create&quot;)
     public String createArticle(ArticleForm form) {
         System.out.println(form.toString());
         // 1, DTO를 엔터티로 변환
         Article article = form.toEntity();
         System.out.println(article.toString());
         // 2. 리파지터리로 엔터티를 DB에 저장
         Article saved = articleRepository.save(article);
         return &quot;&quot;;
     }
 }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;폼에서 전송한 데이터를 createArticle() 메서드의 매개변수로 받아온다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DTO로 만든 클래스 ArticleForm 타입의 form 객체를 매개변수로 선언한다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;[articles/new.mustache]&lt;/p&gt;
&lt;pre id=&quot;code_1742174615864&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;         &amp;lt;label Class=&quot;form-label&quot;&amp;gt;제목&amp;lt;/label&amp;gt;
         &amp;lt;input type=&quot;text&quot; class=&quot;form-control&quot; name=&quot;title&quot;&amp;gt;
     &amp;lt;/div&amp;gt;
     &amp;lt;div class=&quot;mb-3&quot;&amp;gt;
         &amp;lt;label Class=&quot;form-label&quot;&amp;gt;내용&amp;lt;/label&amp;gt;
         &amp;lt;textarea class=&quot;form-control&quot; rows=&quot;3&quot; name=&quot;content&quot;&amp;gt;&amp;lt;/textarea&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위에서 적었던 HTML을 다시 살펴보면 name 를 DTO 필드와 일치 시킴으로써 해당 필드와 연결된다.&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;단! DB는 SQL언어를 사용하기 때문에 자바 언어를 이해하지 못하기에 &lt;b&gt;&lt;u&gt;JPA를 사용하여 명령을 내린다&lt;/u&gt;.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;● JPA: (Java Persistence API) 자바 언어로 DB에 명령을 내리는 도구이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1339&quot; data-origin-height=&quot;334&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/biXwr9/btsMNbT762S/9yry3CxxhkRuFNKxefJU2k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/biXwr9/btsMNbT762S/9yry3CxxhkRuFNKxefJU2k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/biXwr9/btsMNbT762S/9yry3CxxhkRuFNKxefJU2k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbiXwr9%2FbtsMNbT762S%2F9yry3CxxhkRuFNKxefJU2k%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;1339&quot; height=&quot;334&quot; data-origin-width=&quot;1339&quot; data-origin-height=&quot;334&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;JPA의 핵심 도구로는 엔티티(entity)와 리파지토리(repository) 가 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;● 엔티티(entity) : 자바 객체를 DB가 이해할 수 있게 만든 것으로, 이를 기반으로 테이블이 만들어진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;● 리파지토리(repository) : 엔티티가 DB 속 테이블에 저장 및 관리될 수 있게 하는 인터페이스.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1029&quot; data-origin-height=&quot;366&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eIjYAR/btsMNdYHE3U/5Pnotiy9SSVbT8083k8pAK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eIjYAR/btsMNdYHE3U/5Pnotiy9SSVbT8083k8pAK/img.png&quot; data-alt=&quot;DTO 가 Entity 로 변환후 DB에 저장된다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eIjYAR/btsMNdYHE3U/5Pnotiy9SSVbT8083k8pAK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FeIjYAR%2FbtsMNdYHE3U%2F5Pnotiy9SSVbT8083k8pAK%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;644&quot; height=&quot;229&quot; data-origin-width=&quot;1029&quot; data-origin-height=&quot;366&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;DTO 가 Entity 로 변환후 DB에 저장된다.&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;&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;[ArticleController]&lt;/p&gt;
&lt;pre id=&quot;code_1742175524900&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;     @PostMapping(&quot;/articles/create&quot;)
     public String createArticle(ArticleForm form) {
         System.out.println(form.toString());
         // 1, DTO를 엔터티로 변환
         Article article = form.toEntity();
         System.out.println(article.toString());
         // 2. 리파지터리로 엔터티를 DB에 저장
         Article saved = articleRepository.save(article);
         return &quot;&quot;;
     }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와 같이 DTO를 엔터티로 변환후 Reposiory로 Entity를 DB에 저장하게 된다.&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;b&gt; form.toEntity(), articleRepository.save()&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;[entity/Article]&lt;/p&gt;
&lt;pre id=&quot;code_1742175651088&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Entity
public class Article {
    @Id // 대표값 선언
    @GeneratedValue(strategy = GenerationType.IDENTITY) // DB가 id 자동 생성
    private Long id;

    @Column
    private String title;

    @Column
    private String content;&lt;/code&gt;&lt;/pre&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;span style=&quot;color: #333333; text-align: start;&quot;&gt;●&lt;span&gt; @Entity : Entity 선언&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;●&lt;span&gt; @Id : Entity 의 대표값 지정&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;●&lt;span&gt; @GeneratedValue : 자동 생성 기능 추가(숫자가 자동으로 매겨짐)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;●&lt;span&gt; @Column : 필드 선언, DB 테이블의 해당열(title, content) 과 연결됨.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1091&quot; data-origin-height=&quot;338&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/S0exE/btsMMcsPQtq/AzbKwwXT3O3O9zTBWntyi1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/S0exE/btsMMcsPQtq/AzbKwwXT3O3O9zTBWntyi1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/S0exE/btsMMcsPQtq/AzbKwwXT3O3O9zTBWntyi1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FS0exE%2FbtsMMcsPQtq%2FAzbKwwXT3O3O9zTBWntyi1%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;670&quot; height=&quot;208&quot; data-origin-width=&quot;1091&quot; data-origin-height=&quot;338&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[entity/Article]&lt;/p&gt;
&lt;pre id=&quot;code_1742176103748&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Entity
public class Article {
    @Id // 대표값 선언
    @GeneratedValue(strategy = GenerationType.IDENTITY) // DB가 id 자동 생성
    private Long id;

    @Column
    private String title;
    @Column
    private String content;
    
    // Article 생성자 추가
     public Article(Long id, String title, String content) {
         this.id = id;
         this.title = title;
         this.content = content;
     }
     
    // toString() 메서드 추가
     @Override
     public String toString() {
         return &quot;Article{&quot; +
                 &quot;id=&quot; + id +
                 &quot;, title='&quot; + title + '\'' +
                 &quot;, content='&quot; + content + '\'' +
                 '}';
     }
 }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DTO와 마찬가지로 Entity 또한 생성자와 toString() 메서드를 추가한다.&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;또한, DTO를 Entity로 변환시키는 &lt;b&gt;toEntity() 메서드&lt;/b&gt;를 위해 ArticleForm(DTO)에 해당 메서드를 추가한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다시 ArticleForm 으로 돌아간다.&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;[dto/ArticleForm]&lt;/p&gt;
&lt;pre id=&quot;code_1742176480335&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class ArticleForm {
     private String title; // 제목을 받을 필드
     private String content; // 내용을 받을 필드
 
     // 전송받은 제목과 내용을 필드에 저장하는 생성자 추가
     public ArticleForm(String title, String content) {
         this.title = title;
         this.content = content;
     }
 
     // 데이터를 잘 받았는지 확인할 toString() 메서드 추가
     @Override
     public String toString() {
         return &quot;ArticleForm{&quot; +
                 &quot;title='&quot; + title + '\'' +
                 &quot;, content='&quot; + content + '\'' +
                 '}';
     }
 
     public Article toEntity() {
         return new Article(null, title, content);
     }
 }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 DTO는 id가 없지만, Entity로 변환하기 위해 리턴값은 null, title, content 로 채워준다.&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;이제 최종적으로 Respository에 저장하기 위해 ArticleRepository 인터페이스를 생성한다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[repository/ArticleRepository]&lt;/p&gt;
&lt;pre id=&quot;code_1742176814383&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public interface ArticleRepository extends CrudRepository&amp;lt;Article, Long&amp;gt; {
 }&lt;/code&gt;&lt;/pre&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;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;CrudRepository : JPA에서 제공하는 인터페이스로 이를 상속해 Entity를 관리(생성, 조회, 수정, 삭제) 할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;● Article : 관리 대상 &lt;b&gt;Entity의 클래스 타입&lt;/b&gt;. (여기서는 Article)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;● Long : 관리 대상 &lt;b&gt;Entity의 대표값 타입&lt;/b&gt;. Article.java 파일에 가면 id를 대표값으로 지정했는데, id의 타입은 Long이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;603&quot; data-origin-height=&quot;336&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b2Ciwx/btsMMDXO565/ZX6aNXPauCIThSEcWtIO7K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b2Ciwx/btsMMDXO565/ZX6aNXPauCIThSEcWtIO7K/img.png&quot; data-alt=&quot;*참고로 id는 1로 출력되는 것이 정상. (글쓴이는 다른 아이디 생성 후 출력하여 id=7로 출력됨)&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b2Ciwx/btsMMDXO565/ZX6aNXPauCIThSEcWtIO7K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb2Ciwx%2FbtsMMDXO565%2FZX6aNXPauCIThSEcWtIO7K%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;603&quot; height=&quot;336&quot; data-origin-width=&quot;603&quot; data-origin-height=&quot;336&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;*참고로 id는 1로 출력되는 것이 정상. (글쓴이는 다른 아이디 생성 후 출력하여 id=7로 출력됨)&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;최종적으로.&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;1. Form에서 제출한 title, content -&amp;gt; DTO(ArticleForm) 로 객체에 담겨 서버로 전송되어&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. Controller에 의해 DTO -&amp;gt; Entity(Article) 로 변경되고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. @GeneratedValue 로 자동생성된 id와 함께 Entity객체가 ArticleRepository로 저장됨을 확인 할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;727&quot; data-origin-height=&quot;669&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bOLNH0/btsMLKKs6kH/nIOFAPwUK6ovSYMTCqkfk0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bOLNH0/btsMLKKs6kH/nIOFAPwUK6ovSYMTCqkfk0/img.png&quot; data-alt=&quot;DB에도 성공적으로 저장됨을 확인할 수 있음.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bOLNH0/btsMLKKs6kH/nIOFAPwUK6ovSYMTCqkfk0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbOLNH0%2FbtsMLKKs6kH%2FnIOFAPwUK6ovSYMTCqkfk0%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;431&quot; height=&quot;397&quot; data-origin-width=&quot;727&quot; data-origin-height=&quot;669&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;DB에도 성공적으로 저장됨을 확인할 수 있음.&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;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt; &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;●&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt; 레코드(record) : 행 단위인 테이블의 '한 행' 을 일컫는다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p style=&quot;text-align: right;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;**출처 : 스프링부트3 자바 백엔드 개발 입문 (홍팍 지음)&amp;nbsp;&lt;/span&gt;&lt;/p&gt;</description>
      <category>개발/Spring boot</category>
      <category>게시판</category>
      <category>새 글 작성하기</category>
      <category>스프링부트3</category>
      <author>J_yoonS</author>
      <guid isPermaLink="true">https://this-is-another-one.tistory.com/8</guid>
      <comments>https://this-is-another-one.tistory.com/entry/%EA%B2%8C%EC%8B%9C%ED%8C%90-%EC%83%88-%EA%B8%80-%EC%9E%91%EC%84%B1%ED%95%98%EA%B8%B0-%ED%8F%BC-%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%A5%BC-DTO%EB%A1%9C-%EB%B0%9B%EC%95%84-DB%EC%97%90-%EC%A0%80%EC%9E%A5%ED%95%98%EA%B8%B0#entry8comment</comments>
      <pubDate>Mon, 17 Mar 2025 11:22:16 +0900</pubDate>
    </item>
    <item>
      <title>스프링 부트 (Spring boot) 의 특징</title>
      <link>https://this-is-another-one.tistory.com/entry/%EC%8A%A4%ED%94%84%EB%A7%81-%EB%B6%80%ED%8A%B8-Spring-boot-%EC%9D%98-%ED%8A%B9%EC%A7%95</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;스프링부트 특징&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;톰캣, 제티, 언더토우 같은 WAS(web application server)가 내장되어 있어서 설치 하지 않아도 독립적으로 실행 가능하다.&lt;/li&gt;
&lt;li&gt;빌드 구성을 단순화하는 Spring boot Starter 제공하다,&lt;/li&gt;
&lt;li&gt;XML 설정을 하지 않고 자바 코드를 모두 작성할 수 있다.&lt;/li&gt;
&lt;li&gt;JAR을 이용해서 자바 옵션만으로도 배포가 가능하다.&lt;/li&gt;
&lt;li&gt;애플레이케이션의 모니터링 및 관리 도구인 스프링 엑츄에이터 (Spring actuator) 제공한다.&lt;/li&gt;
&lt;/ul&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;b&gt; 스프링&amp;nbsp; VS&amp;nbsp; 스프링부트&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 99.3025%; height: 124px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 21px;&quot;&gt;
&lt;td style=&quot;width: 33.3333%; height: 21px;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 21px;&quot;&gt;&lt;b&gt;스프링&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 21px;&quot;&gt;&lt;b&gt;스프링 부트&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 21px;&quot;&gt;
&lt;td style=&quot;width: 33.3333%; height: 21px;&quot;&gt;&lt;b&gt;목적&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 21px;&quot;&gt;엔터프라이즈 애플리케이션 개발을 더 쉽게&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 21px;&quot;&gt;스프링의 개발을 더 빠르고 쉽게 하기&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 21px;&quot;&gt;
&lt;td style=&quot;width: 33.3333%; height: 21px;&quot;&gt;&lt;b&gt;설정 파일&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 21px;&quot;&gt;개발자가 수동으로 구성&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 21px;&quot;&gt;자동 구성&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 21px;&quot;&gt;
&lt;td style=&quot;width: 33.3333%; height: 21px;&quot;&gt;&lt;b&gt;XML&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 21px;&quot;&gt;일부 파일은 XML로 직접 생성하고 관리&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 21px;&quot;&gt;사용하지 않음.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 21px;&quot;&gt;
&lt;td style=&quot;width: 33.3333%; height: 21px;&quot;&gt;&lt;b&gt;인메모리 데이터베이스 지원&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 21px;&quot;&gt;지원하지 않음&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 21px;&quot;&gt;인메모리 데이터베이스 자동 설정 지원&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;width: 33.3333%; height: 19px;&quot;&gt;&lt;b&gt;서버&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 19px;&quot;&gt;프로젝트를 띄우는 서버(ex. 톰캣, 제티)&lt;br /&gt;를 별도로 수동 설정&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 19px;&quot;&gt;내장형 서버를 제공하여 별도 설정 필요 X&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;1, IOC / DI 를 기초로 하는 스프링 코드.&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 여기에서 사용하는 @Autowired 는 스프링 컨테이너에 있는 빈을 주입하는데&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&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;pre id=&quot;code_1740569589237&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Component
public class MyBean {
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;빈을 등록하기 위해서는 @Component 어노테이션을 붙여서 Bean 클래스를 관리해준다.&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;*IOC(Inversion Of Control /&amp;nbsp; 제어의 역전) : 객체의 생성과 관리를 개발자가 하는 것이 아니라 프레임워크가 대신하는 것.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;*DI(Dependency Injection / 의존성 주입) : 외부에서 객체를 주입받아 사용하는 것.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;2. 스프링의 또다른 개념 AOP(Aspect Oriented Programming) : 관점 지향 프로그래밍.&amp;nbsp;&lt;/b&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;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;b&gt;[AOP설명]&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://adjh54.tistory.com/133#1.%20AOP%20%EC%9A%A9%EC%96%B4%20%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0-1-1&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://adjh54.tistory.com/133#1.%20AOP%20%EC%9A%A9%EC%96%B4%20%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0-1-1&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1740571710944&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;[Java] Spring Boot AOP(Aspect-Oriented Programming) 이해하고 설정하기&quot; data-og-description=&quot;해당 글에서는 Spring AOP에 대해 이해하고 환경설정을 해보는 방법에 대해서 공유를 목적으로 작성한 글입니다.1) Spring AOP(Aspect-Oriented Programming, AOP)1. AOP 용어 이해하기&amp;nbsp;  Spring AOP란?- Spring AOP는 &quot; data-og-host=&quot;adjh54.tistory.com&quot; data-og-source-url=&quot;https://adjh54.tistory.com/133#1.%20AOP%20%EC%9A%A9%EC%96%B4%20%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0-1-1&quot; data-og-url=&quot;https://adjh54.tistory.com/133&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/fjTte/hyYjmJ9qlu/FVKzKygi5uLDLoL8OF1UC0/img.png?width=800&amp;amp;height=431&amp;amp;face=0_0_800_431,https://scrap.kakaocdn.net/dn/eeqier/hyYmOZRfgH/tBaG2vpjjiJhZfwSa3AmX0/img.png?width=800&amp;amp;height=431&amp;amp;face=0_0_800_431,https://scrap.kakaocdn.net/dn/EJszk/hyYjCfFcx0/6nk9LbXcr2IM7mtFu8U6P1/img.png?width=2730&amp;amp;height=1700&amp;amp;face=0_0_2730_1700&quot;&gt;&lt;a href=&quot;https://adjh54.tistory.com/133#1.%20AOP%20%EC%9A%A9%EC%96%B4%20%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0-1-1&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://adjh54.tistory.com/133#1.%20AOP%20%EC%9A%A9%EC%96%B4%20%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0-1-1&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/fjTte/hyYjmJ9qlu/FVKzKygi5uLDLoL8OF1UC0/img.png?width=800&amp;amp;height=431&amp;amp;face=0_0_800_431,https://scrap.kakaocdn.net/dn/eeqier/hyYmOZRfgH/tBaG2vpjjiJhZfwSa3AmX0/img.png?width=800&amp;amp;height=431&amp;amp;face=0_0_800_431,https://scrap.kakaocdn.net/dn/EJszk/hyYjCfFcx0/6nk9LbXcr2IM7mtFu8U6P1/img.png?width=2730&amp;amp;height=1700&amp;amp;face=0_0_2730_1700');&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;[Java] Spring Boot AOP(Aspect-Oriented Programming) 이해하고 설정하기&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;해당 글에서는 Spring AOP에 대해 이해하고 환경설정을 해보는 방법에 대해서 공유를 목적으로 작성한 글입니다.1) Spring AOP(Aspect-Oriented Programming, AOP)1. AOP 용어 이해하기&amp;nbsp;  Spring AOP란?- Spring AOP는&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;adjh54.tistory.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;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;3. 이식 가능한 서비스 추상화 PSA(Potable Service Abstraction)&lt;/b&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;ex) Mapping &amp;amp; Class &amp;amp; Annotation('@')&amp;nbsp; , DB에 접근하기 위한 JPA, JDBC 같은 것들, WAS 또한 PSA의 예시 중 하나이다.&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;b&gt;[PSA설명]&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://sabarada.tistory.com/127&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://sabarada.tistory.com/127&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1740571762640&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;[Spring] Spring의 핵심기술 PSA - 개념과 원리&quot; data-og-description=&quot;안녕하세요. 오늘은 오랜만에 Spring에 대해서 이야기 해보고자합니다. [Spring] Spring의 정의와 기본 개념 포스팅에서 Spring의 대표적인 핵심가치 3가지로 IoC, AOP, PSA가 있다고 말씀드렸었습니다. 그&quot; data-og-host=&quot;sabarada.tistory.com&quot; data-og-source-url=&quot;https://sabarada.tistory.com/127&quot; data-og-url=&quot;https://sabarada.tistory.com/127&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/pVyjh/hyYmXvJfUp/YDzukLBqEkXPE3MSJcYbZ0/img.png?width=300&amp;amp;height=300&amp;amp;face=0_0_300_300,https://scrap.kakaocdn.net/dn/eACoH/hyYjrFg7R7/iHNkybyDQJUPOerBSurDWk/img.png?width=300&amp;amp;height=300&amp;amp;face=0_0_300_300,https://scrap.kakaocdn.net/dn/Vqt6n/hyYjlrxBfL/RhVECBWuaY9GVHNqTOruDk/img.png?width=2506&amp;amp;height=624&amp;amp;face=0_0_2506_624&quot;&gt;&lt;a href=&quot;https://sabarada.tistory.com/127&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://sabarada.tistory.com/127&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/pVyjh/hyYmXvJfUp/YDzukLBqEkXPE3MSJcYbZ0/img.png?width=300&amp;amp;height=300&amp;amp;face=0_0_300_300,https://scrap.kakaocdn.net/dn/eACoH/hyYjrFg7R7/iHNkybyDQJUPOerBSurDWk/img.png?width=300&amp;amp;height=300&amp;amp;face=0_0_300_300,https://scrap.kakaocdn.net/dn/Vqt6n/hyYjlrxBfL/RhVECBWuaY9GVHNqTOruDk/img.png?width=2506&amp;amp;height=624&amp;amp;face=0_0_2506_624');&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;[Spring] Spring의 핵심기술 PSA - 개념과 원리&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;안녕하세요. 오늘은 오랜만에 Spring에 대해서 이야기 해보고자합니다. [Spring] Spring의 정의와 기본 개념 포스팅에서 Spring의 대표적인 핵심가치 3가지로 IoC, AOP, PSA가 있다고 말씀드렸었습니다. 그&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;sabarada.tistory.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;* PSA(Potable Service Abstraction / 의식가능한 서비스 추상화) : 어느 기술을 사용하던 일관된 방식으로 처리하도록 하는 것.&lt;/p&gt;</description>
      <category>개발/Spring boot</category>
      <author>J_yoonS</author>
      <guid isPermaLink="true">https://this-is-another-one.tistory.com/7</guid>
      <comments>https://this-is-another-one.tistory.com/entry/%EC%8A%A4%ED%94%84%EB%A7%81-%EB%B6%80%ED%8A%B8-Spring-boot-%EC%9D%98-%ED%8A%B9%EC%A7%95#entry7comment</comments>
      <pubDate>Wed, 26 Feb 2025 21:12:19 +0900</pubDate>
    </item>
    <item>
      <title>게시글 단건 저장 &amp;amp; 조회</title>
      <link>https://this-is-another-one.tistory.com/entry/%EA%B2%8C%EC%8B%9C%EA%B8%80-%EB%8B%A8%EA%B1%B4-%EC%A0%80%EC%9E%A5-%EC%A1%B0%ED%9A%8C</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt; 전체 로직 : Controller -&amp;gt; Serivce 호출 -&amp;gt; Repository 호출 -&amp;gt; 최종적으로 넘어온 Json값은 post entity로 저장&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;&lt;b&gt;[PostController]&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1740275344116&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Slf4j
@RestController
@RequiredArgsConstructor 
public class PostController {

        private final PostService postService;

        @PostMapping(&quot;/posts&quot;)
        public void post(@RequestBody @Valid PostCreate request) {
            postService.write(request);
    }

        // posts/{postId} -&amp;gt; 글 한개만 조회
        @GetMapping(&quot;/posts/{postId}&quot;)
        public PostResponse get(@PathVariable Long postId) {
            return postService.get(postId);
        }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;@RequiredArgsContstrctor -&amp;gt; @autowired 보다 권고되는 이유&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot;&gt;선언만으로도 생성자 주입이 가능하게 된다.&lt;/span&gt;&lt;/b&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;④ 객체 변이 방지 (final 가능)&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;b&gt;1. 게시글 작성 메서드&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;- Json형태로 받아오기 위해 @RequestBody 사용, @Valid 는 유효성검사를 해준다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;그리고 게시글을 작성하는 postSerivce.write 메서드 가 실행된다. (하단 Service 참고.)&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. 게시글 정보 조회 메서드&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;- postService.get(postId);를 호출하여 게시글 정보를 가져오고, 이를 PostResponse 형태로 반환한다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; 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;a href=&quot;https://madplay.github.io/post/why-constructor-injection-is-better-than-field-injection&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://madplay.github.io/post/why-constructor-injection-is-better-than-field-injection&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;b&gt;**@RequiredArgsContstrctor -&amp;gt; @autowired 보다 권고되는 이유 참고.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;b&gt;[PostService]&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1740277610965&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Slf4j
@Service
@RequiredArgsConstructor
public class PostService {

    private final PostRepository postRepository;

    public void write(PostCreate postCreate) { // jsonBody 에서 꺼내와서 생성자 형태로 넘겨주고 있음.
        Post post = Post.builder()
                    .title(postCreate.getTitle())
                    .content(postCreate.getContent())
                    .build();

        postRepository.save(post);
    }

    public PostResponse get(Long id) {
        Post post = postRepository.findById(id) // warning
                .orElseThrow(()-&amp;gt; new IllegalArgumentException(&quot;존재하지 않는 글입니다.&quot;));


        PostResponse response = PostResponse.builder()
                .id(post.getId())
                .title(post.getTitle())
                .content(post.getContent())
                .build();

        return response;

    }

}&lt;/code&gt;&lt;/pre&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;b&gt;1. 새로운 게시글을 생성하고 저장하는 메서드&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Post.builder()를 사용하여 Post 객체를 생성, postCreate에서 제목과 내용을 가져와서 설정한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- postRepository.save(post); 를 호출하여 생성한 Post 객체를 데이터베이스에 저장한다,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1740278403031&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public interface PostRepository extends JpaRepository&amp;lt;Post, Long&amp;gt; {
}&lt;/code&gt;&lt;/pre&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;u&gt;*postRepository는 JDBC 역할의&lt;span&gt;&amp;nbsp;&lt;/span&gt;JpaRepository 를 상속받는다.&lt;/u&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;b&gt;2. 게시글의 생성과 조회&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- postRepository.findById(id)를 호출하여 주어진 ID에 해당하는 게시글을 조회하여. 게시글이 존재하지 않는 경우IllegalArgumentException을 발생시킨다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 게시글이 존재할 경우, PostResponse 객체를 생성하여 게시글의 ID, 제목, 내용을 포함하여&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PostResponse 반환한다. (하단 DTO 참고)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;b&gt;[게시글 조회를 위한 DTO : PostResponse]&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1740279963484&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Getter
public class PostResponse {

    private final Long id;
    private final String title;
    private final String content;

    // 생성자 오버로딩
    public PostResponse(Post post) {
        this.id = post.getId();
        this.title = post.getTitle();
        this.content = post.getContent();
    }

    @Builder
    public PostResponse(Long id, String title, String content) {
        this.id = id;
        this.title = title.substring(0, Math.min(title.length(), 10));
        this.content = content;
    }

}&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;this.title&amp;nbsp;=&amp;nbsp;title.substring(0,&amp;nbsp;Math.min(title.length(),&amp;nbsp;10));&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 제목의 글자수를 최대 10글자로 잘라서 저장한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;b&gt;[게시글 생성을 위한 DTO : PostCreate]&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1740279111294&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Setter
@Getter
@ToString
@NoArgsConstructor
public class PostCreate {

    @NotBlank(message = &quot;타이틀을 입력하세요.&quot;)
    private String title;

    @NotBlank(message = &quot;콘텐츠를 입력해주세요.&quot;)
    private String content;

    @Builder
    public PostCreate(String title, String content) {
        this.title = title;
        this.content = content;
    }

}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;@NotBlank -&amp;gt; null 또는 blank 가 들어오면 에러를 발생시킨다. (Message 를 통해 내가 원하는 문구 가능.)&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;b&gt;빌더 패턴의 장점&lt;/b&gt;&lt;br /&gt;1. 필요한 데이터만 설정할 수 있다.&lt;br /&gt;2. 유연성을 확보할 수 있다.&lt;br /&gt;3. 가독성을 높일 수 있다.&lt;br /&gt;4. 불변성을 확보할 수 있다.&lt;br /&gt;&lt;br /&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;a href=&quot;https://velog.io/@bey1548/JAVA-%EB%B9%8C%EB%8D%94-%ED%8C%A8%ED%84%B4Builder-Pattern%EC%9D%84-%EC%82%AC%EC%9A%A9%ED%95%B4%EC%95%BC-%ED%95%98%EB%8A%94-%EC%9D%B4%EC%9C%A0&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://velog.io/@bey1548/JAVA-%EB%B9%8C%EB%8D%94-%ED%8C%A8%ED%84%B4Builder-Pattern%EC%9D%84-%EC%82%AC%EC%9A%A9%ED%95%B4%EC%95%BC-%ED%95%98%EB%8A%94-%EC%9D%B4%EC%9C%A0&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1740279712242&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;[JAVA] 빌더 패턴(Builder Pattern)을 사용해야 하는 이유&quot; data-og-description=&quot;필요한 데이터만 설정할 수 있음유연성을 확보할 수 있음가독성을 높일 수 있음불변성을 확보할 수 있음예를 들어 User 객체를 생성하는데 age라는 parameter가 필요 없는 상황이라고 가정.생성자나&quot; data-og-host=&quot;velog.io&quot; data-og-source-url=&quot;https://velog.io/@bey1548/JAVA-%EB%B9%8C%EB%8D%94-%ED%8C%A8%ED%84%B4Builder-Pattern%EC%9D%84-%EC%82%AC%EC%9A%A9%ED%95%B4%EC%95%BC-%ED%95%98%EB%8A%94-%EC%9D%B4%EC%9C%A0&quot; data-og-url=&quot;https://velog.io/@bey1548/JAVA-빌더-패턴Builder-Pattern을-사용해야-하는-이유&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/cN62V4/hyYjkrD0Ny/QpC7Pep1ifKPO6t65xSLtK/img.png?width=950&amp;amp;height=500&amp;amp;face=0_0_950_500,https://scrap.kakaocdn.net/dn/eaHCBt/hyYjAgT8qv/H60UAuPT4d1RDSOG1uXR30/img.png?width=420&amp;amp;height=420&amp;amp;face=0_0_420_420&quot;&gt;&lt;a href=&quot;https://velog.io/@bey1548/JAVA-%EB%B9%8C%EB%8D%94-%ED%8C%A8%ED%84%B4Builder-Pattern%EC%9D%84-%EC%82%AC%EC%9A%A9%ED%95%B4%EC%95%BC-%ED%95%98%EB%8A%94-%EC%9D%B4%EC%9C%A0&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://velog.io/@bey1548/JAVA-%EB%B9%8C%EB%8D%94-%ED%8C%A8%ED%84%B4Builder-Pattern%EC%9D%84-%EC%82%AC%EC%9A%A9%ED%95%B4%EC%95%BC-%ED%95%98%EB%8A%94-%EC%9D%B4%EC%9C%A0&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/cN62V4/hyYjkrD0Ny/QpC7Pep1ifKPO6t65xSLtK/img.png?width=950&amp;amp;height=500&amp;amp;face=0_0_950_500,https://scrap.kakaocdn.net/dn/eaHCBt/hyYjAgT8qv/H60UAuPT4d1RDSOG1uXR30/img.png?width=420&amp;amp;height=420&amp;amp;face=0_0_420_420');&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;[JAVA] 빌더 패턴(Builder Pattern)을 사용해야 하는 이유&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;필요한 데이터만 설정할 수 있음유연성을 확보할 수 있음가독성을 높일 수 있음불변성을 확보할 수 있음예를 들어 User 객체를 생성하는데 age라는 parameter가 필요 없는 상황이라고 가정.생성자나&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;velog.io&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size14&quot;&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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;[게시글을 DB에&amp;nbsp; 저장하기 위한 Entity : Post]&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1740280849687&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Getter
@Entity
@NoArgsConstructor(access = AccessLevel.PUBLIC)
public class Post {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id; //자동생성

    private String title;

    @Lob
    private String content;

    @Builder
    public Post(String title, String content) {
        this.title = title;
        this.content = content;
    }

}&lt;/code&gt;&lt;/pre&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;b&gt;JPA 엔티티 클래스&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;@Lob : 큰 데이터를 저장하는데 사용한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;@GeneratedValue(strategy = GenerationType.IDENTITY) -&amp;gt; ID값 자동생성 한다.&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;&lt;b&gt;[각 클래스의 역할]&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #333333; text-align: start;&quot;&gt;&amp;bull;&lt;/span&gt; PostCreate:&amp;nbsp;게시글&amp;nbsp;생성을&amp;nbsp;위한&amp;nbsp;요청&amp;nbsp;데이터&amp;nbsp;구조&amp;nbsp;(클라이언트&amp;nbsp;&amp;rarr;&amp;nbsp;서버).&lt;br /&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #333333; text-align: start;&quot;&gt;&amp;bull;&lt;/span&gt; PostResponse:&amp;nbsp;게시글&amp;nbsp;조회&amp;nbsp;시&amp;nbsp;반환되는&amp;nbsp;응답&amp;nbsp;데이터&amp;nbsp;구조&amp;nbsp;(서버&amp;nbsp;&amp;rarr;&amp;nbsp;클라이언트).&lt;br /&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #333333; text-align: start;&quot;&gt;&amp;bull;&lt;/span&gt; Post: 데이터베이스에 저장되는 Entity&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>개발/Spring boot</category>
      <author>J_yoonS</author>
      <guid isPermaLink="true">https://this-is-another-one.tistory.com/6</guid>
      <comments>https://this-is-another-one.tistory.com/entry/%EA%B2%8C%EC%8B%9C%EA%B8%80-%EB%8B%A8%EA%B1%B4-%EC%A0%80%EC%9E%A5-%EC%A1%B0%ED%9A%8C#entry6comment</comments>
      <pubDate>Sun, 23 Feb 2025 12:43:33 +0900</pubDate>
    </item>
    <item>
      <title>데이터 검증</title>
      <link>https://this-is-another-one.tistory.com/entry/%EB%8D%B0%EC%9D%B4%ED%84%B0-%EA%B2%80%EC%A6%9D</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://spring.io/blog/2013/11/01/exception-handling-in-spring-mvc&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://spring.io/blog/2013/11/01/exception-handling-in-spring-mvc&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;validation을 위해 &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;gradle 에&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt; implementation 을 넣고&lt;/p&gt;
&lt;div style=&quot;background-color: #1e1f22; color: #bcbec4;&quot;&gt;
&lt;pre class=&quot;clean&quot;&gt;&lt;code&gt;    implementation 'org.springframework.boot:spring-boot-starter-validation'
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div style=&quot;background-color: #1e1f22; color: #bcbec4;&quot;&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;public class PostCreate {

    @NotBlank(message=&quot;타이틀을 입력해주세요.&quot;)
    private String title;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;@NotBlank(message=&quot;타이틀을 입력해주세요.&quot;)&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;dto 에 @NotBlank를 추가하면, null &amp;amp; blank를 검사해줘서 값이 들어올 경우 error를 발생시켜준다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;-&amp;gt; message 를 직접 입력할 수 있다.&lt;/p&gt;
&lt;div style=&quot;background-color: #1e1f22; color: #bcbec4;&quot;&gt;
&lt;pre class=&quot;kotlin&quot;&gt;&lt;code&gt;@PostMapping(&quot;/posts&quot;)
public String post(@RequestBody @Valid PostCreate params) throws Exception {
    log.info(&quot;params={}&quot;, params.toString());

    return &quot;Hello World&quot;;
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;추가로 Postcontorller 클래스,&amp;nbsp; @RequestBody 옆에 @Vaild를 적어준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div style=&quot;background-color: #1e1f22; color: #bcbec4;&quot;&gt;
&lt;pre class=&quot;kotlin&quot;&gt;&lt;code&gt;@PostMapping(&quot;/posts&quot;)
public String post(@RequestBody @Valid PostCreate params,BindingResult result) {
    log.info(&quot;params={}&quot;, params.toString());

    return &quot;Hello World&quot;;
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;BindingResult 를 넣으면, error문으로 무엇이 들어있는지 확인 가능하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div style=&quot;background-color: #1e1f22; color: #bcbec4;&quot;&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;@PostMapping(&quot;/posts&quot;)
        public Map&amp;lt;String, String&amp;gt; post(@RequestBody @Valid PostCreate params,BindingResult result) {
            if (result.hasErrors()) {
                List&amp;lt; FieldError&amp;gt; fieldErrors = result.getFieldErrors();
                FieldError firstFieldError = fieldErrors.get(0);
                String fieldName = firstFieldError.getField(); // title
                String errorMessage = firstFieldError.getDefaultMessage(); // ..에러 메시지

                Map&amp;lt;String, String&amp;gt; error = new HashMap&amp;lt;&amp;gt;();
                error.put(fieldName, errorMessage);
                return error;
            }

            return Map.of();
        }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&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; 알고 싶을경우, BindingResult 를 List화 시켜서 볼 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1, FieldEorros 를 배열로 받아서, 첫번째 배열을 firstFildError 로 받는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. fieldName 은 title, errorMessage 에러메시지를 나타낸다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 값을 Map으로 받아서 나타낸다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. return 값은 Map.of();&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;*JsonPath 에 대한 검증방법 (Object &amp;amp; List 정도 알아두면 좋음.)&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;a href=&quot;https://bomz.tistory.com/29&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;출처 : https://bomz.tistory.com/29&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1740193994782&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;Spring Boot 에서 JUnit5 , MockMvc 를 이용하여 JSon 응답 값 검증하기&quot; data-og-description=&quot;전 포스팅으로 Spring Boot 기반에서 JUnit5 를 이용하여 테스트 진행법을 작성했다 이번에는 기존 포스팅에서 실수로 빼먹은 응답 값 유효성 검증 방법을 작성한다 GET 요청 import static org.springframework&quot; data-og-host=&quot;bomz.tistory.com&quot; data-og-source-url=&quot;https://bomz.tistory.com/29&quot; data-og-url=&quot;https://bomz.tistory.com/29&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/cnahhs/hyYjMasj6M/Xy7YAlCarfXdOaQZ9bQ4J0/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/cd1fbC/hyYfRYSKc9/sok26rHkBu7fk8AKM2kpa0/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/bznQHY/hyYf3dVreu/0jrpA0aLB34HzS7GCCZSt0/img.png?width=264&amp;amp;height=200&amp;amp;face=0_0_264_200&quot;&gt;&lt;a href=&quot;https://bomz.tistory.com/29&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://bomz.tistory.com/29&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/cnahhs/hyYjMasj6M/Xy7YAlCarfXdOaQZ9bQ4J0/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/cd1fbC/hyYfRYSKc9/sok26rHkBu7fk8AKM2kpa0/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/bznQHY/hyYf3dVreu/0jrpA0aLB34HzS7GCCZSt0/img.png?width=264&amp;amp;height=200&amp;amp;face=0_0_264_200');&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;Spring Boot 에서 JUnit5 , MockMvc 를 이용하여 JSon 응답 값 검증하기&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;전 포스팅으로 Spring Boot 기반에서 JUnit5 를 이용하여 테스트 진행법을 작성했다 이번에는 기존 포스팅에서 실수로 빼먹은 응답 값 유효성 검증 방법을 작성한다 GET 요청 import static org.springframework&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;bomz.tistory.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;a href=&quot;https://spring.io/blog/2013/11/01/exception-handling-in-spring-mvc&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://spring.io/blog/2013/11/01/exception-handling-in-spring-mvc&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1740194299377&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;Exception Handling in Spring MVC&quot; data-og-description=&quot;NOTE: Revised April 2018 Spring MVC provides several complimentary approaches to exception handling but, when teaching Spring MVC, I often find that my students are confused or not comfortable with them. Today I'm going to show you the various options avai&quot; data-og-host=&quot;spring.io&quot; data-og-source-url=&quot;https://spring.io/blog/2013/11/01/exception-handling-in-spring-mvc&quot; data-og-url=&quot;https://spring.io/blog/2013/11/01/exception-handling-in-spring-mvc&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/81IJl/hyYjugDeiq/ZrKbMpEFhH1UP336qZnfj0/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/cL57GE/hyYjM2y2Hq/Sp6ChFkLHZvMVrNCSQzhGk/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/bNSzCG/hyYfXKOfYQ/9dkFiPk6JvUQ5TAenKB6Ik/img.png?width=1343&amp;amp;height=906&amp;amp;face=0_0_1343_906&quot;&gt;&lt;a href=&quot;https://spring.io/blog/2013/11/01/exception-handling-in-spring-mvc&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://spring.io/blog/2013/11/01/exception-handling-in-spring-mvc&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/81IJl/hyYjugDeiq/ZrKbMpEFhH1UP336qZnfj0/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/cL57GE/hyYjM2y2Hq/Sp6ChFkLHZvMVrNCSQzhGk/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/bNSzCG/hyYfXKOfYQ/9dkFiPk6JvUQ5TAenKB6Ik/img.png?width=1343&amp;amp;height=906&amp;amp;face=0_0_1343_906');&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;Exception Handling in Spring MVC&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;NOTE: Revised April 2018 Spring MVC provides several complimentary approaches to exception handling but, when teaching Spring MVC, I often find that my students are confused or not comfortable with them. Today I'm going to show you the various options avai&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;spring.io&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;@controllerAdvice -&amp;gt; 개별이 아닌, 모든 예외처리 가능.&lt;/p&gt;
&lt;pre id=&quot;code_1740194476939&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@ControllerAdvice
class GlobalControllerExceptionHandler {
    @ResponseStatus(HttpStatus.CONFLICT)  // 409
    @ExceptionHandler(DataIntegrityViolationException.class)
    public void handleConflict() {
        // Nothing to do
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;응답값은 409에러로 발생.&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;pre id=&quot;code_1740195526513&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@ControllerAdvice
public class ExceptionController {

    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler(Exception.class)
    public void exceptionHandler() {
        System.out.println(&quot;하하하&quot;);
    }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;BAD_REQUEST // 에러 400으로 응답.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div style=&quot;background-color: #1e1f22; color: #bcbec4;&quot;&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler(MethodArgumentNotValidException.class)
public void exceptionHandler(MethodArgumentNotValidException e) {
    // MethodArgumentNotValidException
    // e.getField()

}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;MethodArgumentNotValidException 발생 했을때만 해당 메서드가 실행되도록 변경.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1740196517096&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseBody
    public Map&amp;lt;String, String&amp;gt; invalidRequestHandler(MethodArgumentNotValidException e) {
        FieldError fieldError = e.getFieldError();
        String field = fieldError.getField();
        String message = fieldError.getDefaultMessage();

        Map&amp;lt;String, String&amp;gt; response = new HashMap&amp;lt;&amp;gt;();
        response.put(field, message);
        return response;
    }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;@responseBody 를 통해서 HashMap -&amp;gt; Json 형태로 응답할수 있다.&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;client 에서 요청값이 잘못 됐을때, 사용자에게 피드백을 보여주기 위해 사용.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;validation object 는 값이 필드별로 어떻게 잘못됐는지 알려주기 위해 사용.&lt;/p&gt;</description>
      <category>개발/Spring boot</category>
      <author>J_yoonS</author>
      <guid isPermaLink="true">https://this-is-another-one.tistory.com/4</guid>
      <comments>https://this-is-another-one.tistory.com/entry/%EB%8D%B0%EC%9D%B4%ED%84%B0-%EA%B2%80%EC%A6%9D#entry4comment</comments>
      <pubDate>Sat, 22 Feb 2025 13:40:45 +0900</pubDate>
    </item>
  </channel>
</rss>