<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>Hyeonjoon's code</title>
    <link>https://joon0112.tistory.com/</link>
    <description>스프링이랑 자바 공부 중 입니다!!</description>
    <language>ko</language>
    <pubDate>Tue, 21 Jul 2026 10:38:07 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>dev_Hyeonjoon</managingEditor>
    <image>
      <title>Hyeonjoon's code</title>
      <url>https://tistory1.daumcdn.net/tistory/5810396/attach/3e4f7b47c95b4f3eb169993ce5be3434</url>
      <link>https://joon0112.tistory.com</link>
    </image>
    <item>
      <title>모듈식 모놀리스와 헥사고날 아키텍처로 구성된 Nearby 서버 구조 분석하기</title>
      <link>https://joon0112.tistory.com/85</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;아키텍처 선택 이유&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SOPT에서 세미나, 솝커톤, 합동 세미나 모두 모두 레이어드 아키텍처를 사용해왔다. 하지만 이번 AppJam에서는 새로운 구조를 직접 경험하고, 기존 방식과 어떤 차이가 있는지 알아보고 싶었다.&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://tech.kakaobank.com/posts/2507-legacy-to-modular-monolith-with-spring-modulith/&quot;&gt;다음 글&lt;/a&gt;이었다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;미리 회고하자면&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아키텍처를 선택한 이후 가장 큰 문제는 이를 실제 코드로 구현하는 방법이었다. 팀 내에 모듈식 모놀리스와 헥사고날 아키텍처를 충분히 경험해 본 사람이 없었기 때문에, 명확한 기준 없이 구조를 만들어가야 했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로젝트를 진행하면서 모듈식 모놀리스에서는 단순히 Gradle 모듈이나 패키지를 여러 개로 나누는 것보다, 먼저 도메인의 경계와 각 도메인의 책임을 명확하게 정의하는 것이 중요하다는 점을 알게 되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음부터 모듈식 모놀리스를 적용하기보다는 하나의 모놀리스로 시작해 도메인에 대한 이해가 충분히 쌓인 이후, 경계를 기준으로 모듈을 분리하는 접근도 있다는 사실도 뒤늦게 알게 되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 우리 팀은 초기에 도메인 영역과 책임을 충분히 나누지 못한 상태에서 구조를 먼저 설계했다. 여기에 해당 아키텍처에 대한 경험 부족까지 겹치면서 모듈의 책임이 불분명해지거나, 의존성의 방향이 의도와 다르게 구성되는 등 여러 시행착오를 겪었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결국 새로운 아키텍처를 선택하는 것보다 더 중요한 것은, 해당 아키텍처가 해결하려는 문제가 무엇인지 이해하고 프로젝트의 도메인에 맞게 적용하는 것이라는 점을 배울 수 있었다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;구조 분석하기&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;adapter-in/web: HTTP 요청을 받는 곳&lt;/li&gt;
&lt;li&gt;application: 도메인 모델과 핵심 업무 규칙, 유스케이스, Port를 정의하는 애플리케이션 코어&lt;/li&gt;
&lt;li&gt;adapter-out/persistence: DB에 접근하는 곳&lt;/li&gt;
&lt;li&gt;bootstrap: 각 모듈을 조립하고 애플리케이션을 실행하는 곳&lt;/li&gt;
&lt;li&gt;common, logging: 공통 기능&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선 모듈 구조는 위와 같이 나누게 되었다. 이렇게 나눈 이유는 아래 사진처럼 헥사고날 구조를 가져가기 위함이였다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;980&quot; data-origin-height=&quot;613&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ND0CK/dJMcaiYiKmj/sFItb0aK4ptME48ntFAfX1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ND0CK/dJMcaiYiKmj/sFItb0aK4ptME48ntFAfX1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ND0CK/dJMcaiYiKmj/sFItb0aK4ptME48ntFAfX1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FND0CK%2FdJMcaiYiKmj%2FsFItb0aK4ptME48ntFAfX1%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;980&quot; height=&quot;613&quot; data-origin-width=&quot;980&quot; data-origin-height=&quot;613&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;헥사고날의 특징이라고 하면 핵심 비즈니스 로직을 데이터베이스, API, 사용자 인터페이스와 같은 외부 시스템과 분리하는 소프트웨어 설계 접근 방식이라고 할 수 있다. 이를 통해 유연하고 유지 관리가 용이하며 테스트가 간편한 애플리케이션을 구축할 수 있게 된다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1672&quot; data-origin-height=&quot;941&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/8K0Ly/dJMcai44UVe/0SgrAFkRG32yfbddd9Em7K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/8K0Ly/dJMcai44UVe/0SgrAFkRG32yfbddd9Em7K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/8K0Ly/dJMcai44UVe/0SgrAFkRG32yfbddd9Em7K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F8K0Ly%2FdJMcai44UVe%2F0SgrAFkRG32yfbddd9Em7K%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;1672&quot; height=&quot;941&quot; data-origin-width=&quot;1672&quot; data-origin-height=&quot;941&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Nearby는&lt;/b&gt; Google Maps 장소 검색, 카카오 인증, Solapi 문자 발송, S3 이미지 저장 및 JPA&amp;middot;Redis 영속성 처리를 어댑터로 분리했다. 이를 통해 동행 신청, 매칭, 일정 확정과 같은 핵심 비즈니스 규칙을 외부 기술의 변화와 분리하고, 실제 외부 시스템 없이도 유스케이스를 독립적으로 테스트할 수 있도록 했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rarr; 외부 시스템과의 상호작용을 Port 인터페이스로 추상화하여, 핵심 비즈니스 로직이 JPA, Redis, 외부 API와 같은 구체적인 기술 구현에 직접 의존하지 않도록 하는 것이 핵심!&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;최종 Gradle 모듈 구조&lt;/h3&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;nearby
├── bootstrap
├── application
├── adapter-in
│   └── web
├── adapter-out
│   ├── persistence
│   └── security
├── common
└── logging&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;모듈별 구조&lt;/h3&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 555px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style12&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 22px;&quot;&gt;
&lt;td style=&quot;height: 22px;&quot;&gt;모듈&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;height: 22px;&quot;&gt;책임&lt;/td&gt;
&lt;td style=&quot;height: 22px;&quot;&gt;&amp;nbsp;판단 근거&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 66px;&quot;&gt;
&lt;td style=&quot;height: 66px;&quot;&gt;bootstrap&lt;/td&gt;
&lt;td style=&quot;height: 66px;&quot;&gt;Spring Boot 실행 진입점, 런타임 조립, 설정 로딩, Actuator, Spring Modulith 런타임 구성&lt;/td&gt;
&lt;td style=&quot;height: 66px;&quot;&gt;실행 가능한 애플리케이션을 만드는 책임은 비즈니스 코드나 어댑터 구현과 분리되어야 한다. 이 모듈만 Spring Boot 애플리케이션 플러그인을 사용한다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 66px;&quot;&gt;
&lt;td style=&quot;height: 66px;&quot;&gt;application&lt;/td&gt;
&lt;td style=&quot;height: 66px;&quot;&gt;도메인 모델, 업무 규칙, Outbound Port&lt;/td&gt;
&lt;td style=&quot;height: 66px;&quot;&gt;헥사고날 아키텍처의 중심은 외부 기술에 의존하지 않는 애플리케이션 코어다. 현재는 도메인 모델과 Port가 중심이며, 추후 Use Case Service가 생기면 이 모듈에 둔다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 61px;&quot;&gt;
&lt;td style=&quot;height: 61px;&quot;&gt;adapter-in:web&lt;/td&gt;
&lt;td style=&quot;height: 61px;&quot;&gt;HTTP Controller, Request&amp;middot;Response DTO, Validation, 웹 예외 처리, Swagger 설정&lt;/td&gt;
&lt;td style=&quot;height: 61px;&quot;&gt;HTTP 요청은 애플리케이션 코어로 들어오는 Inbound Adapter다. Spring MVC와 OpenAPI 의존성은 이 모듈 안에 머무는 것이 적절하다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 154px;&quot;&gt;
&lt;td style=&quot;height: 154px;&quot;&gt;adapter-out:persistence&lt;/td&gt;
&lt;td style=&quot;height: 154px;&quot;&gt;JPA Entity, Spring Data Repository, Redis, Persistence Mapper, Outbound Port 구현&lt;/td&gt;
&lt;td style=&quot;height: 154px;&quot;&gt;데이터 저장소는 애플리케이션 코어가 의존하면 안 되는 외부 기술이다. JPA와 Redis 의존성을 별도의 Outbound Adapter에 둔다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 66px;&quot;&gt;
&lt;td style=&quot;height: 66px;&quot;&gt;adapter-out:security&lt;/td&gt;
&lt;td style=&quot;height: 66px;&quot;&gt;Spring Security 기반 인증&amp;middot;인가 구현&lt;/td&gt;
&lt;td style=&quot;height: 66px;&quot;&gt;보안 구현은 Persistence와는 다른 기술 영역이다. 인증 필터, Security Context, Token 처리 등의 책임이 커질 수 있으므로 별도 Outbound Adapter로 분리한다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 44px;&quot;&gt;
&lt;td style=&quot;height: 44px;&quot;&gt;common&lt;/td&gt;
&lt;td style=&quot;height: 44px;&quot;&gt;여러 모듈에서 공유할 수 있는 안정적인 예외와 Port 보조 타입&lt;/td&gt;
&lt;td style=&quot;height: 44px;&quot;&gt;특정 Feature나 기술 구현에 종속되지 않는 계약만 둔다. 단순히 편리하다는 이유로 코드를 모아두는 장소로 사용하지 않는다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 66px;&quot;&gt;
&lt;td style=&quot;height: 66px;&quot;&gt;logging&lt;/td&gt;
&lt;td style=&quot;height: 66px;&quot;&gt;MDC, Request ID, 요청 로그 필터, 민감 정보 마스킹&lt;/td&gt;
&lt;td style=&quot;height: 66px;&quot;&gt;로깅은 업무 규칙이 아닌 횡단 관심사이자 인프라 책임이다. Spring Web과 Servlet Filter에 의존하므로 common이 아닌 별도 모듈로 분리하는 것이 적절하다.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;의존 방향&lt;/h3&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;bootstrap -&amp;gt; adapter-in:web
bootstrap -&amp;gt; adapter-out:persistence
bootstrap -&amp;gt; adapter-out:security
bootstrap -&amp;gt; application
bootstrap -&amp;gt; common
bootstrap -&amp;gt; logging

adapter-in:web -&amp;gt; application
adapter-in:web -&amp;gt; common
adapter-in:web -&amp;gt; logging

adapter-out:persistence -&amp;gt; application
adapter-out:persistence -&amp;gt; common
adapter-out:persistence -&amp;gt; logging

adapter-out:security -&amp;gt; application
adapter-out:security -&amp;gt; common
adapter-out:security -&amp;gt; logging

application -&amp;gt; common
logging -&amp;gt; common
common -&amp;gt; none&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;핵심 규칙은 application 이 외부 기술을 모르는 것이다.&lt;/li&gt;
&lt;li&gt;Spring Web, JPA, Redis, Security 의존성은 adapter 쪽에 있고, application은 port 인터페이스를 통해 필요한 기능만 표현한다&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Back-end/Architecture</category>
      <category>nearby</category>
      <category>백엔드</category>
      <category>아키텍처</category>
      <category>프로젝트</category>
      <category>헥사고날</category>
      <author>dev_Hyeonjoon</author>
      <guid isPermaLink="true">https://joon0112.tistory.com/85</guid>
      <comments>https://joon0112.tistory.com/85#entry85comment</comments>
      <pubDate>Fri, 17 Jul 2026 23:39:37 +0900</pubDate>
    </item>
    <item>
      <title>Appjam 전 간단한 프로젝트를 연습하려고 했었다...</title>
      <link>https://joon0112.tistory.com/84</link>
      <description>&lt;blockquote data-ke-style=&quot;style3&quot;&gt;사실... Appjam 합숙 전에 모든걸 다 끝내고 들어가려 했으나 못 했고 회고식아니면 나중에라도 더 구체화 시켜서 올려보려고 한다... 아래 있는 글들은 우선 먼저 적어놨던거라도 올리고자 이렇게 적게 되었다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/guswnsj0112/spring-auth-board&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://github.com/guswnsj0112/spring-auth-board&lt;/a&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;계기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 SOPT 38기 AppJam에서 운 좋게 Server로 참여 할 수 있게 되었다. 하지만 가장 큰 문제가 있었다. 바로 내가 백엔드를 올해 처음한다는 점이였다. 물론 파트장님께서는 세미나 때 친철하고 잘 알려주셨긴 했지만 학기 중 시간 관리를 못 했던 나에게는 아직 미숙한 부분이 많이 보였다. 그래서 Appjam 시작 전까지는 인증/인가, 엔터티 등 다양한걸 공부해서 가려고 한다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;구조&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선 서버 리드님과 상의했을 때 이번에 아키텍처를 모듈식 모놀리스로 가져가는게 어떻냐고 이야기 들었다. 나는 많은 걸 배우고 싶었기 때문에 좋다고 했고 그 후 계속 공부하면서 모듈식 아키텍처에 관해 배워가고 있다&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;학습 목표 설계&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1272&quot; data-origin-height=&quot;642&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bkmEeo/dJMcaixhiBL/DzaQ7ZpjaYiFUtbSRk3oAK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bkmEeo/dJMcaixhiBL/DzaQ7ZpjaYiFUtbSRk3oAK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bkmEeo/dJMcaixhiBL/DzaQ7ZpjaYiFUtbSRk3oAK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbkmEeo%2FdJMcaixhiBL%2FDzaQ7ZpjaYiFUtbSRk3oAK%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;1272&quot; height=&quot;642&quot; data-origin-width=&quot;1272&quot; data-origin-height=&quot;642&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선 GPT를 통해서 백엔드 프로젝트 목적을 세우게 되었다. 관련 레포는 &lt;a href=&quot;https://github.com/guswnsj0112/spring-auth-board&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;여기서&lt;/a&gt; 확인 가능하다. 이걸 본 후 ERD를 먼저 설계 하였다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;ERD&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1530&quot; data-origin-height=&quot;862&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/AJuBt/dJMcacRhJzO/3kQP77W2odJXqApanLHdM1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/AJuBt/dJMcacRhJzO/3kQP77W2odJXqApanLHdM1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/AJuBt/dJMcacRhJzO/3kQP77W2odJXqApanLHdM1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FAJuBt%2FdJMcacRhJzO%2F3kQP77W2odJXqApanLHdM1%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;1530&quot; height=&quot;862&quot; data-origin-width=&quot;1530&quot; data-origin-height=&quot;862&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;User 1 : N Post
User 1 : N Comment
User 1 : N PostLike
User 1 : 1 RefreshToken
Post 1 : N Comment
Post 1 : N PostLike
&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;리프레쉬 토큰은 한 유저 당 한개 씩으로 1:1 관계로 지정하였다&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;회원 가입 구현하기&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;User 엔티티&lt;/h3&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;@Entity
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Table(name = &quot;users&quot;)
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(unique = true)
    private String email;

    @Column(nullable = false)
    private String password;

    @Column(nullable = false)
    private String nickname;

    @Enumerated(EnumType.STRING)
    @Column(nullable = false)
    private Role role;

    public User(String email, String nickname, String password) {
        this.email = email;
        this.nickname = nickname;
        this.password = password;
        this.role = Role.USER;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;User 엔터티에 있는 role 에 관해 어떻게 작성해야할지 고민이 되었다&amp;hellip;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Role이 Enum인데 어디에 넣어야 하는가? 에 대한 고민이 들었는데&lt;/li&gt;
&lt;li&gt;&amp;rArr; User와 강하게 관련된 값임으로 Entity 패키지 안에 넣어두었다&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;어떤 방식으로 ENUM을 저장할 것 인지?
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이 방법은 DB에 순서에 따른 숫자로 저장되기 때문에 나중에 Role 추가 된다면 다른 Role로 지정될 수 있다&lt;/li&gt;
&lt;/ul&gt;
때문에 아래와 같은 방식을 사용하였다&lt;/li&gt;
&lt;li&gt;@Enumerated(EnumType.STRING)&lt;/li&gt;
&lt;li&gt;@Enumerated(EnumType.ORDINAL) private Role role;&lt;/li&gt;
&lt;li&gt;생성자에서 Role을 받으면 안된다..일반 회원가입은 무조건 User 임으로 User로 설정하자
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;회원가입할 때 사용자가 ADMIN 으로 가입하면 안되니까&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;public User(String email, String password, String nickname) { this.email = email; this.password = password; this.nickname = nickname; this.role = Role.USER; }&lt;/li&gt;
&lt;li&gt;생성자 실수처음에 그냥 @NoArgsConstructor 면 public 기본 생성자가 생기게 된다 이렇게 되면 아래와 같은 게 가능해진다이러면 email, password, nickname이 없는 불안전한 User가 만들어질 수 있다&lt;/li&gt;
&lt;li&gt;그래서 JPA용 기본 생성자는 열어두되, 외부에서는 막는 느낌으로 protected 를 많이 쓴다&lt;/li&gt;
&lt;li&gt;User user = new User();&lt;/li&gt;
&lt;li&gt;@NoArgsConstructor&lt;/li&gt;
&lt;/ol&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;암호화&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;핵심흐름&lt;/h3&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;요청 들어옴
&amp;rarr; JwtAuthenticationFilter 실행
&amp;rarr; Authorization Header에서 Bearer Token 추출
&amp;rarr; JWT 검증
&amp;rarr; userId 추출
&amp;rarr; Authentication 객체 생성
&amp;rarr; SecurityContextHolder에 저장
&amp;rarr; Controller/Service에서 로그인 유저 사용&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;의존성&lt;/h2&gt;
&lt;pre class=&quot;clean&quot;&gt;&lt;code&gt;implementation 'org.springframework.security:spring-security-crypto'
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;auth/build.gradle&lt;/p&gt;
&lt;pre class=&quot;clean&quot;&gt;&lt;code&gt;implementation 'org.springframework.boot:spring-boot-starter-security'
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;app/build.gradle&lt;/p&gt;
&lt;pre class=&quot;clean&quot;&gt;&lt;code&gt;implementation 'io.jsonwebtoken:jjwt-api:0.12.6'
runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.12.6'
runtimeOnly 'io.jsonwebtoken:jjwt-jackson:0.12.6'
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비밀번호 암호화만 auth에서 할 거면 spring-security-crypto를 auth에 둬도 되지만, &lt;b&gt;SecurityConfig와 Filter는 app에서 관리&lt;/b&gt;하는 게 깔끔하다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;pre class=&quot;java&quot;&gt;&lt;code&gt;@Configuration // 스프링 설정 클래스
public class PasswordEncoderConfig {
    //   BCryptPasswordEncoder를 Spring Bean으로 등록
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;@Bean을 사용하여 BCryptPasswordEncoder를 스프링 빈으로 등록&lt;/li&gt;
&lt;li&gt;이제 어디서든 DI(의존성 주입)를 통해 passwordEncoder를 사용할 수 있음&lt;/li&gt;
&lt;li&gt;BCryptPasswordEncoder는 비밀번호를 안전하게 해시화하고 검증하는 역할을 함&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rarr; 앞으로 PasswordEncoder가 필요하면 BCryptPasswordEncoder 객체를 주입해준다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 아래와 같이 AuthService에서 사용할 수 있다&lt;/p&gt;
&lt;pre class=&quot;java&quot;&gt;&lt;code&gt;@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class UserService {
    private final UserRepository userRepository;
    private final PasswordEncoder passwordEncoder;

    //회원가입
    @Transactional
    public User register(SignupUserRequest request) {

        if (userRepository.existsByEmail(request.email())) {
            throw new IllegalArgumentException(&quot;이미 존재하는 이메일입니다.&quot;);
        }

        String hashedPassword = passwordEncoder.encode(request.password());

        User savedUser = userRepository.save(new User(
                request.email(),
                request.nickName(),
                hashedPassword
        ));

        return savedUser;
    }
}

&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;공부 용임으로 User엔터티를 전체 반환했다&lt;/p&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;@Configuration
public class SecurityConfig {

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        return http
                .csrf(csrf -&amp;gt; csrf.disable())
                .headers(headers -&amp;gt; headers.frameOptions(frame -&amp;gt; frame.disable()))
                .authorizeHttpRequests(auth -&amp;gt; auth
                        .requestMatchers(
                                &quot;/swagger-ui.html&quot;,
                                &quot;/swagger-ui/**&quot;,
                                &quot;/v3/api-docs/**&quot;,
                                &quot;/api/auth/signup&quot;,
                                &quot;/api/auth/login&quot;,
                                &quot;/h2-console/**&quot;
                        ).permitAll()
                        .anyRequest().permitAll()
                )
                .formLogin(form -&amp;gt; form.disable())
                .httpBasic(basic -&amp;gt; basic.disable())
                .build();
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;dts&quot;&gt;&lt;code&gt;app/src/main/java/org/sopt/appjam/global/config/SecurityConfig.java
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모듈러 모놀리식 구조를 사용 중임으로 app 모듈 안에 있는 config에 설정해놨다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;추가로 공부 중이라서 anyRequest().permitAll() 으로 열었지만 나중에 JWT 필터를 붙일 때 .anyRequest().authenticated() 이렇게 할 것이다&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;JWT 토큰 적용하기&lt;/h1&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;의존성 추가&lt;/h2&gt;
&lt;pre class=&quot;clean&quot;&gt;&lt;code&gt;// JWT
implementation 'io.jsonwebtoken:jjwt-api:0.11.5'
runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.11.5'
runtimeOnly 'io.jsonwebtoken:jjwt-jackson:0.11.5'
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;TokenProvider 추가&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JWT 인증 시스템에서 &lt;b&gt;토큰 생성, 검증, 정보 추출을 담당하는 클래스&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;openssl rand -base64 32
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선, 터미널에 위에처럼 입력한다&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;윈도우에서는 Git bash에 입력하면 됨
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;복사는 ctrl + insert&lt;/li&gt;
&lt;li&gt;붙여넣기는 shift + insert&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정말 합숙 기간 전에는 다 끝내려고 했는데.. 여행이나 뭐 핑계 대느라 안했던 것 같다... 그래서 현재 개발 중인 NearBy 서비스를 더 자세히 분석해서 올리고자 한다!&lt;/p&gt;</description>
      <category>Back-end</category>
      <category>backend</category>
      <category>Spring</category>
      <category>Spring Boot</category>
      <author>dev_Hyeonjoon</author>
      <guid isPermaLink="true">https://joon0112.tistory.com/84</guid>
      <comments>https://joon0112.tistory.com/84#entry84comment</comments>
      <pubDate>Sun, 12 Jul 2026 22:20:30 +0900</pubDate>
    </item>
    <item>
      <title>DDD(Domain-Driven Design)란? 핵심 개념과 계층형 아키텍처</title>
      <link>https://joon0112.tistory.com/83</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;DDD(Domain-Drvien Design, 도메인 주도 설계) 란?&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;도메인 모델을 기반으로 복잡한 소프트웨어 시스템을 설계하고 개발하는 방법론&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;도메인(Domain)&lt;/h2&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;&amp;rarr; 도메인이 무엇인지 보다는 &lt;b&gt;도메인에 포함되는 것이 무엇인가&lt;/b&gt; 정의를 내리는게 더 중요!&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 여행 애플리케이션은 예약, 결제, 여행 일정, 회원 관리 등의 하위 도메인으로 나눌 수 있다. 예약 도메인 안에는 예약 요청, 확정, 취소와 같은 상태와 행위가 존재할 수 있다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이처럼 여러 도메인들이 상호작용하며, 비즈니스 도메인별로 나누어 설계하는 것을 도메인 주도 설계라고 한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;도메인과 객체의 차이점&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;객체(Object)&lt;/b&gt;&lt;br /&gt;객체는 프로그램에서 특정 개념을 표현하기 위해 상태와 행동을 하나로 묶은 단위이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;객체는 현실 세계의 대상을 그대로 복사한 것이 아니라, 소프트웨어가 해결하려는 문제에 필요한 특징만 선택하여 추상화한 결과이다.&lt;br /&gt;예를 들어 여행 서비스의 사용자 객체는 실제 사람의 모든 정보를 표현하지 않는다. 여행 서비스에서 필요한 사용자 식별자, 닉네임, 여행 성향 등의 정보만 포함할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;도메인(Domain)&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;소프트웨어가 해결하고자 하는 문제 영역을 의미&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 여행 애플리케이션에는 회원 관리, 여행 일정, 예약, 결제, 리뷰 등의 도메인이 존재할 수 있다.&lt;br /&gt;도메인 모델은 이러한 문제 영역의 개념과 규칙을 객체로 표현한 모델이다. 따라서 객체는 도메인을 코드로 표현하기 위한 수단이고, 도메인은 객체가 표현하려는 문제 영역이라고 볼 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정리하면 다음과 같다.&lt;br /&gt;&amp;bull; 도메인: 소프트웨어가 해결하려는 문제 영역&lt;br /&gt;&amp;bull; 도메인 모델: 문제 영역의 개념과 규칙을 추상화한 모델&lt;br /&gt;&amp;bull; 객체: 도메인 모델을 코드로 표현하는 수단&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DDD의 핵심 목표는 복잡한 비즈니스 규칙을 도메인 모델에 명확하게 표현하고, 바운디드 컨텍스트를 통해 모델의 경계를 구분하는 것이다. 이를 통해 각 영역의 응집도를 높이고 영역 간 결합도를 낮춰 변경과 확장에 유연한 소프트웨어를 설계할 수 있다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;DDD 핵심 개념&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;유비쿼터스 언어 (Ubiquitous Language)&lt;/h3&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;b&gt;이점&lt;/b&gt;: 의사소통 오류를 감소시키고 모델에 반영된 용어가 코드에도 그래도 쓰여, 일관성을 유지한다. 또한 도메인에 대한 이해를 높이기도 한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;바운디드 컨텍스트(Bounded Context)&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;정의&lt;/b&gt;: 도메인이 여러 하위 영역으로 나뉘어 있을 때, 각 영역을 경계(Context)로 구분하고 독립된 모델을 유지하는 개념&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 data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;이점&lt;/b&gt;: 영역별 요구사항 충돌 최소한다. 컨텍스트 간 의존관계를 명확히 정의해, 복잡도를 관리한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;도메인 모델&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;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;엔티티(Entity), 값 객체(Value Object), 서비스(Service), 리포지터리(Repository) 등의 구성요소로 이루어짐&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;역할&lt;/b&gt;: 비즈니스 로직을 객체지향적으로 표현해, 문제 해결 로직을 직관적으로 이해하게 한다. 또 한 유지보수성과 확장성을 향상시킨다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;애그리거트 (Aggregate)&lt;/h3&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;b&gt;루트 엔티티(Root Entity)&lt;/b&gt;: 애그리거트의 대표자 역할을 한다. 외부에서 애그리거트에 접근할 때, 루트 엔터티를 통해서만 조작한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;엔티티 (Entity) 와 값 객체 (Value Object)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;엔티티&lt;/b&gt;: 고유한 식별자(ID)를 갖고, 라이프사이클 전반에 걸쳐 상태가 변할 수 있는 객체&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;값 객체&lt;/b&gt;: 식별자 없이 불변성을 띠며, 동일한 속성이면 같은 객체로 취급&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;도메인 서비스 &lt;b&gt;(Domain Service)&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;정의&lt;/b&gt;: 모델 객체(Entity, Value Object)로 표현하기 어려운 도메인 규칙이나 로직을 담당&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;역할:&lt;/b&gt; 여러 애그리거트를 한꺼번에 조작하거나, 계산 로직 등 비즈니스 로직 을 캡슐화해 코드의 응집도를 높인다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;레포지터리(Repository)&lt;/h3&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;b&gt;역할&lt;/b&gt;: 영속성(persistence) 로직을 캡슐화하여, 도메인 로직과 데이터 접근 로직을 분리한다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;DDD의 계층구조(Layerd Architecture)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;계층이 나뉘어져 있는 아키텍처&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;주된 목표는 각각의 layer는 하나의 관심사에만 집중할 수 있도록 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일반적으로 3 계층 또는 4계층으로 나누어 사용&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;※ 3계층으로 나눌 때는 표현 계층(Presentation Layer) &amp;rarr; 서비스 계층 (Business Layer) &amp;rarr; 영속성 계층(Persistence Layer)으로 나누어 사용하곤 한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;996&quot; data-origin-height=&quot;1020&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/em8tcQ/dJMcad3Iq46/PR2aVmNV3Eqa1K0sglRBVK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/em8tcQ/dJMcad3Iq46/PR2aVmNV3Eqa1K0sglRBVK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/em8tcQ/dJMcad3Iq46/PR2aVmNV3Eqa1K0sglRBVK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fem8tcQ%2FdJMcad3Iq46%2FPR2aVmNV3Eqa1K0sglRBVK%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;996&quot; height=&quot;1020&quot; data-origin-width=&quot;996&quot; data-origin-height=&quot;1020&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;규칙&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;위의 계층에서 아래 계층에는 접근이 가능하지만 아래에서 위로는 불가능한 것을 기본으로 한다.&lt;/li&gt;
&lt;li&gt;한 계층의 관심사와 관련된 어떤 것도 다른 계층에 배치되어서는 안된다.&lt;/li&gt;
&lt;/ol&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;계층별 설명&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. Presentation Layer (표현 계층) (Controller)&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자 요청에 대해 해석하고 응답하는 일을 책임지는 계층&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;사용자에게 UI를 제공하거나 클라이언트에 응답을 다시 보내는 역할을 하는 모든 클래스가 포함&lt;/li&gt;
&lt;li&gt;Client로부터 request를 받고 response를 return 하는 API 정의&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2. Application Layer (응용 계층) (Service)&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비즈니스 로직을 정의하고 정삭적으로 수행될 수 있도록 도메인 계층과 인프라스트럭쳐 계층을 연결해주는 역할을 하는 계층&lt;/p&gt;
&lt;/blockquote&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;h3 data-ke-size=&quot;size23&quot;&gt;기능&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;트랜잭션의 단위&lt;/li&gt;
&lt;li&gt;DTO 변환&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;단순하게 말하면 Entity를 찾고 (Repository), 변경 내용을 저장하는 기능(Persistence)을 호출한다.&lt;/li&gt;
&lt;/ul&gt;
구현은 Infra Layer에서 한다&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;사용자가 특정 URL에 대해 권한이 있는지 정도의 인가는 presentation layer에서 하지만, URL만으로 판단이 어렵거나, DB내의 데이터와 대조해봐야 알 수 있는 경우 (데이터 존재 여부, 중복 여부 등)&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;presentation layer에서도 수행할 수 있지만 주로 요청 방식에 따라 달라지는 &amp;lsquo;형식&amp;rsquo;에 대한 검증을 하고, application layer에서는 &amp;lsquo;논리적&amp;rsquo;인 오류를 검증한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3. Domain Layer (도메인 계층) (Model)&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비즈니스 규칙, 정보에 대한 실질적인 도메인에 대한 정보를 가지고 있으며 이 모든 것을 책임지는 계층&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Entity를 활용하여 도메인 로직이 실행되며, 업무 상황을 반영하여 상태를 제어하는 역할에 집중하는 계층&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;4. Infrastructure Layer (인프라 계층)&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;외부와의 통신(DB, 메시징 시스템 등)을 담당하는 계층&lt;/p&gt;
&lt;/blockquote&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 data-ke-size=&quot;size16&quot;&gt;각각의 도메인들을 위와 같은 Layer로 철저히 분리해서 만드는 것이 DDD(Domain-Driven Design)의 핵심 설계&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Layered Architecture의 장단점&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Layered Architecture 장점&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;각 레이어를 Loosely Coupling된 형태로 구축하면서, 각각 자신의 관심사에만 집중할 수 있다.&lt;/li&gt;
&lt;li&gt;핵심 비즈니스 로직을 순수하게 유지함으로써 유지보수와 확장성 측면에서 이득을 얻을 수 있다.&lt;/li&gt;
&lt;li&gt;각 레이어에 서로 다른 추상화 수준을 가진 상태와 행동을 위치시킴으로써 코드 재사용성을 높일 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Layered Architecture 단점&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;li&gt;레이어로 분리된 관심사 외에 다른 관심사가 생길 경우 패키지 분리 및 코드 배치가 어렵다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;출처&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://limdae94.tistory.com/84&quot;&gt;https://limdae94.tistory.com/84&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://tech.kakaopay.com/post/backend-domain-driven-design/&quot;&gt;https://tech.kakaopay.com/post/backend-domain-driven-design/&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://wikidocs.net/275501&quot;&gt;https://wikidocs.net/275501&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://dev-coco.tistory.com/166&quot;&gt;https://dev-coco.tistory.com/166&lt;/a&gt;&lt;/p&gt;</description>
      <category>CS/Architecture</category>
      <category>DDD</category>
      <category>domain</category>
      <category>Spring</category>
      <category>도메인</category>
      <category>아키텍처</category>
      <author>dev_Hyeonjoon</author>
      <guid isPermaLink="true">https://joon0112.tistory.com/83</guid>
      <comments>https://joon0112.tistory.com/83#entry83comment</comments>
      <pubDate>Sat, 11 Jul 2026 22:19:34 +0900</pubDate>
    </item>
    <item>
      <title>객체 간의 결합도(Coupling)와 응집도(Cohesion)의 관계</title>
      <link>https://joon0112.tistory.com/82</link>
      <description>&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결합도와 응집도는 소프트웨어 구조 품질을 설명하는 가장 기본적인 두 축이다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;결합도&lt;/b&gt; &amp;rarr; 모듈 간 의존의 강도를 의미&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;응집도&lt;/b&gt; &amp;rarr; 하나의 모듈 내부에서 책임이 얼마나 잘 모여 있는지를 나타냄&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;모듈&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;소프트웨어를 각 기능별로 나누어진 소스 단위&lt;/li&gt;
&lt;li&gt;모듈은 문맥에 따라 함수, 클래스, 패키지, Gradle 모듈처럼 서로 다른 크기의 소프트웨어 구성 단위를 의미할 수 있다. 결합도와 응집도는 이러한 여러 수준에서 모두 판단할 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;모듈화&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제가 복잡하고 큰 문제라면, 이 문제를 작은 부분으로 쪼개나가는 것&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;모듈의 효율성&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결합도가 낮고 응집도가 높을 수록 모듈화의 효율성이 높다&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;객체지향 언어인지 절차지향 언어인지와 관계없이, 모듈 내부의 관련 기능은 함께 모으고 모듈 사이의 불필요한 의존은 줄이는 것이 좋은 설계의 기본 방향이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 말을 다시 정리해보자면, 좋은 모듈화는 &lt;b&gt;목적에 맞는 기능만으로 모듈을 나누게 되는&lt;/b&gt;데, 각각의 모듈은 주어진 기능만을 독립적으로 수행하기 때문에 재사용성이 높고 코드의 이해/수정이 용이하기 때문이다&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;결합도(Coupling)&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1043&quot; data-origin-height=&quot;746&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/PF5YF/dJMcado5PwZ/Cc1LeKVaGiQD8jSaqIKmp1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/PF5YF/dJMcado5PwZ/Cc1LeKVaGiQD8jSaqIKmp1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/PF5YF/dJMcado5PwZ/Cc1LeKVaGiQD8jSaqIKmp1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FPF5YF%2FdJMcado5PwZ%2FCc1LeKVaGiQD8jSaqIKmp1%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;1043&quot; height=&quot;746&quot; data-origin-width=&quot;1043&quot; data-origin-height=&quot;746&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;모듈(클래스 파일)간의 &lt;b&gt;상호 의존 정도&lt;/b&gt; 또는 연관된 관계의 끈끈함 정도를 의미&lt;/li&gt;
&lt;li&gt;결합도를 &lt;b&gt;의존도&lt;/b&gt;라고 부른다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결합도가 높다는 것은 모듈들이 밀접하게 연결되어 있어 한 모듈의 변경 사항이 다른 모듈에 영향을 미칠 수 있다. 반대로 결합도 낮다는 것은 모듈들이 독립적이어서 한 모듈의 변경 사항이 다른 모듈에 미치는 영향이 미미하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결합도가 높다는 것을 예를 들어보면, 여행 플랫폼에서 회원 예매를 구축한다고 할 때 예매 로직에서 회원 가입 로직을 알고 있을 때 결합도가 높다고 할 수 있다. 예매 로직에서는 로그인한 회원의 정보만 알고 있으면 결합도를 낮출 수 있다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;기준&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, 어떤 클래스가 다른 클래스에 대해 너무 자세히 알고 있다면 두 모듈은 높은 결합도를 가지게 되고, 반대로 어떤 클래스가 다른 클래스에 대해 꼭 필요한 지식만 가지고 있다면 두 모듈은 낮은 결합도를 가진다고 말할 수 있는 것&lt;/p&gt;
&lt;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;이 경우에 인터페이스를 사용했더라도 호출자가 내부 영속성 구조인 UserJpaEntity 까지 알고 있다면 여전히 결합도가 높다&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;interface UserService {
    UserJpaEntity findUserEntityWithPasswordAndLoginHistory(Long userId);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: none;&quot;&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;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;interface CurrentUserProvider {
    CurrentUser getCurrentUser();
}&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rarr;낮은 결합도는 변경의 영향을 줄여주며, OCP를 지키기 쉬운 구조를 만드는 데 도움을 준다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;확장에는 열려있고 변경에는 닫혀있는 클래스&lt;/li&gt;
&lt;li&gt;다형성을 잘 지킨 클래스&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;응집도(Cohesion)&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1043&quot; data-origin-height=&quot;746&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/TDqIm/dJMcafN7D3c/1zhHPvNDFyjMHRsDSjWgt0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/TDqIm/dJMcafN7D3c/1zhHPvNDFyjMHRsDSjWgt0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/TDqIm/dJMcafN7D3c/1zhHPvNDFyjMHRsDSjWgt0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FTDqIm%2FdJMcafN7D3c%2F1zhHPvNDFyjMHRsDSjWgt0%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;1043&quot; height=&quot;746&quot; data-origin-width=&quot;1043&quot; data-origin-height=&quot;746&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모듈 내 요소들이 하나의 명확한 목적을 달성하기 위해 얼마나 긴밀하게 협력하는 지를 나타내는 정도이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한 모듈이 하나의 기능(책임)을 갖고 있다면 응집도가 높은 것&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한 모듈이 여러 기능을 갖고 있는 것은 응집도가 낮은 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;응집도가 높은 모듈은 하나의 모듈 안에 함수나 데이터와 같은 구성 요소들이 하나의 기능을 구현하기 위해 필요한 것들만 배치되어 있고 긴밀하게 협력한다. 반대로 응집도가 낮은 모듈은 모듈 내부에 서로 관련 없는 함수나 데이터들이 존재하거나 관련성이 적은 여러 기능들이 서로 다른 목적을 추구하며 산재해 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어, 여행 프로젝트에서 예매 처리를 담당하는 클래스에서 로그 아웃을 하는 메서드가 있다면, 이것은 응집도가 낮은 것이다. 따라서 클래스를 분리하는 게 응집도를 높일 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;응집도를 판단할 때는 메서드들이 같은 데이터를 사용하는지만 보는 것이 아니라, 같은 이유로 함께 변경되는지도 살펴봐야 한다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;결합도와 응집도&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서론 관련된 책임을 하나의 모듈 안에 모으면 응집도가 높아지고, 관련 없는 책임을 다른 모듈로 분리하면 모듈 사이의 불필요한 의존도 줄어든다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 높은 응집도를 만들기 위해 무조건 클래스를 작게 나누는 것이 아니라, 함께 변경되고 함께 동작하는 책임은 모으고 서로 다른 이유로 변경되는 책임은 분리해야 한다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;코드를 판단하는 질문&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;응집도를 판단하는 질문&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이 클래스의 메서드들을 한 문장으로 설명할 수 있는가?&lt;/li&gt;
&lt;li&gt;메서드들이 동일한 상태나 데이터를 중심으로 동작하는가?&lt;/li&gt;
&lt;li&gt;클래스 이름과 관계없는 메서드가 들어 있지는 않은가?&lt;/li&gt;
&lt;li&gt;메서드들이 비슷한 이유로 함께 변경되는가?&lt;/li&gt;
&lt;li&gt;클래스 이름에 Manager, Util, Helper처럼 책임이 모호한 단어가 붙어 있지는 않은가?&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;결합도를 판단하는 질문&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;다른 객체의 내부 구현 방식을 알고 있는가?&lt;/li&gt;
&lt;li&gt;다른 객체의 필드나 DB Entity를 직접 사용하고 있는가?&lt;/li&gt;
&lt;li&gt;한 클래스를 변경했을 때 여러 클래스가 함께 변경되는가?&lt;/li&gt;
&lt;li&gt;구체 클래스 대신 필요한 역할이나 계약에 의존하고 있는가?&lt;/li&gt;
&lt;li&gt;메서드의 매개변수로 정말 필요한 정보만 전달하고 있는가?&lt;/li&gt;
&lt;li&gt;다른 모듈의 상태를 직접 변경하고 있지는 않은가?&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;참고자료&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://wikidocs.net/369737&quot;&gt;https://wikidocs.net/369737&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://inpa.tistory.com/entry/OOP-&quot;&gt;https://inpa.tistory.com/entry/OOP-&lt;/a&gt;&lt;a href=&quot;https://inpa.tistory.com/entry/OOP-%F0%9F%92%A0-%EA%B0%9D%EC%B2%B4%EC%9D%98-%EA%B2%B0%ED%95%A9%EB%8F%84-%EC%9D%91%EC%A7%91%EB%8F%84-%EC%9D%98%EB%AF%B8%EC%99%80-%EB%8B%A8%EA%B3%84-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0-%EC%89%BD%EA%B2%8C-%EC%A0%95%EB%A6%AC&quot;&gt; -객체의-결합도-응집도-의미와-단계-이해하기-쉽게-정리&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.geeksforgeeks.org/software-engineering/software-engineering-coupling-and-cohesion/&quot;&gt;https://www.geeksforgeeks.org/software-engineering/software-engineering-coupling-and-cohesion/&lt;/a&gt;&lt;/p&gt;</description>
      <category>CS/Architecture</category>
      <category>CS</category>
      <category>객체</category>
      <category>결합도</category>
      <category>아키텍처</category>
      <category>응집도</category>
      <author>dev_Hyeonjoon</author>
      <guid isPermaLink="true">https://joon0112.tistory.com/82</guid>
      <comments>https://joon0112.tistory.com/82#entry82comment</comments>
      <pubDate>Fri, 10 Jul 2026 15:55:09 +0900</pubDate>
    </item>
    <item>
      <title>Nginx는 왜 등장했을까? Apache 구조의 한계와 이벤트 기반 웹 서버 이해하기</title>
      <link>https://joon0112.tistory.com/81</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;이번 프로젝트에서 Nginx를 쓰게 되었고 본격적인 프로젝트를 시작하기 전에 왜 Nginx를 사용하는지 정리해보려고 한다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;웹 서버는 대부분 Apache나 Nginx를 사용한다. 그 이유가 뭘까?&quot;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Nginx 소개&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Nginx는 고성능의 오픈 소스 웹 서버 소프트웨어로 많은 웹 서버와 리버스 프록시로 널리 사용&lt;/li&gt;
&lt;/ul&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;가볍고 확장 가능한 구조와 높은 처리량이 특징&lt;/li&gt;
&lt;/ol&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;가상 호스팅, 로드 밸런싱, SSL/TLS 암호화, URL 리다이렉션 등 다양한 기능을 제공&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Nginx 란?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Nginx는 다목적 비동기 웹 서버 소프트웨어로, 많은 웹 서버와 리버스 프록시로 널리 사용된다. 주요 목적은 클라이언트 요청을 받아 정적 및 동적 콘텐츠를 처리하여 웹 서비스를 제공하는 것&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 data-ke-size=&quot;size16&quot;&gt;웹서버의 역할뿐만 아니라 프록시 서버, 캐싱, 분산 처리, 미디어 스트리밍 등을 위한 다양한 기능을 제공하며 기능뿐만 아니라 성능면에서 기존의 웹서버들보다 뛰어나 현재 NGINX는 가장 널리 사용되고 있는 웹서버이다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Nginx 탄생 이유&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Apache 작동 방식&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;620&quot; data-origin-height=&quot;485&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ZqwPg/dJMcah53jHA/LK2Xoae3og9zUtRlpshYTk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ZqwPg/dJMcah53jHA/LK2Xoae3og9zUtRlpshYTk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ZqwPg/dJMcah53jHA/LK2Xoae3og9zUtRlpshYTk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FZqwPg%2FdJMcah53jHA%2FLK2Xoae3og9zUtRlpshYTk%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;276&quot; height=&quot;216&quot; data-origin-width=&quot;620&quot; data-origin-height=&quot;485&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;NCSA HTTPd의 불편함을 해결하기 위해 &lt;b&gt;Apache Server&lt;/b&gt;라는 게 등장한다. &lt;b&gt;Apache Server는 요청이 들어오는 경우 connection을 생성&lt;/b&gt;한다. &lt;b&gt;그래서 새로운 클라이언트의 요청이 올 때마다 새로운 process를 생성&lt;/b&gt;한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;544&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/3t2ot/dJMcaiw5hez/NFVb8343BTXWtyxTpDSTGK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/3t2ot/dJMcaiw5hez/NFVb8343BTXWtyxTpDSTGK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/3t2ot/dJMcaiw5hez/NFVb8343BTXWtyxTpDSTGK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F3t2ot%2FdJMcaiw5hez%2FNFVb8343BTXWtyxTpDSTGK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1280&quot; height=&quot;544&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;544&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데 process를 생성하는 경우 시간이 오래걸린다. 이를 해결하기 위해 Apache에서는 &lt;b&gt;PREFORK&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;만약 만들어 놓은 프로세스가 없는 경우 추가로 Process를 생성&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;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cbSnF9/dJMcadbnbLz/kCitYspKTwaKdHGWsRGpu0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cbSnF9/dJMcadbnbLz/kCitYspKTwaKdHGWsRGpu0/img.png&quot; data-origin-width=&quot;650&quot; data-origin-height=&quot;387&quot; data-is-animation=&quot;false&quot; width=&quot;564&quot; height=&quot;336&quot; style=&quot;width: 52.6455%; margin-right: 10px;&quot; data-widthpercent=&quot;53.26&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cbSnF9/dJMcadbnbLz/kCitYspKTwaKdHGWsRGpu0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcbSnF9%2FdJMcadbnbLz%2FkCitYspKTwaKdHGWsRGpu0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;650&quot; height=&quot;387&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/9H95N/dJMcadbnbLV/TOmtMnrHYS6eRFMbxKSTg0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/9H95N/dJMcadbnbLV/TOmtMnrHYS6eRFMbxKSTg0/img.png&quot; data-origin-width=&quot;672&quot; data-origin-height=&quot;456&quot; data-is-animation=&quot;false&quot; width=&quot;460&quot; height=&quot;312&quot; style=&quot;width: 46.1917%;&quot; data-widthpercent=&quot;46.74&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/9H95N/dJMcadbnbLV/TOmtMnrHYS6eRFMbxKSTg0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F9H95N%2FdJMcadbnbLV%2FTOmtMnrHYS6eRFMbxKSTg0%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;672&quot; height=&quot;456&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러한 구조 덕분에 개발자들은 다양한 모듈을 만들어 서버에 빠르게 기능을 추가할 수 있었다. 즉, 확장성이 높았고, Apache Server는 동적 컨텐츠를 처리할 수 있게 되었다. 확장성이 좋다는 장점은 결국 요청을 받고 응답을 처리하는 과정을 하나의 서버에서 해결하기 좋았다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Apache 구조의 한계와 Nginx가 등장한 배경&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 좋은 점만 있어보이는 Apache Server가 대체된 이유는 1999년 이후 컴퓨터가 많이 보급됨에 따라 요청이 많아져서 서버에 동시에 연결된 connection이 많을 때 더 이상 새로운 connection을 생성하지 못 하게 되었다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;579&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/unQNZ/dJMcajo6Lon/Q1iKrKNTblKVdUFAerjRtk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/unQNZ/dJMcajo6Lon/Q1iKrKNTblKVdUFAerjRtk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/unQNZ/dJMcajo6Lon/Q1iKrKNTblKVdUFAerjRtk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FunQNZ%2FdJMcajo6Lon%2FQ1iKrKNTblKVdUFAerjRtk%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;608&quot; height=&quot;275&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;579&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를 **C10K(connection 10000 problem)**문제라고 부른다. &lt;b&gt;connection 10000개의 문제&lt;/b&gt;라는 뜻이며&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Apache Server는 구조적으로 아래와 같은 문제점이 있다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;메모리 부족&lt;/b&gt;: connection이 연결될 때마다 프로세스를 생성&lt;/li&gt;
&lt;li&gt;&lt;b&gt;무거운 프로그램&lt;/b&gt;: 확장성이 좋다는건 곧 리소스가 않다는 걸 의미&lt;/li&gt;
&lt;li&gt;&lt;b&gt;CPU 부하 증가&lt;/b&gt;: 많은 connection 요청이 들어오면 context switching을 많이 하기에 CPU 부하가 증가&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;1280&quot; data-origin-height=&quot;302&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bkxQ20/dJMcaaMzr2A/CTBcx1q0y6deGuBoJbjA6K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bkxQ20/dJMcaaMzr2A/CTBcx1q0y6deGuBoJbjA6K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bkxQ20/dJMcaaMzr2A/CTBcx1q0y6deGuBoJbjA6K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbkxQ20%2FdJMcaaMzr2A%2FCTBcx1q0y6deGuBoJbjA6K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1280&quot; height=&quot;302&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;302&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;동시 접속이 급격히 증가하는 환경에서는 프로세스/스레드 기반 구조가 메모리 사용량과 context switching 측면에서 부담이 될 수 있었다. 이 문제를 해결하기 위해 이벤트 기반 구조를 가진 Nginx가 주목받기 시작했다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;초창기 Nginx는 Apache를 대체하기 위한 것이 아닌 보완 목적으로써 Apache Server가 지닌 구조적 문제점을 해결하기 위한 목적이였다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;555&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bYHXuP/dJMcai4PDwj/F1OHPWOre4BNfLqvE3kzh0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bYHXuP/dJMcai4PDwj/F1OHPWOre4BNfLqvE3kzh0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bYHXuP/dJMcai4PDwj/F1OHPWOre4BNfLqvE3kzh0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbYHXuP%2FdJMcai4PDwj%2FF1OHPWOre4BNfLqvE3kzh0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1280&quot; height=&quot;555&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;555&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사진에서 보는 것처럼 &lt;span data-token-index=&quot;1&quot;&gt;수많은 동시 connection을 Nginx가 유지하고,&amp;nbsp;Nginx도 웹 서버이기에 정적 파일에 대한 요청은 스스로 처리하고,&amp;nbsp;클라이언트로부터 동적 파일의 요청을 받았을 때만 아파치 서버와 connection을 형성하여 아파치 서버의 부하를 줄였다.&lt;/span&gt;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;Nginx 구조&lt;/h1&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;master - worker 프로세스 모델을 사용한다.&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;598&quot; data-origin-height=&quot;363&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/baMCwS/dJMcacDF1Pe/b1wg0T4JTSqyLsBIKPrOk1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/baMCwS/dJMcacDF1Pe/b1wg0T4JTSqyLsBIKPrOk1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/baMCwS/dJMcacDF1Pe/b1wg0T4JTSqyLsBIKPrOk1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbaMCwS%2FdJMcacDF1Pe%2Fb1wg0T4JTSqyLsBIKPrOk1%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;598&quot; height=&quot;363&quot; data-origin-width=&quot;598&quot; data-origin-height=&quot;363&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;master 프로세스는 설정 파일을 읽고, worker 프로세스를 생성하고 관리한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;worker 프로세스는 실제로 클라이언트 요청을 처리하는 프로세스이다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;worker process가 만들어질 때 지정된 listen 소켓을 배정받는다.&lt;/li&gt;
&lt;li&gt;그 후 그 소켓에 새로운 클라이언트 요청이 온다면 connection을 형성하고 처리한다.&lt;/li&gt;
&lt;li&gt;connection은 정해진 Keep-Alive 시간만큼 유지됩니다. 하지만&amp;nbsp;connection이 형성되었다고 해서&amp;nbsp;worker process가 해당&amp;nbsp;connection&amp;nbsp;하나만 담당하지는 않습니다&lt;/li&gt;
&lt;li&gt;형성된 connection으로부터 아무런 요청이 없다면 새로운 connection을 형성하거나 이미 만들어진 다른 connection 으로부터 들어온 요청을 처리한다.&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;1280&quot; data-origin-height=&quot;770&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dVYvie/dJMcajvY7ku/bhDkSkz7SjwvmWUssdJQV0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dVYvie/dJMcajvY7ku/bhDkSkz7SjwvmWUssdJQV0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dVYvie/dJMcajvY7ku/bhDkSkz7SjwvmWUssdJQV0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdVYvie%2FdJMcajvY7ku%2FbhDkSkz7SjwvmWUssdJQV0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1280&quot; height=&quot;770&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;770&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span data-token-index=&quot;0&quot;&gt;Nginx에서는 이러한&amp;nbsp;connection 형성과 제거, 그리고&amp;nbsp;새로운 요청을 처리하는 것을&amp;nbsp;이벤트(event)라고한다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;545&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dVKrtn/dJMcaiqhQ3B/ukeu0LfBOVp8QlAEILsfHk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dVKrtn/dJMcaiqhQ3B/ukeu0LfBOVp8QlAEILsfHk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dVKrtn/dJMcaiqhQ3B/ukeu0LfBOVp8QlAEILsfHk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdVKrtn%2FdJMcaiqhQ3B%2Fukeu0LfBOVp8QlAEILsfHk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1280&quot; height=&quot;545&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;545&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 이벤트들은 OS 커널이 Queue형식으로 worker process에 전달한다. 이 이벤트가 Queue에 있다면 비동기 상태로 유지가 된다. 그리고 worker process는 하나의 스레드로 이벤트를 꺼내서 처리해나간다. 이런 방식은 worker process가 쉬지 않고 일을 하기에, 요청이 없을 때 프로세스를 방치시키는 Apache Server보다 훨씬 효율적으로 자원을 사용할 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;700&quot; data-origin-height=&quot;209&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cZASFe/dJMcabLyHXg/TjthCdT7ijbIJJLu1tOSiK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cZASFe/dJMcabLyHXg/TjthCdT7ijbIJJLu1tOSiK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cZASFe/dJMcabLyHXg/TjthCdT7ijbIJJLu1tOSiK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcZASFe%2FdJMcabLyHXg%2FTjthCdT7ijbIJJLu1tOSiK%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;700&quot; height=&quot;209&quot; data-origin-width=&quot;700&quot; data-origin-height=&quot;209&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;700&quot; data-origin-height=&quot;209&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c0dIzw/dJMcabLyHXC/ZKDxGzu6qiOGsPQDv6kqD1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c0dIzw/dJMcabLyHXC/ZKDxGzu6qiOGsPQDv6kqD1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c0dIzw/dJMcabLyHXC/ZKDxGzu6qiOGsPQDv6kqD1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc0dIzw%2FdJMcabLyHXC%2FZKDxGzu6qiOGsPQDv6kqD1%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;700&quot; height=&quot;209&quot; data-origin-width=&quot;700&quot; data-origin-height=&quot;209&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위에 있는 이미지처럼 Apache 방식인 스레드 기반은 하나의 커넥션 당 하나의 스레드를 잡아먹지만 이벤트 기반 방식은 여러 개의 connection을 전부 Event Handler를 통해 비동기 방식으로 처리해 먼저 처리되는 것부터 로직이 진행되게끔 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러한 이벤트 구조가 바로 Nginx의 핵심&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Nginx의 단점&lt;/b&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;동적 컨텐츠를 기본적으로 처리 할 수 없음&lt;/li&gt;
&lt;li&gt;동적 콘텐츠에 대한 PHP 및 기타 요청을 처리하려면 NGINX가이를 실행하기 위해 외부 프로세서로 전달하고 렌더링 된 콘텐츠가 다시 전송 될 때까지 기다려야함(프로세스 속도 저하).&lt;/li&gt;
&lt;li&gt;즉, 동적 웹 페이지 컨텐츠를 가진 모든 요청을 위해 외부 자원과 연계(php-fpm)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Nginx의 장점&lt;/b&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이벤트 중심 접근 방식을 사용하여 클라이언트 요청 제공&lt;/li&gt;
&lt;li&gt;제한된 하드웨어 리소스로도 여러 클라이언트 요청을 동시에 효율적으로 처리&lt;/li&gt;
&lt;li&gt;단일 스레드를 통해 여러 연결을 처리 가능&lt;/li&gt;
&lt;li&gt;최소한의 리소스로 웹 서버의 아키텍처를 개선하기 위해 독립형 HTTP 서버로 배치 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;참고 자료&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://dev-wisdom.tistory.com/234&quot;&gt;https://dev-wisdom.tistory.com/234&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://soonmin.tistory.com/88&quot;&gt;https://soonmin.tistory.com/88&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://dkswnkk.tistory.com/513&quot;&gt;https://dkswnkk.tistory.com/513&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=6FAwAXXj5N0&quot;&gt;https://www.youtube.com/watch?v=6FAwAXXj5N0&lt;/a&gt;&lt;/p&gt;</description>
      <category>Back-end/DevOps</category>
      <author>dev_Hyeonjoon</author>
      <guid isPermaLink="true">https://joon0112.tistory.com/81</guid>
      <comments>https://joon0112.tistory.com/81#entry81comment</comments>
      <pubDate>Fri, 26 Jun 2026 18:56:12 +0900</pubDate>
    </item>
    <item>
      <title>[Spring, Docker] 모듈식 모놀리스에서 Docker 배포하기</title>
      <link>https://joon0112.tistory.com/80</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;762&quot; data-origin-height=&quot;538&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/7bOst/dJMcaay18CL/6S4GbgIEhyAw6y2JvsYxwK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/7bOst/dJMcaay18CL/6S4GbgIEhyAw6y2JvsYxwK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/7bOst/dJMcaay18CL/6S4GbgIEhyAw6y2JvsYxwK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F7bOst%2FdJMcaay18CL%2F6S4GbgIEhyAw6y2JvsYxwK%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;282&quot; height=&quot;199&quot; data-origin-width=&quot;762&quot; data-origin-height=&quot;538&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선 모듈식 모놀리스로 아키텍처를 가져갔다면 전통적인 모놀리식과 다르게 여러 개의 모듈이 있을 것이다. 하지만 모듈러식 모놀리스는 여러 모듈로 코드를 나누더라도, 최종적으로는 실행 모듈인 app에서 하나의 JAR 파일을 만들어 배포한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;610&quot; data-origin-height=&quot;1152&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bVccdc/dJMcaaTjaGy/vBelXpDmPwrBUEB0NXAm8K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bVccdc/dJMcaaTjaGy/vBelXpDmPwrBUEB0NXAm8K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bVccdc/dJMcaaTjaGy/vBelXpDmPwrBUEB0NXAm8K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbVccdc%2FdJMcaaTjaGy%2FvBelXpDmPwrBUEB0NXAm8K%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;383&quot; height=&quot;723&quot; data-origin-width=&quot;610&quot; data-origin-height=&quot;1152&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선 app 모듈에서 배포를 할 예정이라 app &amp;rarr; Tasks &amp;rarr; bootJar 를 클릭해줬다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;app/build/libs 의 경로에 .jar로 끝나는 파일이 생성된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;이제 Dockerfile을 성해준다. (확장자 x)&lt;/b&gt;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Dockerfile 생성하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;방법은 두 가지가 있다&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1.jar 있는 곳에 Dockerfile 두기&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;678&quot; data-origin-height=&quot;312&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xmxKK/dJMcaaZ3JIK/Kgt3Y80JL0Xe8EMrSzyro0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xmxKK/dJMcaaZ3JIK/Kgt3Y80JL0Xe8EMrSzyro0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xmxKK/dJMcaaZ3JIK/Kgt3Y80JL0Xe8EMrSzyro0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxmxKK%2FdJMcaaZ3JIK%2FKgt3Y80JL0Xe8EMrSzyro0%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;474&quot; height=&quot;218&quot; data-origin-width=&quot;678&quot; data-origin-height=&quot;312&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;.jar 파일이 있는 곳에 Dockerfile을 생성하는 방법&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;모듈식 모놀리스에서 생기는 단점&lt;/h4&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;1. Dockerfile이 build/libs 안에 들어감
2. build 폴더는 보통 .gitignore 대상임
3. gradlew clean 하면 build/libs가 삭제됨
4. Dockerfile도 같이 사라질 수 있음
5. 프로젝트 구조 관리가 지저분해짐
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. 프로젝트 루트에 Dockerfile 두기&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 방법이 추천되는 방법이다&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;794&quot; data-origin-height=&quot;948&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nxDW6/dJMcai4NALa/XDU7CNYTpGLbAmiJp9X6vk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nxDW6/dJMcai4NALa/XDU7CNYTpGLbAmiJp9X6vk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nxDW6/dJMcai4NALa/XDU7CNYTpGLbAmiJp9X6vk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FnxDW6%2FdJMcai4NALa%2FXDU7CNYTpGLbAmiJp9X6vk%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;447&quot; height=&quot;534&quot; data-origin-width=&quot;794&quot; data-origin-height=&quot;948&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;좋은 이유&lt;/h4&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;1. Dockerfile이 프로젝트 루트에 있어서 관리하기 좋음
2. GitHub에 올리기 좋음
3. 모듈러식 모놀리스 구조가 더 명확함
4. 나중에 docker-compose.yml 추가하기 좋음
5. build/libs 안에 직접 들어가지 않아도 됨
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Dockerfile 설정하기&lt;/h2&gt;
&lt;pre class=&quot;dockerfile&quot;&gt;&lt;code&gt;FROM eclipse-temurin:17-jre-alpine

WORKDIR /app

COPY app/build/libs/*.jar app.jar

EXPOSE 8080

ENTRYPOINT [&quot;java&quot;, &quot;-jar&quot;, &quot;app.jar&quot;]
&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;FROM&lt;/b&gt;&amp;nbsp;: Docker Base Image (기반이 되는 이미지, &amp;lt;이미지 이름&amp;gt;:&amp;lt;태그&amp;gt; 형식으로 설정, Java에 맞는 버전을 넣으면 된다)&lt;/li&gt;
&lt;li&gt;&lt;b&gt; &lt;span&gt;WORKDIR&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/b&gt; :컨테이너 내부에서 작업할 디렉터리를 지정한다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이후 실행되는 COPY, ENTRYPOINT 같은 명령어는 기본적으로 /app 경로를 기준으로 동작한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;COPY&lt;/b&gt; : 로컬에 있는 JAR 파일을 컨테이너 내부로 복사한다.
&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; 구조이기 때문에 auth, board, common을 각각 실행하는 것이 아니라, 실행 모듈인 app에서 하나의 JAR 파일을 만든다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;span&gt;EXPOSE : &lt;/span&gt;&lt;/b&gt;&lt;span&gt;컨테이너가 내부적으로 사용할 포트를 문서화한다.&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt; Spring Boot 애플리케이션은 기본적으로 8080 포트에서 실행되기 때문에 8080을 지정했다. &lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt; 다만 EXPOSE만으로 실제 포트가 열리는 것은 아니다.&lt;br /&gt;실제로 내 컴퓨터에서 접속하려면 docker run 할 때 -p 옵션으로 포트 매핑을 해야 한다.&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;예를&amp;nbsp;들어&amp;nbsp;-p&amp;nbsp;5000:8080은&amp;nbsp;내&amp;nbsp;PC의&amp;nbsp;5000번&amp;nbsp;포트로&amp;nbsp;들어온&amp;nbsp;요청을&amp;nbsp;컨테이너&amp;nbsp;내부의&amp;nbsp;8080번&amp;nbsp;포트로&amp;nbsp;전달한다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;ENTRYPOINT&lt;/b&gt; : 컨테이너가 시작될 때 실행할 명령어를 지정한다
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;여기서는 java -jar app.jar를 실행하여 Spring Boot 애플리케이션을 실행한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;stata&quot;&gt;&lt;code&gt;Java 17 실행 환경 준비
&amp;rarr; app/build/libs 안의 jar 복사
&amp;rarr; 컨테이너 안에서 app.jar로 이름 변경
&amp;rarr; 8080 포트 사용
&amp;rarr; java -jar app.jar 실행
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;DockerImage 만들기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;터미널의 위치는 Dockerfile이 있는 곳 이여야 한다.&lt;/p&gt;
&lt;pre class=&quot;asciidoc&quot;&gt;&lt;code&gt;**docker build -t {이미지명} .**

**설명**
docker build      &amp;rarr; Docker 이미지 만들기
-t 이미지명 &amp;rarr; 이미지 이름 지정
.                 &amp;rarr; 현재 폴더를 기준으로 Dockerfile 찾기
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;180&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/PLupu/dJMcagsrMd0/uM3vBZM4i9kEUoBafMn0Hk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/PLupu/dJMcagsrMd0/uM3vBZM4i9kEUoBafMn0Hk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/PLupu/dJMcagsrMd0/uM3vBZM4i9kEUoBafMn0Hk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FPLupu%2FdJMcagsrMd0%2FuM3vBZM4i9kEUoBafMn0Hk%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;1440&quot; height=&quot;180&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;180&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 확인할 수 있다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Docker 컨테이너 실행하기&lt;/h2&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;docker run --name 컨테이너명 -p 5000:8080 이미지명&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2048&quot; data-origin-height=&quot;653&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rmQjv/dJMcai4NAUN/LtS2rTsOWedAk6EfYrDth0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rmQjv/dJMcai4NAUN/LtS2rTsOWedAk6EfYrDth0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rmQjv/dJMcai4NAUN/LtS2rTsOWedAk6EfYrDth0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FrmQjv%2FdJMcai4NAUN%2FLtS2rTsOWedAk6EfYrDth0%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;819&quot; height=&quot;261&quot; data-origin-width=&quot;2048&quot; data-origin-height=&quot;653&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;--name appjam-auth-board-container &amp;rarr; 생성할 컨테이너 이름
-p 5000:8080 &amp;rarr; 내 PC의 5000번 포트를 컨테이너 내부 8080번 포트와 연결
appjam-auth-board &amp;rarr; 실행할 Docker 이미지 이름
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Docker Desktop&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Docker Desktop을 사용하면 Containers와 images를 쉽게 확인할 수 있을 뿐만 아니라 삭제 및 Container 중지/실행 모두 가능하다&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cCdVDY/dJMcah51b0i/JN4zNUWXZqYwqtOYkaOKy1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cCdVDY/dJMcah51b0i/JN4zNUWXZqYwqtOYkaOKy1/img.png&quot; data-origin-width=&quot;1102&quot; data-origin-height=&quot;1696&quot; data-is-animation=&quot;false&quot; width=&quot;622&quot; height=&quot;957&quot; style=&quot;width: 48.1521%; margin-right: 10px;&quot; data-widthpercent=&quot;48.72&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cCdVDY/dJMcah51b0i/JN4zNUWXZqYwqtOYkaOKy1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcCdVDY%2FdJMcah51b0i%2FJN4zNUWXZqYwqtOYkaOKy1%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;1102&quot; height=&quot;1696&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/btPYkW/dJMcahSnorj/FggpygurfEkX29oDsdHLhk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/btPYkW/dJMcahSnorj/FggpygurfEkX29oDsdHLhk/img.png&quot; data-origin-width=&quot;1082&quot; data-origin-height=&quot;1582&quot; data-is-animation=&quot;false&quot; width=&quot;659&quot; height=&quot;964&quot; style=&quot;width: 50.6851%;&quot; data-widthpercent=&quot;51.28&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/btPYkW/dJMcahSnorj/FggpygurfEkX29oDsdHLhk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbtPYkW%2FdJMcahSnorj%2FFggpygurfEkX29oDsdHLhk%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;1082&quot; height=&quot;1582&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;br /&gt;정리&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;모듈러식 모놀리스는 내부적으로 여러 모듈을 가지지만, 배포 관점에서는 하나의 애플리케이션으로 실행된다. 따라서 Docker 이미지도 auth, board, common을 각각 만드는 것이 아니라, 실행 모듈인 app에서 생성된 JAR 파일 하나를 기준으로 만든다.&lt;/blockquote&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;참고자료&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://da2uns2.tistory.com/entry/Docker-도커에-Spring-Boot-구축하기&quot;&gt;https://da2uns2.tistory.com/entry/Docker-도커에-Spring-Boot-구축하기&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Back-end/Spring</category>
      <category>backend</category>
      <category>docker</category>
      <category>Spring</category>
      <author>dev_Hyeonjoon</author>
      <guid isPermaLink="true">https://joon0112.tistory.com/80</guid>
      <comments>https://joon0112.tistory.com/80#entry80comment</comments>
      <pubDate>Wed, 24 Jun 2026 16:01:10 +0900</pubDate>
    </item>
    <item>
      <title>[Docker] Docker 입문: 이미지, 컨테이너, Registry, Docker Engine 정리</title>
      <link>https://joon0112.tistory.com/79</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;개발할 때는 잘 실행되던 애플리케이션이 서버에 배포하자마자 오류가 나는 경우가 있다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;운영체제, 라이브러리 버전, 실행 환경이 다르기 때문&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rArr; Docker는 이런 환경 차이를 줄이기 위해 등장한 컨테이너 기반 플랫폼이다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Docker란?&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;lsquo;컨테이너화&amp;rsquo;를 사용하여 응용 프로그램의 배포, 확장 및 관리를 자동화할 수 있는 오픈 소스 플랫폼이다&lt;/p&gt;
&lt;/blockquote&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;h3 data-ke-size=&quot;size23&quot;&gt;사용 이유&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Docker를 사용하는 가장 큰 이유는 environment disparity(환경 격차)라는 문제를 해결하는 것이다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;내 컴퓨터에서는 되는데 서버에서는 안 되는 문제&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;400&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qbJwf/dJMcaasfLm7/rJKc0GKblpR6mQG8NRKIK0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qbJwf/dJMcaasfLm7/rJKc0GKblpR6mQG8NRKIK0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qbJwf/dJMcaasfLm7/rJKc0GKblpR6mQG8NRKIK0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqbJwf%2FdJMcaasfLm7%2FrJKc0GKblpR6mQG8NRKIK0%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;586&quot; height=&quot;293&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;400&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기존에 내 컴퓨터가 Windows라고 하고, 실제 프로덕션 서버를 Linux라고 할 때 프로덕션 서버에 프로그램을 올리자 환경이 적절히 구성되어 있지 않으니 잘 안돌아간다&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;h3 data-ke-size=&quot;size23&quot;&gt;Docker의 해결방식&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Docker는 이런 문제를 런타임 환경을 표준화함으로써 이 문제를 해결하였다. 애플리케이션 코드와 특정 종속성을 단일 단위로 묶어 개발자 노트북, 테스트 서버 또는 클라우드 클러스터 등 어떤 환경에서든 소프트웨어가 동일하게 실행되도록 보장하였다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;휴대성: 로컬 컴퓨터, 클라우드, 온프레미스 서버 등 어디에서든 실행 가능&lt;/li&gt;
&lt;li&gt;일관성: 개발, 테스트 및 운영 환경에서 동일한 동작&lt;/li&gt;
&lt;li&gt;경량화: 앱별로 완전한 운영체제가 필요하지 않으며, 컨테이너는 호스트 커널을 공유&lt;/li&gt;
&lt;li&gt;확장성: 마이크로서비스 및 Kubernetes, Docker Swarm과 같은 오케스트레이터에 이상적&lt;/li&gt;
&lt;li&gt;효율성: 몇 초 만에 시작되며 시스템 리소스를 적게 사용&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;컨테이너화란?&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;680&quot; data-origin-height=&quot;400&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/clt0MK/dJMb99UmR2G/H4eKQL1AbSjQPhP1bqezO0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/clt0MK/dJMb99UmR2G/H4eKQL1AbSjQPhP1bqezO0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/clt0MK/dJMb99UmR2G/H4eKQL1AbSjQPhP1bqezO0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fclt0MK%2FdJMb99UmR2G%2FH4eKQL1AbSjQPhP1bqezO0%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;680&quot; height=&quot;400&quot; data-origin-width=&quot;680&quot; data-origin-height=&quot;400&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;응용 프로그램을 실행하는 데 필요한 모든 것을 포함한 가벼우며 격리된 환경을 제공
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;단, VM처럼 운영체제 전체를 포함하는 것이 아니라 호스트 OS의 커널을 공유하고, 필요한 실행 환경과 라이브러리만 이미지에 포함한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;코드, 실행 시간, 시스템 도구 및 라이브러리 등을 포함하여 응용 프로그램과 해당 종속성을 표준화된 단위로 패키징하여 일관되게 배포하고 실행하는 것이 컨테이너화의 목적&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, 어플리케이션을 개발 후 사용자가 실행할 때 필요한 환경들은 한번에 패키징하여 별 다른 설치 없이 한 번에 실행시켜주도록 하는 것&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;VM vs 컨테이너&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;718&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bfLhz9/dJMcafNTGcL/QA800pAoxrUB7tIobJlW0K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bfLhz9/dJMcafNTGcL/QA800pAoxrUB7tIobJlW0K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bfLhz9/dJMcafNTGcL/QA800pAoxrUB7tIobJlW0K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbfLhz9%2FdJMcafNTGcL%2FQA800pAoxrUB7tIobJlW0K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1280&quot; height=&quot;718&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;718&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt; 비교 요소 &lt;/b&gt;&lt;/td&gt;
&lt;td&gt;가상 머신 (VM)&lt;/td&gt;
&lt;td&gt;도커 (Docker)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;구조&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;하드웨어 위에 호스트 OS와 게스트 OS로 구성&lt;/td&gt;
&lt;td&gt;호스트 OS 위에서 동작하며 컨테이너화된 애플리케이션 실행&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;성능&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;하이퍼바이저로 인한 오버헤드로 약간의 성능 저하&lt;/td&gt;
&lt;td&gt;컨테이너화로 인한 가벼운 성능 손실&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;시작 시간&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;VM을 시작하기 위해 시간이 필요&lt;/td&gt;
&lt;td&gt;컨테이너는 몇 초 내에 시작 가능&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;자원 사용량&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;독립적인 자원을 사용하여 오버헤드 발생&lt;/td&gt;
&lt;td&gt;호스트의 커널 및 자원을 공유하여 효율적인 자원 사용&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;확장성&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;가상 머신은 더 많은 하드웨어를 추가하여 확장 가능&lt;/td&gt;
&lt;td&gt;도커는 컨테이너를 복제하여 수평으로 확장 가능&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;격리성&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;격리된 환경을 제공하여 보안을 강화&lt;/td&gt;
&lt;td&gt;호스트와 컨테이너 간 격리가 상대적으로 약함&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;관리 용이성&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;VM은 완전한 운영 체제를 관리해야 함&lt;/td&gt;
&lt;td&gt;도커는 이미지와 컨테이너를 사용하여 관리 용이&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Docker 아키텍처 및 작동 방식&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클라이언트 - 서버 아키텍처를 사용&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;300&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ZdyfX/dJMb991bxGN/0p2lcbMjJC0VLiYnIJ5hTk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ZdyfX/dJMb991bxGN/0p2lcbMjJC0VLiYnIJ5hTk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ZdyfX/dJMb991bxGN/0p2lcbMjJC0VLiYnIJ5hTk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FZdyfX%2FdJMb991bxGN%2F0p2lcbMjJC0VLiYnIJ5hTk%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;800&quot; height=&quot;300&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;300&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Client&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Docker 데몬과 통신하여 Docker 컨테이너를 빌드, 실행 및 배포하는 데 도움&lt;/li&gt;
&lt;li&gt;데몬과 같은 시스템에서 실행되거나, Docker 클라이언트를 Docker 데몬에 원격으로 연결할 수 있음&lt;/li&gt;
&lt;li&gt;Docker 클라이언트와 데몬은 유닉스 소켓이나 네트워크를 통한 REST API를 이용하여 서로 상호 작용한다&lt;/li&gt;
&lt;li&gt;Docker 명령어를 사용하여 컨테이너를 실행, 관리, 모니터링하고, 이미지를 빌드하거나 다운로드할 수 있음&lt;/li&gt;
&lt;li&gt;Docker 명령어를 통해 Docker Host와 상호작용 하는 역할&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Docker Host&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Docker Host는 Docker Engine이 설치되어 컨테이너를 실행하고 관리하는 환경이다. 물리 서버, 가상 머신, 클라우드 인스턴스 등이 Docker Host가 될 수 있다.&lt;/li&gt;
&lt;li&gt;Docker 데몬을 실행하여 컨테이너를 생성, 시작, 중지 및 관리를 수행하는 역할을 수행&lt;/li&gt;
&lt;li&gt;Client의 요청을 받아들이고 컨테이너를 생성, 시작, 중지, 제거하는 등의 작업을 수행
&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;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Docker Registry&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Docker 이미지를 저장 및 관리하는 중앙 집중 식 저장소&lt;/li&gt;
&lt;li&gt;공식적인 도커 레지스트리로, 도커 허브(Docker Hub)를 통해서 Docker 이미지를 공유하고 검색할 수 있도록 함
&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;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Docker 클라이언트, 도커 호스트, 도커 레지스트리 간 흐름&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1233&quot; data-origin-height=&quot;651&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/6qnAw/dJMcaaeIukZ/NzxN85RhLOZK7kqJWkXAs1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/6qnAw/dJMcaaeIukZ/NzxN85RhLOZK7kqJWkXAs1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/6qnAw/dJMcaaeIukZ/NzxN85RhLOZK7kqJWkXAs1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F6qnAw%2FdJMcaaeIukZ%2FNzxN85RhLOZK7kqJWkXAs1%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;1233&quot; height=&quot;651&quot; data-origin-width=&quot;1233&quot; data-origin-height=&quot;651&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;Client &amp;rarr; Docker Host&lt;/li&gt;
&lt;/ol&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;클라이언트(Client)는 도커 명령어(Docker run, build, pull, &amp;hellip;)를 사용하여 도커 호스트(Docker Host)에 요청&lt;/li&gt;
&lt;/ul&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;Docker Host&lt;/li&gt;
&lt;/ol&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;도커 호스트(Docker Host)는 클라이언트(Client)의 요청을 받아들이고 해당 요청에 따라 컨테이너를 생성, 중지, 제거하거나 이미지를 관리&lt;/li&gt;
&lt;/ul&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;Docker Host &amp;rarr; Registry&lt;/li&gt;
&lt;/ol&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;만약 클라이언트(Client)가 이미지를 생성하거나 업로드하려면, 도커 호스트(Docker Host)는 해당 이미지를 도커 레지스트리(Registry)에 업로드&lt;/li&gt;
&lt;/ul&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;Registry&lt;/li&gt;
&lt;/ol&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;도커 레지스트리(Registry)는 이미지를 저장하고 관리하는 중앙 집중식 저장소입니다. 도커 호스트(Docker Host)에서는 도커 레지스트리(Registry)에 이미지를 업로드하거나 다운로드할 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;Docker Host &amp;rarr; Client&lt;/li&gt;
&lt;/ol&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;컨테이너가 종료되면, 도커 호스트(Docker Host)는 해당 컨테이너의 상태와 결과를 클라이언트(Client)에게 반환&lt;/li&gt;
&lt;li&gt;이러한 과정들을 통하여 클라이언트, 도커 호스트, 도커 레지스트리는 도커 환경에서 상호작용하며 이미지 업로드와 다운로드, 컨테이너의 생성과 관리 등의 작업을 수행&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;구성 요소&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Docker의 주요 구성 요소 중 일부&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Docker Engine:&amp;nbsp; 컨테이너 생성 및 관리를 담당하는 핵심 부분인 Docker 데몬을 포함&lt;/li&gt;
&lt;li&gt;Dockerfile: 이미지를 빠르게 생성하는 단계를 설명하는 파일&lt;/li&gt;
&lt;li&gt;Docker 이미지:&amp;nbsp; 애플리케이션 코드와 종속성을 포함하는 컨테이너를 생성하는 데 사용되는 읽기 전용 템플릿&lt;/li&gt;
&lt;li&gt;Docker Hub: 컨테이너 이미지를 찾고 공유하는 데 사용되는 클라우드 기반 저장소&lt;/li&gt;
&lt;li&gt;Docker Registry: Docker 이미지를 저장하는 분산 시스템으로, 이미지를 공개 모드와 비공개 모드 모두에 저장할 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Docker Engine&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Docker Engine이 없다면 Docker 이미지를 빌드하거나 컨테이너를 실행할 수 없다&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;클라이언트는 Docker 명령 (docker build, docker run 등)을 보낸다.&lt;/li&gt;
&lt;li&gt;데몬은 이러한 명령어를 수신하고 컨테이너 작업을 수행&lt;/li&gt;
&lt;li&gt;REST API는 이러한 통신을 가능하게 하는 인터페이스&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;800&quot; data-origin-height=&quot;549&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/KEw16/dJMcagTwvgn/QVpT8qjEWKveJUiHi76RL1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/KEw16/dJMcagTwvgn/QVpT8qjEWKveJUiHi76RL1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/KEw16/dJMcagTwvgn/QVpT8qjEWKveJUiHi76RL1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FKEw16%2FdJMcagTwvgn%2FQVpT8qjEWKveJUiHi76RL1%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;800&quot; height=&quot;549&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;549&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, Docker Engine은 Docker 클라이언트와 데몬을 연결하여 컨테이너를 효율적으로 구축하고 관리함으로써 컨테이너화를 가능하게 하는 런타임&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Dockerfile&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DSL(도메인 특화 언어)을 사용하며 Docker 이미지를 생성하는 명령어를 포함&lt;/p&gt;
&lt;/blockquote&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;애플리케이션을 개발할 때 Docker 데몬이 모든 명령어를 위에서부터 순서대로 실행하므로 Dockerfile을 순서대로 작성하는 것이 좋다&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;800&quot; data-origin-height=&quot;300&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/4codt/dJMcaiqe1td/eUDm6nBKYyKRXOV3pFTmf1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/4codt/dJMcaiqe1td/eUDm6nBKYyKRXOV3pFTmf1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/4codt/dJMcaiqe1td/eUDm6nBKYyKRXOV3pFTmf1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F4codt%2FdJMcaiqe1td%2FeUDm6nBKYyKRXOV3pFTmf1%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;800&quot; height=&quot;300&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;300&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;※Docker 이미지는 Dockerfile을 사용하여 생성된다&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Docker 이미지&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Docker 이미지는 컨테이너를 생성하기 위한 읽기 전용 템플릿이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;애플리케이션 코드, 런타임, 라이브러리, 환경 변수, 실행 명령 등이 레이어 형태로 포함되어 있다.&lt;/p&gt;
&lt;/blockquote&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-origin-width=&quot;946&quot; data-origin-height=&quot;294&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/8eANy/dJMcadbkkeQ/ZkksrHSNyOvwDIkw1e7cEK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/8eANy/dJMcadbkkeQ/ZkksrHSNyOvwDIkw1e7cEK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/8eANy/dJMcadbkkeQ/ZkksrHSNyOvwDIkw1e7cEK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F8eANy%2FdJMcadbkkeQ%2FZkksrHSNyOvwDIkw1e7cEK%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;946&quot; height=&quot;294&quot; data-origin-width=&quot;946&quot; data-origin-height=&quot;294&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;작동 방식&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이 이미지는 컨테이너를 어떻게 생성해야 하는지를 정의한다.&lt;/li&gt;
&lt;li&gt;어떤 소프트웨어 구성 요소가 실행될지, 그리고 어떻게 구성될지를 지정한다.&lt;/li&gt;
&lt;li&gt;이미지가 실행되면 Docker 컨테이너가 된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;컨테이너와의 관계&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Docker 이미지&lt;/b&gt; &amp;rarr; Blueprint(정적, 읽기 전용).&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Docker 컨테이너&lt;/b&gt; &amp;rarr; 해당 이미지의 실행 중인 인스턴스 (동적, 실행 가능)&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Docker 컨테이너&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Docker 이미지의 경량 실행 가능한 인스턴스&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;애플리케이션 코드와 모든 종속성을 함께 패키징하여 격리된 환경에서 실행한다. 컨테이너를 사용하면 개발자 노트북, 테스트 서버, 프로덕션 환경 등 다양한 환경에서 애플리케이션을 빠르고 안정적으로 실행할 수 있다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Docker 이미지가 실행될 때 컨테이너가 생성된다.&lt;/li&gt;
&lt;li&gt;호스트 시스템에서 독립적인 프로세스로 실행되지만 호스트 시스템의 운영 체제 커널을 공유한다.&lt;/li&gt;
&lt;li&gt;여러 컨테이너가 서로 간섭하지 않고 동일한 시스템에서 실행할 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;이미지와의 관계:&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Docker 이미지&lt;/b&gt; &amp;rarr; Blueprint(정적, 읽기 전용).&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Docker 컨테이너&lt;/b&gt; &amp;rarr; 해당 이미지의 실행 중인 인스턴스 (동적, 실행 가능)&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Docker Hub&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저장소 서비스이며, 클라우드 기반 서비스로 사용자는 인터넷을 통해 언제 어디서든 Docker 컨테이너 이미지를 Docker Hub에 Push하거나 Docker 컨테이너 이미지를 가져올 수 있다&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;400&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cG9xFl/dJMcahY9Imu/hkbWEbb9Ey8dMRWskZRIf0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cG9xFl/dJMcahY9Imu/hkbWEbb9Ey8dMRWskZRIf0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cG9xFl/dJMcahY9Imu/hkbWEbb9Ey8dMRWskZRIf0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcG9xFl%2FdJMcahY9Imu%2FhkbWEbb9Ey8dMRWskZRIf0%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;800&quot; height=&quot;400&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;400&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;리포지토리 서비스&lt;/b&gt;: 사용자가 인터넷을 통해 어디에서든 컨테이너 이미지를 &lt;b&gt;푸시&lt;/b&gt; (업로드) 하거나 &lt;b&gt;풀&lt;/b&gt;(다운로드) 할 수 있는 글로벌 스토리지 허브 역할을 한다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;이미지 관리&lt;/b&gt;: 누구나 접근할 수 있는 &lt;b&gt;공개 레지스트리&lt;/b&gt; 또는 특정 사용자나 팀만 접근할 수 있는 &lt;b&gt;비공개 레지스트리&lt;/b&gt;에 이미지를 호스팅할 수 있는 유연성을 제공한다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;협업&lt;/b&gt;: 표준화된 환경을 팀이 찾고, 재사용하고, 공유할 수 있도록 하여 DevOps 워크플로를 간소화한다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;접근성&lt;/b&gt;: 모든 주요 운영 체제와 호환되는 오픈 소스 무료 도구이다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;리소스 라이브러리&lt;/b&gt;: Nginx, Python, Ubuntu와 같은 인기 소프트웨어의 수백만 개의 &amp;ldquo;공식 이미지&amp;rdquo;를 호스팅하여 프로젝트를 위한 검증된 시작점을 제공한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Registry와 Hub의 차이&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Docker Registry는 Docker 이미지를 저장하고 배포하는 저장소이다.&lt;/li&gt;
&lt;li&gt;Docker Hub는 Docker에서 공식적으로 제공하는 대표적인 공개 Registry 서비스이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;Docker 명령어&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Docker는 컨테이너 관리 프로세스를 간소화하는 강력한 소프트웨어로 자리매김했습니다. Docker는 원활한 개발 및 배포 워크플로우를 보장하는 데 도움이 됩니다. 다음은 일반적으로 사용되는 몇 가지 Docker 명령어입니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Docker Run:&lt;/b&gt; 이미지에서 컨테이너를 실행하는 데 사용되며, 런타임 옵션과 명령어를 지정&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Docker Pull:&lt;/b&gt; Docker Hub와 같은 컨테이너 레지스트리에서 컨테이너 이미지를 로컬 컴퓨터로 가져옴&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Docker ps:&lt;/b&gt; 명령어는 실행 중인 컨테이너와 컨테이너 ID, 사용 이미지, 상태 등의 중요한 정보를 표시하는 데 도움 됨&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Docker Stop&lt;/b&gt;: 실행 중인 컨테이너를 안전하게 종료하고 컨테이너 내부의 프로세스를 종료하는 데 도움이 된다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Docker Start:&lt;/b&gt; 중지된 컨테이너를 다시 시작하여 이전 상태에서 작업을 재개하는 데 도움이 된다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Docker 로그인:&lt;/b&gt; Docker 레지스트리에 로그인하여 비공개 저장소에 접근할 수 있도록 도와준다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;정리&lt;/h1&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결국 Docker는 &amp;ldquo;내 컴퓨터에서는 됐는데 서버에서는 안 돼요&amp;rdquo;라는 문제를 줄이기 위해 애플리케이션과 실행 환경을 하나의 컨테이너 단위로 패키징하는 기술이다. Docker를 사용하면 개발, 테스트, 운영 환경을 더 일관성 있게 유지할 수 있고, 컨테이너 기반 배포와 확장도 훨씬 쉬워진다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;참고 자료&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://adjh54.tistory.com/352&quot;&gt;https://adjh54.tistory.com/352&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://velog.io/@seokbin/신입을-위한-도커-기본-사용법&quot;&gt;https://velog.io/@seokbin/신입을-위한-도커-기본-사용법&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.geeksforgeeks.org/devops/introduction-to-docker/&quot;&gt;https://www.geeksforgeeks.org/devops/introduction-to-docker/&lt;/a&gt;&lt;/p&gt;</description>
      <category>Back-end/DevOps</category>
      <category>backend</category>
      <category>devops</category>
      <category>docker</category>
      <category>dockerfile</category>
      <category>DockerImage</category>
      <category>vm</category>
      <category>컨테이너</category>
      <author>dev_Hyeonjoon</author>
      <guid isPermaLink="true">https://joon0112.tistory.com/79</guid>
      <comments>https://joon0112.tistory.com/79#entry79comment</comments>
      <pubDate>Tue, 23 Jun 2026 15:20:56 +0900</pubDate>
    </item>
    <item>
      <title>SpringDoc Swagger에서 PathVariable Parameters가 비어 있을 때: Gradle -parameters 옵션 문제 해결기</title>
      <link>https://joon0112.tistory.com/78</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;문제 상황&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모듈식 모놀리스로 전환 후 Swagger API를 사용하여 API 명세를 손쉽게 하려고 세팅했었다. 하지만 Parameters 를 인식하지 못 하는 상황이 발생하게 되었다&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cVidaK/dJMcajvVbN2/BsSd0zzOJ3R8JboKPEtkM0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cVidaK/dJMcajvVbN2/BsSd0zzOJ3R8JboKPEtkM0/img.png&quot; data-origin-width=&quot;2048&quot; data-origin-height=&quot;1271&quot; data-is-animation=&quot;false&quot; width=&quot;535&quot; height=&quot;332&quot; style=&quot;width: 49.4186%; margin-right: 10px;&quot; data-widthpercent=&quot;50&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cVidaK/dJMcajvVbN2/BsSd0zzOJ3R8JboKPEtkM0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcVidaK%2FdJMcajvVbN2%2FBsSd0zzOJ3R8JboKPEtkM0%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;2048&quot; height=&quot;1271&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ZTKcK/dJMb99Ul4j2/cFGchUCmalQXsA8LsUeaqk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ZTKcK/dJMb99Ul4j2/cFGchUCmalQXsA8LsUeaqk/img.png&quot; data-origin-width=&quot;2048&quot; data-origin-height=&quot;1271&quot; data-is-animation=&quot;false&quot; width=&quot;559&quot; height=&quot;347&quot; style=&quot;width: 49.4186%;&quot; data-widthpercent=&quot;50&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ZTKcK/dJMb99Ul4j2/cFGchUCmalQXsA8LsUeaqk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FZTKcK%2FdJMb99Ul4j2%2FcFGchUCmalQXsA8LsUeaqk%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;2048&quot; height=&quot;1271&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;코드 뜯어보기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선 코드를 살펴보자면 저자는 Controller와 인터페이스를 사용한 Swagger API를 명확히 나눴다&lt;/p&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;@RestController
@RequiredArgsConstructor
@RequestMapping(&quot;/api/posts&quot;)
public class PostController implements PostAPI {
    private final PostService postService;

    @PostMapping
    public Long createPost(
            @Valid @RequestBody PostCreateRequest request
    ){
        return postService.createPost(request);
    }

    @GetMapping
    public List&amp;lt;PostResponse&amp;gt; findPosts(){
        return postService.getAllPosts();
    }

    @GetMapping(&quot;/{postId}&quot;)
    public PostResponse findPostById(
            @PathVariable Long postId
    ){
        return postService.findPostById(postId);
    }

    @PatchMapping(&quot;/{postId}&quot;)
    public PostResponse updatePost(
            @Valid @RequestBody PostUpdateRequest request,
            @PathVariable Long postId
    ){
        Long post = postService.updatePost(postId, request);
        return postService.findPostById(post);
    }

    @DeleteMapping(&quot;/{postId}&quot;)
    public void deletePost(
            @PathVariable Long postId
    ){
        postService.deletePost(postId);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;@Tag(name = &quot;Post&quot;, description = &quot;게시글 API&quot;)
public interface PostAPI {
    @Operation(summary = &quot;게시글 생성&quot;, description = &quot;게시글을 생성합니다.&quot;)
    Long createPost(
            @RequestBody PostCreateRequest request
    );

    @Operation(summary = &quot;게시글 리스트 조회&quot;, description = &quot;게시글 리스트를 조회합니다.&quot;)
    List&amp;lt;PostResponse&amp;gt; findPosts(
    );

    @Operation(summary = &quot;게시글 상세 조회&quot;, description = &quot;게시글 상세 조회합니다.&quot;)
    PostResponse findPostById(
            @PathVariable Long postId
    );
    @Operation(summary = &quot;게시글 삭제&quot;, description = &quot;게시글을 삭제합니다.&quot;)
    void deletePost(
            @PathVariable Long postId
    );
}&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;문제 원인&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PostAPI 구조 때문이 아니라, board 모듈 컴파일 결과에 파라미터 이름 메타데이터가 없어서&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원인을 Codex로 해결 할 수 있었다&lt;/p&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;RuntimeVisibleParameterAnnotations:
  parameter 0:
    org.springframework.web.bind.annotation.PathVariable&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;javap 결과에 LocalVariableTable에는 postId가 보이지만, Java reflection이 읽는 MethodParameters가 없던 문제였다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;쉽게 말하자면&lt;/p&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;소스코드에는 Long postId가 있음
컴파일된 클래스에는 @PathVariable은 있음
하지만 런타임 reflection 기준으로 &quot;이 파라미터 이름이 postId다&quot; 정보가 없음&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;때문이였다. 이런 일이 왜 발생했냐면&lt;/p&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;plugins {
    id 'java-library'
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모듈식 모놀리스로 나누는 과정에서 board/build.gradle 에서 java-library만 사용했기 때문이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한 Spring Boot Gradle 플러그인도 app에만 있던 상황인지라 board 컴파일에 -parameters 옵션이 안 붙어있던 상태였던 것. 루트 build.gradle를 살펴보면 현재 인코딩만 설정하고 있었다&lt;/p&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;tasks.withType(JavaCompile).configureEach {
    options.encoding = 'UTF-8'
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 SpringDoc이 @PathVariable Long postId를 봐도 이름을 못 얻었던 것. 결과적으로 /api/posts/{postId} 의 {postId}와 메서드 파라미터를 연결하지 못해서 parameters: [] 가 된다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;요약&lt;/h3&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;board 모듈이 -parameters 없이 컴파일됨
+ @PathVariable에 명시 이름이 없음
= springdoc이 postId 이름을 못 알아냄
= Swagger Parameters가 비어 있음&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;해결 방법&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. 루트 gradle 설정하기&lt;/h3&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;tasks.withType(JavaCompile).configureEach {
    options.encoding = 'UTF-8'
    options.compilerArgs += ['-parameters']
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;options.compilerArgs += ['-parameters'] 을 추가해주면 된다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이걸 루트 build.gradle의 subprojects 안에 넣으면 board, auth, app 전부 파라미터 이름이 보존된다&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. 각 @PathVariable에 이름을 명시 해주기&lt;/h3&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;@PathVariable(&quot;postId&quot;) Long postId&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;왜 안 되냐&amp;rdquo;의 진짜 이유는 &lt;b&gt;board 모듈 class 파일에 postId라는 파라미터 이름이 reflection metadata로 안 남아있기 때문&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1648&quot; data-origin-height=&quot;1402&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/zIcfC/dJMcafNSRhu/sU37057WvNJ02RlLmyES20/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/zIcfC/dJMcafNSRhu/sU37057WvNJ02RlLmyES20/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/zIcfC/dJMcafNSRhu/sU37057WvNJ02RlLmyES20/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FzIcfC%2FdJMcafNSRhu%2FsU37057WvNJ02RlLmyES20%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;1648&quot; height=&quot;1402&quot; data-origin-width=&quot;1648&quot; data-origin-height=&quot;1402&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>Back-end/Trouble Shooting</category>
      <category>Gradle -parameters</category>
      <category>parameters</category>
      <category>PathVariable</category>
      <category>SpringDoc</category>
      <category>swagger</category>
      <author>dev_Hyeonjoon</author>
      <guid isPermaLink="true">https://joon0112.tistory.com/78</guid>
      <comments>https://joon0112.tistory.com/78#entry78comment</comments>
      <pubDate>Mon, 22 Jun 2026 16:13:07 +0900</pubDate>
    </item>
    <item>
      <title>[LeetCode] 1. Two Sum (JAVA)</title>
      <link>https://joon0112.tistory.com/77</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;문제&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://leetcode.com/problems/two-sum/description/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;문제 링크&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;고민 했던 상황&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;배열 안에서 어떻게 해야 짝을 찾을 수 있을까? i,j 를 써서 j는 난수 인덱스로 지정해서 target 에 맞춰야하나? 라고 생각했었다&lt;/blockquote&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;나의 코드&lt;/h2&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;class Solution {
    public int[] twoSum(int[] nums, int target) {
        int sum = 0;

        int[] result = new int[2];

        for(int i = 0; i &amp;lt; nums.length; i++){
            for(int j = i+1; j &amp;lt; nums.length; j++){
                sum = nums[i] + nums[j];

                if(sum == target){
                    result[0] = i;
                    result[1] = j;

                    return result; //반복문 조기 종료를 위해서
                }
            }
        }
        return result;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;최선의 경우: O(1)
예: nums[0] + nums[1]이 바로 target인 경우

최악의 경우: O(n&amp;sup2;)
예: 정답이 맨 마지막 조합에 있거나, 거의 끝까지 탐색해야 하는 경우

평균적으로도: O(n&amp;sup2;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;896&quot; data-origin-height=&quot;1158&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bq70Tr/dJMcafAhZbf/05hV3Avwr6rFyMdoJKNZ3K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bq70Tr/dJMcafAhZbf/05hV3Avwr6rFyMdoJKNZ3K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bq70Tr/dJMcafAhZbf/05hV3Avwr6rFyMdoJKNZ3K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbq70Tr%2FdJMcafAhZbf%2F05hV3Avwr6rFyMdoJKNZ3K%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;412&quot; height=&quot;532&quot; data-origin-width=&quot;896&quot; data-origin-height=&quot;1158&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다른 사람들의 코드와 비교했을 때 딱히 좋은 성능은 아니였다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;다른 사람들의 코드는 HashMap을 사용해서 구현했기 때문이다&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;다른 코드&lt;/h2&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;class Solution {
    public int[] twoSum(int[] nums, int target) {
        Map&amp;lt;Integer, Integer&amp;gt; map = new HashMap&amp;lt;&amp;gt;();

        for (int i = 0; i &amp;lt; nums.length; i++) {
            if (map.containsKey(nums[i])) {
                return new int[]{map.get(nums[i]), i};
            }

            map.put(target - nums[i], i);
        }

        return new int[]{-1, -1};
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;핵심 아이디어&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재 숫자를 봤을 때, 이 숫자를 필요로 했던 이전 숫자가 있었는지 확인한다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 target = 9이고 현재 숫자가 2라면, 2와 더해서 9가 되려면 7이 필요하다.&lt;/p&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;target - nums[i]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, 9-2 = 7 이므로 7이 나중에 나오면 현재 숫자 2와 짝이 될 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 HashMap에는 현재 숫자 자체를 저장하는 것이 아니라, &lt;b&gt;앞으로 필요한 숫자&lt;/b&gt;를 key로 저장한다.&lt;/p&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;map.put(target - nums[i], i);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 의미는 다음과 같다.&lt;/p&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;key   : 앞으로 필요한 숫자
value : 그 숫자를 필요로 하는 현재 인덱스&lt;/code&gt;&lt;/pre&gt;</description>
      <category>CS/Algorithm</category>
      <category>leetcode</category>
      <category>알고리즘</category>
      <category>코딩테스트</category>
      <category>코테</category>
      <author>dev_Hyeonjoon</author>
      <guid isPermaLink="true">https://joon0112.tistory.com/77</guid>
      <comments>https://joon0112.tistory.com/77#entry77comment</comments>
      <pubDate>Sun, 21 Jun 2026 22:48:02 +0900</pubDate>
    </item>
    <item>
      <title>모듈러 모놀리스(modular monolith) 아키텍처가 뭘까?</title>
      <link>https://joon0112.tistory.com/76</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;탄생 배경&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;MSA의 장점을 가지고 다른 기업에서 적용시키다 보니 아래와 같은 문제들이 나타나게 되었다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;MSA의 부작용&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;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특히, 팀이 작을 수록 아래와 같은 문제점이 발생함&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;팀이 작을 때&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;쓸데 없이 나눈 서비스 수가 오히려 불편함만 가져옴
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;즉, 서비스 수 &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;Conway&amp;rsquo;s Law - 조직이 아키텍쳐를 결정&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;복잡성이 증가할 수 록 소규모 팀에서는 발목이 잡히는 경우 발생&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;모듈러 모놀리스&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1001&quot; data-origin-height=&quot;471&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/72Vtz/dJMcahLBONN/vjlxSSgTe9D3Id9wdLpgwK/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/72Vtz/dJMcahLBONN/vjlxSSgTe9D3Id9wdLpgwK/img.webp&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/72Vtz/dJMcahLBONN/vjlxSSgTe9D3Id9wdLpgwK/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F72Vtz%2FdJMcahLBONN%2FvjlxSSgTe9D3Id9wdLpgwK%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;1001&quot; height=&quot;471&quot; data-origin-width=&quot;1001&quot; data-origin-height=&quot;471&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모놀리식과 모듈식 설계 패러다임의 측면을 결합한 아키텍처 접근&lt;/p&gt;
&lt;/blockquote&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;모듈은 일반적으로 비즈니스 역량 또는 도메인 주도 설계 (DDD) 원칙을 중심으로 조직된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;특징&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;모듈성&lt;/b&gt;:
&lt;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;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;모듈 구조를 가지지만 모든 모듈은 하나의 코드베이스와 런타임 환경 안에서 긴밀히 통합된다.&lt;/li&gt;
&lt;li&gt;모듈 간 별도의 배포나 통신 메커니즘이 필요 xx&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;모든 모듈이 동일한 코드베이스, 라이브러리, 데이터 저장소를 공유&lt;/li&gt;
&lt;li&gt;이는 분산 시스템에 비해 개발과 배포를 단순화하면서도, 코드 조직과 관심사 분리 같은 모듈성의 이점을 유지하게 된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;확장성&amp;nbsp;및 유지보수성&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;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;단일 코드베이스임에도 개발과 배포 측면에서 유연&lt;/li&gt;
&lt;li&gt;전체 시스템에 영향을 주지 않고도 요구 사항 변경에 맞춰 모듈을 쉽게 추가, 제거, 수정 가능&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;배포 아티팩트가 하나뿐이므로 분산 시스템에 비해 배포가 더 간단하다.&lt;/li&gt;
&lt;li&gt;배포와 운영의 복잡성이 줄어들어 애플리케이션 라이프사이클 관리가 쉬워짐&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rArr; 모듈성과 모놀리식 아키텍처의 단순함을 결합함으로써, 모듈러 모놀리식은 유연성, 확장성, 유지보수성 간 균형을 이루어 &lt;b&gt;중간 정도의 복잡성과 확장성 요구를 가진 애플리케이션에 적합&lt;/b&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;원칙&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;모듈성&lt;/b&gt;
&lt;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;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;각 모듈은 정확하고 집중된 목적을 가져야 하며 애플리케이션의 특정 측면을 책임져야 한다.(높은 응집도)&lt;/li&gt;
&lt;li&gt;동시에 모듈 간 의존은 느슨해야 하며 서로에 과도하게 의존해서는 안된다.(낮은 결합도)&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;모듈 간 경계를 명확히 정의하여 의존성을 최소화하고, 독립적인 개발과 테스트를 용이하게 한다.&lt;/li&gt;
&lt;li&gt;모듈을 뒤섞거나 강한 결합을 도입하면 복잡성이 증가하고 변경이 어려워진다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;단일 책임 원칙(SRP)&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;h3 data-ke-size=&quot;size23&quot;&gt;패턴&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;레이어드 아키텍처&lt;/b&gt;
&lt;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;일반적으로 표현/UI 레이어, 비즈니스 로직 레이저, 데이터 접근 레이어가 포함된다.&lt;/li&gt;
&lt;li&gt;관심사의 분리를 촉진하고 확장성과 유지보수성을 높임&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;애플리케이션을 더 작고 독립적인 모듈로 분해하며, 각 모듈은 특정 기능이나 비즈니스 도메인을 담당한다&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;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;애플리케이션을 재사용 가능한 독립 컴포넌트로 조직하며, 각 컴포넌트는 관련 집합을 캡슐화한다.&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;&lt;b&gt;단점&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;복잡성 관리&lt;/b&gt;: 애플리케이션의 규모와 복잡성이 커질수록 모듈 간 상호작용을 관리하고 코드베이스 전반의 일관성을 보장하는 일이 어려워질 수 있다.
&lt;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;의존성 관리&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;배포 복잡성&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;테스트 오버헤드&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;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3가지 아키텍처 비교&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;모놀리스 방식&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;경계 x&lt;/p&gt;
&lt;/blockquote&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;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;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;모듈러 모놀리스&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;도메인 경계 강제&lt;/p&gt;
&lt;/blockquote&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;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;내부적으로 도메인 경계를 강제함으로써 팀이 분리되고 서비스가 커지면 MSA로 자연스럽게 분리 및 확장이 가능하게 한다&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;MSA&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;독립 배포 단위&lt;/p&gt;
&lt;/blockquote&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;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;전환 전략&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모놀리스 &amp;rarr; 모듈러 &amp;rarr; MSA&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모놀리스를 처음으로 하는 이유는 도메인 경계를 정확히 식별하기 위함이다. 댓글을 찾아보던 중 정확하게 식별을 하지 않는다면 모듈러 모놀리스의 구조는 이상하게 간다고 한다&amp;hellip;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모듈러 모놀리스는 MSA의 예행연습이라고 한다. 경계를 코드로 강제해두면, 필요할 때 쪼개기가 훨씬 수월하여 MSA 전환이 가능하다는 점이다&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;참고자료&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=3UJhhMultL4&quot;&gt;https://www.youtube.com/watch?v=3UJhhMultL4&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://rosettalens.com/s/ko/what-is-a-modular-monolith&quot;&gt;https://rosettalens.com/s/ko/what-is-a-modular-monolith&lt;/a&gt;&lt;/p&gt;</description>
      <category>Back-end/Architecture</category>
      <category>모놀리스</category>
      <category>모듈러</category>
      <category>모듈러 모놀리스</category>
      <category>아키텍처</category>
      <author>dev_Hyeonjoon</author>
      <guid isPermaLink="true">https://joon0112.tistory.com/76</guid>
      <comments>https://joon0112.tistory.com/76#entry76comment</comments>
      <pubDate>Fri, 19 Jun 2026 22:06:14 +0900</pubDate>
    </item>
    <item>
      <title>멀티모듈 환경에서 공통 모듈을 설계하는 방법: 유스케이스 분리와 인프라 설정 제어 with Spring Boot</title>
      <link>https://joon0112.tistory.com/75</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;도메인 로직과 유스케이스&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;핵심 비즈니스 로직&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;현실 세계의 비즈니스 규칙 그 자체&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;유스케이스&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;사용자가 시스템을 통해 어떤 목적을 달성하는 흐름&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;예시&lt;/h3&gt;
&lt;pre class=&quot;asciidoc&quot;&gt;&lt;code&gt;도메인 로직:
- 게시글 제목은 비어 있을 수 없다.
- 삭제된 게시글에는 댓글을 달 수 없다.
- 작성자만 게시글을 수정할 수 있다.

유스케이스:
- 게시글 작성하기
- 게시글 수정하기
- 게시글 삭제하기
- 게시글 목록 조회하기
&lt;/code&gt;&lt;/pre&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;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;유스케이스를 공통 코드로 뺀다면, 사이드 이펙트가 발생하기 쉬울 뿐만 아니라 예외 케이스를 위한 분기 처리도 들어가게 되면서 많은 문제가 발생한다&lt;/li&gt;
&lt;li&gt;또한 유스케이스는 서비스마다 요구 사항이 다르기 쉽기 때문이다&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 게시글 작성 이라는 이름은 같아도,&lt;/p&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;board-service:
- 게시글 저장
- 작성자 검증
- 카테고리 검증

community-service:
- 게시글 저장
- 알림 발송
- 포인트 지급
- 신고 제한 검증&lt;/code&gt;&lt;/pre&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;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;if (serviceType==BOARD) {
    ...
}else if (serviceType==COMMUNITY) {
    ...
}&lt;/code&gt;&lt;/pre&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;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;공통 모듈에 넣어도 되는 것:
- 공통 예외
- 공통 응답 형식
- 공통 유틸
- 공통 인증 객체
- 공통 타입
- 정말 안정적인 shared kernel

공통 모듈에 넣으면 위험한 것:
- 유스케이스
- 서비스별 비즈니스 흐름
- 특정 서비스의 Repository
- 특정 서비스의 Entity
- 특정 서비스의 Application Service&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;자동 빈 등록 방식을 피해야한다&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;공통 인프라 설정 모듈에서는 컴포넌트 스캔에 의존한 자동 등록을 피하고, 각 서비스가 필요한 설정만 명시적으로 선택하도록 하는 것이 좋다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;주의점&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모든 @Component, @Service, @Repository를 쓰지 말라는 뜻이 아니다&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;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;@Service
publicclassCreateBoardUseCase {
    ...
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;@Repository
publicinterfaceBoardRepositoryextendsJpaRepository&amp;lt;Board,Long&amp;gt; {
}&lt;/code&gt;&lt;/pre&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;li&gt;또한 해당 방식은 어떤 인프라 구성들이 존재하는지, 무엇이 현재 모듈에 적용되는지 명시적으로 파악하기가 어렵다&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 공통 모듈에 이런 설정이 있다고 해보자&lt;/p&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;@Configuration
@EnableJpaRepositories(...)
public class JpaConfig {
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이게 컴포넌트 스캔으로 자동 등록된다면, 어떤 서비스에서는 JPA가 필요없는데도 JPA 설정이 들어올 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또는 어떤 서비스는 Redis만 필요한데, JPA, Async, Jasypt까지 딸려올 수도 있다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 우리는 인프라 구성에 대한 제어권을 획득할 수 있는 방법을 사용하는 것이 좋은데, 이 때 Spring 프레임워크에서 제공하는 ImportSelector를 이용하여 이를 구현해보도록 하자&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;인터페이스를 구성하자&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각 서비스가 필요한 인프라 설정만 선택해서 사용한다.&lt;/p&gt;
&lt;/blockquote&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;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;public interface BoardInfraConfig {
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모든 인프라 구성들은 해당 인터페이스를 구현한다. 구성 클래스들에는 자동 빈 스캔 방식에 의해 등록되지 않도록 @Component 를 포함한 하위 어노테이션들이 존재하지 않는다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;설정 클래스의 의미 붙이기&lt;/h2&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;@Configuration(proxyBeanMethods = false)
@EnableAsync
public class AsyncConfig implements BoardInfraConfig {

    ...

}

@Configuration(proxyBeanMethods = false)
@EnableTransactionManagement
@EntityScan(&quot;com.mangkyu.appstore&quot;)
@EnableJpaRepositories(&quot;com.mangkyu.appstore&quot;)
public class JpaConfig implements BoardInfraConfig {

    ...

}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;@Configuration(proxyBeanMethods = false) 를 붙이는 게 의도를 명확히 드러내기에 안전하다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 이렇게 하면 @Configuration도 결국 내부적으로는 @Component 계열이라서 컴포넌트 스캔 대상이 될 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 자동 등록을 피하려면 아래와 같다&lt;/p&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;1. 해당 설정 클래스를 컴포넌트 스캔 범위 밖에 두거나
2. 메인 애플리케이션의 scanBasePackages에 포함되지 않게 하거나
3. @Import / ImportSelector로만 가져오도록 구조를 잡아야 함&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉 ,@Configuration 을 붙이면 무조건 문제가 아니라, 스캔으로 자동 등록되지 않게 패키지 구조를 잘 잡는 게 중요하다&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 구성 클래스들을 모아둔 enum 클래스를 하나 생성한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를 통해 인프라 구성들이 존재하는지, 무엇을 적용할지 손쉽게 파악할 수 있다.&lt;/p&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;@Getter
@RequiredArgsConstructor
public enum BoardConfig{

	ASYNC(AsyncConfig.class),
	JASYPT(JasyptConfig.class),
	JPA(JpaConfig.class),
	;

	private final Class&amp;lt;? extends BoardConfig&amp;gt; configClass;
	
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기까지 했다면 적용할 인프라 구성을 명시할 @Enable 어노테이션과 어노테이션에 존재하는 인프라 구성을 적용시켜 줄 ImportSelector를 구현한다. ImportSelector는 애플리케이션이 실행되는 시점에 해당 어노테이션에 붙은 Enum 값들을 기반으로 동적으로 구성 파일들을 불러온다.&lt;/p&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Import(BoardConfigImportSelector.class)
public @interface EnableBoardConfig {

    BoardConfigGroup[] value();

}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ImportSelector를 구현할 때는 ImportSelector의 하위 인터페이스인 DeferredImportSelector를 사용하면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DeferredImportSelector는 모든 @Configuration 빈들이 처리된 후에 동작하는 ImportSelector이다. 선택된 설정들이 @Conditional 조건을 갖고 있는 경에 유용하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를 처리하기 위해 EnableBoardConfig의 value에 할당된 Enum 값들을 모두 불러온 후에 configClass 값을 가져와야한다. 이러한 역할을 담당하는 ImportSelector 구현체는 다음과 같이 만들어줄 수 있다.&lt;/p&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;public class BoardConfigImportSelector implements DeferredImportSelector {

    @Override
    public String[] selectImports(AnnotationMetadata metadata) {
        return Arrays.stream(getValues(metadata))
                .map(value -&amp;gt; value.getConfigClass().getName())
                .toArray(String[]::new);
    }

    private BoardConfigGroup[] getValues(AnnotationMetadata metadata) {
        Map&amp;lt;String, Object&amp;gt; attributes =
                metadata.getAnnotationAttributes(EnableBoardConfig.class.getName());

        if (attributes == null) {
            return new BoardConfigGroup[]{};
        }

        return (BoardConfigGroup[]) attributes.getOrDefault(
                &quot;value&quot;,
                new BoardConfigGroup[]{}
        );
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러면 이제 다음과 같이 개별 모듈들에서 적용할 인프라 구성을 동적으로 그리고 명시적으로 선택할 수 있다. 이를 통해 인프라 구성에 대한 제어권을 획득할 수 있게 된 것이다.&lt;/p&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;@Configuration(proxyBeanMethods = false)
@EnableAppStoreConfig({
    BoardConfigGroup.ASYNC,
    BoardConfigGroup.JASYPT,
    BoardConfigGroup.JPA,
})

class InfraConfig {

}&lt;/code&gt;&lt;/pre&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://mangkyu.tistory.com/304&quot;&gt;https://mangkyu.tistory.com/304&lt;/a&gt;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;결론&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;공통 모듈은 최대한 작고 안정적으로 유지한다.&lt;/li&gt;
&lt;li&gt;유스케이스는 각 서비스 내부에 둔다.&lt;/li&gt;
&lt;li&gt;인프라 설정은 필요한 서비스가 명시적으로 선택하게 한다.&lt;/li&gt;
&lt;li&gt;컴포넌트 스캔으로 의도치 않은 Bean이 등록되지 않게 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt; 참고자료&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://mangkyu.tistory.com/304&quot;&gt;https://mangkyu.tistory.com/304&lt;/a&gt;&lt;/p&gt;</description>
      <category>CS/Architecture</category>
      <category>importselector</category>
      <category>MSA</category>
      <category>Spring</category>
      <category>Spring Boot</category>
      <category>공통모듈</category>
      <category>도메인로직</category>
      <category>멀티모듈</category>
      <category>백엔드</category>
      <category>유스케이스</category>
      <author>dev_Hyeonjoon</author>
      <guid isPermaLink="true">https://joon0112.tistory.com/75</guid>
      <comments>https://joon0112.tistory.com/75#entry75comment</comments>
      <pubDate>Thu, 18 Jun 2026 15:49:51 +0900</pubDate>
    </item>
    <item>
      <title>GitHub Issue / PR 템플릿으로 일관성있게 작업하기</title>
      <link>https://joon0112.tistory.com/74</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;GitHub에서 Issue와 Pull Request를 작성하다 보면 매번 내용을 새로 작성해야 해서 생각보다 번거로운 경우가 많습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특히 협업을 할 때는 사람마다 Issue나 PR을 작성하는 방식이 달라서, 어떤 Issue에는 작업 내용이 빠져 있고 어떤 PR에는 리뷰어가 확인해야 할 내용이 부족한 상황이 생기기도 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;물론 팀에서 미리 형식을 정해둘 수도 있지만, 매번 직접 작성하다 보면 실수로 특정 항목을 빼먹는 경우가 생길 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 이번에는 GitHub에서 Issue와 PR 템플릿을 만들어, 협업 시 작성 형식을 조금 더 일관성 있게 관리하는 방법을 정리해보려고 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;템플릿을 미리 만들어두면 Issue나 PR을 생성할 때 정해진 양식이 자동으로 표시되기 때문에, 작성 시간을 줄이고 협업 과정에서도 필요한 정보를 빠뜨리지 않도록 도와줄 수 있습니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Issue 템플릿 생성하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 프로젝트 루트 경로에 .github 폴더를 만들고, 그 안에 ISSUE_TEMPLATE 폴더를 생성합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구조는 다음과 같습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;910&quot; data-origin-height=&quot;132&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ss4DO/dJMcajoZ3r0/ymY5W2dMULqKv7KgWzQp00/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ss4DO/dJMcajoZ3r0/ymY5W2dMULqKv7KgWzQp00/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ss4DO/dJMcajoZ3r0/ymY5W2dMULqKv7KgWzQp00/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fss4DO%2FdJMcajoZ3r0%2FymY5W2dMULqKv7KgWzQp00%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;910&quot; height=&quot;132&quot; data-origin-width=&quot;910&quot; data-origin-height=&quot;132&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후 issue-template.md 파일 안에 원하는 Issue 템플릿을 작성하면 됩니다.&lt;/p&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;---
name: &quot;\bIssue 생성 템플릿&quot;
about: 이슈 생성을 위한 템플릿입니다.
title: ''
labels: ''
assignees: ''

---

## 어떤 기능인가요?
&amp;gt; 추가하려는 기능에 대해 간결하게 설명해주세요

##   작업 상세 내용
- [ ] 구현 내용
- [ ] 
- [ ] 

##   참고 자료 (선택)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와 같이 작성해두면 새로운 Issue를 생성할 때 해당 템플릿을 선택해서 사용할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를 통해 기능 설명, 작업 상세 내용, 참고 자료 등을 일정한 형식으로 작성할 수 있어 협업 과정에서 Issue 관리가 훨씬 쉬워집니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;PR 템플릿&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Pull Request 템플릿도 비슷한 방식으로 만들 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로젝트 루트 경로에 .github 폴더를 만들고, 그 안에 pull_request_template.md 파일을 생성합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구조는 다음과 같습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;846&quot; data-origin-height=&quot;176&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/brvHHD/dJMcadWHzm7/3LiGleiZBB6kfUBzYQADEk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/brvHHD/dJMcadWHzm7/3LiGleiZBB6kfUBzYQADEk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/brvHHD/dJMcadWHzm7/3LiGleiZBB6kfUBzYQADEk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbrvHHD%2FdJMcadWHzm7%2F3LiGleiZBB6kfUBzYQADEk%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;846&quot; height=&quot;176&quot; data-origin-width=&quot;846&quot; data-origin-height=&quot;176&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후 pull_request_template.md 파일 안에 원하는 PR 템플릿을 작성하면 됩니다.&lt;/p&gt;
&lt;pre class=&quot;shell&quot;&gt;&lt;code&gt;## #️⃣연관된 이슈

&amp;gt; ex) #이슈번호, #이슈번호

##  작업 내용

&amp;gt; 이번 PR에서 작업한 내용을 간략히 설명해주세요(이미지 첨부 가능)

### 스크린샷 (선택)

##  리뷰 요구사항(선택)

&amp;gt; 리뷰어가 특별히 봐주었으면 하는 부분이 있다면 작성해주세요
&amp;gt;
&amp;gt; ex) 메서드 XXX의 이름을 더 잘 짓고 싶은데 혹시 좋은 명칭이 있을까요?
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PR 템플릿을 만들어두면 Pull Request를 생성할 때 본문에 위 양식이 자동으로 들어갑니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;덕분에 작업 내용, 관련 Issue, 리뷰 요청 사항 등을 빠뜨리지 않고 작성할 수 있으며, 리뷰어 입장에서도 변경 사항을 더 쉽게 파악할 수 있습니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;이슈 올리기&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2626&quot; data-origin-height=&quot;834&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/7llH6/dJMcaf1go6e/7ahsai2F69QPbbhGlhocxk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/7llH6/dJMcaf1go6e/7ahsai2F69QPbbhGlhocxk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/7llH6/dJMcaf1go6e/7ahsai2F69QPbbhGlhocxk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F7llH6%2FdJMcaf1go6e%2F7ahsai2F69QPbbhGlhocxk%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;2626&quot; height=&quot;834&quot; data-origin-width=&quot;2626&quot; data-origin-height=&quot;834&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2600&quot; data-origin-height=&quot;1328&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cDaXAe/dJMcadWHznc/7Z3VvZkclVTupnXIMgKFi0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cDaXAe/dJMcadWHznc/7Z3VvZkclVTupnXIMgKFi0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cDaXAe/dJMcadWHznc/7Z3VvZkclVTupnXIMgKFi0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcDaXAe%2FdJMcadWHznc%2F7Z3VvZkclVTupnXIMgKFi0%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;2600&quot; height=&quot;1328&quot; data-origin-width=&quot;2600&quot; data-origin-height=&quot;1328&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1796&quot; data-origin-height=&quot;1280&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cYkemu/dJMcadWHznd/FYkKYD1kb1IpJJh0xv1Buk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cYkemu/dJMcadWHznd/FYkKYD1kb1IpJJh0xv1Buk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cYkemu/dJMcadWHznd/FYkKYD1kb1IpJJh0xv1Buk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcYkemu%2FdJMcadWHznd%2FFYkKYD1kb1IpJJh0xv1Buk%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;1796&quot; height=&quot;1280&quot; data-origin-width=&quot;1796&quot; data-origin-height=&quot;1280&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;마무리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Issue와 PR 템플릿은 설정 자체는 간단하지만, 협업할 때는 꽤 큰 도움이 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;매번 같은 내용을 반복해서 작성하지 않아도 되고, 팀원마다 다른 방식으로 작성하던 Issue와 PR을 일정한 형식으로 맞출 수 있기 때문입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;작은 설정이지만 협업의 흐름을 깔끔하게 만들어주는 기능이기 때문에, 팀 프로젝트를 진행한다면 초기에 설정해두는 것을 추천합니다.&lt;/p&gt;</description>
      <category>Tools/GitHub</category>
      <category>git</category>
      <category>github</category>
      <category>issue</category>
      <category>템플릿</category>
      <author>dev_Hyeonjoon</author>
      <guid isPermaLink="true">https://joon0112.tistory.com/74</guid>
      <comments>https://joon0112.tistory.com/74#entry74comment</comments>
      <pubDate>Thu, 18 Jun 2026 06:43:40 +0900</pubDate>
    </item>
    <item>
      <title>[Spring] Business Layer와 Presentation Layer 분리의 중요성</title>
      <link>https://joon0112.tistory.com/73</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp; 결론&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Request/Response DTO는 API 입출력 형식에 가깝고, API 요구사항은 FE 화면 구성이나 기획 변경에 따라 자주 바뀐다. 그래서 Service가 DTO를 직접 반환하면 비즈니스 로직이 프레젠테이션 계층의 변화에 끌려다닐 수 있다. 이번 프로젝트에서는 Service는 Entity, VO, primitive, Map 같은 비즈니스에 가까운 값을 반환하고, Controller에서 Response DTO로 변환하는 방식을 사용했다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. 문제 발생 상황&lt;/h2&gt;
&lt;div data-block-id=&quot;371190e2-f732-8059-a2dd-faaff90fe160&quot;&gt;
&lt;div style=&quot;color: #000000;&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 SOPT에서 합동 세미나를 진행했고 아래와 같은 일이 있었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내가 원래 배웠던 구조는 차트 API, 좋아요 토글 API, 아티스트 곡 목록 API를 구현하면서 Service가 바로 Response DTO를 반환할 수 있었다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 리드님께서는 Business Layer와 Presentation Layer 를 확실히 원했고 합동 세미나 그라운드 룰에 규칙을 적으셨다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;합동 세미나 그라운드 룰을 만들면서 &amp;rdquo;귀찮게 왜 분리시키는거지? 한 번에 해결하면 쉽고 파일양도 줄일 수 있어서 이득 아닌가..?&amp;rdquo; 라는 생각에 사로 잡혀있었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 이렇게 하면 Service가 API 응답 형태를 알게 되어버리는 문제가 있었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2. 합동 세미나 그라운드 룰&lt;/h2&gt;
&lt;div data-block-id=&quot;371190e2-f732-808b-bf27-e996d50849aa&quot;&gt;
&lt;div&gt;
&lt;div style=&quot;color: #000000;&quot;&gt;
&lt;div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;비즈니스 로직: 서버가 책임지는 규칙
&lt;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;프레젠테이션 로직: API 응답을 어떻게 보여줄지 조립하는 영역
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;예: FE가 필요한 형태로&amp;nbsp;songId,&amp;nbsp;title,&amp;nbsp;artist,&amp;nbsp;albumImageUrl을 묶어서 내려주기
&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;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rArr; Service는 최대한 얇게, Controller에서는 조립 시키기!&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3. 합동세미나 예시&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;문제 발생 상황&lt;/h3&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;public record ChartSongInfo(
				 Long songId,
        String title,
        Long artistId,
        String artistName,
        String albumImageUrl
) {

}&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;맨 처음에는 Vo객체는 관심사를 모으는 걸로 이해해서 곡과 아티스트를 한꺼번에 모으면 되겠네 하고 Vo패키지에 적용시켰다&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class ChartService {

    private final SongDetailRepository songDetailRepository;

    public ChartResponse findChartByFilter(final ChartFilterType chartFilterType) {
        List&amp;lt;ChartSongInfo&amp;gt; chartSongs = switch (chartFilterType) {
            case TOP100 -&amp;gt; songDetailRepository.findTop100Chart();
            case HOT100 -&amp;gt; songDetailRepository.findHot100Chart();
            case ABROAD_2006, SWEET -&amp;gt; songDetailRepository.readChart();
        };

        return ChartResponse.of(chartSongs);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;그 후 Service에서는 dto/reponse/에 있는 ChartResponse를 바로 반환하는 실수를 했었다
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;그라운드 룰에 의해 Service에서는 dto를 반환하면 안됨&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;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;vo 객체가 필요없다고 판단이 들어서 삭제 시켰다
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;ChartResponse에서 아래와 같이 반환하게 되면 join도 필요없이 반환할 수 있다는 장점에서 삭제&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;public record ChartResponse(
        @Schema(description = &quot;차트 곡 목록&quot;)
        List&amp;lt;SongInfo&amp;gt; songs
) {

    public static ChartResponse of(List&amp;lt;Song&amp;gt; songs, Map&amp;lt;Long, List&amp;lt;Artist&amp;gt;&amp;gt; artistsMap) {
        return new ChartResponse(
                songs.stream()
                        .map(song -&amp;gt; SongInfo.of(
                                song,
                                artistsMap.getOrDefault(song.getId(), List.of())
                        ))
                        .toList()
        );
    }

    public record SongInfo(
            @Schema(description = &quot;곡 ID&quot;, example = &quot;1&quot;)
            Long songId,

            String albumImageUrl

    ) {

        public static SongInfo of(Song song, List&amp;lt;Artist&amp;gt; artists) {
            Artist artist = artists.getFirst();

            return new SongInfo(
                    song.getId(),
                    song.getTitle(),
                    new ArtistInfo(artist),
                    song.getAlbum().getImageUrl()
            );
        }
    }

    public record ArtistInfo(
            String name
    ) {

        public ArtistInfo(Artist artist) {
            this(artist.getId(), artist.getName());
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;Service는 Entity, VO, primitive, Map 같은 비즈니스에 가까운 값을 반환하기
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Mapper를 사용한 아티스트 곡 목록 조회 Service&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class=&quot;swift&quot;&gt;&lt;code&gt;package org.sopt.collaboration.melon.domain.song.service;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import org.sopt.collaboration.melon.domain.artist.entity.Artist;
import org.sopt.collaboration.melon.domain.song.entity.Song;
import org.sopt.collaboration.melon.domain.song.entity.SongArtist;
import org.sopt.collaboration.melon.domain.song.repository.SongArtistRepository;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class SongArtistService {

    private final SongArtistRepository songArtistRepository;

    public List&amp;lt;Artist&amp;gt; findAllArtistsBySongId(Long songId) {
        return songArtistRepository.findAllBySongId(songId)
                .stream()
                .map(SongArtist::getArtist)
                .toList();
    }

    public Map&amp;lt;Long, List&amp;lt;Artist&amp;gt;&amp;gt; findArtistAsMap(List&amp;lt;Song&amp;gt; songs) {
        List&amp;lt;Long&amp;gt; songIds = songs.stream()
                .map(Song::getId)
                .toList();

        return songArtistRepository.findAllBySongIdIn(songIds).stream()
                .collect(Collectors.groupingBy(
                        SongArtist::getSongId,
                        Collectors.mapping(SongArtist::getArtist, Collectors.toList())
                ));
    }

    public List&amp;lt;Song&amp;gt; findArtistSongBySort(Long artistId, List&amp;lt;Song&amp;gt; sortedSong) {
        List&amp;lt;Long&amp;gt; artistSongIds = songArtistRepository.findSongIdsByArtistId(artistId);
        return sortedSong.stream()
                .filter(song -&amp;gt; artistSongIds.contains(song.getId()))
                .toList();
    }

}
&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;3. Controller는 조립해서 Dto로&lt;/p&gt;
&lt;pre class=&quot;kotlin&quot;&gt;&lt;code&gt;@RestController
@RequestMapping(&quot;/v1/chart&quot;)
@RequiredArgsConstructor
public class ChartController implements ChartApi {

    private final ChartService chartService;
    private final SongArtistService songArtistService;

    @GetMapping
    public CommonResponse&amp;lt;ChartResponse&amp;gt; getChartByFilter(
            @RequestParam(defaultValue = &quot;TOP100&quot;) String chartFilter
    ) {

        List&amp;lt;Song&amp;gt; chartSongsByFilter = chartService.findChartSongByFilter(ChartFilterType.from(chartFilter));

        Map&amp;lt;Long, List&amp;lt;Artist&amp;gt;&amp;gt; artistsMap = songArtistService.findArtistAsMap(chartSongsByFilter);

        ChartResponse response = ChartResponse.of(chartSongsByFilter, artistsMap);

        return CommonResponse.success(ChartSuccessCode.GET_CHART, response);
    }

}
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;정리&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개념을 알기 전에는 &lt;b&gt;Business Layer와 Presentation Layer 분리&lt;/b&gt;하는 게 너무 귀찮고 실수도 많았었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 합동 세미나를 진행하면서 많은 API이 삭제되거나 추가되거나 수정되는 일이 많이 발생하였다. 이 때마다 Service에서 dto를 반환하지 않아서 간편하게 Controller와 dto만 신경 쓰면 되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 크게 느낀 부분은 차트 API였다. 필터 정렬 순서를 어떻게 처리할지 팀 내에서 여러 번 논의가 오갔고, 요구사항도 계속 바뀌었는데, 정렬과 계산 로직을 Service 쪽에서 집중적으로 관리할 수 있어서 수정 부담이 줄었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한 차트 API와 아티스트 곡 목록 조회 API에서 계산 로직이 겹치는 필터가 있었는데, 공통 로직을 재사용하고 필터명만 다르게 처리할 수 있도록 구현하면서 코드량도 줄일 수 있었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;참고자료&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Command 읽어봤던 자료&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://lets-do-the-odessey.tistory.com/47&quot;&gt;https://lets-do-the-odessey.tistory.com/47&lt;/a&gt;&lt;/p&gt;</description>
      <category>Back-end/Spring</category>
      <author>dev_Hyeonjoon</author>
      <guid isPermaLink="true">https://joon0112.tistory.com/73</guid>
      <comments>https://joon0112.tistory.com/73#entry73comment</comments>
      <pubDate>Tue, 16 Jun 2026 17:39:50 +0900</pubDate>
    </item>
    <item>
      <title>[TIL] Java 함수형 프로그래밍 입문: 람다, 스트림, Predicate&amp;middot;Consumer&amp;middot;Function 이해하기</title>
      <link>https://joon0112.tistory.com/72</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;함수형 프로그래밍이란&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일급 객체로 취급하여 프로그램을 작성하는 프로그래밍 패러다임&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;일급 객체는&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 일급은 사용할 때 다른 요소들과 아무런 차별이 없다는 것을 뜻합니다!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;변수에 저장할 수 있다&lt;/li&gt;
&lt;li&gt;함수의 매개변수로 전달할 수 있다&lt;/li&gt;
&lt;li&gt;함수의 반환값으로 사용할 수 있다&lt;/li&gt;
&lt;li&gt;런타임에 생성할 수 있다&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;자바에서 함수 프로그래밍이 필요한 이유&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Java 8버전 부터 함수형 프로그래밍을 지원하기 위해 람다(lambda)와 스트림(stream)이 도입되었는데 이 때, 람다와 스트림을 사용하면 가독성이 좋아지기 때문입니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;병렬 처리 용이 (parallelStream)&lt;/li&gt;
&lt;li&gt;부작용 감소&lt;/li&gt;
&lt;li&gt;선언형 프로그래밍 가능&lt;/li&gt;
&lt;li&gt;내부 반복 (Internal Iteration)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;람다(lambda)&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;람다(lambda)는 익명 함수(anonymous function)를 의미&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래에서는 람다와 일반적인 코드를 비교하면서 왜 람다가 도움이 되는지 적어보겠습니다&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;일반 코드&lt;/h3&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;List&amp;lt;Integer&amp;gt; numbers = List.of(4, 6, 8, 13, 3, 15);
int sum = 0;
for (int number : numbers) {sum += number; }
        
System.out.println(sum);&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;람다식을 사용하지 않고 배열의 합계를 구하기 위해 for 반복문을 활용해 복잡하게 구현했어야 했습니다.&lt;/li&gt;
&lt;li&gt;하지만 람다식을 사용한다면 가독성을 올릴 수 있게 됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;람다를 적용한 코드&lt;/b&gt;&lt;/h3&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;int sum = numbers.stream().reduce(
                0, 
                (number1, number2) -&amp;gt; number1 + number2);&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;기존 코드에서 복잡했던 것들은 람다 표현식을 통해 가독성이 매우 좋아진 걸 확인할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;차이점&lt;/h4&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&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;일반 코드에서 sum 변수는 초기 값이 0이었지만 숫자를 반복해서 더할 때마다 총합이 계속 증가하는데 이를 &lt;b&gt;변수 변이&lt;/b&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;for문에서 합을 어떻게 할지 정확하게 표현해줬어야 합니다
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;0으로 초기화하고, 숫자를 루프한 다음 숫자 하나를 대입하고, 그 값을 리턴하라는 것&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;람다 표현식 작성하는 방법&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;람다 표현식에 보이는 stream() 은 &amp;ldquo;&lt;b&gt;자주 사용하는 대표 사례&lt;/b&gt;&amp;rdquo;입니다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;stream은 &amp;lsquo;흐름&amp;rsquo;이라는 뜻으로써, 데이터가 물결처럼 흘러가면서 필터링 과정을 통해 여러 번 변경되어 반환되기 때문에 이러한 이름을 갖게 되었습니다. 이러한 stream은 배열의 요소들을 전개해줍니다&lt;/p&gt;
&lt;pre class=&quot;livescript&quot;&gt;&lt;code&gt;(매개변수) -&amp;gt; { 실행문 }
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;람다 표현식의 구성 요소는 3가지 입니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;(매개변수) : 입력 값&lt;/li&gt;
&lt;li&gt;&amp;gt; : 람다 연산자 (parameter와 body를 구분)&lt;/li&gt;
&lt;li&gt;{ 실행문 } : 실행할 코드 (함수 몸체)&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;작성 규칙&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;매개 변수가 없을 때&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;() -&amp;gt; System.out.println(&quot;Hello&quot;);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;매개변수가 하나일 때 (괄호 생략 가능)&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;sas&quot;&gt;&lt;code&gt;x -&amp;gt;System.out.println(x);
&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;(x) -&amp;gt;System.out.println(x);// 둘 다 가능&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;매개변수가 여러 개 일때&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;(a,b) -&amp;gt;a+b&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;실행문이 한 줄이면 {} 생략 가능&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;livescript&quot;&gt;&lt;code&gt;(a,b) -&amp;gt;a+b
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;여러 줄이면 반드시 {} 필요&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;livescript&quot;&gt;&lt;code&gt;(a,b) -&amp;gt; {
intresult=a+b;
returnresult;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;반환값 규칙&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;한 줄 표현식 &amp;rarr; return 생략&lt;/li&gt;
&lt;li&gt;블록 {} 사용 시 &amp;rarr; return 반드시 명시&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;xl&quot;&gt;&lt;code&gt;// return 생략 가능
(a,b) -&amp;gt;a+b

// return 필요
(a,b) -&amp;gt; {
returna+b;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;람다 표현식은 &amp;ldquo;코드를 줄이기 위한 문법&amp;rdquo;이 아니라, &lt;b&gt;동작 자체를 값처럼 전달하기 위한 방식&lt;/b&gt;이라는 점이 핵심!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;람다 예제&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;람다 예제 전, Stream에는 두 가지 연산이 있습니다 중간 연산과 종단 연산&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;public static void main(String[] args) {
        List.of(23,43,34,45,36,48).stream()
                .filter(n -&amp;gt; n%2 == 0)
                .forEach(e -&amp;gt; System.out.println(e));
    }
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;중간 연산&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Sort&lt;/p&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;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Distinct&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;중복을 제거합니다&lt;/li&gt;
&lt;li&gt;리스트에 존재하는 순서대로 출력됩니다&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;css&quot;&gt;&lt;code&gt;numbers.stream().distinct().sorted().forEach(e-&amp;gt;System.out.println(e));
&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Sort와 Distinct는 중간 연산에 해당합니다&lt;/li&gt;
&lt;li&gt;중간 연산은 메소드 갯수 제한이 없습니다&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Map&lt;/p&gt;
&lt;pre class=&quot;css&quot;&gt;&lt;code&gt;numbers.stream().distinct().map(e -&amp;gt; e*e).forEach(e-&amp;gt;System.out.println(e));
&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;리스트에서 요소를 받아 중복 제외된 값을 찾고 그 숫자의 제곱을 출력한다고 할 때
&lt;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;Map 또한 중간 연산에 포함됩니다&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;종단 연산&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스트림을 종료시키는 연산이며 더 이상 스트림 연산을 이어갈 수 없습니다&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre class=&quot;livescript&quot;&gt;&lt;code&gt;IntStream.range(1,11).reduce( 0, (n1, n2) -&amp;gt; n1 + n2)
&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;reduce의 역할을 생각해보면 숫자 스트림을 하나의 결괏값으로 반환하며 더 이상 스트림 연산을 이어갈 수 없습니
&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;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Max&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;pre class=&quot;livescript&quot;&gt;&lt;code&gt;List.of(23,12,34,53).stream().max((n1,n2) -&amp;gt; Integer.compare(n1,n2))
//Optional[53]
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본적으로 반환값은 Optional로 반환되는데 그 이유는 최대 값이 있을지 없을지 모르기 때문입니다&lt;/p&gt;
&lt;pre class=&quot;livescript&quot;&gt;&lt;code&gt;List.of(23,12,34,53).stream().max((n1,n2) -&amp;gt; Integer.compare(n1,n2)).get()
//53
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;뒤에 .get()을 통해 최대 값만 가져올 수 있습니다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Min&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;pre class=&quot;livescript&quot;&gt;&lt;code&gt;List.of(23,12,34,53).stream().min((n1,n2) -&amp;gt; Integer.compare(n1,n2)).get()
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;함수형 인터페이스 이면의 원리&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;람다 표현식은 Functional Interface에 기반을 두어 실행됩니다&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Predicate In 구현&lt;/h3&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;public static void main(String[] args) {
        List.of(23,43,34,45,36,48).stream()
                .filter(n -&amp;gt; n%2 == 0)
                .forEach(e -&amp;gt; System.out.println(e));
    }
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기 리스트 원소들이 어떻게 filter 메소드에 전송되는 걸까요?&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1105&quot; data-origin-height=&quot;707&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/W7cxL/dJMcahXJHtb/pq3rD79KQOVVtA0EGdVglK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/W7cxL/dJMcahXJHtb/pq3rD79KQOVVtA0EGdVglK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/W7cxL/dJMcahXJHtb/pq3rD79KQOVVtA0EGdVglK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FW7cxL%2FdJMcahXJHtb%2Fpq3rD79KQOVVtA0EGdVglK%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;1105&quot; height=&quot;707&quot; data-origin-width=&quot;1105&quot; data-origin-height=&quot;707&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;filter메소드를 보면 Predicate를 사용한다고 나와있습니다 Predicate에 대해 더 자세히 보자면&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1172&quot; data-origin-height=&quot;424&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/1Dhyn/dJMcab4hdDV/ruBo9BjFQjsfnjlIGHBYT1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/1Dhyn/dJMcab4hdDV/ruBo9BjFQjsfnjlIGHBYT1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/1Dhyn/dJMcab4hdDV/ruBo9BjFQjsfnjlIGHBYT1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F1Dhyn%2FdJMcab4hdDV%2FruBo9BjFQjsfnjlIGHBYT1%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;1172&quot; height=&quot;424&quot; data-origin-width=&quot;1172&quot; data-origin-height=&quot;424&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;FunctionalInterface를 사용하며 Predicate 인터페이스며 그 인터페이스 안에는 test라는 메소드를 가지고 있습니다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;test 메소드는 사실 실행되지 않는 유일한 메소드입니다. 그럼에도 Predicate 인터페이스와 일치하게 매핑되는 이유는 만약 인터페이스를 허용하는 메소드들를 가지고 있다면, 그 인터페이스에 대해서만 그 인터페이스의 실행에 대한 대상만 파라미터로써 실행이 가능합니다.&lt;/p&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;package functionalprogramming;

import java.util.List;
import java.util.function.Predicate;

class EvenNumberPredicate implements Predicate&amp;lt;Integer&amp;gt;{
    @Override
    public boolean test(Integer number) {
        return number %2 == 0;
    }
}
public class LambdaBehindTheScreensRunner {
    public static void main(String[] args) {
        List.of(23,43,34,45,36,48).stream()
                .filter(n -&amp;gt; n%2 == 0)
                .forEach(e -&amp;gt; System.out.println(e));

        
        List.of(23,43,34,45,36,48).stream()
                .filter(new EvenNumberPredicate())
                .forEach(e -&amp;gt; System.out.println(e));
    }
}

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;244&quot; data-origin-height=&quot;268&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/JJAPn/dJMcagqY2Mi/TEA9JRklh3hvvamk0piRE1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/JJAPn/dJMcagqY2Mi/TEA9JRklh3hvvamk0piRE1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/JJAPn/dJMcagqY2Mi/TEA9JRklh3hvvamk0piRE1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FJJAPn%2FdJMcagqY2Mi%2FTEA9JRklh3hvvamk0piRE1%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;244&quot; height=&quot;268&quot; data-origin-width=&quot;244&quot; data-origin-height=&quot;268&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;같은 값을 출력하는 걸 볼 수 있는데 그 이유는 로직을 이용하고 여기에 filter 메소드를 사용하면 화면 뒤에서는 아래와 같이 행동합니다&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;자바 컴파일러가 함수형 인터페이스를 실행합니다
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;함수형 인터페이스에서 가장 중요한 것은, Predicate처럼 딱 한 개의 메소드만 정의 되지 않는다는 것 인데 기본적으로 람다형을 생성할 때에는 특정 메소드를 실행해주는 작업을 합니다&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;여기에서 test메소드를 이 부분이 실행되도록 하는 것입니다&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;이 특정한 인터페이스를 Predicate라고 부르는데, 그 이유는 이게 하는 적업이 평가를 진행한 후에 참인지 거짓인지를 판단하여 그 값을 반환하기 때문입니다&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Consumer Int 구현&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;804&quot; data-origin-height=&quot;98&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cIm2yV/dJMb996tvBf/l9HxoybSu0mNk6RQHm2s31/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cIm2yV/dJMb996tvBf/l9HxoybSu0mNk6RQHm2s31/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cIm2yV/dJMb996tvBf/l9HxoybSu0mNk6RQHm2s31/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcIm2yV%2FdJMb996tvBf%2Fl9HxoybSu0mNk6RQHm2s31%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;804&quot; height=&quot;98&quot; data-origin-width=&quot;804&quot; data-origin-height=&quot;98&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ForEach에서는 이렇게 Consumer 인터페이스를 사용합니다&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;898&quot; data-origin-height=&quot;372&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/0t6ms/dJMcaa5nA4s/SHiXrFIVkOT5k46LKoI39K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/0t6ms/dJMcaa5nA4s/SHiXrFIVkOT5k46LKoI39K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/0t6ms/dJMcaa5nA4s/SHiXrFIVkOT5k46LKoI39K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F0t6ms%2FdJMcaa5nA4s%2FSHiXrFIVkOT5k46LKoI39K%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;898&quot; height=&quot;372&quot; data-origin-width=&quot;898&quot; data-origin-height=&quot;372&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Consumer 인터페이스에는 accept 메소드를 사용합니다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;accept 메소드&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;아무것도 반환하지 않습니다
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이는 Consumer (소비자) 라고 불리는 이유입니다.&lt;/li&gt;
&lt;li&gt;예시로 forEach에서는 e &amp;rarr; System.out.print(e) 구문을 자주 쓰는데&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;forEach에는 Consumer 인터페이스가 존재한다&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;java&quot;&gt;&lt;code&gt;package functionalprogramming;

import java.util.List;
import java.util.function.Consumer;
import java.util.function.Predicate;

class EvenNumberPredicate implements Predicate&amp;lt;Integer&amp;gt;{
    @Override
    public boolean test(Integer number) {
        return number %2 == 0;
    }
}

class SystemOutConsumer implements Consumer&amp;lt;Integer&amp;gt; {

    @Override
    public void accept(Integer number) {
        System.out.println(number);
    }
}

public class LambdaBehindTheScreensRunner {
    public static void main(String[] args) {
        List.of(23,43,34,45,36,48).stream()
                .filter(n -&amp;gt; n%2 == 0)
                .forEach(e -&amp;gt; System.out.println(e));

        List.of(23,43,34,45,36,48).stream()
                .filter(new EvenNumberPredicate())
                .forEach(new SystemOutConsumer());
    }
}

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;244&quot; data-origin-height=&quot;268&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ouRBj/dJMcadHKSQP/9UJrBqUR6NvAXjaBiYNo70/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ouRBj/dJMcadHKSQP/9UJrBqUR6NvAXjaBiYNo70/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ouRBj/dJMcadHKSQP/9UJrBqUR6NvAXjaBiYNo70/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FouRBj%2FdJMcadHKSQP%2F9UJrBqUR6NvAXjaBiYNo70%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;244&quot; height=&quot;268&quot; data-origin-width=&quot;244&quot; data-origin-height=&quot;268&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이 또한 결과가 일치합니다&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Function Int 구현&lt;/h3&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;List.of(23, 43, 34, 45, 36, 48).stream()
                .filter(n -&amp;gt; n % 2 == 0)
                .map(n -&amp;gt; n * n)
                .forEach(e -&amp;gt; System.out.println(e));
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;map을 사용할 때는 Function 인터페이스를 사용합니다&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;984&quot; data-origin-height=&quot;414&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/3mqLJ/dJMcaaK4FIv/Otok1DBc6aMU3kEgr63nF0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/3mqLJ/dJMcaaK4FIv/Otok1DBc6aMU3kEgr63nF0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/3mqLJ/dJMcaaK4FIv/Otok1DBc6aMU3kEgr63nF0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F3mqLJ%2FdJMcaaK4FIv%2FOtok1DBc6aMU3kEgr63nF0%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;984&quot; height=&quot;414&quot; data-origin-width=&quot;984&quot; data-origin-height=&quot;414&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어떤 값을 넣어주면 다른 값을 반환해줍니다&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;위 코드에서 map을 보면 Stream을 반환해줬음을 알 수 있습니다&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;위 코드에서는 입력 값이 n, 출력 값이 n*n이 되는 것입니다&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;package functionalprogramming;

import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;

class EvenNumberPredicate implements Predicate&amp;lt;Integer&amp;gt;{
    @Override
    public boolean test(Integer number) {
        return number %2 == 0;
    }
}

class SystemOutConsumer implements Consumer&amp;lt;Integer&amp;gt; {

    @Override
    public void accept(Integer number) {
        System.out.println(number);
    }
}

class NumberSquareMapper implements Function&amp;lt;Integer, Integer&amp;gt; {

    @Override
    public Integer apply(Integer number) {
        return number * number;
    }
}

public class LambdaBehindTheScreensRunner {
    public static void main(String[] args) {
        List.of(23, 43, 34, 45, 36, 48).stream()
                .filter(n -&amp;gt; n % 2 == 0)
                .map(n -&amp;gt; n * n)
                .forEach(e -&amp;gt; System.out.println(e));

        List.of(23, 43, 34, 45, 36, 48).stream()
                .filter(new EvenNumberPredicate())
                .map(new NumberSquareMapper())
                .forEach(new SystemOutConsumer());
    }
}

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;678&quot; data-origin-height=&quot;310&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Hc7MI/dJMcafZTNfM/FgbM08fZKsTjBKw5J44kc0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Hc7MI/dJMcafZTNfM/FgbM08fZKsTjBKw5J44kc0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Hc7MI/dJMcafZTNfM/FgbM08fZKsTjBKw5J44kc0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FHc7MI%2FdJMcafZTNfM%2FFgbM08fZKsTjBKw5J44kc0%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;678&quot; height=&quot;310&quot; data-origin-width=&quot;678&quot; data-origin-height=&quot;310&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;똑같이 출력됩니다&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;정리&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Function은 함수형 인터페이스 중 하나로, 입력값을 얻고 어떤 값을 출력해내는 인터페이스를 뜻합니다&lt;/li&gt;
&lt;li&gt;Predicate는 입력값을 보고 참인지 거짓인지를 판단&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;그러므로 어떤 값도 반환 x&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;  References&lt;/b&gt;&lt;/h2&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;Udemy, Best Java Programming Course
&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://www.udemy.com/course/best-java-programming/&quot;&gt;https://www.udemy.com/course/best-java-programming/&lt;/a&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;a href=&quot;https://wikidocs.net/157858&quot;&gt;https://wikidocs.net/157858&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Inpa Dev
&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://inpa.tistory.com/entry/CS-&quot;&gt;https://inpa.tistory.com/entry/CS-&lt;/a&gt;&lt;a href=&quot;https://inpa.tistory.com/entry/CS-%F0%9F%91%A8%E2%80%8D%F0%9F%92%BB-%EC%9D%BC%EA%B8%89-%EA%B0%9D%EC%B2%B4first-class-object&quot;&gt; &amp;zwj; -일급-객체first-class-object&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;추천자료&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://inpa.tistory.com/entry/&quot;&gt;https://inpa.tistory.com/entry/&lt;/a&gt;&lt;a href=&quot;https://inpa.tistory.com/entry/%E2%98%95-%EB%9E%8C%EB%8B%A4%EC%8B%9D-%EB%A6%AC%ED%8C%A9%ED%86%A0%EB%A7%81-Comparator&quot;&gt;☕-람다식-리팩토링-Comparator&lt;/a&gt;&lt;/p&gt;</description>
      <category>Back-end/Java</category>
      <author>dev_Hyeonjoon</author>
      <guid isPermaLink="true">https://joon0112.tistory.com/72</guid>
      <comments>https://joon0112.tistory.com/72#entry72comment</comments>
      <pubDate>Sun, 22 Feb 2026 01:00:13 +0900</pubDate>
    </item>
    <item>
      <title>[TIL] - Java Map 구조 이해하기 &amp;mdash; HashMap, LinkedHashMap, TreeMap 언제 사용할까?</title>
      <link>https://joon0112.tistory.com/71</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;Map Interface&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;key-value 방식을 사용합니다&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;822&quot; data-origin-height=&quot;576&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dmtKI3/dJMcadHFRd9/2UmfC8TMbLAZsHBq2ogC30/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dmtKI3/dJMcadHFRd9/2UmfC8TMbLAZsHBq2ogC30/img.png&quot; data-alt=&quot;https://techvidvan.com/tutorials/java-collection-framework/&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dmtKI3/dJMcadHFRd9/2UmfC8TMbLAZsHBq2ogC30/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdmtKI3%2FdJMcadHFRd9%2F2UmfC8TMbLAZsHBq2ogC30%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;628&quot; height=&quot;440&quot; data-origin-width=&quot;822&quot; data-origin-height=&quot;576&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://techvidvan.com/tutorials/java-collection-framework/&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Map 인터페이스는 사진에서 보는 것과 같이 Collection 인터페이스를 연장하지 않습니다
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;하지만 keySet(), values(), entrySet()을 통해 Collection 형태로 데이터를 다룰 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Map은 키-값을 저장하는데 쓰입니다&lt;/li&gt;
&lt;li&gt;Map 에서도 Collection과 같이 다양한 구현들이 있습니다&lt;/li&gt;
&lt;li&gt;&lt;b&gt;고유한 Key를 통해 빠른 데이터 검색, 추가, 삭제, 수정이 가능&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Key는 고유해야 함&lt;/li&gt;
&lt;li&gt;Value는 고유 xx&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;요소의 저장 순서를 유지하지 않습니다.&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;HashMap&lt;/h3&gt;
&lt;pre class=&quot;vhdl&quot;&gt;&lt;code&gt;Map&amp;lt;Character, Integer&amp;gt; occurances = new HashMap&amp;lt;&amp;gt;();
&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;HashMap을 이루는 데이터 구조는 HashTable입니다
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;하지만 충돌이 발생하면 LinkedList 또는 Red-Black Tree 형태로 데이터를 저장합니다(Java 8 이상).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;분류되지 않고 순서도 없습니다&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;HashTable과 차이점&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;HashTable, HashMap 모두 해싱 기법을 데이터 구조에 사용합니다&lt;/li&gt;
&lt;li&gt;&amp;rArr; 연산과 관련해서는 아무 차이 ❌&lt;/li&gt;
&lt;li&gt;하지만 &lt;b&gt;HashTable은 Vector와 유사하게 모든 메소드가 동기화&lt;/b&gt;되어 있습니다
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;스레드가 HashMap에 비해 더 안전&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;asciidoc&quot;&gt;&lt;code&gt;- Hashtable은 모든 메서드가 synchronized 되어 있어 멀티스레드 환경에서 안전하지만
  성능 오버헤드가 크기 때문에 현재는 거의 사용되지 않는다.
- 대신 ConcurrentHashMap 사용이 권장된다.

&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;HashMap은 Key를 null값으로 저장&lt;/b&gt;할 수 있습니다
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;하지만 HashTable 에서는 ❌&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;LinkedHashMap&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;삽입 순서가 유지됩니다&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre class=&quot;vhdl&quot;&gt;&lt;code&gt;Map&amp;lt;Character, Integer&amp;gt; linkedHashMap = new LinkedHashMap&amp;lt;&amp;gt;();
&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;정렬되어 있지 않고 삽입 순서이기 때문에 HashMap에 비해 삽입과 제거는 조금 느립니다
&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;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;TreeMap&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정렬된 순서로 데이터 저장&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre class=&quot;vhdl&quot;&gt;&lt;code&gt;Map&amp;lt;Character, Integer&amp;gt; treeMap = new TreeMap&amp;lt;&amp;gt;();
&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;TreeMap은 Red-Black Tree 기반으로 동작하며, 정렬된 데이터를 탐색하기 위해 NavigableMap 인터페이스를 구현합니다
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;TreeMap의 경우 Navigable&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Map Interface의 기초 연산&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;of()로 Map 생성&lt;/h4&gt;
&lt;pre class=&quot;lasso&quot;&gt;&lt;code&gt; Map&amp;lt;String, Integer&amp;gt; map = Map.of(&quot;A&quot;, 3, &quot;B&quot;, 5, &quot;Z&quot;, 10);
&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Map을 작성할 때는 Key-Value 값의 타입을 각각 설정해줘야 합니다&lt;/li&gt;
&lt;li&gt;또한 위 코드는 of 함수를 사용했기에 수정이 불가능합니다&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Value 갖고 오기&lt;/h4&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;map.get(&quot;Z&quot;); //키로 값을 불러올 수 있다 
//10
&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;만약 존재하지 않는 값을 찾으려고 할 때 null을 반환&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;다양한 메소드&lt;/h4&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;map.size(); //맵의 크기를 검색
map.isEmpty(); //비어있는지 검색
map.containsKey(&quot;A&quot;); //&quot;A&quot;라는 열쇠를 포함하고 있는지
map.containsValue(3); // 3이라는 값을 포함하고 있는지

map.keySet(); //데이터 구조와 열쇠들의 Collection만 가져온다
map.values(); // 값만 반환

&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Map 에 Key-Value 추가하기&lt;/h4&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;Map&amp;lt;String, Integer&amp;gt; hashmap = new HashMap&amp;lt;&amp;gt;(map);
hashmap.put(&quot;F&quot;,5);
hashmap.put(&quot;Z&quot;,11); //기존에 있던 Z=10 이 Z=11로 변경

&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;TreeMap NavigableMap의 메소드 - floorKey, higherKey, firstEntry&lt;/h4&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;treemap.higherKey(&quot;B&quot;); //B 초과 키를 반환한다
treemap.ceilingKey(&quot;B&quot;); // B 이상 키를 반환

treemap.lowerKey(&quot;B&quot;); // B 미만 키를 반환
treemap.floorKey(&quot;B&quot;); // B 이하 키를 반환

treemap.firstEntry(); //  첫 번째  키-값을 반환
treemap.lastEntry(); // 마지막 키-값을 반환

treemap.submap(&quot;C&quot;, &quot;Y&quot;); //하위 맵 생성 (C이상 Y 미만의 모든 키와 값을 반환) 
treemap.submap(&quot;C&quot;,true, &quot;Y&quot;, true); //하위 맵 생성 (C이상 Y 이하의 모든 키와 값을 반환)
treemap.submap(&quot;C&quot;,false, &quot;Y&quot;, false); //하위 맵 생성 (C초과 Y 미만의 모든 키와 값을 반환)  
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;※ TreeMap은 정렬 기준(Comparable 또는 Comparator)에 따라 위 결과가 결정&lt;/b&gt;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;언제 어떤 Map을 써야 할까?&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;빠른 조회만 필요 &amp;rarr; HashMap&lt;/li&gt;
&lt;li&gt;입력 순서 유지 필요 &amp;rarr; LinkedHashMap&lt;/li&gt;
&lt;li&gt;정렬 및 범위 탐색 필요 &amp;rarr; TreeMap&lt;/li&gt;
&lt;li&gt;멀티스레드 환경 &amp;rarr; ConcurrentHashMap&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;  References&lt;/b&gt;&lt;/h2&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;Udemy, Best Java Programming Course
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://www.udemy.com/course/best-java-programming/&quot;&gt;https://www.udemy.com/course/best-java-programming/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;  함께 보면 좋은 글&lt;/b&gt; &lt;br /&gt;-&amp;nbsp;&lt;a href=&quot;https://joon0112.tistory.com/69&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Java Collection Framework 과 List&lt;/a&gt;&lt;br /&gt;- &lt;a href=&quot;https://joon0112.tistory.com/70&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Set 과 Queue&lt;/a&gt;&lt;/p&gt;</description>
      <category>Back-end/Java</category>
      <category>Java</category>
      <category>map</category>
      <category>Til</category>
      <category>자료구조</category>
      <category>자바</category>
      <author>dev_Hyeonjoon</author>
      <guid isPermaLink="true">https://joon0112.tistory.com/71</guid>
      <comments>https://joon0112.tistory.com/71#entry71comment</comments>
      <pubDate>Fri, 13 Feb 2026 20:47:22 +0900</pubDate>
    </item>
    <item>
      <title>[TIL]HashSet vs TreeSet vs LinkedHashSet 차이점과 PriorityQueue 이해</title>
      <link>https://joon0112.tistory.com/70</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;Set 소개&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://joon0112.tistory.com/69&quot;&gt;Java Collection&lt;/a&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;유일한 값만 가질 수 있고 순서가 없습니다&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;만약 두 개의 값이 같다면, 그 중 하나만 Set에 들어갈 수 있습니다&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;데이터 구조에 따른 Set&lt;/h3&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;package collection;

import java.util.*;

public class SetRunner {

    public static void main(String[] args) {
        List&amp;lt;Character&amp;gt; characters = List.of('A', 'Z', 'A', 'B', 'Z', 'F');

        //정렬 순서 - TreeSet
        Set&amp;lt;Character&amp;gt; treeSet = new TreeSet&amp;lt;&amp;gt; (characters);
        System.out.println(&quot;treeSet&quot; + treeSet);

        //삽입 순서 - LinkedHashSet
        Set&amp;lt;Character&amp;gt; linkedSet = new LinkedHashSet&amp;lt;&amp;gt;(characters);
        System.out.println(&quot;linkedSet&quot; + linkedSet);

        //상관없다면 - hashSet
        Set&amp;lt;Character&amp;gt; hashSet = new HashSet&amp;lt;&amp;gt;(characters);
        System.out.println(&quot;hashSet&quot; + hashSet);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;696&quot; data-origin-height=&quot;146&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/853V7/dJMcadVcBrx/GI1L2kr5FefFMrPQb4RWvk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/853V7/dJMcadVcBrx/GI1L2kr5FefFMrPQb4RWvk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/853V7/dJMcadVcBrx/GI1L2kr5FefFMrPQb4RWvk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F853V7%2FdJMcadVcBrx%2FGI1L2kr5FefFMrPQb4RWvk%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;639&quot; height=&quot;134&quot; data-origin-width=&quot;696&quot; data-origin-height=&quot;146&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;HashSet&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;801&quot; data-origin-height=&quot;401&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/F6I9Q/dJMcafS4obq/i7ugp3XFGKqmttF7kpRU01/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/F6I9Q/dJMcafS4obq/i7ugp3XFGKqmttF7kpRU01/img.png&quot; data-alt=&quot;geeksforgeeks&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/F6I9Q/dJMcafS4obq/i7ugp3XFGKqmttF7kpRU01/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FF6I9Q%2FdJMcafS4obq%2Fi7ugp3XFGKqmttF7kpRU01%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;801&quot; height=&quot;401&quot; data-origin-width=&quot;801&quot; data-origin-height=&quot;401&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;geeksforgeeks&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;HashSet은 해시 테이블을 기반으로 구현되었습니다&lt;/li&gt;
&lt;li&gt;데이터 추가, 삭제, 검색이 평균의 시간 복잡도가 평균 - O(1), 최악 - O(n) 으로 매우 빠르며, 유일한 데이터 집합을 관리하거나 중복을 제거할 때 주로 사용됩니다&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;LinkedHashSet&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;HashSet&lt;b&gt;에 연결 리스트(LinkedList)를 결합하여&amp;nbsp;요소가 삽입된 순서를 보장하는 자료구조&lt;/b&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;해시 테이블을 사용하여 검색 성능이 뛰어나며, 데이터를 추가한 순서대로 유지해야 하는 캐시(Cache)나 순서 보장형 집합에 적합합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;TreeSet&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;500&quot; data-origin-height=&quot;241&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mSDEP/dJMb996oaBL/EgGF2wgzPbeTKu1vwJPr1K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mSDEP/dJMb996oaBL/EgGF2wgzPbeTKu1vwJPr1K/img.png&quot; data-alt=&quot;https://coding-factory.tistory.com/555&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mSDEP/dJMb996oaBL/EgGF2wgzPbeTKu1vwJPr1K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmSDEP%2FdJMb996oaBL%2FEgGF2wgzPbeTKu1vwJPr1K%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;500&quot; height=&quot;241&quot; data-origin-width=&quot;500&quot; data-origin-height=&quot;241&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://coding-factory.tistory.com/555&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;중복을 허용하지 않으며 요소들이 자동으로 오름차순 정렬됩니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Red-Black Tree (균형 이진 탐색 트리)&lt;/b&gt;를 사용하여 검색과 정렬에 높은 성능을 제공하며, 대량의 데이터를 정렬된 상태로 유지해야 할 때 유용합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;TreeSet의 NavigableSet&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;HashSet과 LinkedHashSet 와는 다르게 TreeSet 에서는 Collection 프레임워크 뿐만 아니라 Navigable의 메소드도 지원합니다&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;NavigableSet&amp;lt;Integer&amp;gt; numbers = new TreeSet&amp;lt;&amp;gt;(Set.of(65,54,34,12,99));
// numbers ==&amp;gt; [12, 34, 54, 65, 99]
&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;TreeSet.floor(34); //이하 

numbers.lower(34); //미만

numbers.ceiling(34); //이상

numbers.higher(34); //초과 

numbers.subSet(20,80) // 20 이상  80 미만 사이에 있는 숫자 찾기 
numbers.subSet(20,true,80,true) // 20이상 80이하 사이에 있는 숫자 찾기
numbers.subSet(20,false,80,false) // 20초과 80미만 사이에 있는 숫자 찾기

numbers.headSet(50); // 50까지의 모든 숫자들을 출력
numbers.tailSet(50); // 50 이후의 모든 숫자들을 출력
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Set 정리&lt;/h3&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 100px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style13&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;구현체&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;중복&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;순서&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;정렬&lt;/td&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;시간복잡도&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 22px;&quot;&gt;
&lt;td style=&quot;height: 22px;&quot;&gt;HashSet&lt;/td&gt;
&lt;td style=&quot;height: 22px;&quot;&gt;X&lt;/td&gt;
&lt;td style=&quot;height: 22px;&quot;&gt;없음&lt;/td&gt;
&lt;td style=&quot;height: 22px;&quot;&gt;X&lt;/td&gt;
&lt;td style=&quot;height: 22px;&quot;&gt;O(1)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 22px;&quot;&gt;
&lt;td style=&quot;height: 22px;&quot;&gt;LinkedHashSet&lt;/td&gt;
&lt;td style=&quot;height: 22px;&quot;&gt;X&lt;/td&gt;
&lt;td style=&quot;height: 22px;&quot;&gt;삽입순&lt;/td&gt;
&lt;td style=&quot;height: 22px;&quot;&gt;X&lt;/td&gt;
&lt;td style=&quot;height: 22px;&quot;&gt;O(1)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 22px;&quot;&gt;
&lt;td style=&quot;height: 22px;&quot;&gt;TreeSet&lt;/td&gt;
&lt;td style=&quot;height: 22px;&quot;&gt;X&lt;/td&gt;
&lt;td style=&quot;height: 22px;&quot;&gt;정렬순&lt;/td&gt;
&lt;td style=&quot;height: 22px;&quot;&gt;O&lt;/td&gt;
&lt;td style=&quot;height: 22px;&quot;&gt;O(log n)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Queue 소개&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;먼저 들어온 데이터가 먼저 나가는 선입선출(FIFO, First-In-First-Out) 구조의 선형 자료구조&lt;/blockquote&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;Collection의 연장선이라 Collection의 주요 메소드를 지원합니다
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;그 외에도 Queue는 add, offer, remove, poll, peek 라는 메서드도 지원합니다&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;인덱스를 통한 요소에 직접 접근은 거부됩니다&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;PriorityQueue - 기본 메소드와 사용자 정의 우선 순위&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;일반 Queue &amp;rarr; First In First Out&lt;/li&gt;
&lt;li&gt;PriorityQueue &amp;rarr; FIFO  
&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;/ul&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;Queue&amp;lt;String&amp;gt; queue = new PriorityQueue&amp;lt;&amp;gt;(); //Queue 선언 

queue.poll(); //queue에서 요소를 꺼냄 

queue.offer(&quot;Apple&quot;); //queue에 요소를 넣음

queue.addAll(List.of(&quot;Zebra&quot;, &quot;Monkey&quot;, &quot;Cat&quot;)); // queue에 모든 요소들을 넣음 
//이때 결과값으로는 [Apple, Cat, Monkey, Zebra] 이 나오는데 queue에서 자동으로 알파벳
//로 설정해주기 때문&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;jshell&amp;gt; queue.poll()
$6 ==&amp;gt; &quot;Apple&quot;

jshell&amp;gt; queue
queue ==&amp;gt; [Cat, Zebra, Monkey]
&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Queue는 전시화나 영화관에서 웨이팅 하는 것 처럼 동작합니다
&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;Queue에서는 요소의 우선순위를 지정할 수 있다&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;package collection;

import java.util.List;
import java.util.PriorityQueue;
import java.util.Queue;

public class QueueRunner {
    public static void main(String[] args) {
        Queue&amp;lt;String&amp;gt; queue = new PriorityQueue&amp;lt;&amp;gt;();
        queue.addAll(List.of(&quot;Zebra&quot;, &quot;Monkey&quot;, &quot;Cat&quot;));
        System.out.println(queue.poll()); //Cat
        System.out.println(queue.poll()); //Monkey
        System.out.println(queue.poll()); //Zebra
        System.out.println(queue.poll()); //null

    }
}

&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Queue에서 사용자 지정 순서 정하기&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;comparator 인터페이스로 간단하게 가능합니다&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;package collection;

import java.util.Comparator;
import java.util.List;
import java.util.PriorityQueue;
import java.util.Queue;

class StringLengthComparator implements Comparator&amp;lt;String&amp;gt; {
    //오름차순 정렬
    @Override
    public int compare(String value1, String value2) {
        return Integer.compare(value1.length(), value2.length());
    }
}
public class QueueRunner {
    public static void main(String[] args) {
        Queue&amp;lt;String&amp;gt; queue = new PriorityQueue&amp;lt;&amp;gt;(new StringLengthComparator());

        queue.addAll(List.of(&quot;Zebra&quot;, &quot;Monkey&quot;, &quot;Cat&quot;));
        System.out.println(queue.poll());
        System.out.println(queue.poll());
        System.out.println(queue.poll());
        System.out.println(queue.poll());

    }
}

/* 
출력값
Cat
Zebra
Monkey
null
*/
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;h2 data-end=&quot;47&quot; data-start=&quot;36&quot; data-ke-size=&quot;size26&quot;&gt;  참고 자료&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;394&quot; data-start=&quot;49&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;135&quot; data-start=&quot;49&quot;&gt;Coding Factory,&lt;br /&gt;[Java TreeSet 정리]&lt;br /&gt;&lt;a href=&quot;https://coding-factory.tistory.com/555&quot;&gt;https://coding-factory.tistory.com/555&lt;/a&gt;&lt;/li&gt;
&lt;li data-end=&quot;246&quot; data-start=&quot;137&quot;&gt;GeeksforGeeks,&lt;br /&gt;Queue Interface in Java&lt;br /&gt;&lt;a href=&quot;https://www.geeksforgeeks.org/java/queue-interface-java/&quot;&gt;https://www.geeksforgeeks.org/java/queue-interface-java/&lt;/a&gt;&lt;/li&gt;
&lt;li data-end=&quot;394&quot; data-start=&quot;248&quot;&gt;Udemy,&lt;br /&gt;Java Programming 강의&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.udemy.com/course/best-java-programming/&quot;&gt;https://www.udemy.com/course/best-java-programming/&lt;/a&gt;&lt;/p&gt;</description>
      <category>Back-end/Java</category>
      <category>Java</category>
      <category>Queue</category>
      <category>SET</category>
      <category>Til</category>
      <category>자료구조</category>
      <author>dev_Hyeonjoon</author>
      <guid isPermaLink="true">https://joon0112.tistory.com/70</guid>
      <comments>https://joon0112.tistory.com/70#entry70comment</comments>
      <pubDate>Fri, 13 Feb 2026 00:18:53 +0900</pubDate>
    </item>
    <item>
      <title>[TIL]자바 컬렉션 프레임워크 구조 분석 &amp;mdash; List 내부 동작과 정렬 원리 파헤치기</title>
      <link>https://joon0112.tistory.com/69</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;자바 컬렉션&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터를 저장하는 자료 구조와 데이터를 처리하는 알고리즘을 구조화하여 클래스로 구현해 놓을 것&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;822&quot; data-origin-height=&quot;576&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/NYLkh/dJMcaf6ASMm/FGoEu3vfNyt8b1GJzc4D6K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/NYLkh/dJMcaf6ASMm/FGoEu3vfNyt8b1GJzc4D6K/img.png&quot; data-alt=&quot;https://techvidvan.com/tutorials/java-collection-framework/&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/NYLkh/dJMcaf6ASMm/FGoEu3vfNyt8b1GJzc4D6K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FNYLkh%2FdJMcaf6ASMm%2FFGoEu3vfNyt8b1GJzc4D6K%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;822&quot; height=&quot;576&quot; data-origin-width=&quot;822&quot; data-origin-height=&quot;576&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://techvidvan.com/tutorials/java-collection-framework/&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;컬렉션 프레임워크의 장점&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;인터페이스와 다형성을 이용한 객체지향적 설계를 통해 표준화되어 있기 때문에, 사용법을 익히기도 편하고 재사용성이 높다&lt;/li&gt;
&lt;li&gt;데이터 구조 및 알고리즘의 고성능 구현을 제공하여 프로그램의 성능과 품질을 향상 시킨다&lt;/li&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;상위 인터페이스 타입으로 업캐스팅하여 사용&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;이미 구현되어 있는 API를 사용하기에, 새로운 API를 익히고 설계하는 시간이 줄어든다&lt;/li&gt;
&lt;li&gt;소프트웨어 재사용을 촉진하다. 만일 자바에서 지원하지 않는 새로운 자료구조가 필요하다면, 컬렉션들을 재활용하고 조합하여 새로운 알고리즘을 만들어낼 수 있다&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;List 분석하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자바9 이후에서 리스트 선언&lt;/p&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;List&amp;lt;String&amp;gt; words = List.of(&quot;Apple&quot;, &quot;Bat&quot;, &quot;Cat&quot;);&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;여기서 of는 List 인터페이스 안에 존재하는 정적 메소드입니다.&lt;/li&gt;
&lt;li&gt;만약 of 함수를 사용한다면 크기는 고정되어 어떤 데이터 타입에서도 크기를 바꿀 수 없습니다&lt;/li&gt;
&lt;li&gt;그리고 이것을 불변성 이라고 부릅니다&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;불변성&lt;/h3&gt;
&lt;pre class=&quot;dart&quot;&gt;&lt;code&gt;List&amp;lt;String&amp;gt; words = List.of(&quot;Apple&quot;, &quot;Bat&quot;, &quot;Cat&quot;);
words.add(&quot;Dog&quot;); //error
&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;of 함수를 사용해 만든 것들은 불변성을 가지기에 에러가 납니다&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;가변&lt;/h3&gt;
&lt;pre class=&quot;dart&quot;&gt;&lt;code&gt;List&amp;lt;String&amp;gt; words = List.of(&quot;Apple&quot;, &quot;Bat&quot;, &quot;Cat&quot;);
List&amp;lt;String&amp;gt; wordsArrayList = new ArrayList&amp;lt;String&amp;gt;(words);
List&amp;lt;String&amp;gt; wordsLinkedList = new LinkedList&amp;lt;String&amp;gt;(words);
List&amp;lt;String&amp;gt; wordsVector = new Vector&amp;lt;String&amp;gt;(words);
&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이러한 객체들은 모두 추가하는게 허용됩니다&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;cs&quot;&gt;&lt;code&gt;public static void main(String[] args) {

        //ArrayList 추가할 때
        wordsArrayList.add(&quot;Dog&quot;);
        System.out.println(wordsArrayList);

        //LinkedList 추가할 때
        wordsLinkedList.add(&quot;Dog&quot;);
        System.out.println(wordsLinkedList);

        //Vector 추가할 때
        wordsVector.add(&quot;Dog&quot;);
        System.out.println(wordsVector);
    }
&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;llvm&quot;&gt;&lt;code&gt;Vector, Stack, Hashtable, Properties 와 같은 클래스들은 컬렉션 프레임워크가 만들어지기 이전부터 존재하던 것이기 때문에 컬렉션 프레임워크의 명명법을 따르지 않는다. 또한 Vector 나 Hashtable 과 같은 기존의 컬렉션 클래스들은 호환을 위해 남겨진 것이므로 가급적 사용하지 않는 것이 좋다.

출처: [&amp;lt;https://inpa.tistory.com/entry/JCF- -Collections-Framework-종류-총정리&amp;gt;](&amp;lt;https://inpa.tistory.com/entry/JCF-%F0%9F%A7%B1-Collections-Framework-%EC%A2%85%EB%A5%98-%EC%B4%9D%EC%A0%95%EB%A6%AC&amp;gt;) [Inpa Dev  &amp;zwj; :티스토리]
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;배열 메소드&lt;/h2&gt;
&lt;pre class=&quot;abnf&quot;&gt;&lt;code&gt;words.size();
&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;배열은 length 필드를 사용했지만 컬렉션은size() 메서드를 사용합니다.&lt;/li&gt;
&lt;li&gt;컬렉션은 인터페이스 기반 구조이기 때문에 메서드 형태로 크기를 제공합니다&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;배열이 비어있는지 확인하기특정 요소 가져오기&lt;/p&gt;
&lt;pre class=&quot;applescript&quot;&gt;&lt;code&gt;words.get();
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;배열이 포함하고 있나?&lt;/p&gt;
&lt;pre class=&quot;applescript&quot;&gt;&lt;code&gt;words.contains(&quot;Dog&quot;);
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;가변 리스트 종류별 맞게 쓰는 시기&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;배열의 경우 ArrayList와 Vector에서 값을 불러올 때 빠르게 불러올 수 있습니다&lt;/li&gt;
&lt;li&gt;하지만 값을 삽입하거나 제거하는 것은 매우 시간이 걸립니다&lt;/li&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-origin-width=&quot;670&quot; data-origin-height=&quot;285&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/RVRYL/dJMcadt7wYV/j9R8HWQjxd4o2Wb7e3F5lk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/RVRYL/dJMcadt7wYV/j9R8HWQjxd4o2Wb7e3F5lk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/RVRYL/dJMcadt7wYV/j9R8HWQjxd4o2Wb7e3F5lk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FRVRYL%2FdJMcadt7wYV%2Fj9R8HWQjxd4o2Wb7e3F5lk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;670&quot; height=&quot;285&quot; data-origin-width=&quot;670&quot; data-origin-height=&quot;285&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어떤 요소를 지우거나 삽입하고 싶다면 어떤 걸 먼저 찾고 모든 요소들의 위치를 변경시켜줘야 하기 때문입니다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;LinkedList&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c31b5Q/dJMb996n2Qz/Q51kTLugQqeXQ1f9SDGxzk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c31b5Q/dJMb996n2Qz/Q51kTLugQqeXQ1f9SDGxzk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c31b5Q/dJMb996n2Qz/Q51kTLugQqeXQ1f9SDGxzk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc31b5Q%2FdJMb996n2Qz%2FQ51kTLugQqeXQ1f9SDGxzk%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;1920&quot; height=&quot;1080&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Eg1Ky/dJMcab4bCCK/gFuRG3ub941lkZyGBaMLQk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Eg1Ky/dJMcab4bCCK/gFuRG3ub941lkZyGBaMLQk/img.png&quot; data-origin-width=&quot;400&quot; data-origin-height=&quot;95&quot; data-is-animation=&quot;false&quot; style=&quot;width: 59.3854%; margin-right: 10px;&quot; data-widthpercent=&quot;60.08&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Eg1Ky/dJMcab4bCCK/gFuRG3ub941lkZyGBaMLQk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FEg1Ky%2FdJMcab4bCCK%2FgFuRG3ub941lkZyGBaMLQk%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;400&quot; height=&quot;95&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/zofgI/dJMcabb2Oxq/dD6ZaF5ieeFA9XryyE2a8K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/zofgI/dJMcabb2Oxq/dD6ZaF5ieeFA9XryyE2a8K/img.png&quot; data-origin-width=&quot;400&quot; data-origin-height=&quot;143&quot; data-is-animation=&quot;false&quot; style=&quot;width: 39.4518%;&quot; data-widthpercent=&quot;39.92&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/zofgI/dJMcabb2Oxq/dD6ZaF5ieeFA9XryyE2a8K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FzofgI%2FdJMcabb2Oxq%2FdD6ZaF5ieeFA9XryyE2a8K%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;400&quot; height=&quot;143&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;LinkedList의 경우 전방과 후방을 연결하는 요소들로 양면 연결되어 있습니다
&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;하지만 만약 어떤 걸 삽입 또는 삭제한다고 했을 때 Array 보다는 쉽습니다&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Vector&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Vector는 잘 쓰이지 않는데 그 이유는 &lt;a href=&quot;https://www.notion.so/172e0b38263d8050b790c491e3072610?pvs=21&quot;&gt;이 글&lt;/a&gt;을 참고해주세요.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Vector는 많은 메소드들이 동기화되어 있습니다&lt;/li&gt;
&lt;li&gt;한 클래스 안에 25개의 동기화된 메소드들이 있다고 할 때, 이 동기화된 메소드들 안에서는 한 순간에 오직 하나의 스레드만 코드를 실행시킬 수 있습니다&lt;/li&gt;
&lt;li&gt;프로그램은 스레드 하나가 사용하든 15개의 스레드를 사용하든 행동방식이 바뀌면 안되니까 synchronized 가 그 역할을 하는 것입니다&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;메소드&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;더하기, 빼기, 원소 변경을 위한 메소드&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;리스트는 중복을 허용합니다&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;wordsArrayList.add(2, &quot;Ball&quot;);&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;인덱스를 사용해 원하는 위치에 추가가 가능합니다&lt;/li&gt;
&lt;li&gt;리스트 끼리 합치기&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;haxe&quot;&gt;&lt;code&gt;List&amp;lt;String&amp;gt; newList = List.of(&quot;Yak&quot;, &quot;Zebra&quot;);

wordsArrayList.addAll(newList);
wordsArrayList.addAll(2, newList); //인덱스 위치 선정도 가능
&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;값 변경하기&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;gams&quot;&gt;&lt;code&gt;wordsArrayList.set(6, &quot;Fish&quot;);
&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;값 삭제&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;wordsArrayList.remove(2); //인덱스 제거 
wordsArrayList.remove(&quot;Dog&quot;); //선택한 값 제거 
&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;여기에서는 우리에게 선택한 요소를 되돌려주고, ArrayList에서 그 요소를 제거하는 것&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;ArrayList - 원소들의 반복&lt;/h4&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;public class studyCollections {
   static List&amp;lt;String&amp;gt; words = List.of(&quot;Apple&quot;, &quot;Bat&quot;, &quot;Cat&quot;);

    public static void main(String[] args) {
        for (int i = 0; i &amp;lt; words.size(); i++){
          System.out.println(i);
        }

        for (String word : words){
            System.out.println(word);
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;기존에는 이런 방식의 반목문을 사용했었습니다 하지만 리스트에서는 반복문을 사용할 수 있는게 하나 더 있습니다&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;armasm&quot;&gt;&lt;code&gt;Iterator wordsIterator = words.iterator();
&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Iterator 인터페이스를 사용하면 조금 더 간편하게 반복문을 돌릴 수 있게됩니다&lt;/li&gt;
&lt;li&gt;접근법에서는 while루프를 사용하면 됩니다&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;dart&quot;&gt;&lt;code&gt;import java.util.Iterator;
import java.util.List;

public class studyCollections {
   static List&amp;lt;String&amp;gt; words = List.of(&quot;Apple&quot;, &quot;Bat&quot;, &quot;Cat&quot;);

    public static void main(String[] args) {
        Iterator wordsIterator = words.iterator();

        while (wordsIterator.hasNext()) {
            System.out.println(wordsIterator.next());
        }

    }
}

&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;반복할 요소가 존재하고 wordsIterator가 next를 가지는 한 계속 반복하게 된다&lt;/li&gt;
&lt;li&gt;Vector 와 LinkedList에서도 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;반복문이 여러 개 인 이유&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;반복문이 3가지가 존재하는 이유는 특정 작업 동안에는 특정 루프를 사용해야 하기 때문입니다&lt;/li&gt;
&lt;li&gt;만약 at 로 끝나는 원소만 출력하고 싶다면&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;import java.util.ArrayList;
import java.util.List;

public class studyCollections {
   static List&amp;lt;String&amp;gt; words = List.of(&quot;Apple&quot;, &quot;Bat&quot;, &quot;Cat&quot;);
   static List&amp;lt;String&amp;gt; wordsAl = new ArrayList&amp;lt;&amp;gt;(words);

   public static void main(String[] args) {
        for(String word: words){
            if(word.endsWith(&quot;at&quot;)){
                System.out.println(word);
            }
        }

    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;하지만 만약에 at로 끝나는 단어를 지우려고 하면&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;import java.util.ArrayList;
import java.util.List;

public class studyCollections {
   static List&amp;lt;String&amp;gt; words = List.of(&quot;Apple&quot;, &quot;Bat&quot;, &quot;Cat&quot;);
   static List&amp;lt;String&amp;gt; wordsAl = new ArrayList&amp;lt;&amp;gt;(words);

   public static void main(String[] args) {
        for(String word: wordsAl){
            if(word.endsWith(&quot;at&quot;)){
                wordsAl.remove(word);
            }
        }
        System.out.println(wordsAl);
    }
}

//결과 : [Apple, Cat]
&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;At로 끝나는 모든 것을 지우려고 했지만 Cat은 삭제되지 않았습니다
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;그 이유는 , 개선된 for 루프를 사용할 때 루프의 중간에서 변경점을 만드는 것은 추천하지 않는 방식 입니다.
&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;이런 상황에서는 iterator 인터페이스를 가지고 하는 것이 추천된다&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;그래서 만약 특정 단어를 리스트에서 제거하고 싶다면, 반복자가 가장 좋을 것이다&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;dart&quot;&gt;&lt;code&gt;import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class studyCollections {
   static List&amp;lt;String&amp;gt; words = List.of(&quot;Apple&quot;, &quot;Bat&quot;, &quot;Cat&quot;);
   static List&amp;lt;String&amp;gt; wordsAl = new ArrayList&amp;lt;&amp;gt;(words);
   static Iterator&amp;lt;String&amp;gt; iterator = wordsAl.iterator();
    
    
   public static void main(String[] args) {
       while (iterator.hasNext()) {
           if (iterator.next().endsWith(&quot;at&quot;)) {
               iterator.remove();
           }
       }
       System.out.println(wordsAl);
    }
}

//결과: [Apple]
 
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그냥 루프만 한다고하면 개선된 for 문이 최고이지만 제거한다고 할 때는 iterator 인터페이스가 제일 좋다&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;리스트 타입 안정성&lt;/h3&gt;
&lt;pre class=&quot;cs&quot;&gt;&lt;code&gt;import java.util.List;

public class studyCollections {
    static List value = List.of(&quot;A&quot;, 'A', 1, 1.0);

    public static void main(String[] args) {
        System.out.println(value.get(2));
        System.out.println(value.get(2) instanceof Integer);
    }
}

// 1
// true
&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이 경우 리스트 타입이 뒤죽박죽 섞여있습니다&lt;/li&gt;
&lt;li&gt;value.get(2)에서 생성된 것은 정수가 아닌데 True가 나온 이유는 리스트 안에는 기초 요소들을 보관할 수 없기 때문입니다
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;true 가 나온 이유는 &lt;a href=&quot;https://inpa.tistory.com/entry/JAVA-%E2%98%95-wrapper-class-Boxing-UnBoxing&quot;&gt;오토복싱&lt;/a&gt; 때문&lt;/li&gt;
&lt;li&gt;리스트를 만드려 할 때 일어나는 일은 이것들이 다 오토복싱되어 래퍼 클래스가 생성되는 것입니다&lt;/li&gt;
&lt;li&gt;value.get(2)의 경우 오토복싱의 래퍼 클래스가 정수&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;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;일반화&lt;/h4&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;  static List&amp;lt;String&amp;gt; value = List.of(&quot;A&quot;,&quot;Banana&quot;);&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;위의 코드는 리스트에 스트링만 저장되게 설정했습니다&lt;/li&gt;
&lt;li&gt;스트링에 정수나 더블을 넣으면 에러가 나게 됩니다&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;import java.util.ArrayList;
import java.util.List;

public class studyCollections {
    static List&amp;lt;Integer&amp;gt; numbers = List.of(101, 102, 103, 104, 105);
    static List&amp;lt;Integer&amp;gt; numberAl = new ArrayList&amp;lt;&amp;gt;(numbers);

    public static void main(String[] args) {
        System.out.println(numberAl.indexOf(101)); // 존재하지 않으니 0을 반환
        System.out.println(numberAl.remove(101));
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이렇게 하면 IndexOutOfBoundsException 에러가 나게 됩니다&lt;/li&gt;
&lt;li&gt;그 이유는 indexOf() 메소드에서는 오버로드된 메소드가 indexOf()를 위해선 없다는 것
&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;무엇이 일어나고 있냐면, 이 101은 정수로 오토복싱되었고 나는 정수를 검색&lt;/li&gt;
&lt;li&gt;하지만 우리가 remove() 메소드를 보게 되면 두 가지가 있는 데 하나는 객체를 받아들이고, 다른 것은 인덱스를 받아들임&lt;/li&gt;
&lt;li&gt;그래서 101이라 했을 때 어떤 일이 벌어지냐면 이 메소드를 사용하고 101을 정수로 오토복싱하는 대신에 무엇을 하냐면, 인덱스를 사용하는 remove 메소드로 변경시켜버린 것&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;배열 정렬 시키기&lt;/h3&gt;
&lt;pre class=&quot;dart&quot;&gt;&lt;code&gt;import java.util.ArrayList;
import java.util.List;

public class studyCollections {
    static List&amp;lt;Integer&amp;gt; numbers = List.of(123, 12, 3, 45);
    static List&amp;lt;Integer&amp;gt; numbersAl = new ArrayList&amp;lt;&amp;gt;(numbers);
    public static void main(String[] args) {
        numbersAl.sort();
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;java: method sort in interface java.util.List&amp;lt;E&amp;gt; cannot be applied to given types;
  required: java.util.Comparator&amp;lt;? super java.lang.Integer&amp;gt;
  found:    no arguments
  reason: actual and formal argument lists differ in length
&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;기존 배열과는 다르게 비교자가 필요하다고 에러가 뜹니다&lt;/li&gt;
&lt;li&gt;기본적으로, 리스트 인터페이스 안의 정렬 메소드를 사용하고 싶다면 비교자를 사용해야 합니다&lt;/li&gt;
&lt;li&gt;저희는 이걸 쉽게 하는 Collections.sort 메소드를 사용할 것 입니다 -&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Collections.sort&lt;/h4&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;Collections.sort(numbersAl);
&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;sort는 Collections안에 존재하는 정적 메소드입니다&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;그 정렬은 Comparable 인터페이스를 사용&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;package collection;

public class Student implements Comparable&amp;lt;Student&amp;gt; {
    private int id;
    private String name;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Student(int id, String name) {
        this.id = id;
        this.name = name;
    }

    public String toString() {
        return id + &quot; &quot; + name;
    }

    @Override
    public int compareTo(Student that) {
        return Integer.compare(this.id, that.id);
    }
}

//여기서 this는 현재 객체를 가르키며 that는 외부에서 갖고온 객체를 의미한다
&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;haxe&quot;&gt;&lt;code&gt;package collection;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class StudentCollectionRunner {
    static List&amp;lt;Student&amp;gt; students = List.of(new Student(1, &quot;Ranga&quot;),
            new Student(100, &quot;Adam&quot;),
            new Student(2, &quot;Eve&quot;)
    );

    static List&amp;lt;Student&amp;gt; studentsAl = new ArrayList&amp;lt;&amp;gt;(students);
    public static void main(String[] args) {
        System.out.println(students);

        Collections.sort(studentsAl);
        System.out.println(studentsAl);

    }
}
// [1 Ranga, 100 Adam, 2 Eve]
// [1 Ranga, 2 Eve, 100 Adam]
&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이렇게 간단하게 정렬이 되는데 만약 뒤집고 싶다면 this와 that 부분만 바꿔주면 됩니다&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;aspectj&quot;&gt;&lt;code&gt;@Override
public int compareTo(Student that) {
        return Integer.compare(that.id, this.id);
    }
    
// 결과값 
// [1 Ranga, 100 Adam, 2 Eve]
// [100 Adam, 2 Eve, 1 Ranga]
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;정렬 - C구현을 통해 유연성을 제공&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;rArr; &lt;b&gt;비교자&lt;/b&gt;를 통해 구현&lt;/p&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;package collection;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

class AscendingStudentComparator implements Comparator&amp;lt;Student&amp;gt; {

    @Override
    public int compare(Student student1, Student student2) {
        return Integer.compare(student1.getId(), student2.getId());
    }

}

public class StudentCollectionRunner {
    static List&amp;lt;Student&amp;gt; students = List.of(new Student(1, &quot;Ranga&quot;),
            new Student(100, &quot;Adam&quot;),
            new Student(2, &quot;Eve&quot;)
    );

    static List&amp;lt;Student&amp;gt; studentsAl = new ArrayList&amp;lt;&amp;gt;(students);

    public static void main(String[] args) {
        System.out.println(students);

        Collections.sort(studentsAl);
        System.out.println(&quot;Desc&quot; + studentsAl);

        Collections.sort(studentsAl, new AscendingStudentComparator());
        System.out.println(&quot;AscendingStudentComparator &quot; + studentsAl);

    }
}

/* 
출력결과 

[1 Ranga, 100 Adam, 2 Eve]
ASC[100 Adam, 2 Eve, 1 Ranga]
DescendingStudentComparator [1 Ranga, 2 Eve, 100 Adam]

*/

&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;기본형을 이용할 때 아무 인수를 넣지 않았다면 Student 클래스 안에 있는 논리를 쓸 것이고 이렇게 오름차순과 내림차순이 출력 됩니다&lt;/li&gt;
&lt;li&gt;사실 Comparator 인터페이스를 여러 번 구현할 수 있습니다&lt;/li&gt;
&lt;li&gt;즉, 10가지의 다른 구현을 생성하고 10가지 다른 알고리즘을 통해 학생들을 분류할 수 있게 되는 것
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이름을 기준으로 정렬, id를 기준으로 정렬 혹은 이름과 id의 결합으로 정렬이 가능합니다
&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;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;리스트 요약&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;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;즉, 이것은 컬렉션 인터페이스에 있는 모든 것을 구현하고 거기에 더해서, 객체의 위치에 상관하는 메서드를 제공한다&lt;/li&gt;
&lt;li&gt;그래서, 리스트의 끝이나 중간, 어디든지 요소를 삽입할 수 있다&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-end=&quot;137&quot; data-start=&quot;121&quot; data-ke-size=&quot;size26&quot;&gt;  References&lt;/h2&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-end=&quot;502&quot; data-start=&quot;139&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li data-end=&quot;283&quot; data-start=&quot;139&quot;&gt;Inpa Dev  &amp;zwj; , JAVA ☕ Wrapper Class - Boxing &amp;amp; UnBoxing&lt;br /&gt;&lt;a href=&quot;https://inpa.tistory.com/entry/JAVA-%E2%98%95-wrapper-class-Boxing-UnBoxing&quot;&gt;https://inpa.tistory.com/entry/JAVA-%E2%98%95-wrapper-class-Boxing-UnBoxing&lt;/a&gt;&lt;/li&gt;
&lt;li data-end=&quot;403&quot; data-start=&quot;285&quot;&gt;TechVidvan, Java Collection Framework Tutorial&lt;br /&gt;&lt;a href=&quot;https://techvidvan.com/tutorials/java-collection-framework/&quot;&gt;https://techvidvan.com/tutorials/java-collection-framework/&lt;/a&gt;&lt;/li&gt;
&lt;li data-end=&quot;502&quot; data-start=&quot;405&quot;&gt;Udemy, Best Java Programming Course&lt;br /&gt;&lt;a href=&quot;https://www.udemy.com/course/best-java-programming/&quot;&gt;https://www.udemy.com/course/best-java-programming/&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt; &amp;nbsp;함께&amp;nbsp;보면&amp;nbsp;좋은&amp;nbsp;글&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://joon0112.tistory.com/70&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;[TIL]HashSet vs TreeSet vs LinkedHashSet 차이점과 PriorityQueue 이해&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://joon0112.tistory.com/71&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;[TIL]&amp;nbsp;-&amp;nbsp;Java&amp;nbsp;Map&amp;nbsp;구조&amp;nbsp;이해하기&amp;nbsp;&amp;mdash;&amp;nbsp;HashMap,&amp;nbsp;LinkedHashMap,&amp;nbsp;TreeMap&amp;nbsp;언제&amp;nbsp;사용할까?&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Java Collection 팁들&amp;nbsp;&lt;/h2&gt;
&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;순서가 정해지고 모든 요소가 한번만 처리되는 Queue&lt;/li&gt;
&lt;li&gt;키-값 쌍을 저장하는데 쓰이는 Map&lt;/li&gt;
&lt;li&gt;Hash
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Collection의 이름에서 Hash를 본다면 순서도 없고 정렬도 되어 있지 않다는 걸 기억!&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;삽입 순서, 정렬 순서 xxx&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Linked
&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;b&gt;삽입 순서대로 데이터를 저장&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Tree
&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;즉, 언제든지 Tree라는 키워드가 보이면 &lt;b&gt;데이터가 정렬된 순서로 저장&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;Tree는 기본적으로 데이터가 저장되어 있기 때문에 NavigableSet이나 NavigableMap 구현이 있을 것이다&lt;/li&gt;
&lt;li&gt;즉, TreeSet은 NavigableSet을 구현하고 TreeMap은 NavigableMap을 구현하는 것&lt;/li&gt;
&lt;li&gt;트리셋과 트리맵은 하위 셋을 Collection의 종류에 따라 키나 값을 이용해 하위 Set을 만들 수 있는 추가적인 작업들도 있다&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Back-end/Java</category>
      <category>Java</category>
      <category>list</category>
      <category>Til</category>
      <category>자바 자료구조</category>
      <author>dev_Hyeonjoon</author>
      <guid isPermaLink="true">https://joon0112.tistory.com/69</guid>
      <comments>https://joon0112.tistory.com/69#entry69comment</comments>
      <pubDate>Thu, 12 Feb 2026 17:55:34 +0900</pubDate>
    </item>
    <item>
      <title>[TIL] 인터페이스</title>
      <link>https://joon0112.tistory.com/68</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;인터페이스란&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인터페이스는 &amp;ldquo;이 기능을 제공하겠다&amp;rdquo;는 약속(계약)&lt;/p&gt;
&lt;/blockquote&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;100% 추상 메서드와 상수만을 포함(Java 8이후로 부터 default 와 static 포함)하며, 다중 구현을 통해 다형성을 극대화하고 클래스 간의 결합도를 낮추는 핵심적인 설계 도구입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;인터페이스 구현&lt;/h3&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;public interface GamingConsole {
    public void up();
    public void down();
    public void left();
    public void right();   
}&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;interface 만 붙이면 됩니다.&lt;/li&gt;
&lt;li&gt;인터페이스 안에서는 추상 클래스와 유사하게 그냥 메서드만 선언하고 구현 부분은 비워두면 됩니다&lt;/li&gt;
&lt;li&gt;추상 클래스와 유사하게 인터페이스도 그 자체로는 인스턴스를 생성할 수 없으며, 추상 클래스가 상속을 통해 완성되는 것 처럼 인터페이스도 구현부를 만들어주는 클래스에 상속되어야 합니다&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;java&quot;&gt;&lt;code&gt;public class MarioGame implements GamingConsole {

    @Override
    public void up() {
        System.out.println(&quot;Jump&quot;);
    }

    @Override
    public void down() {
        System.out.println(&quot;Goes into a hole&quot;);
    }

    @Override
    public void left() {
        System.out.println(&quot;left&quot;);
    }

    @Override
    public void right() {
        System.out.println(&quot;right&quot;);
    }
}

&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;그 후 인터페이스를 상속받는 클래스에서 메소드를 정의하면 됩니다&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;public class GameRunner {
    public static void main(String[] args) {
        GamingConsole game = new MarioGame();
        game.up();
        game.down();
        game.left();
        game.right();
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;인터페이스의 장점&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다중 구현이 가능&lt;br /&gt;클래스 상속과 인터페이스 구현이 동시에 가능&lt;/p&gt;
&lt;/blockquote&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;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;java&quot;&gt;&lt;code&gt;public class ChessGame implements GamingConsole{
    @Override
    public void up() {
        System.out.println(&quot;Move piece up&quot;);
    }

    @Override
    public void down() {
        System.out.println(&quot;Move piece down&quot;);
    }

    @Override
    public void left() {
        System.out.println(&quot;Move piece left&quot;);
    }

    @Override
    public void right() {
        System.out.println(&quot;Move piece right&quot;);
    }
}

&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;public class GameRunner {
    public static void main(String[] args) {
        //GamingConsole game = new MarioGame();

        GamingConsole game = new ChessGame();
        game.up();
        game.down();
        game.left();
        game.right();
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;같은 코드인데 결과만 달라지는걸 확인할 수 있습니다
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;단지 MarioGame() 을 ChessGame()으로 바꿔주기만 했습니다&lt;/li&gt;
&lt;li&gt;이것을 바로 &lt;b&gt;다형성&lt;/b&gt;이라고 부릅니다&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한 클래스 상속과 인터페이스 구현이 동시에 가능한데 아래와 같이 사용할 수 있습니다.&lt;/p&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;public class ChessGame extends boardGame implements GamingConsole{}&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;외부에서 정의된 API [인터페이스 활용]&lt;/h2&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;public interface ComplexAlgorithm {
    int complexAlgorithm(int number1, int number2);
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;public class DummyAlgorithm implements ComplexAlgorithm{
    public int complexAlgorithm(int number1, int number2) {
        return number1 + number2;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;public class Project {
    public static void main(String[] args) {
        ComplexAlgorithm algorithm = new DummyAlgorithm();
        System.out.println(algorithm.complexAlgorithm(10, 20));
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이 코드가 오류 없이 작동하는 이유는 두 시스템 사이의 통신을 정의하는 ComplexAlgorithm 이라는 인터페이스가 있기 때문입니다.&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;나중에 ~.complexAlgorithm(10, 20)을 호출하면, 어떤 클래스가 실제로 구현했는지에 따라 동작이 달라지기 때문에 &lt;b&gt;같은 타입(ComplexAlgorithm)으로 묶어서 관리하면서, 실제 동작은 구현체에 따라 바뀌도록&lt;/b&gt; 만드는 거죠.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;새로운 알고리듬 추가 시키기&lt;/h3&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;public class RealAlgorithm implements ComplexAlgorithm{
    public int complexAlgorithm(int number1, int number2) {
        return number1 * number2;
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;public class Project {
    public static void main(String[] args) {

        ComplexAlgorithm algorithm = new RealAlgorithm();
        System.out.println(algorithm.complexAlgorithm(10, 20));
    }
}

&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;인터페이스끼리의 확장&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1176&quot; data-origin-height=&quot;214&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/q8KCC/dJMcahcdlZo/7d5ZoFP3g80sxayenxxks0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/q8KCC/dJMcahcdlZo/7d5ZoFP3g80sxayenxxks0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/q8KCC/dJMcahcdlZo/7d5ZoFP3g80sxayenxxks0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fq8KCC%2FdJMcahcdlZo%2F7d5ZoFP3g80sxayenxxks0%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;1176&quot; height=&quot;214&quot; data-origin-width=&quot;1176&quot; data-origin-height=&quot;214&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;인터페이스 끼리 확장하는 건 extends를 통해 인터페이스를 상속 시키면 됩니다.&lt;/li&gt;
&lt;li&gt;클래스는 &lt;b&gt;Interface2만 구현해도 가능&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;단, &lt;b&gt;Interface2가 상속한 모든 인터페이스의 메서드까지 전부 구현해야 합니다&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1072&quot; data-origin-height=&quot;264&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/XUnl0/dJMcadnkbS4/4tgLPn7e6coYLk494vKWq0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/XUnl0/dJMcadnkbS4/4tgLPn7e6coYLk494vKWq0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/XUnl0/dJMcadnkbS4/4tgLPn7e6coYLk494vKWq0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FXUnl0%2FdJMcadnkbS4%2F4tgLPn7e6coYLk494vKWq0%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;1072&quot; height=&quot;264&quot; data-origin-width=&quot;1072&quot; data-origin-height=&quot;264&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;만약 클래스에 인터페이스를 사용한다면 이렇게 인터페이스에 해당하는 메소드들을 적어줘야합니다
&lt;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;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;추상 클래스를 사용한 인터페이스&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1234&quot; data-origin-height=&quot;178&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/yuKTm/dJMcahXBFqM/1krrSaA00PFvYn6174pnm0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/yuKTm/dJMcahXBFqM/1krrSaA00PFvYn6174pnm0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/yuKTm/dJMcahXBFqM/1krrSaA00PFvYn6174pnm0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FyuKTm%2FdJMcahXBFqM%2F1krrSaA00PFvYn6174pnm0%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;1234&quot; height=&quot;178&quot; data-origin-width=&quot;1234&quot; data-origin-height=&quot;178&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;추상 클래스는 인터페이스에 정의되어 있는 메소드들의 일부만 구현하는걸 허용합니다&lt;/li&gt;
&lt;li&gt;하지만 아무 클래스, 추상 클래스를 연장하는 구상 클래스는 당연히 모든 것을 구현해야 합니다&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;상수만 가지는 인터페이스&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;688&quot; data-origin-height=&quot;270&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/BzoKa/dJMcad1UKO1/dFXndkY1mkEXQXCLdhWCLk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/BzoKa/dJMcad1UKO1/dFXndkY1mkEXQXCLdhWCLk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/BzoKa/dJMcad1UKO1/dFXndkY1mkEXQXCLdhWCLk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FBzoKa%2FdJMcad1UKO1%2FdFXndkY1mkEXQXCLdhWCLk%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;688&quot; height=&quot;270&quot; data-origin-width=&quot;688&quot; data-origin-height=&quot;270&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;인터페이스는 항상 상수를 가집니다.&lt;/li&gt;
&lt;li&gt;여기서 public static final 은 생략해도 상관없습니다.
&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;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;692&quot; data-origin-height=&quot;158&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bnZwJB/dJMcaaKWg52/wZKquWRmes4RudSLXjMAY1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bnZwJB/dJMcaaKWg52/wZKquWRmes4RudSLXjMAY1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bnZwJB/dJMcaaKWg52/wZKquWRmes4RudSLXjMAY1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbnZwJB%2FdJMcaaKWg52%2FwZKquWRmes4RudSLXjMAY1%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;692&quot; height=&quot;158&quot; data-origin-width=&quot;692&quot; data-origin-height=&quot;158&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;default 키워드&lt;/h2&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;하지만 자바 8 이후로는 default를 넣으면 꼭 그렇게 안해도 됩니다&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;java&quot;&gt;&lt;code&gt;public class Project {
    public static void main(String[] args) {

        interface Test{
            void nothing();
            default void nothing1() {}
        }

        class Class1 implements Test{

            @Override
            public void nothing() {}
        }
        class Class2 implements Test{

            @Override
            public void nothing() {}
        }

    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;nothing1 은 어느 클래스에서도 구현하고 있지 않습니다&lt;/li&gt;
&lt;li&gt;하지만 컴파일 오류 없이 잘 굴러갑니다&lt;/li&gt;
&lt;li&gt;이것이 특히나 유용한 상황은 만약 내가 인터페이스를 제공하지만 또 다른 제 3자가 인터페이스의 구현을 제공할 때입니다.&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;왜냐면 내가 제 3자의 코드를 망치지 않을 수 있기 때문&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;인터페이스 vs 추상 클래스&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;인터페이스 사용시기&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;두 시스템 사이에서 소통하길 원할 때&lt;/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;추상 클래스 사용 시점&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;가장 큰 차이점&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;인터페이스 안에는 변수가 안된다
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&amp;harr; 추상 클래스에서는 일반 클래스와 마찬가지로 모든 변수를 가질 수 있다&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;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;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;참고자료  &lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://zero-zae.tistory.com/219#개요&quot;&gt;https://zero-zae.tistory.com/219#개요&lt;/a&gt;&lt;a href=&quot;https://zero-zae.tistory.com/219#%EA%B0%9C%EC%9A%94%C2%A0-1&quot;&gt;&amp;nbsp;-1&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://inpa.tistory.com/entry/JAVA-&quot;&gt;https://inpa.tistory.com/entry/JAVA-&lt;/a&gt;&lt;a href=&quot;https://inpa.tistory.com/entry/JAVA-%E2%98%95-%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4Interface%EC%9D%98-%EC%A0%95%EC%84%9D-%ED%83%84%ED%83%84%ED%95%98%EA%B2%8C-%EA%B0%9C%EB%85%90-%EC%A0%95%EB%A6%AC#%EC%9E%90%EB%B0%94%EC%9D%98_%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4&quot;&gt;☕-인터페이스Interface의-정석-탄탄하게-개념-정리#자바의_인터페이스&lt;/a&gt;&lt;/p&gt;</description>
      <category>Back-end/Java</category>
      <category>Java</category>
      <category>Til</category>
      <category>다형성</category>
      <category>인터페이스</category>
      <category>인터페이스vs추상클래스</category>
      <author>dev_Hyeonjoon</author>
      <guid isPermaLink="true">https://joon0112.tistory.com/68</guid>
      <comments>https://joon0112.tistory.com/68#entry68comment</comments>
      <pubDate>Fri, 6 Feb 2026 00:43:26 +0900</pubDate>
    </item>
    <item>
      <title>[TIL] 추상 클래스란? 개념, 사용 이유, 예제로 이해하기</title>
      <link>https://joon0112.tistory.com/67</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;추상 클래스&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;추상 클래스 덕분에 기본 알고리즘 정의가 가능&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;추상화란?&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;알고는 있지만 정확하게 표현하기 힘든 것들을 중요한 부분이나 특징점을 잡아 설명하는 것&lt;/blockquote&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;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&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;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;출처 &amp;amp; 더 자세히 알아보기 : [&lt;a href=&quot;https://www.notion.so/28de0b38263d80aeb400ee3cc9671ce2?pvs=21&quot;&gt;Inpa Dev  &amp;zwj; :티스토리&lt;/a&gt;]&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;추상 클래스 사용 이유&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;자바에서 추상 클래스(Abstract Class)는 공통된 필드와 메서드를 추출하여 상위 클래스에서 정의하고, 하위 클래스에서 이를 상속받아 구체적으로 구현하도록 강제하여&amp;nbsp;코드의 재사용성, 일관성, 그리고 유지보수성을 높이기 위해 사용합니다. 인스턴스화를 막아 설계도 역할을 하며, 템플릿 메서드 패턴을 통해 구조적이고 유연한 시스템을 구축할 수 있게 합니다.&lt;/blockquote&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;추상 클래스 문법&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;추상 클래스는 단순히&lt;span style=&quot;background-color: #dddddd; color: #ee2323;&quot;&gt; abstract &lt;/span&gt;를 붙임으로써 자바 컴파일러에게 추상 클래스라는 것을 알려줍니다&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;public abstract class AbstractRecipe {
    public void execute(){
        getReady();
        doTheDish();
        cleanup();
    }
    abstract void getReady();
    abstract void doTheDish();
    abstract void cleanup();
}&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;추상 메소드에서는 메소소드 선언만 작성하고 구현 부분은 작성하지 않습니다.
&lt;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;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;추상 메서드를 비워두는 이유&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;자식 클래스에 따라 어떤 행동을 할지 모르기 때문입니다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;즉, 주제만 추상 클래스에서 작성하고&lt;b&gt; 실제 행동은 상속받는 클래스에서 작성&lt;/b&gt;하면 되는거죠&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;추상 클래스 상속 받기&lt;/h3&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;public class Recipe1 extends AbstractRecipe{
}&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;단순히&lt;span style=&quot;background-color: #dddddd; color: #ee2323;&quot;&gt; extends &lt;/span&gt;키워드를 사용하면 쉽게 상속 받을 수 있습니다&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;추상 메소드 구현하기&lt;/h3&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;public abstract class AbstractRecipe {
    public String recipeName; //인스턴스 필드
    public void execute(){ //인스턴스 메소드
        getReady();
        doTheDish();
        cleanup();
    }
    //추상 메소드
    abstract void getReady();
    abstract void doTheDish();
    abstract void cleanup();
}

class Recipe1 extends AbstractRecipe{
    @Override
    void getReady(){
        System.out.println(&quot;Get the raw materials&quot;);
        System.out.println(&quot;Get the utensils&quot;);
    };

    @Override
    void doTheDish(){
        System.out.println(&quot;prepare the dish&quot;);
    }

    @Override
    void cleanup(){
        System.out.println(&quot;Cleanup the utensils&quot;);
    }

    public static void main(String[] args) {
        Recipe1 recipe1 = new Recipe1();
        recipe1.execute();
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;@Overide 는 물론 생략이 가능합니다.&lt;/li&gt;
&lt;li&gt;추상 클래스는 일반 클래스와 &lt;b&gt;거의 동일하지만&lt;/b&gt;, 인스턴스 생성 불가 + 추상 메서드 강제 구현이라는 &lt;b&gt;설계 제약이 핵심 차이&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;추상 클래스에도 생성자가 있으며 독립적인 인스턴스 멤버 변수와 메서드도 가질 수 있기 때문입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;추상적 클래스는 인스턴스를 만들 수 없다.&lt;/h3&gt;
&lt;pre class=&quot;ebnf&quot;&gt;&lt;code&gt;AbstractRecipe recipe = new AbstractRecipe();
&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이렇게 작성을하면 에러가 납니다.&lt;/li&gt;
&lt;li&gt;그 이유는 추상 클래스는 상속 구조에서 부모 클래스를 나타내는 역할로만 이용되기 때문입니다.&lt;/li&gt;
&lt;li&gt;추상 메소드는 정의도 없고 형태도 없는 메소드를 의미&lt;/li&gt;
&lt;li&gt;따라서 구상 클래스가 추상 클래스를 연장하려면 모든 추상 메소드에 대해 구현해야 합니다&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;추상 클래스 끼리 확장 시키기&lt;/h3&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;abstract class Recipe1 extends AbstractRecipe{
	...
}&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;추상 클래스끼리 확장하는 방법도 물론 가능합니다&lt;/li&gt;
&lt;li&gt;하지만 나중에 자식 클래스가 구상 클래스라면 모든 추상 클래스의 메소드를 구현해야합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;추상 클래스는 상태(필드)를 가질 수 있고, 인터페이스는 행동 규약에 집중한다&lt;/blockquote&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;참고 자료  &lt;/h1&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://inpa.tistory.com/entry/JAVA-%E2%98%95-%EC%B6%94%EC%83%81-%ED%81%B4%EB%9E%98%EC%8A%A4Abstract-%EC%9A%A9%EB%8F%84-%EC%99%84%EB%B2%BD-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0#%EC%B6%94%EC%83%81_%ED%81%B4%EB%9E%98%EC%8A%A4_%EC%99%80_%EC%B6%94%EC%83%81%ED%99%94&quot;&gt;추상 클래스 -inpa&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Back-end/Java</category>
      <category>Java</category>
      <category>Til</category>
      <category>객체지향프로그래밍</category>
      <category>추상메소드</category>
      <category>추상클래스</category>
      <author>dev_Hyeonjoon</author>
      <guid isPermaLink="true">https://joon0112.tistory.com/67</guid>
      <comments>https://joon0112.tistory.com/67#entry67comment</comments>
      <pubDate>Thu, 5 Feb 2026 18:07:46 +0900</pubDate>
    </item>
    <item>
      <title>[TIL] 자바 객체 설계부터 상속까지 (+ toString이 자동 호출되는 이유)</title>
      <link>https://joon0112.tistory.com/66</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;클래스 및 객체 구성 설계&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;상속하기 전 &amp;lsquo;설계&amp;rsquo; 단계는 매우 중요합니다&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;객체 구성 관계&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클래스를 먼저 결정하고 그다음에는 각 클래스가 어떻게 구성될지 계획해야 한다&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;객체는 멤버 변수의 값으로 정의되는 &lt;b&gt;&amp;lsquo;상태&amp;rsquo;&lt;/b&gt;라는 개념을 가지고 있습니다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;해당 객체의 인스턴스를 통해 노출되는 &lt;b&gt;&amp;lsquo;행동&amp;rsquo; &lt;/b&gt;이라는 개념 또한 가지고 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;객체 구성 관계 (객체 컴포지션)&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;public class Customer {
    private String name;
    private Address address;
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;public class Address {
    private String line1;
    private String city;
    private String zip;
}&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;두 개의 코드들을 보면 Customer 안에 Address 클래스가 있다는걸 확인하 수 있습니다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이게 바로 &lt;b&gt;객체 구성 관계&lt;/b&gt;인데요&lt;/li&gt;
&lt;li&gt;Customer 클래스는 주소 클래스의 인스턴스에 대해 참조 역할을 하는 것&lt;/li&gt;
&lt;li&gt;그래서 클래스를 디자인할 때 중요한 것 중 하나가 다른 객체의 관계를 살펴보는 것입니다&lt;/li&gt;
&lt;li&gt;생성자에는 필수적인 것을 넣고 필수적이지 않다면 setter에서 추가 시켜주면 됩니다&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;클래스를 설계할 때 고려해야 할 세 가지&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;1. 상태가 어떠한지&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재 시점에서 어떤 변숫값을 가질지 고려&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;public class MotorBike {
	//상태
	private int speed; //멤버 변수
}
&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;예제에서는 속도 라는 상태밖에 없지만 나중에 색깔이나 브랜드 등 여러가지가 올 수 있습니다&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2. 어떤 생성자를 가지는지&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어떤 클래스가 되길 원하는지 고려&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;예제를 보면, 누군가 MotorBike 인스턴스를 직접 만든다고 하면 속도를 5로 지정할 수 있지만 초깃값을 미리 설정해 둘 수 있는 것&lt;/li&gt;
&lt;li&gt;&lt;b&gt;생성자에는 꼭 필요한 상태만 올 수 있어야 합니다&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;processing&quot;&gt;&lt;code&gt;public class Fan {
    //상태 (필수O)
    private String make;
    private double radius;
    private String color;

    //상태 (필수X)
    private boolean isOn;
    private byte speed;

    //생성자
    public Fan(String make, double radius, String color){
        this.make = make;
        this.radius = radius;
        this.color = color;
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;3. 행동&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;객체를 통해 실행하고자 하는 메소드가 어떤게 있을지 고려&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre class=&quot;processing&quot;&gt;&lt;code&gt;public class Fan {
    //상태 (필수O)
    private String make;
    private double radius;
    private String color;

    //상태 (필수X)
    private boolean isOn;
    private byte speed;

    //생성자
    public Fan(String make, double radius, String color){
        this.make = make;
        this.radius = radius;
        this.color = color;
    }

		//메서드
    public String toString(){
       return String.format(&quot;make - %s , radius - %f , color - %s , isOn - %b , speed - %d&quot;, make, radius, color, isOn, speed);
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;객체를 스트링으로 변환 시키는 메서드&lt;/li&gt;
&lt;li&gt;System.out.println 으로 출력 시 구문만 잘 매칭시킨다면 자동으로 출력해줄 것 입니다.&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;1426&quot; data-origin-height=&quot;140&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/2gtS7/dJMcaajRlnV/JOXuFen6nX8ZcbtwDsF3L1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/2gtS7/dJMcaajRlnV/JOXuFen6nX8ZcbtwDsF3L1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/2gtS7/dJMcaajRlnV/JOXuFen6nX8ZcbtwDsF3L1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F2gtS7%2FdJMcaajRlnV%2FJOXuFen6nX8ZcbtwDsF3L1%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;1426&quot; height=&quot;140&quot; data-origin-width=&quot;1426&quot; data-origin-height=&quot;140&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;toString이 자동 호출되는 이유 ⁉️&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1️⃣Object 타입을 받는 println 오버로드 메서드&lt;/b&gt;가 있기 때문에.&lt;/p&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;public void println(Object x) {
	String s = String.valueOf(x);
    print(s);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 여기서 핵심이 String.valueOf(x)  &lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt; &lt;b&gt;2️⃣&lt;/b&gt;&amp;nbsp;String.valueOf(Object)가 하는 역할&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;public static StringvalueOf(Object obj) {
		return (obj == null) ? &quot;null&quot; : obj.toString();
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;객체가 null이면 &quot;null&quot;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;null 아니면 &amp;rarr; obj.toString() 호출&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;  이 시점에서 &lt;b&gt;&amp;nbsp;만든 Fan의 toString()이 실행되는 것&lt;/b&gt;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;b&gt;3️⃣&lt;/b&gt;&lt;/b&gt;&amp;nbsp;&lt;b&gt;왜 Fan의 toString이 실행될까? &lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자바의 핵심 개념 하나:&lt;/p&gt;
&lt;pre class=&quot;ebnf&quot;&gt;&lt;code&gt;Fan fan = new Fan(...);

&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;변수 타입: Fan&lt;/li&gt;
&lt;li&gt;실제 객체 타입: Fan&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;println은 Object 기준으로 호출하지만  Fan에서 &lt;b&gt;오버라이딩한 toString()이 실행됨&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;fan.toString();
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이게 &lt;b&gt;암묵적으로&lt;/b&gt; 일어나는 거야.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4️⃣ 만약 toString을 안 만들었다면?&lt;/p&gt;
&lt;pre class=&quot;gherkin&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot;&gt;&lt;code&gt;클래스명@해시코드
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이건 Object 클래스의 기본 toString() 결과&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5️⃣ 흐름을 한 줄로 정리하면&lt;/p&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;System.out.println(fan)
        &amp;darr;
println(Object)
        &amp;darr;
String.valueOf(fan)
        &amp;darr;
fan.toString()
        &amp;darr;
Fan 클래스의 toString 실행
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;6️⃣ 그래서 중요한 포인트 정리&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;println(fan)이 &lt;b&gt;toString을 직접 부른 건 아님&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;하지만 &lt;b&gt;Object를 출력할 때 자바가 자동으로 toString 호출&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;이건 &lt;b&gt;자바 언어 차원의 규칙&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;그래서 디버깅, 로그, 출력에서 toString()이 엄청 중요함&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;상태를 변화 시키는 메서드&lt;/h3&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;public class Fan {
    //상태 (필수O)
    private String make;
    private double radius;
    private String color;

    //상태 (필수X)
    private boolean isOn;
    private byte speed;

    //생성자
    public Fan(String make, double radius, String color){
        this.make = make;
        this.radius = radius;
        this.color = color;
    }

    //isOn
    public void isOn(boolean isOn){
        this.isOn = isOn;
    }

    //상태 출력하기
    public String toString(){
       return String.format(&quot;make - %s , radius - %f , color - %s , isOn - %b , speed - %d&quot;, make, radius, color, isOn, speed);
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;public class FanRunner {
    public static void main(String[] args) {
        Fan fan = new Fan(&quot;Manufacturer 1&quot;, 0.34567, &quot;GREEN&quot;);
        fan.isOn(true);

        System.out.println(fan);
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이렇게 하면 상태를 변화시킬 수 있습니다.&lt;/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;/ul&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;public class Fan {
    //상태 (필수O)
    private String make;
    private double radius;
    private String color;

    //상태 (필수X)
    private boolean isOn;
    private byte speed;

    //생성자
    public Fan(String make, double radius, String color){
        this.make = make;
        this.radius = radius;
        this.color = color;
    }

    //isOn
    public void isOn(boolean isOn){
        this.isOn = isOn;
    }

    public void switchOn(){
        this.isOn = true;
    }

    public void switchOff() {
        this.isOn = false;
    }
    //상태 출력하기
    public String toString(){
       return String.format(&quot;make - %s , radius - %f , color - %s , isOn - %b , speed - %d&quot;, make, radius, color, isOn, speed);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;public class FanRunner {
    public static void main(String[] args) {
        Fan fan = new Fan(&quot;Manufacturer 1&quot;, 0.34567, &quot;GREEN&quot;);
        fan.switchOn();
        System.out.println(fan);
        fan.switchOff();
        System.out.println(fan);
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1466&quot; data-origin-height=&quot;118&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bi2NU4/dJMcac9Lk5S/ezZ5rYTKTbBEVh938WRNv0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bi2NU4/dJMcac9Lk5S/ezZ5rYTKTbBEVh938WRNv0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bi2NU4/dJMcac9Lk5S/ezZ5rYTKTbBEVh938WRNv0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbi2NU4%2FdJMcac9Lk5S%2FezZ5rYTKTbBEVh938WRNv0%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;1466&quot; height=&quot;118&quot; data-origin-width=&quot;1466&quot; data-origin-height=&quot;118&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;더 사용자 친화적이게 됐습니다&lt;/li&gt;
&lt;li&gt;계속 고민해야할 것 중 하나는 이렇게 &lt;b&gt;언제나 사용자 입장에서 고민해야 한다는 점&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;전형적으로 객체에 대해 연관 지어 생각하는 부분은 getter와 setter인데 그렇게 연관 짓는 것은 좋지 않다 항상 사용자가 객체에 대해 어떤 생각할지, 어떤 메소드가 나의 객체를 사용하기 쉽게 할지 생각해야한다&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;상속&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;상속을 하는 이유&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;중복을 피하기 위해서&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;public class Person {
    private String name;
    private String email;
    private String phoneNumber;

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPhoneNumber() {
        return phoneNumber;
    }

    public void setPhoneNumber(String phoneNumber) {
        this.phoneNumber = phoneNumber;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;public class Student {
    public class Person {
        private String name;
        private String email;
        private String phoneNumber;

        private String college;
        private int year;

        public String getEmail() {
            return email;
        }

        public void setEmail(String email) {
            this.email = email;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public String getPhoneNumber() {
            return phoneNumber;
        }

        public void setPhoneNumber(String phoneNumber) {
            this.phoneNumber = phoneNumber;
        }

        public String getCollege() {
            return college;
        }

        public void setCollege(String college) {
            this.college = college;
        }

        public int getYear() {
            return year;
        }

        public void setYear(int year) {
            this.year = year;
        }
    }

}&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이렇게 &amp;lsquo;Person&amp;rsquo; 과 &amp;lsquo;Student&amp;rsquo; 클래스가 각각 있을 때 서로 중복되는 코드가 매우 많습니다
&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;
&amp;rArr; 이를 상속을 통한 해결!&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;우리가 무의식으로 상속하고 있던 것.&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2386&quot; data-origin-height=&quot;1130&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b4aQ9K/dJMcahDf8My/7XqBtKrC2XK4UU5amkIT1k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b4aQ9K/dJMcahDf8My/7XqBtKrC2XK4UU5amkIT1k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b4aQ9K/dJMcahDf8My/7XqBtKrC2XK4UU5amkIT1k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb4aQ9K%2FdJMcahDf8My%2F7XqBtKrC2XK4UU5amkIT1k%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;2386&quot; height=&quot;1130&quot; data-origin-width=&quot;2386&quot; data-origin-height=&quot;1130&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;형광펜 칠해진 사진을 보면 우리가 메소드를 정의한 적이 없는데 사용할 수 있는 메서들을 확인할 수 있습니다&lt;/li&gt;
&lt;li&gt;이는 Java의 기능으로써 아무것도 확장하지 않았을 경우 &lt;b&gt;모든 클래스가 Object 클래스를 확장하였기 때문입니다.&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;public class Person extends Object
//자바는 암묵적으로 Obejct클래스를 확장!&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1888&quot; data-origin-height=&quot;1298&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cdoGLN/dJMcahccpVw/j1gAt73D96fmk8lkKpP5M0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cdoGLN/dJMcahccpVw/j1gAt73D96fmk8lkKpP5M0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cdoGLN/dJMcahccpVw/j1gAt73D96fmk8lkKpP5M0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcdoGLN%2FdJMcahccpVw%2Fj1gAt73D96fmk8lkKpP5M0%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;1888&quot; height=&quot;1298&quot; data-origin-width=&quot;1888&quot; data-origin-height=&quot;1298&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Object 객체는 사진에서 맛보기로 확인할 수 있습니다.&lt;/li&gt;
&lt;li&gt;이 객체가 클래스 체계의 근본이며 &amp;ldquo;**모든 다른 클래스가 다른 객체나 클래스로부터 상속을 해야만 한다&amp;rdquo;**는 말이 적혀 있습니다
&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;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;오버라이딩&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모든 클래스는 Object 클래스의 하위 클래스&lt;br /&gt;하위 클래스에서 상위 클래스에서 제공하는 메서드를 덮어씌울 수 있다&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;public class StudentRunner {
    public static void main(String[] args) {
        Person person = new Person();
        String value = person.toString();
        
        System.out.println(value);
        System.out.println(person);

    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;514&quot; data-origin-height=&quot;104&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/duyIkG/dJMcaaxo5L6/4H9i88WerRqNIKKKjRT1UK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/duyIkG/dJMcaaxo5L6/4H9i88WerRqNIKKKjRT1UK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/duyIkG/dJMcaaxo5L6/4H9i88WerRqNIKKKjRT1UK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FduyIkG%2FdJMcaaxo5L6%2F4H9i88WerRqNIKKKjRT1UK%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;514&quot; height=&quot;104&quot; data-origin-width=&quot;514&quot; data-origin-height=&quot;104&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재의 toString의 출력값은 사진과 같이 나오는데 그 이유는 Object 클래스 떄문&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1904&quot; data-origin-height=&quot;946&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/EnscZ/dJMb99LZKwT/25t6CgBecwSNYZueuE39m1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/EnscZ/dJMb99LZKwT/25t6CgBecwSNYZueuE39m1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/EnscZ/dJMb99LZKwT/25t6CgBecwSNYZueuE39m1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FEnscZ%2FdJMb99LZKwT%2F25t6CgBecwSNYZueuE39m1%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;1904&quot; height=&quot;946&quot; data-origin-width=&quot;1904&quot; data-origin-height=&quot;946&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;저는 toString이 이렇게 '@' 대신 '#' 으로 출력되길 원합니다
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;똑같은 메소드 이름으로 덮어씌우는 걸 &lt;b&gt;메소드&lt;/b&gt; &lt;b&gt;오버라이딩&lt;/b&gt;이라고 합니다&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;public class Person extends Object{
    private String name;
    private String email;
    private String phoneNumber;

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPhoneNumber() {
        return phoneNumber;
    }

    public void setPhoneNumber(String phoneNumber) {
        this.phoneNumber = phoneNumber;
    }

    public String toString() {
        return getClass().getName() + &quot;#&quot; + Integer.toHexString(hashCode());
    }
}

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;536&quot; data-origin-height=&quot;94&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kxmg8/dJMcagEoRve/mIpA2eHeMnU98t5pezmhQ1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kxmg8/dJMcagEoRve/mIpA2eHeMnU98t5pezmhQ1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kxmg8/dJMcagEoRve/mIpA2eHeMnU98t5pezmhQ1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fkxmg8%2FdJMcagEoRve%2FmIpA2eHeMnU98t5pezmhQ1%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;536&quot; height=&quot;94&quot; data-origin-width=&quot;536&quot; data-origin-height=&quot;94&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;@ &amp;rarr; # 으로 바뀐 걸 확인할 수 있습니다
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;왜냐하면 Person 클래스에서 Object 클래스에 의해 제공되는 적용을 덮어씌운 것이기 때문&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;상속의 작동 순서&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt; 하위 클래스에서 생성자를 만들 때마다 첫번째 줄에서는 자동으로 상위 생성자가 발동  &lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;import java.math.BigDecimal;

public class EmployeeRunner {
    public static void main(String[] args) {
        Employee employee = new Employee();
        //상속 설정
        employee.setEmail(&quot;guswnsj0112@naver.com&quot;);
        employee.setPhoneNumber(&quot;013-38929890230&quot;);

        //하위 클래스
        employee.setEmploy(&quot;jonny&quot;);
        employee.setEmployeeGrade(&quot;A&quot;);
        employee.setTitle(&quot;FAANG!!&quot;);

        System.out.println(employee);
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;scala&quot;&gt;&lt;code&gt;public class Employee extends Person{
    private String title;
    private String employ;
    private String employeeGrade;
    private BigDecimal salary;

    public Employee() {
		    //super() 함축적으로 포함됨
        System.out.println(&quot;Employee Constructor&quot;);
    }
   
   //중략
}

&lt;/code&gt;&lt;/pre&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;Employee 생성자를 호출 &amp;rarr; Employee 생성자를 부름&lt;/li&gt;
&lt;li&gt;Employee 생성자는 함축적으로 super를 호출하게 됨&lt;/li&gt;
&lt;li&gt;자바컴파일러는 자동으로 상위 클래스인 Person을 호출&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1732&quot; data-origin-height=&quot;158&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/EY35T/dJMcacvd82O/zFjw5alj1SlrFwykppLDg1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/EY35T/dJMcacvd82O/zFjw5alj1SlrFwykppLDg1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/EY35T/dJMcacvd82O/zFjw5alj1SlrFwykppLDg1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FEY35T%2FdJMcacvd82O%2FzFjw5alj1SlrFwykppLDg1%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;1732&quot; height=&quot;158&quot; data-origin-width=&quot;1732&quot; data-origin-height=&quot;158&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;상위 클래스에 데이터 넘겨주기&lt;/h4&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;public Person(String name) {
        System.out.println(&quot;Person Constructor&quot;);
        this.name = name;
 }&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;만약 상위 클래스에 이름이 필요하다고 생성자에 적는다면 하위 클래스에서도 당연히 이름이 필요할 것입니다
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이는 간단히 super안에 인수를 넣어줌으로써 해결 가능합니다&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;public Employee(String name, String title) {
        super(name);
        System.out.println(&quot;Employee Constructor&quot;);
        this.title = title;
    }
&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;ebnf&quot;&gt;&lt;code&gt;Employee employee = new Employee(&quot;Ranga&quot;, &quot;Programmer Analyst&quot;);
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;상속을 확인하는 instanceof&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;instanceof는 다형성 설계가 잘못됐을 때의 냄새(code smell) 일 수 있다&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;570&quot; data-origin-height=&quot;86&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/BsCCh/dJMcah4mjrW/tYv9jok58HBkWtizASwz60/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/BsCCh/dJMcah4mjrW/tYv9jok58HBkWtizASwz60/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/BsCCh/dJMcah4mjrW/tYv9jok58HBkWtizASwz60/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FBsCCh%2FdJMcah4mjrW%2FtYv9jok58HBkWtizASwz60%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;86&quot; data-origin-width=&quot;570&quot; data-origin-height=&quot;86&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이렇게 boolean 값으로 반환 됩니다&lt;/li&gt;
&lt;li&gt;현재 객체가 특정 클래스의 인스턴스인지 알 수 있게 해줍니디&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Back-end/Java</category>
      <category>Java</category>
      <category>Til</category>
      <category>ToString</category>
      <category>메소드오버라이딩</category>
      <category>자바 객체</category>
      <author>dev_Hyeonjoon</author>
      <guid isPermaLink="true">https://joon0112.tistory.com/66</guid>
      <comments>https://joon0112.tistory.com/66#entry66comment</comments>
      <pubDate>Tue, 3 Feb 2026 20:43:11 +0900</pubDate>
    </item>
    <item>
      <title>[TIL] JAVA 배열에 관해서</title>
      <link>https://joon0112.tistory.com/65</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;배열이 필요한 이유&lt;/h2&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;int mark1 = 100;
int mark2 = 75;
int mark3 = 60;
int sum = mark1 + mark2 + mark3;&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;만약 위에 있는 코드처럼 과목 점수를 일일이 적는다면 매우 귀찮을 것입니다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;심지어 과목이 추가 된다면 또 다시 변수를 선언하고 sum변수를 수정해야한다는 단점이 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rarr; 이 경우 배열을 사용한다면 매우 편해질 것 입니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;배열에 관해서&lt;/h1&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;배열은 같은 타입의 여러 값을 저장할 수 있습니다.&lt;br /&gt; 배열을 통해 같은 타입의 요소들을 묶을 수 있다 !  &lt;/p&gt;
&lt;/blockquote&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;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;int [] marks = {75, 60, 56};
//세 가지 요소를 가지는 배열 마크를 생성했음 
&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;세 가지의 숫자를 한 번에 저장할 수 있게 됩니다.&lt;/li&gt;
&lt;li&gt;이 배열은 점수 배열이며 대괄호 뒤로 마크 값이 들어오게 됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;배열 반복문&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;배열을 정의하고 그 안에 요소를 구성했다면 구성 요소를 차례대로 반복할 수 있는 반복문을 설정할 수 있습니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;향상된 for 문 (Enhanced For Loop)&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; for-each&lt;/b&gt;라고도 불리우는&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;public class Main {
    public static void main(String[] args) {
        int [] marks = { 75, 60, 65} ;
        int sum = 0;
        for (int mark:marks){
            sum = sum + mark;
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;mark는 &lt;b&gt;배열 요소를 하나씩 복사한 지역 변수&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;mark 값을 바꿔도 marks 배열 자체는 바뀌지 않음 ❗&lt;/li&gt;
&lt;li&gt;이 코드가 편한 이유 중 하나는 구성 요소가 얼마나 있는지 상관없이 코드를 사용할 수 있기 때문입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;배열 선언&lt;/h2&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;int [] 배열이름 = new int[요소 개수];

int [] mark = new int[5];&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rarr; 5개의 값을 가지는 정수 배열을 선언&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 data-ke-size=&quot;size16&quot;&gt;⚠️배열의 값을 설정하지 않으면 정수일 때 디폴트 값은 항상 0&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;❗int[] marks = new int[];&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;와 같이 배열의 규모를 알 수 없는 코드를 작성 시 오류를 일으킨다&lt;/li&gt;
&lt;li&gt;배열 사이즈는 항상 오른쪽에 작성해야 함 !&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;❗배열은 항상 명시된 타입만 가질 수 있다&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;int를 작성해 놓고 float라고 적을 시 오류를 일으킴&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;배열 간단하게 적는 방법&lt;/h3&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;int[] marks = {97, 98, 100};
Student student = new Student(&quot;Ranga&quot;, marks);&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;지금까지 써왔던 이런 방식 말고 더 간단하게 줄이고 싶다면 아래와 같이 적으면 됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;Student student = new Student(&quot;Ranga&quot;, new int[] {97,98,100});&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;좋긴 한데 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;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;배열 값 추출하기&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;배열의 인덱스를 사용&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;❗배열의 인덱스는 항상 0으로 시작&lt;/p&gt;
&lt;pre class=&quot;css&quot;&gt;&lt;code&gt;배열[인덱스번호]

mark[0]
&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;mark 배열의 인덱스 0인 값을 추출&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;배열 값 변경하기&lt;/h3&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;배열[인덱스번호] = 변경할값
amrk[0] = 10;
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;배열 길이&lt;/h2&gt;
&lt;pre class=&quot;applescript&quot;&gt;&lt;code&gt;배열.length
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;배열 초기값&lt;/h2&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;int[] marks = new int[5];
double[] values = new double[5];
boolean[] test = new boolean[5];
&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;모든 정수 타입의 배열은 초기 값 0&lt;/li&gt;
&lt;li&gt;모든 double타입의 초기 값 0.0&lt;/li&gt;
&lt;li&gt;모든 boolean타입의 초기 값 false&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;객체 요소로 하는 배열&lt;/h2&gt;
&lt;pre class=&quot;inform7&quot;&gt;&lt;code&gt;class Person {}
Person[] person = new Person[5]
&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;객체 배열을 만들 경우 초기 값 null&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;배열 전체를 출력하는 법&lt;/h2&gt;
&lt;pre class=&quot;css&quot;&gt;&lt;code&gt;System.out.println(배열);
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;⚠️배열의 요소가 아닌 저장 경로가 출력 됩니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;저희가 원하는 건 요소이기 때문에 다른 방법을 사용해서 출력해야 합니다&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;정적 메소드를 사용하여 출력하기&lt;/h3&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;System.out.println(Arrays.toString(배열));
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;배열 초기 값 설정하기&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정적 메소드를 사용&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;Arrays.fill(배열,초기값)
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;배열이 값이 동등한지&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정적 메소드를 사용&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;Arrays.equals(배열1, 배열2);
&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;boolean 값으로 출력됩니다.&lt;/li&gt;
&lt;li&gt;배열의 길이가 다르거나 매칭되는 요소가 없을 때 false&lt;/li&gt;
&lt;li&gt;길이가 같고 AND 각 요소가 모두 매칭될 때 true&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;배열 정렬하기&lt;/h2&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;Arrays.sort(배열);
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;가변 매개 변수&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;가변 매개 변수가 필요한 이유&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;가변 매개 변수는 아래와 같이 얼마나 인수가 들어올지 모르기 때문에 사용됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;lsl&quot;&gt;&lt;code&gt;Student student = new Student(&quot;Ranga&quot;, 97,98,100);
Student student1 = new Student(&quot;Adam&quot;, 97,98);
Student student2 = new Student(&quot;Eve&quot;, 97,98,90,98);
&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;정해진 매개 변수 없이 사용자의 입력을 받고 싶다면?&lt;/li&gt;
&lt;li&gt;&amp;rArr; 가변 매개 변수 사용&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;가변 매개 변수 사용법&lt;/h3&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;public class Student {
    private String name;
    private int[] marks; //배열 유지해도 상관없다

    public Student (String name, int... marks){
        this.name = name;
        this.marks = marks;
    } 
  }
&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;가변적 매개변수는 매개변수 앞 &amp;hellip;만 붙여주면 됩니다&lt;/b&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;a href=&quot;https://velog.io/@enamu/배열Array과-리스트List#:~:text=배열과&quot;&gt;https://velog.io/@enamu/배열Array과-리스트List#:~:text=배열과&lt;/a&gt;&lt;a href=&quot;https://velog.io/@enamu/%EB%B0%B0%EC%97%B4Array%EA%B3%BC-%EB%A6%AC%EC%8A%A4%ED%8A%B8List#:~:text=%EB%B0%B0%EC%97%B4%EA%B3%BC%20%EB%A6%AC%EC%8A%A4%ED%8A%B8%EC%9D%98%20%EC%B0%A8%EC%9D%B4%EC%A0%90,-%EB%A9%94%EB%AA%A8%EB%A6%AC%20%ED%95%A0%EB%8B%B9:%20%EB%B0%B0%EC%97%B4&amp;amp;text=%ED%81%AC%EA%B8%B0:%20%EB%B0%B0%EC%97%B4%EC%9D%80%20%ED%81%AC%EA%B8%B0%EA%B0%80,%EC%82%BD%EC%9E%85%EA%B3%BC%20%EC%82%AD%EC%A0%9C%EA%B0%80%20%EB%B9%A0%EB%A5%B4%EB%8B%A4.)&quot;&gt; 리스트의 차이점,-메모리 할당: 배열&amp;amp;text=크기: 배열은 크기가,삽입과 삭제가 빠르다.)&lt;/a&gt;&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;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;void print (int... value, String name){} //에러
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;배열 추가 및 삭제&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;  ArrayList를 사용하지 않는 방법은 다소 까다로울 수 있습니다  &lt;/blockquote&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;배열 추가&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;배열이 한번 생성되고 나면 사이즈가 크기가 정해지기 때문에 기존 배열에서 추가될 수 없습니다&lt;/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;이런식으로 배열의 사이즈를 늘린 후 요소 자리에 위에 있는 값을 복사해 오고 배열의 마지막 값만 넣어주면 됩니다
&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;/ul&gt;
&lt;/li&gt;
&lt;li&gt;int[] marks = {12,34, 45}; int [] newMarks = new int[marks.length + 1];&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;배열 삭제&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;배열 추가하는 방법과 마찬가지로 크기를 수정해줘야 합니다&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;haxe&quot;&gt;&lt;code&gt;int [] newMarksWithOneDeleted = new int[marks.length - 1];
&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이렇게 한 후 똑같이 배열 요소를 넣어주면 끝&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;ArrayList를 활용해 더 쉽게 추가 및 삭제하기&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ArrayList : 배열을 추가, 삭제하기 편해지는 컬렉션 프레임워크&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;ArrayList arrayList = new ArrayList();
arrayList.add(&quot;Apple&quot;);
arrayList.add(&quot;Cat&quot;);
System.out.println(arrayList);

arrayList.remove(&quot;Cat&quot;);
System.out.println(arrayList);
&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;추가 및 삭제가 매우 간편해짐&lt;/li&gt;
&lt;li&gt;그리고 원본 배열을 수정할 수 있다는 장점이 있습니다.&lt;/li&gt;
&lt;li&gt;하지만 위에 있는 코드에서는 타입을 설정하지 않았기 때문에 문자와 숫자가 섞여버릴 수 도 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;ArrayList arrayList = new ArrayList();
arrayList.add(&quot;Apple&quot;);
arrayList.add(1);
System.out.println(arrayList);
//에러 x
&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;따라서 타입을 명시해주는게 좋습니다.
&lt;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;/ul&gt;
&lt;pre class=&quot;haxe&quot;&gt;&lt;code&gt;ArrayList&amp;lt;String&amp;gt; items = new ArrayList&amp;lt;String&amp;gt;();

// Java 7 이상부터는 다이아몬드 연산자 사용 가능
ArrayList&amp;lt;String&amp;gt; items = new ArrayList&amp;lt;&amp;gt;();
&lt;/code&gt;&lt;/pre&gt;</description>
      <category>Back-end/Java</category>
      <category>ArrayList</category>
      <category>Java</category>
      <category>Til</category>
      <category>배열공부</category>
      <category>자바</category>
      <author>dev_Hyeonjoon</author>
      <guid isPermaLink="true">https://joon0112.tistory.com/65</guid>
      <comments>https://joon0112.tistory.com/65#entry65comment</comments>
      <pubDate>Fri, 30 Jan 2026 09:52:53 +0900</pubDate>
    </item>
    <item>
      <title>[TIL] Wrapper클래스</title>
      <link>https://joon0112.tistory.com/64</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h1&gt;Wrapper클래스&lt;/h1&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;값들을 싸고 있는 것과 같다고 하여 Wrapper Class 라고 부릅니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본타입(primitive type) 래퍼클래스(wrapper class)&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;byte&lt;/td&gt;
&lt;td&gt;Byte&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;char&lt;/td&gt;
&lt;td&gt;Character&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;int&lt;/td&gt;
&lt;td&gt;Integer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;float&lt;/td&gt;
&lt;td&gt;Float&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;double&lt;/td&gt;
&lt;td&gt;Double&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;boolean&lt;/td&gt;
&lt;td&gt;Boolean&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;long&lt;/td&gt;
&lt;td&gt;Long&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;short&lt;/td&gt;
&lt;td&gt;Short&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;char, int의 래퍼 클래스는 각각 Integer와 Character이고 나머지는 대문자로 시작된다는 점 외 이름은 동일&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Wrapper 클래스가 필요한 이유&lt;/h2&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;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&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;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;Integer hundred = Integer.valueOf(&quot;100&quot;);
Boolean value = Boolean.valueOf(&quot;True&quot;);

//valueOf = 객체를 &amp;ldquo;클래스에 따라 변환&amp;rdquo;하는 데 사용되는 함수입니다
&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;스트링에서 boolean 값 또는 integer 값을 출력할 경우 래퍼 클래스를 이용해 실행할 수 있습니다&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;float가 있고 이 특정 float의 정숫값을 출력하려고 할 때 intValue 메서드를 사용할 수 있습니다&lt;/li&gt;
&lt;li&gt;추가로, 만약 2진법으로 이루어진 스트링을 전환하고 싶을 때,
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;다시, 2진법 형태의 스트링이 정수를 나타내도록 전환시키고 싶은 경우, 래퍼 클래스에는 이런 것들을 실행할 수 있는 많은 유틸리티 메소드가 있다&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;/ul&gt;
&lt;/li&gt;
&lt;li&gt;//Conversion Float floatWrapper = Float.valueOf(57.0f); int floatToInt = floatWrapper.intValue(); // 57 Integer seven = Integer.valueOf(&quot;111&quot;, 2); Integer.toString(seven,2);&lt;/li&gt;
&lt;/ol&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;래퍼 클래스의 생성자로 정수 생성하기&lt;/h2&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;Integer integer = new Integer(5);
Integer integer1 = new Integer(5);

//Integer(int) 생성자는 Java 9부터 deprecated 되었으며, 사용이 권장되지 않는다.
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;래퍼 클래스의 정적 메서드로 정수 생성하기&lt;/h2&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;Integer integer = Integer.valueOf(5);
Integer integer1 = Integer.valueOf(5);
&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;각각의 래퍼 클래스는 모두 정적 메소드를 갖고 있는데&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;gams&quot;&gt;&lt;code&gt;Integer integer = Integer.valueOf(&quot;54654&quot;);
&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이런식으로 값으로 스트링을 넣을 수 있습니다&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;둘 중 어떤 것이 좋을까?&lt;/h2&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;Integer i1 = new Integer(5);
Integer i2 = new Integer(5);
Integer i3 = Integer.valueOf(5);
Integer i4 = Integer.valueOf(5);

i1== i2
//false ❗ (캐시 범위 밖)

i3 == i4 // true ✅ (캐시 범위 안)

//Integer.valueOf()는 -128~127 범위의 값에 대해 동일한 객체를 재사용하므로, 이 범위 내에서는 == 비교 시 true가 나올 수 있다.
&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;integer 참조 타입&lt;/li&gt;
&lt;li&gt;i1 참조하는 값&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;스트링 클래스와 동일하게 모든 래퍼 클래스 또한 불변성을 갖습니다
&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;여기 보면 i1에 대해 새로운 정수 변수가 생성되었고, i2에 대해 또 다른 정수 변수가 생성이 됐는데 값은 같은 숫자를 가지고 있는 것&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Integer.valueOf()의 기능은 존재하는 객체 중 같은 값을 가지는 게 있는지 체크한 후 있다면 재사용합니다.&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;만약 다른 객체에서 동일한 값을 찾는다면, 그 값을 다시 사용하고 동일한 결과를 출력&lt;/li&gt;
&lt;li&gt;해당 객체의 값이 변하는 것이 아니기 때문에 괜찮다&lt;/li&gt;
&lt;li&gt;정수 &amp;rarr; 불변성 따라서 괜찮&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;그렇기 때문에 두 개의 다른 참조 값이 하나의 객체를 가리키고 있다고 해도 전혀 문제가 되지 않습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;추천 방식&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Integer.valueOf() 또는 valueOf()를 사용해서 어떤 래퍼든 메서드를 생성하고 객체가 생성되어 있다면 매번 새로운 객체를 생성하지 않아도 되게 다시 활용할 수 있게 하는 것이 좋습니다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;만약 new를 사용한다면 새로운 객체를 매번 사용하고 있는 걸 의미하는데&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;Integer.valueOf()는 그런 방식x&lt;/li&gt;
&lt;li&gt;이 메서드는 Heap 안에 존재하는 기존 객체를 다시 사용하려고 할 것입니다. (정수에도 동일하게 적용)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;float, Double, String을 값을 받을 수 있습니다&lt;/li&gt;
&lt;li&gt;이 모든 생성자를 이용할 수 있고 글자 생성자를 이용할 수 있습니다&lt;/li&gt;
&lt;li&gt;나아가 boolean과 스트링을 입력할 수 있습니다&lt;/li&gt;
&lt;/ul&gt;
Boolean
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;boolean 생성자도 이용가능&lt;/li&gt;
&lt;li&gt;문자열이 &quot;true&quot;(대소문자 무관)일 때만 true, 그 외 모든 값은 false&lt;/li&gt;
&lt;li&gt;이걸 통해 값을 출력할 수도 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Boolean b1 = new Boolean(&quot;true&quot;); // true Boolean b2 = new Boolean(&quot;True&quot;); // true Boolean b3 = new Boolean(&quot;False&quot;); // false Boolean b4 = new Boolean(&quot;SomeString&quot;); // false&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Back-end/Java</category>
      <author>dev_Hyeonjoon</author>
      <guid isPermaLink="true">https://joon0112.tistory.com/64</guid>
      <comments>https://joon0112.tistory.com/64#entry64comment</comments>
      <pubDate>Wed, 28 Jan 2026 22:51:29 +0900</pubDate>
    </item>
    <item>
      <title>[TIL] String 클래스</title>
      <link>https://joon0112.tistory.com/63</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;스트링이라고 불리는 클래스 인스턴스&lt;/h2&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;&quot;test&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;여기서 test는 인스턴스입니다. 그렇다면 어떤 클래스의 인스턴스일까요
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;자바에서 글씨는 모두 &lt;b&gt;String Class&lt;/b&gt;에 의해 출력됩니다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이 때 큰 따옴표(&amp;rdquo;&amp;rdquo;)와 함께 사용됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;만약 저장을 하고 싶다면&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;String str = &quot;test&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;와 같이 사용할 수 있습니다.&lt;/li&gt;
&lt;li&gt;&amp;rarr; test에 대한 인스턴스를 생성하고 래퍼런스를 str에 저장&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;String 리터럴은 Heap 영역 내부의 String Constant Pool에 저장된다. 같은 문자열 리터럴은 하나의 객체를 공유한다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;String a = &quot;test&quot;;
String b = &quot;test&quot;;

a == b // true&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;String a = new String(&quot;test&quot;);
String b = new String(&quot;test&quot;);

a == b // false
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;스트링 인스턴스가 특별한 이유&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;BigDecimal bd = new BigDecimal(&quot;1.0&quot;) 이와 같이 다른 객체들은 &lt;b&gt;생성자(constructor)&lt;/b&gt;가 있어야 만들 수 있었습니다&lt;/li&gt;
&lt;li&gt;그러나 str은 생성자가 없어도 만들 수 있고 생성자를 사용해 만들 수도 있다&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;생성자로 스트링 만드는법&lt;/h4&gt;
&lt;pre class=&quot;processing&quot;&gt;&lt;code&gt;String str = new String(&quot;Test&quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;우리는 test를 &lt;b&gt;스트링 리터럴&lt;/b&gt; 이라고 부릅니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;스트링의 인덱스&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;⚠️스트링은 무조건 0부터 시작합니다!&lt;/b&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;charAt (한 문자 자르기)&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;charAt&lt;/b&gt;을 사용&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;processing&quot;&gt;&lt;code&gt;String str = &quot;Test&quot;
str.charAt(0) // T
str.charAt(2) // s
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;substring (여러 문자 잘라내기)&lt;/h3&gt;
&lt;pre class=&quot;armasm&quot;&gt;&lt;code&gt;String biggerString = &quot;This is a lot of text&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;서브 스트링
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;문자열에서 특정 부분을 잘라내어 새로운 문자열을 생성하는 메서드&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;서브 스트링 메서드는 이 문자의 인덱스를 받는다&lt;/li&gt;
&lt;li&gt;해야될 것은 문자의 인덱스 번호를 넣으면 된다&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;biggerString.substring(5)
// &quot;is a lot of text&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;시작과 끝도 설정하기&lt;/h3&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;biggerString.substring(5, 13)
// &quot;is a lot&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;중요한 건 시작은 포함이고 끝은 포함하지 않는다는 것
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;즉, 범위는 5 ~ 12까지&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;lastIndexOf (마지막에 있는 단어 찾기)&lt;/h4&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;string.lastIndexOf('i');
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;contains (글자가 있는지 확인하기)&lt;/h4&gt;
&lt;pre class=&quot;applescript&quot;&gt;&lt;code&gt;string.contains(&quot;text&quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;text 라는 단어가 존재하는지 찾고자 할 때 &amp;lsquo;text&amp;rsquo;를 값으로 입력하면 된다&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;startWith (특정 단어로 시작하는지 확인하기)&lt;/h4&gt;
&lt;pre class=&quot;autoit&quot;&gt;&lt;code&gt;string.startsWith(&quot;This&quot;)

// true or false
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;endsWith (특정 단어로 끝나는지 확인하기)&lt;/h4&gt;
&lt;pre class=&quot;autoit&quot;&gt;&lt;code&gt;string.endsWith(&quot;text&quot;)

// true or false
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;isEmpty (비어 있는지 확인하기)&lt;/h4&gt;
&lt;pre class=&quot;yaml&quot;&gt;&lt;code&gt;string.isEmpty()

// true or false
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;equals(글자가 똑같은지 확인하기)&lt;/h4&gt;
&lt;pre class=&quot;cs&quot;&gt;&lt;code&gt;&quot;true&quot;.equals(&quot;true&quot;)

// true
&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;대소문자가 다르게 인식됨&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;equalsIgnoreCase (대소문자 상관없이 글자가 똑같은지 확인하기)&lt;/h4&gt;
&lt;pre class=&quot;jboss-cli&quot;&gt;&lt;code&gt;&quot;true&quot;.equalsIgnoreCase(&quot;TRUE&quot;) // true

// true
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;스트링 수정&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;스트링은 불변의 객체로 값을 수정할 수 없습니다&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;338&quot; data-origin-height=&quot;146&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bIbTQx/dJMcabXj8MK/uQdqRs4vpxfX89Mv61pZTK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bIbTQx/dJMcabXj8MK/uQdqRs4vpxfX89Mv61pZTK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bIbTQx/dJMcabXj8MK/uQdqRs4vpxfX89Mv61pZTK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbIbTQx%2FdJMcabXj8MK%2FuQdqRs4vpxfX89Mv61pZTK%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;338&quot; height=&quot;146&quot; data-origin-width=&quot;338&quot; data-origin-height=&quot;146&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;사진과 같이 문자를 합쳤음에도 str에서는 반영되지 않았습니다&lt;/li&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-origin-width=&quot;446&quot; data-origin-height=&quot;93&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bw2J0X/dJMcaaxmmSj/5zRTXuKn5HsVwCeNCGoPHK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bw2J0X/dJMcaaxmmSj/5zRTXuKn5HsVwCeNCGoPHK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bw2J0X/dJMcaaxmmSj/5zRTXuKn5HsVwCeNCGoPHK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbw2J0X%2FdJMcaaxmmSj%2F5zRTXuKn5HsVwCeNCGoPHK%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;446&quot; height=&quot;93&quot; data-origin-width=&quot;446&quot; data-origin-height=&quot;93&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이런식으로 변수가 달라져야 저장
&lt;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;string.concat을 사용하면 새로운 스트링이 만들어지며 원래의 스트링은 영향을 받지 않고 그대로 남아 있게 됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&amp;rArr; 이런 스트링의 특징을 &lt;b&gt;불변성&lt;/b&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;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;toUpperCase (대문자로)&lt;/h3&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;string.toUpperCase()
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;toLowerCase (소문자로)&lt;/h3&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;string.toLowerCase()
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;trim (앞 뒤 간격 제거)&lt;/h3&gt;
&lt;pre class=&quot;mel&quot;&gt;&lt;code&gt;string.trim()
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;스트링과 숫자&lt;/h2&gt;
&lt;pre class=&quot;basic&quot;&gt;&lt;code&gt;1 + 2 // 3
&quot;1&quot; + &quot;2&quot; //&quot;12&quot;
&quot;1&quot; + 2 // &quot;12&quot;
&quot;1&quot; + 23 // &quot;123&quot;

1 + 2+ &quot;3&quot; // &quot;33&quot;
&quot;1&quot; + 2 + 3 // &quot;123&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이런 결과가 나오는 이유는 자바는 &lt;b&gt;문자열 + 숫자는 = 문자열&lt;/b&gt;이 됩니다&lt;/li&gt;
&lt;li&gt;1 + 2+ &amp;ldquo;3&amp;rdquo; 과 &amp;ldquo;1&amp;rdquo; + 2 + 3의 차이점은 자바는 왼 &amp;rarr; 오 으로 해석하기 때문
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;1+2 = 3 이 되고 3 + &amp;ldquo;3&amp;rdquo; = &amp;ldquo;33&amp;rdquo;이 된다&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;예제&lt;/h3&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;Sytem.out.println(&quot;Value is &quot; + 20)
Sytem.out.println(&quot;Value is &quot; + 20 + 20)
Sytem.out.println(&quot;Value is &quot; + (20+20))
&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;// Value is 20
// Value is 2020
// Value is 40
&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;괄호가 가장 먼저 연산되기 때문에 마지막은 40이 된다&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;join (문자 합치기)&lt;/h4&gt;
&lt;pre class=&quot;lasso&quot;&gt;&lt;code&gt;String.join(&quot;,&quot;, &quot;2&quot;, &quot;3&quot;, &quot;4&quot;)

// &quot;2,3,4&quot;

String.join(&quot;,&quot;, &quot;A&quot;, &quot;B&quot;, &quot;4&quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;첫 번째 문자는 어떤 문자를 합칠 것인지, 그리고 나머지는 뒤로 덧붙이고 싶은 숫자들이나 문자들&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;replace (문자열 대체하기)&lt;/h4&gt;
&lt;pre class=&quot;1c&quot;&gt;&lt;code&gt;&quot;abcd&quot;.replace('a', 'z');

//zbcd
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;String 대체&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;StringBuffer&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;/ul&gt;
&lt;pre class=&quot;dart&quot;&gt;&lt;code&gt;StringBuffer sb = new StringBuffer(&quot;TEst&quot;);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;435&quot; data-origin-height=&quot;156&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/2nrYM/dJMcagK7mGw/5fkxSyPzyho6Gt1eNFPw5k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/2nrYM/dJMcagK7mGw/5fkxSyPzyho6Gt1eNFPw5k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/2nrYM/dJMcagK7mGw/5fkxSyPzyho6Gt1eNFPw5k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F2nrYM%2FdJMcagK7mGw%2F5fkxSyPzyho6Gt1eNFPw5k%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;435&quot; height=&quot;156&quot; data-origin-width=&quot;435&quot; data-origin-height=&quot;156&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;수정이 되고 결합이 많은 경우 String보단 StringBuffer가 더 유용&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;StringBuilder&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;StringBuffer와 유사하지만 동기화를 제공하지 않아 단일 스레드 환경에서 더 빠르다.&lt;/p&gt;
&lt;/blockquote&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;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;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Back-end/Java</category>
      <category>Java</category>
      <category>string</category>
      <category>StringBuffer</category>
      <category>stringbuilder</category>
      <category>Til</category>
      <author>dev_Hyeonjoon</author>
      <guid isPermaLink="true">https://joon0112.tistory.com/63</guid>
      <comments>https://joon0112.tistory.com/63#entry63comment</comments>
      <pubDate>Wed, 28 Jan 2026 22:02:33 +0900</pubDate>
    </item>
    <item>
      <title>[TIL]자바 프로그래밍의 참조 자료형</title>
      <link>https://joon0112.tistory.com/62</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;참조 타입이란&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자바에서 class로 정의된 타입과 배열 타입은 모두 참조 타입이며, new 연산자를 통해 생성된 객체는 Heap 영역에 저장된다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;참조 변수&lt;/h3&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;class Planet {
}
Planet jupiter = new Planet();&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;위에서 본 것 처럼 Planet이라는 인스턴스를 사용해 jupiter에 저장할 때 jupiter는 참조변수가 됩니다&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;참조 변수 메모리의 저장방식&lt;/h4&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;class Animal {
	int id;
	Animal(int id) {
		this.id = id;
	}
}

Animal dog = new Animal(12);
Animal cat = new Animal(15);&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;새로운 객체가 생성될 때마다 이들은 모두 Heap이라고 하는 곳에 저장됩니다&lt;/li&gt;
&lt;li&gt;자바 프로그램이 실행될 때 두 가지 종류의 메모리가 있는데 그 중 하나는 &amp;lsquo;Stack&amp;rsquo;이고 다른 하나는 &amp;lsquo;Heap&amp;rsquo;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;모든 새로운 객체는 Heap에 저장되는데, 이것은 자바 프로그램에서 공유되는 가장 기본적인 저장소&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;즉, 모든 객체는 heap에 저장&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Heap도 여러개의 저장소로 나눠짐&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&amp;rarr; Animal(12)는 이곳에 저장됨&lt;/li&gt;
&lt;li&gt;기본 변수, 메소드에 로컬 변수를 생성하면 Stack에 저장&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;514&quot; data-origin-height=&quot;253&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/6gCUt/dJMcaioBPWp/oHcW5jrnq6CtIHrCczNjw0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/6gCUt/dJMcaioBPWp/oHcW5jrnq6CtIHrCczNjw0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/6gCUt/dJMcaioBPWp/oHcW5jrnq6CtIHrCczNjw0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F6gCUt%2FdJMcaioBPWp%2FoHcW5jrnq6CtIHrCczNjw0%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;514&quot; height=&quot;253&quot; data-origin-width=&quot;514&quot; data-origin-height=&quot;253&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;dog는 Animal12라는 값을 갖고 있는데 Animal12는 Heap에서 1A에 위치 따라서 Stack에서는 value에 1A를 갖게 되는 것&lt;/li&gt;
&lt;li&gt;그래서 이처럼 &amp;lsquo;dog&amp;rsquo;에 대한 값은 객체가 저장된 경로의 참조 정보로 Stack에 저장되는 것&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;Dog는 1A라고 하는 참조 경로를 가지고 있기 때문에 참조 변수라고 부르는 것&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;621&quot; data-origin-height=&quot;280&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ekTLnz/dJMcagqMNqt/LKgpxuymlQHi1QhmMvok11/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ekTLnz/dJMcagqMNqt/LKgpxuymlQHi1QhmMvok11/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ekTLnz/dJMcagqMNqt/LKgpxuymlQHi1QhmMvok11/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FekTLnz%2FdJMcagqMNqt%2FLKgpxuymlQHi1QhmMvok11%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;621&quot; height=&quot;280&quot; data-origin-width=&quot;621&quot; data-origin-height=&quot;280&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;cat도 마찬가지&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;만약 null이라면&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;227&quot; data-origin-height=&quot;37&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bpctUl/dJMb99Zwu5W/SjCevZZa8KSpJD6sSwA30k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bpctUl/dJMb99Zwu5W/SjCevZZa8KSpJD6sSwA30k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bpctUl/dJMb99Zwu5W/SjCevZZa8KSpJD6sSwA30k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbpctUl%2FdJMb99Zwu5W%2FSjCevZZa8KSpJD6sSwA30k%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;227&quot; height=&quot;37&quot; data-origin-width=&quot;227&quot; data-origin-height=&quot;37&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;아무것도 생성한 것이 없기 때문에 값은 null이 됩니다.
&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;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;553&quot; data-origin-height=&quot;311&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b6ssci/dJMcabwfqNG/BCeQp5OwNba1YZYsKkpI60/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b6ssci/dJMcabwfqNG/BCeQp5OwNba1YZYsKkpI60/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b6ssci/dJMcabwfqNG/BCeQp5OwNba1YZYsKkpI60/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb6ssci%2FdJMcabwfqNG%2FBCeQp5OwNba1YZYsKkpI60%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;553&quot; height=&quot;311&quot; data-origin-width=&quot;553&quot; data-origin-height=&quot;311&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;엑셀에서 이와 같이 표현할 수 있습니다&lt;/li&gt;
&lt;li&gt;null은 참조 타입 변수이지만, &lt;b&gt;어떤 객체도 참조하지 않는 상태&lt;/b&gt; 를 의미&lt;/li&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-origin-width=&quot;222&quot; data-origin-height=&quot;40&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/tZT6a/dJMcac2XHsO/KHfUN5Cr6Ygg2kuaEAASS1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/tZT6a/dJMcac2XHsO/KHfUN5Cr6Ygg2kuaEAASS1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/tZT6a/dJMcac2XHsO/KHfUN5Cr6Ygg2kuaEAASS1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FtZT6a%2FdJMcac2XHsO%2FKHfUN5Cr6Ygg2kuaEAASS1%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;222&quot; height=&quot;40&quot; data-origin-width=&quot;222&quot; data-origin-height=&quot;40&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;=&amp;gt; 이와 같이 입력한다면 1c로 연결&lt;/p&gt;
&lt;p style=&quot;text-align: center;&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;516&quot; data-origin-height=&quot;256&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ADUFm/dJMcacaS2Hl/b6KbH4UEacusvkdKnbPXW0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ADUFm/dJMcacaS2Hl/b6KbH4UEacusvkdKnbPXW0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ADUFm/dJMcacaS2Hl/b6KbH4UEacusvkdKnbPXW0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FADUFm%2FdJMcacaS2Hl%2Fb6KbH4UEacusvkdKnbPXW0%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;516&quot; height=&quot;256&quot; data-origin-width=&quot;516&quot; data-origin-height=&quot;256&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Quiz. 아래처럼 작성했을 때 결과값은&lt;span&gt;❓&lt;/span&gt; &lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;nothing.id = 10&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;cat.id&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rArr; 10&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;nothing &amp;rarr; 1C를 의미 &amp;rarr; 글로벌의 1C에 있는 객체의 값이 변경&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;510&quot; data-origin-height=&quot;221&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ciUetc/dJMcachCXiW/mJPKZf572zuil5oooE7eV0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ciUetc/dJMcachCXiW/mJPKZf572zuil5oooE7eV0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ciUetc/dJMcachCXiW/mJPKZf572zuil5oooE7eV0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FciUetc%2FdJMcachCXiW%2FmJPKZf572zuil5oooE7eV0%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;510&quot; height=&quot;221&quot; data-origin-width=&quot;510&quot; data-origin-height=&quot;221&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;마찬가지로 cat이라는 이름을 가진 변수도 같은 것을 의미하고 있기 때문에 값이 10으로 바뀌게 됩니다&lt;/li&gt;
&lt;li&gt;만약 nothing = dog라고 적는다면 1C의 값이 기존 1A가 있던 곳에 올 것&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;528&quot; data-origin-height=&quot;236&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/KUkcZ/dJMcab35f0C/RCQRRZIFe0gCcCMy0KOCBK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/KUkcZ/dJMcab35f0C/RCQRRZIFe0gCcCMy0KOCBK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/KUkcZ/dJMcab35f0C/RCQRRZIFe0gCcCMy0KOCBK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FKUkcZ%2FdJMcab35f0C%2FRCQRRZIFe0gCcCMy0KOCBK%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;528&quot; height=&quot;236&quot; data-origin-width=&quot;528&quot; data-origin-height=&quot;236&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;155&quot; data-origin-height=&quot;37&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/djLzs6/dJMcajntgDL/IJ2ERutxsLgExviZoil6j1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/djLzs6/dJMcajntgDL/IJ2ERutxsLgExviZoil6j1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/djLzs6/dJMcajntgDL/IJ2ERutxsLgExviZoil6j1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdjLzs6%2FdJMcajntgDL%2FIJ2ERutxsLgExviZoil6j1%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;155&quot; height=&quot;37&quot; data-origin-width=&quot;155&quot; data-origin-height=&quot;37&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;기본 변수와의 차이점&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;int j = i; 라고 한다면&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;498&quot; data-origin-height=&quot;253&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c2GKH1/dJMcacooPhu/Q5E2k9QKBkoSq0tD1zjSWk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c2GKH1/dJMcacooPhu/Q5E2k9QKBkoSq0tD1zjSWk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c2GKH1/dJMcacooPhu/Q5E2k9QKBkoSq0tD1zjSWk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc2GKH1%2FdJMcacooPhu%2FQ5E2k9QKBkoSq0tD1zjSWk%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;498&quot; height=&quot;253&quot; data-origin-width=&quot;498&quot; data-origin-height=&quot;253&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이렇게 독립적인 값을 갖습니다&lt;/li&gt;
&lt;li&gt;그리고 만약에 j의 값을 변경한다고 해도 변경되는 건 오직 j의 값&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;504&quot; data-origin-height=&quot;223&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cy6fzP/dJMcacooPhP/YsdXF5TPE7m8WnTDq3vh10/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cy6fzP/dJMcacooPhP/YsdXF5TPE7m8WnTDq3vh10/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cy6fzP/dJMcacooPhP/YsdXF5TPE7m8WnTDq3vh10/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcy6fzP%2FdJMcacooPhP%2FYsdXF5TPE7m8WnTDq3vh10%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;504&quot; height=&quot;223&quot; data-origin-width=&quot;504&quot; data-origin-height=&quot;223&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;하지만 참조 변수의 경우 저장하는 것이 값이 아닌 &lt;b&gt;경로이기 때문에&lt;/b&gt; 참조 변수를 복사할 때에는 실제 객체가 저장된 경로가 복사됩니다&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;504&quot; data-origin-height=&quot;235&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b0cEfM/dJMcadngDR1/fc4exIb1MSFlLjGdTJ37Dk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b0cEfM/dJMcadngDR1/fc4exIb1MSFlLjGdTJ37Dk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b0cEfM/dJMcadngDR1/fc4exIb1MSFlLjGdTJ37Dk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb0cEfM%2FdJMcadngDR1%2Ffc4exIb1MSFlLjGdTJ37Dk%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;504&quot; height=&quot;235&quot; data-origin-width=&quot;504&quot; data-origin-height=&quot;235&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이렇게 참조가 된다고 했을 때&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;cat == dog
//false

cat == ref
//true

dog == dog2
//false&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;출력 값이 false인 이유는 같은 값을 가지고 있지만, 그것과는 무관하게 &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;여기서 이 두 개가 나타내는 객체가 다르므로 dog와 dog2가 일치하지 않는다고 본다&lt;/li&gt;
&lt;li&gt;Heap에서 나타내는 객체가 다르다&lt;/li&gt;
&lt;li&gt;보면 12로 같은 값을 갖지만, Heap에 있는 저장 경로가 1A와 1E로 다르다&lt;/li&gt;
&lt;li&gt;Heap에는 다른 객체로 저장되어 있는 것&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;나타내는 객체가 다르다면 값이 같아도 같은걸로 인식하지 않는다&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;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Back-end/Java</category>
      <category>Java</category>
      <category>stack</category>
      <category>객체지향</category>
      <category>자바</category>
      <category>참조변수</category>
      <category>참조타입</category>
      <author>dev_Hyeonjoon</author>
      <guid isPermaLink="true">https://joon0112.tistory.com/62</guid>
      <comments>https://joon0112.tistory.com/62#entry62comment</comments>
      <pubDate>Wed, 28 Jan 2026 16:23:07 +0900</pubDate>
    </item>
    <item>
      <title>[전역 후] 그동안 내가 군 생활에서 이뤘던 것과 못 이뤘던 것들</title>
      <link>https://joon0112.tistory.com/61</link>
      <description>&lt;h2 style=&quot;text-align: left;&quot; data-ke-size=&quot;size26&quot;&gt;쉬어갑니다 종료.&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1019&quot; data-origin-height=&quot;726&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bgADfA/dJMcaaYj5kw/PEa5rxptWqnDKht5I19u51/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bgADfA/dJMcaaYj5kw/PEa5rxptWqnDKht5I19u51/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bgADfA/dJMcaaYj5kw/PEa5rxptWqnDKht5I19u51/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbgADfA%2FdJMcaaYj5kw%2FPEa5rxptWqnDKht5I19u51%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;494&quot; height=&quot;726&quot; data-origin-width=&quot;1019&quot; data-origin-height=&quot;726&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;2025년11월08일에 &lt;b&gt;잠시 쉬어갑니다....&lt;/b&gt;를 올린 후 엄청 일들을 처리하느라 제대로 공부도 못 하고 깃허브 잔디도 신경을 못 썼습니다. 하지만 막상 논건 아니고 그냥 꾸준히 다른 공부를 하며 지냈습니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;h2 style=&quot;text-align: left;&quot; data-ke-size=&quot;size26&quot;&gt;군 생활에 세웠던 목표  &lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;1. 개인 프로젝트 만들어서 배포&lt;br /&gt;2. 운동으로 체중 감량&lt;br /&gt;3. 창업 대회 나가기&lt;br /&gt;4. 토플 성적 90+ 이상&lt;br /&gt;5. 군e러닝 1,2학기 A+ 받기&lt;br /&gt;6. 해외파병 경험하기&lt;br /&gt;7. 특급전사 달성하기&lt;br /&gt;8. 컴활 1급 자격 따기&lt;br /&gt;9. 1달에 1번 책 읽기&lt;br /&gt;10. SQLD 자격증 따기&lt;br /&gt;&lt;br /&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;h2 style=&quot;text-align: left;&quot; data-ke-size=&quot;size26&quot;&gt;이룬 것들 &lt;span&gt;✅&lt;/span&gt;&lt;/h2&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&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;물론 현재는 거의다 까먹었기도 하고 GPT와 Gemini 힘이 많이 들어가서 만족하지는 않습니다..&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://joon0112.tistory.com/34&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;군e러닝 1,2학기 A+받기&lt;/a&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;1학기는 전역 전에 시험봤고 2학기에는 전역 후 기말고사&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;컴활 1급 자격 따기 (&lt;b&gt;50%&lt;/b&gt;)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;필기는 전역 전에 합격했으나 실기는 내일인 26.01.14에 봅니다&lt;/li&gt;
&lt;li&gt;(합격 후기로 돌아왔으면 좋겠네요..)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;1달에 1번 책 읽기
&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;a href=&quot;https://joon0112.tistory.com/27&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;SQLD 자격증 따기&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;h2 style=&quot;text-align: left;&quot; data-ke-size=&quot;size26&quot;&gt;못 이룬 것들  &lt;/h2&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&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;hellip;&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;한 번에 기회가 찾아왔는데 전역일이 1달 빨라서 탈락..&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;토플 성적 90+ 이상
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;프로젝트 만드랴 컴활 따랴 KCU공부 하랴 해서 공부 실패..&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;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;h2 style=&quot;text-align: left;&quot; data-ke-size=&quot;size26&quot;&gt;리뷰&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;1년 6개월&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;길다고 하면 길고 짧다고 하면 짧은 기간 동안 나태해지기 싫어서 스스로 갈아넣으면서 열심히 살았던 것 같습니다. 남들 놀 때 맨날 사지방에서 공부하고 연등 신청해서 책 읽고 ..&lt;b&gt; 모두가 열심히 산다고 했었지만 지금와서 보면 약간의 &amp;lsquo;하는 척&amp;rsquo;이 섞여있던 것 같습니다&lt;/b&gt;. 1달 정도 공부를 쉬니 코딩 공부도 거의 까먹고 전역 후 군대에서 공부했던 습관은 다시 리셋되어 놀고 있는 저를 스스로 다그친적이 한 두번이 아닙니다. 하지만 군대에서 있었던 일들은 제게 너무 소중합니다. 남들과는 달리 저는 군대에서 배운 게 너무 많습니다. 후임과 선임을 대하는 방법이나 저의 한계를 알고 그 끝까지 해보는 능력 등&amp;hellip; 저는 대학교 1학년을 마치고 5월 달에 입대했습니다. 하지만&lt;b&gt; &quot;이것보다 빨리 군대에 갔었더라면 저는 정신을 빨리 차리고 더 열심히 모든 걸 해봤지 않을까..?&quot;&lt;/b&gt; 그리고 &lt;b&gt;&quot;겁 먹더라도 조금은 더 열심히 해보자!&quot;&lt;/b&gt; 라는 마인드가 생겼을 것 같아서 그게 가장 아쉬웠습니다&amp;hellip;&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;전과가 만약 성공한다면 더욱 더 전공지식을 블로그에 올릴게요 :3&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>회고/기타</category>
      <category>군대에서</category>
      <category>군생활</category>
      <category>전역</category>
      <category>전역일기</category>
      <author>dev_Hyeonjoon</author>
      <guid isPermaLink="true">https://joon0112.tistory.com/61</guid>
      <comments>https://joon0112.tistory.com/61#entry61comment</comments>
      <pubDate>Tue, 13 Jan 2026 10:26:56 +0900</pubDate>
    </item>
    <item>
      <title> 잠시 쉬어갑니다....</title>
      <link>https://joon0112.tistory.com/60</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;Java TIL을 쉬는 이유&lt;/h2&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;현재 2025년 11월 8일 기준으로 &lt;b&gt;전역까지 약 19일 남은 말년 병장&lt;/b&gt;입니다.&lt;br&gt;요즘은 &lt;b&gt;컴퓨터활용능력 1급(컴활 1급)&lt;/b&gt; 필기 시험 준비에 집중하고 있습니다.&lt;br&gt;원래는 자바 공부와 병행했지만, &lt;b&gt;11월 10일 시험&lt;/b&gt;을 앞두고 부담이 커지면서 잠시 코딩을 쉬기로 했습니다.&lt;br&gt;말년 휴가도 겸사겸사 &lt;b&gt;조금은 쉬어가려구요.&lt;/b&gt;&lt;br&gt;(금방 돌아오겠습니다!)&lt;/p&gt;&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot;&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;1순위: 어깨 및 허리 재활 운동&lt;/li&gt;&lt;li&gt;2순위: 군e러닝(KCU)&lt;/li&gt;&lt;li&gt;3순위: 컴활 1급 필기&lt;/li&gt;&lt;li&gt;4순위: 운전면허 시험 (말출 활용 예정)&lt;/li&gt;&lt;/ul&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;이 세 가지를 병행하기엔 하루 24시간이 너무 짧네요  &lt;/p&gt;&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot;&gt;&lt;h3 data-ke-size=&quot;size23&quot;&gt;추가) Java를 공부하는 이유&lt;/h3&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;저는 &lt;b&gt;명지대학교 경영정보학과 2학년 군 휴학생&lt;/b&gt;입니다.&lt;br&gt;2023년, IT 창업 동아리에서 직접 서비스를 만들어보며 &lt;b&gt;프론트엔드 개발&lt;/b&gt;에 흥미를 느꼈고&lt;br&gt;그 즐거움이 이어져 군대에서도 꾸준히 코딩을 이어져왔습니다&lt;br&gt;&amp;nbsp;&lt;br&gt;하지만 2025년 중반쯤, CSS 스트레스가 너무 심해져 방향을 바꾸기로 했습니다&lt;br&gt;&lt;b&gt;“응용소프트웨어학과로 전과할 예정이니 자바를 배우자.”&lt;/b&gt;&lt;br&gt;이 선택이 결국 제 커리어의 중요한 전환점이 되리라 믿어요.&lt;br&gt;자바는 백엔드, 안드로이드 등 확장성도 크니까요  &lt;/p&gt;&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot;&gt;&lt;blockquote data-ke-style=&quot;style3&quot;&gt;지금은 잠시 쉬지만, &lt;br&gt;이 휴식이 곧 더 단단한 성장으로 이어질 겁니다.&lt;/blockquote&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>회고/기타</category>
      <category>#컴활1급 #컴활공부 #군e러닝 #KCU #공부기록 #공부블로그 #자기계발</category>
      <author>dev_Hyeonjoon</author>
      <guid isPermaLink="true">https://joon0112.tistory.com/60</guid>
      <comments>https://joon0112.tistory.com/60#entry60comment</comments>
      <pubDate>Sat, 8 Nov 2025 23:46:29 +0900</pubDate>
    </item>
    <item>
      <title>[WIL] 자바 반복문 그리고 아쉬운 부분</title>
      <link>https://joon0112.tistory.com/59</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;  1. 이번 주 학습 주제&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 주에는&amp;nbsp;반복문 수강&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  2. 배운 점 요약&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Do While과 While의 차이점&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;반복문을 써야 할 때&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Continue 와 Break&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  3. 삽질(실수) &amp;amp; 해결 과정&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어렵지 않아서 딱히 없었다&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  4. 깨달음 / 느낀 점&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;반복문을 사용할 때는 먼저 어떤 상황인지 생각을 해야한다&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  5. 아쉬운 부분&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컴활 시험이 오늘 기준으로 8일 밖에 안남아서 컴활 필기에 집중하여 얼마 못 한게 매우 아쉽다&amp;hellip;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  6. 다음 주 계획&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컴활 시험이 얼마 남지 않아서 복습 위주로 갈 거 같다&lt;br /&gt;추가적으로 전역도 얼마남지 않아서 전역 전까지는 TIL과 WIL은 매우 뜸해질 것 같다..&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Back-end/Java</category>
      <category>#WIL #Java #객체지향 #OOP #Loop #반복문 #프로그래밍공부 #개발블로그 #군대에서도성장중</category>
      <author>dev_Hyeonjoon</author>
      <guid isPermaLink="true">https://joon0112.tistory.com/59</guid>
      <comments>https://joon0112.tistory.com/59#entry59comment</comments>
      <pubDate>Sun, 2 Nov 2025 20:09:42 +0900</pubDate>
    </item>
    <item>
      <title>[TIL] While, Do While, Break, Continue 차이 정리</title>
      <link>https://joon0112.tistory.com/58</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;반복문&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;제어문(control statement)의 일종으로,&amp;nbsp;&lt;a href=&quot;https://namu.wiki/w/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D%20%EC%96%B8%EC%96%B4&quot;&gt;프로그래밍 언어&lt;/a&gt;에서 특정 부분의 코드를 반복적으로 실행하는 문법입니다&lt;/li&gt;
&lt;li&gt;자바에서는 반복문으로 For, While, Do While 이 있습니다
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;for는 &lt;a href=&quot;https://joon0112.tistory.com/search/For%20%EB%B0%98%EB%B3%B5%EB%AC%B8&quot;&gt;전 글&lt;/a&gt;에서 이미 다뤘으므로 자세한 건 패스하겠습니다&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;While&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;조건이 참일 때만 반복&lt;/b&gt;을 수행합니다.&lt;/li&gt;
&lt;li&gt;조건이 처음부터 거짓이라면 한 번도 실행되지 않습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;사용법&lt;/h3&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;int i = 0;
while (i &amp;lt; 5) {
	System.out.println(i);
	i++;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;출력결과&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;0
1
2
3
4&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;i가 5보다 작을 동안 반복됩니다.&lt;/li&gt;
&lt;li&gt;i가 5 이상이 되면 조건이 false가 되어 반복이 종료됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;조건이 처음부터 맞지 않다면&lt;/h3&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;int i = 6;
while (i&amp;lt; 5){
	System.out.println(i);
	i++;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;⚠️&lt;b&gt;주의:&lt;/b&gt; &lt;b&gt;실행이 아예 안되기 때문에 항상 조건에 주의하며 작성해야합니다&lt;/b&gt;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Do While&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;조건이 거짓이더라도 한 번은 실행&lt;/b&gt;됩니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;먼저 실행 &amp;rarr; 나중에 조건 확인&lt;/b&gt; 구조입니다.&lt;/li&gt;
&lt;li&gt;Do While은 While 반복문과 상당히 비슷한 구문을 이루고 있습니다&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;사용법&lt;/h3&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;int i = 0;
do {
	System.out.println(i + &quot; &quot;);
	i++;
} while (i &amp;lt; 5)
// 1 2 3 4&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;While 반복문과 비슷하지 않나요??&lt;/li&gt;
&lt;li&gt;While문은 먼저 조건을 적는 반면 Do While은 뒤에 조건문을 적으며 문을 마칩니다.&lt;/li&gt;
&lt;li&gt;따라서 아래와 같은 효과를 일으키게 됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;조건이 처음부터 맞지 않다면&lt;/h3&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;int i = 10;
do {
	System.out.println(i + &quot; &quot;);
	i++;
} while (i &amp;lt; 5)
// 10&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;우선 do에 있는 문들이 실행 후 조건을 확인하게 됩니다.&lt;/li&gt;
&lt;li&gt;따라서 &lt;b&gt;무조건 1번은 실행&lt;/b&gt;한다고 볼 수 있습니다&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;✅ &lt;b&gt;핵심 요약&lt;/b&gt;&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&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;style13&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align: center;&quot;&gt;구분&lt;/td&gt;
&lt;td style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&amp;nbsp;실행 순서&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;text-align: center;&quot;&gt;최소 실행 횟수&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align: center;&quot;&gt;While&lt;/td&gt;
&lt;td style=&quot;text-align: center;&quot;&gt;조건 &amp;rarr; 실행&lt;/td&gt;
&lt;td style=&quot;text-align: center;&quot;&gt;0회&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align: center;&quot;&gt;Do While&lt;/td&gt;
&lt;td style=&quot;text-align: center;&quot;&gt;실행 &amp;rarr; 조건&lt;/td&gt;
&lt;td style=&quot;text-align: center;&quot;&gt;1회 이상&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Break과 Continue&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Break&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;반복문을 &lt;b&gt;즉시 멈춥니다&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;for (i=1; i&amp;lt;=10; i++) {
	if(i ==5)
		break;
	System.out.print(i + &quot; &quot;);
}
// 1 2 3 4&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Continue&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;현재 반복문을 &lt;b&gt;건너뛰고 다음 반복&lt;/b&gt;으로 이동합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;for (i=1; i&amp;lt;=10; i++) {
	if(i %2 ==0)
		continue;
	System.out.print(i + &quot; &quot;);
}

// 출력: 1 3 5 7 9&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  반복문 선택 가이드&lt;/h2&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;반복 횟수를 정확히 알 수 있다면&lt;/b&gt; &amp;rarr; for&lt;/li&gt;
&lt;li&gt;&lt;b&gt;반복 횟수를 모른다면&lt;/b&gt; &amp;rarr; while&lt;/li&gt;
&lt;li&gt;&lt;b&gt;최소 한 번은 실행해야 한다면&lt;/b&gt; &amp;rarr; do while&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결국 중요한 것은 &lt;b&gt;&amp;lsquo;가독성&amp;rsquo;&lt;/b&gt;입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;세 문법은 모두 같은 결과를 낼 수 있지만, 읽기 쉽고 의도를 드러내는 코드가 더 좋은 코드입니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt; 참고자료&lt;/h1&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://namu.wiki/w/%EB%B0%98%EB%B3%B5%EB%AC%B8&quot;&gt;나무위키 - 반복문&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.udemy.com/course/best-java-programming/?couponCode=KEEPLEARNING&quot;&gt;Udemy - Java Programming Masterclass&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://joon0112.tistory.com/search/For%20%EB%B0%98%EB%B3%B5%EB%AC%B8&quot;&gt;Tistory - For 반복문 정리&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Back-end/Java</category>
      <category>Break</category>
      <category>CONTINUE</category>
      <category>dowhile</category>
      <category>Java</category>
      <category>JavaTIL</category>
      <category>Til</category>
      <category>while</category>
      <category>반복문</category>
      <category>자바</category>
      <category>자바문법</category>
      <author>dev_Hyeonjoon</author>
      <guid isPermaLink="true">https://joon0112.tistory.com/58</guid>
      <comments>https://joon0112.tistory.com/58#entry58comment</comments>
      <pubDate>Sun, 2 Nov 2025 20:04:41 +0900</pubDate>
    </item>
    <item>
      <title>[WIL] 자바 조건문 그리고 아쉬운 부분</title>
      <link>https://joon0112.tistory.com/57</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;  1. 이번 주 학습 주제&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 주에는 조건문, 반복문 (20%)&amp;nbsp;를 수강&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  2. 배운 점 요약&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자바의 삼항 연산자에 대해 배움&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;switch 함수를 어떻게 쓰고 long 과 같은 값은 안됨&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;사용자 값을 읽는 Scanner&lt;/blockquote&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  3. 삽질(실수) &amp;amp; 해결 과정&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;처음 강의에서 Scanner를 Jshell에서 사용했다. 그래서 임포트도 안하고 계속 에러 뜬 이유를 찾아다니다 구글링을 통해서 해결했다&lt;/blockquote&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  4. 깨달음 / 느낀 점&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;반복된 구문은 Switch로 줄여봐야겠다&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Scanner로 조금 더 사용자와 상호작용할 수 있는 방법으로 나아가봐야겠다&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;  5. 아쉬운 부분&lt;/span&gt;&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;현재 군 e러닝으로 kcu 온라인 대학교 강의와 컴활 그리고 자바 공부까지 하느라 군 생활이 많이 바쁘다...&lt;br /&gt;그렇기에 계획도 잘 못 지키고 자바도 까먹고... 그게 너무 아쉽다&lt;br /&gt;계획을 수정할 수 도 없고 최대한 안까먹게 오늘처럼 전부 복습도 하고 그래야겠다!!&lt;/blockquote&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  6. 다음 주 계획&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;욕심 부리지 않고 자바 반복분 공부해서 TIL 올리기&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컴활 엑셀 강의 다 보기&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Back-end/Java</category>
      <category>Java</category>
      <category>Switch</category>
      <category>Wil</category>
      <category>반복분</category>
      <category>복습</category>
      <category>조건문</category>
      <author>dev_Hyeonjoon</author>
      <guid isPermaLink="true">https://joon0112.tistory.com/57</guid>
      <comments>https://joon0112.tistory.com/57#entry57comment</comments>
      <pubDate>Sun, 26 Oct 2025 19:05:29 +0900</pubDate>
    </item>
    <item>
      <title>[TIL] Java 조건문 (if, switch, 삼항연산자, Scanner )</title>
      <link>https://joon0112.tistory.com/56</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;if 조건문&lt;/h2&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;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;if(i==3){
	System.out.println(&quot;True&quot;);
}
//조건을 명시하고, 조건으로 실행될 코드를 if 블록 안에 쓴다&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;if-else&lt;/h3&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;int i = 25;
if(i==25){
    System.out.println(&quot;i = 25&quot;);
 } else {
    System.out.println(&quot;i != 25&quot;);
 }&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;if 조건이 true와 false 두 가지 경우의 수를 적을 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Nested if (중첩 if)&lt;/h2&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;//if - else if - else (Nested If)
int i = 24;
if(i==25){
	 System.out.println(&quot;i = 25&quot;);
} else if (i == 24) {
			System.out.println(&quot;i == 24&quot;);
} else {
       System.out.println(&quot;i != 24 and i != 25&quot;);
	}&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;858&quot; data-start=&quot;822&quot;&gt;if &amp;rarr; else if &amp;rarr; else 구조로 실행됩니다.&lt;/li&gt;
&lt;li data-end=&quot;892&quot; data-start=&quot;859&quot;&gt;상이한 조건 여러 개 중 하나만 참일 때 유용합니다.&lt;/li&gt;
&lt;li data-end=&quot;929&quot; data-start=&quot;893&quot;&gt;&lt;b&gt;한 번 true가 되면 나머지는 검사하지 않습니다.&lt;/b&gt;&lt;/li&gt;
&lt;li data-end=&quot;964&quot; data-start=&quot;930&quot;&gt;각 블록 {}은 반드시 열고 닫는 습관을 들이세요.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;사용자 값을 읽는 Scanner&lt;/h2&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;은 Scanner 클래스로 받을 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;사용법&lt;/h3&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;import java.util.Scanner;&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;자바에 내재된 클래스임으로 임포트를 받아야 합니다&lt;/li&gt;
&lt;li&gt;그 후 아래 있는 코드와 같이 작성 시 쉽게 불러올 수 있게 됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;import java.util.Scanner;

public class MenuRunner
{
    public static void main(String[] args)
    {

        Scanner scanner = new Scanner(System.in);
        System.out.println(&quot;Enter Number1: &quot;);
        int number1 = scanner.nextInt(); //정수를 읽는 방법
        System.out.println(&quot;The number you entered is - &quot; + number1);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;  참고: &lt;a href=&quot;https://coding-factory.tistory.com/863&quot; data-end=&quot;1484&quot; data-start=&quot;1424&quot;&gt;Scanner 자세한 사용법 보기&lt;/a&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Switch 문&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;if의 문제점&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;if문에 문제가 있습니다 뭘까요??
&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;이 코드가 정말 100개 까지 있다고 생각해보세요 엄청 길어질 것이며 사용하기에도 불편할 것입니다&lt;/li&gt;
&lt;li&gt;이를 조금이나마 해소할 수 있는게 &lt;b&gt;Switch 문&lt;/b&gt;입니다&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt; if (operation == 1){
             System.out.println(number1 + number2);
        }
        else if (operation == 2){
             System.out.println(number1 - number2);
        }
        else if (operation == 3){
             System.out.println(number1 / number2);
        }
        else if (operation == 4){
             System.out.println(number1 * number2);
        } 
        else{
            System.out.println(&quot;Invalid Operation&quot;);
        }&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Switch문 사용법&lt;/h3&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;int number = 1;
switch (number) {
	 case 1 : System.out.println(&quot;hello&quot;);
	 case 2 : System.out.println(&quot;안녕&quot;);
	 default :  System.out.println(&quot;기본값&quot;);
}&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;switch를 적고 원하는 변수를 적은 뒤, 중괄호를 열어 필요한 코드를 입력합니다&lt;/li&gt;
&lt;li&gt;switch문에서 default case는 그냥 default&lt;/li&gt;
&lt;li&gt;하지만 여기서 또 문제가 생깁니다.&lt;/li&gt;
&lt;li&gt;위에 있는 코드를 실행시키면&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;hello
안녕
기본값&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이런 식으로 출력될 것입니다&lt;/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;이를 fall through 현상이라고 부릅니다&lt;/li&gt;
&lt;li&gt;해결 방법은 &lt;b&gt;break&lt;/b&gt;을 사용하면 됩니다&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;fall through를 막는 break&lt;/h3&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;int number = 1;
switch (number) {
	 case 1 : 
	 case 2 : System.out.println(&quot;이것은 2 일까요 1일까요?&quot;); break;
	 case 3 : 
	 case 4 : System.out.println(&quot;이것은 3 일까요 4일까요?&quot;); break;
}

//출력: &quot;이것은 2 일까요 1일까요?&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;int number = 10;
switch (number) {
	default:
		System.out.println(&quot;Default&quot;);
		break;
	case 1:
		System.out.println(&quot;Default&quot;);
		break;
	case 2:
		System.out.println(&quot;Default&quot;);
		break;
	case 3:
		System.out.println(&quot;Default&quot;);
		break;
}&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;fall-through 코드는 떄로는 유용하게 사용될 수 있습니다&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;Nested if 의 경우 매칭되는 조건이 없으면 마지막 &amp;lsquo;else&amp;rsquo; 코드가 실행되게 된다&lt;/li&gt;
&lt;li&gt;유일하게 마지막 조건 입력이 가능한 곳&lt;/li&gt;
&lt;li&gt;하지만 switch문에서는 첫 번째를 디폴트 조건으로 설정할 수 있다&lt;/li&gt;
&lt;li&gt;그 어떤 case 문도 매칭되는 바가 없을 때 디폴트 설정이 실행되는 것&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;switch의 컴파일 에러&lt;/h3&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;long l = 15;
switch (l) {
}&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;컴파일 에러
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;롱 타입에서 switch 불가능, 타입, 스트링에서만 변환 가능, enum 변수 허용됨&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;char, int, byte, short 등에서만 switch문을 사용 가능하다&lt;/li&gt;
&lt;li&gt;long 이나 double에서 switch를 사용할 수 없다&lt;/li&gt;
&lt;li&gt;float , boolean&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;케이스에는 조건이 올 수 없습니다&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;case number &amp;gt; 5 : //에러&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;삼항 연산자&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;삼항 연산자는 if로 나열된 문을 줄일 수 있다는 점에서 강점입니다&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;boolean isEven;
isEven = (condition ? valueIfCondnIsTrue : valueIfFalse);&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;위에 처럼 작성합니다
&lt;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;/ul&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;isEven = (i % 2 == 0? true : false );&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;그리고 이 조건 연산자는 다른 데이터 타입에서도 사용할 수 있습니다&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;String even =  (i % 2 == 0 ? &quot;YES&quot; : &quot;NO&quot; );&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;중요한 건 어떤 것을 사용하든 &lt;b&gt;두 개의 조건 타입이 동일해야 한다는 것&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;String even =  (i % 2 == 0 ? &quot;YES&quot; : false );&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;물론 이런건 안됩니다&lt;/li&gt;
&lt;li&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;코드를 읽을 수 없기 때문&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;정리 (if 와 switch 비교 표)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&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;style12&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;구분&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;text-align: center;&quot;&gt;if문&lt;/td&gt;
&lt;td style=&quot;text-align: center;&quot;&gt;&amp;nbsp;switch문&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align: center;&quot;&gt;조건 타입&lt;/td&gt;
&lt;td style=&quot;text-align: center;&quot;&gt;boolean 표현식&lt;/td&gt;
&lt;td style=&quot;text-align: center;&quot;&gt;int, char, String 등&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align: center;&quot;&gt;실행 방식&lt;/td&gt;
&lt;td style=&quot;text-align: center;&quot;&gt;위에서 아래로 검사&lt;/td&gt;
&lt;td style=&quot;text-align: center;&quot;&gt;일치하는 case부터 실행&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align: center;&quot;&gt;다중 조건&lt;/td&gt;
&lt;td style=&quot;text-align: center;&quot;&gt;가능&lt;/td&gt;
&lt;td style=&quot;text-align: center;&quot;&gt;제한적&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align: center;&quot;&gt;코드 길이&lt;/td&gt;
&lt;td style=&quot;text-align: center;&quot;&gt;복잡해질 수 있음&lt;/td&gt;
&lt;td style=&quot;text-align: center;&quot;&gt;간결함&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align: center;&quot;&gt;default&lt;/td&gt;
&lt;td style=&quot;text-align: center;&quot;&gt;else와 동일&lt;/td&gt;
&lt;td style=&quot;text-align: center;&quot;&gt;case 불일치 시 실행&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;if + scanner의 예제 (계산기 만들기)&lt;/h2&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;import java.util.Scanner;

public class MenuRunner
{
    public static void main(String[] args)
    {

        Scanner scanner = new Scanner(System.in);
        System.out.println(&quot;Enter Number1: &quot;);
        int number1 = scanner.nextInt(); //정수를 읽는 방법
        System.out.println(&quot;Enter Number2: &quot;);
        int number2 = scanner.nextInt(); 

        System.out.println(&quot;1 - add &quot;);
        System.out.println(&quot;2 - Subtract &quot;);
        System.out.println(&quot;3 - Divide &quot;);
        System.out.println(&quot;4 - Multiply &quot;);
        System.out.println(&quot;Choose Operation: &quot;);
        int operation = scanner.nextInt(); 

        if (operation == 1){
             System.out.println(number1 + number2);
        }
        else if (operation == 2){
             System.out.println(number1 - number2);
        }
        else if (operation == 3){
             System.out.println(number1 / number2);
        }
        else if (operation == 4){
             System.out.println(number1 * number2);
        } 
        else{
            System.out.println(&quot;Invalid Operation&quot;);
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt; ️리팩토링&lt;/h3&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt; public static void performOperationUsingNestedIfElse (int number1, int number2, int operation ){
				if (operation == 1){
             System.out.println(number1 + number2);
        }
        else if (operation == 2){
             System.out.println(number1 - number2);
        }
        else if (operation == 3){
             System.out.println(number1 / number2);
        }
        else if (operation == 4){
             System.out.println(number1 * number2);
        } 
        else{
            System.out.println(&quot;Invalid Operation&quot;);
        }
	 }
}&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  참고 자료&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://www.udemy.com/course/best-java-programming/?couponCode=KEEPLEARNING&quot;&gt;Udemy - Java Programming Masterclass&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://coding-factory.tistory.com/863&quot;&gt;Coding Factory - Scanner 클래스 사용법&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Back-end/Java</category>
      <category>if문</category>
      <category>Java</category>
      <category>scanner</category>
      <category>switch문</category>
      <category>Til</category>
      <category>개발공부</category>
      <category>삼항연산자</category>
      <category>자바기초</category>
      <category>자바문법</category>
      <category>조건문</category>
      <author>dev_Hyeonjoon</author>
      <guid isPermaLink="true">https://joon0112.tistory.com/56</guid>
      <comments>https://joon0112.tistory.com/56#entry56comment</comments>
      <pubDate>Tue, 21 Oct 2025 23:06:04 +0900</pubDate>
    </item>
    <item>
      <title>[WIL] 자바의 객체지향부터 BigDecimal까지 &amp;mdash; 실수와 학습의 한 주</title>
      <link>https://joon0112.tistory.com/55</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;  1. 이번 주 학습 주제&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 주에는 OOP(객체 지향 프로그래밍), Java의 캡슐화, 생성자, Wrapper Class, 진수 체계, 자료형 변환, BigDecimal 클래스, 정적 메서드 등을 학습했다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  2. 배운 점 요약&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;객체 지향 프로그래밍이 뭔지 알게 되었고 왜 자바에서는 캡슐화를 하려고 하는지 Setter 와 Getter를 통해 배움.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;부동 소수점의 더 하기는 표현 방식 때문에 달라짐으로 BigDecimal 클래스의 필요성도 알게 되었으며, 마지막으로 형변환은 단순히 타입 바꾸는 게 아니라, 메모리 구조 이해의 출발점임을 깨달음.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  3. 삽질(실수) &amp;amp; 해결 과정&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;double과 float의 차이를 잘못 이해해서 계산 오류가 났다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;강의에서 배워 BigDecimal을 알게 되었고, 계산을 정확하게 할 수 있었다&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또 다른 실수는 메인 메서드 내부에 또 다른 메서드를 정의한 것이다. 처음에는 이유를 몰랐지만, 디버깅과 구글링을 통해 메서드는 메인 메서드 밖에 정의해야 한다는 구조적 규칙을 이해했다. 단순한 문법 오류였지만, 코드 구조의 중요성을 다시금 깨닫는 계가 되었다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  4. 깨달음 / 느낀 점&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;파이썬, 자바스크립트와 비슷한 구문이 많아 지루했지만, 새로운 개념을 발견하려는 시도 자체가 즐거웠다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;되게 아쉬웠던 점은 일요일마다 WIL을 올리고 싶었지만 군대 안에서 시간을 잘쪼개면서 공부하기 쉽지 않다&amp;hellip;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;시간이 부족해서 TIL을 쓸 때마다 GPT를 많이 활용한다.. 원래 WIL을 작성하는 이유는 전과 후 자바에 적응을 잘하고 백엔드 개발자로서 성장하기 위함인데 약간 모순이 되어버리고 있다&lt;br /&gt;&lt;s&gt;(이 글은 구조만 GPT한테 부탁하고 전체 다 내가 쓰고 있다)&lt;/s&gt;&lt;/blockquote&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  5. 다음 주 계획&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;조건문 강의를 마무리하고 TIL을 올릴 것이며 루프절까지 TIL에 올릴 것이다&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일요일에 꼭 WIL을 올릴 계획이다&lt;/p&gt;
&lt;/blockquote&gt;</description>
      <category>Back-end/Java</category>
      <category>BigDecimal</category>
      <category>Java</category>
      <category>OOP</category>
      <category>Wil</category>
      <category>WrapperClass</category>
      <category>개발블로그</category>
      <category>객체지향</category>
      <category>군대에서도성장중</category>
      <category>프로그래밍공부</category>
      <category>형변환</category>
      <author>dev_Hyeonjoon</author>
      <guid isPermaLink="true">https://joon0112.tistory.com/55</guid>
      <comments>https://joon0112.tistory.com/55#entry55comment</comments>
      <pubDate>Mon, 20 Oct 2025 23:11:37 +0900</pubDate>
    </item>
    <item>
      <title>[TIL] Java 불리안, 문자형, 그리고 정적 메서드 정리</title>
      <link>https://joon0112.tistory.com/54</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;  불리안(boolean)&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;대소문자 구분 주의&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;불리안의 기본 리터럴은 &lt;b&gt;true&lt;/b&gt;, &lt;b&gt;false&lt;/b&gt; 두 가지뿐.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;boolean isValue = false;
boolean isValid = true;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  관계 연산자 (Comparison Operators)&lt;/h2&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;i &amp;gt; 7    // false
i &amp;gt;= 7   // true
i == 7   // true&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;관계 연산자의 결과는 항상 &lt;b&gt;boolean&lt;/b&gt; 값으로 반환된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;⚙️ 논리 연산자 (Logical Operators)&lt;/h2&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;i &amp;gt;= 15 &amp;amp;&amp;amp; i &amp;lt;= 25   // 두 조건 모두 참일 때만 true
false || true        // true
false || false       // false
false ^ true         // true (XOR: 두 값이 다르면 참)
!true                // false (NOT: 반대값)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;연산자&lt;/td&gt;
&lt;td&gt;의미&lt;/td&gt;
&lt;td&gt;특징&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&amp;amp;&amp;amp;&lt;/td&gt;
&lt;td&gt;AND&lt;/td&gt;
&lt;td&gt;두 피연산자 모두 참일 때만 true&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;||&lt;/td&gt;
&lt;td&gt;OR&lt;/td&gt;
&lt;td&gt;두 피연산자 중 하나만 참일 떄 true&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;^&lt;/td&gt;
&lt;td&gt;XOR&lt;/td&gt;
&lt;td&gt;서로 다르면 true&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;!&lt;/td&gt;
&lt;td&gt;NOT&lt;/td&gt;
&lt;td&gt;반대값 반환&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;⚡ 단축 회로 연산자 (Short-Circuit Operator)&lt;/h2&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;int j = 15;
int i = 10;

j &amp;gt; 15 &amp;amp;&amp;amp; i++ &amp;gt; 5;  // false
// i는 10 그대로 (두 번째 조건 평가 X)

i &amp;gt; 15 &amp;amp; i++ &amp;gt; 5;   // false
// i는 11로 증가 (모든 피연산자 평가 O)&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&amp;amp;&amp;amp;, || &amp;rarr; &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;첫 번째 피연산자 결과로 이미 전체 결과가 결정되면 &lt;b&gt;두 번째는 평가하지 않음&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&amp;amp;, | &amp;rarr; &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;부수효과(i++ 등)가 있을 경우 값이 달라질 수 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;필요하면 이렇게 명확히 작성하는 게 좋다.&lt;/p&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;i++;
if (j &amp;gt; 15 &amp;amp;&amp;amp; i &amp;gt; 5) { ... }&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  문자형(char)&lt;/h2&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;char ch = 'a';   // ✅ OK
char ch = a;     // ❌ Error
char ch = 'ab';  // ❌ Error&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;문자는 &lt;b&gt;한 글자만 가능&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;내부적으로는 &lt;b&gt;유니코드(2바이트)&lt;/b&gt; 값을 가짐&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;char ch2 = '\\u0022'; // 출력: &quot;&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;키보드로 입력하기 어려운 특수문자는 유니코드로 표현 가능.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;✏️ 문자 연산&lt;/h3&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;char ch = 65;  // 'A'
ch++;
System.out.println(ch); // 'B'

(int) ch; // 66 (정수로 변환)&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;문자도 연산 가능하며,&lt;/li&gt;
&lt;li&gt;정수형(4바이트)과 연산 시 &lt;b&gt;정수형으로 변환&lt;/b&gt;된다.&lt;/li&gt;
&lt;li&gt;개행 문자 \\n &amp;rarr; 줄바꿈&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;char ch = '\\n';&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;⚙️ 정적 메서드 (Static Method)&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;클래스의 데이터를 사용하지 않을 때&lt;/b&gt; 정적 메서드를 쓰는 것이 효율적이다.&lt;/li&gt;
&lt;li&gt;객체 생성 없이 &lt;b&gt;클래스명.메서드()&lt;/b&gt; 형태로 바로 호출 가능.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;class MathUtils {
    static int add(int a, int b) {
        return a + b;
    }
}

int result = MathUtils.add(3, 5); // ✅ 객체 없이 호출 가능&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;인스턴스가 필요 없고, &lt;b&gt;독립적으로 동작하는 기능&lt;/b&gt;에 적합하다.&lt;/li&gt;
&lt;li&gt;예: Math.pow(), Math.sqrt() 등&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  핵심 요약&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구분 설명&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;boolean&lt;/td&gt;
&lt;td&gt;true/false 두 가지 값&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&amp;amp;&amp;amp;,||&lt;/td&gt;
&lt;td&gt;단축 회로 연산자&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&amp;amp;,|&lt;/td&gt;
&lt;td&gt;모든 피연산자 평가&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;char&lt;/td&gt;
&lt;td&gt;문자 하나, 2바이트, 유니코드 기반&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;정적 메서드&lt;/td&gt;
&lt;td&gt;객체 없이 호출 가능, 클래스 단위 기능 구현&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;</description>
      <category>Back-end/Java</category>
      <category>Char</category>
      <category>Java</category>
      <category>Til</category>
      <category>기초문법</category>
      <category>논리연산자</category>
      <category>불리안</category>
      <category>자바공부</category>
      <category>자바기초</category>
      <category>자바스터디</category>
      <category>정적메서드</category>
      <author>dev_Hyeonjoon</author>
      <guid isPermaLink="true">https://joon0112.tistory.com/54</guid>
      <comments>https://joon0112.tistory.com/54#entry54comment</comments>
      <pubDate>Sun, 19 Oct 2025 10:00:22 +0900</pubDate>
    </item>
    <item>
      <title>[TIL] Java 부동소수점(float, double)과 BigDecimal 정확도 차이  이해하기</title>
      <link>https://joon0112.tistory.com/53</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;부동 소수점?&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;정수 부분과 소수 부분 모두 다 가진 값을 말합니다.&lt;/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;double과 float&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;double&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;8바이트&lt;/li&gt;
&lt;li&gt;어떤 부동소수 연산이던 결과는 항상 double&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;double dbl = 34.5678;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;float&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;4바이트&lt;/li&gt;
&lt;li&gt;&lt;b&gt;부동 소숫값 뒤에 꼭 f를 붙여함&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;float f = 34.5; //에러

float f = 34.5f;
float f = 34.5F;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;형변환 오류&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;큰 타입&amp;rarr; 작은 타입으로 변환 할 때 오류&lt;/b&gt;가 발생합니다.&lt;/li&gt;
&lt;li&gt;위를 예로 들자면 double &amp;rarr; float로 변환시 에러가 난다는걸 확인할 수 있습니다&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;public class main
{
    public static void main(String[] args)
    {
        double dbl = 3.45;
        float f = dbl;
    }
}

//incompatible types: possible lossy conversion from double to float
//      float f = dbl;
                 ^
//1 error&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이는 전 글에서 말했던 &lt;a href=&quot;https://joon0112.tistory.com/52&quot;&gt;명시적 형변환&lt;/a&gt;으로 간단히 해결할 수 있습니다&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;부동소수점에 형변환 적용하기&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;명시적 형변환&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;큰 타입 &amp;rarr; 작은 타입&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;public class main
{
    public static void main(String[] args)
    {
        double dbl = 3.45;
        float f = (float) dbl;
        System.out.println(f);
    }
}

// 3.45&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;암묵적 형변환&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;작은 타입 &amp;rarr; 큰 타입&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;public class main
{
    public static void main(String[] args)
    {
        float f2 = 3.45f;
        double dbl2 = f2;
        System.out.println(dbl2);
    }
}
// 3.450000047683716&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;여기서 보면 출력값이 이상한걸 확인하실 수 있습니다.&lt;/li&gt;
&lt;li&gt;아래에서 자세히 살펴보도록 하겠습니다&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;부동소수점의 문제점&lt;/h2&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;System.out.println(34.56789876 + 34.2234);
//출력값 : 68.79129875999999
&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;갑자기 9는 어디서 나온걸까요?&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;  대부분의 부동소수 오차는 IEEE 754 표준의 이진 부동소수 표현 방식 때문입니다. 10진수를 2진수로 바꿀 때 일부 소수가 무한 이진소수로 변환되어 정확히 저장되지 못합니다. (&lt;a href=&quot;https://inpa.tistory.com/entry/JAVA-%E2%98%95-%EC%8B%A4%EC%88%98-%ED%91%9C%ED%98%84%EB%B6%80%EB%8F%99-%EC%86%8C%EC%88%98%EC%A0%90-%EC%9B%90%EB%A6%AC-%ED%95%9C%EB%88%88%EC%97%90-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;참고&lt;/a&gt;)&lt;/blockquote&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;따라서 부동소수는 소숫점값을 명료하게 나타내지 않아서 결과의 정확성이 요구되는 것에는 부동소수 데이터 유형을 계산에서는 float와 double을 사용하지 않는 게 좋습니다&lt;/li&gt;
&lt;li&gt;정확한 결과를 원한다면 &lt;b&gt;BigDecimal 클래스&lt;/b&gt;를 사용해야합니다&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;BigDecimal 클래스&lt;/b&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;BigDecimal은 자바 클래스&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;import java.math.BigDecimal;
public class main
{
    public static void main(String[] args)
    {
        BigDecimal number1 = new BigDecimal(&quot;34.56789876&quot;);
        BigDecimal number2 = new BigDecimal(&quot;34.2234&quot;);
        System.out.println(number1.add(number2));
    }
}

//출력값: 68.79129876&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;여기서 중요한 점은, &lt;b&gt;자바에서 BigDecimal 클래스는 변경 불가능하다는 점&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;BigDecimal 객체는 불변(Immutable) 클래스입니다. 한 번 생성된 값은 변경할 수 없고, 연산 시 새로운 객체를 반환합니다.&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;BigDecimal에 문자열을 넣는 이유?&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;정확성&lt;/b&gt;을 올리기 위해서&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;import java.math.BigDecimal;
public class main
{
    public static void main(String[] args)
    {
        BigDecimal number1 = new BigDecimal(34.56789876);
        BigDecimal number2 = new BigDecimal(34.2234);
        BigDecimal number3 = number1.add(number2);
        System.out.println(number3);
    }
}

///68.79129875999999654823113814927637577056884765625&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;double 타입을 사용해서 만들었더니 출력값이 매우 이상해졌습니다&lt;/li&gt;
&lt;li&gt;&lt;b&gt;정확한 것을 원한다면 문자열을 사용!!&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;BigDecimal 끼리만 연산이 가능해요&lt;/h3&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;import java.math.BigDecimal;
public class main
{
    public static void main(String[] args)
    {
        BigDecimal number = new BigDecimal(&quot;11.5&quot;);
        BigDecimal number2 = new BigDecimal(&quot;23.45678&quot;);
        int i = 5;
        System.out.println(number.add(i));
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이렇게 타입이 다른데 더할 경우 에러가 발생합니다&lt;/li&gt;
&lt;li&gt;무조건 BigDecimal 끼리만 연산해주세요&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;import java.math.BigDecimal;
public class main
{
    public static void main(String[] args)
    {
        BigDecimal number = new BigDecimal(&quot;11.5&quot;);
        BigDecimal number2 = new BigDecimal(&quot;23.45678&quot;);
        int i = 5;
        System.out.println(number.add(new BigDecimal(i)));
    }
}

//출력값: 16.5&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(BigDecimal 메서드 같은 경우 &lt;a href=&quot;https://inpa.tistory.com/entry/JAVA-%E2%98%95-BigInteger-BigDecimal-%EC%9E%90%EB%A3%8C%ED%98%95-%EC%82%AC%EC%9A%A9%EB%B2%95-%EC%B4%9D%EC%A0%95%EB%A6%AC#bigdecimal_%EC%9E%90%EB%A3%8C%ED%98%95&quot;&gt;이 글&lt;/a&gt;에서 배우고 있습니다!)&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;예제 BigDecimal로 이자 계산기 만들기&lt;/h2&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;import java.math.BigDecimal;

public class SimpleInterestCalculator {
    private BigDecimal principal;
    private BigDecimal interest;

    public SimpleInterestCalculator(String principal, String interest) {
        this.principal = new BigDecimal(principal);
        this.interest = new BigDecimal(interest);
    }

    public BigDecimal calculateTotalValue(BigDecimal noOfYears) {
        BigDecimal interestRate = this.interest.divide(new BigDecimal(&quot;100&quot;));

        // 2. 총 이자 계산 (원금 * 이율 * 기간)
        // (Principal * Rate * Time)
        BigDecimal totalInterest = this.principal.multiply(interestRate).multiply(noOfYears);

        // 3. 총액 계산 (원금 + 총 이자)
        // (Principal + Total Interest)
        BigDecimal totalValue = this.principal.add(totalInterest);

        // 4. 총액 반환
        return totalValue;
    }

}

import java.math.BigDecimal;
public class SimpleInterestCalculatorRunner
{
    public static void main(String[] args)
    {
        SimpleInterestCalculator calculator = new SimpleInterestCalculator(&quot;4500.00&quot;, &quot;7.5&quot;);
	 
	// '5'는 문자형, 5는 숫자형 &amp;rarr; 문자 '5'는 내부적으로 아스키코드 53으로 처리됩니다.
        BigDecimal totalValue = calculator.calculateTotalValue(new BigDecimal(&quot;5&quot;));
        System.out.println(totalValue);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;✍️ 요약&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Java의 float와 double은 부동소수점 오차를 가질 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정확한 계산이 필요한 금융, 이자 계산, 금액 처리에서는 BigDecimal 클래스를 사용해야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특히 new BigDecimal(&quot;문자열&quot;) 형태로 선언하면 오차 없이 안전하게 연산할 수 있습니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  참고자료&amp;nbsp;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://inpa.tistory.com/entry/JAVA-%E2%98%95-BigInteger-BigDecimal-%EC%9E%90%EB%A3%8C%ED%98%95-%EC%82%AC%EC%9A%A9%EB%B2%95-%EC%B4%9D%EC%A0%95%EB%A6%AC#bigdecimal_%EC%9E%90%EB%A3%8C%ED%98%95&quot;&gt;☕ BigInteger &amp;amp; BigDecimal 사용법 정리 &amp;ndash; 인파&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://inpa.tistory.com/entry/JAVA-%E2%98%95-%EC%8B%A4%EC%88%98-%ED%91%9C%ED%98%84%EB%B6%80%EB%8F%99-%EC%86%8C%EC%88%98%EC%A0%90-%EC%9B%90%EB%A6%AC-%ED%95%9C%EB%88%88%EC%97%90-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0&quot;&gt;☕ 실수 표현(부동 소수점)-원리 한눈에 이해하기 &amp;ndash; 인파&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://joon0112.tistory.com/52&quot;&gt;TIL 이전 글 &amp;ndash; joon0112&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.udemy.com/course/best-java-programming/?couponCode=MT251015G1&quot;&gt;Udemy Java Programming (온라인 강좌)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Back-end/Java</category>
      <category>BigDecimal</category>
      <category>DOUBLE</category>
      <category>float</category>
      <category>Java</category>
      <category>Til</category>
      <category>부동소수점</category>
      <category>자료형</category>
      <category>자바공부</category>
      <category>자바기초</category>
      <category>형변환</category>
      <author>dev_Hyeonjoon</author>
      <guid isPermaLink="true">https://joon0112.tistory.com/53</guid>
      <comments>https://joon0112.tistory.com/53#entry53comment</comments>
      <pubDate>Sat, 18 Oct 2025 22:56:40 +0900</pubDate>
    </item>
    <item>
      <title>[TIL]  Java 자료형과 형변환 완전 정리 (Wrapper Class &amp;middot; 진수 체계)</title>
      <link>https://joon0112.tistory.com/52</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Java의 자료형과 크기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Java에서 변수와 자료형, 형변환, 진수 체계를 정확히 이해하면 &lt;b&gt;코드의 안정성과 가독성&lt;/b&gt;을 높일 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 글에서는 &lt;b&gt;Wrapper Class&lt;/b&gt;를 통한 자료형 정보 확인, 형변환 종류, 진수 체계까지 한 번에 정리합니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Java 기본 자료형과 Wrapper Class&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Java의 &lt;b&gt;기본 자료형(primitive type)&lt;/b&gt; 은 각각 대응하는 &lt;b&gt;래퍼 클래스(Wrapper Class)&lt;/b&gt;가 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;래퍼 클래스는 해당 자료형의 &lt;b&gt;크기, 최댓값, 최솟값&lt;/b&gt; 등을 제공하여 프로그래밍에 활용할 수 있습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Wrapper Class 예시&lt;/h3&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 10.4651%;&quot;&gt;기본형&lt;/td&gt;
&lt;td style=&quot;width: 14.7674%;&quot;&gt;&amp;nbsp;래퍼 클래스&lt;/td&gt;
&lt;td style=&quot;width: 10.6977%;&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&amp;nbsp;크기(bit)&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 11.2791%;&quot;&gt;크기(bite)&lt;/td&gt;
&lt;td style=&quot;width: 23.2558%;&quot;&gt;최소값&lt;/td&gt;
&lt;td style=&quot;width: 29.5349%;&quot;&gt;&amp;nbsp;최대값&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 10.4651%;&quot;&gt;byte&lt;/td&gt;
&lt;td style=&quot;width: 14.7674%;&quot;&gt;Byte&lt;/td&gt;
&lt;td style=&quot;width: 10.6977%;&quot;&gt;8&lt;/td&gt;
&lt;td style=&quot;width: 11.2791%;&quot;&gt;1&lt;/td&gt;
&lt;td style=&quot;width: 23.2558%;&quot;&gt;-128&lt;/td&gt;
&lt;td style=&quot;width: 29.5349%;&quot;&gt;127&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 10.4651%;&quot;&gt;short&lt;/td&gt;
&lt;td style=&quot;width: 14.7674%;&quot;&gt;Short&lt;/td&gt;
&lt;td style=&quot;width: 10.6977%;&quot;&gt;16&lt;/td&gt;
&lt;td style=&quot;width: 11.2791%;&quot;&gt;2&lt;/td&gt;
&lt;td style=&quot;width: 23.2558%;&quot;&gt;-32,768&lt;/td&gt;
&lt;td style=&quot;width: 29.5349%;&quot;&gt;32,767&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 10.4651%;&quot;&gt;int&lt;/td&gt;
&lt;td style=&quot;width: 14.7674%;&quot;&gt;Integer&lt;/td&gt;
&lt;td style=&quot;width: 10.6977%;&quot;&gt;32&lt;/td&gt;
&lt;td style=&quot;width: 11.2791%;&quot;&gt;4&lt;/td&gt;
&lt;td style=&quot;width: 23.2558%;&quot;&gt;-2,147,483,648&lt;/td&gt;
&lt;td style=&quot;width: 29.5349%;&quot;&gt;2,147,483,647&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 10.4651%;&quot;&gt;long&lt;/td&gt;
&lt;td style=&quot;width: 14.7674%;&quot;&gt;Long&lt;/td&gt;
&lt;td style=&quot;width: 10.6977%;&quot;&gt;64&lt;/td&gt;
&lt;td style=&quot;width: 11.2791%;&quot;&gt;8&lt;/td&gt;
&lt;td style=&quot;width: 23.2558%;&quot;&gt;-9,223,372,036,854,775,808&lt;/td&gt;
&lt;td style=&quot;width: 29.5349%;&quot;&gt;9,223,372,036,854,775,807&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 10.4651%;&quot;&gt;float&lt;/td&gt;
&lt;td style=&quot;width: 14.7674%;&quot;&gt;Float&lt;/td&gt;
&lt;td style=&quot;width: 10.6977%;&quot;&gt;32&lt;/td&gt;
&lt;td style=&quot;width: 11.2791%;&quot;&gt;4&lt;/td&gt;
&lt;td style=&quot;width: 23.2558%;&quot;&gt;-3.4E38&lt;/td&gt;
&lt;td style=&quot;width: 29.5349%;&quot;&gt;3.4E38&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 10.4651%;&quot;&gt;double&lt;/td&gt;
&lt;td style=&quot;width: 14.7674%;&quot;&gt;Double&lt;/td&gt;
&lt;td style=&quot;width: 10.6977%;&quot;&gt;64&lt;/td&gt;
&lt;td style=&quot;width: 11.2791%;&quot;&gt;8&lt;/td&gt;
&lt;td style=&quot;width: 23.2558%;&quot;&gt;-1.7E308&lt;/td&gt;
&lt;td style=&quot;width: 29.5349%;&quot;&gt;1.7E308&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 10.4651%;&quot;&gt;char&lt;/td&gt;
&lt;td style=&quot;width: 14.7674%;&quot;&gt;Character&lt;/td&gt;
&lt;td style=&quot;width: 10.6977%;&quot;&gt;16&lt;/td&gt;
&lt;td style=&quot;width: 11.2791%;&quot;&gt;2&lt;/td&gt;
&lt;td style=&quot;width: 23.2558%;&quot;&gt;'\u0000'&lt;/td&gt;
&lt;td style=&quot;width: 29.5349%;&quot;&gt;65,535&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 10.4651%;&quot;&gt;boolean&lt;/td&gt;
&lt;td style=&quot;width: 14.7674%;&quot;&gt;Boolean&lt;/td&gt;
&lt;td style=&quot;width: 10.6977%;&quot;&gt;1 (논리값)&lt;/td&gt;
&lt;td style=&quot;width: 11.2791%;&quot;&gt;1&lt;/td&gt;
&lt;td style=&quot;width: 23.2558%;&quot;&gt;true&lt;/td&gt;
&lt;td style=&quot;width: 29.5349%;&quot;&gt;false&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Wrapper Class 활용 예제&lt;/h3&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;System.out.println(&quot;Integer.SIZE: &quot; + Integer.SIZE);       // 32 (비트)
System.out.println(&quot;Integer.MIN_VALUE: &quot; + Integer.MIN_VALUE); // -2147483648
System.out.println(&quot;Integer.MAX_VALUE: &quot; + Integer.MAX_VALUE); // 2147483647&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;형변환 (Casting)&lt;/h2&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;Java는 엄격한 자료형을 요구하기 때문에 &lt;b&gt;자동 변환&lt;/b&gt;과 &lt;b&gt;강제 변환&lt;/b&gt;을 이해하는 것이 중요합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2-1. 묵시적 형변환 (Implicit Casting)&lt;/h3&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;&lt;b&gt;자동으로 처리&lt;/b&gt;, 데이터 손실 없음&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;int i = 500000;
long l = i; // 묵시적 형변환 (자동)&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2-2. 명시적 형변환 (Explicit Casting)&lt;/h3&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;&lt;b&gt;데이터 손실 가능&lt;/b&gt;, 반드시 (타입) 명시 필요&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;long l = 10000000000L;
int i = (int) l; // 명시적 형변환, 데이터 손실 가능
System.out.println(i); // 출력: -147483648&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;⚠️ 주의: 큰 값(long)을 int로 변환하면 값이 잘못 나올 수 있습니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;자바 진수 체계&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Java는 &lt;b&gt;2진수, 8진수, 10진수, 16진수&lt;/b&gt;를 지원합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;예제&lt;/h3&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;int decimal = 10;       // 10진수
int octal = 010;        // 8진수 (8)
int hex = 0x10;         // 16진수 (16)
int binary = 0b1010;    // 2진수 (10)&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;진수 규칙&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;0으로 시작 &amp;rarr; 8진수&lt;/li&gt;
&lt;li&gt;0x로 시작 &amp;rarr; 16진수&lt;/li&gt;
&lt;li&gt;0b로 시작 &amp;rarr; 2진수&lt;/li&gt;
&lt;li&gt;10진수는 0~9&lt;/li&gt;
&lt;li&gt;16진수는 0~9, A~F (A=10, B=11 &amp;hellip; F=15)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;진수 변환 메서드&lt;/h3&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;Integer.toBinaryString(10); // &quot;1010&quot;
Integer.toHexString(10);    // &quot;a&quot;
Integer.toOctalString(10);  // &quot;12&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;⚠️ 주의: 다른 진수 사용은 코드 가독성을 떨어뜨리므로, 가능하면 10진수를 기본으로 사용하세요.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;참고 자료&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://ko.wikipedia.org/wiki/%ED%98%95_%EB%B3%80%ED%99%98&quot;&gt;형 변환 - Wikipedia&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://backendcode.tistory.com/211&quot;&gt;BackendCode: Java Wrapper Class&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.udemy.com/course/best-java-programming/?couponCode=MT251015G1&quot;&gt;Udemy Java Programming&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;정리&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Wrapper Class를 활용하면 &lt;b&gt;자료형의 크기와 범위&lt;/b&gt;를 쉽게 확인 가능&lt;/li&gt;
&lt;li&gt;형변환은 &lt;b&gt;묵시적(자동)과 명시적(강제)&lt;/b&gt;으로 나뉘며, &lt;b&gt;데이터 손실 여부&lt;/b&gt;를 확인해야 함&lt;/li&gt;
&lt;li&gt;진수 체계와 변환 메서드를 알고 있으면 &lt;b&gt;진수 관련 연산과 출력&lt;/b&gt;이 편리함&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Back-end/Java</category>
      <category>Java</category>
      <category>JavaTip</category>
      <category>Til</category>
      <category>WrapperClass</category>
      <category>자료형</category>
      <category>자바공부</category>
      <category>진수체계</category>
      <category>코딩</category>
      <category>프로그래밍</category>
      <category>형변환</category>
      <author>dev_Hyeonjoon</author>
      <guid isPermaLink="true">https://joon0112.tistory.com/52</guid>
      <comments>https://joon0112.tistory.com/52#entry52comment</comments>
      <pubDate>Sat, 18 Oct 2025 19:51:00 +0900</pubDate>
    </item>
    <item>
      <title>[TIL] 자바(Java) 생성자(Constructor) 완벽 정리: 메소드 오버로딩과 함께 사용하는 예제</title>
      <link>https://joon0112.tistory.com/51</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;생성자(Constructor)란 무엇일까요?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;생성자&lt;/b&gt;는 객체(Object)가 생성될 때 &lt;b&gt;단 한 번&lt;/b&gt; 호출되는 특별한 종류의 메소드입니다. 주된 역할은 클래스의 인스턴스 변수(필드)들을 원하는 값으로 초기화하는 것입니다. 우리가 new 키워드를 사용하여 객체를 만들 때, 내부적으로는 이 생성자가 호출되고 있는 것이죠.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;생성자, 일반 메소드와 무엇이 다를까요?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;생성자는 일반적인 메소드와 몇 가지 뚜렷한 차이점을 가집니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;반환 타입(Return Type)이 없습니다.&lt;/b&gt; 일반 메소드는 void, String, int 등 반드시 반환 타입을 명시해야 하지만, 생성자는 반환 타입을 지정하지 않습니다. 값을 반환하는 목적이 아니라 객체를 초기화하는 것이 유일한 임무이기 때문입니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;이름이 클래스 이름과 동일합니다.&lt;/b&gt; 생성자의 이름은 반드시 해당 클래스의 이름과 &lt;b&gt;대소문자까지 정확하게&lt;/b&gt; 일치해야 합니다. 만약 단 한 글자라도 다르다면, 자바는 그것을 생성자로 인식하지 않고 일반 메소드로 취급합니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;기본 생성자 예제: MotorBike 클래스&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;간단한 MotorBike 클래스를 통해 생성자를 직접 만들어 보겠습니다.&lt;/p&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;public class MotorBike {
    // 인스턴스 변수 선언
    String brand;
    int speed;

    // 생성자
    public MotorBike(String brandName, int initialSpeed) {
        System.out.println(&quot;생성자가 호출되었습니다.&quot;);
        // this는 현재 객체(만들어질 인스턴스)를 가리킵니다.
        this.brand = brandName;
        this.speed = initialSpeed;
    }

    public static void main(String[] args) {
        // new 키워드로 객체를 생성하는 순간, 생성자가 호출됩니다.
        MotorBike myBike = new MotorBike(&quot;Harley-Davidson&quot;, 0);

        System.out.println(&quot;내 바이크 브랜드: &quot; + myBike.brand); // 출력: Harley-Davidson
        System.out.println(&quot;내 바이크 초기 속도: &quot; + myBike.speed); // 출력: 0
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 예제에서 MotorBike myBike = new MotorBike(&quot;Harley-Davidson&quot;, 0); 코드가 실행되는 순간, MotorBike 클래스의 생성자가 호출됩니다. 생성자는 전달받은 &quot;Harley-Davidson&quot;과 0이라는 값으로 객체의 brand와 speed 변수를 각각 초기화합니다. 이처럼 생성자는 객체가 처음 만들어질 때 필요한 &lt;b&gt;초깃값을 설정&lt;/b&gt;하는 데 매우 유용합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;메소드 오버로딩을 활용한 여러가지 생성자 만들기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;하나의 클래스 안에는 여러 개의 생성자를 만들 수 있습니다&lt;/b&gt;. 이때 &lt;b&gt;메소드 오버로딩&lt;/b&gt; 규칙이 적용되는데요, 바로 &lt;b&gt;매개변수의 개수나 타입&lt;/b&gt;을 다르게 하여 같은 이름의 생성자를 여러 개 정의하는 것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;상황에 따라 객체를 다르게 초기화하고 싶을 때 매우 유용합니다.&lt;/p&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;public class MotorBike {
    String brand;
    int speed;

    // 1. 매개변수가 없는 생성자
    public MotorBike() {
        this.brand = &quot;Unknown&quot;; // 기본 브랜드 설정
        this.speed = 0;         // 기본 속도 설정
    }

    // 2. 브랜드만 받는 생성자 (오버로딩)
    public MotorBike(String brandName) {
        this.brand = brandName;
        this.speed = 0;         // 속도는 기본값으로 설정
    }

    // 3. 브랜드와 속도를 모두 받는 생성자 (오버로딩)
    public MotorBike(String brandName, int initialSpeed) {
        this.brand = brandName;
        this.speed = initialSpeed;
    }

    public static void main(String[] args) {
        MotorBike bike1 = new MotorBike(); // 1번 생성자 호출
        System.out.println(&quot;바이크1: &quot; + bike1.brand + &quot;, 속도: &quot; + bike1.speed);
        // 출력: 바이크1: Unknown, 속도: 0

        MotorBike bike2 = new MotorBike(&quot;Ducati&quot;); // 2번 생성자 호출
        System.out.println(&quot;바이크2: &quot; + bike2.brand + &quot;, 속도: &quot; + bike2.speed);
        // 출력: 바이크2: Ducati, 속도: 0

        MotorBike bike3 = new MotorBike(&quot;BMW&quot;, 10); // 3번 생성자 호출
        System.out.println(&quot;바이크3: &quot; + bike3.brand + &quot;, 속도: &quot; + bike3.speed);
        // 출력: 바이크3: BMW, 속도: 10
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;예제 1: 기본값으로 초기화하는 생성자&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;예제 2: 브랜드만 받아서 초기화하는 생성자&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;예제 3: 브랜드와 속도를 모두 받아서 초기화하는 생성자&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이처럼 생성자 오버로딩을 활용하면, 객체를 생성하는 시점에 전달하는 인자에 따라 각기 다른 방식으로 객체를 초기화할 수 있어 코드의 &lt;b&gt;유연성&lt;/b&gt;이 크게 향상됩니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;정리&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 포스팅의 핵심 내용을 다시 한번 정리해 보겠습니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;생성자&lt;/b&gt;는 객체가 생성될 때 호출되는 &lt;b&gt;초기화 메소드&lt;/b&gt;입니다.&lt;/li&gt;
&lt;li&gt;생성자는 &lt;b&gt;반환 타입이 없고&lt;/b&gt;, 이름이 &lt;b&gt;클래스명과 반드시 동일&lt;/b&gt;해야 합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;메소드 오버로딩&lt;/b&gt;을 통해 매개변수가 다른 여러 생성자를 만들어, 상황에 맞게 객체를 다양하게 초기화할 수 있습니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h4 data-end=&quot;2661&quot; data-start=&quot;2647&quot; data-ke-size=&quot;size20&quot;&gt;  &lt;b&gt;참고 자료&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;2914&quot; data-start=&quot;2662&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;2742&quot; data-start=&quot;2662&quot;&gt;&lt;a href=&quot;https://kadosholy.tistory.com/91#google_vignette&quot; data-end=&quot;2740&quot; data-start=&quot;2664&quot;&gt;kadosholy.tistory.com/91&lt;span aria-hidden=&quot;true&quot;&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li data-end=&quot;2853&quot; data-start=&quot;2743&quot;&gt;&lt;a href=&quot;https://www.udemy.com/course/best-java-programming/?couponCode=MT251015G1&quot; data-end=&quot;2851&quot; data-start=&quot;2745&quot;&gt;Udemy - Best Java Programming&lt;span aria-hidden=&quot;true&quot;&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li data-end=&quot;2914&quot; data-start=&quot;2854&quot;&gt;&lt;a href=&quot;https://kephilab.tistory.com/47&quot; data-end=&quot;2914&quot; data-start=&quot;2856&quot;&gt;kephilab.tistory.com/47&lt;span aria-hidden=&quot;true&quot;&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Back-end/Java</category>
      <category>constructor</category>
      <category>Java</category>
      <category>OOP</category>
      <category>Til</category>
      <category>메소드오버로딩</category>
      <author>dev_Hyeonjoon</author>
      <guid isPermaLink="true">https://joon0112.tistory.com/51</guid>
      <comments>https://joon0112.tistory.com/51#entry51comment</comments>
      <pubDate>Thu, 16 Oct 2025 19:47:54 +0900</pubDate>
    </item>
    <item>
      <title>[TIL] Java 객체의 상태와 캡슐화 - Setter, Getter로 배우는 OOP 기본</title>
      <link>https://joon0112.tistory.com/50</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;객체의 상태&lt;/h2&gt;
&lt;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;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;class Publishing{
    int noOfCopies;
    public void publish(int noOfCopies){
        System.out.println(&quot;publish&quot;);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;class PublishingExample
{
    public static void main(String[] args)
    {
        Publishing zeroToOne = new Publishing();
        zeroToOne.publish = 10
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt; 여기서 문제점이 무엇일까요?&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&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;필드 noOfCopies가 public이 아니라 default지만, 외부에서 직접 접근 가능하지 않은 게 아니라, setter/getter 없이 직접 변경이 가능하다는 점에서 OOP 원칙 위배&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;복사본 조건 설정 불가: 현재 publish(int noOfCopies)는 아무 값이나 받을 수 있음. 예: 음수 입력 가능 &amp;rarr; 논리적 오류 발생 가능.&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를 해결하기 위해서 Setter와 Getter가 사용됩니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Setter &amp;amp; Getter 가 필요한 이유&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;클래스의 &lt;b&gt;데이터 접근을 제한하고 제어하기 위해&lt;/b&gt; 사용됩니다.&lt;/li&gt;
&lt;li&gt;외부에서는 메서드를 통해서만 데이터에 접근하도록 하여, &lt;b&gt;안정성과 일관성&lt;/b&gt;을 확보합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Setter&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;b&gt;동시에 조건 검사나 검증 로직을 추가할 수 있습니다.&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;class Publishing{
    private int noOfCopies;
    public void setPublish(int noOfCopies){
        if ( noOfCopies &amp;gt; 0){
            this.noOfCopies = noOfCopies;  
            //여기서 this.noOfCopies는 2번째 줄의 noOfCopies를 가르키며
						// 등호 오른쪽에 있는 noOfCopies는 매개변수를 가르킵니다.
            System.out.println(noOfCopies);
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;class PublishingExample
{
    public static void main(String[] args)
    {
        Publishing zeroToOne = new Publishing();

        zeroToOne.setPublish(10);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이제 복사본이 1개 이상일 때만 성공적으로 출판되게 만들었습니다.&lt;/li&gt;
&lt;li&gt;이렇게 하면 캡슐화 뿐아니라 조건도 걸 수 있기에 아주 유용합니다&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Getter&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;b&gt;가공된 데이터 반환&lt;/b&gt;에도 활용됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;class Publishing{
    private int noOfCopies;

    public void setNoOfCopies(int noOfCopies){
        this.noOfCopies = noOfCopies;
    }

    public int getNoOfCopies(){
        return this.noOfCopies;
    }
    public void setPublish(int noOfCopies){
        if ( noOfCopies &amp;gt; 0){
            System.out.println(noOfCopies);
        }
        
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;class PublishingExample
{
    public static void main(String[] args)
    {
        Publishing zeroToOne = new Publishing();

        zeroToOne.setNoOfCopies(10);
        System.out.println(zeroToOne.getNoOfCopies());
    }
}

//출력 결과 : 10&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;결론&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;캡슐화(encapsulation)&lt;/b&gt;는 객체 지향의 핵심 원칙으로,&lt;/li&gt;
&lt;li&gt;데이터(필드)는 private으로 보호하고, Setter와 Getter를 통해서만 접근하도록 해야 합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;구분&lt;/td&gt;
&lt;td&gt;역할&lt;/td&gt;
&lt;td&gt;핵심 목적&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Setter&lt;/td&gt;
&lt;td&gt;데이터 변경&lt;/td&gt;
&lt;td&gt;유효성 검사 가능&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Getter&lt;/td&gt;
&lt;td&gt;데이터 읽기&lt;/td&gt;
&lt;td&gt;안전한 접근 및 가공&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 하면 객체의 상태를 안정적으로 유지하면서도 유연한 제어가 가능합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(하지만 요새는 &lt;a href=&quot;https://jaykaybaek.tistory.com/14&quot;&gt;Setter와 Getter를 지양하기도 합니다&lt;/a&gt;)&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt; 참고 자료&lt;/h1&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://mundol-colynn.tistory.com/133&quot;&gt;Colynn의 Mundo 블로그&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://ji-gwang.tistory.com/123&quot;&gt;지광의 개발 블로그&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.udemy.com/course/best-java-programming/&quot;&gt;Udemy - Java Programming Course&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://ittrue.tistory.com/131#google_vignette&quot;&gt;ITTrue 블로그&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Back-end/Java</category>
      <category>getter</category>
      <category>Java</category>
      <category>OOP</category>
      <category>setter</category>
      <category>Til</category>
      <category>객체지향</category>
      <category>자바공부</category>
      <category>자바기초</category>
      <category>자바클래스</category>
      <category>캡슐화</category>
      <author>dev_Hyeonjoon</author>
      <guid isPermaLink="true">https://joon0112.tistory.com/50</guid>
      <comments>https://joon0112.tistory.com/50#entry50comment</comments>
      <pubDate>Wed, 15 Oct 2025 23:27:26 +0900</pubDate>
    </item>
    <item>
      <title>[TIL] 객체 지향 프로그래밍 (OOP) 핵심 개념 총정리</title>
      <link>https://joon0112.tistory.com/49</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;객체 지향 프로그래밍?&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;객체 지향형 프로그래밍 (Object-oriented programming, OOP)은 프로그램을 데이터(객체) 중심으로 구성하여, 객체 간의 상호작용을 통해 동작하도록 설계하는 프로그래밍 패러다임입니다.&lt;/blockquote&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;객체 지향 프로그래밍에서 클래스가 중요한 이유&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://joon0112.tistory.com/45&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;전 글&lt;/a&gt;에서 말했듯이 클래스는 무엇이라고 비유할 수 있을까요?&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;(전 글에서 조금 더 추가해서) &lt;br /&gt;클래스는 객체를 생성하기 위한 설계도(blueprint) 또는 템플릿 입니다. &lt;br /&gt;즉, 클래스는 객체가 가져야 할 속성과 동작을 정의하고, &lt;br /&gt;실제 실행 시 이 설계도를 기반으로 객체가 메모리에 생성됩니다.&lt;/blockquote&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;lsquo;상태&amp;rsquo;라고 하고 객체의 상태는 시간에 따라 바뀔 수 있습니다&lt;/li&gt;
&lt;li&gt;객체에 행할 수 있는 행동은 &amp;lsquo;동작&amp;rsquo; 이라고 합니다&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;즉, 객체가 갖고 있는 데이터와 객체에 행할 수 있는 동작이 무엇인지 규정할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;객체 지향 프로그래밍의 특징&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;추상화(abstraction)&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;복잡한 시스템으로부터 핵심적인 개념 또는 기능을 간추려내는 것을 의미합니다.&lt;/b&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;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;캡슐화(encapsulation)&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;객체의 속성과 메서드를 하나로 묶고 일부를 외부에 감추어 은닉하는 것을 말합니다.&lt;/b&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;lsquo;가속 페달&amp;rsquo;을 밟을 뿐 내부 엔진의 복잡한 로직은 알 수 없습니다.&lt;/li&gt;
&lt;li&gt;이렇게 내부 동작을 숨기고 필요한 인터페이스만 제공하는 것이 캡슐화입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;상속성(inheritance)&lt;/h4&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;h4 data-ke-size=&quot;size20&quot;&gt;다형성(polymorphism)&lt;/h4&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&amp;lsquo;달린다&amp;rsquo; 메서드가 사람, 자동차, 동물 클래스에서 각각 다르게 구현될 수 있습니다&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://ko.wikipedia.org/wiki/%EC%97%B0%EC%82%B0%EC%9E%90_%EC%98%A4%EB%B2%84%EB%A1%9C%EB%94%A9&quot;&gt;오버로딩&lt;/a&gt;, &lt;a href=&quot;https://ko.wikipedia.org/wiki/%EB%A9%94%EC%86%8C%EB%93%9C_%EC%98%A4%EB%B2%84%EB%9D%BC%EC%9D%B4%EB%94%A9&quot;&gt;오버라이딩&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;객체지향프로그래밍의 단점&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;설계와 구조화에 많은 시간이 소요됩니다.&lt;/li&gt;
&lt;li&gt;처리 속도가 절차지향 프로그래밍에 비해 상대적으로 느릴 수 있습니다.&lt;/li&gt;
&lt;li&gt;클래스와 객체 간 의존성이 복잡해지면 &lt;b&gt;유지보수 난이도&lt;/b&gt;가 높아질 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  요약&lt;/h3&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt; 구분 &lt;/b&gt;&lt;/td&gt;
&lt;td&gt;의미&lt;/td&gt;
&lt;td&gt;예시&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;추상화&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;핵심만 간추리기&lt;/td&gt;
&lt;td&gt;자동차의 &amp;lsquo;달린다&amp;rsquo;, &amp;lsquo;멈춘다&amp;rsquo; 기능만 표현&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;캡슐화&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;내부 로직 은닉&lt;/td&gt;
&lt;td&gt;가속페달을 밟지만 엔진 동작은 숨김&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;상속성&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;코드 재사용&lt;/td&gt;
&lt;td&gt;Animal &amp;rarr; Dog, Cat&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;다형성&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;다양한 형태로 동작&lt;/td&gt;
&lt;td&gt;run()이 객체마다 다르게 실행됨&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;결론&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;객체 지향 프로그래밍은 단순히 문법이 아닌 사고방식이다.&lt;br /&gt;현실 세계를 코드로 모델링하며, 유지보수성과 확장성을 높이는 핵심 패러다임이다.&lt;br /&gt;다만, 설계에 신중해야 하며 구조가 복잡해질수록 관리가 어려워질 수 있다.&lt;br /&gt;&lt;br /&gt;+ 객체 지향 프로그래밍은 Java뿐만 아니라 Python, C++, Kotlin 등 대부분의 현대 언어에서 핵심 개념으로 사용&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;  이 글은 Udemy Java 강의와 『면접을 위한 CS 전공지식 노트』를 기반으로,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;제가 직접 이해한 내용을 제 사비로 구매&amp;middot;학습 후 정리한 글입니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt; 참고 자료&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://velog.io/@looljoon/%EA%B0%9D%EC%B2%B4%EC%A7%80%ED%96%A5%EC%96%B8%EC%96%B4%EB%9E%80&quot;&gt;Velog - 객체지향언어란?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.yes24.com/product/goods/108887922&quot;&gt;YES24 - 면접을 위한 CS 전공지식 노트&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.udemy.com/course/best-java-programming/&quot;&gt;Udemy - 자바 강의&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>CS/Architecture</category>
      <category>CS기초</category>
      <category>Java</category>
      <category>OOP</category>
      <category>Til</category>
      <category>객체지향프로그래밍</category>
      <category>다형성</category>
      <category>상속성</category>
      <category>추상화</category>
      <category>캡술화</category>
      <author>dev_Hyeonjoon</author>
      <guid isPermaLink="true">https://joon0112.tistory.com/49</guid>
      <comments>https://joon0112.tistory.com/49#entry49comment</comments>
      <pubDate>Wed, 15 Oct 2025 20:02:48 +0900</pubDate>
    </item>
    <item>
      <title>[WIL] 자바 주간 회고</title>
      <link>https://joon0112.tistory.com/48</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;  자바를 시작한 이유&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;검정색 배경에 코드를 입력하는 순간이 저에겐 정말 짜릿했습니다.처음엔 &amp;ldquo;공부가 부족해서 어렵나?&amp;rdquo; 싶었지만, 시간이 지나도 나아지지 않자 결국 &lt;b&gt;백엔드로 전향&lt;/b&gt;하기로 결심했고, 그렇게 &lt;b&gt;자바(Java)&lt;/b&gt; 공부를 시작했습니다.&lt;/li&gt;
&lt;li&gt;하지만 대학교 때부터 군대까지 &lt;b&gt;프론트엔드&lt;/b&gt;를 계속 하다 보니, &lt;b&gt;CSS 스트레스&lt;/b&gt;가 한계에 다다랐습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  자바를 배우면서 힘들었던 점&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;자바스크립트와 파이썬만 배웠던 제게 &lt;b&gt;타입 지정&lt;/b&gt;, &lt;b&gt;메모리 크기 관리&lt;/b&gt;, &lt;b&gt;공용 정적 메서드(static method)&lt;/b&gt; 등은 처음엔 낯설었습니다.&lt;/li&gt;
&lt;li&gt;특히 메서드 안에서 다른 메서드를 불러오고, 그 안에서 System.out.println()으로 출력하는 과정이 복잡하게 느껴졌습니다.&lt;/li&gt;
&lt;li&gt;하지만 반복 학습과 코드 분석을 통해 &lt;b&gt;&amp;ldquo;아, 이런 구조로 흘러가는구나&amp;rdquo;&lt;/b&gt; 하는 순간이 오면서 점점 적응해나가고 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  TIL(Today I Learned)을 시작한 이유&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;그동안 모든 강의는 &lt;b&gt;Udemy &amp;rarr; 노션 정리&lt;/b&gt; 방식으로 공부했습니다.&lt;/li&gt;
&lt;li&gt;하지만 이 방식은 &lt;b&gt;&amp;lsquo;정리만 하고 복습은 없는&amp;rsquo; 비효율적 루프&lt;/b&gt;였습니다.&lt;/li&gt;
&lt;li&gt;1년 넘게 공부했는데도 머릿속엔 남는 게 거의 없다는 걸 느끼며,&lt;/li&gt;
&lt;li&gt;이제는 &lt;b&gt;기록 중심이 아닌 복습 중심의 학습 루틴&lt;/b&gt;을 만들고자 &lt;b&gt;TIL을 시작&lt;/b&gt;했습니다.&lt;/li&gt;
&lt;li&gt;TIL은 저에게 &amp;ldquo;공부한 것을 내 것으로 만드는 과정&amp;rdquo;이자, &amp;ldquo;성장의 증거를 남기는 기록&amp;rdquo;입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt; &amp;zwj;  간단한 자기소개&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;현재 &lt;b&gt;군 복무 중인 병장(3호봉)&lt;/b&gt;이며, 전역까지 약 &lt;b&gt;45일 남았습니다.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;일과 시간에는 맡은 업무를 마치고, 개인정비 시간에는 책을 읽거나 코딩 공부를 병행하고 있습니다.&lt;/li&gt;
&lt;li&gt;입대 후 &lt;b&gt;SQLD 자격증을 취득&lt;/b&gt;했고, 전역 전까지는 두 가지 목표를 꼭 이루려 합니다.
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;자바 완전 마스터하기&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;군 e-러닝 2학기 A+ 달성하기&lt;/b&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Back-end/Java</category>
      <category>TIL #WIL #Java #백엔드 #자바공부 #개발일지 #개발자성장 #프로그래밍기록 #군코딩 #SQLD #전역준비 #노션공부 #Udemy #백엔드전향 #자바학습 #개발자블로그</category>
      <author>dev_Hyeonjoon</author>
      <guid isPermaLink="true">https://joon0112.tistory.com/48</guid>
      <comments>https://joon0112.tistory.com/48#entry48comment</comments>
      <pubDate>Mon, 13 Oct 2025 19:01:01 +0900</pubDate>
    </item>
    <item>
      <title>  행복한 프로그래머를 위한 10가지 규칙</title>
      <link>https://joon0112.tistory.com/47</link>
      <description>&lt;blockquote data-end=&quot;153&quot; data-start=&quot;122&quot; data-ke-style=&quot;style2&quot;&gt;
&lt;p data-end=&quot;153&quot; data-start=&quot;124&quot; data-ke-size=&quot;size16&quot;&gt;프로그래밍은 단순한 기술이 아니라, 삶의 태도다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1️⃣ 도전을 받아들여라&lt;/h2&gt;
&lt;blockquote data-end=&quot;220&quot; data-start=&quot;180&quot; data-ke-style=&quot;style2&quot;&gt;
&lt;p data-end=&quot;220&quot; data-start=&quot;182&quot; data-ke-size=&quot;size16&quot;&gt;문제는 배움의 시작이다.&lt;br /&gt;에러는 네가 성장하고 있다는 증거다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2️⃣ 실패해도 괜찮다&lt;/h2&gt;
&lt;blockquote data-end=&quot;305&quot; data-start=&quot;246&quot; data-ke-style=&quot;style2&quot;&gt;
&lt;p data-end=&quot;305&quot; data-start=&quot;248&quot; data-ke-size=&quot;size16&quot;&gt;실패는 &amp;lsquo;끝&amp;rsquo;이 아니라, 학습의 한 과정이다.&lt;br /&gt;한 번의 오류가 너를 더 단단하게 만든다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3️⃣ 연습은 완벽함을 만든다&lt;/h2&gt;
&lt;blockquote data-end=&quot;385&quot; data-start=&quot;335&quot; data-ke-style=&quot;style2&quot;&gt;
&lt;p data-end=&quot;385&quot; data-start=&quot;337&quot; data-ke-size=&quot;size16&quot;&gt;많은 코드는 결국 너를 더 나은 개발자로 만든다.&lt;br /&gt;꾸준함이 최고의 알고리즘이다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;4️⃣ 인내심을 가져라&lt;/h2&gt;
&lt;blockquote data-end=&quot;476&quot; data-start=&quot;411&quot; data-ke-style=&quot;style2&quot;&gt;
&lt;p data-end=&quot;476&quot; data-start=&quot;413&quot; data-ke-size=&quot;size16&quot;&gt;프로그래밍은 단거리 달리기가 아니라 마라톤이다.&lt;br /&gt;오늘 이해하지 못한 개념도, 내일엔 보일 수 있다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;5️⃣ 즐겨라&lt;/h2&gt;
&lt;blockquote data-end=&quot;550&quot; data-start=&quot;497&quot; data-ke-style=&quot;style2&quot;&gt;
&lt;p data-end=&quot;550&quot; data-start=&quot;499&quot; data-ke-size=&quot;size16&quot;&gt;코드의 과정 속에서 작은 성취감을 느껴라.&lt;br /&gt;즐기는 사람은 결국 더 멀리 간다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;6️⃣ 포기하지 마라&lt;/h2&gt;
&lt;blockquote data-end=&quot;621&quot; data-start=&quot;575&quot; data-ke-style=&quot;style2&quot;&gt;
&lt;p data-end=&quot;621&quot; data-start=&quot;577&quot; data-ke-size=&quot;size16&quot;&gt;에러는 끝이 아니라, 다음 줄의 시작이다.&lt;br /&gt;멈추지 않으면 결국 완성된다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;7️⃣ 문제를 쪼개라&lt;/h2&gt;
&lt;blockquote data-end=&quot;690&quot; data-start=&quot;646&quot; data-ke-style=&quot;style2&quot;&gt;
&lt;p data-end=&quot;690&quot; data-start=&quot;648&quot; data-ke-size=&quot;size16&quot;&gt;복잡한 문제는 작은 단위로 나누면 단순해진다.&lt;br /&gt;한 줄씩, 한 단계씩.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;8️⃣ 끈기를 가져라&lt;/h2&gt;
&lt;blockquote data-end=&quot;761&quot; data-start=&quot;715&quot; data-ke-style=&quot;style2&quot;&gt;
&lt;p data-end=&quot;761&quot; data-start=&quot;717&quot; data-ke-size=&quot;size16&quot;&gt;어려워 보여도 계속하라.&lt;br /&gt;진짜 실력은 버텨낸 시간에서 만들어진다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;9️⃣ 스스로를 칭찬하라&lt;/h2&gt;
&lt;blockquote data-end=&quot;834&quot; data-start=&quot;788&quot; data-ke-style=&quot;style2&quot;&gt;
&lt;p data-end=&quot;834&quot; data-start=&quot;790&quot; data-ke-size=&quot;size16&quot;&gt;작은 성취라도 스스로에게 박수를 쳐라.&lt;br /&gt;그것이 다음 단계로 가는 연료다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  호기심을 가져라&lt;/h2&gt;
&lt;blockquote data-end=&quot;914&quot; data-start=&quot;859&quot; data-ke-style=&quot;style2&quot;&gt;
&lt;p data-end=&quot;914&quot; data-start=&quot;861&quot; data-ke-size=&quot;size16&quot;&gt;프로그래밍은 평생 학습의 여정이다.&lt;br /&gt;새로운 언어, 개념, 기술에 끊임없이 마음을 열어라.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-end=&quot;959&quot; data-start=&quot;921&quot; data-ke-style=&quot;style2&quot;&gt;
&lt;p data-end=&quot;959&quot; data-start=&quot;923&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;  &amp;ldquo;완벽한 개발자가 아니라, 행복한 개발자가 되어라.&amp;rdquo;&lt;/b&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  코멘트&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;유데미: 완전 초보자를 위한 Java 프로그래밍: 단기간에 Java 완벽 정복을 보다가 강의에서 나온 말 중에 감명받고 정리해서 블로그에 올립니다. 저도 완벽함에 집착하기 보단 행복한 개발자가 되기 위해 노력해야겠습니다!&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>회고/기타</category>
      <category>Til</category>
      <category>개발</category>
      <category>개발자</category>
      <category>자바</category>
      <category>코딩</category>
      <category>프로그래머</category>
      <category>행복한개발자</category>
      <author>dev_Hyeonjoon</author>
      <guid isPermaLink="true">https://joon0112.tistory.com/47</guid>
      <comments>https://joon0112.tistory.com/47#entry47comment</comments>
      <pubDate>Thu, 9 Oct 2025 13:10:24 +0900</pubDate>
    </item>
    <item>
      <title>[TIL] 자바 개발자를 위한 IDE 비교표 (Eclipse, VS Code, JShell, Web IDE)</title>
      <link>https://joon0112.tistory.com/46</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;IDE이란?&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;IDE는 '&lt;b&gt;통합 개발 환경&lt;/b&gt;'(Integrated Development Environment)의 약자로, 소프트웨어 개발에 필요한 여러 도구(코드 편집기, 컴파일러, 디버거 등)를 하나의 그래픽 사용자 인터페이스(GUI) 환경에 통합하여 프로그래머가 코드를 작성하고, 디버깅하고, 테스트하는 과정을 효율적으로 진행할 수 있도록 돕는 소프트웨어 애플리케이션입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;IDE를 사용해야 하는 이유&lt;/h1&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/YcGdF/btsQ3axWkVx/3g9ny2DcPjtUPtDdHNdif1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/YcGdF/btsQ3axWkVx/3g9ny2DcPjtUPtDdHNdif1/img.png&quot; data-origin-width=&quot;763&quot; data-origin-height=&quot;526&quot; data-is-animation=&quot;false&quot; style=&quot;width: 38.5965%; margin-right: 10px;&quot; data-widthpercent=&quot;39.05&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/YcGdF/btsQ3axWkVx/3g9ny2DcPjtUPtDdHNdif1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FYcGdF%2FbtsQ3axWkVx%2F3g9ny2DcPjtUPtDdHNdif1%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;763&quot; height=&quot;526&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/AJU8q/btsQ4zqfuMe/FS6JrzoaTGuLMFMDS4kjw0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/AJU8q/btsQ4zqfuMe/FS6JrzoaTGuLMFMDS4kjw0/img.png&quot; data-origin-width=&quot;686&quot; data-origin-height=&quot;303&quot; data-is-animation=&quot;false&quot; style=&quot;width: 60.2407%;&quot; data-widthpercent=&quot;60.95&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/AJU8q/btsQ4zqfuMe/FS6JrzoaTGuLMFMDS4kjw0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FAJU8q%2FbtsQ4zqfuMe%2FFS6JrzoaTGuLMFMDS4kjw0%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;686&quot; height=&quot;303&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1.클래스 분리&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;IDE를 사용하면 가장 좋은 점은 클래스를 분리 시켜서 가독성과 유지보수 측면에서 큰 이점이라는 것입니다
&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;사실, 이 부분은 '객체 지향 프로그래밍(OOP)'의 핵심 원칙에 따른 것이지만 IDE를 사용하면 이런 핵심원칙에 따르기 쉬워집니다.&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;2.편리한 단축키&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;파일을 생성하는 것부터 저장하는 것 까지 그 외 다양한 기능의 단축키들이 IDE 프로그램에 따라서 존재&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3.리팩터링이 쉽다&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;리팩토링이란?&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;코드의 기능을 건드리지 않으면서 구조에만 변화를 주는 것&lt;/li&gt;
&lt;li&gt;본인의 코드를 개선하는 더 나은 아이디어를 생각해 내는 것이 리팩터링의 본질&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;리팩토링 예시&lt;/h4&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;package project;

public class MultiplicationTable
{
    void print (){
       for(int i = 1 ; i &amp;lt;= 10; i ++){
           System.out.printf(&quot;%d * %d = %d&quot;, 5, i, 5 *i).println();
        }
    }

    void print (int n){
       for(int i = 1 ; i &amp;lt;= 10; i ++){
           System.out.printf(&quot;%d * %d = %d&quot;, n, i, n*i).println();
        }
    }

    void print (int n, int from, int to){
       for(int i = from ; i &amp;lt;= to; i ++){
           System.out.printf(&quot;%d * %d = %d&quot;, n, i, n*i).println();
       }
    }
}

//길고 중복되는 코드가 너무 많다 이걸 리팩토링한다면&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;package project;

public class MultiplicationTable
{
    void print (){
        print(5);
       // print(5, 1, 10);
    }

    void print (int n){
      print(n, 1, 10);
    }

    void print (int n, int from, int to){
       for(int i = from ; i &amp;lt;= to; i ++){
           System.out.printf(&quot;%d * %d = %d&quot;, n, i, n*i).println();
       }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  주의할 점&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;자바에서는 파일 경로를 이용해 클래스를 가져오지 않고, &lt;b&gt;패키지 경로&lt;/b&gt;를 사용합니다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;하지만 MultiplicationTable 클래스가 Main 클래스와 같은 project 패키지(폴더) 안에 있다면, import 문은 &lt;b&gt;아예 필요 없습니다&lt;/b&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;비교표: Web IDE, Eclipse, VS Code, JShell&lt;/h2&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;style8&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;도구명&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;특징 요약&lt;/td&gt;
&lt;td&gt;장점&lt;/td&gt;
&lt;td&gt;단점&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;  Web IDE&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;브라우저 기반 IDE (예: Replit, GitHub Codespaces)&lt;/td&gt;
&lt;td&gt;- 설치 없이 사용 가능- 협업에 용이- 자동 저장 및 클라우드 연동&lt;/td&gt;
&lt;td&gt;- 인터넷 환경 의존- 실행 속도 느림- 제한된 확장성&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;  Eclipse&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;Java 개발 대표 IDE&lt;/td&gt;
&lt;td&gt;- 강력한 디버깅 및 플러그인- 대형 프로젝트에 안정적- 정통 IDE 구조&lt;/td&gt;
&lt;td&gt;- 초기 설정 복잡- 무겁고 느림- UI 직관성 낮음&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;  Visual Studio Code (VSC)&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;경량화된 코드 에디터형 IDE&lt;/td&gt;
&lt;td&gt;- 빠른 속도, 다양한 확장 기능- 여러 언어 지원- 커스터마이징 자유도 높음&lt;/td&gt;
&lt;td&gt;- 고급 기능은 플러그인 의존- 초보자는 세팅 어려움&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;  JShell&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;Java 9+ 버전부터 제공된 REPL 도구&lt;/td&gt;
&lt;td&gt;- 즉시 실행 및 테스트 가능- 실험적 코드 작성 용이- 학습용으로 적합&lt;/td&gt;
&lt;td&gt;- 대형 프로젝트 부적합- 파일 단위 관리 어려움- IDE 수준 기능 부족&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  요약 정리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 100px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style8&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;height: 20px;&quot;&gt;상황 추천&lt;/td&gt;
&lt;td style=&quot;height: 20px;&quot;&gt;&amp;nbsp;IDE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;height: 20px;&quot;&gt;&lt;b&gt;빠르게 코드 테스트 / 학습용&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;height: 20px;&quot;&gt;✅ JShell&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;height: 20px;&quot;&gt;&lt;b&gt;가벼운 개발, 웹 프로젝트 중심&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;height: 20px;&quot;&gt;✅ VS Code&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;height: 20px;&quot;&gt;&lt;b&gt;자바 중심의 대규모 프로젝트&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;height: 20px;&quot;&gt;✅ Eclipse&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;height: 20px;&quot;&gt;&lt;b&gt;설치 없이 간단히 실습 / 팀 협업용&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;height: 20px;&quot;&gt;✅ Web IDE&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;  JShell은 실험용,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;  Eclipse는 본격 개발용,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;  VS Code는 확장형 경량 IDE,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;  Web IDE는 언제 어디서나 접근 가능한 클라우드형.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt; 참고자료&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.redhat.com/ko/topics/platform-engineering/what-is-ide#:~:text=통합&quot;&gt;https://www.redhat.com/ko/topics/platform-engineering/what-is-ide#:~:text=통합&lt;/a&gt;&lt;a href=&quot;https://www.redhat.com/ko/topics/platform-engineering/what-is-ide#:~:text=%ED%86%B5%ED%95%A9%20%EA%B0%9C%EB%B0%9C%20%ED%99%98%EA%B2%BD(Integrated%20Development%20Environment%2C%20IDE)%EC%9D%B4%EB%9E%80%20%EA%B3%B5%ED%86%B5%EB%90%9C,Interface%2C%20GUI&quot;&gt; 개발 환경(Integrated Development Environment%2C IDE)이란 공통된,Interface%2C GUI&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.megazonesoft.com/google_ide-cloudworkstatiom/&quot;&gt;https://www.megazonesoft.com/google_ide-cloudworkstatiom/&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://studioplug.tistory.com/351&quot;&gt;https://studioplug.tistory.com/351&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://i-ri.tistory.com/64&quot;&gt;https://i-ri.tistory.com/64&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://jjini-note.tistory.com/22&quot;&gt;https://jjini-note.tistory.com/22&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://comparedev.tistory.com/entry/JShell-을-이용해-자바-테스트하기&quot;&gt;https://comparedev.tistory.com/entry/JShell-을-이용해-자바-테스트하기&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://dimorin.tistory.com/entry/Eclipse-vs-Visual-Studio-Code-VS-Code-비교&quot;&gt;https://dimorin.tistory.com/entry/Eclipse-vs-Visual-Studio-Code-VS-Code-비교&lt;/a&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;</description>
      <category>Back-end/Java</category>
      <category>Eclipse</category>
      <category>IDE</category>
      <category>Java</category>
      <category>jshell</category>
      <category>Til</category>
      <category>vscode</category>
      <category>WebIDE</category>
      <category>개발툴비교</category>
      <category>자바</category>
      <category>통합개발환경</category>
      <author>dev_Hyeonjoon</author>
      <guid isPermaLink="true">https://joon0112.tistory.com/46</guid>
      <comments>https://joon0112.tistory.com/46#entry46comment</comments>
      <pubDate>Thu, 9 Oct 2025 11:13:24 +0900</pubDate>
    </item>
    <item>
      <title>[TIL] 자바 플랫폼 독립 (+ 클래스)</title>
      <link>https://joon0112.tistory.com/45</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;768&quot; data-origin-height=&quot;581&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dziguv/btsQ4mROB7j/ENUR0rpfwwsc4I6yLrX6nK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dziguv/btsQ4mROB7j/ENUR0rpfwwsc4I6yLrX6nK/img.png&quot; data-alt=&quot;GeeksforGeeks&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dziguv/btsQ4mROB7j/ENUR0rpfwwsc4I6yLrX6nK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdziguv%2FbtsQ4mROB7j%2FENUR0rpfwwsc4I6yLrX6nK%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;768&quot; height=&quot;581&quot; data-origin-width=&quot;768&quot; data-origin-height=&quot;581&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;GeeksforGeeks&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;컴퓨터는 0과 1 밖에 모른다&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;컴퓨터는 사실 0과 1밖에 알아듣지 못 합니다. 0과1로만 코딩하는걸 기본 명령이라고 하는데 이는 어셈블리 언어에서 사용됩니다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이 0과1은 CPU가 이해하는 기계어이며, 운영체제는 그 위에서 동작합니다&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;그런데 운영체제마다 명령어가 다르다면 자바 코드는 어떻게 운영체제에서 작동될 수 있을까요?&lt;/li&gt;
&lt;li&gt;이는 &lt;b&gt;플랫폼 독립성&lt;/b&gt;으로 해결 가능합니다&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;플랫폼 독립성이란&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;특정 하드웨어나 운영체제 등 플랫폼에 제약받지 않고 소프트웨어가 실행될 수 있는 특성&lt;/b&gt;
&lt;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;바이트 코드&lt;/h3&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://ko.wikipedia.org/wiki/%EC%9E%90%EB%B0%94_%EB%B0%94%EC%9D%B4%ED%8A%B8%EC%BD%94%EB%93%9C&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;b&gt;자바 소스 코드를 자바 가상 머신(JVM)이 이해할 수 있도록 변환한 중간 코드&lt;/b&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;바이트 코드는 운영체제와 관계없이 공통적인 포맷을 취합니다&lt;/li&gt;
&lt;li&gt;하지만, 운영체제들은 기초적인 명령들만 알아듣기에 이해할 수 없습니다&lt;/li&gt;
&lt;li&gt;이 문제를 해결하기 위해 등장한 것이 JVM (자바 가상 머신) 입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;통역사 같은 역할 JVM&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;바이트코드를 각 운영체제를 위한 명령으로 바꿔주는 역할을 합니다&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;여기서 명심해야할 사실은 JVM은 운영체제마다 다르다는 것입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;덕분에 윈도우에서 작성한 자바 코드가 리눅스 나 유닉스에서도 작동될 수 있죠&lt;/li&gt;
&lt;li&gt;다시 말하자면 JVM이 바이트 코드를 기반으로 코드를 실행하는데 그걸 위해서 JVM이 바이트코드를 기계 명령으로 바꾸는 것
&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;h4 data-ke-size=&quot;size20&quot;&gt;실행 과정&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;소스 코드 작성 &amp;rarr; 컴파일 -&amp;gt; 바이트코드로 변환 -&amp;gt; 실행 중 JVM이 바이트코드 읽어 특정 운영체제 명령어로 바꿈 -&amp;gt; 운영체제에 프로그램을 실행&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JVM이 실제 실행을 담당한다면, 자바 프로그램이 실행되기까지는 다른 도구들도 필요합니다. 바로 JRE(Java Runtime Environment) 와 JDK(Java Development Kit)입니다. 다음은 이들이 어떤 역할을 하는전 이해하기 쉽도록 자바 프로그램이 어떤 구조(클래스와 메서드)로 구성되는지를 알아보겠습니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;자바 클래스&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;자바는 객체지향언어로써 &amp;lsquo;클래스&amp;rsquo;로 이루어져 있습니다.&lt;/li&gt;
&lt;li&gt;JVM, JRE, JDK 를 이해하기 전 클래스가 어떻게 구성되었는지 반드시 알아야 합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;클래스란&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;클래스는 &amp;lsquo;템플렛&amp;rsquo; 이라고 말할 수 있습니다.&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;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;클래스 생성하기&lt;/h3&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;class Country {
   //methods
 }&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이와 같이 클래스를 정의할 수 있습니다.&lt;/li&gt;
&lt;li&gt;class 는 Country 라는 유형을 정의한 것입니다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;int num = 1 과 같이 말이죠&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;오브젝트&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Country라는 클래스가 있을 때 India, USA, Korea 등 과 같은 나라들을 만들 수 있겠죠
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;여기서 Country는 클래스, India, USA, Korea 는 오브젝트들이 됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;오브젝트 생성하기&lt;/h3&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;Country India = new Country();
Country USA  = new Country();
Country Korea = new Country();&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;India, USA, Korea는 Country 형의 오브젝트입니다
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;즉, 형이든 클래스든 둘 다 Country를 뜻함&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;보통 클래스에서는 데이터, 메서드가 있으며 메서드로 클래스의 데이터에 작업을 할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;메서드&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;클래스들에 행해질 수 있는 행동 (&lt;a href=&quot;https://joon0112.tistory.com/43?category=1312034&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;전글 참조&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;class Country {
   void sayHello(){
		System.out.println(&quot;Hello!!!&quot;)
	}
    }
    
Country India = new Country();
Country USA  = new Country();
Country Korea = new Country();

Korea.sayHello();&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이렇게 하면 오브젝트도 클래스에 정의된 메서드를 사용할 수 있습니다&lt;/li&gt;
&lt;/ul&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;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;컴파일 과정&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자바 코드 &amp;rarr; 파일로 만듦 &amp;rarr; 컴파일 &amp;rarr; 바이트코드&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;s&gt;(터미널이 불가하여 글로 대체하겠습니다&amp;hellip; 양해부탁드려요)&lt;/s&gt;&lt;/p&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;class Country {
   void sayHello(){
		System.out.println(&quot;Hello!!!&quot;)
	}
    }&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이 파일을 가지고 컴파일한다고 가정해보겠습니다&lt;/li&gt;
&lt;li&gt;컴파일 명령어는 javac 파일명
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;*.java 파일을 컴파일하면 *.class 로 컴파일되어 새로운 파일이 생깁니다.&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;java 클래스의 이름
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;*.class 의 파일을 사용한다&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;다시 정리하자면&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;*.java -&amp;gt; 컴파일 -&amp;gt; *.class 생성 -&amp;gt; java *이 *.class를 실행하려고 할 것이다&lt;/p&gt;
&lt;/blockquote&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;하다 (JShell 외에서)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;공허는 메서드가 아무것도 반환하지 않았고 메인은 메서드의 이름이고 &lt;span style=&quot;color: #ef5369; background-color: #dddddd;&quot;&gt;String[] args &lt;/span&gt;인수들 입니다&lt;/li&gt;
&lt;li&gt;문자열,대괄호는 인수의 배열이라는 걸 뜻 합니다&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #dddddd; color: #ef5369;&quot;&gt;public static void main(String[] args) {} &lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;package project;
class Country{
    void sayHello() {
        System.out.println(&quot;Hello&quot;);
    }
    public static void main(String[] args) {
        Country Korea = new Korea();
        Korea.sayHello();
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;최종적으로 이렇게 바꿨음에도 아직 오류가 뜰 겁니다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이는, *.class 파일이 실행되고 있기 때문인데 *.java를 컴파일하고 다시 *.class 파일을 실행하면 해결 가능합니다&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;⚠️주의사항&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;자바 파일은 메인 메서드가 있어야 실행되는데 어떤 것을 추가하거나 어떤 변화라도 준다면 다시 꼭 컴파일해야만 변화가 적용됩니다&lt;/li&gt;
&lt;li&gt;javac(자바 컴파일)를 실행하려면 *.java 가 있는 폴더와 똑같은 곳에 있어야 합니다&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;JVM, JRE, JDK 함께 보기&amp;nbsp;&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;400&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/GcRLJ/btsQ2WNsrIp/NsAKqHHbKDqzi6JB1WoS80/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/GcRLJ/btsQ2WNsrIp/NsAKqHHbKDqzi6JB1WoS80/img.png&quot; data-alt=&quot;GeeksforGeeks&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/GcRLJ/btsQ2WNsrIp/NsAKqHHbKDqzi6JB1WoS80/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FGcRLJ%2FbtsQ2WNsrIp%2FNsAKqHHbKDqzi6JB1WoS80%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;800&quot; height=&quot;400&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;400&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;GeeksforGeeks&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;JVM (Java Virtual Machine)&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;그러니 윈도우 JVM, 유닉스 JVM, 리눅스 JVM 모두 제각각 다릅니다&lt;/li&gt;
&lt;li&gt;이것들이 할 수 있는 건 바이트코드를 가져다가 특정한 운영 체제가 명령을 실행할 수 있도록 바꾸는 것&lt;/li&gt;
&lt;li&gt;다시 말하자면 JVM이 바이트 코드를 기반으로 코드를 실행하는데 그걸 위해서 JVM이 바이트코드를 기계 명령으로 바꾸는 것
&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;JRE(Java Runtime Environment, 자바 실행 환경)&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;JVM + Libraries + Other Components&lt;/li&gt;
&lt;li&gt;어떤 자바 프로그램을 예로 들어도 기본적으로 내재되어 있는 자바 클래스가 몇 개는 필요&lt;/li&gt;
&lt;li&gt;System.out.println 은 자바 라이브러리 안에 있음&lt;/li&gt;
&lt;li&gt;어떤 자바 라이브러리든 어떤 자바 클래스가 필요하든 여기에 포함되어 있을 것&lt;/li&gt;
&lt;li&gt;JRE, 자바 실행 환경은 JVM과 내재된 모든 자바 클래스를 합친 것&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;JDK(Java Development Kit&lt;b&gt;)&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;JRE + Compilers + Debuggers&lt;/li&gt;
&lt;li&gt;JRE, JVM 하고 자바 라이브러리가 더해진 거고 모든 컴파일러와 디버거가 합쳐진 것&lt;/li&gt;
&lt;li&gt;전체가 자바 프로그램을 개발하고, 컴파일하고 실행시킬 때까지 필요한 것들이라는 것&lt;/li&gt;
&lt;li&gt;JDK는 자바 프로그램을 개발하고 실행할 때 필요하고 JRE는 자바 프로그램을 실행할 때 필요하고 그리고 모든 자바 프로그램은 JVM을 이용해서 실행&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;참고&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://velog.io/@hyhy9501/섹션5-자바-플랫폼-소개&quot;&gt;https://velog.io/@hyhy9501/섹션5-자바-플랫폼-소개&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.geeksforgeeks.org/java/jdk-in-java/&quot;&gt;https://www.geeksforgeeks.org/java/jdk-in-java/&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.geeksforgeeks.org/java/java-platform-independent/&quot;&gt;https://www.geeksforgeeks.org/java/java-platform-independent/&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://ko.wikipedia.org/wiki/%EC%9E%90%EB%B0%94_%EB%B0%94%EC%9D%B4%ED%8A%B8%EC%BD%94%EB%93%9C&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://ko.wikipedia.org/wiki/%EC%9E%90%EB%B0%94_%EB%B0%94%EC%9D%B4%ED%8A%B8%EC%BD%94%EB%93%9C&lt;/a&gt;&lt;/p&gt;</description>
      <category>Back-end/Java</category>
      <category>Java</category>
      <category>jdk</category>
      <category>jre</category>
      <category>JVM</category>
      <category>Til</category>
      <category>바이트코드</category>
      <category>자바기초</category>
      <category>컴파일</category>
      <category>클래스</category>
      <category>플랫폼독립성</category>
      <author>dev_Hyeonjoon</author>
      <guid isPermaLink="true">https://joon0112.tistory.com/45</guid>
      <comments>https://joon0112.tistory.com/45#entry45comment</comments>
      <pubDate>Wed, 8 Oct 2025 16:38:21 +0900</pubDate>
    </item>
    <item>
      <title>[인프런]  무료 노션 강의 후기 &amp;mdash; &amp;ldquo;노션, 단순 기록을 넘어서 시스템으로&amp;rdquo;</title>
      <link>https://joon0112.tistory.com/44</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;941&quot; data-origin-height=&quot;728&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/pU1Yc/btsQ2qnzDd2/3pHN4r9iaGBMZh73Zz4aa1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/pU1Yc/btsQ2qnzDd2/3pHN4r9iaGBMZh73Zz4aa1/img.png&quot; data-alt=&quot;https://inf.run/P2KrQ&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/pU1Yc/btsQ2qnzDd2/3pHN4r9iaGBMZh73Zz4aa1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FpU1Yc%2FbtsQ2qnzDd2%2F3pHN4r9iaGBMZh73Zz4aa1%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;941&quot; height=&quot;728&quot; data-origin-width=&quot;941&quot; data-origin-height=&quot;728&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://inf.run/P2KrQ&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span&gt; &lt;/span&gt; 강의를 듣게 된 계기&lt;/h2&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;노션 템플릿을 사용하다 보니&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;이건 어떻게 만들었지?&amp;rdquo;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;여기서 수식은 뭐지?&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 궁금증이 생겼습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마침 인프런에서 무료로 제공되는 노션 기초 강의가 있어 바로 수강하게 되었습니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  강의 구성&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;721&quot; data-origin-height=&quot;379&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cUGbR0/btsQ3pIoFDu/yF6XoH5Q3VSSVTyhyYxEyk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cUGbR0/btsQ3pIoFDu/yF6XoH5Q3VSSVTyhyYxEyk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cUGbR0/btsQ3pIoFDu/yF6XoH5Q3VSSVTyhyYxEyk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcUGbR0%2FbtsQ3pIoFDu%2FyF6XoH5Q3VSSVTyhyYxEyk%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;451&quot; height=&quot;237&quot; data-origin-width=&quot;721&quot; data-origin-height=&quot;379&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;총 &lt;b&gt;5개 섹션 / 48강 / 약 5시간 44분 분량&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;하루에 한 섹션씩, &lt;b&gt;5일 플랜&lt;/b&gt;으로 완강 (25.10.02 ~ 25.10.07)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단순히 페이지를 꾸미는 수준이 아니라,&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;데이터베이스 관계(Relation)&lt;/li&gt;
&lt;li&gt;Rollup, Formula 계산식&lt;/li&gt;
&lt;li&gt;템플릿 자동화 및 필터링 시스템&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;까지 다루어 &lt;b&gt;노션의 기술적 구조&lt;/b&gt;를 전반적으로 이해할 수 있었습니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  이런 분들에게 추천합니다&lt;/h2&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;노션을 처음 접하거나 계정만 만든 채 방치한 분&lt;/li&gt;
&lt;li&gt;노션을 쓰고 있지만 기능을 30%도 활용하지 못하는 분&lt;/li&gt;
&lt;li&gt;개인 공부나 프로젝트를 &lt;b&gt;체계적으로 관리하고 싶은 사람&lt;/b&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;✅ 장점&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;실습 중심으로 따라 하기 쉬운 구성&lt;/li&gt;
&lt;li&gt;강사님의 톤이 친절하고 세세하게 설명&lt;/li&gt;
&lt;li&gt;&amp;ldquo;왜 이렇게 설계해야 하는가&amp;rdquo;에 대한 설명이 있어 응용이 쉬움&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;⚠️ 단점&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;2020년 기준 강의&lt;/b&gt;라 일부 기능(데이터베이스 뷰, 캘린더 UI 등)이 현재 버전과 다름&lt;/li&gt;
&lt;li&gt;&amp;rarr; 하지만 공식 노션 문서나 구글, Reddit 커뮤니티 참고로 쉽게 해결 가능&lt;/li&gt;
&lt;li&gt;중급 이상 유저에게는 다소 기본적으로 느껴질 수 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  수강 후 변화&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이전에는 템플릿을 아예 만들지 못했지만,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제는 데이터베이스와 Formula를 이용해&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Java 학습 노트 관리용 템플릿&lt;/b&gt;을 직접 제작했습니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Before: 단순 텍스트 기록&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;After: 학습 진도, 복습 주기, 요약을 자동 계산하는 시스템화된 노트&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;노션이 단순 노트가 아니라,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;개인 맞춤형 생산성 툴&lt;/b&gt;이라는 걸 실감했습니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  앞으로의 활용 계획&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 강의를 통해 노션의 구조적 사고를 익혔고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앞으로는 개발 공부, 프로젝트 관리, 사이드 템플릿 제작까지&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;수익화&lt;/b&gt;에도 도전해볼 생각입니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt; 이 글은 광고나 협찬이 아닌,&lt;br /&gt;제가&amp;nbsp;순수하게 배우고 싶어서 들은 강의 후기입니다.&lt;br /&gt;노션을 막 시작하려는 분들께 도움이 되길 바랍니다!&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>회고/기타</category>
      <category>#TIL #노션강의후기 #인프런 #노션활용 #생산성도구 #템플릿제작 #기술블로그</category>
      <author>dev_Hyeonjoon</author>
      <guid isPermaLink="true">https://joon0112.tistory.com/44</guid>
      <comments>https://joon0112.tistory.com/44#entry44comment</comments>
      <pubDate>Tue, 7 Oct 2025 23:31:25 +0900</pubDate>
    </item>
    <item>
      <title>[TIL] 자바 메서드</title>
      <link>https://joon0112.tistory.com/43</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;Java 메서드란?&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;메서드란 클래스 내부에 정의되어, &lt;b&gt;특정 객체의 행동을 나타내는 함수&lt;/b&gt;입니다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;예를 들어, &lt;span style=&quot;background-color: #dddddd; color: #000000;&quot;&gt;자동차&lt;/span&gt; 라는 클래스에 시동을 거는 것 그것이 &lt;b&gt;메서드&lt;/b&gt;로 볼 수 있습니다&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;메서드의 이점&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;1. 코드의 재사용성 (Reusability)  &lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;똑같은 코드를 여러 곳에 복사해서 붙여넣을 필요가 없습니다. 특정 기능을 하는 코드를 메서드로 만들어두면, 필요할 때마다 그 메서드를 호출하기만 하면 됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;2. 가독성 및 구조화 (Readability &amp;amp; Organization)  &lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;복잡한 프로그램을 잘게 쪼개진 여러 개의 메서드로 나누면 전체 코드의 구조를 파악하기가 매우 쉬워집니다. 각 메서드는 &lt;b&gt;하나의 특정 기능만 담당&lt;/b&gt;하므로, 메서드 이름만 봐도 어떤 작업을 하는지 바로 알 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;3. 유지보수 용이성 (Maintainability)  ️&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;코드 수정이 필요할 때, 해당 기능을 담당하는 메서드 &lt;b&gt;한 곳만 수정&lt;/b&gt;하면 됩니다. 만약 메서드를 사용하지 않고 코드를 복사해서 붙여넣었다면, 그 코드가 사용된 모든 곳을 찾아서 일일이 수정해야 하는 번거로움이 있습니다&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&amp;nbsp;아래 메서드의 예제를 보고 다시 한번 이점을 생각해보도록 합시다!  &lt;/blockquote&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Java에는 함수가 없나요?&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;네, Java는 모든 코드가 클래스 안에 작성되어야 하는 &lt;a href=&quot;https://namu.wiki/w/%EA%B0%9D%EC%B2%B4%20%EC%A7%80%ED%96%A5%20%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D&quot;&gt;&lt;b&gt;객체 지향 언어&lt;/b&gt;&lt;/a&gt;입니다. 따라서 Java에서 만드는 모든 기능은 클래스에 소속되므로 &lt;b&gt;메서드&lt;/b&gt;라고 부르는 것이 가장 정확한 표현입니다.  &lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;메서드&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;메서드 문법&lt;/h3&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;ReturnType nameOfTheMethod() {
	//Body of the method
}&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;리턴 타입, 메서드 명 , 매개변수, 그리고 메서드 몸통으로 이루어져 있습니다&lt;/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;&lt;b&gt;void :&lt;/b&gt; 반환하지 않는 타입 (공허 메서드 라고도 불림)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;String:&lt;/b&gt; 문자를 반환&lt;/li&gt;
&lt;li&gt;&lt;b&gt;int :&lt;/b&gt; 숫자 반환&lt;/li&gt;
&lt;li&gt;기타 등등&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;읽었을 때 한번에 메서드의 역할을 이해할 수 있는게 가장 좋은 메서드 명&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;메서드 몸통&lt;/b&gt;: 코드 블록({}) 안에 들어가는것들&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;예제&lt;/h4&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;void sayHelloWorldTwice() {
	System.out.println(&quot;Hello World&quot;);
	System.out.println(&quot;Hello World&quot;);
}

sayHelloWorldTwice() // 메서드 실행&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;⚠️ : 메서드 &quot;선언&quot;과 &quot;실행(호출)&quot;은 엄연히 다릅니다&lt;br /&gt;선언만 해서는 코드가 실행되지 않습니다&lt;/blockquote&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span&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; 메서드는 '어떤 동작을 수행'하므로, 그 동작을 나타내는 &lt;b&gt;동사&lt;/b&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;좋은 예: &lt;span style=&quot;background-color: #dddddd; color: #000000;&quot;&gt;print, send, calculate&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;카멜 케이스(Camel Case) 표기법 사용&lt;/b&gt; 메서드 이름이 여러 단어로 이루어진 경우, 첫 단어는 소문자로 시작하고 그 이후 각 단어의 첫 글자만 대문자로 작성합니다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #dddddd; color: #000000;&quot;&gt;get user name &amp;rarr; getUserName()&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #dddddd; color: #000000;&quot;&gt;calculate total price &amp;rarr; calculateTotalPrice()&lt;/span&gt;&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;나쁜 예: &lt;span style=&quot;background-color: #dddddd; color: #000000;&quot;&gt;proc(), calc(), ud()&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;좋은 예: &lt;span style=&quot;background-color: #dddddd; color: #000000;&quot;&gt;processUserData(), calculateScore(), updateDatabase()&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;자주 사용되는 접두사&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메서드의 역할을 더 명확하게 나타내기 위해 다음과 같은 접두사를 관례적으로 사용합니다.&amp;nbsp;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 135px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;접두사&lt;/td&gt;
&lt;td&gt;&amp;nbsp;역할&lt;/td&gt;
&lt;td&gt;예시&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 25px;&quot;&gt;
&lt;td style=&quot;height: 25px;&quot;&gt;get...&lt;/td&gt;
&lt;td style=&quot;height: 25px;&quot;&gt;값을 가져올 때&lt;/td&gt;
&lt;td style=&quot;height: 25px;&quot;&gt;getName()&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 25px;&quot;&gt;
&lt;td style=&quot;height: 25px;&quot;&gt;set...&lt;/td&gt;
&lt;td style=&quot;height: 25px;&quot;&gt;값을 설정할 때&lt;/td&gt;
&lt;td style=&quot;height: 25px;&quot;&gt;setAge(25)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 25px;&quot;&gt;
&lt;td style=&quot;height: 25px;&quot;&gt;is... / has...&lt;/td&gt;
&lt;td style=&quot;height: 25px;&quot;&gt;boolean 반환 시&lt;/td&gt;
&lt;td style=&quot;height: 25px;&quot;&gt;isEmpty(), hasChildren()&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 25px;&quot;&gt;
&lt;td style=&quot;height: 25px;&quot;&gt;calculate...&lt;/td&gt;
&lt;td style=&quot;height: 25px;&quot;&gt;계산 기능&lt;/td&gt;
&lt;td style=&quot;height: 25px;&quot;&gt;calculateTax()&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 25px;&quot;&gt;
&lt;td style=&quot;height: 25px;&quot;&gt;find...&lt;/td&gt;
&lt;td style=&quot;height: 25px;&quot;&gt;탐색 기능&lt;/td&gt;
&lt;td style=&quot;height: 25px;&quot;&gt;findUserById()&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;메서드에 매개변수 및 인자 넣기&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;만약 Hello World를 1000번 해야한다고 했을 때 sayHelloWorldTwice 를 500번 적는다면 그건 상당한 고충일 것입니다.&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;매개변수와 인자는 아래에서 더 자세히 설명드리겠습니다  &lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;void sayHelloWorld(int num) {
        for (int i = 1 ; i &amp;lt;= num ; i++ ){
            System.out.println(&quot;Hello World&quot;);
}

sayHelloWorld(3)
//HelloWorld는 총 3번 출력된다&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;호출할 때 꼭! 인자를 넣어줘야 합니다&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;추가적으로 매개 변수를 전달하려면 메서드 안에 있는 &lt;b&gt;인수 타입을 꼭 맞춰줘야 해요&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span&gt;⚠️&lt;/span&gt; 인자가 없거나 타입이 맞지 않을 때&lt;/h4&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;Main.java:21: error: method printSquaresOfNumbers in class Main cannot be applied to given types;
        printSquaresOfNumbers();
        ^
  required: int
  found:    no arguments
  reason: actual and formal argument lists differ in length
1 error

**이런식으로 오류가 뜬다**
---------------------------------------------------------------------------------------

Main.java:21: error: unclosed character literal
        sayHelloWorld('hi');
                              ^
Main.java:21: error: unclosed character literal
        sayHelloWorld('hi');
                                 ^
Main.java:21: error: not a statement
        sayHelloWorld('hi');
                                ^
3 errors

**타입이 안맞는 경우에도 그럼** 
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;매개 변수 그리고 인자 소개&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;매개변수(Parameters)&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;void sayHelloWorld(int num) 처럼 함수를 선언할 때 들어가는 변수를 매개변수라고 불러요&lt;/li&gt;
&lt;li&gt;즉, &lt;b&gt;매개변수는 메서드 코드 내에서 사용하는거죠&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;인자 (Arguments)&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;sayHelloWorld(3) 메서드 호출할 때 전달하는 것을 인자라고 해요&lt;/li&gt;
&lt;li&gt;즉, &lt;b&gt;메서드를 호출할 때 인자를 전달하는거죠&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;메서드 오버로딩&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;한 클래스 내에 똑같은 메서드 이름으로써 다른 역할을 하는 메서드를 뜻&lt;/b&gt;해요&lt;/li&gt;
&lt;li&gt;대부분 매개 변수의 유무로 메서드를 달리하는 default 값으로 주로 사용합니다!
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;JS, Python과 달리 default 값을 메서드를 사용해 지정해줘야 해요&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;예제&lt;/h4&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;//메서드 오버로딩
class Main {
    public static void prinMultiplicationTable() {
        for (int i = 1 ; i &amp;lt;= 10 ; i++ ){
            System.out.printf(&quot;%d * %d = %d&quot;, 5,i, 5 *i).println();
        }
    }
    public static void prinMultiplicationTable(int table) {
        for (int i = 1 ; i &amp;lt;= 10 ; i++ ){
            System.out.printf(&quot;%d * %d = %d&quot;, table,i, table *i).println();
        }
    }
    public static void main(String[] args) {
        prinMultiplicationTable(6);
        prinMultiplicationTable();
    }
}

//매개 변수가 없는, 기본값인 5단을 출력하는 메서드를 부를 수 잇고 아니면 매개 변수를 전달할 수 도 있다
//여기서 매개 변수의 유무도 다른 똑같은 이름의 두 개의 메서드를 만든 것&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;여러 개의 매개변수를 자바 메소드로 전달하기&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;지금까지 배우면서 매개변수가 한 개라니 불편하지 않으셨나요?&lt;/li&gt;
&lt;li&gt;다른 언어들과 같이 매개변수는 여러 개를 넣을 수 있어요&lt;/li&gt;
&lt;li&gt;아래 예제를 통해 함께 배워봐요!&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;예제&lt;/h4&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;// 여러 개의 매개변수를 자바 메소드로 전달하기 
sum(int a, int b) {
     System.out.println(a + b);
} 
sum(5,6) //11&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;이때도 타입은 꼭 필수로 명시해주셔야 합니다&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;메서드 값 반환하기&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;호출하는 메서드에 계산 결과를 반환하는데에 사용됩니다&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;글로만 보면 어려우실 수 있는데 아래 예제를 보면서 함께 이해해봐요&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;예제&lt;/h4&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;int sumOfTwoNumbers(int fristNumber, int secondNumber){
        int sum = fristNumber + secondNumber;
        return sum;
}
sumOfTwoNumbers(1,1); //반환 값이기때문에 출력은 안된다

int sumOfThirdNumbers = sumOfTwoNumbers + 1;
System.out.print(sumOfThirdNumbers);

// 3 출력&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;int sumOfThirdNumbers = sumOfTwoNumbers + 1; 이 코드를 분해 해봤을 때,
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;sumOfTwoNumbers 는 메서드입니다. 하지만 return 즉, sum을 반환 했기에 sumOfTwoNumbers는 인수 2개에 의해서 결국 2가 되었습니다.&lt;/li&gt;
&lt;li&gt;그리고 나서 2 + 1 을 했으니 결국 sumOfThirdNumbers 는 3이 된거죠&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;오늘의 예제&lt;/h2&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;// 코드 예시

class Main {

		// 세 개의 수를 더하기 
    public static int sumOfThreeNumbers(int firstNumber, int secondNumber, int thirdNumber){
        int sum = firstNumber + secondNumber + thirdNumber;
        return sum;
    }
    
    // 삼각형의 마지막 각 구하기 
    public static int calculateThirdAngle(int firstAngle, int secondAngle){
        int thirdAngle = 180 - (firstAngle + secondAngle);
        return thirdAngle;
    }
    
    public static void main(String[] args) {
        System.out.println(sumOfThreeNumbers(1, 1, 3));
        System.out.println(calculateThirdAngle(50, 70));
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;계산 결과는 무엇일까요??&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  참고 자료&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://namu.wiki/w/%EA%B0%9D%EC%B2%B4%20%EC%A7%80%ED%96%A5%20%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://namu.wiki/w/%EA%B0%9D%EC%B2%B4%20%EC%A7%80%ED%96%A5%20%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://peemangit.tistory.com/389&quot;&gt;https://peemangit.tistory.com/389&lt;/a&gt;&lt;/p&gt;</description>
      <category>Back-end/Java</category>
      <category>Java_공부</category>
      <category>Java_기초</category>
      <category>Java_메서드</category>
      <category>Java_문법</category>
      <category>Til</category>
      <category>TIL_Java</category>
      <category>TIL_Method</category>
      <category>개발기록</category>
      <category>자바공부</category>
      <category>프로그래밍기초</category>
      <author>dev_Hyeonjoon</author>
      <guid isPermaLink="true">https://joon0112.tistory.com/43</guid>
      <comments>https://joon0112.tistory.com/43#entry43comment</comments>
      <pubDate>Tue, 7 Oct 2025 15:45:55 +0900</pubDate>
    </item>
    <item>
      <title>[TIL] 자바 IF 조건문 그리고 For 반복문</title>
      <link>https://joon0112.tistory.com/42</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;  IF 조건문&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;if 조건문은 조건식의 결과가 &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;조건은 무조건 &lt;b&gt;불리언 값&lt;/b&gt;만 가능하다&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;else는 거짓일 때 실행 조건을 가르킨다&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;if 예제&lt;/h3&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;if (조건) 문&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;위에 코드의 경우 문이 한 줄일 때 밖에 쓰지 못 합니다&lt;/li&gt;
&lt;li&gt;조건이 true일 시 문이 실행됩니다&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;/ul&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;int a = 1;
if (a &amp;gt;= 1) {
	System.out.println(&quot;True&quot;);
}&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;문이 여러 개일때 사용됩니다&lt;/li&gt;
&lt;li&gt;가독성 및 유지 보수에 용이&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;if- else&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;조건을 딱 한번만 확인해도 될 때&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;int a = 1;
if (a &amp;gt;= 1) {
	System.out.println(&quot;True&quot;);
} else {
  // 거짓일 때 실행될 문
  System.out.println(&quot;false&quot;);
}&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;만약 if에서 거짓이 될 시에 else로 바로 이동합니다!&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;else if&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;조건이 복수로 확인이 필요할 때&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;int a = 1;
if (a &amp;gt;= 1) {
	System.out.println(&quot;a는 양수입니다.&quot;);
} else if (a &amp;lt;= -1) {
  // 거짓일 때 실행될 문
  System.out.println(&quot;a는 음수 입니다.&quot;);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;else if는 개수 제한이 없으며 위에서 아래로 순차적으로 계산하며 내려갑니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;else if - else&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;els&lt;b&gt;e if 가 끝났는데도 불구하고 false 일 때&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;int a = 1;
if (a &amp;gt;= 1) {
	System.out.println(&quot;a는 양수입니다.&quot;);
} else if (a &amp;lt;= -1) {
  // 거짓일 때 실행될 문
  System.out.println(&quot;a는 음수 입니다.&quot;);
} else {
	 System.out.println(&quot;a는 0 입니다.&quot;);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  for 반복문&lt;/h2&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;//반복문
for(initialisation; condition; update) {
		statement;
	}&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;for 반복문에서 가장 중요한 부분은 &lt;b&gt;조건을 설정&lt;/b&gt;하는 것입니다&lt;/li&gt;
&lt;li&gt;반복문에는 우선 &lt;b&gt;초기치 설정, 조건, 업데이트를 입력해야 합니다&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;조건이 fasle 일 경우 for는 바로 멈춥니다&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;for 반복문 예제&lt;/h3&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;//반복문 예시
for(int i=1; i&amp;lt;=10; i++){
	System.out.printf(&quot;%d * %d = %d&quot;, 5, i, 5*i).println();
}&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;반복문이 실행될 때 초기치 설정은 단 한번만 실행됩니다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;반복문이 실행될 시 i는 1이라는 값을 배정받고 초기치 설정은 반복문이 끝날 때까지 실행x&lt;/li&gt;
&lt;li&gt;***처음*** 초기치 설정 -&amp;gt; 조건절 실행 -&amp;gt; 문 실행 -&amp;gt; 업데이트 실행 ***그 후 ~ 끝날 때까지 *** 조건절 실행 -&amp;gt; 문 실행 -&amp;gt; 업데이트 실행&lt;/li&gt;
&lt;li&gt;위를 예시로 만약 반복문이 10번 실행된다면 초기치 설정은 한 번만 실행되지만, 업데이트는 9번 실행된다&lt;/li&gt;
&lt;li&gt;그런데 여기서 명심해야 할 점은 &lt;b&gt;조건은 항상 실행&lt;/b&gt;된다는 것&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;for 반복문의 빈 문&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;말 그대로 &amp;ldquo;비어 있는 문&amp;rdquo;&lt;/li&gt;
&lt;li&gt;for 반복문에는 초기치 와 조건 그리고 업데이트 하는 자리를 비워둘 수 있습니다&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;for ( ; i&amp;lt;=10 ; i++);&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;for 빈 문을 사용하여 무한 반복 시키기&lt;/h3&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;for ( ; ; ;)&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;조건은 항상 참이니까 무한 반복&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;for 반복문에 복수 개의 식 넣기&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;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;int j = 0
for (i=1, j=2 ; i &amp;lt;= 10; i++, j++);  // i == 11 , j == 12
// 그러나 조건은 한 개 밖에 안됩니다.&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;반복문 예제 (별 찍어보기)&lt;/h2&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;// 코드 예시
package project;

public class Main {
    public static void main(String[] args) {
        int j=0;
        for(int i=1;i&amp;lt;=5;i++){
            for(j=0; j&amp;lt;i; j++){
                System.out.print(&quot;* &quot;);
            }
            System.out.println();
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;출력 결과:&lt;/p&gt;
&lt;pre id=&quot;code_1759756134002&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;* 
* * 
* * * 
* * * * 
* * * * *&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;추가 개념&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;리터럴&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;리터럴은 숫자 값을 의미합니다.&lt;/li&gt;
&lt;li&gt;7은 정수 리터럴이고 7.5는 소수 리터럴로 나눠집니다&lt;/li&gt;
&lt;li&gt;정수 리터럴은 int 타입이며 소수 리터럴은 double 타입니다&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;식&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;table * i 처럼 * 연산자와 두 오퍼랜드가 있을 때 *로 둘을 곱하는 건데, 이걸 통틀어서 식이라고 한다&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;1+1 = 2&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;문&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;명령을 실행하라는 코드 조각&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;즉, &amp;ldquo;무엇을 하라&amp;rdquo;는 지시를 담고 있습니다&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;int i = 0;, if(...) {...}, for(...) {...}&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  생각해보기&lt;/h2&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;for 문과 if 문은 언제 쓰일까요?&lt;/li&gt;
&lt;li&gt;for 문을 배우기 전 if문을 먼저 배운 이유가 뭘까요?&lt;/li&gt;
&lt;li&gt;별을 찍는 과정에서 바깥 반복문과 안쪽 반복문은 어떤 역할을 할까요?&lt;/li&gt;
&lt;li&gt;for 문 안에서 if 문을 사용해 짝수만 출력하는 프로그램을 만들어보세요.&lt;/li&gt;
&lt;/ol&gt;</description>
      <category>Back-end/Java</category>
      <category>For문</category>
      <category>if문</category>
      <category>Java</category>
      <category>Til</category>
      <category>반복문</category>
      <category>자바</category>
      <category>자바 공부</category>
      <category>자바 문법</category>
      <category>자바 예제</category>
      <category>조건문</category>
      <author>dev_Hyeonjoon</author>
      <guid isPermaLink="true">https://joon0112.tistory.com/42</guid>
      <comments>https://joon0112.tistory.com/42#entry42comment</comments>
      <pubDate>Mon, 6 Oct 2025 22:07:32 +0900</pubDate>
    </item>
    <item>
      <title>[TIL] 자바 변수 이해하기</title>
      <link>https://joon0112.tistory.com/41</link>
      <description>&lt;h2 style=&quot;text-align: left;&quot; data-ke-size=&quot;size26&quot;&gt;변수란?&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터를 저장하기 위한 메모리 공간에 붙인 이름이에요&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;값이 변할 수 있기 때문에 &amp;lsquo;변수&amp;rsquo; 라고 불립니다.&lt;/li&gt;
&lt;li&gt;마치 이사할 때, &quot;이 상자에는 책만 담을 거야&quot;, &quot;이 상자에는 옷만 넣을 거야&quot;라고 이름표를 붙이는 것과 같아요. 덕분에 컴퓨터는 데이터를 훨씬 효율적으로 관리할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;자바와 자바스크립트의 변수 차이&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;가장 큰 차이점은 &lt;b&gt;타입을 지정하는 방식&lt;/b&gt;이에요&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 style=&quot;text-align: left;&quot; data-ke-size=&quot;size20&quot;&gt;자바 (Java) ☕: 정적 타입 언어 (Static Typing)&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;변수를 선언할 때 반드시 int, String과 같이 &lt;b&gt;어떤 종류의 데이터가 들어갈지 타입을 명시&lt;/b&gt;해야 합니다. 한번 타입이 정해지면 다른 타입의 값은 저장할 수 없어 코드의 안정성이 높습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;int number = 10;
// number = &quot;hello&quot;; // 에러 발생! int 타입 변수에 문자열을 넣을 수 없음&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;  핵심: 변수를 만들기 전에 어떤 데이터를 담을지 먼저 고민하고, 그에 맞는 '타입'을 고르는 습관을 들여야 합니다!&lt;/b&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4 style=&quot;text-align: left;&quot; data-ke-size=&quot;size20&quot;&gt;자바스크립트 (JavaScript)  : 동적 타입 언어 (Dynamic Typing)&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;변수를 선언할 때 타입을 지정하지 않고 let, const, var 같은 키워드만 사용합니다. 변수의 타입은 &lt;b&gt;값이 할당될 때 결정&lt;/b&gt;되며, 실행 중에 다른 타입의 값으로 변경할 수 있어 유연성이 높습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1759651850078&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;let data = 10; // data는 숫자(Number) 타입이 됨 data = &quot;hello&quot;; // 가능! data는 이제 문자열(String) 타입이 됨&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 style=&quot;text-align: left;&quot; data-ke-size=&quot;size26&quot;&gt;변수 종류&lt;/h2&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;변수는 크게 값이 직접 저장되는 &lt;b&gt;기본형(Primitive Type)&lt;/b&gt;과, 값이 저장된 곳의 주소가 저장되는 &lt;b&gt;참조형(Reference Type)&lt;/b&gt; 으로 나뉩니다.&lt;/p&gt;
&lt;h3 style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;기본형(primivite type)&lt;/h3&gt;
&lt;h4 style=&quot;text-align: left;&quot; data-ke-size=&quot;size20&quot;&gt;문자형&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #dddddd; color: #ef5369;&quot;&gt;char:&lt;/span&gt; 한 개의 문자(2byte)를 저장합니다. 작은따옴표(' ')로 값을 감쌉니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 style=&quot;text-align: left;&quot; data-ke-size=&quot;size20&quot;&gt;정수형&lt;span style=&quot;background-color: #dddddd; color: #ef5369;&quot;&gt; byte, short, int, long&lt;/span&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;소수점 없는 숫자&lt;/b&gt; 저장.&lt;/li&gt;
&lt;li&gt;크기에 따라 메모리 차이가 다름.&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;타입 크기 표현 범위&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;byte&lt;/td&gt;
&lt;td&gt;1바이트&lt;/td&gt;
&lt;td&gt;-128 ~ 127&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;short&lt;/td&gt;
&lt;td&gt;2바이트&lt;/td&gt;
&lt;td&gt;-32,768 ~ 32,767&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;int&lt;/td&gt;
&lt;td&gt;4바이트&lt;/td&gt;
&lt;td&gt;약 -21억 ~ 21억&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;long&lt;/td&gt;
&lt;td&gt;8바이트&lt;/td&gt;
&lt;td&gt;아주 큰 정수 (끝에 L 붙임)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;int age = 21;
long population = 8000000000L;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;실수형 &lt;span style=&quot;background-color: #dddddd; color: #ef5369;&quot;&gt;float, double&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; 저장.&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;타입 크기 비고&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;float&lt;/td&gt;
&lt;td&gt;4바이트&lt;/td&gt;
&lt;td&gt;끝에 F 붙임 (3.14F)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;double&lt;/td&gt;
&lt;td&gt;8바이트&lt;/td&gt;
&lt;td&gt;기본 실수 타입 (3.14)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;float pi = 3.14F;
double avg = 93.7;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;논리형 &lt;span style=&quot;background-color: #dddddd; color: #ef5369;&quot;&gt;boolean&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;true 또는 false 두 값만 가짐.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;boolean isStudent = true;
boolean hasLicense = false;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 style=&quot;text-align: left;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;참조형 (Reference Type)&lt;/b&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;객체(Object)&lt;/b&gt;의 주소를 저장.&lt;/li&gt;
&lt;li&gt;기본형처럼 값을 직접 저장하는 게 아니라, 실제 데이터가 저장된 공간의 위치(주소)를 가리킴.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;String name = &quot;Hyeonjun's code&quot;;
int[] scores = {90, 85, 100};&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;⚡ String은 사실 &amp;lsquo;문자 배열&amp;rsquo;(char[])을 감싸는 참조형 객체예요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;Hello&quot;라는 문자열 자체가 아닌, 그 문자열이 저장된 &lt;b&gt;위치&lt;/b&gt;를 가리키는 거죠&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 style=&quot;text-align: left;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt; ️ 변수 명명 규칙 (Naming Rules)&lt;/b&gt;&lt;/h2&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;자바에서는 변수 이름에도 철저한 규칙이 있습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;가독성과 유지보수를 위해 꼭 지켜야 해요.&lt;/p&gt;
&lt;h3 style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;✅ 필수 규칙&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;영문자, 숫자, _, $만 사용 가능&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;숫자로 시작할 수 없음&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;공백, 특수문자(@, #, ! 등) 불가능&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;대소문자 구분함 (age &amp;ne; Age)&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;예약어 사용 금지&lt;/b&gt; (class, if, for 등)&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;✨ 권장 컨벤션&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;camelCase 사용&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;예: studentName, totalScore&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;x, y보다는 age, height, userName&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;boolean은 is/has로 시작&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;isLoggedIn, hasLicense&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;final double PI = 3.14159;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;  요약&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자바의 변수는 &amp;ldquo;타입이 있는 상자&amp;rdquo;이고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 상자를 만들 때 이름 붙이는 법(규칙)까지 정해져 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;초반엔 복잡하지만, 익숙해지면 훨씬 안정적인 코드 작성이 가능해진다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Back-end/Java</category>
      <category>Til</category>
      <category>사지방</category>
      <category>사지방코딩</category>
      <category>자바</category>
      <author>dev_Hyeonjoon</author>
      <guid isPermaLink="true">https://joon0112.tistory.com/41</guid>
      <comments>https://joon0112.tistory.com/41#entry41comment</comments>
      <pubDate>Sun, 5 Oct 2025 17:07:28 +0900</pubDate>
    </item>
    <item>
      <title>햄버거 메뉴 만들기 [리액트+ vite + tailwindCSS v.4.1]</title>
      <link>https://joon0112.tistory.com/40</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;380&quot; data-origin-height=&quot;62&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kX96v/btsQPoVRGCv/lZ5OFcXXKhjvUr22T7eChk/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kX96v/btsQPoVRGCv/lZ5OFcXXKhjvUr22T7eChk/img.webp&quot; data-alt=&quot;햄버거 닫힘&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kX96v/btsQPoVRGCv/lZ5OFcXXKhjvUr22T7eChk/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkX96v%2FbtsQPoVRGCv%2FlZ5OFcXXKhjvUr22T7eChk%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;380&quot; height=&quot;62&quot; data-origin-width=&quot;380&quot; data-origin-height=&quot;62&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;햄버거 닫힘&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;373&quot; data-origin-height=&quot;209&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b7HbwC/btsQM0vfTyw/D3BYwqpFliYfENZqWEJSp0/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b7HbwC/btsQM0vfTyw/D3BYwqpFliYfENZqWEJSp0/img.webp&quot; data-alt=&quot;햄버거 열림&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b7HbwC/btsQM0vfTyw/D3BYwqpFliYfENZqWEJSp0/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb7HbwC%2FbtsQM0vfTyw%2FD3BYwqpFliYfENZqWEJSp0%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;373&quot; height=&quot;209&quot; data-origin-width=&quot;373&quot; data-origin-height=&quot;209&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;햄버거 열림&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  만들게 된 이유&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;읽잇(Readit) 프로젝트를 진행하다 보니, 반응형 UI가 꼭 필요하다는 생각이 들었습니다. 특히 기존 NavBar가 모바일 화면에서는 자리를 많이 차지해서 이용하기가 불편했죠. 그래서&amp;nbsp;&lt;b&gt;&lt;span data-token-index=&quot;1&quot;&gt;TailwindCSS&lt;/span&gt;&lt;/b&gt;를 활용해 반응형 레이아웃을 만들었고, 모바일에서는&amp;nbsp;&lt;b&gt;&lt;span data-token-index=&quot;3&quot;&gt;햄버거 메뉴&lt;/span&gt;&lt;/b&gt;를 적용해&amp;nbsp;&lt;b&gt;&lt;span data-token-index=&quot;5&quot;&gt;더 편리하게&lt;/span&gt;&lt;/b&gt;&amp;nbsp;사용할 수 있도록 했습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  햄버거 메뉴 구현 해보기&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. 가장 중요한 부분 (상태 정리하기)&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;가장 중요한 부분은 상태를 사용해 햄버거 창이 열렸는지 안열렸지는 알려주는 &lt;b&gt;useState &lt;/b&gt;아닐까? 라는 생각에 가장 중요한 부분으로 뽑아봤습니다!&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;전제&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;닫힘&lt;/b&gt;: 메뉴가 숨겨져 있을 때 (false)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;열림&lt;/b&gt;: 메뉴가 화면에 보일 때 (true)&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;const [isOpen, setIsOpen] = useState(false);&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;isOpen: 현재 메뉴의 상태를 알려주는 변수. 지금은 false니까 &amp;ldquo;&lt;b&gt;메뉴가 닫혀 있어!&lt;/b&gt;&quot;라고 말해주는 거죠.&lt;/li&gt;
&lt;li&gt;setIsOpen: isOpen의 상태를 &lt;b&gt;바꿔주는 스위치&lt;/b&gt;. 이 스위치를 누르면 isOpen의 값이 true로 바뀌면서 &quot;메뉴가 열렸어!&quot;라고 알려줘요.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. 함수 만들기&lt;/h3&gt;
&lt;pre class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;const toggleMenu = () =&amp;gt; {
    setIsOpen(!isOpen);
  };&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;함수를 실행시키면 isOpen을 &lt;b&gt;Not&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;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. 함수와 버튼 연결하기&lt;/h3&gt;
&lt;pre class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;&amp;lt;button
  onClick={toggleMenu}
  className=&quot;md:hidden focus:outline-none&quot;
&amp;gt;
  {/* ...SVG 아이콘들... */}
&amp;lt;/button&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;onClick={toggleMenu}: 이 코드가 바로 스위치를 연결하는 부분이에요. toggleMenu 함수는 isOpen 상태를 true와 false 사이에서 바꿔주는 역할을 해요.
&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; isOpen은 false에서 true로 바뀌고,&lt;/li&gt;
&lt;li&gt;&lt;b&gt;다시 누르면&lt;/b&gt; true에서 false로 바뀌죠.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;그리고 그 아래에 있는 복잡한 &amp;lt;svg&amp;gt; 코드는 isOpen 상태에 따라 햄버거 모양(false)과 닫기 버튼 모양(true)을 보여주는 역할을 합니다.
&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;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4. 메뉴 내용 숨겼다 보여주기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rArr; 마지막으로, 메뉴 내용 자체를 isOpen 상태에 따라 숨기거나 보여주는 거예요.&lt;/p&gt;
&lt;pre class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;&amp;lt;ul className={`${isOpen ? 'block' : 'hidden'} md:hidden w-full ...`}&amp;gt;
  {/* ...메뉴 내용들... */}
&amp;lt;/ul&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;className=&quot;...&quot;: 이 부분에서 CSS 클래스를 &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;isOpen ? 'block' : 'hidden': 삼항 연산자를 사용해서 만약 isOpen이 true라면 'block' 클래스를 넣어서 메뉴를 &lt;b&gt;보여주고&lt;/b&gt;, false라면 'hidden' 클래스를 넣어서 &lt;b&gt;숨깁니다&lt;/b&gt;.&lt;/li&gt;
&lt;li&gt;md:hidden: 이 클래스는 화면이 태블릿(md) 크기보다 커지면 메뉴를 아예 숨겨버립니다. 그래서 모바일에서만 햄버거 메뉴가 작동하는 거죠.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;정리&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;상태 블록&lt;/b&gt;: isOpen이라는 변수가 &quot;&lt;b&gt;메뉴가 닫혔어요&lt;/b&gt;&quot;라고 말해줘요.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;버튼 블록&lt;/b&gt;: 사용자가 햄버거 버튼을 누르면, isOpen의 상태가 &quot;&lt;b&gt;메뉴가 열렸어요!&quot;&lt;/b&gt;로 바뀝니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;메뉴 블록&lt;/b&gt;: isOpen의 상태가 바뀌는 것을 감지하고, &lt;b&gt;숨겨져 있던 메뉴가 나타납니다&lt;/b&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;예제 코드&lt;/h4&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;import React, { useState } from 'react';
import { Link } from 'react-router-dom';
import nav_logo from '../images/nav_logo.png';
import './Nav.css';

function Nav() {
  const [isOpen, setIsOpen] = useState(false);

  const toggleMenu = () =&amp;gt; {
    setIsOpen(!isOpen);
  };

  return (
    &amp;lt;&amp;gt;
      &amp;lt;nav className=&quot;flex justify-between items-center h-12 lg:h-24 max-w-[21.875rem] lg:max-w-[75.00rem] my-2 m-auto py-0 px-2 lg:px-6 border-b border-gray-1&quot;&amp;gt;
        &amp;lt;Link to=&quot;/&quot;&amp;gt;
          &amp;lt;img src={nav_logo} alt=&quot;로고 사진&quot; className=&quot;w-[150px] mb-[5px] lg:w-[200px] h-auto flex&quot; /&amp;gt;
        &amp;lt;/Link&amp;gt;
        
        {/* 데스크톱 메뉴 (md: 이상 화면에서 보임) */}
        &amp;lt;ul className=&quot;hidden md:flex gap-12 items-center font-bold text-base leading-[1.2]&quot;&amp;gt;
          &amp;lt;li&amp;gt;
            &amp;lt;Link to=&quot;/about&quot; className=&quot;hover:text-gray-600 transition-colors&quot;&amp;gt;
              &amp;lt;span&amp;gt;소개 &amp;lt;sup&amp;gt;01&amp;lt;/sup&amp;gt;&amp;lt;/span&amp;gt;
            &amp;lt;/Link&amp;gt;
          &amp;lt;/li&amp;gt;
          &amp;lt;li&amp;gt;
            &amp;lt;Link to=&quot;/bookcase&quot; className=&quot;hover:text-gray-600 transition-colors&quot;&amp;gt;
              &amp;lt;span&amp;gt;책장 &amp;lt;sup&amp;gt;02&amp;lt;/sup&amp;gt;&amp;lt;/span&amp;gt;
            &amp;lt;/Link&amp;gt;
          &amp;lt;/li&amp;gt;
          &amp;lt;li&amp;gt;
            &amp;lt;Link to=&quot;/contact&quot; className=&quot;hover:text-gray-600 transition-colors&quot;&amp;gt;
              &amp;lt;span&amp;gt;문의 &amp;lt;sup&amp;gt;03&amp;lt;/sup&amp;gt;&amp;lt;/span&amp;gt;
            &amp;lt;/Link&amp;gt;
          &amp;lt;/li&amp;gt;
        &amp;lt;/ul&amp;gt;

        {/* 햄버거 버튼 (모바일에서만 보임) */}
        &amp;lt;button
          onClick={toggleMenu}
          className=&quot;md:hidden focus:outline-none&quot;
        &amp;gt;
          {/* 메뉴가 닫혔을 때 (햄버거 아이콘) */}
          {!isOpen ? (
            &amp;lt;svg className=&quot;w-6 h-6 text-gray-800&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; viewBox=&quot;0 0 24 24&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&amp;gt;
              &amp;lt;path strokeLinecap=&quot;round&quot; strokeLinejoin=&quot;round&quot; strokeWidth=&quot;2&quot; d=&quot;M4 6h16M4 12h16M4 18h16&quot;&amp;gt;&amp;lt;/path&amp;gt;
            &amp;lt;/svg&amp;gt;
          ) : (
            /* 메뉴가 열렸을 때 (X 아이콘) */
            &amp;lt;svg className=&quot;w-6 h-6 text-gray-800&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; viewBox=&quot;0 0 24 24&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&amp;gt;
              &amp;lt;path strokeLinecap=&quot;round&quot; strokeLinejoin=&quot;round&quot; strokeWidth=&quot;2&quot; d=&quot;M6 18L18 6M6 6l12 12&quot;&amp;gt;&amp;lt;/path&amp;gt;
            &amp;lt;/svg&amp;gt;
          )}
        &amp;lt;/button&amp;gt;
      &amp;lt;/nav&amp;gt;

      {/* 모바일 드롭다운 메뉴 */}
      {/* isOpen 상태에 따라 메뉴를 보여주거나 숨깁니다. */}
      {/* md: 이상 화면에서는 항상 숨깁니다. */}
      &amp;lt;ul className={`${isOpen ? 'block' : 'hidden'} md:hidden w-full max-w-[21.875rem] m-auto py-0 px-2 lg:px-6`}&amp;gt;
        &amp;lt;li className=&quot;py-3 px-2 border-b border-gray-1&quot;&amp;gt;
          &amp;lt;Link to=&quot;/about&quot; onClick={toggleMenu} className=&quot;block text-gray-800&quot;&amp;gt;
            &amp;lt;span&amp;gt;소개 &amp;lt;sup&amp;gt;01&amp;lt;/sup&amp;gt;&amp;lt;/span&amp;gt;
          &amp;lt;/Link&amp;gt;
        &amp;lt;/li&amp;gt;
        &amp;lt;li className=&quot;py-3 px-2 border-b border-gray-1&quot;&amp;gt;
          &amp;lt;Link to=&quot;/bookcase&quot; onClick={toggleMenu} className=&quot;block text-gray-800&quot;&amp;gt;
            &amp;lt;span&amp;gt;책장 &amp;lt;sup&amp;gt;02&amp;lt;/sup&amp;gt;&amp;lt;/span&amp;gt;
          &amp;lt;/Link&amp;gt;
        &amp;lt;/li&amp;gt;
        &amp;lt;li className=&quot;py-3 px-2 border-b border-gray-1&quot;&amp;gt;
          &amp;lt;Link to=&quot;/contact&quot; onClick={toggleMenu} className=&quot;block text-gray-800&quot;&amp;gt;
            &amp;lt;span&amp;gt;문의 &amp;lt;sup&amp;gt;03&amp;lt;/sup&amp;gt;&amp;lt;/span&amp;gt;
          &amp;lt;/Link&amp;gt;
        &amp;lt;/li&amp;gt;
      &amp;lt;/ul&amp;gt;
    &amp;lt;/&amp;gt;
  );
}

export default Nav;&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;➕ 추가) SVG 구현 부분에 대해서&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 코드는 'Scalable Vector Graphics'의 약자인 &lt;b&gt;SVG&lt;/b&gt;라는 웹 기술로 만들어진 이미지 파일이에요. 즉, 햄버거 메뉴 아이콘을 &lt;b&gt;글자처럼 코드 한 줄로 그린 것&lt;/b&gt;이라고 생각하시면 돼요.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;핵심은 &amp;lt;path&amp;gt; 태그예요.&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&amp;lt;svg&amp;gt;: SVG 이미지의 시작을 알리는 태그.&lt;/li&gt;
&lt;li&gt;&amp;lt;path&amp;gt;: 선(line)이나 곡선(curve)을 그려서 도형을 만드는 태그예요.&lt;/li&gt;
&lt;li&gt;d=&quot;M6 18L18 6M6 6l12 12&quot;: 이 부분이 그림을 그리는 실제 &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;M: &lt;b&gt;M&lt;/b&gt;ove to (펜을 이동).&lt;/li&gt;
&lt;li&gt;L: &lt;b&gt;L&lt;/b&gt;ine to (선 그리기).&lt;/li&gt;
&lt;li&gt;d 속성 안의 복잡한 문자들은 **'어떤 좌표로 이동해서 어디까지 선을 그려라'**라고 명령하는 명령어들의 모음이에요.&lt;/li&gt;
&lt;li&gt;M6 18L18 6는 (6, 18) 지점에서 시작해서 (18, 6) 지점까지 선을 그으라는 뜻이고, M6 6l12 12는 (6, 6) 지점에서 시작해 (12, 12) 지점까지 선을 그으라는 뜻이죠. 이 두 개의 선을 합치면 바로 X자 모양이 됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;즉, &amp;lt;path&amp;gt; 태그가 아이콘의 모양을 만들고, 그 앞의 &amp;lt;svg&amp;gt; 태그는 아이콘을 담는 그릇 역할을 하는 거예요.&lt;/b&gt;&lt;/p&gt;</description>
      <category>Front-end/React-project</category>
      <category>리액트</category>
      <category>리액트햄버거메뉴</category>
      <category>테일윈드css</category>
      <category>테일윈드CSSv4.1</category>
      <category>프론트엔드</category>
      <category>햄버거메뉴</category>
      <author>dev_Hyeonjoon</author>
      <guid isPermaLink="true">https://joon0112.tistory.com/40</guid>
      <comments>https://joon0112.tistory.com/40#entry40comment</comments>
      <pubDate>Wed, 24 Sep 2025 18:34:57 +0900</pubDate>
    </item>
    <item>
      <title>사지방에서 풀 스택과 기획 그리고 배포까지 (읽잇 MVP 완성)</title>
      <link>https://joon0112.tistory.com/37</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;476510418-09ccd988-260a-4e34-a571-6a77f3264d0e.gif&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;365&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bt62MW/btsPVEMavGi/DKHcGViKmyAW2bAZK2Ajbk/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bt62MW/btsPVEMavGi/DKHcGViKmyAW2bAZK2Ajbk/img.gif&quot; data-alt=&quot;https://readit-38t1.onrender.com/&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bt62MW/btsPVEMavGi/DKHcGViKmyAW2bAZK2Ajbk/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/bt62MW/btsPVEMavGi/DKHcGViKmyAW2bAZK2Ajbk/img.gif&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;800&quot; height=&quot;365&quot; data-filename=&quot;476510418-09ccd988-260a-4e34-a571-6a77f3264d0e.gif&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;365&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://readit-38t1.onrender.com/&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;  &lt;b&gt;프로젝트 링크: &lt;/b&gt;&lt;a href=&quot;https://readit-38t1.onrender.com/&quot;&gt;https://readit-38t1.onrender.com/&lt;/a&gt;&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;프로젝트 개요&amp;nbsp;&lt;/h2&gt;
&lt;h3 style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span&gt; 시작 이유&amp;nbsp;&lt;/span&gt;&lt;/h3&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;그래서 &quot;기획 + 개발&quot;을 동시에 진행하는 &lt;b&gt;실전형 프로젝트&lt;/b&gt;를 시작했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;군대에서 책을 읽다 문득,&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;노션이 아니라, 내가 만든 웹사이트에서 간편하게 독서 기록을 남기면 어떨까?&quot;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;라는 아이디어가 떠올랐고, 바로 실행에 옮겼습니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;  프로젝트 목표&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt; &lt;/span&gt; 책 검색 &amp;amp; 감상문 기록이 가능한 &lt;span data-token-index=&quot;1&quot;&gt;개인 독서 기록 웹서비스&lt;/span&gt; 제작&lt;/li&gt;
&lt;li&gt;&lt;span&gt; &lt;/span&gt; &lt;span data-token-index=&quot;1&quot;&gt;React 기반 감성 UI&lt;/span&gt; 구현&lt;/li&gt;
&lt;li&gt;&lt;span&gt; &lt;/span&gt; 취업 포트폴리오 활용&lt;/li&gt;
&lt;li&gt;&lt;span&gt;⏳&lt;/span&gt; &lt;span data-token-index=&quot;1&quot;&gt;1달 내 MVP 완성&lt;/span&gt; + 단계별 확장성 확보&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt; 역할 및 기여 범위&lt;/span&gt;&lt;/h2&gt;
&lt;h3 style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span&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;처음 하는 기획이라 GPT를 활용해 아이디어를 구조화&lt;/li&gt;
&lt;li&gt;&lt;b&gt;MVP &lt;span data-token-index=&quot;0&quot;&gt;&amp;rarr;&lt;/span&gt; 구현&lt;/b&gt; 단계를 조정하며 노션에 기획안을 작성&lt;/li&gt;
&lt;li&gt;PM 역할에도 관심을 가지기 시작&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mAwPi/btsPVIA19r8/afYjSfsRookkR6WsdNwKl0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mAwPi/btsPVIA19r8/afYjSfsRookkR6WsdNwKl0/img.png&quot; data-origin-width=&quot;743&quot; data-origin-height=&quot;707&quot; data-is-animation=&quot;false&quot; style=&quot;width: 20.0399%; margin-right: 10px;&quot; data-widthpercent=&quot;20.28&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mAwPi/btsPVIA19r8/afYjSfsRookkR6WsdNwKl0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmAwPi%2FbtsPVIA19r8%2FafYjSfsRookkR6WsdNwKl0%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;743&quot; height=&quot;707&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bo4J8R/btsPVZ3SfNj/euiOWSYCXmo9uom2s1mV01/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bo4J8R/btsPVZ3SfNj/euiOWSYCXmo9uom2s1mV01/img.png&quot; data-origin-width=&quot;500&quot; data-origin-height=&quot;121&quot; data-is-animation=&quot;false&quot; data-widthpercent=&quot;79.72&quot; data-filename=&quot;blob&quot; style=&quot;width: 78.7973%;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bo4J8R/btsPVZ3SfNj/euiOWSYCXmo9uom2s1mV01/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbo4J8R%2FbtsPVZ3SfNj%2FeuiOWSYCXmo9uom2s1mV01%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;500&quot; height=&quot;121&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;저는 한번도 기획을 해본 적이 없기 때문에&amp;nbsp; GPT를 사용하여 저의 아이디어를 GPT 안에다가 넣었고 MVP와 구현 단계를 조절하며 이를 노션에 옮겨서 실행했습니다&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://stream-puffin-abd.notion.site/MVP-221e0b38263d806986abfecd3ed69fc9&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;(노션 페이지)&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;이런 기획 후에는 framer를 사용해 디자인을 했고 그 디자인한 걸 가지고 framer는 너무 익숙하지 않아서&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;Figma로 더 자세히 기획해봤습니다&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1240&quot; data-origin-height=&quot;701&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bXAZ21/btsPSrBlWhB/jl1khvdtyVk3tek6k9RxD0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bXAZ21/btsPSrBlWhB/jl1khvdtyVk3tek6k9RxD0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bXAZ21/btsPSrBlWhB/jl1khvdtyVk3tek6k9RxD0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbXAZ21%2FbtsPSrBlWhB%2Fjl1khvdtyVk3tek6k9RxD0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;600&quot; height=&quot;339&quot; data-origin-width=&quot;1240&quot; data-origin-height=&quot;701&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size14&quot;&gt;&lt;a href=&quot;https://www.figma.com/design/AnLqKMJhWCnoWmxwTJYg5y/%EC%9D%BD%EC%9E%87?node-id=0-1&amp;amp;p=f&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt; (피그마 보러 가기)&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;아직은 피그마가 어렵긴 하지만 점점 연습해서 PM도 관심을 가져볼 예정입니다!&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-style=&quot;style6&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;h3 style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span&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;React (Vite)&lt;/b&gt; 로 구현&lt;/li&gt;
&lt;li&gt;모르는 부분은 Gemini를 통해 학습 &amp;amp; 문제 해결&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-style=&quot;style6&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;h3 style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span&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;Naver Book API 사용 중, API Key 보안 문제 인지&lt;/li&gt;
&lt;li&gt;Node.js로 API 서버 구현 (Gemini 도움)&lt;/li&gt;
&lt;li&gt;(현재 기여율: 0%, Node.js 공부 중으로써 향후 확장 계획 있음)&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-style=&quot;style6&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt; &lt;/span&gt; 기술 스택과 아키텍처&lt;/h2&gt;
&lt;table id=&quot;221e0b38-263d-80f1-9fb5-ee1ea99b75cb&quot; style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr id=&quot;221e0b38-263d-80ac-b292-de6a7182a4fd&quot;&gt;
&lt;td id=&quot;_mfD&quot;&gt;구분&lt;/td&gt;
&lt;td id=&quot;CpJh&quot;&gt;기술&lt;/td&gt;
&lt;td id=&quot;zQ{\&quot;&gt;비고&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id=&quot;221e0b38-263d-801c-80dd-eccfce286ba1&quot;&gt;
&lt;td id=&quot;_mfD&quot;&gt;프레임워크&lt;/td&gt;
&lt;td id=&quot;CpJh&quot;&gt;React (vite)&lt;/td&gt;
&lt;td id=&quot;zQ{\&quot;&gt;사지방+구름IDE에서 CRA보다 쾌적&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id=&quot;221e0b38-263d-809a-ba8b-f3471757d42f&quot;&gt;
&lt;td id=&quot;_mfD&quot;&gt;스타일링&lt;/td&gt;
&lt;td id=&quot;CpJh&quot;&gt;기본 CSS + CSS Modules&lt;/td&gt;
&lt;td id=&quot;zQ{\&quot;&gt;점진적 적용&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id=&quot;221e0b38-263d-803e-8a15-e935047fdf89&quot;&gt;
&lt;td id=&quot;_mfD&quot;&gt;디자인&lt;/td&gt;
&lt;td id=&quot;CpJh&quot;&gt;Framer 디자인을 handoff 받아 수작업 적용&lt;/td&gt;
&lt;td id=&quot;zQ{\&quot;&gt;완성도 높은 UI&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id=&quot;221e0b38-263d-80e4-8d80-e5a7cff30fef&quot;&gt;
&lt;td id=&quot;_mfD&quot;&gt;API&lt;/td&gt;
&lt;td id=&quot;CpJh&quot;&gt;Naver Books API&lt;/td&gt;
&lt;td id=&quot;zQ{\&quot;&gt;책 검색 기능&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id=&quot;221e0b38-263d-80ff-9513-d7f48c0f6f8c&quot;&gt;
&lt;td id=&quot;_mfD&quot;&gt;상태 관리&lt;/td&gt;
&lt;td id=&quot;CpJh&quot;&gt;useState / localStorage&lt;/td&gt;
&lt;td id=&quot;zQ{\&quot;&gt;DB 없이 MVP 가능&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id=&quot;221e0b38-263d-8078-8dcd-ecf251a9d86f&quot;&gt;
&lt;td id=&quot;_mfD&quot;&gt;배포&lt;/td&gt;
&lt;td id=&quot;CpJh&quot;&gt;Render&lt;/td&gt;
&lt;td id=&quot;zQ{\&quot;&gt;1클릭 배포 가능&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id=&quot;250e0b38-263d-8072-9700-c678f7b7782c&quot;&gt;
&lt;td id=&quot;_mfD&quot;&gt;검색 엔진&lt;/td&gt;
&lt;td id=&quot;CpJh&quot;&gt;naver search advisor, google search console&lt;/td&gt;
&lt;td id=&quot;zQ{\&quot;&gt;검색 가능&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-style=&quot;style6&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;주요 기능&lt;/h2&gt;
&lt;h3 style=&quot;text-align: center;&quot; data-ke-size=&quot;size23&quot;&gt;LocalStorage를 활용한 책 데이터 CRUD&amp;nbsp;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;920&quot; data-origin-height=&quot;793&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bLxf7H/btsPVBhDfnf/5bY5OCgTnQzDerdSacIcfK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bLxf7H/btsPVBhDfnf/5bY5OCgTnQzDerdSacIcfK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bLxf7H/btsPVBhDfnf/5bY5OCgTnQzDerdSacIcfK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbLxf7H%2FbtsPVBhDfnf%2F5bY5OCgTnQzDerdSacIcfK%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;920&quot; height=&quot;793&quot; data-origin-width=&quot;920&quot; data-origin-height=&quot;793&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;책 없을 시 &amp;rarr; 안내 문구&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;1435&quot; data-origin-height=&quot;754&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/s8PVG/btsPUgyBLa0/FnKrKWsgnhgFlqqyIB5egk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/s8PVG/btsPUgyBLa0/FnKrKWsgnhgFlqqyIB5egk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/s8PVG/btsPUgyBLa0/FnKrKWsgnhgFlqqyIB5egk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fs8PVG%2FbtsPUgyBLa0%2FFnKrKWsgnhgFlqqyIB5egk%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;1435&quot; height=&quot;754&quot; data-origin-width=&quot;1435&quot; data-origin-height=&quot;754&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;책 있을 시 &amp;rarr; 수정/삭제 가능&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 style=&quot;text-align: center;&quot; data-ke-size=&quot;size23&quot;&gt;Naver Book API를 활용한 책 이미지&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1847&quot; data-origin-height=&quot;893&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cOlZvi/btsPUdWawwi/uyyXqrCpuHBvFFLse3Pu2K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cOlZvi/btsPUdWawwi/uyyXqrCpuHBvFFLse3Pu2K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cOlZvi/btsPUdWawwi/uyyXqrCpuHBvFFLse3Pu2K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcOlZvi%2FbtsPUdWawwi%2FuyyXqrCpuHBvFFLse3Pu2K%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;1847&quot; height=&quot;893&quot; data-origin-width=&quot;1847&quot; data-origin-height=&quot;893&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;모든 책 이미지 로드 가능&lt;/li&gt;
&lt;li&gt;단, Render 무료 플랜 &amp;rarr; 첫 로딩 느림  &lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;text-align: center;&quot; data-ke-size=&quot;size23&quot;&gt;무한 스크롤&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;페이지네이션보다 부드러운 UX 제공&lt;/li&gt;
&lt;li&gt;이전 기록을 자연스럽게 확인 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-style=&quot;style6&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt; &lt;/span&gt; 문제와 해결(제약 환경 포함)&lt;/h2&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size14&quot;&gt;(&lt;a href=&quot;https://stream-puffin-abd.notion.site/MVP-222e0b38263d80dcac89c41c53414cd6#22de0b38263d8014932cf32007431210&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;노션 정리본)&lt;/a&gt;&lt;/p&gt;
&lt;h3 style=&quot;text-align: center;&quot; data-ke-size=&quot;size23&quot;&gt;CSS는 전역으로 설정된다&lt;/h3&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;처음 리액트를 배우고 프로젝트를 하는데 서로 다른 컴포넌트인데도 불구하고 CSS가 중복 적용된다는 문제가 발생했습니다. 이렇게 중복으로 설정됐을 때 CSS Module을 사용할 수도 있었겠지만 그냥 className을 서로 다르게 설정해서 해결했습니다&lt;/p&gt;
&lt;h3 style=&quot;text-align: center;&quot; data-ke-size=&quot;size23&quot;&gt;Local Storage는 덮어쓰기 된다&lt;/h3&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;Local Storage에 관해 지식이 없었기 때문에 기존 배열이 있다면 자연스럽게 추가되겠지라는 생각으로 했는데 다 사라지고 추가한 데이터만 있었습니다... Local Storage의 작동방식을 공부한 후 key-값으로 구성된다는 점을 이용해 기존 배열을 복사 후 새로운 원소를 추가하여 키는 고정한 채로 새로운 배열 값을 만드는 방식을 선택했습니다&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;text-align: center;&quot; data-ke-size=&quot;size23&quot;&gt;상태 복잡성&lt;/h3&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;책장 페이지에 있는 책 리스트와 검색창을 구현하는 과정에서 상당히 복잡했습니다&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;상태는 부모 -&amp;gt; 자식으로 흐른다고 배웠는데 검색컴포넌트가 완전히 꼬여있었습니다&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;이를 해결하기 위해 컴포넌트끼리 시각화를 해봤습니다&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1265&quot; data-origin-height=&quot;639&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/PXZc3/btsPUdu5Kfd/a18G85DuuULWzZpmZWdOG0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/PXZc3/btsPUdu5Kfd/a18G85DuuULWzZpmZWdOG0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/PXZc3/btsPUdu5Kfd/a18G85DuuULWzZpmZWdOG0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FPXZc3%2FbtsPUdu5Kfd%2Fa18G85DuuULWzZpmZWdOG0%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;337&quot; height=&quot;170&quot; data-origin-width=&quot;1265&quot; data-origin-height=&quot;639&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;북케이스가 검색창과 북 카드를 렌더링 하고 있는 최상단이 맞기 때문에 여기서 State를 사용하는 게 분명한데 setBooks를 사용해서 하려고 했는데 Search 컴포넌트에서 어떤 것도 반환하지 않았습니다 저의 생각을 정리해보자면&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;SearchBar에서 검색 결과를 가지고 옴&lt;/li&gt;
&lt;li&gt;Bookcase에서 가지고 온 걸 바탕으로 setBooks에 재렌더링&lt;/li&gt;
&lt;li&gt;setBooks를 사용하여 Bookcard로 렌더링&lt;/li&gt;
&lt;/ol&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;이었고 가장 큰 문제는 SearchBar에서 어떻게 가져오는 지모르겠다는 것이었고 그렇게 생각하면서 풀어봤는데 제미나이 쓰기 직전에 아이디어가 떠올랐습니다&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;해답은 책장 페이지에서 searchResult라는 상태를 새로 만들고 검색창 컴포넌트에 searchResult를 활용한 함수를 같이 보내주는 방법을 사용해서 올바르게 표시될 수 있게 했습니다&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;text-align: center;&quot; data-ke-size=&quot;size23&quot;&gt;모달창 만들기&lt;/h3&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;인터넷을 찾는 도중 Protal과 라이브러리 없이 하는 방법을 찾을 수 있었습니다. Portal을 사용하기 위한 주 요인은 DOM 계층 구조와 CSS 문제 해결인데 저의 경우 DOM 계층 구조를 굳이 수정할 필요가 없다고 생각했기에 CSS를 조금 극단적이게 z-index: 100으로 설정해서 모달창을 라이브러리 없이 구현했습니다&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;text-align: center;&quot; data-ke-size=&quot;size23&quot;&gt;SEO 세팅&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/FZNxu/btsPUQ7rdKO/pkPLn5fCCu1AAIZ2VDH92k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/FZNxu/btsPUQ7rdKO/pkPLn5fCCu1AAIZ2VDH92k/img.png&quot; data-origin-width=&quot;726&quot; data-origin-height=&quot;264&quot; data-is-animation=&quot;false&quot; data-widthpercent=&quot;55.52&quot; style=&quot;width: 54.8774%; margin-right: 10px;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/FZNxu/btsPUQ7rdKO/pkPLn5fCCu1AAIZ2VDH92k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FFZNxu%2FbtsPUQ7rdKO%2FpkPLn5fCCu1AAIZ2VDH92k%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;726&quot; height=&quot;264&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cyl5FN/btsPSMrNazD/Sa1kAWgKxKSRua2rsEMm01/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cyl5FN/btsPSMrNazD/Sa1kAWgKxKSRua2rsEMm01/img.png&quot; data-origin-width=&quot;760&quot; data-origin-height=&quot;345&quot; data-is-animation=&quot;false&quot; style=&quot;width: 43.9598%;&quot; data-widthpercent=&quot;44.48&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cyl5FN/btsPSMrNazD/Sa1kAWgKxKSRua2rsEMm01/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcyl5FN%2FbtsPSMrNazD%2FSa1kAWgKxKSRua2rsEMm01%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;760&quot; height=&quot;345&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt; &lt;/span&gt; 학습 포인트&lt;/h2&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;useEffect, useState를 잘 사용할 수 있게 됨&lt;/li&gt;
&lt;li&gt;컴포넌트 분리&amp;nbsp;&lt;/li&gt;
&lt;li&gt;함수 props 활용&lt;/li&gt;
&lt;li&gt;Local Storage 구조를 이해&lt;/li&gt;
&lt;li&gt;API 사용법 숙지&lt;/li&gt;
&lt;li&gt;SEO 세팅 경험&lt;/li&gt;
&lt;li&gt;Render로 &lt;span data-token-index=&quot;1&quot;&gt;&lt;b&gt;Node.js + React&lt;/b&gt; 동시 배포&lt;/span&gt; 경험&lt;/li&gt;
&lt;/ol&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;  다음 개선 계획&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Tailwind로 전체 전환&lt;/li&gt;
&lt;li&gt;Node.js 연동으로 실시간 DB 저장&lt;/li&gt;
&lt;li&gt;로그인 기능 (OAuth 또는 이메일)&lt;/li&gt;
&lt;li&gt;감상문 태그 기능&lt;/li&gt;
&lt;li&gt;공유 기능 (링크 복사)&lt;/li&gt;
&lt;li&gt;TypeScript로 안정성 강화&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 style=&quot;text-align: center;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span&gt; &lt;/span&gt;느낀점 &amp;amp; 향후 계획&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;백엔드 vs 프런트엔드 진로 고민 중&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;  남은 군 복무 기간(104일) 동안 &lt;b&gt;기획 or 백엔드&lt;/b&gt; 집중 (최대한 많은 경험을 위해)&lt;/li&gt;
&lt;li&gt;9~11월 일정
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;백엔드 공부&lt;/li&gt;
&lt;li&gt;KCU 2학기 강의 수강&lt;/li&gt;
&lt;li&gt;노션 심화 학습&lt;/li&gt;
&lt;li&gt;운동 &amp;amp; 다이어트&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-style=&quot;style6&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt; &amp;zwj;  개발자 정보&lt;/h2&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;: HTML5, CSS, JavaScript, React, Git&lt;/li&gt;
&lt;li&gt;&lt;b&gt;GitHub&lt;/b&gt;: &lt;a href=&quot;https://github.com/guswnsj0112&quot;&gt;guswnsj0112&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;블로그&lt;/b&gt;: &lt;a href=&quot;https://joon0112.tistory.com/&quot;&gt;joon0112.tistory.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Instagram&lt;/b&gt;: &lt;a href=&quot;https://www.instagram.com/joonplan.dev/&quot;&gt;joonplan.dev&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Front-end/React-project</category>
      <category>1인개발자</category>
      <category>react</category>
      <category>개인프로젝트</category>
      <category>군대에서코딩</category>
      <category>리액트</category>
      <category>백엔드</category>
      <category>사지방에서코딩하는법</category>
      <category>사지방코딩</category>
      <category>풀스택</category>
      <category>프런트엔드</category>
      <author>dev_Hyeonjoon</author>
      <guid isPermaLink="true">https://joon0112.tistory.com/37</guid>
      <comments>https://joon0112.tistory.com/37#entry37comment</comments>
      <pubDate>Fri, 15 Aug 2025 18:39:37 +0900</pubDate>
    </item>
    <item>
      <title> Minecraft Style Armor Simulator Web 만들기</title>
      <link>https://joon0112.tistory.com/36</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;702&quot; data-origin-height=&quot;627&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cvZBSD/btsPAALrcK5/POeFwSMfwyE1iWj4ac7drK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cvZBSD/btsPAALrcK5/POeFwSMfwyE1iWj4ac7drK/img.png&quot; data-alt=&quot;https://minecraft-style-armor-simulator.netlify.app/&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cvZBSD/btsPAALrcK5/POeFwSMfwyE1iWj4ac7drK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcvZBSD%2FbtsPAALrcK5%2FPOeFwSMfwyE1iWj4ac7drK%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;429&quot; height=&quot;383&quot; data-origin-width=&quot;702&quot; data-origin-height=&quot;627&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://minecraft-style-armor-simulator.netlify.app/&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 style=&quot;text-align: left;&quot; data-ke-size=&quot;size26&quot;&gt; [프로젝트 개요]&lt;/h2&gt;
&lt;h3 style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span&gt; 왜 만들었을까?&lt;/span&gt;&lt;/h3&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;이 프로젝트는 군 복무 중 짬을 내어, &lt;b&gt;리액트의 상태 관리(useState)&lt;/b&gt;와&lt;b&gt; 컴포넌트 구조 분리&lt;/b&gt;를 연습하기 위해서 만들었습니다. &lt;/span&gt;&lt;s&gt;&lt;span&gt;(입원 연기로 읽잇보다 리액트 연습을 더 먼저하려고...)&amp;nbsp;&lt;/span&gt;&lt;/s&gt;&lt;span&gt; 기존 리액트 실력은 너무 강의만 따라쳐서 그런가 'props를 어떻게 넘기고 상태를 어디서 관리해야하는지' 모르는 경우가 너무 많았습니다 그래서 이를 보안하기 위해 강의를 다시 보며 강의 예제 없는 저만의 프로젝트로 만들어보고 싶었습니다&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h3 style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span&gt; &lt;span&gt;  구현 목표 &lt;/span&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;span style=&quot;color: #ee2323;&quot;&gt;부위&lt;/span&gt;(머리, 몸통, 다리)의 아머 색상을 클릭해서 개별적으로 변경할 수 있도록 구현&lt;/li&gt;
&lt;li&gt;&amp;nbsp;전체 색상 변경과 초기화 기능 추가&lt;/li&gt;
&lt;li&gt;반복되는 코드를 줄이기 위한 &lt;b&gt;고차 함수 및 공통 props 처리&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;상태는 &lt;span style=&quot;color: #ee2323;&quot;&gt;최상위(`Steve`)&lt;/span&gt;에서 관리하며 props로 자식에게 전달&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;⚡️ 개인적인 도전&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #1b711d;&quot;&gt;`객체 불변성`&lt;/span&gt;을 지키며 상태 업데이트하기&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #1b711d;&quot;&gt;`컴포넌트 트리 설계`, `props 흐름`, `코드 리팩토링`&lt;/span&gt;에 집중&lt;/li&gt;
&lt;li&gt;&amp;nbsp;Mermaid 다이어그램으로 구조 시각화도 도입해봄&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;이 글은 프로젝트를 진행하면서 마주한 오류들, 그 해결 과정, 리팩토링 아이디어까지 순차적으로 정리한 실전 기록입니다.&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span&gt; 다이어그램&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;776&quot; data-origin-height=&quot;317&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/VsR32/btsPB5QVx7J/Ga5J30CIkeXYZpksSsaFdk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/VsR32/btsPB5QVx7J/Ga5J30CIkeXYZpksSsaFdk/img.png&quot; data-alt=&quot;&amp;amp;lt;Notion을 통해 만든 Mermaid&amp;amp;gt;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/VsR32/btsPB5QVx7J/Ga5J30CIkeXYZpksSsaFdk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FVsR32%2FbtsPB5QVx7J%2FGa5J30CIkeXYZpksSsaFdk%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;776&quot; height=&quot;317&quot; data-origin-width=&quot;776&quot; data-origin-height=&quot;317&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;&amp;lt;Notion을 통해 만든 Mermaid&amp;gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span&gt; &lt;/span&gt; 주요 에러 &lt;span data-token-index=&quot;1&quot;&gt;&amp;amp;&lt;/span&gt; 해결 과정&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;❌&lt;/span&gt; 객체에&lt;span style=&quot;background-color: #dddddd;&quot;&gt; .map()&lt;/span&gt; 사용&lt;/h3&gt;
&lt;pre id=&quot;code_1753583386568&quot; class=&quot;reasonml&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;function earlySteve(){
	return {
		head: &quot;&quot;,
		body: &quot;&quot;,
		leg: &quot;&quot;,
	}
}

const [armors, setArmors] = useState(earlySteve);
setArmors(armors.map(...)) // 오류 발생&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;map()은 배열 전용 메서드&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span&gt;✔&lt;/span&gt; Object.entries()로 수정:&lt;/h4&gt;
&lt;pre class=&quot;maxima&quot;&gt;&lt;code&gt;Object.entries(armors).map(([part, material]) =&amp;gt; (
  &amp;lt;li key={part}&amp;gt;{part}: {material}&amp;lt;/li&amp;gt;
));

&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;❌&lt;/span&gt; JSX 안에서 &lt;span style=&quot;background-color: #dddddd;&quot;&gt;const&lt;/span&gt;, &lt;span style=&quot;background-color: #dddddd;&quot;&gt;for&lt;/span&gt; 사용&lt;/h3&gt;
&lt;pre class=&quot;lisp&quot;&gt;&lt;code&gt;setArmors((prev) =&amp;gt; (
  const update = {}; // ❌ SyntaxError
  ...
));
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span&gt;✔&lt;/span&gt; 블록 바디 사용 + return 명시 필요&lt;/h4&gt;
&lt;pre class=&quot;lisp&quot;&gt;&lt;code&gt;setArmors((prev) =&amp;gt; {
  const update = {};
  for (const part in prev) {
    update[part] = minerals[randIdx(minerals)];
  }
  return update;
});
&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;❌&lt;/span&gt; JSX에서 객체 직접 렌더링&lt;/h3&gt;
&lt;pre class=&quot;axapta&quot;&gt;&lt;code&gt;&amp;lt;div&amp;gt;{armors}&amp;lt;/div&amp;gt; // [object Object]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;595&quot; data-origin-height=&quot;211&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ZUB67/btsPAXszU69/8dUyjrMns6cXlzuzkKEBN0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ZUB67/btsPAXszU69/8dUyjrMns6cXlzuzkKEBN0/img.png&quot; data-alt=&quot;에러 사진&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ZUB67/btsPAXszU69/8dUyjrMns6cXlzuzkKEBN0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FZUB67%2FbtsPAXszU69%2F8dUyjrMns6cXlzuzkKEBN0%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;595&quot; height=&quot;211&quot; data-origin-width=&quot;595&quot; data-origin-height=&quot;211&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;에러 사진&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span&gt;&lt;span&gt;✔&lt;/span&gt; 해결: 객체 리터럴 안에서 불변성 지키기 &lt;/span&gt;&lt;/h4&gt;
&lt;pre class=&quot;lisp&quot;&gt;&lt;code&gt;setArmors(prev =&amp;gt; ({
  ...prev,
  head: minerals[randIdx(minerals)],
}));
&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;❌&lt;/span&gt; HeadArmor를 눌러도 전체 아머가 바뀜&lt;/h3&gt;
&lt;pre class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;const changeMineral = () =&amp;gt; {
	setArmors(prev =&amp;gt; ({
			...prev,
			head: minerals[randIdx(minerals)],
			body: minerals[randIdx(minerals)],
			leg: minerals[randIdx(minerals)],
		}))
};


// JSX 구현부분 !
&amp;lt;div className=&quot;Head&quot;&amp;gt;
	&amp;lt;HeadArmor changeMineral={changeMineral} setColor={mineralToHex(armors.head)} /&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div className=&quot;Body&quot;&amp;gt;
	&amp;lt;BodyArmor changeMineral={changeMineral} setColor={mineralToHex(armors.body)} /&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div className=&quot;Leg&quot;&amp;gt;
	&amp;lt;LegArmor changeMineral={changeMineral} setColor={mineralToHex(armors.leg)} /&amp;gt;
&amp;lt;/div&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span&gt;&lt;span&gt; &lt;span&gt; &lt;/span&gt; 좋지 않은&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;해결: &lt;/span&gt;각각의 부위마다 changeHead, changeBody, changeLeg 함수를 만들어 해결&lt;/h4&gt;
&lt;pre class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;const changeHead = () =&amp;gt; {
	setArmors(prev =&amp;gt; ({
			...prev,
			head: minerals[randIdx(minerals)],
		}))
};
const changeBody = () =&amp;gt; {
	setArmors(prev =&amp;gt; ({
			...prev,
			body: minerals[randIdx(minerals)],
		}))
};
const changeLeg = () =&amp;gt; {
	setArmors(prev =&amp;gt; ({
			...prev,
			leg: minerals[randIdx(minerals)],
		}))
};

return (
		&amp;lt;div className=&quot;Steve&quot;&amp;gt;
			&amp;lt;div className=&quot;Head&quot;&amp;gt;
				&amp;lt;HeadArmor changeMineral={changeHead} setColor={mineralToHex(armors.head)} /&amp;gt;
			&amp;lt;/div&amp;gt;
			&amp;lt;div className=&quot;Body&quot;&amp;gt;
				&amp;lt;div className=&quot;LeftArm&quot;&amp;gt;&amp;lt;/div&amp;gt;
				&amp;lt;div className=&quot;RightArm&quot;&amp;gt;&amp;lt;/div&amp;gt;
				&amp;lt;BodyArmor changeMineral={changeBody} setColor={mineralToHex(armors.body)} /&amp;gt;
			&amp;lt;/div&amp;gt;
			&amp;lt;div className=&quot;Leg&quot;&amp;gt;
				&amp;lt;div className=&quot;centerLine&quot;&amp;gt;&amp;lt;/div&amp;gt;
				&amp;lt;LegArmor changeMineral={changeLeg} setColor={mineralToHex(armors.leg)} /&amp;gt;
			&amp;lt;/div&amp;gt;
			&amp;lt;button onClick={allChange} &amp;gt;allChange&amp;lt;/button&amp;gt;
			&amp;lt;button onClick={reset}&amp;gt;Reset&amp;lt;/button&amp;gt;
		&amp;lt;/div&amp;gt;
	)&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이러한 방식은 코드의 중복을 늘리고 너무 길어지기 때문에 엄청 안좋은 방법이라고 생각이 듭니다&lt;/li&gt;
&lt;li&gt;따라서 아래처럼 &lt;b&gt;고차 함수로 리팩토링&lt;/b&gt; 하길 추천드립니다&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;♻️&lt;/span&gt; 리팩토링: 커링 패턴 + 공통 Props&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span&gt; &lt;/span&gt; 함수를 파라미터화한 커링 패턴&lt;/h3&gt;
&lt;pre class=&quot;dart&quot;&gt;&lt;code&gt;const changeMineral = (part) =&amp;gt; {
  setArmors(prev =&amp;gt; ({
    ...prev,
    [part]: minerals[randIdx(minerals)],
  }));
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span&gt; &lt;/span&gt; 컴포넌트 내부:&lt;/h4&gt;
&lt;pre class=&quot;typescript&quot;&gt;&lt;code&gt;&amp;lt;HeadArmor changeMineral={() =&amp;gt; changeMineral('head')} ... /&amp;gt;
&amp;lt;BodyArmor changeMineral={() =&amp;gt; changeMineral('body')} ... /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;✂️&lt;/span&gt; &lt;span data-token-index=&quot;0&quot;&gt;중복 제거용 공통 props:&lt;/span&gt;&lt;/h3&gt;
&lt;pre class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;export default function BodyArmor({changeMineral, setColor}){
	const commonStyle = { backgroundColor: setColor };
 	 const commonProps = { onClick: changeMineral, style: commonStyle };
	return (
	&amp;lt;&amp;gt;
		&amp;lt;div className=&quot;LeftArm&quot;  {...commonProps}&amp;gt;&amp;lt;/div&amp;gt;
		&amp;lt;div className=&quot;RightArm&quot; {...commonProps}&amp;gt;&amp;lt;/div&amp;gt;
		&amp;lt;div className=&quot;BodyArmor&quot;{...commonProps}&amp;gt;&amp;lt;/div&amp;gt;
			
	&amp;lt;/&amp;gt;
	)
	
}&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;702&quot; data-origin-height=&quot;627&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/l9Pj5/btsPAxnB15W/3ppDmH0IXcdNoF3x5G6W30/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/l9Pj5/btsPAxnB15W/3ppDmH0IXcdNoF3x5G6W30/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/l9Pj5/btsPAxnB15W/3ppDmH0IXcdNoF3x5G6W30/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fl9Pj5%2FbtsPAxnB15W%2F3ppDmH0IXcdNoF3x5G6W30%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;189&quot; height=&quot;169&quot; data-origin-width=&quot;702&quot; data-origin-height=&quot;627&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span&gt; &lt;/span&gt; 최종 결과물&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;2485&quot; data-start=&quot;2461&quot;&gt;각 아머 클릭 시 해당 부위 색상만 변경&lt;/li&gt;
&lt;li data-end=&quot;2509&quot; data-start=&quot;2486&quot;&gt;버튼 2개로 전체 변경 / 초기화 가능&lt;/li&gt;
&lt;li data-end=&quot;2509&quot; data-start=&quot;2486&quot;&gt;&lt;a href=&quot;https://github.com/guswnsj0112/minecraft-style-armor-simulator&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;깃 주소&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span&gt; &lt;/span&gt; 회고&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;군대 일과시간에 나오는 짬 시간에 틈틈히 손 코딩으로 컴포넌트 설계 및 상태 관리를 해나갔습니다 실수한 부분을 통해 GPT와 Gemini에게 물어가며 JSX 문법, React 불변성, 상태 관리, 컴포넌트 설계를 확실히 익혔습니다&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;✨작은 실전에서 큰 배움을 얻었습니다. &lt;br /&gt;앞으로도 &quot;나만의 프로젝트 &amp;rarr; 문제 발생 &amp;rarr; 해결 &amp;rarr; 리팩토링&quot; 루틴을 계속 이어나가며 성장할 계획입니다. 감사합니다!&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span&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;React (useState)&lt;/li&gt;
&lt;li&gt;Mermaid 다이어그램&lt;/li&gt;
&lt;li&gt;Component Props&lt;/li&gt;
&lt;li&gt;JSX 문법 규칙&lt;/li&gt;
&lt;li&gt;고차 함수로 리팩토링&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span&gt; &amp;zwj; &lt;/span&gt; 개발자 정보&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;기술 스택: HTML5, CSS, JavaScript, React, Git&lt;/li&gt;
&lt;li&gt;깃허브: &lt;a href=&quot;https://github.com/guswnsj0112&quot;&gt;guswnsj0112&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;블로그: &lt;a href=&quot;https://joon0112.tistory.com/&quot;&gt;joon0112.tistory.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;인스타그램: &lt;a href=&quot;https://www.instagram.com/joonplan.dev/&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.instagram.com/joonplan.dev/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Front-end/React-project</category>
      <category>React #리액트기초 #컴포넌트설계 #useState #JSX문법 #프론트엔드기초 #코딩공부기록 #개발블로그 #사지방코딩</category>
      <author>dev_Hyeonjoon</author>
      <guid isPermaLink="true">https://joon0112.tistory.com/36</guid>
      <comments>https://joon0112.tistory.com/36#entry36comment</comments>
      <pubDate>Sun, 27 Jul 2025 11:53:33 +0900</pubDate>
    </item>
    <item>
      <title>읽잇(ReadIt) - 감성 독서기록 웹서비스, MVP 1차 개발 회고</title>
      <link>https://joon0112.tistory.com/35</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;landingpage.png&quot; data-origin-width=&quot;476&quot; data-origin-height=&quot;777&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/claEvz/btsPgZb85J1/V1TFj0pjZVlgQb2Zhd8Pf1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/claEvz/btsPgZb85J1/V1TFj0pjZVlgQb2Zhd8Pf1/img.png&quot; data-alt=&quot;https://readit-38t1.onrender.com&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/claEvz/btsPgZb85J1/V1TFj0pjZVlgQb2Zhd8Pf1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FclaEvz%2FbtsPgZb85J1%2FV1TFj0pjZVlgQb2Zhd8Pf1%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;476&quot; height=&quot;777&quot; data-filename=&quot;landingpage.png&quot; data-origin-width=&quot;476&quot; data-origin-height=&quot;777&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://readit-38t1.onrender.com&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  프로젝트 개요&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;군 복무 중 처음으로 다량의 책을 읽게 되었고,&lt;br /&gt;그 감정을 기록하고 싶다는 생각이 들었습니다.&amp;nbsp;&lt;br /&gt;마침 React를 공부하던 시기여서,&lt;br /&gt;&lt;b&gt;감성 독서 기록 웹서비스 '읽잇(ReadIt)' &lt;/b&gt;을 직접 만들게 됐습니다&lt;/blockquote&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;서비스명 : 읽잇 (ReadIt)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이유: 단순한 기록이 아닌, &lt;b&gt;다시 읽게 만드는 감정 저장소&lt;/b&gt;를 만들고 싶어서&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;개발 기간: 약 2주 (MVP 기준)&lt;/li&gt;
&lt;li&gt;사용 기술: React, CSS, Frmaer&lt;/li&gt;
&lt;li&gt;배포: Netlify&lt;/li&gt;
&lt;li&gt;  GitHub: &lt;a href=&quot;https://github.com/guswnsj0112/readIt&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://github.com/guswnsj0112/readIt&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;  &lt;a href=&quot;https://readit-38t1.onrender.com&quot;&gt;서비스 바로가기&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;✍️&amp;nbsp; 기획 과정&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&quot;프론트? 백엔드? PM? 아예 그만둘까?&quot;&lt;br /&gt;고민만 쌓이던 시기, &lt;b&gt;GPT에게 고민을 털어놓으면서&lt;/b&gt; 프로젝트가 시작됐습니다.&lt;/blockquote&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;GPT와 대화하며 기획 방향 설정&lt;/li&gt;
&lt;li&gt;Notion으로 기능 분해 및 일정 플래닝&lt;/li&gt;
&lt;li&gt;Frmaer AI를 사용해 감성 UI시안 제작&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;  기획 노션 링크: &lt;a href=&quot;https://www.notion.so/MVP-221e0b38263d806986abfecd3ed69fc9?pvs=21&quot;&gt;읽잇 MVP 플래너&lt;/a&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  디자인&amp;amp; 로고&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;로고는 GPT가 제안한 텍스트에서 선정&lt;/li&gt;
&lt;li&gt;로고의 배경 투명화는 Photoroom으로 해결&lt;/li&gt;
&lt;li&gt;Framer로 Nav 포함 전체 레이아웃 구성&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;  디자인 미리 보기: &lt;a href=&quot;https://authentic-community-685805.framer.app/&quot; data-end=&quot;1331&quot; data-start=&quot;1271&quot;&gt;Framer 디자인&lt;/a&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  개발 구조 &amp;amp; 작업 내용&lt;/h3&gt;
&lt;pre id=&quot;code_1752242947044&quot; class=&quot;bash&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;readIt/
├── public/
├── src/
│   ├── components/
│   ├── pages/
│   ├── styles/
│   └── App.jsx
├── package.json
└── README.md&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;(일부 생략)&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt; ️ 아쉬운 점&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&quot;독서 기록 시작하기&quot; 버튼을 누르면 감상문 작성 페이지로 이동시켜했으나, 입원 일정으로 인해 현재는 랜딩 페이지까지만 배포한 상태입니다.&lt;/blockquote&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;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;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt; &amp;zwj;  느낀 점&lt;/h3&gt;
&lt;p data-end=&quot;245&quot; data-start=&quot;205&quot; 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-end=&quot;319&quot; data-start=&quot;247&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;259&quot; data-start=&quot;247&quot;&gt;백엔드로 갈까?&lt;/li&gt;
&lt;li data-end=&quot;274&quot; data-start=&quot;260&quot;&gt;프론트엔드로 갈까?&lt;/li&gt;
&lt;li data-end=&quot;296&quot; data-start=&quot;275&quot;&gt;아니면 개발자를 포기할까...?&lt;/li&gt;
&lt;li data-end=&quot;319&quot; data-start=&quot;297&quot;&gt;혹시 &lt;b&gt;개발 PM&lt;/b&gt;이라도 해볼까?&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;406&quot; data-start=&quot;321&quot; data-ke-size=&quot;size16&quot;&gt;이런 고민들이 계속 쌓이던 중,&lt;br /&gt;너무 답답해서 &lt;b&gt;GPT에게 고민을 털어놓았고&lt;/b&gt;,&lt;br /&gt;그 대화가 시작이 되어 이 프로젝트가 만들어졌습니다.&lt;/p&gt;
&lt;hr data-end=&quot;411&quot; data-start=&quot;408&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-end=&quot;550&quot; data-start=&quot;413&quot; data-ke-size=&quot;size16&quot;&gt;비록 Google Books API 연동 같은 부분에선&lt;br /&gt;&lt;b&gt;GPT에게 너무 의존했다는 자괴감&lt;/b&gt;도 있었지만,&lt;br /&gt;&lt;b&gt;입원 전에 랜딩 페이지를 완성했다는 사실 하나만으로도&lt;/b&gt;&lt;br /&gt;스스로에게 굉장히 자랑스럽고, 감사한 순간이었습니다.&amp;nbsp;&lt;/p&gt;
&lt;hr data-end=&quot;555&quot; data-start=&quot;552&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-end=&quot;598&quot; data-start=&quot;557&quot; data-ke-size=&quot;size16&quot;&gt;아직 제 진로는 100% 확실하진 않지만,&lt;br /&gt;하나 분명해진 건 있습니다.&lt;/p&gt;
&lt;blockquote data-end=&quot;672&quot; data-start=&quot;600&quot; data-ke-style=&quot;style1&quot;&gt;
&lt;p data-end=&quot;672&quot; data-start=&quot;602&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;ldquo;전역 후 복학한다면, 꼭 융합소프트웨어로 전과하자.&amp;rdquo;&lt;/b&gt;&lt;br /&gt;이건 이번 프로젝트 덕분에 더욱 확실해졌습니다.&amp;nbsp;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  회고 한 줄 요약&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;기획과 디자인은 힘들었으나 랜딩 페이지가 완성된 순간. 난 내가 멋있었다&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt; &amp;zwj;  개발자 정보&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1559&quot; data-start=&quot;1394&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1424&quot; data-start=&quot;1394&quot;&gt;&lt;b&gt;이름&lt;/b&gt;: 장현준 (HyunJun Jang)&lt;/li&gt;
&lt;li data-end=&quot;1487&quot; data-start=&quot;1425&quot;&gt;&lt;b&gt;GitHub&lt;/b&gt;: &lt;a href=&quot;https://github.com/guswnsj0112&quot; data-end=&quot;1485&quot; data-start=&quot;1439&quot;&gt;@guswnsj0112&lt;/a&gt;&lt;/li&gt;
&lt;li data-end=&quot;1559&quot; data-start=&quot;1488&quot;&gt;&lt;b&gt;블로그&lt;/b&gt;: &lt;a href=&quot;https://joon0112.tistory.com&quot;&gt;https://joon0112.tistory.com&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Front-end/React-project</category>
      <category>#react #개발기록 #포트폴리오 #프론트엔드 #사이드프로젝트 #읽잇 #독서기록 #webproject #개발회고</category>
      <author>dev_Hyeonjoon</author>
      <guid isPermaLink="true">https://joon0112.tistory.com/35</guid>
      <comments>https://joon0112.tistory.com/35#entry35comment</comments>
      <pubDate>Fri, 11 Jul 2025 23:23:36 +0900</pubDate>
    </item>
    <item>
      <title>사지방 + ChatGPT = A+ | 군 e러닝 효율적 공부법</title>
      <link>https://joon0112.tistory.com/34</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;691&quot; data-origin-height=&quot;692&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/brRnV1/btsOI5yofWd/MvgEfHpAukZSdlHiuG3zO0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/brRnV1/btsOI5yofWd/MvgEfHpAukZSdlHiuG3zO0/img.png&quot; data-alt=&quot;군 생활, 단순히 흘려보낼 시간일까요? 저는 아니라고 생각했습니다. 복무 중에도 목표가 있다면, 우리는 그 시간을 &amp;amp;lsquo;성장&amp;amp;rsquo;으로 바꿀 수 있습니다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/brRnV1/btsOI5yofWd/MvgEfHpAukZSdlHiuG3zO0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbrRnV1%2FbtsOI5yofWd%2FMvgEfHpAukZSdlHiuG3zO0%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;691&quot; height=&quot;692&quot; data-origin-width=&quot;691&quot; data-origin-height=&quot;692&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;군 생활, 단순히 흘려보낼 시간일까요? 저는 아니라고 생각했습니다. 복무 중에도 목표가 있다면, 우리는 그 시간을 &amp;lsquo;성장&amp;rsquo;으로 바꿀 수 있습니다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt; &amp;zwj;♂️ 군 e러닝을 선택한 이유&lt;/h2&gt;
&lt;p style=&quot;text-align: center;&quot; data-end=&quot;356&quot; data-start=&quot;304&quot; data-ke-size=&quot;size16&quot;&gt;군 생활을 하며 한 가지 다짐이 있었습니다.&lt;br /&gt;&lt;b&gt;&amp;ldquo;절대로 시간을 헛되이 보내지 말자.&amp;rdquo;&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-end=&quot;450&quot; data-start=&quot;358&quot; data-ke-size=&quot;size16&quot;&gt;그 다짐은 단순한 의욕이 아니라, &lt;b&gt;복학 후 전과를 위한 GPA 관리&lt;/b&gt;라는 현실적인 목표로 이어졌고, 그 첫 실천으로 &lt;b&gt;군 e러닝 수강&lt;/b&gt;을 시작하게 됐습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-end=&quot;578&quot; data-start=&quot;452&quot; data-ke-size=&quot;size16&quot;&gt;또한 저는 &amp;ldquo;군대에서도 충분히 공부하고 A+을 받을 수 있다&amp;rdquo;는 것을 제 자신에게 증명해보고 싶었습니다.&lt;br /&gt;그리고 복학 후에도 쓸 수 있는 &lt;b&gt;효율적인 공부 루틴을 만들기 위해&lt;/b&gt; 실험적으로 다양한 도구도 활용해보기로 했죠.&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;  과목 선택과 전략&lt;/h2&gt;
&lt;p style=&quot;text-align: center;&quot; data-end=&quot;632&quot; data-start=&quot;602&quot; data-ke-size=&quot;size16&quot;&gt;제가 선택한 과목은 &lt;b&gt;「인체안의 전쟁」&lt;/b&gt; 입니다.&lt;/p&gt;
&lt;h3 style=&quot;text-align: center;&quot; data-end=&quot;644&quot; data-start=&quot;634&quot; data-ke-size=&quot;size23&quot;&gt;선택 이유?&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;741&quot; data-start=&quot;645&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;675&quot; data-start=&quot;645&quot;&gt;사지방 특성상 어떤 프로그램도 설치할 수 없어서&lt;/li&gt;
&lt;li data-end=&quot;694&quot; data-start=&quot;676&quot;&gt;팀플이 없는 과목을 찾았고
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;741&quot; data-start=&quot;695&quot;&gt;훈련이나 외출로 인해 팀에 피해를 줄 수 있는 과목은 피하고 싶었기 때문입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;text-align: center;&quot; data-end=&quot;813&quot; data-start=&quot;743&quot; data-ke-size=&quot;size16&quot;&gt;결과적으로 &amp;lsquo;혼자서도 계획적으로 밀고 나갈 수 있는&amp;rsquo; 과목이 가장 적합했고, &lt;b&gt;자연스럽게 이 과목을 선택하게 되었습니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  공부 방법 &amp;amp; 루틴&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;수업 자료는 저작권으로 인해 공유하지 못하지만, 공부 방식에 대해서는 자세히 설명드릴 수 있어요.&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;915&quot; data-origin-height=&quot;628&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lqiHU/btsOJuq3MxM/JUIvxXZkdburkzgcfgk4G1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lqiHU/btsOJuq3MxM/JUIvxXZkdburkzgcfgk4G1/img.png&quot; data-alt=&quot;수업 저작권으로 인해 나머지는 글로 대체하겠습니다!&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lqiHU/btsOJuq3MxM/JUIvxXZkdburkzgcfgk4G1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlqiHU%2FbtsOJuq3MxM%2FJUIvxXZkdburkzgcfgk4G1%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;915&quot; height=&quot;628&quot; data-origin-width=&quot;915&quot; data-origin-height=&quot;628&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;수업 저작권으로 인해 나머지는 글로 대체하겠습니다!&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-end=&quot;911&quot; data-start=&quot;900&quot; data-ke-size=&quot;size23&quot;&gt;⏰ 공부 시간&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1002&quot; data-start=&quot;912&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;924&quot; data-start=&quot;912&quot;&gt;평일: 약 1시간씩&lt;/li&gt;
&lt;li data-end=&quot;1002&quot; data-start=&quot;925&quot;&gt;주말: 2~3시간 정도 확보&lt;br /&gt;(※ 프론트엔드 공부도 병행했기 때문에 &amp;lsquo;&lt;b&gt;적게, 하지만 꾸준하게&lt;/b&gt;&amp;rsquo;를 핵심 전략으로 삼았습니다.)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-end=&quot;1019&quot; data-start=&quot;1004&quot; data-ke-size=&quot;size23&quot;&gt;  공부 방법 요약&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-end=&quot;1224&quot; data-start=&quot;1020&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li data-end=&quot;1085&quot; data-start=&quot;1020&quot;&gt;&lt;b&gt;강의 시청 + 노션 필기&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1085&quot; data-start=&quot;1044&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1064&quot; data-start=&quot;1044&quot;&gt;강의 내용을 최대한 세세하게 정리&lt;/li&gt;
&lt;li data-end=&quot;1085&quot; data-start=&quot;1068&quot;&gt;정리한 노트를 PDF로 추출&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;1224&quot; data-start=&quot;1086&quot;&gt;&lt;b&gt;AI 도구 활용&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1224&quot; data-start=&quot;1105&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1129&quot; data-start=&quot;1105&quot;&gt;ilovepdf로 주차별 PDF 압축&lt;/li&gt;
&lt;li data-end=&quot;1191&quot; data-start=&quot;1133&quot;&gt;ChatGPT, Gemini, NotebookLM을 활용하여 &lt;b&gt;30문제 + 해설 생성&lt;/b&gt;&lt;/li&gt;
&lt;li data-end=&quot;1224&quot; data-start=&quot;1195&quot;&gt;모르는 개념은 AI에게 &lt;b&gt;세세하게 설명 요청&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote data-end=&quot;1308&quot; data-start=&quot;1226&quot; data-ke-style=&quot;style1&quot;&gt;
&lt;p data-end=&quot;1308&quot; data-start=&quot;1228&quot; data-ke-size=&quot;size16&quot;&gt;이 과정에서 &lt;b&gt;AI 도구는 보조교사&lt;/b&gt;의 역할을 톡톡히 해냈습니다.&lt;br /&gt;시험 공부를 체계적으로 할 수 있었고, 반복 학습도 훨씬 쉬워졌습니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  결과 &amp;amp; 느낀 점&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;728&quot; data-origin-height=&quot;315&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ecoz9e/btsOHD3TgrE/uokpijVck5okLoB7yeet91/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ecoz9e/btsOHD3TgrE/uokpijVck5okLoB7yeet91/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ecoz9e/btsOHD3TgrE/uokpijVck5okLoB7yeet91/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fecoz9e%2FbtsOHD3TgrE%2FuokpijVck5okLoB7yeet91%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;728&quot; height=&quot;315&quot; data-origin-width=&quot;728&quot; data-origin-height=&quot;315&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-end=&quot;1368&quot; data-start=&quot;1332&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;저는 군대에서도 A+를 받을 수 있었습니다.&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-end=&quot;1394&quot; data-start=&quot;1370&quot; data-ke-size=&quot;size16&quot;&gt;이 경험을 통해 느꼈던 건 다음과 같습니다:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1503&quot; data-start=&quot;1396&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1428&quot; data-start=&quot;1396&quot;&gt;&lt;b&gt;AI 시대에 도구를 적극 활용하는 것이 효율이다&lt;/b&gt;&lt;/li&gt;
&lt;li data-end=&quot;1462&quot; data-start=&quot;1429&quot;&gt;군 복무 중이라도 충분히 성장하고 목표를 달성할 수 있다&lt;/li&gt;
&lt;li data-end=&quot;1503&quot; data-start=&quot;1463&quot;&gt;내가 직접 만든 루틴과 도구 세트는 복학 후에도 그대로 활용 가능하다&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-end=&quot;1530&quot; data-start=&quot;1510&quot; data-ke-size=&quot;size26&quot;&gt;  군 e러닝 A+ 꿀팁 요약&lt;/h2&gt;
&lt;div&gt;
&lt;div&gt;항목팁
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-end=&quot;1722&quot; data-start=&quot;1532&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody data-end=&quot;1722&quot; data-start=&quot;1557&quot;&gt;
&lt;tr data-end=&quot;1591&quot; data-start=&quot;1557&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1565&quot; data-start=&quot;1557&quot;&gt;과목 선택&lt;/td&gt;
&lt;td data-end=&quot;1591&quot; data-start=&quot;1565&quot; data-col-size=&quot;sm&quot;&gt;팀플 없는 과목 추천, 사지방 환경 고려&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;1630&quot; data-start=&quot;1592&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1600&quot; data-start=&quot;1592&quot;&gt;공부 시간&lt;/td&gt;
&lt;td data-end=&quot;1630&quot; data-start=&quot;1600&quot; data-col-size=&quot;sm&quot;&gt;적게라도 &lt;b&gt;꾸준하게&lt;/b&gt; (1일 30분~1시간)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;1662&quot; data-start=&quot;1631&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1639&quot; data-start=&quot;1631&quot;&gt;기록 방식&lt;/td&gt;
&lt;td data-end=&quot;1662&quot; data-start=&quot;1639&quot; data-col-size=&quot;sm&quot;&gt;노션에 꼼꼼히 필기 후 PDF 추출&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;1697&quot; data-start=&quot;1663&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1671&quot; data-start=&quot;1663&quot;&gt;AI 활용&lt;/td&gt;
&lt;td data-end=&quot;1697&quot; data-start=&quot;1671&quot; data-col-size=&quot;sm&quot;&gt;강의 정리 &amp;rarr; 문제 생성 &amp;rarr; 복습 최적화&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;1722&quot; data-start=&quot;1698&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1703&quot; data-start=&quot;1698&quot;&gt;태도&lt;/td&gt;
&lt;td data-end=&quot;1722&quot; data-start=&quot;1703&quot; data-col-size=&quot;sm&quot;&gt;&amp;lsquo;성장 루틴 만들기&amp;rsquo;에 집중&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-end=&quot;1751&quot; data-start=&quot;1729&quot; data-ke-size=&quot;size26&quot;&gt; &amp;zwj;  이런 분들께 추천합니다!&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1846&quot; data-start=&quot;1753&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1785&quot; data-start=&quot;1753&quot;&gt;군 생활 중 &lt;b&gt;헛되지 않은 시간을 보내고 싶은 분&lt;/b&gt;&lt;/li&gt;
&lt;li data-end=&quot;1815&quot; data-start=&quot;1786&quot;&gt;&lt;b&gt;복학 후 GPA&lt;/b&gt;를 올리고 싶은 예비 복학생&lt;/li&gt;
&lt;li data-end=&quot;1846&quot; data-start=&quot;1816&quot;&gt;AI 도구를 &lt;b&gt;실전 공부에 접목해보고 싶은 분&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-end=&quot;1851&quot; data-start=&quot;1848&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;1863&quot; data-start=&quot;1853&quot; data-ke-size=&quot;size26&quot;&gt;✨ 마무리하며&lt;/h2&gt;
&lt;p data-end=&quot;1923&quot; data-start=&quot;1865&quot; data-ke-size=&quot;size16&quot;&gt;저는 앞으로도 이 루틴을 발전시켜 나가며,&lt;br /&gt;복학 후에도 AI와 함께 공부 효율을 극대화할 계획입니다.&lt;/p&gt;
&lt;blockquote data-end=&quot;2002&quot; data-start=&quot;1925&quot; data-ke-style=&quot;style1&quot;&gt;
&lt;p data-end=&quot;2002&quot; data-start=&quot;1927&quot; data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;당신의 군 생활도, 분명 &lt;b&gt;성장의 한 챕터&lt;/b&gt;가 될 수 있습니다.&lt;br /&gt;지금의 시간을 어떻게 쓰느냐가, 앞으로의 나를 만듭니다.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;</description>
      <category>회고/기타</category>
      <category>ai 공부 도구</category>
      <category>chatgpt 공부법</category>
      <category>군e러닝</category>
      <category>군대 공부 루틴</category>
      <category>군대 학점</category>
      <category>노션 공부법</category>
      <category>복학생 꿀팁</category>
      <category>사이버지식정보방</category>
      <category>인체안의전쟁</category>
      <author>dev_Hyeonjoon</author>
      <guid isPermaLink="true">https://joon0112.tistory.com/34</guid>
      <comments>https://joon0112.tistory.com/34#entry34comment</comments>
      <pubDate>Thu, 19 Jun 2025 20:04:37 +0900</pubDate>
    </item>
  </channel>
</rss>