<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>All :L</title>
    <link>https://jhw29.tistory.com/</link>
    <description> ️ Daily Dev Log ٩(๑❛ᴗ❛๑)۶</description>
    <language>ko</language>
    <pubDate>Fri, 10 Apr 2026 08:07:00 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>ofijwe</managingEditor>
    <image>
      <title>All :L</title>
      <url>https://tistory1.daumcdn.net/tistory/4250714/attach/9e5905e8dc964869b4b1e96c37fe8830</url>
      <link>https://jhw29.tistory.com</link>
    </image>
    <item>
      <title>[우아한테크코스] 프리코스 4주차 회고록</title>
      <link>https://jhw29.tistory.com/249</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;image.png&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;511&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kXmGP/btsKJELm2k7/HnQxj5gbKByOyNDez36e30/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kXmGP/btsKJELm2k7/HnQxj5gbKByOyNDez36e30/img.webp&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kXmGP/btsKJELm2k7/HnQxj5gbKByOyNDez36e30/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkXmGP%2FbtsKJELm2k7%2FHnQxj5gbKByOyNDez36e30%2Fimg.webp&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1280&quot; height=&quot;511&quot; data-filename=&quot;image.png&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;511&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;프리코스 4주차를 마치며...&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마지막 편의점 미션에는 그동안 프리코스를 통해 익힌 다양한 기술을 하나의 프로그램에 모두 적용해 보았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프리코스의 처음부터 끝까지 매일 새로운 문제에 직면하며 이를 해결하기 위한 과정을 통해 많은 기술적 성장을 이루었다. 처음에는 모든 과정이 복잡하고 낯설게 느껴졌지만, 프리코스를 진행하며 배운 내용을 바탕으로 차근차근 진행하면서 각 단계의 중요성을 이해할 수 있었다. 요구 사항을 명확히 정의하는 것부터 시작해, 이를 구현하는 과정에서의 중요성도 실감하게 되었다. 매일 설정한 목표를 하나씩 이루어가며 그때그때 배운 점과 경험이 하나의 큰 결과물로 이어지는 과정에서 많은 배움을 얻었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/jhw296/java-convenience-store-7-jhw296&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://github.com/jhw296/java-convenience-store-7-jhw296&lt;/a&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;초반에는 미션의 전반적인 흐름과 요구 사항을 파악하고, 코드의 기초 구조를 세우는 데 집중했다. 그동안 진행했던 미션을 되돌아보며 OOP와 SOLID 원칙을 복습하고, MVC 패턴을 기반으로 클래스 구조를 설계하는 데 중점을 두었다. 이 과정에서 SOLID 원칙과 OOP의 중요성을 다시 한 번 되새길 수 있었고 코드의 확장성과 유지보수성을 고려해 프로그램을 설계했다.&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;객체지향 5원칙 (SOLID)&lt;/b&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 38px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style16&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;width: 33.3333%; text-align: justify; height: 19px;&quot;&gt;&lt;b&gt;&amp;bull;&lt;/b&gt; &lt;a href=&quot;https://inpa.tistory.com/entry/OOP-%F0%9F%92%A0-%EC%95%84%EC%A3%BC-%EC%89%BD%EA%B2%8C-%EC%9D%B4%ED%95%B4%ED%95%98%EB%8A%94-SRP-%EB%8B%A8%EC%9D%BC-%EC%B1%85%EC%9E%84-%EC%9B%90%EC%B9%99&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;단일 책임 원칙 (SRP)&lt;/a&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; text-align: justify; height: 19px;&quot;&gt;&lt;b&gt;&amp;bull;&lt;/b&gt;&lt;span style=&quot;color: #333333; text-align: justify;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;a href=&quot;https://inpa.tistory.com/entry/OOP-%F0%9F%92%A0-%EC%95%84%EC%A3%BC-%EC%89%BD%EA%B2%8C-%EC%9D%B4%ED%95%B4%ED%95%98%EB%8A%94-OCP-%EA%B0%9C%EB%B0%A9-%ED%8F%90%EC%87%84-%EC%9B%90%EC%B9%99&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;개방 폐쇄 원칙 (OCP)&lt;/a&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; text-align: justify; height: 19px;&quot;&gt;&lt;b&gt;&amp;bull;&lt;/b&gt;&lt;span style=&quot;color: #333333; text-align: justify;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;a href=&quot;https://inpa.tistory.com/entry/OOP-%F0%9F%92%A0-%EC%95%84%EC%A3%BC-%EC%89%BD%EA%B2%8C-%EC%9D%B4%ED%95%B4%ED%95%98%EB%8A%94-LSP-%EB%A6%AC%EC%8A%A4%EC%BD%94%ED%94%84-%EC%B9%98%ED%99%98-%EC%9B%90%EC%B9%99&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;리스코프 치환 원칙 (LSP)&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;width: 33.3333%; text-align: justify; height: 19px;&quot;&gt;&lt;b&gt;&amp;bull;&lt;/b&gt;&lt;span style=&quot;color: #333333; text-align: justify;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;a href=&quot;https://inpa.tistory.com/entry/OOP-%F0%9F%92%A0-%EC%95%84%EC%A3%BC-%EC%89%BD%EA%B2%8C-%EC%9D%B4%ED%95%B4%ED%95%98%EB%8A%94-ISP-%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4-%EB%B6%84%EB%A6%AC-%EC%9B%90%EC%B9%99&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;인터페이스 분리 원칙 (ISP)&lt;/a&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; text-align: justify; height: 19px;&quot;&gt;&lt;b&gt;&amp;bull;&lt;/b&gt;&lt;span style=&quot;color: #333333; text-align: justify;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;a href=&quot;https://inpa.tistory.com/entry/OOP-%F0%9F%92%A0-%EC%95%84%EC%A3%BC-%EC%89%BD%EA%B2%8C-%EC%9D%B4%ED%95%B4%ED%95%98%EB%8A%94-DIP-%EC%9D%98%EC%A1%B4-%EC%97%AD%EC%A0%84-%EC%9B%90%EC%B9%99&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;의존성 역전 원칙 (DIP)&lt;/a&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; text-align: justify; height: 19px;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;중반부에는 MVC 패턴을 적용하고 테스트 케이스를 작성했다. MVC 패턴을 처음 접했을 때는 다소 어려움을 느꼈지만 점차 익숙해지기 위해 MVC패턴에 대해 공부했다. 지난 미션에서 해당 패턴을 사용했음에도 디렉터리 구조를 명확히 하지 않았다는 점을 피드백을 통해 깨달았다. 디렉터리로 각 컴포넌트의 역할을 분리하고 코드의 구조를 개선하는 방식이 유지보수성에 큰 도움이 된다는 점을 실감했다. 따라서 각 컴포넌트의 역할을 분리하고 디렉터리 구조를 더욱 꼼꼼히 작성했다. 또한, 다양한 입력값에 대해 견고한 코드를 작성하려는 노력을 기울이면서 테스트의 중요성도 점차 실감하게 되었다. 단위 테스트를 진행하며 코드를 작성하니 개발해야 할 순서가 명확하게 보였다.&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;MVC 패턴&lt;/b&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style16&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;&lt;img src=&quot;https://velog.velcdn.com/images/langoustine/post/7f79e8f1-2524-4685-9ba3-9352d814380d/image.png&quot; /&gt;&lt;/td&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;&lt;img src=&quot;https://velog.velcdn.com/images/langoustine/post/7c433d37-6e00-4444-8ad4-d37e06d8cf27/image.png&quot; /&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;후반부에는 파일 처리와 예외 처리에 집중했다. 특히 파일에서 데이터를 읽어오는 과정과 예외 상황을 처리하는 데 많은 시간을 할애했다. 오랜만에 파일의 텍스트를 파싱하는 작업을 하다 보니 필요한 메소드가 잘 기억나지 않았다. 하지만 Java의 파일 처리 방법을 공부하고 이를 코드에 적용하면서 최적의 방법을 찾아나갔던 것 같다. 이 과정에서 문제를 체계적으로 해결하는 방법과 예외 처리의 중요성을 다시 한 번 깨달았다. 또한, 지속적으로 단위 테스트를 작성하면서 예상치 못한 오류를 사전에 방지할 수 있었다. 그리고 리팩토링을 통해 코드를 더 효율적이고 깔끔하게 개선했다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;FileReader&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.oracle.com/javase/8/docs/api/?java/io/FileReader.html&quot;&gt;FileReader 클래스&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;FileReader 계층적 흐름&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;292&quot; data-origin-height=&quot;300&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bizVaQ/btsKICU2O62/i6EaxkdRnBkpakJkKx8nh1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bizVaQ/btsKICU2O62/i6EaxkdRnBkpakJkKx8nh1/img.jpg&quot; data-alt=&quot;https://www.geeksforgeeks.org/java-io-filereader-class/&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bizVaQ/btsKICU2O62/i6EaxkdRnBkpakJkKx8nh1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbizVaQ%2FbtsKICU2O62%2Fi6EaxkdRnBkpakJkKx8nh1%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;292&quot; height=&quot;300&quot; data-origin-width=&quot;292&quot; data-origin-height=&quot;300&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://www.geeksforgeeks.org/java-io-filereader-class/&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;프로젝트 마무리 단계에서는 작성한 코드를 간결하고 효율적으로 개선하는 데 집중했다. 반복되는 로직을 함수로 분리하기 위해 노력했다. 한 번 잘못된 방향으로 진행된 로직을 제대로 작동하도록 되돌리기 쉽지 않았다. 다양한 방법을 시도하며 코드를 최적화하려고 했고 이 과정에서 리팩토링이 단순한 수정이 아니라 코드 구조를 개선하는 중요한 작업임을 확실히 깨달았다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;마지막 미션을 마치며 객체지향 설계, 단위 테스트, 리팩토링의 중요성을 깊이 이해하게 되었다. 초반에는 시행착오가 많았지만 매일 진행 사항을 기록하고 분석하며 점차 더 나은 코드를 작성하는 방법을 익혔고 기술적으로 많이 성장한 것을 느낄 수 있었다. 앞으로의 프로젝트에서도 이번 미션에서 배운 점들을 적극적으로 활용해 더 체계적이고 효율적인 개발 방식을 적용해 나갈 것이다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&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;1546&quot; data-origin-height=&quot;438&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/csrZq1/btsKJzDpfkh/TZYpMvc5uiNWpnOOrx46sK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/csrZq1/btsKJzDpfkh/TZYpMvc5uiNWpnOOrx46sK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/csrZq1/btsKJzDpfkh/TZYpMvc5uiNWpnOOrx46sK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcsrZq1%2FbtsKJzDpfkh%2FTZYpMvc5uiNWpnOOrx46sK%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;1546&quot; height=&quot;438&quot; data-origin-width=&quot;1546&quot; data-origin-height=&quot;438&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <author>ofijwe</author>
      <guid isPermaLink="true">https://jhw29.tistory.com/249</guid>
      <comments>https://jhw29.tistory.com/249#entry249comment</comments>
      <pubDate>Wed, 13 Nov 2024 18:33:40 +0900</pubDate>
    </item>
    <item>
      <title>[BOJ/Java] 나무 재테크 (16235)</title>
      <link>https://jhw29.tistory.com/241</link>
      <description>&lt;p&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/16235&quot;&gt;나무 재테크 (16235)&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;1. &lt;span style='background-color: #fff5b1'&gt;문제 분석&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;문제 개요&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;나무 재테크 문제는 N x N 크기의 땅에 나무를 심고, 주어진 조건에 따라 나무를 키워나가며, K년이 지난 후 살아남은 나무의 개수를 구하는 문제이다.&lt;/li&gt;
