<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>sootudio</title>
    <link>https://sootudio-programming.tistory.com/</link>
    <description>지식의 나눔을 실천하는 개발자가 되고 싶습니다.</description>
    <language>ko</language>
    <pubDate>Thu, 11 Jun 2026 21:17:13 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>swimee</managingEditor>
    <image>
      <title>sootudio</title>
      <url>https://tistory1.daumcdn.net/tistory/4852080/attach/47489398ff2d4d2f868f05c6fe4243b8</url>
      <link>https://sootudio-programming.tistory.com</link>
    </image>
    <item>
      <title>2024년 하반기부터 2026년 초까지, 길었던 취준 생활을 마무리하며</title>
      <link>https://sootudio-programming.tistory.com/entry/2024%EB%85%84-%ED%95%98%EB%B0%98%EA%B8%B0%EB%B6%80%ED%84%B0-2026%EB%85%84-%EC%B4%88%EA%B9%8C%EC%A7%80-%EA%B8%B8%EC%97%88%EB%8D%98-%EC%B7%A8%EC%A4%80-%EC%83%9D%ED%99%9C%EC%9D%84-%EB%A7%88%EB%AC%B4%EB%A6%AC%ED%95%98%EB%A9%B0</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;0. 시작하기 전에&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시작하기 전에 말하자면, 제가 2024년 하반기부터 지금까지 계속 취준만 했던 건 아닙니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실제로는 6개월은 부트캠프에, 8개월은 회사에서 일을 하며 있었고, 지금 다니는 회사에 들어온 지도 한 달이 다 되어 갑니다.&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&gt;&lt;del&gt;사실 자극적인 라이팅으로 블로그 유입을 늘리고 싶었습니다&lt;/del&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;나 너무 많은 일이 있었어.jpeg&quot; data-origin-width=&quot;512&quot; data-origin-height=&quot;249&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b05vRg/dJMcabjIvNu/Hcjr0LFLGqgnRRK9hGHjK1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b05vRg/dJMcabjIvNu/Hcjr0LFLGqgnRRK9hGHjK1/img.jpg&quot; data-alt=&quot;진짜 많은 일이 잇엇어&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b05vRg/dJMcabjIvNu/Hcjr0LFLGqgnRRK9hGHjK1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb05vRg%2FdJMcabjIvNu%2FHcjr0LFLGqgnRRK9hGHjK1%2Fimg.jpg&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;512&quot; height=&quot;249&quot; data-filename=&quot;나 너무 많은 일이 있었어.jpeg&quot; data-origin-width=&quot;512&quot; data-origin-height=&quot;249&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;이전에 올린 마지막 회고가 2024년 상반기 회고였으니, 그로부터 거의 1년 9개월 정도가 지났습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그동안 정말 많은 일들이 있었고, 다 쓰려니 이 글이 2026년 상반기 안에는 올라갈 수 있을지 걱정이지만...&lt;br /&gt;일단 차근차근 시작해 보겠습니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. 2024년 하반기 : 어쩌면, 취업에 가장 가까웠던 시기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2024년 하반기는 어쩌면 그동안의 기간 중 제가 취업에 가장 가까워졌던 시기였지 않을까 생각합니다.&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;br /&gt;기억에 남는 몇 가지 키워드들로 2024년 하반기 회고를 해보려 합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1.1. 신한은행 해커톤 대상&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;temp_1777190773188.-6449292.jpeg&quot; data-origin-width=&quot;4032&quot; data-origin-height=&quot;3024&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lIc7v/dJMcacCULK9/XzliEzKb8bDZktlHJ33kq1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lIc7v/dJMcacCULK9/XzliEzKb8bDZktlHJ33kq1/img.jpg&quot; data-alt=&quot;너무 멀리서 찍혔죠? 인터넷에 치면 더 화질 좋은 사진이 있습니다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lIc7v/dJMcacCULK9/XzliEzKb8bDZktlHJ33kq1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlIc7v%2FdJMcacCULK9%2FXzliEzKb8bDZktlHJ33kq1%2Fimg.jpg&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;675&quot; height=&quot;506&quot; data-filename=&quot;temp_1777190773188.-6449292.jpeg&quot; data-origin-width=&quot;4032&quot; data-origin-height=&quot;3024&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;하반기에 가장 기억에 남는 일을 꼽으라고 한다면, '2024 신한은행 해커톤'에서 대상을 받은 일입니다.&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;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;br /&gt;해커톤 주제가 'Everywhere Bank'였던 걸로 기억하는데, 반려동물 금융 서비스라는 참신한 아이디어와 훌륭한 디자인이 좋은 평가를 받았던 것 같습니다.&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-filename=&quot;temp_1777190749153.-1759632368.jpeg&quot; data-origin-width=&quot;1400&quot; data-origin-height=&quot;1050&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/zX6mW/dJMcaf7q7xQ/xFKQBy4uxMPTMR2uN7Nkq0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/zX6mW/dJMcaf7q7xQ/xFKQBy4uxMPTMR2uN7Nkq0/img.jpg&quot; data-alt=&quot;진짜 뭐 하는건 아니고, 뭐 하는척 하라고 해서...&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/zX6mW/dJMcaf7q7xQ/xFKQBy4uxMPTMR2uN7Nkq0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FzX6mW%2FdJMcaf7q7xQ%2FxFKQBy4uxMPTMR2uN7Nkq0%2Fimg.jpg&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;529&quot; height=&quot;397&quot; data-filename=&quot;temp_1777190749153.-1759632368.jpeg&quot; data-origin-width=&quot;1400&quot; data-origin-height=&quot;1050&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;이제 와서 생각하니 서버 개발자로서 좀 더 좋은 퍼포먼스를 보여줬으면 어땠을까 하는 아쉬움도 있지만, 그 순간에는 할 수 있는 최선을 다했다고 생각합니다.&lt;br /&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;1.2. 흘려보낸 좋은 기회들&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2024년 하반기에는 유난히 좋은 기회들이 있었던 것 같습니다.&lt;br /&gt;지원을 많이 하지 않았음에도 누구나 다 아는 좋은 기업들의(사실 2개입니다) 서류를 통과하거나, 면접까지 간 경우도 있었습니다.&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;br /&gt;이유는... 위에 &lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;써놨죠?&lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;애초에 지원을 많이 하지 않았습니다.&lt;br /&gt;그리고 프로젝트다, 공모전이다 해서 바쁘다는 핑계로 좋은 기회들을 많이 놓쳤던 것 같습니다.&lt;br /&gt;진짜 최종 합격을 한 사람들을 보면 그런 걸 하면서도 꾸준하게 열심히 취업에 시간과 노력을 투자한 사람들일 텐데 말이죠.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;어쩔수 없어.jpg&quot; data-origin-width=&quot;1200&quot; data-origin-height=&quot;960&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/biyUMS/dJMcaa591pH/NkeZt5aRKMh6fvYsOe69r0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/biyUMS/dJMcaa591pH/NkeZt5aRKMh6fvYsOe69r0/img.jpg&quot; data-alt=&quot;진짜 어쩔 수 없어. 그냥 해야해&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/biyUMS/dJMcaa591pH/NkeZt5aRKMh6fvYsOe69r0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbiyUMS%2FdJMcaa591pH%2FNkeZt5aRKMh6fvYsOe69r0%2Fimg.jpg&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;342&quot; data-filename=&quot;어쩔수 없어.jpg&quot; data-origin-width=&quot;1200&quot; data-origin-height=&quot;960&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;지나간 일에 만약이라는 건 없다지만, 가끔씩 '그때 내가 정말 죽을 둥 살 둥으로 취준을 했다면, 나에게 온 좋은 기회들을 잡을 수 있었을까?' 라는 생각이 듭니다.&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;h3 data-ke-size=&quot;size23&quot;&gt;1.3. 함께 이 시기를 보낸 소중한 사람들&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여러모로 바쁘게 지냈던, 그리고 힘든 일도 많았던 시기였지만...&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;정말 많은 감사한 사람들이 있지만, 싸피에서부터 지금까지 꾸준히 연락하는 두 명이 생각나서 사진을 올려 봅니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Screenshot_20260426_165359_Gallery.jpg&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cJqXlH/dJMcaakLYBl/qhwsnim1mlgZGxaStZ2Zw1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cJqXlH/dJMcaakLYBl/qhwsnim1mlgZGxaStZ2Zw1/img.jpg&quot; data-alt=&quot;취업박람회 갔다가 한강러닝 하는 남자들. 참고로 저는 이 사진을 찍고서 체력 이슈로 조금씩 뒤쳐졌습니다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cJqXlH/dJMcaakLYBl/qhwsnim1mlgZGxaStZ2Zw1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcJqXlH%2FdJMcaakLYBl%2Fqhwsnim1mlgZGxaStZ2Zw1%2Fimg.jpg&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;690&quot; height=&quot;388&quot; data-filename=&quot;Screenshot_20260426_165359_Gallery.jpg&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&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 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;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2. 2025년 상반기 : 공백기를 보내지 않기 위한 몸부림&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2.1. 다시 본가로&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;본가에 내려온 건 2024년 12월 25일, 크리스마스였습니다.&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-filename=&quot;20250504_231626.jpg&quot; data-origin-width=&quot;4000&quot; data-origin-height=&quot;3000&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/0dZaE/dJMcaiXmQea/m3cOMHKSY2XcT1jk6wRZuK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/0dZaE/dJMcaiXmQea/m3cOMHKSY2XcT1jk6wRZuK/img.jpg&quot; data-alt=&quot;당시 제 방 사진입니다. 감성 있게 찍는다고 찍은건데, 다시 보니 조잡하네요.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/0dZaE/dJMcaiXmQea/m3cOMHKSY2XcT1jk6wRZuK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F0dZaE%2FdJMcaiXmQea%2Fm3cOMHKSY2XcT1jk6wRZuK%2Fimg.jpg&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;611&quot; height=&quot;458&quot; data-filename=&quot;20250504_231626.jpg&quot; data-origin-width=&quot;4000&quot; data-origin-height=&quot;3000&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 style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;부모님께 손을 벌리고 싶지 않아서 조금씩 모아뒀던 돈을 대충 계산해봤는데, 용돈 없이 1년은 버틸 수 있을 것 같았습니다. 그래서 스스로와 약속을 하나 했어요.&amp;nbsp;1년 안에 꼭 취업을 하자고.&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;/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-filename=&quot;Screenshot_20260428_092944_Chrome.jpg&quot; data-origin-width=&quot;1913&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/boKJNl/dJMcajvfEa1/SX9N1pTCcsYHpaYuoKjK20/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/boKJNl/dJMcajvfEa1/SX9N1pTCcsYHpaYuoKjK20/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/boKJNl/dJMcajvfEa1/SX9N1pTCcsYHpaYuoKjK20/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FboKJNl%2FdJMcajvfEa1%2FSX9N1pTCcsYHpaYuoKjK20%2Fimg.jpg&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;600&quot; height=&quot;339&quot; data-filename=&quot;Screenshot_20260428_092944_Chrome.jpg&quot; data-origin-width=&quot;1913&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Screenshot_20260428_093123_Chrome (1).jpg&quot; data-origin-width=&quot;1922&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/BpUdw/dJMcafsRtiS/lA5qsJ3QE13y2yETTzdzN0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/BpUdw/dJMcafsRtiS/lA5qsJ3QE13y2yETTzdzN0/img.jpg&quot; data-alt=&quot;제가 침투부에서 굉장히 좋아하는 장면 중 하나입니다. 안할 순 없어. 그냥 해야 해.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/BpUdw/dJMcafsRtiS/lA5qsJ3QE13y2yETTzdzN0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FBpUdw%2FdJMcafsRtiS%2FlA5qsJ3QE13y2yETTzdzN0%2Fimg.jpg&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;600&quot; height=&quot;337&quot; data-filename=&quot;Screenshot_20260428_093123_Chrome (1).jpg&quot; data-origin-width=&quot;1922&quot; data-origin-height=&quot;1080&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;h3 data-ke-size=&quot;size23&quot;&gt;2.2. 다시는 캠퍼스 리크루팅을 하지 않겠다.&lt;/h3&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-filename=&quot;img.jpg&quot; data-origin-width=&quot;1200&quot; data-origin-height=&quot;756&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/UC196/dJMcajhHP2q/Mk8GthKg9qyZOYDHxGk6Z1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/UC196/dJMcajhHP2q/Mk8GthKg9qyZOYDHxGk6Z1/img.jpg&quot; data-alt=&quot;내가 안가고 만다 -&amp;amp;gt; 지금이라도 괜찮으니 제발 연락주세요 -&amp;amp;gt; 내가 진짜 안간다 의 반복...&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/UC196/dJMcajhHP2q/Mk8GthKg9qyZOYDHxGk6Z1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FUC196%2FdJMcajhHP2q%2FMk8GthKg9qyZOYDHxGk6Z1%2Fimg.jpg&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;489&quot; height=&quot;308&quot; data-filename=&quot;img.jpg&quot; data-origin-width=&quot;1200&quot; data-origin-height=&quot;756&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;내가 안가고 만다 -&amp;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;더 상처가 됐던 건 취업 컨설턴트의 반응이었습니다. 당연히 감정적인 공감을 바라는 게 아니라 싸피 캠퍼스 리크루팅에 참여한 기업들이 면접 날짜 지나서 연락하고, 면접 본 뒤에도 아무 연락 없이 다시 채용공고를 올리고 있는데, 싸피 취업 컨설턴트로서 회사랑 연결을 해준다던지, 직접 연락을 해준다던지 정도는 해 줄거라고 생각했습니다. 근데 '합격자 가끔 공유해주기도 하니까 그때 말씀드릴게요~' 말해버리니까... 저도 쓸대없는 희망을 가지고 계속 기다리게 됐던 것 같습니다. 결국 탈락했다고 말하니까 슬퍼요 이모티콘 하나 남기고 연락이 끊기더라구요.&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;나중에 들은 얘기인데, 캠퍼스 리크루팅을 진행한 기업들 중 몇몇 기업들이 월급을 주지 않고 권고사직을 한 사례가 있었다고 하더라고요. 물론 이 프로그램을 통해 좋은 기회를 잡아 잘 다니고 있는 분들도 분명 있을 테니, 이런 회고를 적는 게 조심스러운 것도 사실입니다. 그래도 적어도 저에게는, 쉬운 길에는 이유가 있다는 걸 깨닫게 해준 경험이었습니다.&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;2.3. 내 사랑 워키&lt;/h3&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-filename=&quot;playstore_1024.png&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;500&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b4Cb7F/dJMcacbPdMk/X8EeBlV7YOidLQ4yeCRqhK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b4Cb7F/dJMcacbPdMk/X8EeBlV7YOidLQ4yeCRqhK/img.png&quot; data-alt=&quot;정말 귀엽죠? 다운받고 싶죠?&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b4Cb7F/dJMcacbPdMk/X8EeBlV7YOidLQ4yeCRqhK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb4Cb7F%2FdJMcacbPdMk%2FX8EeBlV7YOidLQ4yeCRqhK%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;555&quot; height=&quot;271&quot; data-filename=&quot;playstore_1024.png&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;500&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;팀은 기획, 디자인, 안드로이드, iOS, 웹 프론트엔드, 서버까지 총 10명으로 구성됐습니다. 싸피에서 알던 사람들도 있었고, 워키를 통해 처음 만난 사람들도 있었는데, 지금은 전부 다 친해졌습니다.&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;2025년 상반기에 앱스토어와 플레이스토어에 정식 출시했어요. 폭발적인 인기는 아니었지만 꾸준한 유입이 있었고, 서비스를 종료할 시점에는 200명이 넘는 사람들이 사용하고 있었습니다.&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-filename=&quot;Screenshot_20250719_174352_Walkie.jpg&quot; data-origin-width=&quot;1080&quot; data-origin-height=&quot;2095&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xd6X9/dJMcaf7sPQF/NhYkjiotYIq8vGT5Yr7bvK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xd6X9/dJMcaf7sPQF/NhYkjiotYIq8vGT5Yr7bvK/img.jpg&quot; data-alt=&quot;열심히 모으다 보면 이런 멋진 캐릭터도 줍니다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xd6X9/dJMcaf7sPQF/NhYkjiotYIq8vGT5Yr7bvK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fxd6X9%2FdJMcaf7sPQF%2FNhYkjiotYIq8vGT5Yr7bvK%2Fimg.jpg&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;262&quot; height=&quot;508&quot; data-filename=&quot;Screenshot_20250719_174352_Walkie.jpg&quot; data-origin-width=&quot;1080&quot; data-origin-height=&quot;2095&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 data-ke-size=&quot;size16&quot;&gt;워키는 제 취준 생활을 함께해준 프로젝트입니다. 이 프로젝트를 하면서 실력도 많이 늘었고, 캐릭터들도 너무 좋았어요. 무엇보다 함께한 사람들이 너무 좋아서, 프로젝트에 대한 애정이 계속 이어졌던 것 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇게 2025년 1월부터 시작된 워키는 2026년 3월에 막을 내렸습니다. 각자의 사정으로 함께하지 못하는 멤버들이 조금씩 생겼고, 어느 정도 이상이 되니 남은 인원으로는 서비스 개선이나 피봇팅을 이어가기 어렵겠다고 판단했습니다. 그렇게 서비스를 종료했는데... 아직도 참 아쉽습니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3. 2025년 하반기 : 첫 회사&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2025년 7월부터 2026년 3월까지, 첫 회사를 다녔습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 시기에 대한 회고는 따로 쓰지 않으려고 합니다. 잊고 싶은 기억들이 있고, 지금의 저에게는 굳이 다시 꺼낼 필요가 없다고 판단했습니다. 언젠가 충분히 시간이 지나면, 그때 담담하게 쓸 수 있을지도 모르겠네요.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;4. 2026년 상반기 : 끊어냄과 도전&lt;/h2&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-filename=&quot;20260217_115414.jpg&quot; data-origin-width=&quot;4000&quot; data-origin-height=&quot;1848&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/da1VDL/dJMcabKO8pD/VWYCQBSazq5xO8jDn8kYO0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/da1VDL/dJMcabKO8pD/VWYCQBSazq5xO8jDn8kYO0/img.jpg&quot; data-alt=&quot;이 때 즈음 설날을 맞아 가족들끼리 남한산성을 갔습니다. 퇴사를 눈앞에 두고 있던 상황이라서 탁 트인 풍경과 다르게 마음은 먹먹했던 기억이 있습니다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/da1VDL/dJMcabKO8pD/VWYCQBSazq5xO8jDn8kYO0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fda1VDL%2FdJMcabKO8pD%2FVWYCQBSazq5xO8jDn8kYO0%2Fimg.jpg&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;589&quot; height=&quot;272&quot; data-filename=&quot;20260217_115414.jpg&quot; data-origin-width=&quot;4000&quot; data-origin-height=&quot;1848&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;막상 퇴사해보니 생각보다 별거 없었습니다. 그동안 회사를 다니며 돈을 아껴둔 덕분에, 금전적으로는 1-2년을 버틸 수 있는 상태였거든요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;s&gt;물론 2년은 이론상 그렇다는 거고, 현실 목표는 6개월 안에 재취업이었지만.&lt;/s&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;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;마무리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 해서 저의 긴 취준 생활이 끝났습니다. 지나고 나니 추억이 되고 미화가 된다고 하는데, 저는 아직 그러지는 못한 것 같네요. 그때 느꼈던 감정이 지금도 잘 생각나고, 가끔씩 그때의 일들이 떠올라 저를 힘들게 할 때도 있습니다. 그렇지만 동시에 취준 기간 동안 나를 응원해주고 격려해줬던 사람들과 행복했던 기억들도 다 생생하게 떠오릅니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;재밌는 건 취준 기간 동안 저를 힘들게 했던 사람들은 지금은 제 주변에 없는데, 감사함을 느꼈던 사람들은 여전히 제 주변에 있습니다. 그래도 꽤 잘 산 것 같아서 기분이 좋네요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;감사함. 결국 이 긴 여행의 끝에 남는 것은 감사함인 것 같습니다. 좋은 사람이나 상황에 대한 감사도 있고, 부정적인 감정에 극한까지 몰렸을 때도 결국은 완전히 무너지지 않았던 것도 감사하게 느껴집니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;20241214_180609.jpg&quot; data-origin-width=&quot;4000&quot; data-origin-height=&quot;3000&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b8oInu/dJMcag6oDAq/2rTxNRk5P3BtpWctSywVzK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b8oInu/dJMcag6oDAq/2rTxNRk5P3BtpWctSywVzK/img.jpg&quot; data-alt=&quot;갑자기 페퍼톤스 콘서트에서 들었던 'thank you'가 생각나서 사진을 넣어봤습니다. 모두 정말 감사합니다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b8oInu/dJMcag6oDAq/2rTxNRk5P3BtpWctSywVzK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb8oInu%2FdJMcag6oDAq%2F2rTxNRk5P3BtpWctSywVzK%2Fimg.jpg&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;641&quot; height=&quot;481&quot; data-filename=&quot;20241214_180609.jpg&quot; data-origin-width=&quot;4000&quot; data-origin-height=&quot;3000&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;갑자기 페퍼톤스 콘서트에서 들었던 'thank you'가 생각나서 사진을 넣어봤습니다. 모두 정말 감사합니다.&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;</description>
      <category>회고</category>
      <category>SSAFY</category>
      <category>개발자</category>
      <category>대상</category>
      <category>신한해커톤</category>
      <category>워키</category>
      <category>이직</category>
      <category>취업</category>
      <category>취업준비</category>
      <category>취준</category>
      <category>회고</category>
      <author>swimee</author>
      <guid isPermaLink="true">https://sootudio-programming.tistory.com/23</guid>
      <comments>https://sootudio-programming.tistory.com/entry/2024%EB%85%84-%ED%95%98%EB%B0%98%EA%B8%B0%EB%B6%80%ED%84%B0-2026%EB%85%84-%EC%B4%88%EA%B9%8C%EC%A7%80-%EA%B8%B8%EC%97%88%EB%8D%98-%EC%B7%A8%EC%A4%80-%EC%83%9D%ED%99%9C%EC%9D%84-%EB%A7%88%EB%AC%B4%EB%A6%AC%ED%95%98%EB%A9%B0#entry23comment</comments>
      <pubDate>Fri, 17 Apr 2026 21:58:38 +0900</pubDate>
    </item>
    <item>
      <title>  SSL 인증서 만료와 재발급 하기 (feat. Let's Encrypt + Certbot)</title>
      <link>https://sootudio-programming.tistory.com/entry/%F0%9F%94%92-SSL-%EC%9D%B8%EC%A6%9D%EC%84%9C-%EB%A7%8C%EB%A3%8C%EC%99%80-%EC%9E%AC%EB%B0%9C%EA%B8%89-%ED%95%98%EA%B8%B0-feat-Lets-Encrypt-Certbot</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;✅ 개요&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;HTTPS를 통한 안전한 통신을 위해 &lt;b&gt;SSL 인증서&lt;/b&gt;는 필수이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;당신이 서비스를 배포해서 HTTPS를 적용하여 쓰고 있는데, 어느 날 브라우저가 &lt;b&gt;&quot;이 사이트는 안전하지 않음&quot;&lt;/b&gt; 이라고 경고할 때, 대부분의 원인은 SSL 인증서 만료이다.&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&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;321&quot; data-origin-height=&quot;157&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bxWcDv/btsOtHQRZsN/tRRNXfsSHKISUtmEP5kxy0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bxWcDv/btsOtHQRZsN/tRRNXfsSHKISUtmEP5kxy0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bxWcDv/btsOtHQRZsN/tRRNXfsSHKISUtmEP5kxy0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbxWcDv%2FbtsOtHQRZsN%2FtRRNXfsSHKISUtmEP5kxy0%2Fimg.jpg&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;390&quot; height=&quot;191&quot; data-origin-width=&quot;321&quot; data-origin-height=&quot;157&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;그래서 해당 문제를 해결하기 위해 인증서를 재발급 받은 김에, SSL에 대한 설명과, 재발급 과정을 정리해보고자 한다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  SSL 인증서란?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SSL(Secure Sockets Layer)은 클라이언트(브라우저)와 서버 간 통신을 &lt;b&gt;암호화&lt;/b&gt;하여, 도청과 변조를 방지하는 보안 기술이다.&lt;br /&gt;현재는 TLS(Transport Layer Security)가 주로 사용되며, 'SSL 인증서'라는 용어가 관례적으로 유지되고 있다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;인증서의 역할&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;사용자의 &lt;b&gt;브라우저와 서버 간 통신을 암호화&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;사이트의 &lt;b&gt;신뢰성과 소유자 인증&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  SSL 인증 방식&lt;/h2&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;방식&lt;/th&gt;
&lt;th&gt;설명&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;DV (Domain Validation)&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;가장 일반적인 방식. 도메인 소유 여부만 확인&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;OV (Organization Validation)&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;기업 정보까지 인증&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;EV (Extended Validation)&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;법적 인증이 포함된 최고 수준 (초록 주소창 표시 등)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rarr; 이 중 해당 글에서 사용한 Let's Encrypt는 &lt;b&gt;DV 방식&lt;/b&gt;의 무료 인증서를 제공한다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;❗ 문제 상황: 인증서 만료&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오늘, 사이드 프로젝트의 개발자 톡방에 카톡 하나가 올라왔다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;897&quot; data-origin-height=&quot;258&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/yd2Ah/btsOrWhUlj5/W9UUdraDGXLPA7Jp9uiTmk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/yd2Ah/btsOrWhUlj5/W9UUdraDGXLPA7Jp9uiTmk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/yd2Ah/btsOrWhUlj5/W9UUdraDGXLPA7Jp9uiTmk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fyd2Ah%2FbtsOrWhUlj5%2FW9UUdraDGXLPA7Jp9uiTmk%2Fimg.jpg&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;466&quot; height=&quot;134&quot; data-origin-width=&quot;897&quot; data-origin-height=&quot;258&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그동안 운영 중 서버가 수 차례 연결이 끊기는 일이 있어서, 모니터링 시스템을 만들어 놓았기에 '드디어 로그가 찍혔겠구나!!' 라고 생각했다.&lt;/p&gt;
&lt;p 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&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;917&quot; data-origin-height=&quot;762&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mukPg/btsOrs2vlrA/hGU9QCcTbb7nXpvkb66kAk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mukPg/btsOrs2vlrA/hGU9QCcTbb7nXpvkb66kAk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mukPg/btsOrs2vlrA/hGU9QCcTbb7nXpvkb66kAk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmukPg%2FbtsOrs2vlrA%2FhGU9QCcTbb7nXpvkb66kAk%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;414&quot; height=&quot;344&quot; data-origin-width=&quot;917&quot; data-origin-height=&quot;762&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  원인 분석&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인증서 기간 만료를 체크하는 가장 쉬운 방법은, 문제가 생긴 사이트에서 적접 확인하는 것이다.&lt;br /&gt;주소창 부분에서 인증서의 상세 정보를 확인할 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;480&quot; data-origin-height=&quot;410&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/baA9RJ/btsOqT625Ev/kcJ0WAykHLz6qVqd6zijaK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/baA9RJ/btsOqT625Ev/kcJ0WAykHLz6qVqd6zijaK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/baA9RJ/btsOqT625Ev/kcJ0WAykHLz6qVqd6zijaK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbaA9RJ%2FbtsOqT625Ev%2FkcJ0WAykHLz6qVqd6zijaK%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;480&quot; height=&quot;410&quot; data-origin-width=&quot;480&quot; data-origin-height=&quot;410&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;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;echo | openssl s_client -servername my-domain.com -connect my-domain.com:443 2&amp;gt;/dev/null | openssl x509 -noout -dates&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;notBefore=Mar 5 00:00:00 2024 GMT
notAfter=Jun 5 23:59:59 2025 GMT &amp;larr; 인증서 유효 기간&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  해결 방법: Certbot으로 인증서 재발급&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;✅ Certbot이란?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://certbot.eff.org/&quot;&gt;Certbot&lt;/a&gt;은 Let's Encrypt에서 인증서를 쉽게 발급하고 관리할 수 있도록 도와주는 자동화 도구이다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;1. Certbot 설치 (Ubuntu 기준)&lt;/h4&gt;
&lt;pre class=&quot;properties&quot;&gt;&lt;code&gt;sudo apt update
sudo apt install certbot python3-certbot-nginx&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2. 인증서 재발급&lt;/h4&gt;
&lt;pre class=&quot;ada&quot;&gt;&lt;code&gt;sudo certbot --nginx -d my-domain.com&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 명령어를 입력할 때, 따로 경로 같은 곳을 지정할 필요가 없다. 자동으로 지정해서 넣어준다. (사실 내가 몰라서 찾아봤다)&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;3. 실행 결과 (일부)&lt;/h4&gt;
&lt;pre class=&quot;applescript&quot;&gt;&lt;code&gt;Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/my-domain.com/fullchain.pem
Key is saved at:         /etc/letsencrypt/live/my-domain.com/privkey.pem
This certificate expires on 2025-09-05.
Successfully deployed certificate for my-domain.com&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  인증서 적용 확인&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;적용이 됐는지 확인해보는 가장 쉬운 방법 역시 직접 들어가 보는 것이다.&lt;br /&gt;적용이 잘 됐다면, 이전과는 달리 보안 경고가 뜨지 않을 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서버 터미널에서 확인하는 방법은 다음과 같다.&lt;/p&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;echo | openssl s_client -servername my-domain.com -connect my-domain.com:443 2&amp;gt;/dev/null | openssl x509 -noout -dates&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rarr; &lt;code&gt;notAfter&lt;/code&gt;가 3개월 뒤로 갱신되었는지 확인&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  자동 갱신 설정 확인&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 부분은 적을까 말까 고민했었는데, 블로그의 투명한(?) 운영을 위해, 그리고 나 처럼 인증서에 대해 잘 모르는 사람들이 있을 것 같아서 추가적으로 적게 되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실, 위에서 설명한 것 처럼 서버를 운영하면서 매번 인증서를 재발급 해야 할 일은 거의 없다.&lt;br /&gt;그 이유는, Certbot으로 인증서의 자동 갱신을 설정해 둘 수 있기 때문이다.&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 class=&quot;angelscript&quot;&gt;&lt;code&gt;user@server:~$ sudo systemctl list-timers | grep certbot
Sat 2025-06-07 22:51:51 KST  2h 13min left  Sat 2025-06-07 10:43:19 KST  9h ago   certbot.timer           certbot.service
Sun 2025-06-08 00:05:00 KST  3h 26min left  Sat 2025-06-07 12:08:12 KST  8h ago   snap.certbot.renew.timer  snap.certbot.renew.service&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;/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;정확하게는, 자동 갱신에 대한 설정(타이머)가 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;br /&gt;위처럼 설정해 놓으면, 하루 2번씩 만료일을 체크하고, 30일 이내면 갱신을 한다고 하니, 이제 인증서 만료 문제는 따로 신경쓰지 않아도 될 것 같다.&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 class=&quot;dsconfig&quot;&gt;&lt;code&gt;sudo systemctl list-timers | grep certbot&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;또는 crontab에서 확인:&lt;/p&gt;
&lt;pre class=&quot;ebnf&quot;&gt;&lt;code&gt;sudo crontab -l&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;✅ 마무리하며&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아무리 실무를 겪지 못한 취준생 개발자라고 하더라도, 그동안 서비스를 운영하며 기본적인 SSL 설정이나 문제가 생길 수 있는 부분을 미리 체크하지 못해서 아쉽다고 느꼈다.&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;개발자를 준비하며 첫 서버 운영에 어려움을 겪는 나같은 사람들이, 이 글을 보고 조금이나마 도움을 받으면 좋겠다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  참고 링크&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://letsencrypt.org/&quot;&gt;Let's Encrypt 공식 사이트&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://certbot.eff.org/instructions&quot;&gt;Certbot 설치 가이드&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[SSL 만료 테스트 사이트: expired.badssl.com](&lt;a href=&quot;https://expired.badssl.com/&quot;&gt;https://expired.badssl.com/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>개발 공부</category>
      <category>HTTP</category>
      <category>https</category>
      <category>Let's Encrypt</category>
      <category>SSL</category>
      <category>배포</category>
      <category>보안</category>
      <category>인증서</category>
      <category>재발급</category>
      <author>swimee</author>
      <guid isPermaLink="true">https://sootudio-programming.tistory.com/22</guid>
      <comments>https://sootudio-programming.tistory.com/entry/%F0%9F%94%92-SSL-%EC%9D%B8%EC%A6%9D%EC%84%9C-%EB%A7%8C%EB%A3%8C%EC%99%80-%EC%9E%AC%EB%B0%9C%EA%B8%89-%ED%95%98%EA%B8%B0-feat-Lets-Encrypt-Certbot#entry22comment</comments>
      <pubDate>Sat, 7 Jun 2025 20:59:23 +0900</pubDate>
    </item>
    <item>
      <title>Spring Boot에서 공통 응답 / 예외 처리 로직 사용하기 (Custom Exception 사용하여 예외 처리하기)</title>
      <link>https://sootudio-programming.tistory.com/entry/Spring-Boot%EC%9D%98-%EC%98%88%EC%99%B8-%EC%B2%98%EB%A6%AC-%EA%B3%B5%ED%86%B5-%EC%98%88%EC%99%B8-%EC%B2%98%EB%A6%AC-%EB%A1%9C%EC%A7%81-Custom-Exception-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;에러 발생 시 전체적인 흐름&lt;/h2&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;1. 에러 발생 (비즈니스 로직 단계)&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;예를 들어, 도메인 로직에서 특정 데이터를 찾지 못한 경우, 조건에 따라 아래와 같이 &lt;code&gt;CustomException&lt;/code&gt;을 발생시킨다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;haxe&quot;&gt;&lt;code&gt;if (user == null) {
    throw new CustomException(ErrorCode.USER_NOT_FOUND);
}&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2. 예외 전파&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;발생한 예외는 컨트롤러로 전파되며, 별도로 처리하지 않으면 스프링의 &lt;code&gt;DispatcherServlet&lt;/code&gt;이 예외를 감지하게 된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;3. 전역 예외 처리&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;스프링은 &lt;code&gt;@RestControllerAdvice&lt;/code&gt;가 선언된 &lt;code&gt;GlobalExceptionHandler&lt;/code&gt;클래스를 찾아 예외를 처리한다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;CustomException&lt;/b&gt;인 경우, &lt;code&gt;handlerCustomException&lt;/code&gt; 메소드가 호출되어,
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;code&gt;ex.getErrorCode().getHttpStatus().value()&lt;/code&gt;로 HTTP 상태 코드를,&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ex.getMessage()&lt;/code&gt;로 에러 메시지를 담은 &lt;code&gt;ExceptionResponse&lt;/code&gt; 객체를 생성한 후,&lt;/li&gt;
&lt;li&gt;해당 상태 코드와 함께 &lt;code&gt;ResponseEntity&lt;/code&gt;로 반환한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;만약 &lt;code&gt;CustomException&lt;/code&gt;이 아닌 일반 &lt;code&gt;Exception&lt;/code&gt;이 발생하면, &lt;code&gt;handleGeneralException&lt;/code&gt; 메소드가 호출되어, HTTP 500(Internal Server Error) 상태와 함께 에러 메시지가 포함된 응답을 반환한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;4. 클라이언트 응답&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;최종적으로 클라이언트는 JSON 형태로 아래와 같은 응답을 받게 된다.
&lt;pre class=&quot;json&quot;&gt;&lt;code&gt;{
  &quot;status&quot;: 404,
  &quot;message&quot;: 존재하지 않는 유저입니다.
}&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>개발 공부/Spring</category>
      <category>customexception</category>
      <category>exception</category>
      <category>ExceptionHandler</category>
      <category>Srping</category>
      <category>예외처리</category>
      <author>swimee</author>
      <guid isPermaLink="true">https://sootudio-programming.tistory.com/21</guid>
      <comments>https://sootudio-programming.tistory.com/entry/Spring-Boot%EC%9D%98-%EC%98%88%EC%99%B8-%EC%B2%98%EB%A6%AC-%EA%B3%B5%ED%86%B5-%EC%98%88%EC%99%B8-%EC%B2%98%EB%A6%AC-%EB%A1%9C%EC%A7%81-Custom-Exception-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0#entry21comment</comments>
      <pubDate>Mon, 24 Feb 2025 11:02:49 +0900</pubDate>
    </item>
    <item>
      <title>[헤드퍼스트 디자인패턴] 14장. 다양한 패턴 빠르게 알아보기 - 기타 패턴</title>
      <link>https://sootudio-programming.tistory.com/entry/%ED%97%A4%EB%93%9C%ED%8D%BC%EC%8A%A4%ED%8A%B8-%EB%94%94%EC%9E%90%EC%9D%B8%ED%8C%A8%ED%84%B4-14%EC%9E%A5-%EB%8B%A4%EC%96%91%ED%95%9C-%ED%8C%A8%ED%84%B4-%EB%B9%A0%EB%A5%B4%EA%B2%8C-%EC%95%8C%EC%95%84%EB%B3%B4%EA%B8%B0-%EA%B8%B0%ED%83%80-%ED%8C%A8%ED%84%B4</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;디자인패턴_블로그로고.png&quot; data-origin-width=&quot;8140&quot; data-origin-height=&quot;3380&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cF5VWg/btsMpCFPCZQ/ChtgDgRuKjODf12eEMJuJ1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cF5VWg/btsMpCFPCZQ/ChtgDgRuKjODf12eEMJuJ1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cF5VWg/btsMpCFPCZQ/ChtgDgRuKjODf12eEMJuJ1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcF5VWg%2FbtsMpCFPCZQ%2FChtgDgRuKjODf12eEMJuJ1%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;8140&quot; height=&quot;3380&quot; data-filename=&quot;디자인패턴_블로그로고.png&quot; data-origin-width=&quot;8140&quot; data-origin-height=&quot;3380&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;해당 게시물은 '헤드퍼스트 디자인패턴'을 읽고 내용을 정리한 글입니다.&lt;br /&gt;헤퍼디 스터디 링크: https://github.com/SSAFY11th-book-study/book-study&lt;/blockquote&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;브리지 패턴&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;706&quot; data-origin-height=&quot;362&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bkrdPM/btsMquttntV/kKyEKvLoKEQGmgMqf2vKL0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bkrdPM/btsMquttntV/kKyEKvLoKEQGmgMqf2vKL0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bkrdPM/btsMquttntV/kKyEKvLoKEQGmgMqf2vKL0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbkrdPM%2FbtsMquttntV%2FkKyEKvLoKEQGmgMqf2vKL0%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;600&quot; height=&quot;308&quot; data-origin-width=&quot;706&quot; data-origin-height=&quot;362&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;브리지 패턴은 구현과 더불어 추상화 부분까지 변경할 때 사용한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;브리지 패턴을 사용하면 추상화된 부분과 구현 부분을 서로 다른 클래스 계층구조로 분리해서 그 둘을 모두 변경할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 그림에서는 리모컨을 나타내는 부분과, 종류별로 다른 TV를 나타내는 부분으로 2개의 계층 구조를 만들었다.&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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;빌더 패턴&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;953&quot; data-origin-height=&quot;524&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Ub2rw/btsMrEokf04/tPbGWAfxeMQz6x2B5aTKLK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Ub2rw/btsMrEokf04/tPbGWAfxeMQz6x2B5aTKLK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Ub2rw/btsMrEokf04/tPbGWAfxeMQz6x2B5aTKLK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FUb2rw%2FbtsMrEokf04%2FtPbGWAfxeMQz6x2B5aTKLK%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;600&quot; height=&quot;330&quot; data-origin-width=&quot;953&quot; data-origin-height=&quot;524&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;빌더 패턴은 제품을 여러 단계로 나눠서 만들도록 제품 생산 단계를 캡슐화할때 사용한다.&lt;/p&gt;
