<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>원 투 쓰리 포 버블버블</title>
    <link>https://bubblebubble.tistory.com/</link>
    <description>Trust your instincts!</description>
    <language>ko</language>
    <pubDate>Fri, 12 Jun 2026 23:16:24 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>Bubbles</managingEditor>
    <image>
      <title>원 투 쓰리 포 버블버블</title>
      <url>https://tistory1.daumcdn.net/tistory/4424955/attach/f1048ba903b04a53b52c434995dea0fb</url>
      <link>https://bubblebubble.tistory.com</link>
    </image>
    <item>
      <title>Enum을 비교할 때에는 ==과 equals()중 어떤 것을 써야 할까?</title>
      <link>https://bubblebubble.tistory.com/172</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;회사에서 MergeRequest를 올리고 코드 리뷰를 팀원께 요청드렸었는데, 아래와 같이 Dto에 있던 enumType비교 시 ==기호를 사용한 것에 대해 코드 리뷰가 달렸었다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1707179650409&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;if (someDto.type == someEnumType.Atype) {
	// do something
}&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;Enum 비교에 있어서 equals( )와 ==의 차이에 대해 공부해보는것도 좋을 것 같다고 공부할만한 토픽을 하나 주셔서, 겸사겸사 공부한 것을 정리하려 포스팅한다.&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;equals( )와 == 연산의 차이는 CS 스터디때도, 멘토링 공부하면서도 알고 있던 부분이라고 생각했고, 다시 내가 공부했던 내용을 찾아보면 아래와 같다.&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; color: #333333; text-align: left;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;equals()는 참조 변수의 값이 같은지 비교하는 메소드로, 재정의 되어있지 않다면 객체의 주소값을 비교하여 동일 객체인지 비교후 boolean 값을 리턴하는 메소드이다.&amp;nbsp;&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;hashCode()도 오버라이딩 해줘야 제대로 중복 객체가 Hash 자료구조에 들어오는 것을 방지할 수 있음&amp;nbsp;&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;== 연산자는 primitive type일 경우 값을, 그 외에는 주소값을 비교하는 연산자이다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 equals()의 경우, String 클래스에는 따로 내용물만 비교할 수 있도록 overriding 되어 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 &lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;Oracle Docs의 Enum class를 보면 equals() 메소드는 final로 선언이 되어있다&lt;/b&gt;&lt;/span&gt;.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, Enum에서의 equals 오버라이딩을 더는 허용하지 않는다는 뜻이고, equals 호출 시 Object의 equlals 호출하여 사용한다. Object의 equals는 아래와 같이 되어 있다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1707181896853&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public boolean equals(Object obj) {
	return (this == obj);
}&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;Oracle 공식 문서에도 아래처럼 나와 있다.&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;a href=&quot;https://docs.oracle.com/javase/specs/jls/se13/html/jls-8.html#jls-8.9&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;https://docs.oracle.com/javase/specs/jls/se13/html/jls-8.html#jls-8.9&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;[ ...&amp;nbsp; 중략 ]&lt;br /&gt;Because there is only one instance of each enum constant, it is permitted to use the&amp;nbsp;==&amp;nbsp;operator in place of the&amp;nbsp;equals&amp;nbsp;method when comparing two object references if it is known that at least one of them refers to an enum constant.&lt;br /&gt;The&amp;nbsp;equals&amp;nbsp;method in&amp;nbsp;Enum&amp;nbsp;is a&amp;nbsp;final&amp;nbsp;method that merely invokes&amp;nbsp;super.equals&amp;nbsp;on its argument and returns the result, thus performing an identity comparison.&lt;/blockquote&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; 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;enum 상수는 1개만 존재하기 때문에, 2개의 객체를 비교할 때 ==을 사용해도 된다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Enum에서의 equals 메소드는 단지 super.equals를 호출하여 동일성 비교를 수행하는 메소드이다.&amp;nbsp;&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;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;592&quot; data-origin-height=&quot;331&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/oHrHU/btsEonprKom/vCwNNeOmmWCZT5rBMdjn60/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/oHrHU/btsEonprKom/vCwNNeOmmWCZT5rBMdjn60/img.png&quot; data-alt=&quot;출처 :&amp;amp;amp;nbsp;https://docs.oracle.com/javase/8/docs/api/java/lang/Enum.html&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/oHrHU/btsEonprKom/vCwNNeOmmWCZT5rBMdjn60/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FoHrHU%2FbtsEonprKom%2FvCwNNeOmmWCZT5rBMdjn60%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;592&quot; height=&quot;331&quot; data-origin-width=&quot;592&quot; data-origin-height=&quot;331&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처 :&amp;amp;nbsp;https://docs.oracle.com/javase/8/docs/api/java/lang/Enum.html&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;이를 보고, 나는 Enum 타입의 경우, == 연산과 equals의 차이가 없으며 NPE 발생 여부만 다르다고 판단하고, 추가적으로&lt;/span&gt; == 과 equals 메소드를 가지고 실험도 해봤다.&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1707180037083&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class Main {
    public static void main(String[] args) {
        Test test = new Test(Types.RED);
        Test test2 = new Test(Types.RED);
        Test test3 = new Test();

        // 같은 enum 넣은 경우 equals든, ==이든 동일하게 true
        System.out.println(test.types.equals(test2.types)); 
        System.out.println(test.types == test2.types);
        
        // 그냥 enum 상수 자체와 비교해도 둘다 true
        System.out.println(test.types.equals(Types.RED));
        System.out.println(test.types == Types.RED);
        
        // test3의 types는 null, equals든, ==이든 동일하게 false
        System.out.println(test.types.equals(test3.types));
        System.out.println(test.types == test3.types);
        
        // false
        System.out.println(new Test().types == Types.RED);
        // NPE 발생
        System.out.println(new Test().types.equals(Types.RED));
    }

    static class Test {
        Types types = null;
        Test (Types types) {
            this.types = types;
        }
        Test() { }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;주목할 것은 이 부분이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Null 이 들어있을 때 두 연산자는 어떤 결과를 뱉는가?&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1707182381472&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// false
System.out.println(new Test().types == Types.RED);
// NPE 발생
System.out.println(new Test().types.equals(Types.RED));&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;Null값이 들어왔을 때, == 연산자는 단지 false를 반환하고, equals 메소드는 NPE를 발생 시킨다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기초적인 것이지만 늘 헷갈리는 부분인만큼 이번 기회에 다시 정리해두었다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;팀원 분 덕분에 좋은 공부를 할 수 있었다 :DD&amp;nbsp;&lt;/p&gt;</description>
      <category>One Cookie a day</category>
      <author>Bubbles</author>
      <guid isPermaLink="true">https://bubblebubble.tistory.com/172</guid>
      <comments>https://bubblebubble.tistory.com/172#entry172comment</comments>
      <pubDate>Tue, 6 Feb 2024 10:23:09 +0900</pubDate>
    </item>
    <item>
      <title>Factory Pattern</title>
      <link>https://bubblebubble.tistory.com/171</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;  인터페이스를 사용한다고 해도 구상 클래스의 인스턴스를 만들어야 하지 않나?&amp;nbsp;&lt;/b&gt;&lt;/h4&gt;
&lt;pre class=&quot;java&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;Duck duck = new MallardDuck();
// Duck이라는 인터페이스를 써서 유연하게 만들려고 해도, 그럼에도 구상 클래스의 인스턴스를 만들어야 한다.

Duck duck;
if (picnic) {
	duck = new MallardDuck();
} else if (hunting) {
	duck = new DecoyDuck();
} else if (inBathTub) {
	duck = new RubberDuck();
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이 코드를 보면 구상 클래스의 인스턴스가 여러 개 있고, 그 인스턴스의 형식은 실행 시 조건에 따라 결정된다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;변경하거나 확장할 때, 코드를 다시 확인하고 새롭게 추가하거나 기존 코드 제거&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;=&amp;gt; 관리와 갱신이 어렵다.&amp;nbsp;&lt;br /&gt;=&amp;gt; 인터페이스에 맞춰서 코딩하면 시스템에서 일어날 수 있는 여러 변화에 대응 가능 (인터페이스만 구현하면 사용 가능, 다형성)&lt;br /&gt;=&amp;gt; 구상 클래스를 많이 사용하면 새로운 구상 클래스 추가될 때마다 코드 고쳐야 함&lt;br /&gt;=&amp;gt; 새로운 구상 형식을 써서 확장할 때에는 어떻게 해서든 다시 열 수 있게 만들어야 한다...!&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre class=&quot;java&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;Pizza orderPizza(String type) {
		Pizza pizza;
		
// 이 부분이 피자가 바뀔 때마다 코드를 계속 추가하고 삭제해야 하는 것이 문제이다.
// ( 인스턴스를 만드는 구상 클래스 선택하는 부분 )
// 이 부분을 따로 빼두자(팩토리)
		if (type.equals(&quot;cheese&quot;)) {
				pizza = new CheezePizza();
		} else if (type.equals(&quot;pepperoni&quot;) {
				pizza = new PepperoniPizza();
		} else if (type.equals(&quot;clam&quot;)) {
				pizza = new ClamPizza();
		} else if (type.equals(&quot;veggie&quot;)) {
				pizza = new VeggiePizza();
		} 

// 이 아래부분은 바뀌지 않음 

		pizza.prepare();
		pizza.bake();
		pizza.cut();
		pizza.box();
		return pizza;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br /&gt;인스턴스를 만드는 구상 클래스를 선택하는 부분 -&amp;gt; 이 부분을 따로 빼내자(피자 종류에 따라 계속 바뀌는 부분이므로)&lt;/p&gt;
&lt;pre class=&quot;java&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;public class SimplePizzaFactory {

		public Pizza createPizza(String type) {
				if (type.equals(&quot;cheese&quot;)) {
								pizza = new CheezePizza();
				} else if (type.equals(&quot;pepperoni&quot;) {
								pizza = new PepperoniPizza();
				} else if (type.equals(&quot;clam&quot;)) {
								pizza = new ClamPizza();
				} else if (type.equals(&quot;veggie&quot;)) {
								pizza = new VeggiePizza();
				} 
				return pizza;
		}
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;피자 객체 생성 작업을 팩토리 클래스로 캡슐화 해놓으면 구현을 변경할 때 여기저기 고칠 필요 없이 팩토리 클래스 하나만 고치면 된다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;피자 객체를 받아서 주문하는 클래스 말고도, 피자를 설명하는 클래스, 가격을 알려주는 클래스 등 다른 방식으로 피자를 처리하는 클래스에도 이 팩토리를 사용할 수 있다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;   간단한 팩토리?&lt;/b&gt;&lt;/h4&gt;
&lt;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;PizzaStore(팩토리 사용하는 클라이언트)&lt;/li&gt;
&lt;li&gt;SimplePizzaFactory (객체를 생성하는 팩토리, 구상 Pizza 클래스를 직접 참조)&lt;/li&gt;
&lt;li&gt;Pizza (팩토리에서 만드는 피자)&amp;nbsp;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;CheesePizza, VeggiePizza, ClamPizza, PepperoniPizza 등등&amp;nbsp;&lt;/li&gt;
&lt;li&gt;팩토리에서 생산하는 제품에 해당하는 구상 클래스&lt;/li&gt;
&lt;li&gt;Pizza 인터페이스를 구현하며, 각각은 구상 클래스이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;java&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;public abstract class PizzaStore {
	public Pizza orderPizza(String type) {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;	Pizza pizza;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;pizza = createPizza(type);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;pizza.prepare();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;pizza.bake();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;pizza.cut();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;pizza.box();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return pizza;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;abstract Pizza createPizza(String type);
}&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;createPizza : PizzaStore 상속받은 NYStylePizzaStore, ChicagoStylePizzaStore 2가지&lt;br /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;ex ) NYStylePizzaStore의 createPizza(type)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;NYStyleCheesePizza()&lt;/li&gt;
&lt;li&gt;NYStylePepperoniPizza()&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;orderPizza : 그냥 구현하지 않고 가져다 사용, 만약 못 고치도록 막고 싶다면 final 붙이면 된다&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;  팩토리 메서드&amp;nbsp;&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;li&gt;어떤 클래스의 인스턴스를 만들 지는 서브 클래스에서 결정한다.&lt;/li&gt;
&lt;li&gt;즉, 클래스 인스턴스 만드는 일을 서브 클래스에게 맡기게 된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;br /&gt;&lt;u&gt;&lt;b&gt;  Creator&amp;nbsp;&lt;/b&gt;&lt;/u&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;nbsp;&lt;/li&gt;
&lt;li&gt;인터페이스만 제공, 실제 팩토리 메소드를 구현하고 객체 인스턴스 만드는 일은 서브 클래스에서만 할 수 있음&amp;nbsp;&lt;/li&gt;
&lt;li&gt;PizzaStore 추상클래스 상속받는 NyPizzaStore, ChicagoPizzStore&amp;nbsp;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;PizzaStore의 orderPizza : pizza = createPizzas(type) 이렇게 호출&lt;/li&gt;
&lt;li&gt;&lt;b&gt;사용하는 쪽에서 어느 PizzaStore의 orderPizza호출하냐 따라 NyPizza가 만들어질수도, ChicagoPizza가 만들어질수도 있다!&amp;nbsp;&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;즉&lt;b&gt;, 서브 클래스에서 어떤 객체가 생성될지&lt;/b&gt; 결정되는 것 !&amp;nbsp;&lt;/span&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;851&quot; data-origin-height=&quot;492&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bOGlCd/btsEhT9d59R/deuZJH6359QvHJZ4K4dMZ0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bOGlCd/btsEhT9d59R/deuZJH6359QvHJZ4K4dMZ0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bOGlCd/btsEhT9d59R/deuZJH6359QvHJZ4K4dMZ0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbOGlCd%2FbtsEhT9d59R%2FdeuZJH6359QvHJZ4K4dMZ0%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;443&quot; height=&quot;256&quot; data-origin-width=&quot;851&quot; data-origin-height=&quot;492&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;  간단한 팩토리와 팩토리 메서드 비교&amp;nbsp;&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;989&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/BOnrS/btsEkywdS8t/YXqkZfL00OtGHPN1DW3vC1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/BOnrS/btsEkywdS8t/YXqkZfL00OtGHPN1DW3vC1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/BOnrS/btsEkywdS8t/YXqkZfL00OtGHPN1DW3vC1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FBOnrS%2FbtsEkywdS8t%2FYXqkZfL00OtGHPN1DW3vC1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;625&quot; height=&quot;483&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;989&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;  추상 팩토리&amp;nbsp;&lt;/b&gt;&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;b&gt;구상 클래스에 의존하지 않고도 서로 연관되거나 의존적인 객체로 이루어진 제품군을 생산하는 인터페이스를 제공하고, 구상 클래스는 서브클래스에서 만들어진다.&amp;nbsp;&lt;/b&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;위의 시나리오에서 원재료들을 생산하는 팩토리도 만들자!&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;java&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;public interface PizzaIngredientFactory {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public Dough createDough();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public Sauce creaetSauce();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public Cheese createCheese();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public Veggies[] createVeggies();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public Pepperoni createPepperoni();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public Clams createClam();
}&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;각 스타일의 피자별로 implements PizzaIngredientFactory 해서 사용&lt;/li&gt;
&lt;li&gt;각각 createXXX 메소드를 지점별로 알맞게 만든다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;ex )&amp;nbsp; 냉동 조개를 쓸 수도 있고, 생 조개 쓸 수도 있고..!&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;기존 PizzaClass에서도 prepare()을 추상 메소드로 만든다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;&lt;b&gt;EX)   CheesePizza&amp;nbsp;&lt;/b&gt;&lt;/u&gt;&lt;/p&gt;
&lt;pre class=&quot;java&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;public class CheesePizza extends Pizza {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;PizzaIngredientFactory ingredientFactory;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public CheesePizza(PizzaIngredientFactory ingredientFactory) {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;	this.ingredientFactory = ingredientFactory;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;void prepare() {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;	dough = ingredientFactory.createDough();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sauce = ingredientFactory.createSauce();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// 등등 재료가 필요할 때마다 팩토리에 있는 메소드 호출하여 만든다
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br /&gt;&lt;u&gt;&lt;b&gt; EX)   NYPizzaStore&lt;/b&gt;&lt;/u&gt;&lt;/p&gt;
&lt;pre class=&quot;java&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;public class NYPizzaStore extends PizzaStore {
	protected Pizza createPizza(String item){
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;	Pizza pizza = null;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;PizzaIntgredientFactory ingredientFactory = new NYPizzaIngredientFactory();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// .. 중략, item별로 치즈 피자 만들기 등등 수행 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;  팩토리 메소드 패턴(PizzaStore)과 추상 팩토리 패턴(PizzaIngredientFactory) 비교&lt;/b&gt;&lt;/h4&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;2127&quot; data-origin-height=&quot;1200&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cHzmEw/btsEnbb1Jkw/MBiRsunvHobQKMJ0q7clB1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cHzmEw/btsEnbb1Jkw/MBiRsunvHobQKMJ0q7clB1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cHzmEw/btsEnbb1Jkw/MBiRsunvHobQKMJ0q7clB1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcHzmEw%2FbtsEnbb1Jkw%2FMBiRsunvHobQKMJ0q7clB1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2127&quot; height=&quot;1200&quot; data-origin-width=&quot;2127&quot; data-origin-height=&quot;1200&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;table style=&quot;border-collapse: collapse; width: 100%; height: 102px;&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: 17px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 17px; text-align: center;&quot;&gt;&lt;b&gt;   팩토리 메소드 패턴   &lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 17px; text-align: center;&quot;&gt;&lt;b&gt;   추상 팩토리 패턴   &lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 100%; height: 17px; text-align: center;&quot; colspan=&quot;2&quot;&gt;어플리케이션을 특정 구현으로부터 분리하기 위해 사용&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 17px;&quot;&gt;&lt;b&gt;&lt;u&gt;   클래스를 사용해서 만든다.&lt;/u&gt;&lt;/b&gt;&lt;br /&gt;- 상속을 통해 객체를 만든다.&amp;nbsp;&lt;br /&gt;- 클래스를 확장, 팩토리 메소드 오버라이드&lt;br /&gt;&lt;br /&gt;  PizzaStore ~ createPizza() 라는 팩토리 메소드 override&lt;br /&gt;&lt;br /&gt;  NYPizzaStore, ChicagoPizzaStore (상속)&amp;nbsp;&lt;br /&gt;&lt;br /&gt;&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 17px;&quot;&gt;&lt;u&gt;&lt;b&gt;   객체 구성을 통해 객체를 만든다.&amp;nbsp;&lt;/b&gt;&lt;/u&gt;&lt;br /&gt;- 필드로 클래스 인스턴스 참조&amp;nbsp;&lt;br /&gt;- 제품군을 만드는 추상 형식 제공&amp;nbsp;&lt;br /&gt;- 제품이 생산되는 방법은 이 형식의 서브 클래스에서 정의&lt;br /&gt;&lt;br /&gt;&lt;b&gt;  PizzaIngredientFactory&lt;/b&gt;&lt;br /&gt;- createDough, createCheese 등 추상 형식을 제공&lt;br /&gt;- 구체적으로 어떤 dough, cheese인지는 Ny, Chic(하위)에서&amp;nbsp;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;u&gt;  NyPizzaStore의 createPizza()&lt;/u&gt;&lt;/b&gt;&lt;br /&gt;PizzaIngredientFactory ingredientFactory = new NyPizzaIngredientFactory 넣어주기&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 17px;&quot;&gt;  클라이언트 코드와 인스턴스를 만들어야 할 구상 클래스를 분리&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 17px;&quot;&gt;&lt;b&gt; &lt;/b&gt;&amp;nbsp; 새로운 제품을 추가 시 인터페이스 변경이 일어난다.&amp;nbsp;&lt;br /&gt;&amp;nbsp;ex)&amp;nbsp; 현재는&amp;nbsp; dough, cheese인데 ham 이런거 추가한다면?&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 17px;&quot;&gt;  클라이언트는 자신이 사용할 추상 형식만 알고 있으면 OK&lt;br /&gt;서브 클래스에서 구상 형식을 처리 해준다.&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 17px;&quot;&gt;  팩토리를 사용하려면, 팩토리 인스턴스를 만들고, 추상 형식을 써서 만든 코드에 전달&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 17px;&quot;&gt;  어떤 구상 클래스가 필요할지 미리 알 수 없을 때에도 유용&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 17px;&quot;&gt;  클라이언트에서 서로 연관된 일련의 제품을 만들 때&amp;nbsp;즉, 제품 군을 만들 때 활용&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Java/디자인패턴</category>
      <author>Bubbles</author>
      <guid isPermaLink="true">https://bubblebubble.tistory.com/171</guid>
      <comments>https://bubblebubble.tistory.com/171#entry171comment</comments>
      <pubDate>Wed, 17 Jan 2024 11:10:53 +0900</pubDate>
    </item>
    <item>
      <title>Decorator Pattern</title>
      <link>https://bubblebubble.tistory.com/169</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;  Decorator Pattern&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;서브 클래스 만들 때보다 훨씬 유연하게 기능을 확장할 수 있음&amp;nbsp;&lt;/li&gt;
&lt;li&gt;데코레이터의 슈퍼 클래스는 자신이 장식하고 있는 객체의 슈퍼 클래스와 동일 ~ 원래 객체에 들어갈 자리에 데코레이터 넣어도 상관 X&lt;/li&gt;
&lt;li&gt;힌 객체를 여러 개의 데코레이터로 감쌀 수 있음&lt;/li&gt;
&lt;li&gt;객체는 언제든지 감쌀 수 있음, 실행중에 필요한 데코레이터를 마음대로 적용 가능&amp;nbsp;&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;1025&quot; data-origin-height=&quot;680&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bzLHTF/btsDAEdqnJN/ijiVlwuQOrOdmXDO7eHPh0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bzLHTF/btsDAEdqnJN/ijiVlwuQOrOdmXDO7eHPh0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bzLHTF/btsDAEdqnJN/ijiVlwuQOrOdmXDO7eHPh0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbzLHTF%2FbtsDAEdqnJN%2FijiVlwuQOrOdmXDO7eHPh0%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;684&quot; height=&quot;454&quot; data-origin-width=&quot;1025&quot; data-origin-height=&quot;680&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; 객체 구성(인스턴스 변수로 다른 객체 저장하는 방식) 사용 ~ 첨가물을 다양하게 추가해도 유연성을 잃지 않도록&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예시 ) 커피 주문&lt;/p&gt;
&lt;pre id=&quot;code_1704961839242&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public abstract class Beverage {
	String description = &quot;제목 없음&quot;;
    
    public String getDescription() {
    	return description;
    }
    
    public abstract double cost();
}

// 데코레이터
public abstract class CondimentDecorator extends Beverage {
	Beverage beverage;
    public abstract Stromg getDescription;
}

// 음료 
public class Espresso extends Beverage {
	public Espresso() {
    	description = &quot;에스프레소&quot;;
    }
    public double cost() {
    	return 1.9;
    }
}

// 첨가물
public class Mocha extends CondimentalDecorator {
	public Mocha(Beverage beverage) {
    	this.beverage = beverage;
    }
    
    public String getDescription() {
    	return beverage.getDescription() + &quot;, 모카&quot;;
    }
    
    public double cost() {
    	return beverage.cost() + .20;
    }
}


Beverage beverage = new DarkRoast();
beverage = new Mocha(beverage);
beverage = new Whip(beverage);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  또 다른 예시 - Java IO&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;InputStream : 추상 구성 요소&amp;nbsp;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;FileInputStream (바이트까지는 데코레이터에 감싸이는 구상 구성 요소)&lt;/li&gt;
&lt;li&gt;StringBufferInputStream&lt;/li&gt;
&lt;li&gt;ByteArrayInputStream&amp;nbsp;&lt;/li&gt;
&lt;li&gt;FileInputStream (추상 데코레이터)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;BufferedInputStream (구상 데코레이터들)&amp;nbsp;&lt;/li&gt;
&lt;li&gt;DataInputStream&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;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;h3 data-ke-size=&quot;size23&quot;&gt;  기타 주의점&amp;nbsp;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;데코레이터를 끼워 넣어도 클라이언트가 데코레이터를 사용하고 있음을 모른다는 것이 장점이다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&amp;nbsp;따라서 특정 형식에 의존하는 코드에 데코레이터 그냥 적용하면 이 장점을 살릴 수 없음&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;구성 요소 인스턴스를 꽤 많은 데코레이터로 감싸야 하는 경우가 있음&lt;/li&gt;
&lt;li&gt;잡다한 클래스가 너무 많아질 수도 있음&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Java/디자인패턴</category>
      <author>Bubbles</author>
      <guid isPermaLink="true">https://bubblebubble.tistory.com/169</guid>
      <comments>https://bubblebubble.tistory.com/169#entry169comment</comments>
      <pubDate>Thu, 11 Jan 2024 17:39:40 +0900</pubDate>
    </item>
    <item>
      <title>Observer Pattern</title>
      <link>https://bubblebubble.tistory.com/168</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;  Observer Pattern이란 무엇인가?&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;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;주제에서 중요한 데이터 관리 &amp;rarr; 주제 데이터 바뀌면 옵저버에게 바뀐 값 / 바뀌었다는 소식이 전해진다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;옵저버 객체들은 주제를 구독하고 있으며(주제 객체에 등록되어 있음), 주제 데이터가 바뀌면 갱신 내용을 전달받는다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;Subject : Observer = 1 : N 관계&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-01-04 오후 5.23.39.png&quot; data-origin-width=&quot;1310&quot; data-origin-height=&quot;718&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b9fiLw/btsC2CgFt72/P0hWOmwCRJlskcLSZVmnp1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b9fiLw/btsC2CgFt72/P0hWOmwCRJlskcLSZVmnp1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b9fiLw/btsC2CgFt72/P0hWOmwCRJlskcLSZVmnp1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb9fiLw%2FbtsC2CgFt72%2FP0hWOmwCRJlskcLSZVmnp1%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;609&quot; height=&quot;334&quot; data-filename=&quot;스크린샷 2024-01-04 오후 5.23.39.png&quot; data-origin-width=&quot;1310&quot; data-origin-height=&quot;718&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1704357359183&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public interface Subject {
	public void registerObserver(Observer o);
	public void removeObserver(Observer o);
	public void notifyObservers(); // 모든 옵저버들에게 변경내용을 알리려 호출하는 메소드
}

public interface Observer {
	public void update(float temp, float humidity, float pressure);
} // 기상 정보가 변경되었을 때 옵저버에게 전달되는 상태값들&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; color: #000000; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;여기까지는 Subject가 Observer들에게 Push 하는 방식&amp;nbsp;&lt;/li&gt;
&lt;li&gt;반대로 Observer들이 Pull 해오는 방식도 있다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1704357723448&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// Subject : 알림 보내기 
public void notifyObservers() {
	for (Observer observer : observers) {
		observer.update();
	} // update 메소드 인자 없이 호출하도록 
}


// Observer : 알림 받기 
public interface Observer {
	public void update();
}

// CurrentConditionsDisplay 클래스라면 업데이트를 아래처럼 구현하면 된다. 
public void update() {
	this.temperature = weatherData.getTemperature();
	this.humidity = weather.getHumidity();
	display();
} // 원하는 데이터만 (온도, 습도) 받아올 수 있다!&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;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt; &amp;nbsp;활용 방안&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000; letter-spacing: 0px;&quot;&gt;옵저버 패턴에서 변하는 것은 주제의 상태와 옵저버의 개수, 형식&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000; letter-spacing: 0px;&quot;&gt;옵저버 패턴에서는 주제를 바꾸지 않고도 주제의 상태에 의존하는 객체를 바꿀 수 있음&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000; letter-spacing: 0px;&quot;&gt;나중에 바뀔것을 대비해두면 편하게 작업할 수 있다&lt;/span&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;span style=&quot;letter-spacing: 0px;&quot;&gt;주제는 Subject interfcae, 옵저버는 Observer interface&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000; letter-spacing: 0px;&quot;&gt;Observer 인터페이스를 구현하는 객체들의 등록과 탈퇴를 관리하고, 그런 객체들에 연락 돌림&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;상속보다는 구성을 활용하자&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Java/디자인패턴</category>
      <author>Bubbles</author>
      <guid isPermaLink="true">https://bubblebubble.tistory.com/168</guid>
      <comments>https://bubblebubble.tistory.com/168#entry168comment</comments>
      <pubDate>Thu, 4 Jan 2024 18:07:55 +0900</pubDate>
    </item>
    <item>
      <title>[ 이모저모 ] ERD 설계(1) - 회원 도메인</title>
      <link>https://bubblebubble.tistory.com/166</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;최근 새롭게 프로젝트를 시작했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지그재그 서비스를 클론코딩한 프로젝트이고, 개인 프로젝트로 백엔드 API 쪽을 구현해보기로 했다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 포스팅에서는 ERD 설계 관련해서 고민하고, 피드백을 받아 수정한 것들에 대해 정리하려 한다.&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; 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;p data-ke-size=&quot;size18&quot;&gt;먼저 구현할 기능들을 &lt;b&gt;&lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;User Story&lt;/span&gt;&lt;/b&gt; 형태로 정리해보면 다음과 같다.&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;회원은 카카오, 네이버 로그인을 통해 서비스에 회원 가입 및 로그인할 수 있다.&lt;/li&gt;
&lt;li&gt;회원은 언제든 서비스 탈퇴가 가능하다.&lt;/li&gt;
&lt;li&gt;회원은 4가지의 등급별로 매달 등급 쿠폰을 발급받을 수 있다.&lt;/li&gt;
&lt;li&gt;회원은 만료된 쿠폰, 소지하고 있는 쿠폰, 발급 가능한 쿠폰 목록을 확인할 수 있다.&lt;/li&gt;
&lt;li&gt;회원은 구매 확정한 주문에 포함한 상품들에 대해 확정 후 30일 이내로 리뷰를 작성할 수 있다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;회원은 작성한 리뷰를 수정할 수 있다.&lt;/li&gt;
&lt;li&gt;회원은 작성 가능한 리뷰, 작성한 리뷰, 작성 만료된 리뷰 목록을 확인할 수 있다.&lt;/li&gt;
&lt;li&gt;회원은 구매 확정한 주문에 대한 적립금을 받을 수 있으며, 적립금의 사용 기한은 1년이다.&lt;/li&gt;
&lt;li&gt;회원은 적립금에 대한 적립, 사용, 만료 내역을 조회할 수 있다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;회원은 상품을 찜하거나 삭제할 수 있다. (위시리스트)&lt;/li&gt;
&lt;li&gt;회원은 장바구니에 상품을 저장할 수 있다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;회원은 장바구니에서 선택한 상품들에 대해 주문을 진행할 수 있다.&lt;/li&gt;
&lt;li&gt;회원은 주문 시 장바구니와 쿠폰, 프로모션 등을 적용할 수 있다.&amp;nbsp;&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;회원, 비회원은 쇼핑몰 또는 상품 이름, 태그로 검색이 가능하다.&amp;nbsp;&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;크게 도메인은 회원, 스토어, 주문 3가지 정도로 구분할 수 있다.&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;회원 도메인 : 회원, 리뷰, 위시, 즐겨찾기 관련 테이블&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스토어 도메인 : 프로모션, 쇼핑몰, 상품 관련 테이블&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;주문 도메인 : 장바구니, 주문 관련 테이블&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&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;설계한 전체 ERD는 아래와 같다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개발하면서 조금씩 바뀔수도 있겠지만, 일단은 아래처럼 확정하였다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;edited_Copy of 지그재그-2.png&quot; data-origin-width=&quot;2457&quot; data-origin-height=&quot;954&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/k4yOb/btsCF6QoZQX/50rd8kRT9QBzvAa2kmvfP0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/k4yOb/btsCF6QoZQX/50rd8kRT9QBzvAa2kmvfP0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/k4yOb/btsCF6QoZQX/50rd8kRT9QBzvAa2kmvfP0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fk4yOb%2FbtsCF6QoZQX%2F50rd8kRT9QBzvAa2kmvfP0%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;2457&quot; height=&quot;954&quot; data-filename=&quot;edited_Copy of 지그재그-2.png&quot; data-origin-width=&quot;2457&quot; data-origin-height=&quot;954&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;회원 도메인에서 고민했던 것들은 2가지 정도였다.&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;1. 적립금 관련해서 이력들을 다 보여줘야 하는데, 적립금 총액을 회원 테이블에 가지고 있어야 하는가?&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 찜과 장바구니, 2가지를 합칠 수 있을까?&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&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;h3 data-ke-size=&quot;size23&quot;&gt;✅ 회원 테이블에 적립금 총액 Column을 만들자.&amp;nbsp;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-12-13 오전 1.14.19.png&quot; data-origin-width=&quot;1346&quot; data-origin-height=&quot;982&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dW0Gym/btsBQoquLVI/Kn9tbtyRZXK5KQmlDzhZK0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dW0Gym/btsBQoquLVI/Kn9tbtyRZXK5KQmlDzhZK0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dW0Gym/btsBQoquLVI/Kn9tbtyRZXK5KQmlDzhZK0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdW0Gym%2FbtsBQoquLVI%2FKn9tbtyRZXK5KQmlDzhZK0%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;684&quot; height=&quot;499&quot; data-filename=&quot;스크린샷 2023-12-13 오전 1.14.19.png&quot; data-origin-width=&quot;1346&quot; data-origin-height=&quot;982&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;처음에는 적립금 총액(reserve_sum) 칼럼을 회원 테이블에 만들어두지 않았다.&lt;/li&gt;
&lt;li&gt;정규화를 생각해서 분리해두고, 그때 그때 계산해야지라는 ... 생각을 했었다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;하지만, 아래와 같은 질문을 생각해보자.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-ke-size=&quot;size16&quot; data-ke-style=&quot;style1&quot;&gt;한 회원이 매일매일 만 건 씩 주문하면 어떻게 될까요?&lt;br /&gt;유효기간이 1년이면, 몇 건이 저장될까요?&lt;br /&gt;그렇다면 데이터를 계산할 때 연산이 얼마가 들까요? &amp;nbsp;&lt;/blockquote&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;위 상황을 가정하면 360만건이다. 아주 극단적인 예시지만, 유저 여럿이 있다고 생각해보면 충분히 가능한 데이터 양이다.&lt;/li&gt;
&lt;li&gt;그럼 이 상황에서 &lt;span style=&quot;background-color: #dddddd;&quot;&gt;&lt;b&gt;특정 회원의 사용 가능한 적립금 총액&lt;/b&gt;&lt;/span&gt;을 계산하려면 어떻게 할까?&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;GROUP BY 연산&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;우선 데이터베이스 자체에 Native Query 날려서 status 별로 분리한 후 계산하여 가져오는 방식&lt;/li&gt;
&lt;li&gt;데이터 자체가 몇 백만건이므로 굉장히 느릴 것&amp;nbsp;&lt;/li&gt;
&lt;li&gt;데이터베이스 자체에 부하를 주는 것이므로 ! 다른 기능들도 영향을 받을 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Application 단에서 연산하기&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;userIdx로 가져온 360만건의 데이터를 그냥 어플리케이션 단으로 올려준다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;데이터베이스 자체에서 연산하진 않으므로 데이터베이스 쪽은 괜찮을지도 모른다.&lt;/li&gt;
&lt;li&gt;하지만 이 방식 또한 JVM 메모리를 생각해보면 불가능하다는 것을 알 수 있다.&amp;nbsp;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;JVM의 Heap 사이즈는 전체 메모리의 1/64가 기본이고, 메모리의 1/4까지 늘어날 수 있다.&amp;nbsp;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Initial heap size of 1/64 of physical memory&lt;/li&gt;
&lt;li&gt;Maximum heap size of 1/4 of physical memory &lt;a href=&quot;https://docs.oracle.com/en/java/javase/11/gctuning/ergonomics.html#GUID-DA88B6A6-AF89-4423-95A6-BBCBD9FAE781&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;(oracle docs)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;주로 운영환경에서는, JVM의 메모리 최소 최대 크기를 동일하게 맞춰둔다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;유동적으로 조절하게 되면, 나중에 JVM이 추가 메모리 요청했을 때 Native 영역에서 못 준다고 하면?&amp;nbsp;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;바로 Out Of Memory 에러 내면서 프로그램이 죽는다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;이 사이즈만큼 메모리 확보해두고, 이 안에서 최대한 버티면서 GC로 메모리를 확보한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;위 2가지를 생각해보면, 제한된 Heap 내에서 GC로 최대한 버티면서 사용하는 것이 메모리 전략이다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;그런데, 데이터 360만건을 메모리에서 처리한다?&amp;nbsp;&lt;/li&gt;
&lt;li&gt;이 데이터 자체가 커서 메모리를 많이 잡아먹으므로, &lt;b&gt;GC가 빈번하게 일어난다.&lt;/b&gt;&amp;nbsp;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;(360만건의 데이터들은 우리가 계산해야 할, reachable 객체이므로 GC 대상이 아니다. 따라서 다른 곳에서 메모리를 확보해야 한다.)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;최악의 경우, GC를 계속해도 메모리 확보가 되지 못해서 Out Of Memory 낼 위험도 있다.&amp;nbsp;&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;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;  그렇다면, 적립금 계산이 바뀔 때에도, 회원 정보가 바뀔 때에도 &lt;br /&gt;같은 회원 테이블에 접근해야 하지 않나요?&amp;nbsp;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 경우에는 어플리케이션 단에서 좀 완화할 수 있는 방법이 있을 것 같다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;트랜잭션 전파 - REQUIRES_NEW 를 사용 : &amp;nbsp;적립금 / 회원 정보 이 2가지 관심사를 분리할 수 있다.&lt;/li&gt;
&lt;li&gt;메서드 단에서 로직 분리 처리 등등...!&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;✅&lt;span&gt;&amp;nbsp; 찜과 장바구니는 분리하자.&amp;nbsp;&lt;/span&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;하지만 도메인 측면에서도 찜은 사용자와 더 가깝고, 장바구니는 주문 도메인과 더 가깝다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한 장바구니는 상품 옵션과 수량이라는 정보까지 가지고 있어야 하는데에 반해, 찜은 그냥 해당 상품 자체에 누른다. (지그재그 기준)&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇기 때문에 2가지 테이블은 분리해야 한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어찌보면 당연한건데 처음에 둘이 비슷해서 그냥 합쳐두는게 편하지 않나? 라고 단순하게 생각했었다...;;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Projects</category>
      <author>Bubbles</author>
      <guid isPermaLink="true">https://bubblebubble.tistory.com/166</guid>
      <comments>https://bubblebubble.tistory.com/166#entry166comment</comments>
      <pubDate>Wed, 13 Dec 2023 02:31:58 +0900</pubDate>
    </item>
    <item>
      <title>프로그래머스 - 단속카메라, 백준 13549, 5427</title>
      <link>https://bubblebubble.tistory.com/164</link>
      <description>&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://school.programmers.co.kr/learn/courses/30/lessons/42884&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://school.programmers.co.kr/learn/courses/30/lessons/42884&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1699549634583&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;프로그래머스&quot; data-og-description=&quot;코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.&quot; data-og-host=&quot;programmers.co.kr&quot; data-og-source-url=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/42884&quot; data-og-url=&quot;https://programmers.co.kr/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/cf3BTP/hyUrAsPEXV/YTxE2Bv8ckWNFsTMknKXSK/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/bUtsut/hyUuQ8CM8k/bf3r3ColgRbqKhLakvFrrk/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630&quot;&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/42884&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/42884&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/cf3BTP/hyUrAsPEXV/YTxE2Bv8ckWNFsTMknKXSK/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/bUtsut/hyUuQ8CM8k/bf3r3ColgRbqKhLakvFrrk/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;프로그래머스&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;programmers.co.kr&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt; &lt;b&gt;그리디 알고리즘 문제&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt; 진입 / 진출 지점에서 만난 것도 만난 것으로 인정하므로 구간 끝에 카메라를 설치한다고 생각하면 된다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt; 여기서 진입 지점으로 정렬할지 진출 지점으로 정렬할지 헷갈렸는데 진출 시점으로 정렬해야 한다. 첫 구간이 아주 길다면 내부 구간이 다 무시되기 때문이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt; &lt;b&gt;그림 설명&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1553&quot; data-origin-height=&quot;1233&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mgP8V/btsz44NYyjQ/BZ6espKPiWFH1VsdYSsuxk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mgP8V/btsz44NYyjQ/BZ6espKPiWFH1VsdYSsuxk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mgP8V/btsz44NYyjQ/BZ6espKPiWFH1VsdYSsuxk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmgP8V%2Fbtsz44NYyjQ%2FBZ6espKPiWFH1VsdYSsuxk%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;589&quot; height=&quot;468&quot; data-origin-width=&quot;1553&quot; data-origin-height=&quot;1233&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt; 전체코드&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참고로 pivot은 이 구간의 최솟값이 -30000이라 -30001로 초기화하였다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1699550839527&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import java.util.*;
class Solution {
    public int solution(int[][] routes) {
        PriorityQueue&amp;lt;Route&amp;gt; queue = new PriorityQueue&amp;lt;&amp;gt;((o1, o2) -&amp;gt; o1.end - o2.end);
        
        for (int[] route : routes) {
            queue.add(new Route(route[0], route[1]));
        }
        
        int answer = 0;
        int pivot = -30001;
        while (!queue.isEmpty()) {
            Route route = queue.poll();
            if (route.start &amp;gt; pivot) {
                pivot = route.end;
                answer++;
            }
        }
        return answer;
    }
    
    class Route {
        int start;
        int end;
        Route(int start, int end) {
            this.start = start;
            this.end = end;
        }
    }
}&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 contenteditable=&quot;false&quot; 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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  백준 13549 : 숨바꼭질 3&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/13549&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.acmicpc.net/problem/13549&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1699895258803&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;13549번: 숨바꼭질 3&quot; data-og-description=&quot;수빈이는 동생과 숨바꼭질을 하고 있다. 수빈이는 현재 점 N(0 &amp;le; N &amp;le; 100,000)에 있고, 동생은 점 K(0 &amp;le; K &amp;le; 100,000)에 있다. 수빈이는 걷거나 순간이동을 할 수 있다. 만약, 수빈이의 위치가 X일 때 &quot; data-og-host=&quot;www.acmicpc.net&quot; data-og-source-url=&quot;https://www.acmicpc.net/problem/13549&quot; data-og-url=&quot;https://www.acmicpc.net/problem/13549&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/4E8xJ/hyUylUFEuV/VccrifIjwYAj77kzO6sVtK/img.png?width=2834&amp;amp;height=1480&amp;amp;face=0_0_2834_1480&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/13549&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.acmicpc.net/problem/13549&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/4E8xJ/hyUylUFEuV/VccrifIjwYAj77kzO6sVtK/img.png?width=2834&amp;amp;height=1480&amp;amp;face=0_0_2834_1480');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;13549번: 숨바꼭질 3&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;수빈이는 동생과 숨바꼭질을 하고 있다. 수빈이는 현재 점 N(0 &amp;le; N &amp;le; 100,000)에 있고, 동생은 점 K(0 &amp;le; K &amp;le; 100,000)에 있다. 수빈이는 걷거나 순간이동을 할 수 있다. 만약, 수빈이의 위치가 X일 때&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.acmicpc.net&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;  BFS 알고리즘 문제&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;  수빈 위치와 동생 위치가 같다면 바로 0 출력해주고 끝난다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;  방문 배열에 방문 처리 하고, 최단 시간 찾는 것이므로 BFS로 풀면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;  순간이동 한 경우 / 걸은 경우 시간은 다르게 표현해줘야 하며, 배열의 인덱스를 넘어가지 않도록 if 조건 분기만 잘 나누어주면 어렵지 않게 풀 수 있다&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;  전체코드&lt;/p&gt;
&lt;pre id=&quot;code_1699894497074&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;

public class p13549 {
    public static void main(String[] args) {
        int[] arr = new int[100001];
        boolean[] visited = new boolean[100001];
        Scanner sc = new Scanner(System.in);
        Queue&amp;lt;Integer&amp;gt; queue = new LinkedList&amp;lt;&amp;gt;();

        int n = sc.nextInt();
        int k = sc.nextInt();
        queue.add(n);
        visited[n] = true;
        arr[n] = 1;
        if (n == k) {
            System.out.println(0);
            return;
        }

        while (!queue.isEmpty()) {
            int poll = queue.poll();
            if (poll == k) {
                System.out.println(arr[poll] -1);
                break;
            }

            if (poll &amp;lt;= 50000 &amp;amp;&amp;amp; !visited[poll*2]) {
                arr[poll*2] = arr[poll];
                visited[poll*2] = true;
                queue.add(poll*2);
            }
            if (poll &amp;gt; 0 &amp;amp;&amp;amp; !visited[poll-1]) {
                arr[poll-1] = arr[poll] + 1;
                visited[poll-1] = true;
                queue.add(poll-1);
            }
            if (poll &amp;lt; 100000 &amp;amp;&amp;amp; !visited[poll+1]) {
                arr[poll+1] = arr[poll] + 1;
                visited[poll+1] = true;
                queue.add(poll+1);
            }

        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; 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;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;h3 data-ke-size=&quot;size23&quot;&gt;  백준 5427 : 불&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/5427&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.acmicpc.net/problem/5427&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1700060440456&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;5427번: 불&quot; data-og-description=&quot;상근이는 빈 공간과 벽으로 이루어진 건물에 갇혀있다. 건물의 일부에는 불이 났고, 상근이는 출구를 향해 뛰고 있다. 매 초마다, 불은 동서남북 방향으로 인접한 빈 공간으로 퍼져나간다. 벽에&quot; data-og-host=&quot;www.acmicpc.net&quot; data-og-source-url=&quot;https://www.acmicpc.net/problem/5427&quot; data-og-url=&quot;https://www.acmicpc.net/problem/5427&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/cnZLQO/hyUym0JYwQ/uV1LE1XyBLOtcFcB0ltAVk/img.png?width=2834&amp;amp;height=1480&amp;amp;face=0_0_2834_1480&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/5427&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.acmicpc.net/problem/5427&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/cnZLQO/hyUym0JYwQ/uV1LE1XyBLOtcFcB0ltAVk/img.png?width=2834&amp;amp;height=1480&amp;amp;face=0_0_2834_1480');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;5427번: 불&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;상근이는 빈 공간과 벽으로 이루어진 건물에 갇혀있다. 건물의 일부에는 불이 났고, 상근이는 출구를 향해 뛰고 있다. 매 초마다, 불은 동서남북 방향으로 인접한 빈 공간으로 퍼져나간다. 벽에&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.acmicpc.net&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt; &lt;a href=&quot;https://www.acmicpc.net/problem/4179&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;백준 4179번 - 불!&lt;/a&gt; 과 느낌표 하나 차이로 다른 문제가 있어서 풀어봤다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt; 동일하게 BFS 문제이다.&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; 불이 아예 없는 경우(fires.isEmpty())인 경우 불 BFS 돌리지 않도록 하기&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt; 불이 있어도 불 자체가 벽으로 둘러쌓여서 못 퍼지는 경우 있을 수도 있다. 이 경우 visitied 값이 0이라 탈출 못한걸로 판정나는 실수가 있었는데, 그래서 마지막 정답 비교조건에서 불길이 아예 닿지 않았거나, 나의 도착시간이 불보다 빠른 경우에 정답을 갱신하도록 만들었다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt; 이 2가지 예외처리만 잘 해준다면 이전에 풀었던 문제와 유사한 문제였다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt; 전체코드&lt;/p&gt;
&lt;pre id=&quot;code_1700060496804&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import java.io.*;
import java.util.*;
public class p5427 {
    private static char[][] map;
    private static int[][] visited;
    private static int[] dirX = { 0, 0, 1, -1 }; // 동서남북
    private static int[] dirY = { 1, -1, 0, 0 };
    private static int row, col;
    private static Pos me;
    private static List&amp;lt;Pos&amp;gt; fires;

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int n = Integer.parseInt(br.readLine());

        for (int i = 0; i &amp;lt; n; i++) {
            StringTokenizer st = new StringTokenizer(br.readLine());
            col = Integer.parseInt(st.nextToken());
            row = Integer.parseInt(st.nextToken());

            map = new char[row][col];
            visited = new int[row][col];
            fires = new ArrayList&amp;lt;&amp;gt;();

            for (int j = 0; j &amp;lt; row; j++) {
                String line = br.readLine();
                for (int k = 0; k &amp;lt; col; k++) {
                    map[j][k] = line.charAt(k);
                    if (map[j][k] == '@') {
                        me = new Pos(j, k);
                    }
                    else if (map[j][k] == '*') {
                        fires.add(new Pos(j, k));
                    }
                }
            }

            int answer = BFS();
            if (answer == Integer.MAX_VALUE) {
                System.out.println(&quot;IMPOSSIBLE&quot;);
            } else {
                System.out.println(answer);
            }
        }

    }


    private static int BFS() {
        int answer = Integer.MAX_VALUE;
        Map&amp;lt;Pos, Integer&amp;gt; time = new HashMap&amp;lt;&amp;gt;();
        Queue&amp;lt;Pos&amp;gt; queue = new LinkedList&amp;lt;&amp;gt;();

        queue.add(me);
        visited[me.x][me.y] = 1;
        while (!queue.isEmpty()) {
            Pos poll = queue.poll();
            for (int i = 0; i &amp;lt; 4; i++) {
                int nextX = poll.x + dirX[i];
                int nextY = poll.y + dirY[i];

                if (nextX &amp;lt; 0|| nextX &amp;gt;= row || nextY &amp;lt; 0 || nextY &amp;gt;= col) {
                    time.put(new Pos(poll.x, poll.y), visited[poll.x][poll.y]);
                    continue;
                }

                if (map[nextX][nextY] != '.') {
                    continue;
                }

                if (visited[nextX][nextY] != 0) {
                    continue;
                }

                queue.add(new Pos(nextX, nextY));
                visited[nextX][nextY] = visited[poll.x][poll.y] + 1;
            }
        }

        if (fires.isEmpty()) {
            for (Integer i : time.values()) {
                answer = Math.min(answer, i);
            }
            return answer;
        }

        // 불 퍼트리기
        queue = new LinkedList&amp;lt;&amp;gt;();
        visited = new int[row][col];
        queue.addAll(fires);
        for (Pos p : fires) {
            visited[p.x][p.y] = 1;
        }


        while (!queue.isEmpty()) {
            Pos poll = queue.poll();
            for (int i = 0; i &amp;lt; 4; i++) {
                int nextX = poll.x + dirX[i];
                int nextY = poll.y + dirY[i];

                if (nextX &amp;lt; 0 || nextX &amp;gt;= row || nextY &amp;lt; 0 || nextY &amp;gt;= col) {
                    continue;
                }

                if (map[nextX][nextY] == '#') {
                    continue;
                }

                if (visited[nextX][nextY] != 0) {
                    continue;
                }

                queue.add(new Pos(nextX, nextY));
                visited[nextX][nextY] = visited[poll.x][poll.y] + 1;
            }
        }

        for (Pos pos : time.keySet()) {
            if (visited[pos.x][pos.y] == 0 || time.get(pos) &amp;lt; visited[pos.x][pos.y]) {
                answer = Math.min(answer, time.get(pos));
            }
        }


        return answer;
    }

    private static class Pos {
        int x;
        int y;

        public Pos (int x, int y) {
            this.x = x;
            this.y = y;
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Java/코딩테스트</category>
      <author>Bubbles</author>
      <guid isPermaLink="true">https://bubblebubble.tistory.com/164</guid>
      <comments>https://bubblebubble.tistory.com/164#entry164comment</comments>
      <pubDate>Fri, 10 Nov 2023 02:28:18 +0900</pubDate>
    </item>
    <item>
      <title>CS - Java &amp;amp; Spring 정리</title>
      <link>https://bubblebubble.tistory.com/163</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;h3 data-ke-size=&quot;size23&quot;&gt;  Java 문법 &amp;amp; 특징&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;  자바는 인터프리터 언어인가요? 컴파일 언어인가요? &amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;자바는 2가지 방식을 모두 혼합하여 사용합니다.&amp;nbsp;자바 컴파일러가 .java 파일을 컴파일을 통해 .class파일을 만들고,&amp;nbsp;JVM의 실행 엔진의 인터프리터가 각 운영체제에 맞게 이진 코드로 변환 후 실행합니다.&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;b&gt; &amp;nbsp;&lt;/b&gt;자바 프로그램의 수행 과정에 대해 말씀해주세요.&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;자바 소스 코드를 프로그래머가 작성(.java) &amp;rarr; &amp;nbsp;자바 컴파일러가 바이트 코드로 변환 (.class) &amp;rarr; JVM 클래스로더로 전달, 클래스 로더가 JVM의 Runtime Data Area(JVM이 OS로부터 할당받는 메모리영역)에 올린다. &amp;rarr; 실행 엔진이 바이트 코드들을 명령어 단위로 하나씩 가져와서 실행합니다.&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;b&gt; &amp;nbsp;&lt;/b&gt;Java의 String 클래스에서 equals()와 == 차이가 무엇인가요?&amp;nbsp;&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;equals()는 참조 변수의 값이 같은지 비교하는 메소드로, 재정의 되어있지 않다면 객체의 주소값을 비교하여 동일 객체인지 비교후 boolean 값을 리턴하는 메소드입니다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;== 연산자는 primitive type일 경우 값을, 그 외에는 주소값을 비교하는 연산자입니다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;String 클래스에 equals를 사용할 경우에는 주소값이 아닌 데이터 값을 비교하여 동일 여부를 판정합니다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;==을 사용하는 경우, 같은 문자열을 가지고 있어도 객체끼리 주소가 다르기 때문에 다르다고 판정합니다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;만약 String a = &quot;hello&quot; String b = &quot;hello&quot; 이런식으로 문자열로 생성할 경우 a를 생성할 때 String constant pool에 먼저 hello를 저장해둬서, b를 생성할 때 기존에 있는 hello를 참조하는 방식으로 생성하므로 이 경우엔 == 연산의 결과가 true이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;color: #333333; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;b&gt; &amp;nbsp;&lt;/b&gt;equals() 함수만 오버라이딩하고 hashCode()는 오버라이딩 하지 않으면 어떤 문제가 발생할까요?&amp;nbsp;&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;equals()는 객체의 주소값을 비교하여 동일 객체인지 비교후 boolean 값을 리턴하는 메소드입니다.&lt;/li&gt;
&lt;li&gt;hashCode()는 객체의 주소값을 이용하여 해싱 기법을 적용한 결과값을 리턴하는 메소드입니다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;자바의 해시 컬렉션은 동일 객체인지 판정할 때 hashCode() 값이 같은지 먼저 확인하고 같다면 equals()함수를 호출하여 같은지 총 2번의 확인 작업을 거칩니다.&amp;nbsp;equals()만 오버라이딩할 경우, hashCode() 값이 달라 다른 객체로 판단되어 동일하다고 의도했던 두 객체가 모두 추가되는 등 원치 않은 방향으로 동작할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;color: #333333; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;b&gt; &amp;nbsp;&lt;/b&gt;Java는 매개변수를 call by value로 전달하나요 call by reference로 전달하나요?&amp;nbsp;&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;Call by value는 메소드의 매개변수로 값을 넘길때 원래 값은 놔두고, 새롭게 값을 복제하여 넘기는 방식입니다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Call by reference는 매개변수로 넘어온 값의 참조 자체를 넘기는 방식입니다.&lt;/li&gt;
&lt;li&gt;자바의 참조형때문에 call by reference라고 생각하기 쉽지만, 주소 값을 전달하는 방식입니다.&amp;nbsp;&lt;br /&gt;참조 자체를 넘긴다면 new로 할당을 했을 때 methodA의 원래 값도 new로 할당한 값으로 변화해야 하지만, 자바는 그렇지 않기 때문입니다. (포인터처럼 메모리에 직접 new 할당하면 해당 객체 쓰는 메소드들 다 영향 받음)&lt;br /&gt;&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;color: #333333; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;b&gt; &amp;nbsp;&lt;/b&gt;Overloading과 Overriding의 차이점이 무엇인가요?&amp;nbsp;&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;nbsp;중복 정의&amp;nbsp;하는 것이다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000; letter-spacing: 0px;&quot;&gt;오버라이딩은 부모 클래스로부터 상속받은 메소드를 자식 클래스에서&lt;/span&gt;&lt;span style=&quot;color: #000000; letter-spacing: 0px;&quot;&gt;&amp;nbsp;재 정의하는&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #000000; letter-spacing: 0px;&quot;&gt;것이다.&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #000000; letter-spacing: 0px;&quot;&gt;부모 클래스의 메소드를 호출해도 실제 타입이 자식 클래스이면 자식 클래스의 메소드가 호출된다.&amp;nbsp;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;color: #333333; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;b&gt;  인터페이스와 추상 클래스의 차이점이 무엇인가요?&lt;/b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;추상 클래스는 abstract로 선언되어 있거나 추상 메소드가 하나 이상 포함된 클래스를 의미합니다.&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;인터페이스는 추상 메소드와 public 정적 상수들만 가지는 구조를 의미합니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;추상클래스는 다중 상속이 불가능하고 인터페이스는 다중 상속(구현)이 가능합니다.&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;b&gt; &amp;nbsp;&lt;/b&gt;다수의 인터페이스를 구현하는 것은 가능한데, 여러 개의 클래스를 상속은 불가능한 이유가 무엇일까요?&amp;nbsp;&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;하나의 클래스가 같은 메소드 이름을 가진 복수의 상위 클래스를 상속받는다면, 해당 클래스는 어느 메소드를 상속받은 것인지 모호해진다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;EX) 물고기 클래스와 사람 클래스 2가지를 상속받은 인어 클래스의 swim 메소드는 물고기처럼 수영할까 사람처럼 수영할까?&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;인터페이스의 경우 구현해야할 행위 자체만을 나타낸 추상 메서드로 이루어져 있으므로, 중간에 구현체가 끼지 않아 다중 구현이 허용된다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;b&gt; &amp;nbsp;&lt;/b&gt;Java의 Thread는 어째서 사용하고, Runnable 인터페이스를 구현하는 방식과 Thread 클래스를 상속받는 방식 중, 어떤 방식으로 구현하는 것이 좋을까요?&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;자바 언어에서는 다중 상속이 지원되지 않으므로, 다른 클래스를 상속받을 가능성을 생각하여 Runnable 인터페이스를 구현하는 방식으로 사용하는 것이 좀 더 권장됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;color: #333333; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;b&gt; &amp;nbsp;&lt;/b&gt;Arrays.asList() 함수로 생성한 리스트는 어떤 특징을 가지나요?&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;remove, add 메소드를 제공하지 않아 엘리먼트를 추가하거나 삭제하는 등의 작업이 불가합니다.(실행 시 unsupportedOperationException 발생)&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;사이즈를 변경할 수 없고 값만 꺼낼 수 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;b&gt; &amp;nbsp;&lt;/b&gt;함수형 인터페이스는 왜 필요할까요?&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;람다식은 익명 함수(객체)여서 함수를 부를 이름이 없으므로 람다식으로 만든 객체에 접근하기 위해 1개의 추상 메소드만를 가지고 있는 함수형 인터페이스를 사용합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;b&gt; &amp;nbsp;&lt;/b&gt;stream을 사용함으로서 얻는 장점이 무엇인가요?&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Java 8의 stream은 함수형 프로그램의 특징들을 대입하여, 기존의 Collection을 다루는 방법보다 간결하고 가독성이 좋도록 개선되었습니다. Lambda 구문을 사용하여 for문, if문 등을 사용하지 않아 더욱 직관적인 코드 작성에 편리하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원본 데이터를 바꾸지는 않으며, 재사용 불가하므로 stream 연산 결과를 컬렉션으로 반환하여 사용해야 합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;b&gt;  Error와 Checked Exception, Unchecked Exception의 차이가 무엇인가요?&amp;nbsp;&lt;/b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 프로그램 외부에서 발생하여 프로그램이 멈추는 것은 Error입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로그램 내부에서 발생하고, 스레드에만 영향을 주어 프로그램 자체는 계속 실행 가능한 것은 Exception입니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;Exception에는 checked, unchecked 2가지 종류가 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;Runtime Exception 이라고도 하는 Unchecked Exception은 컴파일 시 체크하지 않으며 예외처리를 강제하지 않는, 실행 중 발생가능한 예외를 의미합니다. ArrayIndexOutOfBounds, NullPointerException 등이 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;Checked Exception은&amp;nbsp;Exception 클래스의 하위 클래스 중 Runtime Exception을 제외한 나머지로, 컴파일러가 예외처리를 확인하여 반드시 예외처리가 되어야 하는 예외를 의미합니다. IOException 등이 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;b&gt; Java의 Access Modifier 에 대해서 설명해주세요.&lt;/b&gt;&lt;/b&gt;&lt;b&gt;&lt;b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;접근 제어자는 변수, 메소드의 접근 범위를 설정해주기 위해 사용하는 예약어입니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;public, protected(동일패키지, 외부라도 상속받았다면 ok), default(동일패키지), private(해당 클래스 내)이 있습니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;b&gt;  Junit에 대해 설명해주세요.&lt;/b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;Junit은 자바 언어의 단위 테스트 프레임워크입니다. 단위 테스트는 프로그램의 개별 코드 조각들이 의도대로 작동하는지 검증하는 테스트입니다. 단위 테스트를 작성하고 실행하기 위한 도구로 사용됩니다. &amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;b&gt;  Object 클래스에 대해 설명해주세요.&lt;/b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;자바 모든 클래스의 최상위 클래스로 모든 클래스가 상속하게 되는 기본 클래스입니다. 아무런 클래스도 상속하지 않는 클래스더라도 Java 컴파일러가 자동으로 extends Object 코드를 넣어줍니다. Object 클래스에는 equals, hashCode, toString 등 객체들이 공통적으로 가지는 메소드들이 정의되어 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;b&gt;  객체 지향 프로그래밍에서의 메소드 호출과 관련된 2가지 다른 바인딩 방식에 대해 설명해주세요.&lt;/b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;정적 바인딩&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;컴파일 &amp;nbsp;시 변수 / 참조 타입을 기반으로 어떤 메소드 호출되어 실행해야 하는지 결정. 오버로딩된 메소드들의 호출에서 주로 발생합니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;동적 바인딩&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;실행 시간에 메소드 호출과 실제 실행될 메소드를 결정하는 것으로, 객체 실제 타입을 확인하고 해당 객체에 맞는 메소드를 호출합니다.&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;b&gt;  직렬화에 대해 설명해주세요.&lt;/b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;text-align: start;&quot;&gt;사용하고 있는 데이터를 파일 저장 혹은 데이터 통신에서 파싱할 수 있는 유의미한 데이터를 만들기 위해 사용하는 기술로, 자바 시스템 내부에서 사용되는 객체 또는 데이터를 외부의 자바 시스템에서도 사용할 수 있도록 바이트(byte) 형태로 데이터 변환하는 기술입니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;  컬렉션 클래스에서 Generic을 사용하는 이유가 무엇인가요?&amp;nbsp;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #212529; text-align: start;&quot;&gt;컬렉션 클래스에 저장되는 인스턴스 타입을 제한하여 런타임에 발생할 수 있는 잠재적인 모든 예외를 컴파일 타임에 잡아 낼 수 있어서 사용합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #333333; text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;  JVM 관련 질문&lt;/h3&gt;
&lt;p style=&quot;color: #333333; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;  Major GC와 Minor GC 차이점이 무엇인가요?&amp;nbsp;&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;Minor GC
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Young 영역에서 일어나는 Garbage Collection으로, 속도가 빠르고 Eden, Survivor영역에 속한 젊은 객체들에 대한 Garbage Collection을 의미합니다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Major GC
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Old 영역에서 일어나는 Garbage Collection으로, Minor GC에 비해 속도가 느리고 Old 영역에 속한 오래된 객체들에 대한 Garbage Collection을 의미합니다.&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;color: #333333; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt; &lt;b&gt;&lt;span&gt;&amp;nbsp;자바의 메모리 영역은 어떻게 구성되어 있나요?&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;메소드(Method) 영역&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;: 전역변수와 static 변수를 저장, 프로그램의 시작부터 종료까지 남아있습니다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;스택(Stack) 영역&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;: 지역변수와 매개변수 데이터 값이 저장, 메소드 호출 시 메모리에 할당되고 종료되면 메모리가 해제된다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;힙(Heap) 영역&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;: 객체, 배열 등이 저장, 가비지 컬렉터에 의해 관리되어 진다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;color: #333333; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br /&gt;&lt;b&gt;  Reflection이란 무엇인가요?&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;실행 시간에 JVM의 메모리 영역에 저장된 클래스 정보들을 읽어서 활용하는 기술로 라이브러리나 프레임워크에서 활용하는 기술입니다.&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;  Spring 관련 질문&lt;/h3&gt;
&lt;p style=&quot;color: #000000; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt; &amp;nbsp;&lt;b&gt;Spring과 Spring Boot의 차이점이 무엇인가요?&amp;nbsp;&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;Spring은 프레임워크로, 개발자가 직접 설정파일 작성을 통해 컨테이너 구성, 빈 객체 등록, 의존성 설정 등을 수동으로 해줘야 했습니다.&lt;/li&gt;
&lt;li&gt;Spring Boot는 Spring에서 제공하는 여러 기능들을 자동으로 설정하여 Spring을 쉽게 사용하도록 만든 도구입니다. 프로젝트의 설정, 라이브러리 의존성 관리 등 다양한 기능들을 제공하여 편리하다는 장점이 있습니다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Spring Boot는 내장 톰캣 서버를 사용하여 따로 톰캣을 설치할 필요가 없고, starter를 통해 dependency를 자동화하며(버전관리 자동화), jar file을 이용해 자바 옵션만으로 손쉽게 배포가 가능하다는 차이가 있습니다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;color: #000000; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; text-align: left;&quot;&gt; &amp;nbsp;&lt;/span&gt;DTO를 사용하는 이유가 무엇인가요?&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;양방향 참조 시의 순환 참조를 예방하고, entity 내부를 캡슐화하며 계층 간 역할을 분리하기 위해서입니다.&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; text-align: left;&quot;&gt; &amp;nbsp;&lt;/span&gt;Bean Scope 종류는 어떤 것이 있나요?&amp;nbsp;&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;Bean Scope란 문자 그대로 빈이 존재할 수 있는 범위를 의미하며,&amp;nbsp;스프링 빈은 기본적으로 싱글톤 스코프로 관리되어 스프링 컨테이너의 시작과 함께 생성, 컨테이너 종료될 때까지 유지됩니다.&lt;/li&gt;
&lt;li&gt;싱글톤 스코프 외에 스프링 컨테이너가 빈 생성에서 의존관계 주입까지만 관여하는 프로토타입 스코프, 웹 어플리케이션 환경에서 사용하는 웹 스코프인 request, session, application 스코프가 있습니다.&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;color: #000000; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; text-align: left;&quot;&gt; &amp;nbsp;&lt;/span&gt;Spring Bean 라이프사이클에 대해 간단히 설명해주세요.&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br /&gt;스프링 컨테이너가 생성되고, 컨테이너에 의해 빈이 생성됩니다. 빈이 생성되면 의존관계가 주입되고, 초기화 콜백을 통해 의존관계 주입 완료를 알립니다. 그 후 빈을 사용하고, 빈 스코프에 따라 소멸 시 소멸전 콜백이 일어나고 (싱글톤이라면 스프링 컨테이너 종료 전 등) 스프링이 종료됩니다.&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; text-align: left;&quot;&gt; &amp;nbsp;&lt;/span&gt;Spring이 Request를 처리하는 과정에 대해 설명해주세요.&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; color: #333333; text-align: left;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;color: #000000;&quot;&gt;Client 요청을 Dispatcher Servlet이 받음&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;
&lt;li style=&quot;color: #000000;&quot;&gt;Handler Mapping이 요청 정보를 통해 요청을 위임할 Controller 찾는다.&lt;/li&gt;
&lt;li style=&quot;color: #000000;&quot;&gt;요청을 Controller로 위임할 Handler Adpater를 찾아 전달, 해당 Controller로 요청을 위임&lt;/li&gt;
&lt;li style=&quot;color: #000000;&quot;&gt;요청에 맞게 비즈니스 로직을 처리 후 Controller 가 반환값을 반환&amp;nbsp;&lt;/li&gt;
&lt;li style=&quot;color: #000000;&quot;&gt;Handler Adapter가 반환값을 반환&lt;/li&gt;
&lt;li style=&quot;color: #000000;&quot;&gt;최종적으로 Dispatcher Servlet이 클라이언트에게 서버의 응답 반환&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; text-align: left;&quot;&gt; &amp;nbsp;&lt;/span&gt;Spring에서 멤버 변수를 주입받는 방법 3가지에 대해 각각 설명해주세요.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;생성자 주입, 필드 주입, 수정자 주입 총 3가지가 있습니다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;필드 주입, 수정자 주입은 빈을 모두 생성한 이후 해당하는 필드나 setter 메소드를 찾아서 주입하는 방식이고,&amp;nbsp;생성자 주입은 빈을 생성하는 시점에 주입을 같이 하는 방식입니다.&lt;/li&gt;
&lt;li&gt;생성자 주입이 권장되는데, 모든 빈을 생성하지 않아도 되어 단위 테스트가 다른 방식보다 편하고, 필드에 final 키워드를 선언하여 변경불가능하게 사용할 수 있습니다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; text-align: left;&quot;&gt; &amp;nbsp;&lt;/span&gt;Spring의 IOC와 DI의 정의에 대해 간단히 설명해주세요&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;IOC(제어의 역전)&amp;nbsp;: 프로그램의 제어 흐름을 직접 제어하는 것이 아니라 외부에서 관리하는 것&lt;/li&gt;
&lt;li&gt;DI(의존성 주입)&amp;nbsp;: 필요한 객체를 직접 생성하는 것이 아닌 외부로부터 객체를 받아서 사용하는 것&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; text-align: left;&quot;&gt; &amp;nbsp;&lt;/span&gt;Spring Filter와 Interceptor와 사용하는 예시를 설명해주세요.&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Filter&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;요청과 응답을 정제하는 역할로,&amp;nbsp;스프링 컨테이너가 아닌 톰캣과 같은 웹 컨테이너에 의해 관리되며 스프링 범위 밖에서 처리됩니다.&lt;/li&gt;
&lt;li&gt;Dispatcher Servlet에 요청이 전달되기 전/후에 사용합니다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;보안, 인증 / 인가 작업, 요청에 대한 일괄적인&amp;nbsp;로깅 또는 검사,&amp;nbsp;이미지/데이터 압축 및 문자열 인코딩,&amp;nbsp;Spring과 분리되어야 하는 기능&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Interceptor&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Dispatcher Servlet이 Controller를 호출하기 전 / 후에 인터셉터가 끼어들어 요청과 응답을 참조하거나 가공할 수 있으며, Spring Context 내에서 동작합니다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;세부적인 보안 및 인증/인가 작업, API 호출에 대한 로깅 또는 검사, Controller 데이터 가공&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; text-align: left;&quot;&gt; &amp;nbsp;&lt;/span&gt;Controller로 들어오는 입력값을 검증하는 방법은 어떤 것들이 있나요?&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;DTO 를 검사할때는 validation 패키지의 @NotNull, @NotEmpty, @Min, @Max 등을 활용할 수 있습니다. &amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;Controller단에서는 BindingResult 객체를 활용하여 서비스 단에서 직접 클라이언트에게 예외가 발생하였음을 알리거나,&amp;nbsp;@ControllerAdvice를 이용한 전역 에러 핸들링을 활용하는 방법도 존재합니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; text-align: left;&quot;&gt; &amp;nbsp;&lt;/span&gt;@Pathvariable, &amp;nbsp;@RequestParam, @RequestBody, @ModelAttribute 의 차이가 무엇인가요?&amp;nbsp;&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;@PathVariable&amp;nbsp;: 값을 하나만 받아올 수 있으며 보통 id 값을 전송할때 주로 사용&lt;/li&gt;
&lt;li&gt;@RequestParam&amp;nbsp;: param 형식으로 간단한 데이터를 전송할때 주로 사용&lt;/li&gt;
&lt;li&gt;@RequestBody&amp;nbsp;: Json 형식으로 데이터를 전송할때 주로 사용&lt;/li&gt;
&lt;li&gt;@ModelAttribute&amp;nbsp;: 폼 / MultipartFile 형식에 주로 사용&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; text-align: left;&quot;&gt; &amp;nbsp;&lt;/span&gt;Spring에서 Dependency Injection을 IoC Container가 하는 일을 중심으로 설명해주세요&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;IoC Container는 Inversion of Control의 약자로, 개발자가 Spring Bean의 관리를 하지 않고 Framework가 주도적으로 관리하도록 역전시킨것이다.&amp;nbsp;따라서 IoC Container가 Spring Bean의 의존성 주입을 관리하게 되고, 개발자가&amp;nbsp;@AutoWired&amp;nbsp;등의 방법으로 설계해놓은 것을 실행한다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; text-align: left;&quot;&gt; &amp;nbsp;&lt;/span&gt;Spring Bean은 언제 어떻게 생성되게 될까요?&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;Spring Application의 메인 메소드에서 static 메소드인&lt;span&gt;&amp;nbsp;&lt;/span&gt;run()&lt;span&gt;&amp;nbsp;&lt;/span&gt;메소드를 찾아 실행시킨다. run 메소드는 application context를 생성하고,&lt;span&gt;&amp;nbsp;&lt;/span&gt;@ComponentScan&lt;span&gt;&amp;nbsp;&lt;/span&gt;때문에&lt;span&gt;&amp;nbsp;&lt;/span&gt;@Component,&lt;span&gt;&amp;nbsp;&lt;/span&gt;@Bean&lt;span&gt;&amp;nbsp;&lt;/span&gt;등 Bean으로 만드는 어노테이션을 찾아 Spring Bean으로 생성한 뒤, IoC 에 저장한다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; text-align: left;&quot;&gt; &amp;nbsp;&lt;/span&gt;한 클래스에 대해서 Bean 생성을 여러개 하고 싶으면 어떻게 하면 될까요?&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;@Scope 어노테이션을 통해 Bean Scope를 session, prototype등 세션이나 요청마다 생성하는 스코프로 변경해줍니다.&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; text-align: left;&quot;&gt; &amp;nbsp;&lt;/span&gt;Spring에서 테스트 시,&lt;span&gt;&amp;nbsp;&lt;/span&gt;@Mock&lt;span&gt;&amp;nbsp;&lt;/span&gt;과 같은 가짜 객체를 만들어서 테스트하는 이유가 무엇인가요?&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;테스트는 통합 테스트 외 단위 테스트를 실행할 때, Spring 컨테이너를 띄우지 않고 테스트 하고자 하는 영역 외 나머지들은 가짜 객체로 생성하여 테스트하려는 부분만 집중적으로 보기 위해서입니다.&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>CS</category>
      <author>Bubbles</author>
      <guid isPermaLink="true">https://bubblebubble.tistory.com/163</guid>
      <comments>https://bubblebubble.tistory.com/163#entry163comment</comments>
      <pubDate>Thu, 9 Nov 2023 02:30:25 +0900</pubDate>
    </item>
    <item>
      <title>백준 11501, 2169, 프로그래머스 체육복</title>
      <link>https://bubblebubble.tistory.com/162</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;  백준 11501 : 주식 &amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/11501&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.acmicpc.net/problem/11501&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1699347212247&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;11501번: 주식&quot; data-og-description=&quot;입력의 첫 줄에는 테스트케이스 수를 나타내는 자연수 T가 주어진다. 각 테스트케이스 별로 첫 줄에는 날의 수를 나타내는 자연수 N(2 &amp;le; N &amp;le; 1,000,000)이 주어지고, 둘째 줄에는 날 별 주가를 나타&quot; data-og-host=&quot;www.acmicpc.net&quot; data-og-source-url=&quot;https://www.acmicpc.net/problem/11501&quot; data-og-url=&quot;https://www.acmicpc.net/problem/11501&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bAOmfL/hyUrz7TxHD/aiLoBhhkD4KaaCTwYJjfSK/img.png?width=2834&amp;amp;height=1480&amp;amp;face=0_0_2834_1480&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/11501&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.acmicpc.net/problem/11501&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bAOmfL/hyUrz7TxHD/aiLoBhhkD4KaaCTwYJjfSK/img.png?width=2834&amp;amp;height=1480&amp;amp;face=0_0_2834_1480');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;11501번: 주식&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;입력의 첫 줄에는 테스트케이스 수를 나타내는 자연수 T가 주어진다. 각 테스트케이스 별로 첫 줄에는 날의 수를 나타내는 자연수 N(2 &amp;le; N &amp;le; 1,000,000)이 주어지고, 둘째 줄에는 날 별 주가를 나타&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.acmicpc.net&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;  메인 로직&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;각 날짜의 주식가격을 배열에 쭉 저장해둔다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;그리디 유형의 문제긴 하지만, 무조건 높을때 다 팔고 끝나는것이 아니라 마지막날에도 이전보다 올랐다면 팔 수 있다.&lt;/li&gt;
&lt;li&gt;뒤에서부터 차례로 돌면서 현재 내가 가진 최댓값보다 높은 가격이 나왔다 = &amp;nbsp;그날 기점으로 가격이 떨어졌다 이것이므로 최댓값을 갱신해준다.&lt;/li&gt;
&lt;li&gt;그 외에는 최댓값보다 낮은 날이므로 무조건 사뒀다가 파는게 이득이라 answer에 더해준다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;  메인 로직을 코드화하면 아래와 같다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1699347562984&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;int temp = price[days-1];
for (int d = days-2; d &amp;gt;= 0; d--) {
	if (temp &amp;lt; price[d]) {
		temp = price[d]; // 최댓값 갱신해준다. 
	} else {
		answer += (temp - price[d]); // 더 낮은값일때는 계속 사놓는 것이 이득
	}
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;  전체 코드&lt;/p&gt;
&lt;pre id=&quot;code_1699347308497&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

public class p11501 {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int n = Integer.parseInt(br.readLine());

        for (int i = 0; i &amp;lt; n; i++) {
            int days = Integer.parseInt(br.readLine());
            int[] price = new int[days];
            int answer = 0;
            StringTokenizer st = new StringTokenizer(br.readLine());

            for (int d = 0; d &amp;lt; days; d++) {
                price[d] = Integer.parseInt(st.nextToken());
            }

            int temp = price[days-1];
            for (int d = days-2; d &amp;gt;= 0; d--) {
                if (temp &amp;lt; price[d]) {
                    temp = price[d];
                } else {
                    answer += (temp - price[d]);
                }
            }

            System.out.println(answer);

        }

    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  백준 2169 : 로봇 조종하기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/2169&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.acmicpc.net/problem/2169&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1699347992126&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;2169번: 로봇 조종하기&quot; data-og-description=&quot;첫째 줄에 N, M(1&amp;le;N, M&amp;le;1,000)이 주어진다. 다음 N개의 줄에는 M개의 수로 배열이 주어진다. 배열의 각 수는 절댓값이 100을 넘지 않는 정수이다. 이 값은 그 지역의 가치를 나타낸다.&quot; data-og-host=&quot;www.acmicpc.net&quot; data-og-source-url=&quot;https://www.acmicpc.net/problem/2169&quot; data-og-url=&quot;https://www.acmicpc.net/problem/2169&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bGyPwW/hyUry2cCgW/yE1Upd9GINZJZn0ns08QK1/img.png?width=2834&amp;amp;height=1480&amp;amp;face=0_0_2834_1480&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/2169&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.acmicpc.net/problem/2169&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bGyPwW/hyUry2cCgW/yE1Upd9GINZJZn0ns08QK1/img.png?width=2834&amp;amp;height=1480&amp;amp;face=0_0_2834_1480');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;2169번: 로봇 조종하기&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;첫째 줄에 N, M(1&amp;le;N, M&amp;le;1,000)이 주어진다. 다음 N개의 줄에는 M개의 수로 배열이 주어진다. 배열의 각 수는 절댓값이 100을 넘지 않는 정수이다. 이 값은 그 지역의 가치를 나타낸다.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.acmicpc.net&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;  문제 유형 찾기 : DP&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;문제 조건을 보면 이러한 말들이 있다.&amp;nbsp;
&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;처음에는 2차원 배열, 3방향으로 움직일 수 있다는 조건을 보고 BFS를 생각했는데, BFS는 최단거리 찾는것이므로 가치의 합이 최대가 되는 것이라면..하고 DFS를 생각했었다.&lt;/li&gt;
&lt;li&gt;하지만 제한시간이 1초이고 n,m이 1000까지 갈 수 있으므로&amp;nbsp;동적계획법으로 푸는 건가? 라는 생각을 했다. (위의 조건을 보고 / 그리고 실제로 DP문제였다. )&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;  메인 로직&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이동 가능한 방향은 좌, 우, 하 이렇게 3가지이고,&amp;nbsp;DP[ i ][ j ]에서 위, 오른쪽, 왼쪽을 다 비교해보고 Max를 찾아야 한다.&lt;/li&gt;
&lt;li&gt;위로 돌아가는 것은 불가능하므로, 무조건 DP 2차원 배열의 맨 윗줄은 map에서 가져와야 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1699348447591&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;DP[0][0] = map[0][0];
for (int j = 1; j &amp;lt; col; j++) {
	DP[0][j] = DP[0][j-1] + map[0][j];
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;각 칸 별로 왼쪽에서 탐색해서 오는 경우와 오른쪽에서 탐색해서 오는 경우 중 더 큰 걸 찾아야 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1699348721170&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 왼쪽에서 출발
left[0] = DP[i-1][0] + map[i][0];
for (int j = 1; j &amp;lt; col; j++) {
	left[j] = Math.max(DP[i-1][j], left[j-1]) + map[i][j];
}

// 오른쪽에서 출발
right[col-1] = DP[i-1][col-1] + map[i][col-1];
for (int j = col-2; j &amp;gt;= 0; j--) {
	right[j] = Math.max(DP[i-1][j], right[j+1]) + map[i][j];
}&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;왼쪽 오른쪽 다 탐색 후 MAX로 갱신해준다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1699348837991&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;for (int j = 0; j &amp;lt; col; j++) {
	DP[i][j] = Math.max(left[j], right[j]);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;  전체코드&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1699347952610&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import java.util.*;
import java.io.*;
public class p2169 {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());
        int row = Integer.parseInt(st.nextToken());
        int col = Integer.parseInt(st.nextToken());

        int[][] map = new int[row][col];
        int[][] DP = new int[row][col];

        for (int i = 0; i &amp;lt; row; i++) {
            st = new StringTokenizer(br.readLine());
            for (int j = 0; j &amp;lt; col; j++) {
                map[i][j] = Integer.parseInt(st.nextToken());
            }
        }
        DP[0][0] = map[0][0];
        for (int j = 1; j &amp;lt; col; j++) {
            DP[0][j] = DP[0][j-1] + map[0][j];
        }

        for (int i = 1; i &amp;lt; row; i++) {
            int[] left = new int[col];
            int[] right = new int[col];

            // 왼쪽에서 출발
            left[0] = DP[i-1][0] + map[i][0];
            for (int j = 1; j &amp;lt; col; j++) {
                left[j] = Math.max(DP[i-1][j], left[j-1]) + map[i][j];
            }

            // 오른쪽에서 출발
            right[col-1] = DP[i-1][col-1] + map[i][col-1];
            for (int j = col-2; j &amp;gt;= 0; j--) {
                right[j] = Math.max(DP[i-1][j], right[j+1]) + map[i][j];
            }
            for (int j = 0; j &amp;lt; col; j++) {
                DP[i][j] = Math.max(left[j], right[j]);
            }
        }

        System.out.println(DP[row-1][col-1]);
    }


}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;⛹ &amp;zwj;♀️ 프로그래머스 : 체육복&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/42862&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://school.programmers.co.kr/learn/courses/30/lessons/42862&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1699347629949&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;프로그래머스&quot; data-og-description=&quot;코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.&quot; data-og-host=&quot;programmers.co.kr&quot; data-og-source-url=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/42862&quot; data-og-url=&quot;https://programmers.co.kr/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/iBJmA/hyUrAFKuP0/gQvIM2JLw479zTPgfi0vWk/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/JTdXL/hyUrsgD2ld/ZwoJYSTJth5kdenmNoboQ0/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630&quot;&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/42862&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/42862&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/iBJmA/hyUrAFKuP0/gQvIM2JLw479zTPgfi0vWk/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/JTdXL/hyUrsgD2ld/ZwoJYSTJth5kdenmNoboQ0/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;프로그래머스&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;programmers.co.kr&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;⛹ &amp;zwj;♀️ 메인로직&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;먼저 모든 학생들이 참석할 수 있다고 가정하고 answer을 초기화 시킨 다음, 참석 불가능한 애들만 빼주면 된다.&lt;/li&gt;
&lt;li&gt;set에다가 여벌을 가지고 온 학생들 번호를 넣는다.&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;reserve 배열 탐색하면서 set과 동일한 애가 있는 경우가 위의 예시이므로, set에서 제거해준 후 list에 넣지 않는다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;list는 중복을 제거한, 진짜 잃어버린 애들을 담는 리스트이며, 번호 순대로 정렬해준다.(체격 순으로 번호가 매겨지니까)&amp;nbsp;&lt;/li&gt;
&lt;li&gt;그 후 set에서 자기 앞뒤 사이즈의 여벌이 있는지 확인하고, 없다면 answer--해준다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;⛹ &amp;zwj;♀️ 전체코드&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1699347705654&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import java.util.*;
class Solution {
    public int solution(int n, int[] lost, int[] reserve) {
        int answer = n;
        Set&amp;lt;Integer&amp;gt; set = new HashSet&amp;lt;&amp;gt;();
        List&amp;lt;Integer&amp;gt; list = new ArrayList&amp;lt;&amp;gt;();
        for (int i : reserve) {
            set.add(i);
        }
        for (int i : lost) {
            if (set.contains(i)) {
                set.remove(i);
            } else {
                list.add(i);
            }
        }
        Collections.sort(list);
        
        for (int i : list) {
            if (set.contains(i-1)) {
                set.remove(i-1);
            } else if (set.contains(i+1)) {
                set.remove(i+1);
            } else {
                answer--;
            }
        }
        return answer;
    }
}&lt;/code&gt;&lt;/pre&gt;</description>
      <category>Java/코딩테스트</category>
      <author>Bubbles</author>
      <guid isPermaLink="true">https://bubblebubble.tistory.com/162</guid>
      <comments>https://bubblebubble.tistory.com/162#entry162comment</comments>
      <pubDate>Tue, 7 Nov 2023 18:21:13 +0900</pubDate>
    </item>
    <item>
      <title>CS - 운영체제 정리</title>
      <link>https://bubblebubble.tistory.com/160</link>
      <description>&lt;h3 style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;기본 개념&lt;/h3&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;운영체제가 무엇인가요?&lt;/b&gt;&lt;br /&gt;하드웨어 자원을 관리하고, 응용프로그램과 하드웨어 사이를 중재하는 인터페이스입니다.&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;b&gt;커널이 무엇인가요?&amp;nbsp;&lt;/b&gt;&lt;br /&gt;메모리에 상주하는 운영체제의 핵심 부분으로, OS 전체를 메모리에 올려두는 것은 메모리 낭비가 심하므로 핵심 부분인 커널만 메모리에 올려놓고 사용합니다.&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;b&gt;시스템 콜이 무엇이고 왜 존재하는지 설명해주세요.&lt;/b&gt;&lt;br /&gt;OS가 커널에 접근하기 위한 인터페이스로, 유저 프로그램이 OS의 서비스 받기 위해 커널함수를 호출할 때 사용합니다.&amp;nbsp;&lt;br /&gt;자원에 대한 직접 접근을 차단함으로써 자원을 보호한 채 사용자에게 서비스를 제공하기 위해 존재합니다.&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;인터럽트란 무엇이고 어떤 종류가 있나요 ?&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;CPU가 프로그램을 실행하고 있을 때 하드웨어 장치 이벤트나 예외 상항등이 발생했을 때 마이크로 프로세서에게 알려 처리할 수 있도록 합니다.&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;하드웨어 인터럽트
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;CPU가 아닌 다른 하드웨어 장치가 CPU에게 어떤 사실을 알려주거나 CPU 서비스를 요청해야 하는 경우 발생&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;소프트웨어가 발생시키는 인터럽트로 예외 상황, system call 등의 상황에서 발생&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;b&gt;IO interrupt가 발생하면 내부적으로 어떤 일이 일어나나요?&amp;nbsp;&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;I/O 가 필요한 경우, 실행을 멈추고 System Call을 한다.&lt;/li&gt;
&lt;li&gt;해당 프로세스는 Waiting 상태로 이동하고 I/O 를 진행시키며 다른 프로세스에 CPU를 할당해 실행시킨다.&lt;/li&gt;
&lt;li&gt;I/O 가 끝나면 다시 Ready 상태로 이동해서 CPU 할당을 기다린다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;동시성 제어&lt;/h3&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br /&gt;&lt;b&gt;동시성과 병렬성의 차이가 무엇인가요?&amp;nbsp;&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;nbsp;메모리에 여러 프로세스를 적재, 번갈아 수행하여 동시에 실행되는것처럼 보이게 하는 것 / 싱글 코어에서 멀티스레드 동작시키는 방식&lt;/li&gt;
&lt;li&gt;병렬성&amp;nbsp;:&amp;nbsp;멀티&amp;nbsp;프로세싱에서&amp;nbsp;나온&amp;nbsp;개념,&amp;nbsp;실제로&amp;nbsp;동시에&amp;nbsp;여러&amp;nbsp;프로세스를&amp;nbsp;병렬적으로&amp;nbsp;수행하는&amp;nbsp;것&amp;nbsp;/ CPU가&amp;nbsp;멀티&amp;nbsp;코어여야&amp;nbsp;한다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;b&gt;Blocking - Non-blocking과 Synchronous - Asynchronous 차이에 대해 각각 설명해주세요.&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;Blocking VS Non-Blocking
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;color: #000000;&quot;&gt;호출된 함수가 끝날 때까지 제어권을 계속 가지고서&lt;span&gt;&amp;nbsp;&lt;/span&gt;호출한 함수에게 바로 돌려주지 않으면 Blocking&lt;/li&gt;
&lt;li style=&quot;color: #000000;&quot;&gt;호출된 함수가 끝나지 않아도 바로 제어권을 건네주어&amp;nbsp;호출한 함수가 다른 일을 진행할 수 있도록 해주면 Non-blocking&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Synchronous VS Asynchronous&amp;nbsp;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;color: #000000;&quot;&gt;호출된 함수의 수행 결과와 종료를 기다리고, 순서대로 응답을 받을 수 있으면 Synchronous&lt;/li&gt;
&lt;li style=&quot;color: #000000;&quot;&gt;호출된 함수의 수행 결과와 종료를 기다리지 않고 순서대로 응답이 온다는 보장이 없으면 Asynchronous&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;text-align: left;&quot; 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;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;교착상태, 데드락, 경쟁상태&lt;/h3&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;경쟁상태가 발생하는 원인과 해결책에 대해 설명해주세요&lt;/b&gt;.&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;경쟁 상태는 공유 메모리를 사용하기 때문에 발생합니다. &lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;경쟁 상태를 해소하기 위해서는 공유 메모리를 쓰는 프로세스/스레드 간 동기화를 통해&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;순차적 실행을 보장하여 임계구역의 상호 배제를 이뤄지도록 합니다.&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;세마포어와 뮤텍스 등이 있습니다.&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;임계 영역이 무엇이고, 임계영역에 문제가 발생하지 않도록 만족해야하는 조건이 있나요?&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;여러 프로세스가 동시에 공유하면 안되는 자원에 접근하고 실행하는 프로그램의 부분을 의미합니다.&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;상호배제와 비어있는 임계영역에 어떤 프로세스가 진행할지 결정하고, 기아 상태를 방지하기 위해 한번 임계구역에 들어간 프로그램은 다음 진입에 제한을 둡니다.&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;데드락(교착상태)란 무엇인가요?&lt;/b&gt;&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2개 이상의 프로세스나 스레드가 서로 자원을 얻지 못해서 다음 작업을 수행하지 못하고 자원을 무한정 기다리는 상태를 의미합니다.&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;b&gt;데드락의 발생 조건에는 어떤 것들이 있나요?&lt;/b&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;상호배제 : 한 자원에 여러 프로세스가 동시에 접근할 수 없음&lt;/li&gt;
&lt;li&gt;점유대기 : 하나의 자원을 소유한 상태에서 다른 자원을 기다림&lt;/li&gt;
&lt;li&gt;비선점 : 프로세스가 어떤 자원의 사용을 끝낼 때까지 프로세스 자원 뺏을 수 없음&lt;/li&gt;
&lt;li&gt;순환대기 : 각 프로세스가 순환적으로 다음 프로세스가 요구하는 자원을 갖고 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br /&gt;&lt;b&gt;뮤텍스와 세마포어의 차이에 대해 설명해주세요.&amp;nbsp;&lt;/b&gt;&lt;br /&gt;뮤텍스는 오직 하나의 스레드 || 프로세스만 접근할 수 있으며, 락을 획득한 스레드 || 프로세스가 락을 해제해야 합니다.&amp;nbsp;&lt;br /&gt;세마포어는 세마포어 변수만큼의 스레드 || 프로세스가 접근할 수 있으며 현재 수행중이 아닌 프로세스가 세마포어를 해제할 수 있습니다.&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;b&gt;UNIX, Windows 등 대부분의 범용 OS가 채택하고 있는 데드락에 대한 조치 방식은 무엇인가요?&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;Deadlock이 일어나지 않는다고 생각하고 아무런 조치를 취하지 않습니다.&lt;/li&gt;
&lt;li&gt;사실 Deadlock은 매우 드물게 발생하므로 deadlock에 대한 조치 자체가 더 큰 overhead를 불러올 수 있기 때문에 시스템이 비정상적으로 작동하는 것을 사용자가 느끼고 직접 process를 kill하는 방식으로 해결합니다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;text-align: left;&quot; 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;h3 style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;프로세스 &amp;amp; 스레드&amp;nbsp;&lt;/h3&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;프로세스와 스레드의 차이가 무엇인가요?&amp;nbsp;&lt;/b&gt;&lt;br /&gt;프로세스는 실행 중인 프로그램으로, 각 프로세스는 메모리 영역을 독립적으로 사용합니다.&amp;nbsp;&lt;br /&gt;스레드는 프로세스 내에서 프로세스 자원을 이용하여 실행되는 작업으로 Stack과 program counter만 따로 할당 받고, 그 이외의 메모리 영역을 공유합니다.&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;br /&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;프로세스 생성 시 PCB가 생성되고, 부모 프로세스의 내용을 복사해 주소공간을 할당한다. 그 후 자식 프로세스의 실제 데이터를 로딩한다. 그 후 프로세스를 ready queue에 넣고 CPU 할당을 기다린다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br /&gt;&lt;b&gt;Context switching이 무엇인가요?&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;멀티 프로세스 환경에서 CPU는 여러 프로세스를 돌아가면서 작업을 처리하므로, 현재 프로세스를 중단하고 다음 프로세스가 실행되어야 하는 경우가 발생합니다.&lt;/li&gt;
&lt;li&gt;현재까지 수행한 context를 저장해두고 다음 프로세스의 context로 교체하는 것을 의미합니다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br /&gt;&lt;b&gt;PCB에 대해 설명해주세요&amp;nbsp;&lt;/b&gt;&lt;br /&gt;프로세스 생성시 만들어지는 정보로 context switching 발생 시 프로세스의 상태를 기록해두었다가 복구할 때 사용합니다.&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;b&gt;프로세스 status 중 suspended에 대해 설명해주세요&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;사용자가 정지시키거나, 메모리에 너무 많은 프로세스가 올라가 있어 디스크로 swap out 된 상태를 의미합니다. &amp;nbsp;&lt;/li&gt;
&lt;li&gt;Suspended&amp;nbsp;Ready는 Ready 상태였던 프로세스가 swap out 당한 상태를 의미합니다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Suspended Block은 Blocked 상태의 프로세스 swap out된 것으로 blocked 된 조건이 충족되면 Suspended Ready로 바뀝니다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;* swap out :&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;시스템 성능이 저하되는 경우 일부 프로세스로부터 메모리를 통째로 빼앗아 디스크의 swap 영역에 저장.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Running : CPU 받아 명령을 수행중인 상태&lt;/li&gt;
&lt;li&gt;Ready : CPU 제외한 메모리 등 모든 조건이 준비된 상태(메인 메모리로 로드된) - CPU만 받으면 당장 수행 가능한 상태&lt;/li&gt;
&lt;li&gt;Blocked : CPU 받더라도 당장 실행 불가 -&amp;gt; I/O event 기다리거나 디스크에서 file 읽어와야 하는 등 저장매체에 액세스해서 이벤트 발생 대기중인 상태 &amp;nbsp;&lt;/li&gt;
&lt;li&gt;new : 프로세스를 위한 자료구조들은 생성, 아직 메모리 획득 승인은 못 받은 상태&lt;/li&gt;
&lt;li&gt;terminated : 프로세스는 종료되었는데 프로세스와 관련된 자료구조 정리 완전히 못한 상태&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Suspended : 사용자가 정지시키거나 메모리에 너무 많은 프로세스가 올라가있어 디스크로 swap out된 상태&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;b&gt;멀티 스레드 방식이 멀티 프로세스 방식에 비해 가지는 장점에 대해 설명해주세요.&amp;nbsp;&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;nbsp;&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;b&gt;스레드가 독립적으로 할당하는 자원 2가지가 무엇이고, 왜 공유하지 않고 독립적으로 할당할까요?&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Program Counter
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;스레드의 명령어가 어디까지 수행되었는지 저장하는 부분으로 스레드가 CPU 할당받았다가 스케줄러에 의해 선점당하여 연속적으로 수행되지 못합니다.&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;따라서 각 스레드별로 수행된 부분을 기록할 필요가 있습니다.&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Stack&amp;nbsp;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;스택 영역에 함수 호출 시 전달되는 인자, 되돌아갈 주소 등을 저장하므로 함수에 따른 독립적인 실행 흐름을 갖기 위해 스택을 각각 할당해줄 필요가 있습니다.&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;크롬 브라우저에서 한 탭에 오류가 생기더라도, 다른 탭에 영향을 끼치지 않는데, 각각의 크롬 탭은 프로세스일까요? 스레드일까요?&amp;nbsp;&lt;/span&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;nbsp;한 탭에 오류가 생기더라도 다른 탭에 영향을 끼치지 않으므로 크롬 탭은 프로세스입니다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;text-align: left;&quot; 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;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;메모리&lt;/h3&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br /&gt;&lt;b&gt;메모리 단편화란 무엇이고, 어째서 발생하나요?&amp;nbsp;&lt;/b&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;RAM에서 메모리의 공간이 작은 조각으로 나뉘어져 사용 가능한 메모리가 충분히 존재하지만 할당(사용)이 불가능한 상태를 보고 메모리 단편화가 발생했다고 합니다.&lt;/span&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;nbsp;내부 단편화(Internal Fragmentation) : 메모리를 할당할 때 프로세스가 필요한 양보다 더 큰 메모리가 할당되어서 프로세스에서 사용하는 메모리 공간이 낭비 되는 상황&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;외부 단편화(External Fragmentation) : 메모리가 할당되고 해제되는 작업이 반복될 때 작은 메모리가 중간중간 존재하게 된다. 이 때 중간에 생긴 사용하지 않는 메모리들로 인해, 합쳐진 총 메모리 공간은 충분하지만 실제로 할당할 수 없는 상황&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;b&gt;가상 메모리가 필요한 이유와 역할, 구현 방식에 대해 설명해주세요.&lt;/b&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;메모리 크기보다 큰 사용자 프로그램을 실행가능하게 하기 위해 필요합니다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;가상 메모리 기법을 사용하여 프로그램의 필요한 부분만 메모리에 적재하고, &amp;nbsp;필요하지 않은 메모리 공간은 디스크에 저장하게 됩니다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;프로세스가 생성될 때 개별적인 주소 공간이 만들어지며, 이를 물리적 주소로 바꾸어 처리합니다.&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;b&gt;컴퓨터의 설계에 있어 캐시의 이점이 무엇인가요?&lt;/b&gt;&lt;br /&gt;데이터를 미리 복사해놓음으로써 접근 시간이나 다시 계산하는 시간을 줄여주고, 이로 인해&amp;nbsp;속도가 빠른 장치와 느린 장치 사이 속도차이에 따른 병목현상을 완화할 수 있습니다. &amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;b&gt;프로그램이 운영체제로부터 할당받는 메모리 공간의 구조에 대해 설명해주세요.&amp;nbsp;&lt;/b&gt;&lt;br /&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;Code : 프로그램의 코드 / 명령어들이 기계어로 저장된 영역&lt;/li&gt;
&lt;li&gt;Data : 코드에서 선언된 전역 / 정적 변수가 저장되는 영역 -&amp;gt; 실행 시 할당되고 종료 시 소멸&lt;/li&gt;
&lt;li&gt;Stack : 컴파일 타임에 크기 결정, 지역변수, 매개변수, 리턴 값 등 저장&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Heap : 런타임에 크기가 결정, 사용자에 의해 메모리 공간이 동적으로 할당되고 해제되는 영역, 참조형 등 저장&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br /&gt;&lt;b&gt;프로세스 스케줄링 알고리즘을 몇가지 예시를 들어 설명해주세요.&amp;nbsp;&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;nbsp;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;FCFS : 도착 순서대로 실행, 단순하지만 긴 프로세스 실행 시 다른 프로그램이 오래 기다림&lt;/li&gt;
&lt;li&gt;SJF : 점유시간 가장 짧은 프로세스를 우선 처리, 기아 문제 (오래 걸리는 프로세스 CPU 할당을 못받음)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;선점형&amp;nbsp;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;SRTF : 점유시간 가장 짧은 프로세스에 넘겨줌&lt;/li&gt;
&lt;li&gt;RR : 시간 할당량을 각 프로세스마다 할당한 후 끝나면 CPU를 다른 프로세스에 할당&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;b&gt;TLB란 무엇인가요?&amp;nbsp;&lt;/b&gt;&lt;br /&gt;고속 캐시의 일종으로, 주소로 접근되는 일반 메모리와는 다르게 키 값으로 찾고자 하는 워드를 동시에 접근하는 메모리입니다.&lt;br /&gt;페이지 테이블을 메모리에 두고 페이지 참조를 줄여서 접근 속도를 향상시키기 위해 사용하며, TLB miss시 페이지테이블을 참조합니다.&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;b&gt;세그먼테이션이란 무엇인가요?&amp;nbsp;&lt;/b&gt;&lt;br /&gt;고정된 크기로 분할하는 고정 분할방식이 아닌, 크기가 동적으로 변할 수 있는 세그먼트로 나누는 기법입니다.&amp;nbsp;&lt;br /&gt;외부 단편화가 발생할 수 있습니다.&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;b&gt;스레싱에 대해 설명해주세요.&amp;nbsp;&lt;/b&gt;&lt;br /&gt;페이지 부재율이 증가하여 swapping이 자주 일어나게 되고, 이로 인해 CPU 이용율이 급격히 떨어지는 현상을 의미합니다.&amp;nbsp;&lt;br /&gt;CPU 이용율이 낮으면 OS가 메모리에 올라간 프로세스의 수를 늘리고, 실행에 필요한 최소한의 프레임도 할당받지 못하게 되어 CPU 이용율이 지속적으로 떨어지는 악순환을 일으킵니다.&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;b&gt;동시에 메모리에 올라가있는 프로세스의 개수를 조절하는 방식&amp;nbsp;&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;working set : 지역성 원리 이용하여 지역성 집합이 메모리에 동시에 올라갈 수 있도록 보장. 대신 충분한 페이지를 할당하지 않으면 작업집합에 있는 페이지를 물리 메모리에 유지하기 힘듦.&lt;/li&gt;
&lt;li&gt;page fault frequency : 프로세스 페이지 부재율을 주기적으로 조사, 이 값에 근거하여 각 프로세스에 할당할 메모리 양을 동적으로 예측하고 조절하는 방식&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br /&gt;&lt;b&gt;page fault 과정에 대해 설명해주세요&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;CPU가 프로그램을 실행하면서 필요한 페이지가 물리 메모리에 없는 경우가 생기는데 이를 page fault라고 합니다.&lt;/li&gt;
&lt;li&gt;page fault가 발생하면 디스크로부터 해당 페이지를 가져오고, 메모리 상 페이지와 스와핑, 페이지 테이블 갱신 후 프로그램을 다시 실행합니다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&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;/h3&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;USB에서 많이 쓰는 FAT 파일 시스템의 단점을 아시나요?&amp;nbsp;&lt;/b&gt;&lt;br /&gt;파일 할당 여부를 체크하는 file allocation table에 대한 용량을 소비하며, 할당 여부만 확인 가능하여 기능이나 보안부분이 다소 떨어집니다. 대신 USB처럼 많은 기능, 보안 수준이 필요없는 장치에 사용됩니다.&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;b&gt;I-node 파일 시스템에 대해 간단히 설명해주세요&lt;/b&gt;&lt;br /&gt;파일과 관련된 정보들을 테이블 형태로 저장하며, 각 파일마다 inode 번호를 할당하여 파일을 구분하고 찾습니다.&lt;br /&gt;실제 데이터 블록은 inode가 가리키는 위치에 저장됩니다.&amp;nbsp;&lt;/p&gt;</description>
      <category>CS</category>
      <author>Bubbles</author>
      <guid isPermaLink="true">https://bubblebubble.tistory.com/160</guid>
      <comments>https://bubblebubble.tistory.com/160#entry160comment</comments>
      <pubDate>Thu, 2 Nov 2023 02:06:52 +0900</pubDate>
    </item>
    <item>
      <title>Java와 객체지향</title>
      <link>https://bubblebubble.tistory.com/157</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  클래스와 객체 : 정말 붕어빵틀과 붕어빵인가?&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;클래스 : &amp;nbsp;분류에 대한 개념이지 실체가 아니다. 같은 특성을 지닌 여러 객체를 총칭하는 집합의 개념이다.&amp;nbsp;&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;p data-ke-size=&quot;size16&quot;&gt;클래스 - 객체의 관계는 분류와 사물의 관계로 봐야 한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;EX ) 펭귄(클래스) - 뽀로로(객체), 쥐(클래스) - 미키마우스(객체) 이런 느낌이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;객체 지향의 4대 특성&amp;nbsp;&lt;/span&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;nbsp;&lt;/li&gt;
&lt;li&gt;실제 사물을 정확히 복제하는 것이 아닌, (ex. 사람의 모든 특성을 다 나열할 수는 없다) 목적에 맞게 관심이 있는 특성만을 추출해서 표현하고, 실제 사물을 단순하게 묘사하는 것이다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;EX) 병원에서 사람이라는 클래스가 있다면, 사람이라는 클래스의 직업이나 연봉과 같은 특성들은 필요가 없으므로 제거하고, 나이, 몸무게, 혈액형 등 필요한 특성들만 필드로 선언해두는 것&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;♻️ 상속 : 재사용과 확장&amp;nbsp;&lt;/h3&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;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;nbsp;&lt;/li&gt;
&lt;li&gt;부모 - 자식이 아닌 상위 - 하위 클래스 뉘앙스로 기억하자.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;상속을 is A 관계가 아닌, is a kind of로 생각하자.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ex ) 펭귄은 동물의 한 분류이다.&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;정리하자면, 상속은 상위 클래스의 특성을 재사용, 확장하는 것이고 is a kind of 관계를 만족해야 한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;&lt;b&gt;자바는 왜 다중 상속을 지원하지 않는가?&amp;nbsp;&lt;/b&gt;&lt;/u&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;인어공주는 물고기와 사람 클래스를 상속 받았다면, 인어공주는 수영할 때 물고기처럼 수영할까? 아니면 사람처럼 수영할까?&amp;nbsp;&lt;/li&gt;
&lt;li&gt;어느 쪽의 메소드를 수행해야 할 것인지 모호하다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인터페이스는 ?&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구현 클래스 is able to 인터페이스(구현 클래스는 인터페이스 할 수 있어야 한다.)&lt;/p&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;ex ) 헤엄을 칠 수 있는 ~&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;고래도 헤엄을 칠 수 있고 펭귄도 헤엄을 칠 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;고래 클래스와 펭귄 클래스가 헤엄이라는 메소드를 구현한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;상위 클래스는 물려줄 특성이 풍성할수록 좋고, 인터페이스는 구현을 강제할 메소드가 적을 수록 좋다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; 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;h3 data-ke-size=&quot;size23&quot;&gt; &amp;zwj; &amp;zwj; &amp;zwj;  다형성 : 사용편의성&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;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;정수 + 정수, 정수 + 소수, 소수 + 소수 3가지 모두 같은 함수 이름 add 사용이 가능&lt;/li&gt;
&lt;li&gt;add(int a, int b) , add (int a, double b) , add (double a, double b) 이런식으로 작성해둠&lt;/li&gt;
&lt;li&gt;사용하는 측에서 그냥 add만 쓰면 매개변수 따라 적합한 함수 매핑되어 수행&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;오버로딩이 지원되지 않는다면?&amp;nbsp;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;addIntToInt, addDoubleToInt, addDoubleToDouble .... 다 이름이 다르게 생성해야 한다.&lt;/li&gt;
&lt;li&gt;또한 사용할 때도, 정수끼리 덧셈이라면 addIntoInt 부르고, 실수끼리 덧셈이라면 addDoubleToDouble부르고...&lt;/li&gt;
&lt;li&gt;사용 편의성이 현저히 떨어진다!&amp;nbsp;&lt;/li&gt;
&lt;/ul&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;li&gt;형변환이나 instanceof 연산자로 일일이 하위 클래스 무엇인지 신경쓰지 않아도 된다. (알아서 하위 클래스가 오버라이딩한 메서드를 자동으로 호출해주므로)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1698608525296&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// Penguin extends Animal
// Animal의 showName -&amp;gt; Penguin에서 오버라이딩

Animal pingu = new Penguin();
pingu.showName(); // Penguin의 메소드가 호출된다!&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;style1&quot; /&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;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;public&lt;/li&gt;
&lt;li&gt;protected&lt;/li&gt;
&lt;li&gt;default&lt;/li&gt;
&lt;li&gt;private&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1698743195121&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package one;
class A {
    public int pub;
    protected int pro;
    int def;
    private int pri;

    static public int pubStatic;
    static protected int proStatic;
    static int defStatic;
    static private int priStatic;
    
    void runSomething() {
    
    }
    
    static void runStatic() {
    
    }
}&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;runSomething( )&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;상속 받았다면 객체를 생성하지 않아도 자식 클래스에서 부모의 인스턴스 변수(객체 변수) 접근 가능&lt;/li&gt;
&lt;li&gt;상속을 받지 않았다면 new ClassA() 로 객체 생성 후 접근 가능&lt;/li&gt;
&lt;li&gt;정적 변수들은 classA.pub 이런식으로 접근 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;runStatic( )&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;class A의 인스턴스 변수들은 모두 객체를 생성한 후 접근이 가능&lt;/li&gt;
&lt;li&gt;정적 변수들은 classA.pub 이런식으로 접근 가능&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각 접근 제어자, 패키지 별 접근 가능성 여부&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1698743383940&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 동일 패키지 (package one)
class AA extends A
class B

// 다른 패키지 (package two)
class AB extends A
class C&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;class AA extends A&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;runSomething()
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;상속 받았으므로 객체를 생성하지 않아도 public, protected, default 접근 가능&lt;/li&gt;
&lt;li&gt;classA.pubStatic, classA.proStatic, classA.defStatic 접근 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;runStatic()&amp;nbsp;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Static 메소드이므로 new ClassAA() 후 public, protected, default 접근 가능&lt;/li&gt;
&lt;li&gt;classA.pubStatic, classA.proStatic, classA.defStatic 접근 가능&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;h4 data-ke-size=&quot;size20&quot;&gt;class B&amp;nbsp;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;runSomething()
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;상속 받지 않았으므로 new ClassA() 한 후 public, protected, default 접근 가능
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;protected는 동일 패키지라면 상속 여부 상관없이 접근이 가능하고, 다른 패키지라면 상속받은 애만 접근 가능&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;classA.pubStatic, classA.proStatic, classA.defStatic 접근 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;runStatic()&amp;nbsp;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Static 메소드이므로 new ClassA() 후 public, protected, default 접근 가능&lt;/li&gt;
&lt;li&gt;classA.pubStatic, classA.proStatic, classA.defStatic 접근 가능&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;h3 data-ke-size=&quot;size23&quot;&gt;package two&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;class AB extends A&amp;nbsp;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;runSomething()
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;상속 받았으므로 객체 생성하지 않아도 public, protected 접근 가능&lt;/li&gt;
&lt;li&gt;classA.pubStatic, classA.proStatic 접근 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;runStatic()&amp;nbsp;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Static 메소드이므로 new ClassAB() 후 public, protected 접근 가능(상속받았으므로 얘도 가지고 있다)&lt;/li&gt;
&lt;li&gt;classA.pubStatic, classA.proStatic 접근 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;class C&amp;nbsp;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;runSomething()
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;상속 받지 않았으므로 new ClassA() 한 후 public만 접근 가능&lt;/li&gt;
&lt;li&gt;classA.pubStatic만 &amp;nbsp;접근 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;runStatic()&amp;nbsp;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Static 메소드이므로 new ClassA() 후 public만 접근 가능&lt;/li&gt;
&lt;li&gt;classA.pubStatic만 접근 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-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;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스프링 입문을 위한 자바 객체지향의 원리와 이해를 학습하고 정리한 내용입니다.&lt;/p&gt;</description>
      <category>Java/이론&amp;amp;문법</category>
      <author>Bubbles</author>
      <guid isPermaLink="true">https://bubblebubble.tistory.com/157</guid>
      <comments>https://bubblebubble.tistory.com/157#entry157comment</comments>
      <pubDate>Sat, 28 Oct 2023 19:56:21 +0900</pubDate>
    </item>
  </channel>
</rss>