&lt;li&gt;계절에 따라 나무의 성장, 죽음, 번식, 그리고 땅의 양분이 추가되는 과정이 주어지며, 이를 시뮬레이션으로 해결해야 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;입력 형식&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;첫 번째 줄에는 &lt;code&gt;N&lt;/code&gt;(땅의 크기), &lt;code&gt;M&lt;/code&gt;(처음 심어진 나무의 개수), &lt;code&gt;K&lt;/code&gt;(몇 년 후까지 볼 것인지) 주어진다.&lt;/li&gt;
&lt;li&gt;그다음 &lt;code&gt;N&lt;/code&gt;개의 줄에 각 칸에 추가되는 양분의 양이 주어진다.&lt;/li&gt;
&lt;li&gt;그다음 &lt;code&gt;M&lt;/code&gt;개의 줄에 나무의 위치와 나이 정보가 주어진다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;출력 형식&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;K&lt;/code&gt;년 후에 살아남은 나무의 개수를 출력한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;2. &lt;span style='background-color: #fff5b1'&gt;알고리즘 종류&lt;/span&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;시뮬레이션&lt;/strong&gt;: 계절별로 주어진 규칙에 따라 나무의 상태를 변화시켜 시뮬레이션을 진행한다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;우선순위 큐(Priority Queue)&lt;/strong&gt;: 나이가 어린 나무가 먼저 양분을 흡수해야 하므로, 나무의 나이를 기준으로 정렬이 필요하다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;3. &lt;span style='background-color: #fff5b1'&gt;주요 부분 및 코드 작성 방법&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;1. 초기화&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;땅의 크기 &lt;code&gt;N&lt;/code&gt;, 나무의 개수 &lt;code&gt;M&lt;/code&gt;, 몇 년 동안 진행할 것인지 &lt;code&gt;K&lt;/code&gt;를 입력받는다.&lt;/li&gt;
&lt;li&gt;각 칸에 추가되는 양분의 양을 입력받고, 처음에 모든 칸의 양분을 5로 초기화한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;2. 나무의 성장 및 죽음&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;봄: 각 나무는 자신의 나이만큼 땅의 양분을 먹고 나이가 1씩 증가한다. 만약 나무가 충분한 양분을 얻지 못하면 그 나무는 죽는다.&lt;/li&gt;
&lt;li&gt;여름: 봄에 죽은 나무들은 양분이 되어 그 자리에 다시 반환된다. 죽은 나무의 나이 절반만큼 양분이 추가된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;3. 나무의 번식&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;가을: 나무의 나이가 5의 배수인 경우, 인접한 8방향에 새로운 나무가 생긴다. 번식된 나무는 나이가 1이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;4. 양분 추가&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;겨울: 각 칸에 주어진 양분을 추가한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;4. &lt;span style='background-color: #fff5b1'&gt;코드 설명&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;(1) 메인 함수 (&lt;code&gt;main&lt;/code&gt;)&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;초기화 및 입력 처리&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;  N = Integer.parseInt(st.nextToken());  // 땅의 크기
  M = Integer.parseInt(st.nextToken());  // 나무의 개수
  K = Integer.parseInt(st.nextToken());  // 몇 년 동안 진행할지&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;땅의 크기 &lt;code&gt;N&lt;/code&gt;, 나무의 개수 &lt;code&gt;M&lt;/code&gt;, 몇 년 동안 진행할지 &lt;code&gt;K&lt;/code&gt;를 입력받는다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;땅의 양분 정보 및 나무 정보 입력&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;  for (int i = 0; i &amp;lt; N; i++) {
      st = new StringTokenizer(br.readLine());
      for (int j = 0; j &amp;lt; N; j++) {
          A[i][j] = Integer.parseInt(st.nextToken());  // 추가될 양분의 양
          grid[i][j] = 5;  // 초기 양분은 5
      }
  }

  for (int i = 0; i &amp;lt; M; i++) {
      st = new StringTokenizer(br.readLine());
      int x = Integer.parseInt(st.nextToken()) - 1;
      int y = Integer.parseInt(st.nextToken()) - 1;
      int z = Integer.parseInt(st.nextToken());  // 나무의 나이
      plant.add(new Tree(x, y, z));  // 나무 리스트에 추가
  }&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;A&lt;/code&gt; 배열에 양분 정보를 입력받고, 각 칸의 초기 양분을 5로 설정한다.&lt;/li&gt;
&lt;li&gt;나무의 위치와 나이를 받아 &lt;code&gt;Tree&lt;/code&gt; 객체로 저장한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;시뮬레이션 실행&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;  for (int i = 0; i &amp;lt; K; i++) {
      spring();  // 봄
      summer();  // 여름
      fall();    // 가을
      winter();  // 겨울
      Collections.sort(plant, (o1, o2) -&amp;gt; o1.age - o2.age);  // 나이순으로 정렬
  }
  System.out.println(plant.size());  // K년 후 살아남은 나무의 개수 출력&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;K&lt;/code&gt;년 동안 봄, 여름, 가을, 겨울의 시뮬레이션을 차례로 실행한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;(2) 계절별 함수 구현&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;spring 함수&lt;/strong&gt;: 봄에는 나무가 자신의 나이만큼 양분을 먹고 나이가 1씩 증가한다. 만약 양분이 부족하면 그 나무는 죽는다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;  public static void spring() {
      for (int i = 0; i &amp;lt; plant.size(); i++) {
          Tree tree = plant.get(i);
          if (grid[tree.x][tree.y] &amp;lt; tree.age) {  // 양분 부족하면 나무 죽음
              deadTree.add(i);  // 죽은 나무 인덱스 저장
          } else {
              grid[tree.x][tree.y] -= tree.age;  // 양분 흡수
              tree.age++;  // 나이 증가
          }
      }
  }&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;summer 함수&lt;/strong&gt;: 여름에는 죽은 나무가 양분이 되어 땅에 반환된다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;  public static void summer() {
      while (!deadTree.isEmpty()) {
          Tree tree = plant.get(deadTree.poll());  // 죽은 나무 처리
          grid[tree.x][tree.y] += (tree.age / 2);  // 죽은 나무가 양분으로 변환
          tree.deadTree = true;  // 나무 상태를 죽은 나무로 표시
      }
  }&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;fall 함수&lt;/strong&gt;: 가을에는 나무가 번식한다. 나이가 5의 배수인 나무는 인접한 8방향으로 번식한다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;  public static void fall() {
      for (int i = 0; i &amp;lt; plant.size(); i++) {
          Tree tree = plant.get(i);
          if (tree.deadTree) continue;  // 죽은 나무는 번식하지 않음
          if (tree.age % 5 == 0) {  // 나이가 5의 배수인 나무 번식
              for (int d = 0; d &amp;lt; 8; d++) {
                  int nr = tree.x + dr[d];
                  int nc = tree.y + dc[d];
                  if (nr &amp;lt; 0 || nc &amp;lt; 0 || nr &amp;gt;= N || nc &amp;gt;= N) continue;  // 범위 체크
                  plant.add(new Tree(nr, nc, 1));  // 새로운 나무 추가
              }
          }
      }

      // 죽은 나무 제거
      ArrayList&amp;lt;Tree&amp;gt; newTree = new ArrayList&amp;lt;&amp;gt;();
      for (Tree tree : plant) {
          if (tree.deadTree) continue;
          newTree.add(tree);
      }
      plant = newTree;
  }&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;winter 함수&lt;/strong&gt;: 겨울에는 각 칸에 주어진 양분을 추가한다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;  public static void winter() {
      for (int i = 0; i &amp;lt; N; i++) {
          for (int j = 0; j &amp;lt; N; j++) {
              grid[i][j] += A[i][j];  // 추가 양분 더함
          }
      }
  }&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;5. &lt;span style='background-color: #fff5b1'&gt;전체 코드&lt;/span&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;package BOJ.Day0924.BOJ나무_재테크;

import java.io.*;
import java.util.*;

public class BOJ16235 {
    static int N, M, K;  // 땅의 크기, 나무의 개수, 몇 년 동안 진행할지
    static int[][] grid, A;  // 땅의 양분 상태, 추가 양분 정보
    static ArrayList&amp;lt;Tree&amp;gt; plant = new ArrayList&amp;lt;&amp;gt;();  // 나무 리스트
    static Queue&amp;lt;Integer&amp;gt; deadTree = new LinkedList&amp;lt;&amp;gt;();  // 죽은 나무의 인덱스
    static int[] dr = {-1, 1, 0, 0, -1, -1, 1, 1};  // 8방향
    static int[] dc = {0, 0, -1, 1, -

1, 1, -1, 1};

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());
        N = Integer.parseInt(st.nextToken());  // 땅의 크기
        M = Integer.parseInt(st.nextToken());  // 나무의 개수
        K = Integer.parseInt(st.nextToken());  // 몇 년 동안 진행할지
        grid = new int[N][N];
        A = new int[N][N];

        for (int i = 0; i &amp;lt; N; i++) {
            st = new StringTokenizer(br.readLine());
            for (int j = 0; j &amp;lt; N; j++) {
                A[i][j] = Integer.parseInt(st.nextToken());  // 추가 양분 정보
                grid[i][j] = 5;  // 처음 땅의 양분은 5
            }
        }

        for (int i = 0; i &amp;lt; M; i++) {
            st = new StringTokenizer(br.readLine());
            int x = Integer.parseInt(st.nextToken()) - 1;
            int y = Integer.parseInt(st.nextToken()) - 1;
            int z = Integer.parseInt(st.nextToken());  // 나무의 나이
            plant.add(new Tree(x, y, z));  // 나무 추가
        }
        Collections.sort(plant, (o1, o2) -&amp;gt; o1.age - o2.age);  // 나이순으로 정렬

        for (int i = 0; i &amp;lt; K; i++) {
            spring();  // 봄
            summer();  // 여름
            fall();    // 가을
            winter();  // 겨울
            Collections.sort(plant, (o1, o2) -&amp;gt; o1.age - o2.age);  // 나이순으로 재정렬
        }
        System.out.println(plant.size());  // K년 후 살아남은 나무의 개수 출력
    }

    // 봄: 나무가 자신의 나이만큼 양분을 먹고 나이가 1 증가한다. 양분이 부족하면 죽는다.
    public static void spring() {
        for (int i = 0; i &amp;lt; plant.size(); i++) {
            Tree tree = plant.get(i);
            if (grid[tree.x][tree.y] &amp;lt; tree.age) {  // 양분이 부족하면
                deadTree.add(i);  // 죽은 나무 인덱스 추가
            } else {
                grid[tree.x][tree.y] -= tree.age;  // 양분 흡수
                tree.age++;  // 나이 증가
            }
        }
    }

    // 여름: 죽은 나무가 양분이 되어 땅으로 돌아간다.
    public static void summer() {
        while (!deadTree.isEmpty()) {
            Tree tree = plant.get(deadTree.poll());  // 죽은 나무 처리
            grid[tree.x][tree.y] += (tree.age / 2);  // 죽은 나무의 나이 절반이 양분으로 변환
            tree.deadTree = true;  // 나무 상태를 죽은 나무로 표시
        }
    }

    // 가을: 나이가 5의 배수인 나무가 번식한다.
    public static void fall() {
        for (int i = 0; i &amp;lt; plant.size(); i++) {
            Tree tree = plant.get(i);
            if (tree.deadTree) continue;  // 죽은 나무는 번식하지 않음
            if (tree.age % 5 == 0) {  // 나이가 5의 배수인 나무 번식
                for (int d = 0; d &amp;lt; 8; d++) {
                    int nr = tree.x + dr[d];
                    int nc = tree.y + dc[d];
                    if (nr &amp;lt; 0 || nc &amp;lt; 0 || nr &amp;gt;= N || nc &amp;gt;= N) continue;  // 범위 체크
                    plant.add(new Tree(nr, nc, 1));  // 새로운 나무 추가
                }
            }
        }

        // 죽은 나무 제거
        ArrayList&amp;lt;Tree&amp;gt; newTree = new ArrayList&amp;lt;&amp;gt;();
        for (Tree tree : plant) {
            if (tree.deadTree) continue;
            newTree.add(tree);
        }
        plant = newTree;
    }

    // 겨울: 각 칸에 주어진 양분을 추가한다.
    public static void winter() {
        for (int i = 0; i &amp;lt; N; i++) {
            for (int j = 0; j &amp;lt; N; j++) {
                grid[i][j] += A[i][j];  // 양분 추가
            }
        }
    }
}

// 나무 클래스
class Tree {
    int x, y, age;
    boolean deadTree;  // 나무가 죽었는지 여부

    Tree(int x, int y, int age) {
        this.x = x;
        this.y = y;
        this.age = age;
    }
}&lt;/code&gt;&lt;/pre&gt;</description>
      <category>boj</category>
      <category>java</category>
      <category>오블완</category>
      <category>티스토리챌린지</category>
      <author>ofijwe</author>
      <guid isPermaLink="true">https://jhw29.tistory.com/241</guid>
      <comments>https://jhw29.tistory.com/241#entry241comment</comments>
      <pubDate>Fri, 8 Nov 2024 23:55:33 +0900</pubDate>
    </item>
    <item>
      <title>[DB] RDBMS의 기본</title>
      <link>https://jhw29.tistory.com/239</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;[테이블의 구성: 필드와 레코드]&lt;/h3&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;&lt;code&gt;필드타 타입&lt;/code&gt; : 각 필드로 사용 가능한 데이터 유형&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;828&quot; data-origin-height=&quot;847&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rthrz/btsKzyyJ4Fx/iCH8f9rlRTrKMoR4FVZ5g1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rthrz/btsKzyyJ4Fx/iCH8f9rlRTrKMoR4FVZ5g1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rthrz/btsKzyyJ4Fx/iCH8f9rlRTrKMoR4FVZ5g1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Frthrz%2FbtsKzyyJ4Fx%2FiCH8f9rlRTrKMoR4FVZ5g1%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;456&quot; height=&quot;847&quot; data-origin-width=&quot;828&quot; data-origin-height=&quot;847&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;키&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;code&gt;키&lt;/code&gt; : 테이블 내 특정 레코드를 식별할 수 있는 필드의 집합&lt;/li&gt;