&lt;p 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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;책임 연쇄 패턴&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;941&quot; data-origin-height=&quot;340&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/co18eV/btsMq7RZYfT/kth7U1J6exrUadB13ux6a0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/co18eV/btsMq7RZYfT/kth7U1J6exrUadB13ux6a0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/co18eV/btsMq7RZYfT/kth7U1J6exrUadB13ux6a0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fco18eV%2FbtsMq7RZYfT%2Fkth7U1J6exrUadB13ux6a0%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;600&quot; height=&quot;217&quot; data-origin-width=&quot;941&quot; data-origin-height=&quot;340&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;책임 연쇄 패턴은 1개의 요청을 2개 이상의 객체에서 처리할 때 사용한다.&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;973&quot; data-origin-height=&quot;236&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bSi3VV/btsMqiUdLiP/z8GbNbkiPH9BA3gzjZ0zJK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bSi3VV/btsMqiUdLiP/z8GbNbkiPH9BA3gzjZ0zJK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bSi3VV/btsMqiUdLiP/z8GbNbkiPH9BA3gzjZ0zJK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbSi3VV%2FbtsMqiUdLiP%2Fz8GbNbkiPH9BA3gzjZ0zJK%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;600&quot; height=&quot;146&quot; data-origin-width=&quot;973&quot; data-origin-height=&quot;236&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;때문에, 다음과 같이 메일을 분류하는 검출기를 만들 때 사용할 수 있다.&lt;/p&gt;
&lt;p 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;h2 data-ke-size=&quot;size26&quot;&gt;플라이웨이트 패턴&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;864&quot; data-origin-height=&quot;349&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bo3Lpr/btsMp94c3pL/Mu6MkyckHfQmlUs2Dy5vGK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bo3Lpr/btsMp94c3pL/Mu6MkyckHfQmlUs2Dy5vGK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bo3Lpr/btsMp94c3pL/Mu6MkyckHfQmlUs2Dy5vGK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbo3Lpr%2FbtsMp94c3pL%2FMu6MkyckHfQmlUs2Dy5vGK%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;600&quot; height=&quot;242&quot; data-origin-width=&quot;864&quot; data-origin-height=&quot;349&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;플라이웨이트 패턴은 어떤 클래스의 인스턴스 하나로 여러 개의 '가상 인스턴스'를 제공할 때 사용한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;조경을 설계하는 애플리케이션에서 여러 조건들을 가진 나무를 여러 개 추가하고자 할 때, 플라이웨이트 패턴을 사용한다면 Tree 객체를 수 천 개 만드는 대신, 시스템을 조금 고쳐서 Tree의 인스턴스는 하나만 만들고, 모든 나무의 상태를 클라이언트 객체가 관리하도록 만들 수 있다.&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;h2 data-ke-size=&quot;size26&quot;&gt;인터프리터 패턴&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;914&quot; data-origin-height=&quot;455&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Znt6b/btsMpAVpbdp/RFB9cbKtGyKcaK3UB5sTKK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Znt6b/btsMpAVpbdp/RFB9cbKtGyKcaK3UB5sTKK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Znt6b/btsMpAVpbdp/RFB9cbKtGyKcaK3UB5sTKK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FZnt6b%2FbtsMpAVpbdp%2FRFB9cbKtGyKcaK3UB5sTKK%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;600&quot; height=&quot;299&quot; data-origin-width=&quot;914&quot; data-origin-height=&quot;455&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인터프리터 패턴은 어떤 언어의 인터프리터를 만들 때 사용한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, 패턴을 만들려면 언어의 문법에 대한 어느 정도의 이해가 있어야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선, 문법과 구문을 번역하는 인터프리터 클래스를 기반으로 간단한 언어를 정의한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 다음으로는 언어의 규칙을 나타내는 클래스를 사용해서 언어를 표현한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이때, 만들어진 언어를 해석하려면 각 표현식에 대응하는 interpret() 메소드를 호출하면 된다. 해당 메소드에 컨텍스트도 전달되며, 입력된 내용을 확인하고 평가하는 작업도 이 메소드가 처리한다.&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;h2 data-ke-size=&quot;size26&quot;&gt;중재자 패턴&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;652&quot; data-origin-height=&quot;482&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cYUM2D/btsMpiglkoa/M7Ek0Z3v4VjjkBmtzCqrIk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cYUM2D/btsMpiglkoa/M7Ek0Z3v4VjjkBmtzCqrIk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cYUM2D/btsMpiglkoa/M7Ek0Z3v4VjjkBmtzCqrIk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcYUM2D%2FbtsMpiglkoa%2FM7Ek0Z3v4VjjkBmtzCqrIk%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;600&quot; height=&quot;444&quot; data-origin-width=&quot;652&quot; data-origin-height=&quot;482&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;중재자 패턴은 서로 관련된 객체 사이의 복잡한 통신과 제어를 한곳으로 집중하고 싶을 때 사용한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시스템에 중재자 패턴을 적용하면, 이전에 모든 객체가 다른 객체와 서로 알고 있어야 했던 것을 단순화할수 있다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;메멘토 패턴&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;908&quot; data-origin-height=&quot;532&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bfqHjl/btsMrtAt057/NxKKBm6GaRmo9ASioZ8Nc1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bfqHjl/btsMrtAt057/NxKKBm6GaRmo9ASioZ8Nc1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bfqHjl/btsMrtAt057/NxKKBm6GaRmo9ASioZ8Nc1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbfqHjl%2FbtsMrtAt057%2FNxKKBm6GaRmo9ASioZ8Nc1%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;600&quot; height=&quot;352&quot; data-origin-width=&quot;908&quot; data-origin-height=&quot;532&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메멘토 패턴은 객체를 이전의 상태로 복구할 때 사용한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메멘토 패턴에는 2가지 목적이 있다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;시스템에서 핵심적인 기능을 담당하는 객체의 상태 저장&lt;/li&gt;
&lt;li&gt;핵심적인 객체의 캡슐화 유지&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;프로토타입 패턴&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;899&quot; data-origin-height=&quot;631&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lrRJ4/btsMrEPpf5C/LCh3k0KDo6sim0u6EVhMrK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lrRJ4/btsMrEPpf5C/LCh3k0KDo6sim0u6EVhMrK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lrRJ4/btsMrEPpf5C/LCh3k0KDo6sim0u6EVhMrK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlrRJ4%2FbtsMrEPpf5C%2FLCh3k0KDo6sim0u6EVhMrK%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;600&quot; height=&quot;421&quot; data-origin-width=&quot;899&quot; data-origin-height=&quot;631&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로토타입 패턴은 어떤 클래스의 인스턴스를 만들 때 자원과 시간을 줄이기 위해 사용한다.&lt;/p&gt;
&lt;p 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;</description>
      <category>스터디/객체지향</category>
      <category>디자인패턴</category>
      <category>스터디</category>
      <category>해드퍼스트</category>
      <category>해퍼디</category>
      <author>swimee</author>
      <guid isPermaLink="true">https://sootudio-programming.tistory.com/20</guid>
      <comments>https://sootudio-programming.tistory.com/entry/%ED%97%A4%EB%93%9C%ED%8D%BC%EC%8A%A4%ED%8A%B8-%EB%94%94%EC%9E%90%EC%9D%B8%ED%8C%A8%ED%84%B4-14%EC%9E%A5-%EB%8B%A4%EC%96%91%ED%95%9C-%ED%8C%A8%ED%84%B4-%EB%B9%A0%EB%A5%B4%EA%B2%8C-%EC%95%8C%EC%95%84%EB%B3%B4%EA%B8%B0-%EA%B8%B0%ED%83%80-%ED%8C%A8%ED%84%B4#entry20comment</comments>
      <pubDate>Mon, 24 Feb 2025 10:43:10 +0900</pubDate>
    </item>
    <item>
      <title>[헤드퍼스트 디자인패턴] 13장. 패턴과 행복하게 살아가기 - 실전 디자인 패턴</title>
      <link>https://sootudio-programming.tistory.com/entry/%ED%97%A4%EB%93%9C%ED%8D%BC%EC%8A%A4%ED%8A%B8-%EB%94%94%EC%9E%90%EC%9D%B8%ED%8C%A8%ED%84%B4-13%EC%9E%A5-%ED%8C%A8%ED%84%B4%EA%B3%BC-%ED%96%89%EB%B3%B5%ED%95%98%EA%B2%8C-%EC%82%B4%EC%95%84%EA%B0%80%EA%B8%B0-%EC%8B%A4%EC%A0%84-%EB%94%94%EC%9E%90%EC%9D%B8-%ED%8C%A8%ED%84%B4</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;디자인패턴_블로그로고.png&quot; data-origin-width=&quot;8140&quot; data-origin-height=&quot;3380&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/HrvQv/btsMhwFiWpj/9gKiHBAPSVHvyDPvD3T2fk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/HrvQv/btsMhwFiWpj/9gKiHBAPSVHvyDPvD3T2fk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/HrvQv/btsMhwFiWpj/9gKiHBAPSVHvyDPvD3T2fk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FHrvQv%2FbtsMhwFiWpj%2F9gKiHBAPSVHvyDPvD3T2fk%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;8140&quot; height=&quot;3380&quot; data-filename=&quot;디자인패턴_블로그로고.png&quot; data-origin-width=&quot;8140&quot; data-origin-height=&quot;3380&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;해당 게시물은 '헤드퍼스트 디자인패턴'을 읽고 내용을 정리한 글입니다.&lt;br /&gt;헤퍼디 스터디 링크: https://github.com/SSAFY11th-book-study/book-study&lt;/blockquote&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;디자인 패턴의 정의&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;디자인 패턴의 정의는 다음과 같다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;패턴(Pattern)은 특정 컨텍스트 내에서 주어진 문제의 해결책이다.&lt;/blockquote&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;컨텍스트(context)는 패턴이 적용되는 상황을 의미한다. 해당 상황은 반복적으로 일어날 수 있는 상황이어야 한다. &lt;i&gt;(예: 객체들의 컬렉션이 주어져 있다.)&lt;/i&gt;&lt;/li&gt;