&lt;li&gt;&lt;code&gt;후보키&lt;/code&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;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;복합키&lt;/code&gt; : 두 필드 이상으로 구성된 후보 키&lt;/li&gt;
&lt;li&gt;&lt;code&gt;슈퍼키&lt;/code&gt; : 레코드를 식별하기 위한 필드의 집합
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;유일성 만족, 최소성 만족 X&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;기본키&lt;/code&gt; : 레코드를 식별하도록 선정되어 테이블당 하나만 존재할 수 있는 키&lt;/li&gt;
&lt;li&gt;&lt;code&gt;대체키&lt;/code&gt; : 기본 키가 아닌 후보 키&lt;/li&gt;
&lt;li&gt;&lt;code&gt;외래키&lt;/code&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;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;하나의 레코드가 다른 테이블의 레코드 하나에만 대응되는 경우&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;2346&quot; data-origin-height=&quot;988&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nGZbF/btsKACAnXep/pxnkhTompll0o3Ei3OxSTK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nGZbF/btsKACAnXep/pxnkhTompll0o3Ei3OxSTK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nGZbF/btsKACAnXep/pxnkhTompll0o3Ei3OxSTK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FnGZbF%2FbtsKACAnXep%2FpxnkhTompll0o3Ei3OxSTK%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;622&quot; height=&quot;262&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;2346&quot; data-origin-height=&quot;988&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;일대다 대응 관계&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;하나의 레코드가 다른 테이블의 여러 레코드와 대응되는 경우&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;2310&quot; data-origin-height=&quot;1237&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/EmM6M/btsKBbISFQO/US3htaqErTrqR7gUsF5ga1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/EmM6M/btsKBbISFQO/US3htaqErTrqR7gUsF5ga1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/EmM6M/btsKBbISFQO/US3htaqErTrqR7gUsF5ga1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FEmM6M%2FbtsKBbISFQO%2FUS3htaqErTrqR7gUsF5ga1%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;611&quot; height=&quot;327&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;2310&quot; data-origin-height=&quot;1237&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;다대다 대응 관계&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;여러 레코드가 다른 테이블의 여러 레코드와 대응되는 경우&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1686&quot; data-origin-height=&quot;1848&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/L0Nr4/btsKBKqHsng/g1r9whnw9LgLZxjKXWTJ50/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/L0Nr4/btsKBKqHsng/g1r9whnw9LgLZxjKXWTJ50/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/L0Nr4/btsKBKqHsng/g1r9whnw9LgLZxjKXWTJ50/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FL0Nr4%2FbtsKBKqHsng%2Fg1r9whnw9LgLZxjKXWTJ50%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;512&quot; height=&quot;561&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1686&quot; data-origin-height=&quot;1848&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;</description>
      <category>STUDY/Database</category>
      <category>DB</category>
      <category>오블완</category>
      <category>티스토리챌린지</category>
      <author>ofijwe</author>
      <guid isPermaLink="true">https://jhw29.tistory.com/239</guid>
      <comments>https://jhw29.tistory.com/239#entry239comment</comments>
      <pubDate>Thu, 7 Nov 2024 23:52:51 +0900</pubDate>
    </item>
    <item>
      <title>[BOJ/Java] 컨베이어 벨트 위의 로봇 (20055)</title>
      <link>https://jhw29.tistory.com/234</link>
      <description>&lt;p&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/20055&quot;&gt;컨베이어 벨트 위의 로봇 (20055)&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;1. &lt;span style='background-color: #fff5b1'&gt;문제 분석&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;문제 개요&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;주어진 컨베이어 벨트 위에 로봇을 올리고, 로봇을 이동시키는 작업을 반복하면서 각 칸에 있는 내구도가 0이 되는 칸의 개수가 K개 이상이 될 때까지 반복을 수행한다. 각 단계에서 로봇을 이동시키고, 로봇을 올리며 내구도를 갱신하는 작업을 정확히 구현해야 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;입력 형식&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;첫 번째 줄에는 두 정수 N, K가 주어진다. N은 컨베이어 벨트의 반 개수, K는 내구도가 0인 칸이 되어야 하는 목표값이다.&lt;/li&gt;
&lt;li&gt;두 번째 줄에는 각 칸의 내구도가 주어진다. 각 칸의 내구도는 1 이상 100 이하의 자연수로 주어진다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;출력 형식&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;목표값 K에 도달할 때까지 진행된 단계를 출력한다. 즉, K개의 칸의 내구도가 0이 될 때까지의 횟수를 출력한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;2. &lt;span style='background-color: #fff5b1'&gt;알고리즘 종류&lt;/span&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;이 문제는 &lt;strong&gt;시뮬레이션 알고리즘&lt;/strong&gt;을 사용하는 문제이다. 해당 문제는 로봇의 이동과 내구도 갱신, 로봇의 배치 등을 정확하게 구현해야 하므로, 각 단계를 순차적으로 처리하면서 상태를 업데이트해야 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;3. &lt;span style='background-color: #fff5b1'&gt;주요 부분 및 코드 작성 방법&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;1. 회전 및 로봇의 이동&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;rotate&lt;/code&gt; 함수는 컨베이어 벨트를 한 칸 회전시키며, 벨트의 내구도 및 로봇 위치를 갱신한다. 회전 후, 로봇이 벨트에서 내려지게 된다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;move&lt;/code&gt; 함수는 로봇들을 한 칸씩 이동시키며, 이동한 칸의 내구도를 감소시킨다. 내구도가 0이 된 칸은 카운트된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;2. 로봇 배치&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;placeRobot&lt;/code&gt; 함수는 벨트의 첫 번째 칸에 로봇을 올릴 수 있는지 확인하고, 내구도를 감소시키면서 로봇을 배치한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;3. 내구도 체크&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;putdown&lt;/code&gt; 함수는 내구도가 0인 칸에서 로봇을 내린다. 이는 로봇이 더 이상 이동할 수 없게 되면 벨트에서 떨어지도록 처리된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;4. &lt;span style='background-color: #fff5b1'&gt;코드 설명&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;(1) 메인 함수 (&lt;code&gt;main&lt;/code&gt;)&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;입력 처리&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;  BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
  StringTokenizer st = new StringTokenizer(br.readLine());
  N = Integer.parseInt(st.nextToken());
  K = Integer.parseInt(st.nextToken());&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;첫 번째 줄에서 N과 K를 입력받는다. N은 컨베이어 벨트의 반 개수, K는 내구도가 0이 된 칸이 K개 이상이 될 때까지 진행되는 횟수이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;초기화 및 입력된 위치 저장&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;  conveyorBelt = new LinkedList&amp;lt;&amp;gt;();
  robots = new LinkedList&amp;lt;&amp;gt;();
  st = new StringTokenizer(br.readLine());
  for (int i = 0; i &amp;lt; N * 2; i++) {
      conveyorBelt.add(Integer.parseInt(st.nextToken()));
      robots.add(false);
  }&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;conveyorBelt&lt;/code&gt;와 &lt;code&gt;robots&lt;/code&gt;를 초기화한다. &lt;code&gt;conveyorBelt&lt;/code&gt;는 컨베이어 벨트의 내구도를 저장하고, &lt;code&gt;robots&lt;/code&gt;는 각 칸에 로봇이 있는지 여부를 저장한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;알고리즘 수행&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;  int result = 0;
  while (zeroCount &amp;lt; K) {
      result++;
      rotate();
      move();
      placeRobot();
  }
  System.out.println(result);&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;목표인 K개 이상의 내구도가 0인 칸을 만들 때까지 시뮬레이션을 반복한다. 각 단계마다 회전, 이동, 로봇 배치를 수행한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;(2) &lt;code&gt;rotate&lt;/code&gt; 함수&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;회전 처리&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;  conveyorBelt.addFirst(conveyorBelt.remove(conveyorBelt.size() - 1));
  robots.addFirst(robots.remove(robots.size() - 1));&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;컨베이어 벨트를 한 칸 회전시키고, 로봇의 위치도 회전시킨다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;내려놓기&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;  putdown();&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;회전 후, 내구도가 0인 칸에서 로봇을 내린다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;(3) &lt;code&gt;move&lt;/code&gt; 함수&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;로봇 이동 및 내구도 감소&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;  for (int i = N - 2; i &amp;gt;= 0; i--) {
      if (robots.get(i) &amp;amp;&amp;amp; !robots.get(i + 1) &amp;amp;&amp;amp; conveyorBelt.get(i + 1) &amp;gt; 0) {
          robots.set(i, false);
          robots.set(i + 1, true);
          conveyorBelt.set(i + 1, conveyorBelt.get(i + 1) - 1);
          if (conveyorBelt.get(i + 1) == 0) zeroCount++;
      }
  }&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;로봇이 이동할 수 있는지 확인하고, 이동시키며 내구도를 감소시킨다. 내구도가 0이 되면 &lt;code&gt;zeroCount&lt;/code&gt;를 증가시킨다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;내려놓기&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;  putdown();&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;내구도가 0인 칸에서 로봇을 내린다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;(4) &lt;code&gt;putdown&lt;/code&gt; 함수&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;로봇 내리기&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;  if (robots.get(N - 1)) robots.set(N - 1, false);&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;마지막 칸에 있는 로봇을 내린다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;(5) &lt;code&gt;placeRobot&lt;/code&gt; 함수&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;로봇 배치 및 내구도 감소&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;  if (conveyorBelt.get(0) &amp;gt; 0) {
      robots.set(0, true);
      conveyorBelt.set(0, conveyorBelt.get(0) - 1);
      if (conveyorBelt.get(0) == 0) zeroCount++;
  }&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;첫 번째 칸에 내구도가 0이 아닌 경우 로봇을 배치하고, 내구도를 감소시킨다. 내구도가 0이 되면 &lt;code&gt;zeroCount&lt;/code&gt;를 증가시킨다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;5. &lt;span style='background-color: #fff5b1'&gt;전체 코드&lt;/span&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;import java.io.*;
import java.util.*;