&lt;li&gt;문제(problem)은 컨텍스트 내에서 이뤄야 하는 목표를 뜻한다. 여기에는 컨텍스트 내의 제약조건도 포함된다. &lt;i&gt;(예: 컬렉션의 구현을 드러내지 않으면서, 그 안에 있는 각 객체를 대상으로 순환 작업을 할 수 있어야 한다.)&lt;/i&gt;&lt;/li&gt;
&lt;li&gt;해결책(solution)은 제약조건 속에서 누가 적용해도 목표를 이룰 수 있는 일반적인 디자인을 뜻한다.&lt;i&gt; (예: 반복 작업을 별도의 클래스로 캡슐화한다.)&lt;/i&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 단어 풀이를 가지고 디자인 패턴을 다시 정의해보면, 아래와 같이 풀어 쓸 수 있다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;어떤 컨텍스트 내에서 일련의 제약조건에 의해 영향을 받는 문제가 발생했다면, 그 제약조건 내에서 목적 달성을 위한 해결책이 되는 디자인을 적용하면 된다.&lt;/blockquote&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;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;패턴은 반복적으로 등장하는 문제에 적용할 수 있어야 한다. (가령, 반복적으로 차 키를 놓고 내리는 것을 해결하기 위해 차 유리창을 깨는 방법이 패턴이 될 수는 없다.)&lt;/li&gt;
&lt;li&gt;패턴은 다른 사람이 사용해도 그 사람이 처한 문제의 해결책으로 적용하게 하기가 힘들다.&lt;/li&gt;
&lt;li&gt;패턴에는 이름이 있어야 한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 패턴들을 정리해놓은&amp;nbsp;&lt;b&gt;패턴 카탈로그&lt;/b&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;/li&gt;
&lt;li&gt;패턴이 만들어진 배경&lt;/li&gt;
&lt;li&gt;적용할 수 있는 범위&lt;/li&gt;
&lt;li&gt;해결책의 디자인 및 그 해결책을 적용한 결과(장단점)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;와 같이 다양한 내용이 자세히 적혀 있다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;디자인 패턴 분류하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대부분의 카탈로그에서는 몇 가지 범주에 맞춰서 디자인 패턴을 분류하고 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 중 가장 유명한 분류 방법은 맨 처음 출간되었던 패턴 카탈로그에서 제시한 생성, 행동, 구조라는 3가지 범주로, 이것은 패턴을 용도에 따라 나눈 것이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1258&quot; data-origin-height=&quot;637&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dQwEDg/btsMhNNH6kZ/ZAB3fjEL4Dkcxw3E2eNGNK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dQwEDg/btsMhNNH6kZ/ZAB3fjEL4Dkcxw3E2eNGNK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dQwEDg/btsMhNNH6kZ/ZAB3fjEL4Dkcxw3E2eNGNK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdQwEDg%2FbtsMhNNH6kZ%2FZAB3fjEL4Dkcxw3E2eNGNK%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;600&quot; height=&quot;304&quot; data-origin-width=&quot;1258&quot; data-origin-height=&quot;637&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;생성 패턴(Creational Pattern)&lt;/b&gt;은 객체 인스턴스를 생성하는 패턴으로, 클라이언트와 그 클라이언트가 생성해야 하는 객체 인스턴스 사이의 연결을 끊어 주는 패턴이다.&lt;br /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;싱글턴&lt;/li&gt;
&lt;li&gt;추삭 팩토리&lt;/li&gt;
&lt;li&gt;팩토리 메소드&lt;/li&gt;
&lt;li&gt;&lt;i&gt;프로토 타입&lt;/i&gt;&lt;/li&gt;
&lt;li&gt;&lt;i&gt;빌더&lt;/i&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;행동 패턴(Behavioral Pattern)&lt;/b&gt;은 클래스와 객체들이 상호작용하는 방법과 역할을 분담하는 방법을 다루는 패턴이다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;템플릿 메소드&lt;/li&gt;
&lt;li&gt;반복자&lt;/li&gt;
&lt;li&gt;싱글턴&lt;/li&gt;
&lt;li&gt;옵저버&lt;/li&gt;
&lt;li&gt;상태&lt;/li&gt;
&lt;li&gt;전략&lt;/li&gt;
&lt;li&gt;&lt;i&gt;인터프리터&lt;/i&gt;&lt;/li&gt;
&lt;li&gt;&lt;i&gt;역할 변경&lt;/i&gt;&lt;/li&gt;
&lt;li&gt;&lt;i&gt;비지터&lt;/i&gt;&lt;/li&gt;
&lt;li&gt;&lt;i&gt;중재자&lt;/i&gt;&lt;/li&gt;
&lt;li&gt;&lt;i&gt;메멘토&lt;/i&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;구조 패턴(Structural Pattern)&lt;/b&gt;은 클래스와 객체를 더 큰 구조로 만들 수 있게 구상을 사용하는 패턴이다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;프록시&lt;/li&gt;
&lt;li&gt;데코레이터&lt;/li&gt;
&lt;li&gt;컴포지트&lt;/li&gt;
&lt;li&gt;퍼사드&lt;/li&gt;
&lt;li&gt;어댑터&lt;/li&gt;
&lt;li&gt;&lt;i&gt;브리지&lt;/i&gt;&lt;/li&gt;
&lt;li&gt;&lt;i&gt;플라이웨이트&lt;/i&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데코레이터 패턴이 행동을 추가하는 패턴이기 때문에, 구조 패턴이 아닌 행동 패턴이라는 의견이 있지만, GoF의 패턴 책(카탈로그)에서는 데코레이터 패턴을 구조 패턴으로 분류해 놓았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 범주로 나누는 방식 말고도, 다음과 같이 나누는 것도 가능하다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1134&quot; data-origin-height=&quot;535&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/OnW9c/btsMhMVxYUk/qkSAmlPyQKkZ7TkFk1mhyk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/OnW9c/btsMhMVxYUk/qkSAmlPyQKkZ7TkFk1mhyk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/OnW9c/btsMhMVxYUk/qkSAmlPyQKkZ7TkFk1mhyk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FOnW9c%2FbtsMhMVxYUk%2FqkSAmlPyQKkZ7TkFk1mhyk%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;600&quot; height=&quot;283&quot; data-origin-width=&quot;1134&quot; data-origin-height=&quot;535&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;클래스 패턴(Class Pattern)은 클래스 사이의 관계가 상속으로 어떻게 정의되는지를 다룬다. 클래스 사이의 관계는 대부분 컴파일할 때 결정 된다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;템플릿 메소드&lt;/li&gt;
&lt;li&gt;팩토리 메소드&lt;/li&gt;
&lt;li&gt;어댑터&lt;/li&gt;
&lt;li&gt;&lt;i&gt;인터프리터&lt;/i&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;객체 패턴(Object Pattern)은 객체 사이의 관계를 다루며, 객체 사이의 관계는 보통 구성으로 정의된다. 일반적으로 실행 중에 관계가 결정되므로 보다 동적이고 유연하다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;컴포지트&lt;/li&gt;
&lt;li&gt;커맨드&lt;/li&gt;
&lt;li&gt;반복자&lt;/li&gt;
&lt;li&gt;데코레이터&lt;/li&gt;
&lt;li&gt;퍼사드&lt;/li&gt;
&lt;li&gt;프록시&lt;/li&gt;
&lt;li&gt;전략&lt;/li&gt;
&lt;li&gt;옵저버&lt;/li&gt;
&lt;li&gt;상태&lt;/li&gt;
&lt;li&gt;프로토타입&lt;/li&gt;
&lt;li&gt;추상 팩토리&lt;/li&gt;
&lt;li&gt;싱글턴&lt;/li&gt;
&lt;li&gt;&lt;i&gt;비지터&lt;/i&gt;&lt;/li&gt;
&lt;li&gt;&lt;i&gt;메멘토&lt;/i&gt;&lt;/li&gt;
&lt;li&gt;&lt;i&gt;책임 연쇄&lt;/i&gt;&lt;/li&gt;
&lt;li&gt;&lt;i&gt;브리지&lt;/i&gt;&lt;/li&gt;
&lt;li&gt;&lt;i&gt;중재자&lt;/i&gt;&lt;/li&gt;
&lt;li&gt;&lt;i&gt;플라이웨이트&lt;/i&gt;&lt;/li&gt;
&lt;li&gt;&lt;i&gt;빌더&lt;/i&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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;패턴으로 생각하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;패턴으로 생각한다는 것은 어떤 디자인을 봤을 때 패턴 적용 여부를 결정할 수 있는 안목을 가진다는 뜻이다.&lt;/p&gt;
&lt;p 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;/li&gt;
&lt;li&gt;패턴을 사용할 때 그 패턴이 우리가 설계한 디자인에 미칠 영향과 결과를 먼저 생각해 보자&lt;/li&gt;
&lt;li&gt;디자인상의 문제에 적합하다는 확신이 든다면 패턴을 도입해야 한다.&lt;/li&gt;
&lt;li&gt;간단한 해결책으로 문제가 해결되는 데도 시스템의 어떤 부분이 변경될 거라고 예측되는 상황에는 디자인 패턴을 적용해야 한다.&lt;/li&gt;
&lt;li&gt;꼭 필요하지 않은 패턴은 빼야 한다.(패턴보다 간단한 해결책이 얻 나을 것 같다 싶을 때 패턴을 제거하면 된다.)&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;다른 사람과 함께 패턴 사용하기 (with 전문 용어)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>스터디/객체지향</category>
      <author>swimee</author>
      <guid isPermaLink="true">https://sootudio-programming.tistory.com/19</guid>
      <comments>https://sootudio-programming.tistory.com/entry/%ED%97%A4%EB%93%9C%ED%8D%BC%EC%8A%A4%ED%8A%B8-%EB%94%94%EC%9E%90%EC%9D%B8%ED%8C%A8%ED%84%B4-13%EC%9E%A5-%ED%8C%A8%ED%84%B4%EA%B3%BC-%ED%96%89%EB%B3%B5%ED%95%98%EA%B2%8C-%EC%82%B4%EC%95%84%EA%B0%80%EA%B8%B0-%EC%8B%A4%EC%A0%84-%EB%94%94%EC%9E%90%EC%9D%B8-%ED%8C%A8%ED%84%B4#entry19comment</comments>
      <pubDate>Thu, 20 Feb 2025 19:01:15 +0900</pubDate>
    </item>
    <item>
      <title>[헤드퍼스트 디자인패턴] 12장. 패턴을 모아 패턴 만들기 - 복합 패턴</title>
      <link>https://sootudio-programming.tistory.com/entry/%ED%97%A4%EB%93%9C%ED%8D%BC%EC%8A%A4%ED%8A%B8-%EB%94%94%EC%9E%90%EC%9D%B8%ED%8C%A8%ED%84%B4-12%EC%9E%A5-%ED%8C%A8%ED%84%B4%EC%9D%84-%EB%AA%A8%EC%95%84-%ED%8C%A8%ED%84%B4-%EB%A7%8C%EB%93%A4%EA%B8%B0-%EB%B3%B5%ED%95%A9-%ED%8C%A8%ED%84%B4</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;디자인패턴_블로그로고.png&quot; data-origin-width=&quot;8140&quot; data-origin-height=&quot;3380&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/oIvdN/btsMit142H6/Xfk0VfiG9j1NKVtELCT9ik/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/oIvdN/btsMit142H6/Xfk0VfiG9j1NKVtELCT9ik/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/oIvdN/btsMit142H6/Xfk0VfiG9j1NKVtELCT9ik/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FoIvdN%2FbtsMit142H6%2FXfk0VfiG9j1NKVtELCT9ik%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;8140&quot; height=&quot;3380&quot; data-filename=&quot;디자인패턴_블로그로고.png&quot; data-origin-width=&quot;8140&quot; data-origin-height=&quot;3380&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;해당 게시물은 '헤드퍼스트 디자인패턴'을 읽고 내용을 정리한 글입니다.&lt;br /&gt;헤퍼디 스터디 링크: https://github.com/SSAFY11th-book-study/book-study&lt;/blockquote&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;복합 패턴의 정의&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;반복적으로 생길 수 있는 일반적인 문제를 해결하는 용도로 2개 이상의 패턴을 결합해서 사용하는 것.&lt;br /&gt;패턴 몇 개를 결합한다고 해서 무조건 복합 패턴이 되는 것이 아니며, 복합 패턴이라고 불리려면 여러 가지 문제의 일반적인 해결법을 제시해야 합니다.&lt;/blockquote&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;h2 data-ke-size=&quot;size26&quot;&gt;오리 시뮬레이션 게임에서의 복합 패턴&lt;/h2&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;/li&gt;
&lt;li&gt;오리 예시에 거위를 추가한다.&lt;/li&gt;
&lt;li&gt;꽥꽥 소리의 횟수를 측정한다.&lt;/li&gt;
&lt;li&gt;오리를 생산하는 팩토리를 만든다.&lt;/li&gt;
&lt;li&gt;오리를 무리 단위로 관리한다.&lt;/li&gt;
&lt;li&gt;개별 오리의 행동을 관측한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇다면, 각 기능들에는 다음과 같은 패턴들이 쓰이게 된다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;1. 오리 시뮬레이션 게임을 만든다 : 전략 패턴&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Quackable 인터페이스&lt;/p&gt;
&lt;pre id=&quot;code_1738924734788&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public interface Quackable {
	public void quack();
}&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;Duck Class&lt;/p&gt;
&lt;pre id=&quot;code_1738924773468&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class MallarDuck implements Quackable {
	public void quack() {
    	System.out.println(&quot;꽥꽥&quot;);
    }
}

public class RedheadDuck implements Quackable {
	public void quack() {
    	System.out.println(&quot;꽥꽥&quot;);
    }
}

public class DuckCall implements Quackable {
	public void quack() {
    	System.out.println(&quot;꽉꽉&quot;);
    }
}

public class RubberDuck implements Quackable {
	public void quack() {
    	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;h4 data-ke-size=&quot;size20&quot;&gt;2. 거위 추가하기 : 어댑터 패턴&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Goose 클래스&lt;/p&gt;
&lt;pre id=&quot;code_1738924835484&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class Goose {
	public void honk() {
    	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;Goose Adapter&lt;/p&gt;
&lt;pre id=&quot;code_1738924857946&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class GooseAdapter implements Quackable{
	Goose goose;
    
    public GooseAdapter(Goose goose) {
    	this.goose = goose;
    }
    
    public void quack() {
    	goose.honk();
    }
 }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;3. 꽥꽥 소리 횟수 세기: 데코레이터 패턴&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;QuackCounter Class&lt;/p&gt;
&lt;pre id=&quot;code_1738924908657&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class QuackCounter implements Quackable {
	Quackable duck;
    static int numberOfQuacks; 
    
    public QuackCounter (Quackable duck) {
    	this.duck = duck;
    }
    
    public void quack() {
    	duck.quack();
        numberOfQuacks++;
    }
    
    public static int getQuacks() {
    	return numberOfQuacks;
    }
}&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;/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;4. 오리 팩토리 만들기 : 추상 팩토리 패턴&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AbstractDuckFactory&lt;/p&gt;
&lt;pre id=&quot;code_1738924966456&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public abstract class AbstractDuckFactory {
	public abstract Quackable createMallardDuck();
    public abstract Quackable createRedheadDuck();
    public abstract Quackable createDuckCall();
    public abstract Quackable createRubberDuck();
public class DuckFactory extends AbstractDuckFactory {
	public Quackable createMallardDuck() {
    	return new MallardDuck();
    }
	public Quackable createRedheadDuck() {
    	return new RedheadDuck();
    }
	public Quackable createDuckCall() {
    	return new DuckCall();
    }
	public Quackable createRubberDuck() {
    	return new RubberDuck();
    }
}&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;CountingDuckFactory&lt;/p&gt;
&lt;pre id=&quot;code_1738925002675&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class CountingDuckFactory extends AbstractDuckFactory {
	public Quackable createMallardDuck() {
    	return new QuackCounter(new MallardDuck());
	public Quackable createRedheadDuck() {
    	return new QuackCounter(new RedheadDuck());
	public Quackable createDuckCall() {
    	return new QuackCounter(new DuckCall());
	public Quackable createRubberDuck() {
    	return new QuackCounter(new RubberDuck());
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;5. 오리를 일괄적으로 관리하기 : 컴포지트 패턴, 반복자 패턴&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Flock 클래스(소리를 낼 수 있는 오리 무리)&lt;/p&gt;
&lt;pre id=&quot;code_1738925060228&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class Flock implements Quackable {
	List&amp;lt;Quackable&amp;gt; quackers = new ArrayList&amp;lt;Quackable&amp;gt;();
    
    public void add(Quackable quacker) {
    	quackers.add(quacker);
    }
    
    public void quack() {
    	Interaotr&amp;lt;Quackable&amp;gt; iterator = quackers.iterator();
        while (iterator.hasNext()) {
        	Quackable quacker = iterator.next();
            quacker.quack();
        }
    }
}&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;이후 시뮬레이터에서 Flock 객체에 있는 오리들만 관리해 줄 수가 있음.&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;6. 개별 오리의 행동 관측하기 : 옵저버 패턴&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;관찰 대상 인터페이스 만들기&lt;/p&gt;
&lt;pre id=&quot;code_1738925199162&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public interface QuackObservable {
	public void registerObserver(Observer observer);
    public void notifyObservers();
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1738925270667&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public interface Quackable extends QuackObservable {
	public void quack();
}&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;등록과 연락을 위한 Observable 클래스&lt;/p&gt;
&lt;pre id=&quot;code_1738925309163&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class Obseravable implements QuackObservable {
	List&amp;lt;Observer&amp;gt; observers = new ArrayList&amp;lt;Observer&amp;gt;();
    QuackObservable duck;
    
    public Observable(quackObservable duck) {
    	this.duck = duck;
    }
    
    public void registerObserver(Observer observer) {
    	observers.add(observer);
    }
    
    public void notifyObservers() {
    	Iterator iterator = observers.iterator();
        while (iterator.hasNext()) {
        	Observer observer = iterator.next();
            observer.update(duck);
        }
    }
}&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;/p&gt;
&lt;pre id=&quot;code_1738925357271&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class MallardDuck implements Quackable {
    Observable observable;

    public MallardDuck() {
        observable = new Observable(this);
    }

    public void quack() {
        System.out.println(&quot;꽥꽥&quot;);
        notifyObservers();
    }

    public void registerObserver(Observer observer) {
        observable.registerObserver(observer);
    }

    public void notifyObservers() {
        observable.notifyObservers();
    }
}&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;Observer 인터페이스&lt;/p&gt;
&lt;pre id=&quot;code_1738925385087&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public interface Observer {
	public void update(QuackObservable duck);
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1738925420921&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class Quacklogist implements Observer {
	public void update(QuackObservable duck) {
    	System.out.println(&quot;오리 : &quot; + duck + &quot; 가 소리를 냄&quot;);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;MVC에서의 복합 패턴&lt;/h2&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;옵저버 패턴 (모델 - 컨트롤러)&lt;/h4&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;627&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mEFih/btsMbXCr1Ud/fETon7oR69n7OMpUz4p6kk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mEFih/btsMbXCr1Ud/fETon7oR69n7OMpUz4p6kk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mEFih/btsMbXCr1Ud/fETon7oR69n7OMpUz4p6kk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmEFih%2FbtsMbXCr1Ud%2FfETon7oR69n7OMpUz4p6kk%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;600&quot; height=&quot;294&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;627&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;MVC 패턴에서는 모델의 상태가 변경되었을 때 해당 모델과 연관된 객체들에게 연락이 전달된다. 또한 모델을 뷰와 컨트롤러로부터 완전히 독립시킬 수 있고, 한 모델에서 서로 다른 뷰를 사용할 수 있다.&amp;nbsp;&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;컴포지트 패턴 (뷰)&lt;/h4&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;408&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/5ckef/btsMbzhxeIr/JWmdeS7erkslLtcqykTA0k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/5ckef/btsMbzhxeIr/JWmdeS7erkslLtcqykTA0k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/5ckef/btsMbzhxeIr/JWmdeS7erkslLtcqykTA0k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F5ckef%2FbtsMbzhxeIr%2FJWmdeS7erkslLtcqykTA0k%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;600&quot; height=&quot;191&quot; data-origin-width=&quot;1280&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;뷰는 최상위 구성요소에 다른 구성요소들이 들어있는 형태이다. 다만, 최근에는 GUI 패키지들이 복잡해져서, 내부 구조를 한 눈에 알아보기 힘들다 보니, 컴포지트 패턴이 쓰인다는 사실을 알기 어렵다.&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;전략 패턴 ( 뷰 - 컨트롤러)&lt;/h4&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;512&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/v66Cp/btsMcclMc2J/7jkPWGwqjkWKwXfc3OCyJ1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/v66Cp/btsMcclMc2J/7jkPWGwqjkWKwXfc3OCyJ1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/v66Cp/btsMcclMc2J/7jkPWGwqjkWKwXfc3OCyJ1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fv66Cp%2FbtsMcclMc2J%2F7jkPWGwqjkWKwXfc3OCyJ1%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;600&quot; height=&quot;240&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;512&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;뷰는 겉으로 보이는 화면을 표시하는 것에만 신경을 쓰고, 인터페이스의 행동을 결정하는 일은 모두 컨트롤러에게 맡긴다. 이는 뷰를 모델로부터 분리하는 것을 도와준다.&lt;/p&gt;</description>
      <category>스터디/객체지향</category>
      <category>MVC</category>
      <category>디자인패턴</category>
      <category>복합패턴</category>
      <category>헤드퍼스트</category>
      <author>swimee</author>
      <guid isPermaLink="true">https://sootudio-programming.tistory.com/18</guid>
      <comments>https://sootudio-programming.tistory.com/entry/%ED%97%A4%EB%93%9C%ED%8D%BC%EC%8A%A4%ED%8A%B8-%EB%94%94%EC%9E%90%EC%9D%B8%ED%8C%A8%ED%84%B4-12%EC%9E%A5-%ED%8C%A8%ED%84%B4%EC%9D%84-%EB%AA%A8%EC%95%84-%ED%8C%A8%ED%84%B4-%EB%A7%8C%EB%93%A4%EA%B8%B0-%EB%B3%B5%ED%95%A9-%ED%8C%A8%ED%84%B4#entry18comment</comments>
      <pubDate>Fri, 7 Feb 2025 19:58:46 +0900</pubDate>
    </item>
    <item>
      <title>[헤드퍼스트 디자인패턴] 11장. 객체 접근 제어하기 - 프록시 패턴</title>
      <link>https://sootudio-programming.tistory.com/entry/%ED%97%A4%EB%93%9C%ED%8D%BC%EC%8A%A4%ED%8A%B8-%EB%94%94%EC%9E%90%EC%9D%B8%ED%8C%A8%ED%84%B4-11%EC%9E%A5-%EA%B0%9D%EC%B2%B4-%EC%A0%91%EA%B7%BC-%EC%A0%9C%EC%96%B4%ED%95%98%EA%B8%B0-%ED%94%84%EB%A1%9D%EC%8B%9C-%ED%8C%A8%ED%84%B4</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;디자인패턴_블로그로고.png&quot; data-origin-width=&quot;8140&quot; data-origin-height=&quot;3380&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/s8Nj9/btsLWwMnQpw/4GzNY9KVwFV3gbdoJYdcFK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/s8Nj9/btsLWwMnQpw/4GzNY9KVwFV3gbdoJYdcFK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/s8Nj9/btsLWwMnQpw/4GzNY9KVwFV3gbdoJYdcFK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fs8Nj9%2FbtsLWwMnQpw%2F4GzNY9KVwFV3gbdoJYdcFK%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;8140&quot; height=&quot;3380&quot; data-filename=&quot;디자인패턴_블로그로고.png&quot; data-origin-width=&quot;8140&quot; data-origin-height=&quot;3380&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;해당 게시물은 '헤드퍼스트 디자인패턴'을 읽고 내용을 정리한 글입니다.&lt;br /&gt;헤퍼디 스터디 링크: https://github.com/SSAFY11th-book-study/book-study&lt;/blockquote&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;원격 프록시의 역할&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원격 프록시는 원격 객체(JVM의 다른 주소 공간에서 돌아가고 있는 겍체)의 로컬 대변자 역할을 한다.&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;609&quot; data-origin-height=&quot;221&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bCprmX/btsL0O7hNFp/PHjfLxi7RM7iQPIkYCrIK0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bCprmX/btsL0O7hNFp/PHjfLxi7RM7iQPIkYCrIK0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bCprmX/btsL0O7hNFp/PHjfLxi7RM7iQPIkYCrIK0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbCprmX%2FbtsL0O7hNFp%2FPHjfLxi7RM7iQPIkYCrIK0%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;600&quot; height=&quot;218&quot; data-origin-width=&quot;609&quot; data-origin-height=&quot;221&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;책에서는 뽑기 기계의 예시를 들었는데, Proxy가 원격 뽑기 기계(객체)의 역할을 대신해 주므로서, 클라이언트 객체에 해당하는 GumballMonitor는 Proxy 객체의 메소드를 호출하면서도, 원격 객체의 메소드 호출을 하는 것처럼 행동한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 때, 네트워크 통신과 같은 저수준 작업은 Proxy 객체에서 처리해 준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;프록시 패턴의 정의&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프록시 패턴의 정의는 다음과 같다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;프록시 패턴(Proxy Pattern)은 특정 객체로의 접근을 제어하는 대리인(특정 객체를 대변하는 객체)을 제공합니다.&lt;/blockquote&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;원격 프록시를 써서 원격 객체로의 접근을 제어할 수 있다.&lt;/li&gt;
&lt;li&gt;가상 프록시(virtual proxy)를 써서 생성하기 힘든 자원으로서의 접근을 제어할 수 있다.&lt;/li&gt;
&lt;li&gt;보호 프록시(protection proxy)를 써서 접근 권한이 필요한 자원으로의 접근을 제어할 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;클래스 다이어그램&lt;/h3&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;847&quot; data-origin-height=&quot;528&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b1a6xU/btsLWswrEKc/PipTLMmmz093uX20EiPo3K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b1a6xU/btsLWswrEKc/PipTLMmmz093uX20EiPo3K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b1a6xU/btsLWswrEKc/PipTLMmmz093uX20EiPo3K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb1a6xU%2FbtsLWswrEKc%2FPipTLMmmz093uX20EiPo3K%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;600&quot; height=&quot;374&quot; data-origin-width=&quot;847&quot; data-origin-height=&quot;528&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Subject&lt;/b&gt;는 Proxy와 RealSubject 모두 구현하는 인터페이스이다. 이렇게 하면 어떤 클라이언트에서든 프록시를 주제와 똑같은 식으로 다룰 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Proxy&lt;/b&gt;에는 진짜 작업을 처리하는 객체의 레퍼런스가 들어있다. 진짜 객체가 필요하면 그 레퍼런스를 사용해서 요청을 전달한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;RealSubject&lt;/b&gt;는 진짜 작업을 대부분 처리하는 객체이다. Proxy는 그 객체로의 접근을 제어하는 객체이다.&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;h2 data-ke-size=&quot;size26&quot;&gt;원격 프록시와 가상 프록시 비교하기&lt;/h2&gt;
&lt;h3 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;911&quot; data-origin-height=&quot;392&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ceESgQ/btsLXu8dews/nYS2p72kHCEzpGk2S1WuFK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ceESgQ/btsLXu8dews/nYS2p72kHCEzpGk2S1WuFK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ceESgQ/btsLXu8dews/nYS2p72kHCEzpGk2S1WuFK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FceESgQ%2FbtsLXu8dews%2FnYS2p72kHCEzpGk2S1WuFK%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;600&quot; height=&quot;258&quot; data-origin-width=&quot;911&quot; data-origin-height=&quot;392&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원격 프록시는 다른 JVM에 들어있는 객체의 대리인에 해당하는 로컬 객체이다.&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;h3 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;829&quot; data-origin-height=&quot;385&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bzKFj3/btsLVvtUQ6h/JWv2EDBPhFEUhbmmbNfKQ1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bzKFj3/btsLVvtUQ6h/JWv2EDBPhFEUhbmmbNfKQ1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bzKFj3/btsLVvtUQ6h/JWv2EDBPhFEUhbmmbNfKQ1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbzKFj3%2FbtsLVvtUQ6h%2FJWv2EDBPhFEUhbmmbNfKQ1%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;600&quot; height=&quot;279&quot; data-origin-width=&quot;829&quot; data-origin-height=&quot;385&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가상 프록시는 생성하는 데 많은 비용이 드는 객체를 대신한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;진짜 객체가 필요한 상황이 오기 전까지 객체의 생성을 미루는 기능을 제공한다. 객체 생성 전이나 객체 생성 도중에 객체를 대신하기도 한다. 객체 생성이 끝나면 그냥 RealSubject에 직접 요청을 전달한다.&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;h2 data-ke-size=&quot;size26&quot;&gt;프록시와 자바 RMI&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;661&quot; data-origin-height=&quot;308&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/LroYT/btsL1zIgeNh/mOWlJrvSaRgNlUsM9KPa91/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/LroYT/btsL1zIgeNh/mOWlJrvSaRgNlUsM9KPa91/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/LroYT/btsL1zIgeNh/mOWlJrvSaRgNlUsM9KPa91/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FLroYT%2FbtsL1zIgeNh%2FmOWlJrvSaRgNlUsM9KPa91%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;600&quot; height=&quot;280&quot; data-origin-width=&quot;661&quot; data-origin-height=&quot;308&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자바 RMI(Remote Method Invocation)은 네트워크를 통해 원격 객체를 호출할 수 있게 해주는 기술이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프록시 패턴을 사용할 때 RMI의 역할은 클라이언트 보조 객체(stub)을 만들어 주고, 서비스 보조 객체(skeleton)을 만들어 준다. 이때 stub은 원격 객체의 메소드를 호출하는 역할을 하고, skeleton은 클라이언트 호출을 실제 서버 객체에 전달하는 역할을 한다.&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;h2 data-ke-size=&quot;size26&quot;&gt;보호 프록시 (자바 API를 곁들인)&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;734&quot; data-origin-height=&quot;334&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/6xBON/btsL0o9dcMI/bTPNI6BWwpWgh4yHpPOKgK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/6xBON/btsL0o9dcMI/bTPNI6BWwpWgh4yHpPOKgK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/6xBON/btsL0o9dcMI/bTPNI6BWwpWgh4yHpPOKgK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F6xBON%2FbtsL0o9dcMI%2FbTPNI6BWwpWgh4yHpPOKgK%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;600&quot; height=&quot;273&quot; data-origin-width=&quot;734&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;보호 프록시는 객체에 대한 접근을 제어하거나 제한하기 위해 사용한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자바 API를 사용하여 보호 프록세를 만들 수 있다. (java.lang.reflect 패키지에 프록시 기능 내장)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;java.lang.reflect 패키지를 통해 즉석에서 한 개 이상의 인터페이스를 구현하고, 메소드 호출을 지정한 클래스로 전달하는 프록시를 생성할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실제 프록시 클래스는 실행중에 생성되므로 해당 기술을 '동적 프록시(dynamic proxy)'라고 한다.&lt;/p&gt;</description>
      <category>스터디/객체지향</category>
      <author>swimee</author>
      <guid isPermaLink="true">https://sootudio-programming.tistory.com/17</guid>
      <comments>https://sootudio-programming.tistory.com/entry/%ED%97%A4%EB%93%9C%ED%8D%BC%EC%8A%A4%ED%8A%B8-%EB%94%94%EC%9E%90%EC%9D%B8%ED%8C%A8%ED%84%B4-11%EC%9E%A5-%EA%B0%9D%EC%B2%B4-%EC%A0%91%EA%B7%BC-%EC%A0%9C%EC%96%B4%ED%95%98%EA%B8%B0-%ED%94%84%EB%A1%9D%EC%8B%9C-%ED%8C%A8%ED%84%B4#entry17comment</comments>
      <pubDate>Fri, 7 Feb 2025 19:27:22 +0900</pubDate>
    </item>
    <item>
      <title>[헤드퍼스트 디자인패턴] 10장. 객체의 상태 바꾸기 - 상태 패턴</title>
      <link>https://sootudio-programming.tistory.com/entry/%ED%97%A4%EB%93%9C%ED%8D%BC%EC%8A%A4%ED%8A%B8-%EB%94%94%EC%9E%90%EC%9D%B8%ED%8C%A8%ED%84%B4-10%EC%9E%A5-%EA%B0%9D%EC%B2%B4%EC%9D%98-%EC%83%81%ED%83%9C-%EB%B0%94%EA%BE%B8%EA%B8%B0-%EC%83%81%ED%83%9C-%ED%8C%A8%ED%84%B4</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;디자인패턴_블로그로고.png&quot; data-origin-width=&quot;8140&quot; data-origin-height=&quot;3380&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/8ZSUK/btsLOvGXtw8/XeNLwkMO6u70AxTjj1cMx0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/8ZSUK/btsLOvGXtw8/XeNLwkMO6u70AxTjj1cMx0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/8ZSUK/btsLOvGXtw8/XeNLwkMO6u70AxTjj1cMx0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F8ZSUK%2FbtsLOvGXtw8%2FXeNLwkMO6u70AxTjj1cMx0%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;8140&quot; height=&quot;3380&quot; data-filename=&quot;디자인패턴_블로그로고.png&quot; data-origin-width=&quot;8140&quot; data-origin-height=&quot;3380&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;해당 게시물은 '헤드퍼스트 디자인패턴'을 읽고 내용을 정리한 글입니다.&lt;br /&gt;헤퍼디 스터디 링크: https://github.com/SSAFY11th-book-study/book-study&lt;/blockquote&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;뽑기 기계로 알아보는 상태(state)&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;961&quot; data-origin-height=&quot;544&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/CfM5C/btsLOKYhua6/raBYFJrOzchloukvg1xKk1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/CfM5C/btsLOKYhua6/raBYFJrOzchloukvg1xKk1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/CfM5C/btsLOKYhua6/raBYFJrOzchloukvg1xKk1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FCfM5C%2FbtsLOKYhua6%2FraBYFJrOzchloukvg1xKk1%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;600&quot; height=&quot;340&quot; data-origin-width=&quot;961&quot; data-origin-height=&quot;544&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;때문에, 우선 어떤 상태가 있는지 모아본다.&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;h2 data-ke-size=&quot;size26&quot;&gt;상태 패턴의 정의&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;상태 패턴의 정의는 다음과 같다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;상태 패턴(State Pattern)을 사용하면 객체의 내부 상태가 바뀜에 따라서 객체의 행동을 바꿀 수 있습니다. 마치 객체의 클래스가 바뀌는 것과 같은 결과를 얻을 수 있습니다.&lt;/blockquote&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;NoQuarterState (동전이 들어있지 않은 경우)&lt;/li&gt;
&lt;li&gt;HasQuarterState (누군가 동전을 투입해서 동전이 들어있는 경우)&lt;/li&gt;
&lt;/ul&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;h3 data-ke-size=&quot;size23&quot;&gt;클래스 다이어그램&lt;/h3&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;706&quot; data-origin-height=&quot;275&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bB3n6B/btsLN2ZnTun/DKiRXtSYUiYBeT5av4bfe1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bB3n6B/btsLN2ZnTun/DKiRXtSYUiYBeT5av4bfe1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bB3n6B/btsLN2ZnTun/DKiRXtSYUiYBeT5av4bfe1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbB3n6B%2FbtsLN2ZnTun%2FDKiRXtSYUiYBeT5av4bfe1%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;600&quot; height=&quot;234&quot; data-origin-width=&quot;706&quot; data-origin-height=&quot;275&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;Context &lt;/b&gt;클래스에는 여러 가지 내부 상태가 들어있을 수 있다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;뽑기 기계의 예시에서는, 돈이 들어있음, 돈이 들어있지 않음, 재고 있음, 재고 없음 등의 여러가지 상태를 가진 GumballMachine 클래스가 Context에 해당한다.&lt;/li&gt;
&lt;li&gt;Context의 request() 메소드가 호출되면, 그 작업은 상태 객체에게 맡겨진다.&lt;/li&gt;
&lt;li&gt;만약 Context의 인스턴스가 아주 많은 경우, 여러 Context에서 상태 객체를 공유하는 것도 가능하다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;State&lt;/b&gt; 인터페이스는 모든 구상 상태 클래스의 공통 인터페이스를 정의한다. 모든 상태 클래스에서 같은 인터페이스를 구현하므로 바꿔 가면서 쓸 수 있는 것이다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;ConcreateState&lt;/b&gt;는 Context로부터 전달된 요청을 자기 나름의 방식으로 구현해서 처리한다. 이렇게 하면 Context에서 상태를 바꿀 때마다 행동도 바뀌게 된다.&lt;/li&gt;
&lt;li&gt;State 인터페이스를 구현하는 구상 상태 클래스는 원하는 만큼 만들 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;전략 패턴과의 차이&lt;/h3&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;상황에 따라 Context 객체에서 여러 상태 객체 중 한 객체에게 모든 행동을 맡기게 되는 것임.&lt;/li&gt;
&lt;li&gt;그 객체의 내부 상태에 따라 현재 상태를 나타내는 객체가 바뀌게 되고, 그 결과로 Context 객체의 행동도 자연스럽게 바뀌게 됨.&lt;/li&gt;
&lt;li&gt;이 때, 클라이언트는 상태 객체를 몰라도 됨.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;전략 패턴을 사용할 때는 일반적으로 클라이언트가 Context 객체에게 어떤 전략 객체를 사용할지를 지정해 준다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;전략 패턴은 주로 실행 시에 전략 객체를 변경할 수 있는 유연성을 제공하는 용도로 쓰인다.&lt;/li&gt;
&lt;li&gt;보통 가장 적합한 객체를 선택해서 사용하게 된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>스터디/객체지향</category>
      <author>swimee</author>
      <guid isPermaLink="true">https://sootudio-programming.tistory.com/16</guid>
      <comments>https://sootudio-programming.tistory.com/entry/%ED%97%A4%EB%93%9C%ED%8D%BC%EC%8A%A4%ED%8A%B8-%EB%94%94%EC%9E%90%EC%9D%B8%ED%8C%A8%ED%84%B4-10%EC%9E%A5-%EA%B0%9D%EC%B2%B4%EC%9D%98-%EC%83%81%ED%83%9C-%EB%B0%94%EA%BE%B8%EA%B8%B0-%EC%83%81%ED%83%9C-%ED%8C%A8%ED%84%B4#entry16comment</comments>
      <pubDate>Fri, 7 Feb 2025 19:26:19 +0900</pubDate>
    </item>
    <item>
      <title>[헤드퍼스트 디자인패턴] 9장. 컬렉션 잘 관리하기 - 반복자 패턴과 컴포지트 패턴</title>
      <link>https://sootudio-programming.tistory.com/entry/%ED%97%A4%EB%93%9C%ED%8D%BC%EC%8A%A4%ED%8A%B8-%EB%94%94%EC%9E%90%EC%9D%B8%ED%8C%A8%ED%84%B4-9%EC%9E%A5-%EC%BB%AC%EB%A0%89%EC%85%98-%EC%9E%98-%EA%B4%80%EB%A6%AC%ED%95%98%EA%B8%B0-%EB%B0%98%EB%B3%B5%EC%9E%90-%ED%8C%A8%ED%84%B4%EA%B3%BC-%EC%BB%B4%ED%8F%AC%EC%A7%80%ED%8A%B8-%ED%8C%A8%ED%84%B4</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;디자인패턴_블로그로고.png&quot; data-origin-width=&quot;8140&quot; data-origin-height=&quot;3380&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bct6fW/btsLJg3pCCo/4iOshtvOxQRSkOnygUBsc0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bct6fW/btsLJg3pCCo/4iOshtvOxQRSkOnygUBsc0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bct6fW/btsLJg3pCCo/4iOshtvOxQRSkOnygUBsc0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbct6fW%2FbtsLJg3pCCo%2F4iOshtvOxQRSkOnygUBsc0%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;8140&quot; height=&quot;3380&quot; data-filename=&quot;디자인패턴_블로그로고.png&quot; data-origin-width=&quot;8140&quot; data-origin-height=&quot;3380&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;해당 게시물은 '헤드퍼스트 디자인패턴'을 읽고 내용을 정리한 글입니다.&lt;br /&gt;헤퍼디 스터디 링크: https://github.com/SSAFY11th-book-study/book-study&lt;/blockquote&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;반복자 패턴의 정의&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;반복자 패턴의 정의는 다음과 같다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;반복자 패턴(Iterator Pattern)은 컬렉션의 구현 방법을 노출하지 않으면서 집합체 내의 모든 항목에 접근하는 방법을 제공한다.&lt;/blockquote&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;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;책에서는 예시로 서로 메뉴 항목을 다른 형식(ArrayList와 배열)로 저장한 두 식당의 메뉴 코드에서 메뉴에 있는 모든 항목을 출력하는 printMenu() 메소드를 만들었다.&lt;/li&gt;
&lt;/ul&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;h3 data-ke-size=&quot;size23&quot;&gt;반복자 패턴의 구조&lt;/h3&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;1118&quot; data-origin-height=&quot;594&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dx5Ezt/btsLJyCMxvl/geKzOUTybCDaiYUursFskK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dx5Ezt/btsLJyCMxvl/geKzOUTybCDaiYUursFskK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dx5Ezt/btsLJyCMxvl/geKzOUTybCDaiYUursFskK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdx5Ezt%2FbtsLJyCMxvl%2FgeKzOUTybCDaiYUursFskK%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;600&quot; height=&quot;319&quot; data-origin-width=&quot;1118&quot; data-origin-height=&quot;594&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;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;단일 역할 원칙&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단일 역할 원칙은 '하나의 클래스는 하나의 역할만 맡아야 한다'는 객체지향의 원칙이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하나의 클래스 2개 이상의 역할을 맡게 된다는 것은, 이후 해당 클래스에서 변화가 생길 수 있는 부분이 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;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;컬렉션이 바뀌는 상황&lt;/li&gt;
&lt;li&gt;반복자 관련 기능이 바뀌는 상황&lt;/li&gt;
&lt;/ul&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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;컴포지트 패턴의 정의&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컴포지트 패턴의 정의는 다음과 같다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;컴포지트 패턴(Composite Pattern)으로 객체를 트리구조로 구성해서 부분-전체 계층구조를 구현한다. 컴포지트 패턴을 사용하면 클라이언트에서 개별 객체와 복합 객체를 똑같은 방법으로 다룰 수 있다.&lt;/blockquote&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;blockquote data-ke-style=&quot;style2&quot;&gt;예제: 파일 시스템&lt;br /&gt;컴퓨터의 파일 시스템을 떠올려보자.&lt;br /&gt;- Component: 파일과 폴더가 공통으로 가진 기능(열기, 이름 출력 등)&lt;br /&gt;- Leaf: 개별 파일 (하위 요소가 없음)&lt;br /&gt;- Composite: 폴더 (안에 다른 파일이나 폴더를 포함할 수 있음)&lt;/blockquote&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;315&quot; data-origin-height=&quot;331&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bK2C2x/btsLJTfzV5B/u8J5oZcGk9LpnpO3BbLZbK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bK2C2x/btsLJTfzV5B/u8J5oZcGk9LpnpO3BbLZbK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bK2C2x/btsLJTfzV5B/u8J5oZcGk9LpnpO3BbLZbK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbK2C2x%2FbtsLJTfzV5B%2Fu8J5oZcGk9LpnpO3BbLZbK%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;300&quot; height=&quot;315&quot; data-origin-width=&quot;315&quot; data-origin-height=&quot;331&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음과 같은 트리 구조가 있을 때, 하위 구조가 있는 노드를 Composite( = 복합 객체) 라고 하고, 더 이상 하위 구조가 없는 잎을 lesf( = 개별 객체) 라고 하는 것이다. 그리고 이 두가지의 공통된 부분을 Component를 통해 만들면&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1213&quot; data-origin-height=&quot;557&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/5hkbR/btsLJCkRvKz/p5iOP4qtH5Zh0XwbTfBKvk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/5hkbR/btsLJCkRvKz/p5iOP4qtH5Zh0XwbTfBKvk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/5hkbR/btsLJCkRvKz/p5iOP4qtH5Zh0XwbTfBKvk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F5hkbR%2FbtsLJCkRvKz%2Fp5iOP4qtH5Zh0XwbTfBKvk%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;600&quot; height=&quot;276&quot; data-origin-width=&quot;1213&quot; data-origin-height=&quot;557&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음과 같이 전체를 대상으로도, 부분을 대상으로도 같은 작업을 수행할 수 있다는 것이다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;컴포지트 패턴의 구조&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러한 컴포지트 패턴의 클래스 다이어그램은 다음과 같다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;773&quot; data-origin-height=&quot;462&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/wNX2i/btsLHUt3LQa/nAcXT1W1zb4wpU9Z8U16f0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/wNX2i/btsLHUt3LQa/nAcXT1W1zb4wpU9Z8U16f0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/wNX2i/btsLHUt3LQa/nAcXT1W1zb4wpU9Z8U16f0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FwNX2i%2FbtsLHUt3LQa%2FnAcXT1W1zb4wpU9Z8U16f0%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;600&quot; height=&quot;359&quot; data-origin-width=&quot;773&quot; data-origin-height=&quot;462&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;책에서는 Menu와 MenuItem의 공통된 부분을 MenuComponent 라는 추상 클래스로 다음과 같이 구성하였다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;782&quot; data-origin-height=&quot;655&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/O649S/btsLJWDnKqA/nmrXUhXrfqga0Z4KKgq3f1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/O649S/btsLJWDnKqA/nmrXUhXrfqga0Z4KKgq3f1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/O649S/btsLJWDnKqA/nmrXUhXrfqga0Z4KKgq3f1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FO649S%2FbtsLJWDnKqA%2FnmrXUhXrfqga0Z4KKgq3f1%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;600&quot; height=&quot;503&quot; data-origin-width=&quot;782&quot; data-origin-height=&quot;655&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고, 다양한 종류(형식)의 메뉴들을 다음과 같이 정리하였다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1261&quot; data-origin-height=&quot;752&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/T6UeW/btsLJE3380i/VKOxOIo2nr9wAL6tJsaQKK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/T6UeW/btsLJE3380i/VKOxOIo2nr9wAL6tJsaQKK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/T6UeW/btsLJE3380i/VKOxOIo2nr9wAL6tJsaQKK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FT6UeW%2FbtsLJE3380i%2FVKOxOIo2nr9wAL6tJsaQKK%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;600&quot; height=&quot;358&quot; data-origin-width=&quot;1261&quot; data-origin-height=&quot;752&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>스터디/객체지향</category>
      <author>swimee</author>
      <guid isPermaLink="true">https://sootudio-programming.tistory.com/15</guid>
      <comments>https://sootudio-programming.tistory.com/entry/%ED%97%A4%EB%93%9C%ED%8D%BC%EC%8A%A4%ED%8A%B8-%EB%94%94%EC%9E%90%EC%9D%B8%ED%8C%A8%ED%84%B4-9%EC%9E%A5-%EC%BB%AC%EB%A0%89%EC%85%98-%EC%9E%98-%EA%B4%80%EB%A6%AC%ED%95%98%EA%B8%B0-%EB%B0%98%EB%B3%B5%EC%9E%90-%ED%8C%A8%ED%84%B4%EA%B3%BC-%EC%BB%B4%ED%8F%AC%EC%A7%80%ED%8A%B8-%ED%8C%A8%ED%84%B4#entry15comment</comments>
      <pubDate>Thu, 9 Jan 2025 20:02:35 +0900</pubDate>
    </item>
    <item>
      <title>[헤드퍼스트 디자인패턴] 8장. 알고리즘 캡슐화하기 - 템플릿 메소드 패턴</title>
      <link>https://sootudio-programming.tistory.com/entry/%ED%97%A4%EB%93%9C%ED%8D%BC%EC%8A%A4%ED%8A%B8-%EB%94%94%EC%9E%90%EC%9D%B8%ED%8C%A8%ED%84%B4-8%EC%9E%A5-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%EC%BA%A1%EC%8A%90%ED%99%94%ED%95%98%EA%B8%B0-%ED%85%9C%ED%94%8C%EB%A6%BF-%EB%A7%A4%EC%86%8C%EB%93%9C-%ED%8C%A8%ED%84%B4</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;디자인패턴_블로그로고.png&quot; data-origin-width=&quot;8140&quot; data-origin-height=&quot;3380&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mCZ3I/btsLBuWiSho/eCEzSau4P47JVpUM9CAYi0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mCZ3I/btsLBuWiSho/eCEzSau4P47JVpUM9CAYi0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mCZ3I/btsLBuWiSho/eCEzSau4P47JVpUM9CAYi0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmCZ3I%2FbtsLBuWiSho%2FeCEzSau4P47JVpUM9CAYi0%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;8140&quot; height=&quot;3380&quot; data-filename=&quot;디자인패턴_블로그로고.png&quot; data-origin-width=&quot;8140&quot; data-origin-height=&quot;3380&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;해당 게시물은 '헤드퍼스트 디자인패턴'을 읽고 내용을 정리한 글입니다.&lt;br /&gt;헤퍼디 스터디 링크: https://github.com/SSAFY11th-book-study/book-study&lt;/blockquote&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;커피와 홍차 만들기로 알아보는 템플릿 메소드&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;공통된 부분 찾아서 추상화하기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음과 같이 커피와 홍차를 만드는 코드가 있다고 가정해 보자.&lt;/p&gt;
&lt;pre id=&quot;code_1735785103497&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class Coffee {

	void prepareRecipe() {
    	boilWater();
        brewCoffeeGrinds();
        pourInCup();
        addSugarAndMilk();
	}
    
    // 메소드 구현...
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1735785180964&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class Tea {
	
    void prepareRecipe() {
    	boilWater();
        steepTeaBag();
        pourInCup();
        addLemon();
    }
    
   	// 메소드 구현...
}&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;두 코드에서 중복되는 메소드 (prepareRecepe(), boilWater(), pourIncup()) 들이 있으니, 중복되는 메소드들을 하나의 추상 클래스로 만들 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1254&quot; data-origin-height=&quot;708&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/L0Vf9/btsLByqrCKN/38S7JcSupctfpKwy923RP1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/L0Vf9/btsLByqrCKN/38S7JcSupctfpKwy923RP1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/L0Vf9/btsLByqrCKN/38S7JcSupctfpKwy923RP1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FL0Vf9%2FbtsLByqrCKN%2F38S7JcSupctfpKwy923RP1%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;600&quot; height=&quot;339&quot; data-origin-width=&quot;1254&quot; data-origin-height=&quot;708&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위처럼, 중복되는 메소드들은 공통된 CaffeineBeverage 클래스에 넣어 해당 클래스를 상속받는 형식으로 구현할 수 있다. 이때 prepareRecipe의 구현은 각 서브클래스마다 다르므로, 추상 메소드로 선언하고 서브클래스에서 구현하도록 만들었다.&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;prepareRecipe() 메소드 추상화하기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데, 나머지 메소드들도 prepareRecipe처럼 구현 방식이 다른거지, 하나의 큰 틀로 묶을 수 있겠다는 아이디어를 떠올릴 수 있다. brewCoffeeGrinds()와 steepTeaBag() 메소드는 brew() 메소드로, addSugarAndMilk()와 addLemon() 메소드는 addCondiments() 메소드로 합쳐서 슈퍼클래스에서 선언하고, 직접적인 구현은 서브클래스들에서 하는 방식으로 만들어 보자.&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;1197&quot; data-origin-height=&quot;559&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/KeAxG/btsLCsXvlfZ/9KlZV6SjimR6ZPcPvPJQJ0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/KeAxG/btsLCsXvlfZ/9KlZV6SjimR6ZPcPvPJQJ0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/KeAxG/btsLCsXvlfZ/9KlZV6SjimR6ZPcPvPJQJ0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FKeAxG%2FbtsLCsXvlfZ%2F9KlZV6SjimR6ZPcPvPJQJ0%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;600&quot; height=&quot;280&quot; data-origin-width=&quot;1197&quot; data-origin-height=&quot;559&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러면 위와 같은 클래스 다이어그램이 만들어진다. 해당 클래스들을 코드로 보면 다음과 같다.&lt;/p&gt;
&lt;pre id=&quot;code_1735786453590&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public abstract class CaffeineBeverage {
  
	final void prepareRecipe() { // 서브클래스가 이 메소드를 오버라이드하지 못하도록 final로 선언.
		boilWater();
		brew();
		pourInCup();
		addCondiments();
	}
 	
    // Coffee 클래스와 Tea 클래스에서 brew()와 addCondiments()를 다르게 구현하므로, 추상 메소드로 선언한다.
	abstract void brew(); 
  
	abstract void addCondiments();
 
 	// 공통된 메소드는 추상 클래스에서 구현한다.
	void boilWater() {
		System.out.println(&quot;Boiling water&quot;);
	}
  
	void pourInCup() {
		System.out.println(&quot;Pouring into cup&quot;);
	}
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1735786602139&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// Coffee 클래스와 Tea 클래스는 CaffeineBeverage 클래스를 확장(상속) 한다.
public class Coffee extends CaffeineBeverage {
	public void brew() { // CaffeineBeverage 에서 추상 클래스로 만든 메소드들을 구현한다.
		System.out.println(&quot;Dripping Coffee through filter&quot;);
	}
	public void addCondiments() {
		System.out.println(&quot;Adding Sugar and Milk&quot;);
	}
}

public class Tea extends CaffeineBeverage {
	public void brew() {
		System.out.println(&quot;Steeping the tea&quot;);
	}
	public void addCondiments() {
		System.out.println(&quot;Adding Lemon&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;조금 더 자세히 설명하면, CaffeineBeverage 클래스에서 쓰인 prepareRecipe() 가 템플릿 메소드이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 이유는&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;prepareRecipe()가 메소드이다.&lt;/li&gt;
&lt;li&gt;동시에, 어떤 알고리즘(카페인 음료를 만드는)의 템플릿 역할을 한다.&lt;/li&gt;
&lt;/ol&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;템플릿 메소드로 만든 CaffeinBeverage는 다음과 같은 장점이 있다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;코드가 Coffe와 Tea에 중복되지 않고, 서브클래스에서 코드를 재사용할 수 있음.&lt;/li&gt;
&lt;li&gt;알고리즘이 한 군데 모여 있으므로, 알고리즘을 고칠 때 한 부분만 고치면 됨.&lt;/li&gt;
&lt;li&gt;다른 음료도 쉽게 추가할 수 있는 프레임워크를 제공함.&lt;/li&gt;
&lt;li&gt;알고리즘의 지식과 구현 방법이 CaffeinBeverage 클래스에 집중되어 있고, 일부 구현만 서브클래스에 의존함.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;템플릿 메소드 패턴의 정의&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;템플릿 메소드 패턴의 정의는 다음과 같다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;템플릿 메소드 패턴(Template Method Pattern)은 알고리즘의 골격을 정의한다. 템플릿 메소드를 사용하면 알고리즘의 일부 단계를 서브클래스에서 구현할 수 있으며, 알고리즘의 구조는 그대로 유지하면서 알고리즘의 특정 단계를 서브클래스에서 재정의할 수도 있다.&lt;/blockquote&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;&amp;nbsp;&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;1151&quot; data-origin-height=&quot;696&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/odw4S/btsLC1rS08y/SsSHuFv5ukkkgXgYgaNXv0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/odw4S/btsLC1rS08y/SsSHuFv5ukkkgXgYgaNXv0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/odw4S/btsLC1rS08y/SsSHuFv5ukkkgXgYgaNXv0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fodw4S%2FbtsLC1rS08y%2FSsSHuFv5ukkkgXgYgaNXv0%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;600&quot; height=&quot;363&quot; data-origin-width=&quot;1151&quot; data-origin-height=&quot;696&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위에서 봤던 CaffeineBeverage클래스가 Abstract 클래스, Coffee와 Tea 클래스가 ConcreteClass, templateMethod()가 prepareRecipe(), primitveOperation1,2()가 brew와 addCondiments()라고 생각하고 보면 이해하기 쉽다.&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;h2 data-ke-size=&quot;size26&quot;&gt;템플릿 메소드 속 후크 알아보기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;후크(hook)는 추상 클래스에서 선언되지만 기본적인 내용만 구현되어 있거나 아무 코드도 들어있지 않은 메소드이다.&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;pre id=&quot;code_1735793702302&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public abstract class CaffeineBeverageWithHook {
 
	final void prepareRecipe() {
		boilWater();
		brew();
		pourInCup();
		if (customerWantsCondiments()) {
			addCondiments();
		}
	}
 
	abstract void brew();
 
	abstract void addCondiments();
 
	void boilWater() {
		System.out.println(&quot;Boiling water&quot;);
	}
 
	void pourInCup() {
		System.out.println(&quot;Pouring into cup&quot;);
	}
 
	boolean customerWantsCondiments() { // 해당 메소드는 서브클래스에서 필요할 때 오버라이드 할 수 있는 메소드이므로 후크이다.
		return true;
	}
}&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;/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;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;후크를 사용하려면 서브클래스에서 후크를 오버라이드 해야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CaffeineBeverage가 알고리즘의 특정 부분을 처리할지 말지를 결정하는 용도로 사용한 코드를 보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1735800517971&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class CoffeeWithHook extends CaffeineBeverageWithHook {
 
	public void brew() {
		System.out.println(&quot;Dripping Coffee through filter&quot;);
	}
 
	public void addCondiments() {
		System.out.println(&quot;Adding Sugar and Milk&quot;);
	}
 
 	// 후크를 오버라이드해서 원하는 기능을 넣는다.
	public boolean customerWantsCondiments() { 

		String answer = getUserInput();

		if (answer.toLowerCase().startsWith(&quot;y&quot;)) { // 사용자가 입력한 내용에 따라 리턴값이 달라짐
			return true;
		} else {
			return false;
		}
	}
 
	private String getUserInput() {
		String answer = null;

		System.out.print(&quot;Would you like milk and sugar with your coffee (y/n)? &quot;);

		BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
		try {
			answer = in.readLine();
		} catch (IOException ioe) {
			System.err.println(&quot;IO error trying to read your answer&quot;);
		}
		if (answer == null) {
			return &quot;no&quot;;
		}
		return answer;
	}
}&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;/p&gt;
&lt;pre id=&quot;code_1735801696776&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class BeverageTestDrive {
	public static void main(String[] args) {
 
 		// 객체 생성
		TeaWithHook teaHook = new TeaWithHook();
		CoffeeWithHook coffeeHook = new CoffeeWithHook();
 
		System.out.println(&quot;\n차 만드는 중...&quot;);
		teaHook.prepareRecipe();
 
		System.out.println(&quot;\n커피 만드는 중...&quot;);
		coffeeHook.prepareRecipe();
	}
}&lt;/code&gt;&lt;/pre&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;h2 data-ke-size=&quot;size26&quot;&gt;할리우드 원칙과 템플릿 메소드 패턴&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;할리우드 원칙은 저수준 구성 요소가 시스템에 접속할 수는 있지만 언제, 어떻게 그 구성 요소를 사용할지는 고수준 구성 요소가 결정하는 디자인 원칙이다.&lt;/p&gt;
&lt;p 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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1167&quot; data-origin-height=&quot;744&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rHihv/btsLBsYMfBz/uI6ySkxozoKwVRWqIZ56r0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rHihv/btsLBsYMfBz/uI6ySkxozoKwVRWqIZ56r0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rHihv/btsLBsYMfBz/uI6ySkxozoKwVRWqIZ56r0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FrHihv%2FbtsLBsYMfBz%2FuI6ySkxozoKwVRWqIZ56r0%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;600&quot; height=&quot;383&quot; data-origin-width=&quot;1167&quot; data-origin-height=&quot;744&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 그림과 같이, Coffee클래스와 Tea 클래스는 brew()나 addCondiments의 구현을 하는 등에만 쓰이고, 호출 당하기 전까지는 추상 클래스를 직접 호출하지 않는다.&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;h2 data-ke-size=&quot;size26&quot;&gt;자바 API 속 템플릿 메소드 패턴&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Arrays 클래스&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자바의 Arrays 클래스에는 정렬할 때 사용하는 sort()와 mergeSort() 메소드가 있는데, 해당 메소드들은 템플릿 메소드이다.&lt;/p&gt;
&lt;pre id=&quot;code_1735805660563&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public static void sort(Object[] a) {
	Object aus[] = (Object[])a.clone();
    mergeSort(aux, a, 0, a.length, 0);
}

private static void mergeSort(Object src[], Object dest[], int low, int high, int off) {
	
    // 생략된 코드
    
    for(int i = low ; i &amp;lt; high ; i++) {
    	for(int j = i ; j &amp;gt; low &amp;amp;&amp;amp; ((Comparable)dest[j-1].compareTo((Comparable)dest[j])&amp;gt;0 ; j--)
        {
        	swap(dest, j , j-1);
        }
    }
    
    // 생략된 코드
}&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;해당 코드에서, compareTo()를 구현해야지만 템플릿 메소드가 완성되며, 코드가 동작한다.&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;만약, sort()만 사용했을 때의 문제점은, sort()가 정적 메소드이고, sort()자체가 특정 슈퍼클래스에 정의되어 있는 게 아니므로, sort() 메소드가 compareTo()의 구현 여부를 알 수 없다.&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;때문에 compareTo() 메소드만 있는 Comparable 인터페이스를 구현하는 방식으로 문제를 해결한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래는 Comparable 인터페이스를 구현한 Duck 클래스이다.&lt;/p&gt;
&lt;pre id=&quot;code_1735806455652&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 서브클래스를 만들어서 쓰는 대신 Comparable 인터페이스를 구현한다.
public class Duck implements Comparable&amp;lt;Duck&amp;gt; {
	String name;
	int weight;
  
	public Duck(String name, int weight) {
		this.name = name;
		this.weight = weight;
	}
 
	public String toString() {
		return name + &quot; weighs &quot; + weight;
	}
  
	public int compareTo(Duck otherDuck) { // sort 메소드에서 필요로 하는 메소드
 
  
		if (this.weight &amp;lt; otherDuck.weight) {
			return -1;
		} else if (this.weight == otherDuck.weight) {
			return 0;
		} else { // this.weight &amp;gt; otherDuck.weight
			return 1;
		}
	}
}&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;/p&gt;
&lt;pre id=&quot;code_1735806750428&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class DuckSortTestDrive {

	public static void main(String[] args) {
		Duck[] ducks = { 
						new Duck(&quot;Daffy&quot;, 8), 
						new Duck(&quot;Dewey&quot;, 2),
						new Duck(&quot;Howard&quot;, 7),
						new Duck(&quot;Louie&quot;, 2),
						new Duck(&quot;Donald&quot;, 10), 
						new Duck(&quot;Huey&quot;, 2)
		 };

		System.out.println(&quot;Before sorting:&quot;);
		display(ducks);

		Arrays.sort(ducks);
 
		System.out.println(&quot;\nAfter sorting:&quot;);
		display(ducks);
	}

	public static void display(Duck[] ducks) {
		for (Duck d : ducks) {
			System.out.println(d);
		}
	}
}&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;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;Arrays 클래스에 있는 sort() 템플릿 메소드를 호출한다.&amp;nbsp;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;오리 배열을 인자로 전달한다.&lt;/li&gt;
&lt;li&gt;sort() 메소드와 그 보조 메소드인 mergeSort()에서 정렬 작업을 처리한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;배열을 정렬한다.
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;sort() 메소드는 두 오리 객체를 비교할 때 compareTo() 메소드에 의존한다. 한 오리 객체의 compareTo() 메소드를 호출할 때 비교해야 할 다른 오리 객체를 매개변수로 전달한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;비교할 결과가 맞지 않으면 Arrays에 들어있는 swap() 구상 메소드를 써서 두 오리 객체를 맞바꾼다.
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;해당 작업을 반복한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&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;278&quot; data-origin-height=&quot;391&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/BAvZz/btsLDuOcVpz/cTGnm0K1MKZOcKhnoth2NK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/BAvZz/btsLDuOcVpz/cTGnm0K1MKZOcKhnoth2NK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/BAvZz/btsLDuOcVpz/cTGnm0K1MKZOcKhnoth2NK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FBAvZz%2FbtsLDuOcVpz%2FcTGnm0K1MKZOcKhnoth2NK%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;200&quot; height=&quot;281&quot; data-origin-width=&quot;278&quot; data-origin-height=&quot;391&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이처럼, 실전에서 패턴을 적용하는 방법이 온전한 템플릿 메소드라고 할 수는 없겠지만, sort() 메소드 구현 자체는 템플릿 메소드 패턴의 기본을 따르고 있다. 따라서, sort()는 템플릿 메소드를 주어진 상황과 구현상 제약조건에 맞게 고쳐서 적용한 사례라고 볼 수 있다.&lt;/p&gt;</description>
      <category>스터디/객체지향</category>
      <category>disignpattern</category>
      <category>headfirst</category>
      <category>templateMethod</category>
      <category>디자인패턴</category>
      <category>템플릿메소드</category>
      <category>헤드퍼스트</category>
      <author>swimee</author>
      <guid isPermaLink="true">https://sootudio-programming.tistory.com/14</guid>
      <comments>https://sootudio-programming.tistory.com/entry/%ED%97%A4%EB%93%9C%ED%8D%BC%EC%8A%A4%ED%8A%B8-%EB%94%94%EC%9E%90%EC%9D%B8%ED%8C%A8%ED%84%B4-8%EC%9E%A5-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%EC%BA%A1%EC%8A%90%ED%99%94%ED%95%98%EA%B8%B0-%ED%85%9C%ED%94%8C%EB%A6%BF-%EB%A7%A4%EC%86%8C%EB%93%9C-%ED%8C%A8%ED%84%B4#entry14comment</comments>
      <pubDate>Thu, 2 Jan 2025 17:39:34 +0900</pubDate>
    </item>
  </channel>
</rss>