public class BOJ20055 {
    public static int N, K, zeroCount = 0;
    public static LinkedList&amp;lt;Integer&amp;gt; conveyorBelt;
    public static LinkedList&amp;lt;Boolean&amp;gt; robots;

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());

        N = Integer.parseInt(st.nextToken());
        K = Integer.parseInt(st.nextToken());

        conveyorBelt = new LinkedList&amp;lt;&amp;gt;();
        robots = new LinkedList&amp;lt;&amp;gt;();

        st = new StringTokenizer(br.readLine());
        for (int i = 0; i &amp;lt; N * 2; i++) {
            conveyorBelt.add(Integer.parseInt(st.nextToken()));
            robots.add(false);
        }

        int result = 0;
        while (zeroCount &amp;lt; K) {
            result++;
            rotate();  // 회전
            move();    // 로봇 이동
            placeRobot();  // 로봇 배치
        }
        System.out.println(result);  // 결과 출력
    }

    public static void rotate() {
        conveyorBelt.addFirst(conveyorBelt.remove(conveyorBelt.size() - 1));  // 컨베이어 벨트 회전
        robots.addFirst(robots.remove(robots.size() - 1));  // 로봇 위치 회전

        putdown();  // 로봇 내리기
    }

    public static void move() {
        for (int i = N - 2; i &amp;gt;= 0; i--) {
            if (robots.get(i) &amp;amp;&amp;amp; !robots.get(i + 1) &amp;amp;&amp;amp; conveyorBelt.get(i + 1) &amp;gt; 0) {
                robots.set(i, false);  // 현재 칸에서 로봇 내리기
                robots.set(i + 1, true);  // 다음 칸에 로봇 올리기
                conveyorBelt.set(i + 1, conveyorBelt.get(i + 1) - 1);  // 내구도 감소

                if (conveyorBelt.get(i + 1) == 0) zeroCount++;  // 내구도가 0이면 카운트 증가
            }
        }

        putdown();

  // 로봇 내리기
    }

    public static void putdown() {
        if (robots.get(N - 1)) robots.set(N - 1, false);  // 마지막 칸의 로봇 내리기
    }

    public static void placeRobot() {
        if (conveyorBelt.get(0) &amp;gt; 0) {
            robots.set(0, true);  // 첫 번째 칸에 로봇 올리기
            conveyorBelt.set(0, conveyorBelt.get(0) - 1);  // 내구도 감소

            if (conveyorBelt.get(0) == 0) zeroCount++;  // 내구도가 0이면 카운트 증가
        }
    }
}&lt;/code&gt;&lt;/pre&gt;</description>
      <category>CODING/BOJ</category>
      <category>boj</category>
      <category>java</category>
      <author>ofijwe</author>
      <guid isPermaLink="true">https://jhw29.tistory.com/234</guid>
      <comments>https://jhw29.tistory.com/234#entry234comment</comments>
      <pubDate>Tue, 5 Nov 2024 22:42:46 +0900</pubDate>
    </item>
    <item>
      <title>[우아한테크코스] 프리코스 3주차 회고록</title>
      <link>https://jhw29.tistory.com/232</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;image.png&quot; data-origin-width=&quot;2048&quot; data-origin-height=&quot;819&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cqHMPV/btsKyYXIXSZ/10uqkOFpGTEELOmEYkQb1k/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cqHMPV/btsKyYXIXSZ/10uqkOFpGTEELOmEYkQb1k/img.webp&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cqHMPV/btsKyYXIXSZ/10uqkOFpGTEELOmEYkQb1k/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcqHMPV%2FbtsKyYXIXSZ%2F10uqkOFpGTEELOmEYkQb1k%2Fimg.webp&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;2048&quot; height=&quot;819&quot; data-filename=&quot;image.png&quot; data-origin-width=&quot;2048&quot; data-origin-height=&quot;819&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프리코스 3주차를 마치며...&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 로또 미션은 지난 미션에서 적극적으로 사용했던 OOP의 특징과 TDD를 더 활용해 볼 수 있었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;미션의 시작 단계에서는 여전히 클래스 구조와 메소드 세분화에 대한 고민이 많았다. 이전보다 더 많아진 기능을 어떻게 세분화해야 할지 고민이 되었다. MVC 패턴을 잘 사용하고 싶은데 아직 어려운 것 같아 더 힘들었다. 또한, 어떻게 하면 코드의 가독성을 더 높이고 유지보수를 용이하게 할 수 있을지에 대한 생각이 많았던 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/jhw296/java-lotto-7/tree/hyewon&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://github.com/jhw296/java-lotto-7/tree/hyewon&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1730896099301&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;GitHub - jhw296/java-lotto-7&quot; data-og-description=&quot;Contribute to jhw296/java-lotto-7 development by creating an account on GitHub.&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/jhw296/java-lotto-7/tree/hyewon&quot; data-og-url=&quot;https://github.com/jhw296/java-lotto-7&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/cEDb0e/hyXwvNCPoP/ksF7gjWOELfZK7KChiVkBK/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/bbkAto/hyXwqyMIF8/dEfVKH9mXNeQgKk1XDiMVK/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/jhw296/java-lotto-7/tree/hyewon&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/jhw296/java-lotto-7/tree/hyewon&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/cEDb0e/hyXwvNCPoP/ksF7gjWOELfZK7KChiVkBK/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/bbkAto/hyXwqyMIF8/dEfVKH9mXNeQgKk1XDiMVK/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;GitHub - jhw296/java-lotto-7&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Contribute to jhw296/java-lotto-7 development by creating an account on GitHub.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;초기 단계에는 이전 미션을 바탕으로 익힌 기능별 클래스 구분 경험을 활용해 클래스를 작성했다. 이 과정에서 코드를 한 파일에 모두 작성하는 것이 아닌 기능별로 클래스를 나누어 구현하는 것이 얼마나 효율적인지를 실감했다. 따라서, 이번에도 기능별로 클래스를 구분해보기로 했다. 이때, 이번 미션에서는 새로운 방법인 MVC(Model View Controller) 패턴을 적용해보았다. MVC 패턴을 공부하며 해당 패턴을 사용하면 구조적 설계를 통해 코드의 명확성을 더 높일 수 있다는 것을 알게 되었다. 그래서 Model 클래스와 View 클래스, Controller 클래스를 사용해 구조를 설계했다. 확실히 각 기능별로만 클래스 구조가 작성되어있을 때보다 가독성이 좋은 것 같다는 느낌이 들었다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;570&quot; data-origin-height=&quot;295&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eomWxa/btsKzGhJ0go/SaYHUNR64PqatgOU44mgA1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eomWxa/btsKzGhJ0go/SaYHUNR64PqatgOU44mgA1/img.png&quot; data-alt=&quot;https://www.geeksforgeeks.org/mvc-design-pattern/&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eomWxa/btsKzGhJ0go/SaYHUNR64PqatgOU44mgA1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FeomWxa%2FbtsKzGhJ0go%2FSaYHUNR64PqatgOU44mgA1%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;570&quot; height=&quot;295&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;570&quot; data-origin-height=&quot;295&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://www.geeksforgeeks.org/mvc-design-pattern/&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;또한, TDD를 제대로 하기 위해 테스트 케이스를 꼼꼼히 작성해 보았다. 이후 중반부에 들어서면서 작성했던 테스트 케이스를 바탕으로 코드를 작성해 테스트 도구를 활용해 코드를 검증했다. 이전 미션에서 테스트 케이스를 작성할 때는 예외 처리에 대한 테스트 케이스만 작성했었다.&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;261&quot; data-origin-height=&quot;221&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/yke8e/btsKxHbrFHO/U4LjQrAquraf08lSG3w0l0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/yke8e/btsKxHbrFHO/U4LjQrAquraf08lSG3w0l0/img.png&quot; data-alt=&quot;https://testdriven.io/test-driven-development/&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/yke8e/btsKxHbrFHO/U4LjQrAquraf08lSG3w0l0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fyke8e%2FbtsKxHbrFHO%2FU4LjQrAquraf08lSG3w0l0%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;299&quot; height=&quot;253&quot; data-origin-width=&quot;261&quot; data-origin-height=&quot;221&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://testdriven.io/test-driven-development/&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;마지막으로 이번 미션을 통해 MVC 패턴을 사용해봤는데 아직은 확실히 미숙한 것 같다. 다음 미션에서는 조금 더 공부해서 더 나은 구조를 작성해보면 좋을 것 같다. 또한, 프로젝트 구조를 모두 작성하고 나서 &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;테스트 케이스를 작성했다. 하지만, 생각해보니 프로젝트 구조를 작성하기 전에 다양한 테스트 케이스를 생각해 본 후 이때, 정리된 기능들을 바탕으로 구조를 작성하는 것이 더 좋을 것 같다는 생각이 들었다. 따라서 다음 미션에서는&lt;/span&gt; TDD와 리팩토링의 중요성을 더욱 신경 써야 할 것 같다고 생각했다. 또한, 전체적인 흐름을 이해하고 코드를 작성하는 데 있어 체계적인 접근이 필요하다는 것을 느껴 다음 미션에서는 적극적으로 배운 내용들을 활용해볼 생각이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://translucent-mitten-47f.notion.site/3-1331304e880280d59c6dc21a2d0f55bf?pvs=4&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://translucent-mitten-47f.notion.site/3-1331304e880280d59c6dc21a2d0f55bf?pvs=4&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1730897196350&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;3주차 - 로또 | Notion&quot; data-og-description=&quot;1️⃣&amp;nbsp;Todos&quot; data-og-host=&quot;translucent-mitten-47f.notion.site&quot; data-og-source-url=&quot;https://translucent-mitten-47f.notion.site/3-1331304e880280d59c6dc21a2d0f55bf?pvs=4&quot; data-og-url=&quot;https://translucent-mitten-47f.notion.site/3-1331304e880280d59c6dc21a2d0f55bf&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/b1lskc/hyXs4jSCPM/6aDM0xZKM4Kw9JJTwU1Dx1/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/e4JaH/hyXwqMjV0d/gtYfH9V76C7xsbPmVcl9s1/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630&quot;&gt;&lt;a href=&quot;https://translucent-mitten-47f.notion.site/3-1331304e880280d59c6dc21a2d0f55bf?pvs=4&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://translucent-mitten-47f.notion.site/3-1331304e880280d59c6dc21a2d0f55bf?pvs=4&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/b1lskc/hyXs4jSCPM/6aDM0xZKM4Kw9JJTwU1Dx1/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/e4JaH/hyXwqMjV0d/gtYfH9V76C7xsbPmVcl9s1/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;3주차 - 로또 | Notion&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;1️⃣&amp;nbsp;Todos&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;translucent-mitten-47f.notion.site&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-11-06 22.04.33.png&quot; data-origin-width=&quot;1532&quot; data-origin-height=&quot;438&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b7Rxnr/btsKz10bkc3/q86T8tvzbvvkbRchVfjsz1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b7Rxnr/btsKz10bkc3/q86T8tvzbvvkbRchVfjsz1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b7Rxnr/btsKz10bkc3/q86T8tvzbvvkbRchVfjsz1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb7Rxnr%2FbtsKz10bkc3%2Fq86T8tvzbvvkbRchVfjsz1%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;1532&quot; height=&quot;438&quot; data-filename=&quot;스크린샷 2024-11-06 22.04.33.png&quot; data-origin-width=&quot;1532&quot; data-origin-height=&quot;438&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>우테코</category>
      <author>ofijwe</author>
      <guid isPermaLink="true">https://jhw29.tistory.com/232</guid>
      <comments>https://jhw29.tistory.com/232#entry232comment</comments>
      <pubDate>Tue, 5 Nov 2024 14:38:43 +0900</pubDate>
    </item>
    <item>
      <title>[Java] 파일 입출력 (File/IO)</title>
      <link>https://jhw29.tistory.com/227</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;  노드스트림&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1️⃣ &lt;span style=&quot;background-color: #fff5b1;&quot;&gt;I/O와 Stream&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;I/O &amp;rarr; Input/Output&lt;/li&gt;
&lt;li&gt;데이터는 한쪽에서 주고 한쪽에서 받는 구조로 되어있음
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;입력과 출력의 끝단 &amp;rarr; 노드(node)&lt;/li&gt;
&lt;li&gt;두 노드를 연결하고 데이터를 전송할 수 있는 개념 &amp;rarr; 스트림(stream)&lt;/li&gt;
&lt;li&gt;스트림은 단방향 통신만 가능&lt;/li&gt;
&lt;li&gt;하나의 스트림으로 입력과 출력을 같이 처리할 수 X&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Node Stream의 종류와 naming&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Node stream &amp;rarr; node에 연결되는 스트림&lt;br /&gt;&lt;a href=&quot;https://nullnull.tistory.com/23&quot;&gt;JAVA 노드 스트림 &amp;amp; 보조 스트림&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2️⃣ &lt;span style=&quot;background-color: #fff5b1;&quot;&gt;InputStream과 Reader&lt;/span&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;InputStream의 주요 메서드&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;read() &amp;rarr; 데이터 읽어서 반환
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;public abstract int read() throws IOException &amp;rarr; byte 한 개씩 읽음&lt;/li&gt;
&lt;li&gt;public int read(byte b[]) throws IOException&lt;/li&gt;
&lt;li&gt;public int read(byte b[], int offset, int len) throws IOException&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;close() &amp;rarr; 스트림 종료해서 자원 반납
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;public void close() throws IOException&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Reader의 주요 메서드&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;read()
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;public int read() throws IOExction &amp;rarr; char 한 개씩 읽음&lt;/li&gt;
&lt;li&gt;public int read(char cbuf[] throws IOException &amp;rarr; buffer만큼 씩 읽음&lt;/li&gt;
&lt;li&gt;abstract public int read(char cbuf[], int off, int len) throws IOException&lt;/li&gt;
&lt;li&gt;public int read(java.nio.CharBuffer target) throws IOException&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;close()
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;public void close() throws IOException&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3️⃣ &lt;span style=&quot;background-color: #fff5b1;&quot;&gt;OutputStream과 Writer&lt;/span&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;OutputStream의 주요 메서드&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;write() &amp;rarr; 입력받은 내용을 byte, string 등으로 변환해서 출력&lt;/li&gt;
&lt;li&gt;close() &amp;rarr; 스트림 종료해서 자원 반납&lt;/li&gt;
&lt;li&gt;flush() &amp;rarr; 버퍼가 있는 스트림에서 버퍼 내용 출력 후 버퍼 clear&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Writer의 주요 메서드&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;write() &amp;rarr; 입력받은 내용을 char, string 등으로 변환해서 출력&lt;/li&gt;
&lt;li&gt;append() &amp;rarr; 출력 후 리턴&lt;/li&gt;
&lt;li&gt;close() &amp;rarr; 내부적으로 flush() 호출&lt;/li&gt;
&lt;li&gt;flush() &amp;rarr; 버퍼가 있는 스트림에서 버퍼 내용 출력 후 버퍼 clear&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4️⃣ &lt;span style=&quot;background-color: #fff5b1;&quot;&gt;노드 스트림 활용&lt;/span&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;File&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;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;File의 메서드&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;File() &amp;rarr; 파일 생성&lt;/li&gt;
&lt;li&gt;createNewFile() &amp;rarr; 새로운 물리적인 파일 생성&lt;/li&gt;
&lt;li&gt;mkdir() &amp;rarr; 새로운 디렉토리 생성&lt;/li&gt;
&lt;li&gt;mkdirs() &amp;rarr; 경로 상 없는 모든 디렉토리 생성&lt;/li&gt;
&lt;li&gt;delete() &amp;rarr; 파일 또는 디렉터리 삭제&lt;/li&gt;
&lt;li&gt;getName(), getPath(), getAbsolutePath(), getCanonicalPath() &amp;rarr; 이름, 경로, 절대 경로, 정식 경로 리턴&lt;/li&gt;
&lt;li&gt;isDirectory(), isFile() &amp;rarr; 디렉토리인지 파일인지 리턴&lt;/li&gt;
&lt;li&gt;length() &amp;rarr; 파일 길이 리턴&lt;/li&gt;
&lt;li&gt;listFiles() &amp;rarr; 파일이 디렉토리인 경우 자식 파일들을 File[]형태로 리턴&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;FileInputStream &amp;amp; FileOutputStream&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;FileInputStream() &amp;rarr; name 경로의 파일을 읽는 스트림 생성&lt;/li&gt;
&lt;li&gt;FileOuputStream() &amp;rarr; name 경로 파일에 출력하는 스트림 생성 / 기존 파일이 있다면 이어서 작성&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  보조스트림&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1️⃣ &lt;span style=&quot;background-color: #fff5b1;&quot;&gt;보조 스트림 개념과 종류&lt;/span&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;(Filter Stream, Processing Stream)
&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;스트림 체이닝(Stream Chaining) &amp;rarr; 필요에 따라 여러 보조 스트림 연결해서 사용 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;보조 스트림 종류&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;byte 스트림을 char 스트림으로 변환
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;InputStreamReader, OutputStreamWriter &amp;rarr; byte 기반&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;버퍼링을 통한 속도 향상
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;BufferedInputStream, BufferedOutputStream &amp;rarr; byte 기반&lt;/li&gt;
&lt;li&gt;BufferedReader, BufferedWriter &amp;rarr; char 기반&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;객체 전송
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;ObjectInputStream, ObjectOutputStrema &amp;rarr; byte 기반&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;생성 &amp;rarr; 이전 스트림을 생성자의 파라미터에 연결&lt;/li&gt;
&lt;li&gt;종료 &amp;rarr; 보조 스트림의 close()를 호출하면 노드 스트림의 close()까지 호출 됨.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;사용 스트림 결정과정&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;노드가 뭔지 &amp;rarr; 타입은 뭔지(byte? String?) &amp;rarr; 방향이 뭔지 &amp;rarr; 추가 기능이 필요한지&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2️⃣ &lt;span style=&quot;background-color: #fff5b1;&quot;&gt;보조 스트림 활용&lt;/span&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;InputStreamReader &amp;amp; OutputStreamWriter&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;byte 기반 스트림을 char 기반으로 변경해주는 스트림
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;문자열 관리하기 위해 byte 단위보다 char 단위가 유리&lt;/li&gt;
&lt;li&gt;키보드에서 입력받은 데이터 처리할 때 사용&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;변환 시 encoding 지정 가능
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;InputStramReader(), OutputStreamWriter()&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Buffered 계열&lt;/b&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;BufferedInputStream()&lt;/li&gt;
&lt;li&gt;BufferedOutputStream()&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;BufferedReader &amp;amp; BufferedWriter
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;BufferedReader() &amp;rarr; readLine()은 줄 단위로 데이터를 읽음&lt;/li&gt;
&lt;li&gt;BufferedWriter()&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3️⃣ &lt;span style=&quot;background-color: #fff5b1;&quot;&gt;객체 직렬화(serialization)&lt;/span&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;/li&gt;
&lt;li&gt;반대의 경우는 역 직렬화(deserialization)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;직렬화 되기 위한 조건&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Serializable 인터페이스 구현할 것&lt;/li&gt;
&lt;li&gt;클래스의 모든 멤버가 Serializable 인터페이스를 구현해야 함&lt;/li&gt;
&lt;li&gt;직렬화에서 제외하려는 멤버는 transient 선언&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;SerialVersionUID&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;직렬화할 때 UID와 역 직렬화할 때의 UID가 다를 경우 예외 발생&lt;/li&gt;
&lt;li&gt;직렬화되는 객체에 UID가 설정되지 않았을 경우 컴파일러가 자동 생성&lt;/li&gt;
&lt;li&gt;직렬화되는 객체에 대해 serialVersionUID 설정 권장&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4️⃣ &lt;span style=&quot;background-color: #fff5b1;&quot;&gt;ObjectInputStream &amp;amp; ObjectOutputStream&lt;/span&gt;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;5️⃣ &lt;span style=&quot;background-color: #fff5b1;&quot;&gt;Scanner &amp;amp; BufferedReader&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;char 형태의 데이터를 읽기위한 클래스들&lt;/li&gt;
&lt;li&gt;Scanner &amp;rarr; 자동 형변환을 지원하는 등 사용이 간편하지만 속도가 느림&lt;/li&gt;
&lt;li&gt;BufferedReader &amp;rarr; 직접 스트림을 구성해야 하는 등 번거롭지만 속도가 빠름&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>STUDY/Java</category>
      <category>file/io</category>
      <category>java</category>
      <author>ofijwe</author>
      <guid isPermaLink="true">https://jhw29.tistory.com/227</guid>
      <comments>https://jhw29.tistory.com/227#entry227comment</comments>
      <pubDate>Sun, 3 Nov 2024 12:25:18 +0900</pubDate>
    </item>
    <item>
      <title>[Java] 예외 (Exception)</title>
      <link>https://jhw29.tistory.com/225</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;  예외의 처리&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1️⃣ &lt;span style=&quot;background-color: #fff5b1;&quot;&gt;에러와 예외&lt;/span&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;/li&gt;
&lt;li&gt;exception handling(예외 처리)란?
&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;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2️⃣ &lt;span style=&quot;background-color: #fff5b1;&quot;&gt;예외 클래스의 계층&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;checked exception &amp;rarr; 예외에 대한 대처 코드가 없으면 컴파일이 진행되지 X&lt;/li&gt;
&lt;li&gt;unchecked exception &amp;rarr; 예외에대한 코드가 없더라도 컴파일은 진행됨&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3️⃣ &lt;span style=&quot;background-color: #fff5b1;&quot;&gt;Exception handling 기법&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;try{} catch() {}&lt;/li&gt;
&lt;li&gt;public class SimpleException { public static void main(String[] args) { int[] intArray = { 10 }; try { System.out.println(intArray[2]); } catch (ArrayIndexOutOfBoundsException e) { // 사고처리 System.out.println(e.getMessage()); e.printStackTrace(); } System.out.println(&quot;프로그램 종료합니다.&quot;); } }&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Throwable의 주요 메서드&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;public String getMessage() - 발생된 예외에 대한 구체적인 메시지 반환&lt;/li&gt;
&lt;li&gt;public Throwable getCause() - 예외의 원인이 되는 Throwable 객체 또는 null을 반환&lt;/li&gt;
&lt;li&gt;public void printStackTrace() - 예외가 발생된 메서드가 호출되기까지의 메서드 호출 스택을 출력 / 주로 디버깅의 수단으로 사용&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4️⃣ &lt;span style=&quot;background-color: #fff5b1;&quot;&gt;try-catch문 흐름&lt;/span&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;try-catch문 흐름&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;try 블록에서 예외 발생 시 JVM이 해당 Exception 클래스의 객체 생성 후 던짐(throw)&lt;/li&gt;
&lt;li&gt;던져진 exception을 처리할 수 있는 catch 블록에서 받은 후 처리&lt;/li&gt;
&lt;li&gt;정상적으로 처리되면 try-catch블록을 벗어나 다음 문장 진행&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;try 블록에서 어떠한 예외도 발생하지 않을 경우
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;catch 문을 거치지 않고 try-catch블록의 다음 흐름 문장 실행&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Checked Exception 처리&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;처리하지 않으면 컴파일 불가 : Checked Exception&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;public class CheckedExceptionHandling { public static void main(String[] args) { // TODO: 다음에서 발생하는 예외를 처리해보자. // 예외 처리를 위해 try-catch문 사용 try { Class&amp;lt;?&amp;gt; myclass = Class.forName(&quot;com.ssafy.day09.a_basic.SimpleException&quot;); // Unhandled exception type ClassNotFoundException 라는 에러 발생 System.out.println(myclass.getName()); } catch (ClassNotFoundException e) { e.printStackTrace(); } // END System.out.println(&quot;프로그램 정상 종료&quot;); } }&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;5️⃣ &lt;span style=&quot;background-color: #fff5b1;&quot;&gt;다중 exceptino handling&lt;/span&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;try 블록에서 여러 종류의 예외가 발생할 경우&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;하나의 try 블록에 여러 개의 catch 블록 추가 가능&lt;/li&gt;
&lt;li&gt;예외 종류별로 catch 블록 구성&lt;/li&gt;
&lt;li&gt;처리될 catch 문장을 찾을 때는 다형성이 적용됨&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;다중 catch 문장 작성 순성 유의 사항&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;상위 타입의 예외가 먼저 선언되는 경우 뒤에 등장하는 catch 블록 동작 기회 X
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Unreachable catch block for Exception&lt;/li&gt;
&lt;li&gt;상속 관계가 없는 경우는 무관&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;상속 관계에서는 작은 범위(자식)에서 큰 범위(조상)순으로 정의&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;FileNotFoundException의 상속 관계&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;java.lang.Object &amp;rarr; java.lang.Throwable &amp;rarr; java.lang.Exception &amp;rarr; java.lang.IOException &amp;rarr; java.lang.FileNotFoundException&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  try ~ catch ~ finally&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1️⃣ &lt;span style=&quot;background-color: #fff5b1;&quot;&gt;try ~ catch ~ finally 구문을 이용한 예외 처리&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;finally는 예외 발생 여부와 상관없이 언제나 실행
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;중간에 return을 만나는 경우도 finally 블록을 먼저 수행 후 리턴 실행&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;주요 목적 &amp;rarr; try 블록에서 사용한 리소스 반납&lt;/li&gt;
&lt;li&gt;생성한 시스템 자원 반납 필요
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;반납하지 않을 시 장래 resource leak 발생 가능 &amp;rarr; 반드시 close 처리&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;지저분할 수 밖에 없는 finally 블록
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;close 메서드 자체가 IOException 유발 가능&lt;/li&gt;
&lt;li&gt;FileInputStream 생성자에서 IOException 발생 시 fileInput은 null인 상황&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2️⃣ &lt;span style=&quot;background-color: #fff5b1;&quot;&gt;try ~ with ~resources&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;리소스의 자동 close 처리
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;try(리소스_타입1 res1 = 초기화; 리소스_타입2 res2 = 초기화; &amp;hellip;) {} catch() {}&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;try 선언문에 선언된 객체들에 대해 자동 close 호출(finally 역할)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;해당 객체들이 AutoCloseable interface를 구현할 것&lt;/li&gt;
&lt;li&gt;해당 객체는 try 블록에서 다시 할당될 수 X &amp;rarr; final 변수로 간주&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;주의점&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;확장된 rty&lt;del&gt;with&lt;/del&gt;resources 사용시 문장에 하나 이상의 catch 또는 finally 필요&lt;/li&gt;
&lt;li&gt;자동 생성되는 코드들이 실제로 어떻게 동작되는지 정확히 알아야 함.&lt;/li&gt;
&lt;li&gt;try&lt;del&gt;with&lt;/del&gt;resources문장은 nested try 블록을 구성&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;단순 VS 확장 try&lt;del&gt;with&lt;/del&gt;resources&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;단순 &amp;rarr; 그냥 쓰고 close만 할 경우 최적&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  throws 활용&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1️⃣ &lt;span style=&quot;background-color: #fff5b1;&quot;&gt;throws 키워드를 통한 처리 위임&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;method에서 처리해야 할 하나 이상의 예외를 호출한 곳으로 전달 (처리 위임)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;단순 전달(예외 없어지는 것 X)&lt;/li&gt;
&lt;li&gt;예외 전달받은 메서드는 다시 예외처리의 책임 발생&lt;/li&gt;
&lt;li&gt;처리하려는 예외 조상 타입으로 throws 처리 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;checked exception과 throws&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;checked exception &amp;rarr; 반드시 try~catch or throws 필요&lt;/li&gt;
&lt;li&gt;필요한 곳에서 try~catch 처리&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;runtime exception과 throws&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;runtime exception은 throws 하지 않아도 전달됨.&lt;/li&gt;
&lt;li&gt;but, 결국 try~catch로 처리해야 함.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;로그 분석과 예외의 추적&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Throwable의 printStackTrace는 메서드 호출 스택 정보 조회 가능
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;최초 호출 메서드부터 예외 발생 메서드까지 스택 정보출력&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;확인해야할 정보
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;예외 종류 &amp;rarr;어떤 예외인지&lt;/li&gt;
&lt;li&gt;예외 원인 &amp;rarr; 예외 객체의 메시지는 무엇인지&lt;/li&gt;
&lt;li&gt;디버깅 출발점 &amp;rarr; 어디서 발생했는지&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;throws의 목적과 API 활용&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;API가 제공하는 메서드는 사전 예외 발생 가능을 선언부에 명시 (예외 발생 - 예외 전파)&lt;/li&gt;
&lt;li&gt;프로그래머가 예외를 처리하도록 강요 (상황 인지 - 적절한 예외 처리)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2️⃣ &lt;span style=&quot;background-color: #fff5b1;&quot;&gt;메서드 재정의와 throws&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;메서드 오버라이드 5가지 role
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이름, 파라미터, 리턴타입, 접근제한자, 예외처리&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;메서드 재정의 시 조상 클래스 메서드가 던지는 예외보다 부모예외를 던질 수 X
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;즉, 부모가 치지 않은 사고를 자식이 칠 수 X&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3️⃣ &lt;span style=&quot;background-color: #fff5b1;&quot;&gt;예외 변환&lt;/span&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;/li&gt;
&lt;li&gt;쉽게 말해, 배송 측에서 받은 문제사항을 추가로 가공해주고 새로 가공된 걸 고객에게 전달해주는 것&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Exception Chaining&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;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  사용자 정의 예외&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1️⃣ &lt;span style=&quot;background-color: #fff5b1;&quot;&gt;사용자 정의 예외&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;API에 정의된 exception 외 필요에 따라 사용자 정의 예외 클래스 작성&lt;/li&gt;
&lt;li&gt;대부분 Exception or RuntimeException 클래스 상속받아 작성
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;checked exception 활용
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;명시적 예외 처리 or throws 필요&lt;/li&gt;
&lt;li&gt;코드 복잡 &amp;rarr; but, 오류 발생 가능성 낮음&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;runtime exception 활용
&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;코드 간결 &amp;rarr; but, 예외 처리 누락 가능성 발생&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&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;필요한 추가정보, 기능 활용 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&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;/ul&gt;
&lt;/li&gt;
&lt;li&gt;throws 메커니즘 이용
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;중간 호출 단계에서 return 불필요&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>STUDY/Java</category>
      <category>exception</category>
      <category>java</category>
      <author>ofijwe</author>
      <guid isPermaLink="true">https://jhw29.tistory.com/225</guid>
      <comments>https://jhw29.tistory.com/225#entry225comment</comments>
      <pubDate>Fri, 1 Nov 2024 18:02:39 +0900</pubDate>
    </item>
    <item>
      <title>[Java] 컬렉션 (Collection)</title>
      <link>https://jhw29.tistory.com/221</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;  List 계열&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1️⃣ &lt;span style=&quot;background-color: #fff5b1;&quot;&gt;자료구조&lt;/span&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;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2️⃣ &lt;span style=&quot;background-color: #fff5b1;&quot;&gt;배열&lt;/span&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;/li&gt;
&lt;li&gt;homeogeneous collection : 동일한 데이터 타입만 관리 가능&lt;/li&gt;
&lt;li&gt;Polymorphism
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Object를 이용하면 모든 객체 참조 가능 &amp;rarr; Collection Framework&lt;/li&gt;
&lt;li&gt;담을 땐 편리, 빼낼 땐 Object로만&lt;/li&gt;
&lt;li&gt;런타임에 실제 객체의 타입 확인 후 사용해야 하는 번거로움&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Generic을 이용한 타입 한정
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;컴파일 타임에 저장하려는 타입 제한 &amp;rarr; 형변환의 번거로움 제거&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3️⃣ &lt;span style=&quot;background-color: #fff5b1;&quot;&gt;Collection Framework&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;java.util 패키지
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;다수의 데이터를 쉽게 처리하는 방법 제공 &amp;rarr; DB처럼 CRUD 기능 중요&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Collection framework 핵심 interface
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;List : 입력 순서가 있는 데이터 집합&lt;/li&gt;
&lt;li&gt;Set : 입력 순서를 유지하지 않는 데이터의 집합&lt;/li&gt;
&lt;li&gt;Map : key와 value의 쌍으로 데이터를 관리하는 집합&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Collection interface (CRUD)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4️⃣ &lt;span style=&quot;background-color: #fff5b1;&quot;&gt;Collection Framework - List&lt;/span&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;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;li&gt;배열과 ArrayList
&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;가장 기본적인 형태의 자료 구조로 간단하며 사용이 쉬움&lt;/li&gt;
&lt;li&gt;접근 속도가 빠름&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;단점
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;크기를 변경할 수 X, 추가 데이터를 위해 새로운 배열을 만들고 복사해야 함&lt;/li&gt;
&lt;li&gt;비 순차적 데이터의 추가, 삭제에 많은 시간이 걸림&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;LinkedList
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;각 요소를 Node로 정의하고 Node는 다음 요소의 참조 값과 데이터로 구성됨&lt;/li&gt;
&lt;li&gt;각 요소가 다음 요소의 링크 정보를 가지며 연속적으로 구성될 필요 X&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&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;소량의 데이터를 가지고 사용할 경우 큰 차이 X&lt;/li&gt;
&lt;li&gt;정적인 데이터 활용, 단순한 데이터 조회 &amp;rarr; ArrayList&lt;/li&gt;
&lt;li&gt;동적인 데이터 추가, 삭제가 많은 작업 &amp;rarr; LinkedList&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;자료 삭제 시 주의사항
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;index를 이용한 for문
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;요소가 삭제되면 size가 줄어들기 때문에 index 차감 필요&lt;/li&gt;
&lt;li&gt;거꾸로 접근하면 자연스럽게 해결&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;forEach 문장은 Collection 크기가 불변해야함.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  Set 계열&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1️⃣ &lt;span style=&quot;background-color: #fff5b1;&quot;&gt;Set interface&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;입력 순서 관리 X, 주머니에 데이터를 넣는 형태&lt;/li&gt;
&lt;li&gt;데이터를 구별할 순서 X, 중복 허용 X&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  Map 계열&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1️⃣ &lt;span style=&quot;background-color: #fff5b1;&quot;&gt;Map interface&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Key와 Value를 하나의 Entry로 묶어서 데이터 관리
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Key : Object 형태로 데이터 중복을 허락 X&lt;/li&gt;
&lt;li&gt;Value : Object 형태로 데이터 중복 허락 O&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  정렬&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1️⃣ &lt;span style=&quot;background-color: #fff5b1;&quot;&gt;정렬&lt;/span&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;/li&gt;
&lt;li&gt;크기를 비교할 수 있는 요소를 가지는 Colection들만 정렬 가능
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;List 계열&lt;/li&gt;
&lt;li&gt;Set에서는 SortedSet의 자식 객체&lt;/li&gt;
&lt;li&gt;Map에서는 SortedMap의 자식 객체(key 기준)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Collections의 sort()를 이용한 정렬
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;sort(List&lt;code&gt;&amp;lt;T&amp;gt;&lt;/code&gt; list)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2️⃣ &lt;span style=&quot;background-color: #fff5b1;&quot;&gt;Comparator의 활용&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;객체가 Comparable을 구현하고 있지 않거나 사용자 정의 알고리즘으로 정렬하려는 경우&lt;/li&gt;
&lt;li&gt;sort(List&lt;code&gt;&amp;lt;T&amp;gt;&lt;/code&gt; list, Comparator&amp;lt;? Super T&amp;gt; c)&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-java&quot;&gt;  public interface Comparator&amp;lt;T&amp;gt; {
      int compare(T o1, T o2);
  }
  public class StringLengthComparator implements Comparator&amp;lt;String&amp;gt; {
      @Override
      public int compare(String o1, String o2) {
          int len1 = o1.length();
          int len2 = o2.length();
          return Integer.compare(len1, len2);
      }
  }

  public void StringLengthSort() {
      Collections.sort(names, new StringLengthComparator());
      System.out.println(names);
  }&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;1회성 객체 사용 시 anonymous inner class 사용
&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;code class=&quot;language-java&quot;&gt;Collections.sort(names, new StringLengthComparator());
Collections.sort(names, new Comparator&amp;lt;String&amp;gt;() {
  @Override
  public int compare(String o1, String o2) {
      return Integer.compare(o1.length(), o2.length());
  }
});&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;람다 표현식 이용&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-java&quot;&gt;Collections.sort(names, (o1, o2) -&amp;gt; {
  return Integer.compare(o1.length(), o2.length());
});&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  Lambda 표현식&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1️⃣ &lt;span style=&quot;background-color: #fff5b1;&quot;&gt;Lambda 식&lt;/span&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;/li&gt;
&lt;li&gt;기존의 anonymous inner class를 이용한 처리 방식을 간결하게 처리&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2️⃣ &lt;span style=&quot;background-color: #fff5b1;&quot;&gt;Lambda 표현식&lt;/span&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Lambda 식이 할당되는 인터페이스를 Lambda 식의 타겟 타입이라 함.&lt;/li&gt;
&lt;li&gt;타겟 타입은 abstract 메서드가 반드시 하나만 존재해야 함(default, static 등 무관)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;@FunctionalInterface
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;컴파일러가 하나의 abstract method만 있음을 체크&lt;/li&gt;
&lt;li&gt;그렇지 않을 경우 오류 발생 &amp;rarr; 안정적인 programming을 위한 option&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;abstract method가 2개 이상 존재하는 경우는 여전히 익명의 inner class 사용&lt;/li&gt;
&lt;li&gt;기본 Lambda 식 : @FunctionalInterface에 대한 구현체 작성법
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;(type variable_name[,&amp;hellip;]) &amp;rarr; {실행문;};&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3️⃣ &lt;span style=&quot;background-color: #fff5b1;&quot;&gt;Lambda 실행 블록에서의 변수 참조&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Lambda 식 내부에서의 this는 외부 클래스의 instacne
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;외부 클래스의 member 변수 : 접근제한자의 제약 없이 사용 가능&lt;/li&gt;
&lt;li&gt;외부 메서드의 local 변수 : final 키워드가 추가된 것으로 동작 &amp;rarr; read only&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4️⃣ &lt;span style=&quot;background-color: #fff5b1;&quot;&gt;함수형 프로그래밍&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;java.util.function package
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;일반적으로 객체지향의 java 프로그래밍은 메서드의 구조와 이름이 중요&lt;/li&gt;
&lt;li&gt;일반적인 함수형 프로그래밍 언어에서 함수의 타입은 구조적이며 이름이 불필요&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;5️⃣ &lt;span style=&quot;background-color: #fff5b1;&quot;&gt;표준 API&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;기본 제공 API 종류
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;자주 사용되는 함수적 표준 interface를 java.util.function package에 정의&lt;/li&gt;
&lt;li&gt;주로 메서드 또는 생성자의 parameter로 Lambda식을 제공하기 위함&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Consumer 계열
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;parameter는 있으며 return이 없는 형태&lt;/li&gt;
&lt;li&gt;parameter 타입에 따라 다양한 consumer 존재&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Supplier 계열
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;parameter는 없으며 return이 있는 형태&lt;/li&gt;
&lt;li&gt;retrun 타입에 따라 다양한 supplier 존재&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Function 계열
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;parameter와 return 값이 있는 형태&lt;/li&gt;
&lt;li&gt;parameter와 return type에 따라 다양한 인터페이스 존재&lt;/li&gt;
&lt;li&gt;주로 파라미터를 이용해 연산을 수행한 후 원하는 타입으로 반환하는 역할&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Operator 계열
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;function 계열과 유사: parameter와 return 값을 가짐&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Predicate 계열
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;parameter를 받고 boolean 타입을 리턴&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;6️⃣ &lt;span style=&quot;background-color: #fff5b1;&quot;&gt;메서드 참조와 생성자 참조&lt;/span&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&amp;lt;소유자&amp;gt;::&amp;lt;파라미터를 사용하는 소유자의 메서드&amp;gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&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;/ul&gt;
&lt;/li&gt;
&lt;li&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;/li&gt;
&lt;li&gt;특정 객체의 instance의 메서드 참조
&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;li&gt;생성자 참조
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;클래스명 :: new의 형식으로 생성자 참조&lt;/li&gt;
&lt;li&gt;파라미터의 개수, 타입에 의해 호출되는 생성자 결정&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  Stream API&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1️⃣ &lt;span style=&quot;background-color: #fff5b1;&quot;&gt;Stream&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;JDK 8에 추가된 java.util.stream package&lt;/li&gt;
&lt;li&gt;배열 및 Collection의 요소를 하나씩 참조해서 처리하는 목적
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;람다와 내부 반복자를 이용해 컬렉션을 다루는 코드 간결화&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Stream API 역할 및 특징
&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;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2️⃣ &lt;span style=&quot;background-color: #fff5b1;&quot;&gt;Stream 자료 처리&lt;/span&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;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;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;li&gt;각각의 중간 처리는 새로운 스트림을 리턴하여 builder 패턴 적용
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;기존 스트림의 내용을 수정하지 않음&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;최종 처리는 최종적으로 원하는 값을 반환 &amp;rarr; 한번 최종 처리 끝난 스트림 재사용 X&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Stream의 종류와 획득
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;java.util.stream package에 정의&lt;/li&gt;
&lt;li&gt;종류
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Stream - 객체 요소에 대한 처리&lt;/li&gt;
&lt;li&gt;IntStream, LongStream, DoubleStream - 각각 int, long, double 데이터 처리&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;획득
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Collection, 배열, File, Random 및 Stream 클래스의 static method로 생성&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3️⃣ &lt;span style=&quot;background-color: #fff5b1;&quot;&gt;중간 처리&lt;/span&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;/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;h3 data-ke-size=&quot;size23&quot;&gt;4️⃣ &lt;span style=&quot;background-color: #fff5b1;&quot;&gt;최종 처리&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;반복 - forEach()&lt;/li&gt;
&lt;li&gt;매칭&lt;/li&gt;
&lt;li&gt;통계 - count(), sum() &amp;hellip;&lt;/li&gt;
&lt;li&gt;집계(aggregate)&lt;/li&gt;
&lt;li&gt;사용자 정의 집계 처리 - reduce()&lt;/li&gt;
&lt;li&gt;조사 - findFirst(), findAny()&lt;/li&gt;
&lt;li&gt;결과 모으기 - collect()&lt;/li&gt;
&lt;li&gt;결과 모으기 - 분할(partioningBy())과 그룹핑(groupingBy())&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>STUDY/Java</category>
      <category>Collection</category>
      <category>java</category>
      <author>ofijwe</author>
      <guid isPermaLink="true">https://jhw29.tistory.com/221</guid>
      <comments>https://jhw29.tistory.com/221#entry221comment</comments>
      <pubDate>Wed, 30 Oct 2024 17:14:08 +0900</pubDate>
    </item>
    <item>
      <title>[우아한테크코스] 프리코스 중간 회고록</title>
      <link>https://jhw29.tistory.com/219</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;image.png&quot; data-origin-width=&quot;2048&quot; data-origin-height=&quot;819&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/1LpCb/btsKzLQQAnA/Wgit9Mzku5djqd9aSNQ9dk/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/1LpCb/btsKzLQQAnA/Wgit9Mzku5djqd9aSNQ9dk/img.webp&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/1LpCb/btsKzLQQAnA/Wgit9Mzku5djqd9aSNQ9dk/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F1LpCb%2FbtsKzLQQAnA%2FWgit9Mzku5djqd9aSNQ9dk%2Fimg.webp&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;2048&quot; height=&quot;819&quot; data-filename=&quot;image.png&quot; data-origin-width=&quot;2048&quot; data-origin-height=&quot;819&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;벌써 프리코스의 반이 지나갔다. 시간이 진짜 빠른 것 같은 느낌?&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;절반을 완주했다는 의미에서 중간 회고록을 작성하고 넘어가고자 한다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;지원서에 작성한 목표를 얼마나 달성하고 있다고 생각하나요? 그 이유는 무엇인가요?&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;작성한 목표를 일정에 맞춰 대부분 달성하고 있다고 생각합니다. 지원서 작성 당시 각 주차 별로 학습 목표를 설정했지만 단순히 &quot;객체지향 개념 학습&quot;과 같은 광범위한 목표만 세웠습니다. 이러한 부분은 목표를 달성하기 위한 과정에서 해이해질 수 있다고 생각했습니다. 따라서 목표를 구체적으로 세분화하여 진행할 필요성을 느꼈습니다. 이를 바탕으로 각 주차 별로 공부해야 하는 날짜를 지정했습니다. 아래와 같이 세부적인 주제로 목표를 세분화하였고 현재까지도 이를 잘 지켜가며 학습을 지속하고 있습니다.&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 176px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style4&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;width: 99.9999%; text-align: center; height: 19px;&quot; colspan=&quot;3&quot;&gt;&lt;b&gt;Java 학습&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;width: 33.3333%; height: 19px; text-align: center;&quot;&gt;&lt;b&gt;1주차 :&amp;nbsp;자바 기초와 객체지향 기본 이해&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 19px; text-align: center;&quot;&gt;&lt;b&gt;2주차: 객체지향 심화&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 19px; text-align: center;&quot;&gt;&lt;b&gt;3주차: 자바 응용과 예외 처리&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 138px;&quot;&gt;
&lt;td style=&quot;width: 33.3333%; height: 138px;&quot;&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;자바 기본 10/16&lt;/li&gt;
&lt;li&gt;추상화 (Abstraction) 10/18&lt;/li&gt;
&lt;li&gt;상속 (Inheritance) 10/20&lt;/li&gt;
&lt;/ul&gt;
&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 138px;&quot;&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;다형성 (Polymorphism) 10/24&lt;/li&gt;
&lt;li&gt;인터페이스 (Interface) 10/26&lt;/li&gt;
&lt;li&gt;제네릭 (Generic) 10/28&lt;/li&gt;
&lt;/ul&gt;
&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 138px;&quot;&gt;&lt;span&gt;&lt;br /&gt;&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;컬렉션 (Collection) 10/30&lt;/li&gt;
&lt;li&gt;예외 (Exception) 11/1&lt;/li&gt;
&lt;li&gt;파일 입출력 (File/IO) 11/3&lt;/li&gt;
&lt;/ul&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style4&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 100%; text-align: center;&quot; colspan=&quot;4&quot;&gt;&lt;b&gt;&amp;nbsp;『&lt;span style=&quot;font-size: 15px; color: #333333; font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;&lt;span style=&quot;font-size: 15px; color: #333333; font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;이것이 취업을 위한 컴퓨터 과학이다』 학습&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 25%; text-align: center;&quot;&gt;&lt;b&gt;1주차: DataStructure&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; text-align: center;&quot;&gt;&lt;b&gt;2주차: DataStructure &lt;br /&gt;&amp;amp; Network&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; text-align: center;&quot;&gt;&lt;b&gt;3주차: Network&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; text-align: center;&quot;&gt;&lt;b&gt;4주차: Database&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;자료구조의 큰 그림 10/17&lt;/li&gt;
&lt;li&gt;배열과 연결 리스트 10/19&lt;/li&gt;
&lt;li&gt;스택과 큐 10/21&lt;/li&gt;
&lt;li&gt;해시 테이블 10/23&lt;/li&gt;
&lt;/ul&gt;
&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;트리 10/25&lt;/li&gt;
&lt;li&gt;그래프 10/27&lt;/li&gt;
&lt;li&gt;네트워크의 큰 그림 10/29&lt;/li&gt;
&lt;li&gt;물리 계층과 데이터 링크 계층 10/30&lt;/li&gt;
&lt;/ul&gt;
&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;네트워크 계층 10/31&lt;/li&gt;
&lt;li&gt;전송 계층 11/2&lt;/li&gt;
&lt;li&gt;응용 계층 11/4&lt;/li&gt;
&lt;li&gt;프록시와 안정적인 트래픽 11/5&lt;/li&gt;
&lt;/ul&gt;
&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;데이터베이스의 큰 그림 11/6&lt;/li&gt;
&lt;li&gt;RDBMS의 기본 11/7&lt;/li&gt;
&lt;li&gt;SQL 11/8&lt;/li&gt;
&lt;li&gt;효율적 쿼리 11/9&lt;/li&gt;
&lt;li&gt;DB 설계 11/10&lt;/li&gt;
&lt;li&gt;NoSQL 11/11&lt;/li&gt;
&lt;/ul&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한, 가장 중요하게 생각했던 목표는 &lt;b&gt;기록&lt;/b&gt;이었습니다. 프리코스를 끝까지 완주하는 과정에 있었던 모든 일을 기록해 오래 기억할 수 있도록 하는 것이 중요하다고 생각했습니다. 이러한 목표를 달성하기 위해 노션과 블로그를 활용해 개발 과정과 개인 공부 과정을 기록하고 있습니다. 이를 통해 하루하루 작성한 목표를 지속적으로 점검하고 달성 상황을 확인하면서 프리코스의 방향성을 확실히 잡고 나아가고 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a title=&quot;우아한 테크코스 - 프리코스 기록지&quot; href=&quot;https://translucent-mitten-47f.notion.site/1201304e880280349921f33d54ca35d4?v=07dd6a2d2d4841a591a0b04614cacf37&amp;amp;pvs=4&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://translucent-mitten-47f.notion.site/1201304e880280349921f33d54ca35d4?v=07dd6a2d2d4841a591a0b04614cacf37&amp;amp;pvs=4&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1730717437565&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;우테코 프리코스 | Notion&quot; data-og-description=&quot;Made with Notion, the all-in-one connected workspace with publishing capabilities.&quot; data-og-host=&quot;translucent-mitten-47f.notion.site&quot; data-og-source-url=&quot;https://translucent-mitten-47f.notion.site/1201304e880280349921f33d54ca35d4?v=07dd6a2d2d4841a591a0b04614cacf37&amp;amp;pvs=4&quot; data-og-url=&quot;https://translucent-mitten-47f.notion.site/1201304e880280349921f33d54ca35d4&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/lPw84/hyXsWrUQZp/VGNJRPZRi1vyuR7NKeNK3k/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/OWFv4/hyXsZhQ4Y4/bsQSuyX3CJ2Jeo5AR4IsRk/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630&quot;&gt;&lt;a href=&quot;https://translucent-mitten-47f.notion.site/1201304e880280349921f33d54ca35d4?v=07dd6a2d2d4841a591a0b04614cacf37&amp;amp;pvs=4&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://translucent-mitten-47f.notion.site/1201304e880280349921f33d54ca35d4?v=07dd6a2d2d4841a591a0b04614cacf37&amp;amp;pvs=4&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/lPw84/hyXsWrUQZp/VGNJRPZRi1vyuR7NKeNK3k/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/OWFv4/hyXsZhQ4Y4/bsQSuyX3CJ2Jeo5AR4IsRk/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;우테코 프리코스 | Notion&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Made with Notion, the all-in-one connected workspace with publishing capabilities.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;translucent-mitten-47f.notion.site&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;지원서에 작성한 목표를 변경해야 한다고 생각하시나요? 그렇다면 그 이유와 어떤 목표로 변경하고 싶으신가요?&lt;/b&gt;&lt;/h4&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;따라서, 현재는 클린 코드 서적을 분석하는 것이 아닌 앞으로의 프로젝트에 필요한 Java와 CS 지식을 보다 탄탄히 다지는 것에 집중하고자 했습니다. 이렇게 함으로써, 앞으로의 미션에서 객체 지향 언어인 Java를 더 효율적으로 사용하고 프로젝트 개발에 필요한&amp;nbsp;CS 지식을 학습하고자 합니다. 특히, CS에서 중요한 자료 구조와 네트워크, 데이터베이스 같은 개념을 이해하고 적용하는 데 집중하여 프로젝트의 본질적인 부분을 완성도 높게 마무리할 수 있도록 하고자 합니다.&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;b&gt;프리코스를 진행하면서 눈에 띄는 변화나 깨달은 점이 있나요?&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프리코스를 2주 차까지 진행하며 크게 변화한 점은 두 가지가 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;첫째, 객체 지향 프로그래밍(OOP)에 대한 이해가 한층 깊어졌습니다. 이전에는 OOP의 기본 개념인 캡슐화와 상속, 다형성을 이론적으로만 알고 있었습니다. 이번 프리코스 미션을 통해 단순히 개념적으로 알고 있던 OPP 개념들을 이번 프리코스를 통해 실제로 적용해 보았습니다. 클래스를 설계하고 메서드를 정의하는 과정에서 기능에 따라 책임을 분리하고 어떻게 하면 재사용성을 높일 수 있는지를 학습했습니다. 이러한 경험을 이론적인 지식을 가지고 있을 때보다 실제로 미션을 진행하며 클래스와 메서드 설계해보며 보다 체계적으로 생각할 수 있게 되었습니다. 따라서, 앞으로의 미션에서도 코드의 유지보수성과 확장성을 높이는 데 큰 도움이 될 것이라 생각합니다.&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;둘째, 테스트 도구인 JUnit을 활용한 테스트 주도 개발(TDD)의 중요성을 깨달았습니다. 처음에는 테스트 코드 작성을 번거롭게 느꼈습니다. 막연히 제대로 동작되겠지? 코드를 작성하면서 수정하면 되겠지?라는 생각을 하고 있었던 것 같습니다. 하지만, 이번 기회를 통해 테스트 도구를 활용한 TDD 방식을 경험해 보면서 이러한 방법이 코드의 안정성과 품질을 향상시킨다는 것을 체감했습니다. 테스트를 통해 발견한 문제들은 코드 작성 조기에 해결하거나 예외 처리 함으로써 코드의 품질을 높이고 안정적으로 구동할 수 있었습니다.&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>
      <author>ofijwe</author>
      <guid isPermaLink="true">https://jhw29.tistory.com/219</guid>
      <comments>https://jhw29.tistory.com/219#entry219comment</comments>
      <pubDate>Tue, 29 Oct 2024 14:56:19 +0900</pubDate>
    </item>
    <item>
      <title>[우아한테크코스] 프리코스 2주차 회고록</title>
      <link>https://jhw29.tistory.com/218</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;image.png&quot; data-origin-width=&quot;2048&quot; data-origin-height=&quot;819&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/EKoCQ/btsKxNCJtoQ/zD6Qd99h6ukw05uk7UGK0K/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/EKoCQ/btsKxNCJtoQ/zD6Qd99h6ukw05uk7UGK0K/img.webp&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/EKoCQ/btsKxNCJtoQ/zD6Qd99h6ukw05uk7UGK0K/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FEKoCQ%2FbtsKxNCJtoQ%2FzD6Qd99h6ukw05uk7UGK0K%2Fimg.webp&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;2048&quot; height=&quot;819&quot; data-filename=&quot;image.png&quot; data-origin-width=&quot;2048&quot; data-origin-height=&quot;819&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;프리코스 2주차를 마치며...&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이번 자동차 경주 미션은 객체 지향 프로그래밍과 테스트 주도 개발인 TDD를 실제로 적용해 볼 수 있었다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;시작 단계에서는 요구 사항을 이해하고 시스템 구조를 설계하는 과정에서 많은 어려움이 있었다. 전체적인 흐름과 각 기능이 어떻게 연관되어 있는지 파악하는 데 시간이 다소 걸렸다. 시간이 걸리더라도 최대한 완벽하게 개발하기 위해 1주 차 피드백을 살펴보고 요구 사항 세분화를 위해 글로 직접 작성해 보며 미션을 이해하기 위해 노력했다. 이를 통해 README를 작성하며 프로젝트의 목표와 방향성을 확실히 잡을 수 있었다. 하지만 처음 설계할 때 제대로 설계했다고 생각했는데 개발하다보니 점차 수정하고 추가해야 할 것들이 늘어나는 건 당연했다.  &amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/jhw296/java-racingcar-7/tree/hyewon&quot;&gt;https://github.com/jhw296/java-racingcar-7/tree/hyewon&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1730716086165&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;GitHub - jhw296/java-racingcar-7&quot; data-og-description=&quot;Contribute to jhw296/java-racingcar-7 development by creating an account on GitHub.&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/jhw296/java-racingcar-7/tree/hyewon&quot; data-og-url=&quot;https://github.com/jhw296/java-racingcar-7&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/BiXFX/hyXs5vz9BB/oUiM6kflSaonSjvTEyS6A0/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/j9Naj/hyXs1Ug8pl/va2OPmQMhSxO1175owkwh0/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/jhw296/java-racingcar-7/tree/hyewon&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/jhw296/java-racingcar-7/tree/hyewon&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/BiXFX/hyXs5vz9BB/oUiM6kflSaonSjvTEyS6A0/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/j9Naj/hyXs1Ug8pl/va2OPmQMhSxO1175owkwh0/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;GitHub - jhw296/java-racingcar-7&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Contribute to jhw296/java-racingcar-7 development by creating an account on GitHub.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;초기 단계에는 기능별로 클래스를 구분해 작성하는 방법을 익힐 수 있었다. 1주 차 미션을 진행할 때는 메소드는 여러 개로 나누어 코드를 작성했지만, 클래스를 나눌 생각은 못해 한 파일에 모든 코드를 다 작성했었다. 하지만, 이번 미션에서는 기능별로 클래스를 구분하기로 했다. 이 과정을 통해 코드를 한 파일에 모두 작성하는 것이 아니라 여러 개의 클래스를 통해 코드의 가독성을 높일 수 있었다. 특히, 유지보수할 때도 용이하다고 생각했다. 따라서, 기능별로 클래스를 나누어 구현하는 것이 얼마나 효율적인지를 실감했다. 이를 통해 객체 지향 언어의 특성으로 코드의 구조를 더욱 명확하게 할 수 있었던 점이 뿌듯했던 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;중반부에 들어서면서는 테스트 도구를 활용해 테스트 케이스를 작성하고 이를 통해 코드를 검증할 수 있었다. 처음에는 테스트 도구 자체를 처음 사용해봐서 어떻게 테스트 케이스를 작성해야 할지 막막했다. 우테코에서 제공해 준 문서와 다양한 자료를 찾아보며 기본적인 테스트 작성법을 익혔다. 하지만, 단순히 글로 적혀있는 문서를 보고 한 번에 테스트 도구를 익히는 것은 여전히 어려웠다. 따라서, ApplicationTest에 작성되어 있던 기존 코드를 바탕으로 코드를 분석하고 직접 실습을 통해 익히고자 했다. 이러한 방법은 오랜 시간이 소요되었지만 확실히 직접 작성해 보니 문서로 보았을 때보다 더 감을 빨리 잡을 수 있었다.&lt;/p&gt;
&lt;pre id=&quot;code_1730716067298&quot; class=&quot;java&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;class ApplicationTest extends NsTest {
    private static final int MOVING_FORWARD = 4;
    private static final int STOP = 3;

    @Test
    void 기능_테스트() {
        assertRandomNumberInRangeTest(
            () -&amp;gt; {
                run(&quot;pobi,woni&quot;, &quot;1&quot;);
                assertThat(output()).contains(&quot;pobi : -&quot;, &quot;woni : &quot;, &quot;최종 우승자 : pobi&quot;);
            },
            MOVING_FORWARD, STOP
        );
    }

    @Test
    void 예외_테스트() {
        assertSimpleTest(() -&amp;gt;
            assertThatThrownBy(() -&amp;gt; runException(&quot;pobi,javaji&quot;, &quot;1&quot;))
                .isInstanceOf(IllegalArgumentException.class)
        );
    }

    @Override
    public void runMain() {
        Application.main(new String[]{});
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;후반부로 넘어가면서는 1주차와 마찬가지로 리팩토링을 통해 코드의 품질을 더욱 높일 수 있었다. 초기 구현 단계에서 작성한 코드는 가독성이 떨어지는 부분들이 있었다. 가독성이 떨어지는 부분은 API를 사용하거나 불필요한 부분을 삭제했다. 작성했던 코드를 여러번 다시 분석하며 최적화를 위해 노력했다. 또한, 코드에서 발생하는 이슈를 파악하고 해결하는 과정에서 TDD의 중요성과 테스트 도구의 활용법을 더욱 확실히 이해하게 되었다. 이 과정을 통해 실제로 코드의 문제점을 사전에 발견하고 수정할 수 있다는 점을 실감했다. 개발하며 코드를 변경해도 테스트를 해보며 버그를 사전에 예방하는 방법을 배우게 되었고 개발 과정에 자신감도 얻을 수 있었던 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마지막으로 이번 미션을 통해 앞으로의 개발에서는 테스트 도구의 활용과 리팩토링을 더 중요시 해야겠다는 다짐을 했다. 또한, 전체적인 흐름을 이해하고 코드를 작성하는 데 있어 체계적인 접근이 필요하다는 것도 느꼈다. 이번에 배운 내용을 숙지해 3주 차 프로젝트에도 객체 지향 프로그래밍과 TDD를 적극 활용하여 더 나은 코드를 작성해야겠다는 생각을 했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://translucent-mitten-47f.notion.site/2-1281304e88028064bd3eeda3d079218a?pvs=4&quot;&gt;https://translucent-mitten-47f.notion.site/2-1281304e88028064bd3eeda3d079218a?pvs=4&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1730716098277&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;2주차 - 자동차 경주 | Notion&quot; data-og-description=&quot;1️⃣&amp;nbsp;Todos&quot; data-og-host=&quot;translucent-mitten-47f.notion.site&quot; data-og-source-url=&quot;https://translucent-mitten-47f.notion.site/2-1281304e88028064bd3eeda3d079218a?pvs=4&quot; data-og-url=&quot;https://translucent-mitten-47f.notion.site/2-1281304e88028064bd3eeda3d079218a&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/PyZse/hyXs44wbH4/MyaO1jcz7AnXt5E4q35h2K/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/C63fp/hyXsYwtEqq/X6lKYNWQ9Jol8kxCEb7kJk/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/bAqvHu/hyXpwgOvV4/5scv9rK37yC2lukxLwKwhk/img.png?width=1280&amp;amp;height=640&amp;amp;face=558_424_646_512&quot;&gt;&lt;a href=&quot;https://translucent-mitten-47f.notion.site/2-1281304e88028064bd3eeda3d079218a?pvs=4&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://translucent-mitten-47f.notion.site/2-1281304e88028064bd3eeda3d079218a?pvs=4&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/PyZse/hyXs44wbH4/MyaO1jcz7AnXt5E4q35h2K/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/C63fp/hyXsYwtEqq/X6lKYNWQ9Jol8kxCEb7kJk/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/bAqvHu/hyXpwgOvV4/5scv9rK37yC2lukxLwKwhk/img.png?width=1280&amp;amp;height=640&amp;amp;face=558_424_646_512');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;2주차 - 자동차 경주 | Notion&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;1️⃣&amp;nbsp;Todos&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;translucent-mitten-47f.notion.site&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-11-06 22.04.08.png&quot; data-origin-width=&quot;1538&quot; data-origin-height=&quot;436&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qM0cd/btsKxLkyYQl/nTzY0coKzkzph0DJoJUerK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qM0cd/btsKxLkyYQl/nTzY0coKzkzph0DJoJUerK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qM0cd/btsKxLkyYQl/nTzY0coKzkzph0DJoJUerK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqM0cd%2FbtsKxLkyYQl%2FnTzY0coKzkzph0DJoJUerK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1538&quot; height=&quot;436&quot; data-filename=&quot;스크린샷 2024-11-06 22.04.08.png&quot; data-origin-width=&quot;1538&quot; data-origin-height=&quot;436&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>우테코</category>
      <author>ofijwe</author>
      <guid isPermaLink="true">https://jhw29.tistory.com/218</guid>
      <comments>https://jhw29.tistory.com/218#entry218comment</comments>
      <pubDate>Mon, 28 Oct 2024 20:19:30 +0900</pubDate>
    </item>
  </channel>
</rss>