<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>개발 아카이브</title>
    <link>https://kimdeveloper.tistory.com/</link>
    <description></description>
    <language>ko</language>
    <pubDate>Sun, 16 Aug 2026 10:18:04 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>기기디</managingEditor>
    <item>
      <title>Singleton</title>
      <link>https://kimdeveloper.tistory.com/66</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;정의&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;객체의 인스턴스가 오직 1개만 생성되는 패턴을 말한다.&lt;/li&gt;
&lt;li&gt;클래스의 인스턴스가 오직 하나만 생성되는것을 보장하고 해당 인스턴스에 전역적으로 접근할 수 있는 방법을 제공하는 패턴이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;싱글톤의 단점&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;private생성자를 가지고 있어 상속이 불가능하다&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;생성방식이 제한적이고 Mock객체로 대체하기 어려우며 동적으로 객체를 주입하기도 어렵기 때문이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;서버환경에서 싱글톤이 1개만 생성됨을 보장하지 못한다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;클래스로더를 어떻게 구성하느냐에 따라서 싱글톤이지만 1개이상의 객체가 생성될 수 있다. 자바언어를 이용한 싱글톤 기법은 서버환경에서 싱글톤을 보장하지 않는다. 분산환경에서도 싱글톤을 보장하기 어렵다&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;전역상태로 인한 문제
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;싱글톤의 스태틱메소드를 사용하여 언제든지 해당 객체를 사용하도록 전역설정을 할 수 있다. 전역상태는 객체지향 프로그래밍에서 권장하지 않는다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Spring에서는 컨테이너를 통해 직접 객체를 싱글톤으로 관리함으로써 객체지향스럽게 개발이 이루어지도록 해주었다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;(안전한)싱글톤 클래스,인스턴스를 구현하는 방법들&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;초기화 시점에 따라서 나눌 수 있고 thread safe보장여부에 따라서 나눠볼 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Eager Initialization - 이른 초기화&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;장점
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;가장 간단한 형태의 싱글톤 구현방법이다.&lt;/li&gt;
&lt;li&gt;클래스의 인스턴스를 클래스 로딩시점에 생성하는 방법으로 thread safe를 보장한다.&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;Exception에 대한 핸들링을 제공하지 않는다.&lt;/li&gt;
&lt;li&gt;인스턴스를 무조건 미리 만들어놓기에 실제로 사용되지 않을경우 낭비다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Static Block Initailization - 정적 블럭 초기화&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이른 초기화와 유사하지만 static block에 try-catch구문을 사용하여 Exception handling이 가능하다는 차이가 존재한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Lazy Initailization - 게으른 초기화&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이른 초기화처럼 클래스로딩시점에 초기화를 하는것이 아닌 해당 클래스의 인스턴스를 만드는 메소드를 호출할 때 인스턴스가 없다면 생성하는 방식이다.&lt;/li&gt;
&lt;li&gt;장점
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이른 초기화의 문제점인 사용하지 않았을 경우 인스턴스가 낭비되는 문제를 해결한다&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;단점
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;thread safe를 보장하지 않는다. 클래스의 인스턴스가 없는 상황에서 여러 쓰레드가 동시에 인스턴스를 만드는 메소드를 호출한다면 여러개의 인스턴스가 생성되어 싱글톤을 보장하지 못한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Lazy initialization with synchronized - 동기화블럭을 사용한 게으른 초기화&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;기존 게으른 초기화방법에 synchronized block을 사용하여 thread safe를 보장하는 방법이다.&lt;/li&gt;
&lt;li&gt;private static으로 해당 클래스의 인스턴스변수를 선언하고 private생성자를 사용하여 외부에서 생성을 막고 인스턴스 생성 메소드에 synchronized키워드를 사용하여 thread safe하게 만든다.&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;synchronized를 사용함에 따라 큰 성능저하를 유발하여 권장하지 않는 방법이다. 싱글턴 인스턴스를 자주 호출하는 어플리케이션이라면 더욱 더 성능이 떨어진다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Lazy initialization + Double-checked locking&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;synchronized를 바로 사용하는것이 아닌 조건문으로 인스턴스의 존재여부를 체크 이후 synchronized를 사용하여 성능저하를 줄이는 방법이다.&lt;/li&gt;
&lt;li&gt;성능저하를 근본적으로 해결하는 방법은 아니다.&lt;/li&gt;
&lt;li&gt;volatile예약어를 사용하면 멀티스레드환경에서도 instance변수가 singleton인스턴스로 초기화되는 과정이 올바르게 진행되도록 할 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Initialization on demand holder idiom - holder에 의한 초기화&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;inner static helper class를 사용하는 방식으로 volatile이나 synchronized키워드 없이 동시성 문제를 해결한다.&lt;/li&gt;
&lt;li&gt;클래스안에 클래스를 두어 홀더역할을 하게하여 JVM의 Class Loader메커니즘과 Class가 로드되는 시점을 이용한 방법이다.&lt;/li&gt;
&lt;li&gt;JVM의 클래스 초기화 과정에서 보장되는 원자적특성을 이요하여 싱글톤의 초기화 문제에 대한 책임을 JVM에 위임한다.&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;private inner static class를 만들어 싱글톤 인스턴스를 갖게 한다.&lt;/li&gt;
&lt;li&gt;inner class는 Singleton클래스가 Load될때도 Load되지 않다가 getInstance()가 호출됐을때 JVM메모리에 로드되고 인스턴스를 생성한다.&lt;/li&gt;
&lt;li&gt;holder안에 선언된 인스턴스가 static이기 때문에 클래스 로딩시점에 한번만 호출될것이며 final을 사용해 다시 값이 할당되지 않도록 하는 방법이다&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;제일 많이 사용되는 Singleton클래스 사용방법이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Enum Singleton&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;정의&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Java에서 리플렉션이나 직렬화과정에서 싱글톤이 파괴될 수 있기에 이를 방지하기 위하여 enum을 사용하는 방법이다. enum클래스의 인스턴스 생성은 기본적으로 Thread Safe를 보장하기 때문이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;주의해야할점&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;만들려는 싱글톤 클래스가 enum클래스 말고 다른 클래스를 상속받아야하는 경우 다중상속이 불가능하기에 사용하기 어렵다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;싱글톤을 보장하기 위한 Spring Configuration&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;각각 다른 빈에서 의존성 주입의 대상이 같은 클래스(ex&amp;gt;다른 서비스가 같은 레포지토리)일경우 싱글톤이 깨지는 상황이 된다.&lt;/li&gt;
&lt;li&gt;이런 경우 싱글톤이 깨지지 않도록 스프링은 클래스의 바이트코드를 조작하는 라이브러리를 사용한다.(런타임시?) 해당내용은 Configuration Annotation안에 있다.&lt;/li&gt;
&lt;li&gt;Configuration Annotation또한 빈으로 등록된다. Configuration클래스는 그대로 빈으로 등록되지 않고 스프링이 CGLIB이라는 바이트코드조작 라이브러리를 사용하여 Configuration클래스를 상속받은 임의의 다른 클래스를 만들고 그 다른 클래스를 빈으로 등록한다.&lt;/li&gt;
&lt;li&gt;이런 과정을 통해서 @Bean이 등록된 메서드마다 이미 스프링 빈이 존재하면 존재하는 빈을 반환하고, 스프링 빈이 없으면 생성해서 스프링 빈으로 등록하고 반환하는 코드가&amp;nbsp;&lt;b&gt;동적으로 만들어진다.&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <author>기기디</author>
      <guid isPermaLink="true">https://kimdeveloper.tistory.com/66</guid>
      <comments>https://kimdeveloper.tistory.com/66#entry66comment</comments>
      <pubDate>Sat, 16 Mar 2024 16:31:12 +0900</pubDate>
    </item>
    <item>
      <title>Java Input/Output(I/O)</title>
      <link>https://kimdeveloper.tistory.com/64</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;배경&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;java는 데이터 입력, 출력과 관련하여 추상클래스와 다양한 구현클래스를 제공한다.&lt;/li&gt;
&lt;li&gt;InputStream : AudioInputStream, ByteArrayInputStream, FileInputStream, FilterInputStream, ObjectInputStream, PipedInputStream, SequenceInputStream, StringBufferInputStream&lt;/li&gt;
&lt;li&gt;Reader : BufferedReader, CharArrayReader, FilterReader, InputStreamReader, PipedReader, StringReader, URLReader&lt;/li&gt;
&lt;li&gt;OutputStream : ByteArrayOutputStream, FileOutputStream, FilterOutputStream, ObjectOutputStream, PipedOutputStream&lt;/li&gt;
&lt;li&gt;Writer : BufferedWriter, CharArrayWriter, FilterWriter, OutputStreamWriter, PipedWriter, PrintWriter, StringWriter&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;정의&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;입출력&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;프로그램에서 데이터를 외부에서 읽고 다시 외부로 출력하는 작업에 사용하는것을 말한다.&lt;/li&gt;
&lt;li&gt;입출력의 예시 : 키보드입력, 파일입출력, 네트워크, 모니터출력&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Stream&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;단방향으로 연속적으로 데이터가 흘러가는것을 말한다. 단방향이라는 특성상 하나의 스트림으로 입력과 출력을 동시에 하는것이 불가능하다. 네트워크 환경에서 데이터 교환을 하기 위해서는 입력스트림과 출력스트림이 따로 있어야한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Java NIO&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;버퍼와 채널기반의 입출력방식을 말한다. 자바4에 처음 등장했다.&lt;/li&gt;
&lt;li&gt;NIO 방식은&amp;nbsp;버퍼를 사용하여 여러개의&amp;nbsp; 바이트를 한꺼번에 입출력하는것이 가능하다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Java NIO2&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;자바7에 첫등장하였다. 이전 File클래스의 단점들을 보완하여 나왔다.&lt;/li&gt;
&lt;li&gt;심볼릭 링크처리 기능과 WatchService 인터페이스를 통하여 어떤파일이 변경되었는지 쉽게 확인하는것이 가능하다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;특징&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Java NIO&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;기존 IO방식은 출력 스트림이 1바이트를 쓰면 입력 스트림이 1바이트를 읽는것에 반하여 버퍼를 사용함에 따라 여러개의 바이트를 입출력하는것이 가능하다. IO도 버퍼를 제공해주는 보조 스트림인 BufferedInputStream, BufferedOutputStream을 연결해서 사용하기도 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Java NIO2&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;InputStream - OutputStream&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;바이트기반 스트림. 데이터를 byte단위로 입력하고 출력한다.&lt;/li&gt;
&lt;li&gt;바이너리 형태 데이터를 다룰때 사용한다. 그림, 멀티미디어, 문자 등 모든 종류의 데이터를 주고받을 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Reader - Writer&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;문자기반 스트림. 데이터를 char문자 단위로 입력하고 출력한다.&lt;/li&gt;
&lt;li&gt;문자를 주고받는데 특화되어있다. 바이트 코드를 읽어서 문자로 변환하고 문자를 바이트코드로 변환하여 출력하는것을 처리해준다.&lt;/li&gt;
&lt;li&gt;기본적으로 인코딩형식은 JVM의 default charset을 사용한다.&lt;/li&gt;
&lt;li&gt;일반적인 텍스트 파일을 읽을때는 Reader와 Writer의 구현클래스를 사용한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;File&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;파일크기, 파일속성, 파일이름등 정보를 조회하고 파일생성, 삭제기능을 제공하는 클래스다. OS에 디렉토리를 생성하거나 디렉토리에 존재하는 파일리스틑 조회하는것도 가능하다.&lt;/li&gt;
&lt;li&gt;파일의 데이터를 읽고 쓰는 기능은 스트림을 사용해야한다. FileInputStream, FileOutputStream, FileReader, FileWriter가 있다.&lt;/li&gt;
&lt;li&gt;단점 : 심볼릭링크,속성,파일의 권한등에 대한 기능이 없다 / 파일들 삭제하는 delete()메소드는 실패시 예외가 발생하지 않고 boolean타입의 결과만 반환한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;주의해야할점&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;파일이나 소켓통신으로 다른 회사와 협업하여 데이터를 송수신 처리하며 데이터의 규격을 정의할 때, 필드의 길이가 문자단위인지 byte단위인지 명확하게 정해야한다.&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Java</category>
      <author>기기디</author>
      <guid isPermaLink="true">https://kimdeveloper.tistory.com/64</guid>
      <comments>https://kimdeveloper.tistory.com/64#entry64comment</comments>
      <pubDate>Thu, 7 Mar 2024 21:10:57 +0900</pubDate>
    </item>
    <item>
      <title>Java.lang</title>
      <link>https://kimdeveloper.tistory.com/63</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;java.lang이란?&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;자바 언어로 개발하기위한 기본적인 기능들이 담겨져 있는 패키지&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;숫자에 대한 참조자료형과 기본자료형&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;자바에서는 숫자를 처리하기 위한 자료형으로 같은 유형의 값을 다루지만 기본자료형과 참조자료형 두가지가 존재하고 참조자료형은 기본자료형처럼 형변환 없이 사용하는것을 컴파일러에서 지원한다. 그 이유는 다음과 같다.&lt;/li&gt;
&lt;/ul&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;매개 변수를 참조자료형으로만 받는 메소드를 처리하기 위해서이다.&lt;/li&gt;
&lt;li&gt;제네릭과 같이 기본자료형을 사용하지 않는 기능을 사용하기 위해서이다.&lt;/li&gt;
&lt;li&gt;최소값이나 최대값과 같이 클래스에 선언된 상수값을 사용하기 위해서이다. &amp;rarr; 숫자의 참조료형 클래스들은 MIN_VALUE와 MAX_VALUE라는 상수값을 가지고 있다. 이 값들은 각 자료형들의 최소최대값 범위를 나타낸다.&lt;/li&gt;
&lt;li&gt;문자열과 숫자간 변환을 쉽게하고 2,8,10,16진수 변환을 쉽게하기 위해서이다. &amp;rarr; 숫자의 참조료형 클래스들은 toBinaryString(), toHexString()과 같은 메소드를 제공한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;System클래스&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;시스템 속성값 관리 / 시스템 환경값 조회 / GC수행 / JVM종료 / 현재시간조회 / 기타 관리용 메소드 등등의 역할을 한다. 다만 GC, jvm종료와 관련한 메소드들은 개발자가 수행해서는 안된다.&lt;/li&gt;
&lt;li&gt;자바는 메모리처리를 개발자가 하지 않도록 되어있다. 개발자가 호출하지 않아도 JVM이 알아서 관리를 하고, 만약에 개발자가 직접호출한다면 시스템은 하려던 일들을 멈추고 이 메소드를 수행한다. 이에 따라 GC와관련된 메소드는 호출해서는 안된다.&lt;/li&gt;
&lt;li&gt;jvm종료메소드를 사용하면 프로그램이 죽는다. 하지마라.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;toString(), valueOf()&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;객체를 출력할때는 toString()보다 valueOf()를 사용하는것이 null처리 측면에서 훨씬 안전하다.&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Java</category>
      <author>기기디</author>
      <guid isPermaLink="true">https://kimdeveloper.tistory.com/63</guid>
      <comments>https://kimdeveloper.tistory.com/63#entry63comment</comments>
      <pubDate>Tue, 5 Mar 2024 23:10:20 +0900</pubDate>
    </item>
    <item>
      <title>Java Collection</title>
      <link>https://kimdeveloper.tistory.com/62</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;자바에서 제공하는 Collection interface에 대해서 정리한 내용&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Java에서 Collection이란?&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;Iterable인터페이스를 상속받는다. 기본적으로 Iterable인터페이스를 사용하여 순차적으로 데이터를 가져올 수 있다는것을 의미한다. 향상된 for문을 쓸 수 있다는걸 의미하기도 한다.&lt;/li&gt;
&lt;li&gt;컬렉션의 인터페이스는 List, Set, Queue, Map으로 구분할 수 있다. 이 중에서 Map은 Collection Interface를 상속받고 있지 않지만 Collection으로 구분한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Java에서 자료구조의 분류&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;선형자료구조(Linear Data Structure) : List, Queue, Deque이 있다. 데이터가 일렬로 연결된 형태를 말한다.&lt;/li&gt;
&lt;li&gt;비선형자료구조(NonLinear Data Structure) : Graph, Tree가 있다. 각 요소가 여러개의 요소와 연결된 형태를 생각를 말한다. 거미줄처럼 엮여있는 형태로 그려진다.&lt;/li&gt;
&lt;li&gt;Set은 기타자료구조, 집합자료구조로 분류된다. 집합의 경우 데이터가 연결된 형식이 아니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;List인터페이스&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;저장순서가 있는 데이터의 집합으로 데이터의 중복을 허용한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;ArrayList&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;동적으로 크기가 조정되는 배열을 제공한다. 기본크기는 10으로 설정되어있지만 개체를 추가, 삭제함에 따라서 ArrayList내부에서 자동으로 크기를 조절한다. 이러한 작업은 어플리케이션 성능에 영향을 주고 데이터 크기가 예측된다면 크기를 지정하는것도 방법이라고 한다.&lt;/li&gt;
&lt;li&gt;하나의 List객체를 여러 스레드에서 사용한다면 Thread Safe하지 않다. 단방향 포인터구조를 가진다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Vector&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;ArrayList와 유사하지만 Thread Safe하다. Thread Safe를 보장하기 위해서 동기화 처리가 자주 일어나 비교적 성능이 떨어지고 무겁다.&lt;/li&gt;
&lt;li&gt;한개의 스레드만 접근 가능하다. 여러개의 스레드가 접근한다면 다른 스레드는 기다려야한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Stack&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Vector를 확장한다. 나중에 들어온 데이터가 먼저 나간다는 특징(Last In First Out)이 있다.&lt;/li&gt;
&lt;li&gt;보통 프로그래밍 언어에서 스택이라고 하면 메소드가 호출된 순서를 기억하는 장소를 말한다. 보통 메소드 안에 메소드를 호출하는것처럼 갈고리처럼 엮여있는 데이터(정해진 순서를 지켜야하는 데이터)를 다룰때 활용한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Set인터페이스&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;저장순서를 보장하지 않고 데이터의 중복을 허용하지 않는다는 특징을 가진다.&lt;/li&gt;
&lt;li&gt;중복되는것을 방지하고 원하는 값이 포함되어있는지 확인하려고 할 때 주로 쓰인다.&lt;/li&gt;
&lt;li&gt;Set은 순서가 없어서 index를 파라미터로 넘기는 메소드나 데이터의 인덱스를 반환하는 메소드가 존재하지 않는다. ex) get(), indexOf()&lt;/li&gt;
&lt;li&gt;Thread Safe를 보장하지 않는다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;HashSet&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Set중에 가장 빠르다. 순서를 보장하지도 않고 정렬작업도 지원하지 않는다.&lt;/li&gt;
&lt;li&gt;생성자를 이용하여 객체생성시 로드팩터라는 개념을 활용하여 배열의 크기를 지정한다. 데이터의 개수가 증가하여 로드팩터보다 커지면 저장공간의 크기는 증가되고 해시재정리 작업이 필요하다. 이 작업은 자료구조를 재구성하는 단계를 거치므로 성능에 영향을 끼친다.&lt;/li&gt;
&lt;li&gt;로드팩터가 크면 클수록 데이터를 찾는 시간이 늘어난다.&lt;/li&gt;
&lt;li&gt;객체를 저장하기전 저장할 객체의 hashCode()메소드를 호출하여 해시코드를 알아내고 set내부에 hashCode와 비교하여 없을때 저장한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;TreeSet&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;HashSet보다 느리다. 데이터의 순서를 오름차순으로 정렬하여 저장한다. 다른 Set인터페이스를 확장하는 클래스들과 다르게 순서를 정렬하는 메소드를 제공한다.&lt;/li&gt;
&lt;li&gt;red-black이라는 이진탐색트리타입으로 값이 저장된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;LinkedHashSet&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;HashSet과 유사하지만 차이점은 데이터를 저장하는 순서를 보장한다. set중에서 성능이 가장 떨어진다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Queue인터페이스&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;FIFO기능을 지원하기 위해서 필요한 인터페이스다.&lt;/li&gt;
&lt;li&gt;여러 쓰레드에서 들어오는 작업을 순차적으로 처리할 때 많이 사용한다. ex)서버에 클라이언트로 부터 동시에 다수의 요청이 들어왔을때 순차적으로 처리하기 위해 사용&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;LinkedList&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;객체를 생성할때 크기를 지정하지 않는다. 데이터들이 앞뒤로 연결되는 구조이기 때문에 미리 공간을 설정할 필요가 없다. 정해진 길이보다 데이터가 늘어났을때 HashSet이나 다른 배열처럼 크기를 자동으로 늘리는 작업을 하지 않는다.&lt;/li&gt;
&lt;li&gt;List, Queue, Deque인터페이스를 구현한다.&lt;/li&gt;
&lt;li&gt;데이터가 메모리상에서 연속된 위치에 저장되지 않고 데이터부분과 주소부분이 있는 별도의 객체에 저장된다. 이러한 부분때문에 ArrayList와 비교할때 조회부분에서 속도가 느릴 수 있다. 대신 삽입과 삭제가 데이터의 위치정보만 수정하면 되기에 빠르다.&lt;/li&gt;
&lt;li&gt;포인터와 주소를 사용해서 데이터를 가져오고 각 데이터를 노드라고 부르기도한다. 양방향 포인터구조를 가진다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;PriorityQueue&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;우선순위에 따라서 객체를 처리해야 할 때 사용한다. poll() - 오름차순으로 데이터를 반환하고 제거하고 peek()첫번쨰 데이터결과를 반환하는 등의 기능들이 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Deque&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;양방향 큐라고 불리기도한다. 큐와 같이 선입선출의 구조를 가지지만 양쪽 끝에서 데이터를 추가하고 제거 할 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;ArrayDeque&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Deque와 같지만 동적으로 크기조절이 가능하다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Map인터페이스&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;HashTable, HashMap, TreeMap, Properties, LinkedHashMap을 구현한다.&lt;/li&gt;
&lt;li&gt;key-value형식으로 데이터를 저장하고 순서는 유지되지 않으며 키의 중복을 허용하지 않는다.&lt;/li&gt;
&lt;li&gt;Map객체에 저장된 모든 value를 반환하는 values()메소드는 value는 중복을 허용하기 때문에 Collection으로 목록을 반환한다.&lt;/li&gt;
&lt;li&gt;Map객체에 저장된 모든 key를 반환하는 keySet()메소드는 key는 중복을 허용하지 않기 때문에 Set으로 목록을 반환한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;HashMap&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;HashMap에서 키값이 될 객체가 직접 만든 클래스일 경우, 기존의 hashCode()와 equlas()메소드를 재정의하여 동일한 값을 비교할 수 있도록 해줘야한다.&lt;/li&gt;
&lt;li&gt;Thread Safe하지 않다. 이런 특징때문에 싱글쓰레드환경에서 사용하는게 좋다.&lt;/li&gt;
&lt;li&gt;동기화처리를 하지 않기 때문에 데이터 조회시 속도가 빠르다.&lt;/li&gt;
&lt;li&gt;key와 value에 null삽입을 허용한다.&lt;/li&gt;
&lt;li&gt;HashTable이나 ConcurrentHashMap보다 조회속도가 빠르지만 신뢰성과 안정성이 떨어진다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;HashTable&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;JDK1.0부터 만들어져 사용됐고 JDK1.2에 추가된 Map인터페이스에 맞춰 보완됐다. 그렇기에 Map인터페이스를 구현했지만 다른 Map인터페이스를 구현한 클래스들과 차이가 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;Enumeration 객체를 통해서 데이터 처리. Map은 컬렉션 뷰를 사용.&lt;/li&gt;
&lt;li&gt;키-값 쌍으로 데이터 순환 처리 불가능(키, 값은 가능). Map은 키, 값, 키-값 쌍으로 데이터 순환처리 가능.&lt;/li&gt;
&lt;li&gt;이터레이션을 처리하는 도중에 데이터를 삭제하는 안전한 방법 제공 x. Map은 제공.&lt;/li&gt;
&lt;/ol&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;HashMap과 동일하지만 Thread Safe하다. 멀티쓰레드를 사용할 수 있고 ThreadSafe를 Sychronized로 보장하기 때문에 HashMap보다는 느리다.&lt;/li&gt;
&lt;li&gt;key와 value에 null을 허용하지 않는다&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;ConcurrentHashMap&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;key와 value에 null을 허용하지 않는다&lt;/li&gt;
&lt;li&gt;ThreadSafe를 보장한다. 보장방법으로 특정 Entry를 처리할때 해당 Entry에만 락을 거는 방식으로 HashTable보다 빠르다.&lt;/li&gt;
&lt;li&gt;HashMap의 동기화문제를 보완하기 위해서 나타났다.&lt;/li&gt;
&lt;li&gt;키와값으로 구성되는 데이터를 엔트리라고 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;TreemMap&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;SortedMap인터페이스를 구현하여 저장되는 키를 정렬한다.&lt;/li&gt;
&lt;li&gt;저장하는 시점에 키를 오름차순으로 정렬한다. 숫자 &amp;rarr; 알파벳대문자 &amp;rarr; 알파벳소문자 &amp;rarr; 한글순으로 정렬한다.&lt;/li&gt;
&lt;li&gt;키가 정렬되기 때문에 매우 많은 데이터를 저장할 경우 HashMap보다 느리다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Properties&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;HashTable을 확장하는 클래스다. key값을 String으로만 제한한다. .properties파일을 읽을때 사용된다고 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Collections클래스&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;java1.2부터 존재하는 static클래스로 Collection인터페이스에 속하는 클래스 객체들을 정렬하거나 비교, 임의의값으로 섞는 기능들을 지원한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Iterator, ListIterator, Enumeration&lt;/b&gt;&lt;/h2&gt;</description>
      <category>Java</category>
      <author>기기디</author>
      <guid isPermaLink="true">https://kimdeveloper.tistory.com/62</guid>
      <comments>https://kimdeveloper.tistory.com/62#entry62comment</comments>
      <pubDate>Sat, 2 Mar 2024 09:33:00 +0900</pubDate>
    </item>
    <item>
      <title>로드밸런서Load Balancer</title>
      <link>https://kimdeveloper.tistory.com/61</link>
      <description>&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;scale-up : 서버가 더 빠르게 동작하도록 단일서버의 하드웨어의 성능을 올리는 방법&lt;/li&gt;
&lt;li&gt;scale-out : 하나의 서버보다는 여러대의 서버가 나눠서 일을 하는 방법. 무중단서비스를 재공할 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;로드밸런서는 이 중 scale-out에 관한 방법이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;정의&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;클라이언트의 요청에 대하여 각각 서버의 부하,속도저하를 고려하여 적절히 분산처리해주는 것을 말한다.&lt;/li&gt;
&lt;li&gt;트래픽을 여러대의 서버에 균등하게 분산시켜주는 역할을 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;분산방식&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Round Robin라운드로빈
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;서버에 들어온 요청을 순서대로 돌아가며 배정하는 방식을 말한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Least Connections최소 연결 방식
&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;IP해시방식 Source
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;사용자의 IP를 Hashing하여 분배하는 방식&lt;/li&gt;
&lt;li&gt;사용하는 항상 같은서버로 연결된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;분류&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;L2 : Mac Address를 기반으로 Load Balancing&lt;/li&gt;
&lt;li&gt;L3 : IP주소를 기반으로 Load Balancing&lt;/li&gt;
&lt;li&gt;L4 : Transport Level(전송계층 ex&amp;gt;TCP, UDP)에서 Load Balancing.&lt;/li&gt;
&lt;li&gt;L7 : Application Layer Level(HTTP Request)에서 Load Load Balancing.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;부가기능&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;NAT
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;사설IP주소를 공인IP주소로 바꾸는데 사용하는 통신망의 주소변조기&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Tunneling
&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;DSR
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;로드 밸런서 사용시 서버에서 클라이언트로 되돌아가는 경우 목적지 주소를 &lt;b&gt;스위치의 IP주소가 아닌 클라이언트의 IP주소로 전달&lt;/b&gt;해서 네트워크 스위치를 거치지 않고 바로 클라이언트를 찾아가는 개념&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;</description>
      <author>기기디</author>
      <guid isPermaLink="true">https://kimdeveloper.tistory.com/61</guid>
      <comments>https://kimdeveloper.tistory.com/61#entry61comment</comments>
      <pubDate>Thu, 29 Feb 2024 11:58:14 +0900</pubDate>
    </item>
    <item>
      <title>JPA</title>
      <link>https://kimdeveloper.tistory.com/60</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;정의&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Java Persistence API. 자바에서 ORM기준 표준으로 사용되는 인터페이스 모음을 말한다.&lt;/li&gt;
&lt;li&gt;자바 어플리케이션에서 관계형 데티어베이스를 사용하는 방식을 정의한 인터페이스&lt;/li&gt;
&lt;li&gt;인터페이스이기 때문에 별도로 JPA의 구현체가 필요하다. 대표적으로 Hibernate가 있다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;정리&lt;/b&gt; : 자바의 ORM기술표준으로 인터페이스의 모음이 됩니다. 엄밀히 따지면 인터페이스이기 때문에 Hibernate와 같은 구현체가 필요하고 스프링에서는 SpringDataJPA를 통해 JPA를 사용합니다. JPA를 사용하면 개발자가 쿼리를 직접 작성하지 않고도 db테이블과 맵핑되어있는 엔티티 모델클래스와 자바메소드를 이용하여 DB를 조작할 수 있게 만들어줍니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;특징&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;영속성 컨텍스트&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;엔티티를 DB에 영속화 시킬수 있는 환경을 말한다. 엔티티 매니저를 통하여 영속성 컨텍스트에 접근하고 관리하는것이 가능하다. 엔티티 모델클래스를 엔티티매니저를 거쳐 영속성 컨텍스트에 저장시킨다.&lt;/li&gt;
&lt;li&gt;엔티티를 담고 있는 집합으로 영속성컨텍스트에 속해 있는 엔티티만 트랜잭션이 끝나는 시점에 테이블에 변경된 내요을 반경하게 된다. 이러한 특징으로 인해서 엔티티 객체의 값만 변경해주면 update query없이도 값을 수정할 수 있다.(더티체킹)&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;엔티티를 식별자값(@id로 테이블의 기본키와 맵핑한 값)으로 구분한다.&lt;/li&gt;
&lt;li&gt;영속상태에서는 식별자값이 반드시 있어야하고 없을경우 예외가 발생한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;장점
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;엔티티 조회시 영속성컨텍스트 내부에 캐시가 존재한다. 캐시의 키는 식별자값을 사용한다.&lt;/li&gt;
&lt;li&gt;버퍼링기능 지원 통해서 불필요하게 네트워크 타는 횟수를 줄인다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;엔티티의 생명주기&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;비영속
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;영속성컨텍스트와 관계가 없는 상태&lt;/li&gt;
&lt;li&gt;순수한 자바 객체의 상태로 DB, 영속성컨텍스트와 상관이 없다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;영속managed
&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;em.find나 JPQL을 통해 조회한 엔티티도 영속상태다.&lt;/li&gt;
&lt;li&gt;이 상태에서 엔티티의 값을 바꾸면 트랙잭션이 끝날때 DB에 반영된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;준영속detached
&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;em.detach호출로 사용할 수 있다.&lt;/li&gt;
&lt;li&gt;영속상태에서 영속성컨텍스트가 관리하지 않으면 준영속 상태에 빠진다.&lt;/li&gt;
&lt;li&gt;캐시, 지연로딩, 더티체킹 업데이트, 버퍼링 기능을 제공하지 않는다.&lt;/li&gt;
&lt;li&gt;다시 영속상태로 변경하기 위해서는 merge()를 사용하면 된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;삭제removed
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;삭제된상태&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;장점&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;생산성&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;SQL문을 사용하지않고 메소드를 통해 DB를 조작할 수 있어 개발자가 쿼리에 신경쓰지 않고 객체모델을 이용하여 비즈니스 로직을 구성하는데만 집중가능하다.&lt;/li&gt;
&lt;li&gt;MyBatis를 사용할때 필요한 선언문,할당 같은 부가적인 코드가 줄어든다. &amp;rarr; &lt;s&gt;Mybatis를 사용할때는 쿼리 말고도 할당,선언해주어야하는 부분들이 있는데 그런부분들이 줄어듭니다.&lt;/s&gt;&lt;/li&gt;
&lt;li&gt;흔한 경우는 아니지만 데이터베이스가 바뀌는 경우 쿼리를 새롭게 짤 필요가 없다&lt;/li&gt;
&lt;li&gt;간단하게 반복되는 CRUD를 작성할 필요 없다.&lt;/li&gt;
&lt;li&gt;설정에 따라 객체를 변경하면 알아서 DB에 update가 나가도록 할 수 있다.&lt;/li&gt;
&lt;li&gt;유지보수 측면에서 Mybatis는 컬럼에 변동이 있을경우 많은 SQL들을 수정해야하는 반면에 JPA는 엔티티에 필드만 추가하면 된다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;정리 :&lt;/b&gt; 장점으로 생산성이 좋아집니다. 자바객체와 메소드를 가지고 db로 질의를 날릴수 있어서 쿼리를 작성하는 시간이 줄어들고 쿼리외에도 mybatis를 사용하기 위해 할당,선언해줘야하는 xml같은 작업이 줄어듭니다. 반복되는 간단한 CRUD같은 경우 이런 부분에서 크게 체감이 됩니다. 그것 외에도 테이블 컬럼에 변동이 있을때 엔티티클래스에 수정만 해주면 되기 때문에 편리합니다. &amp;rarr; 가장 큰 장점으로는 생산성이있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;객체지향 관점&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;객체지향적인 코드작성이 가능하다. 쿼리가 아닌 객체중심으로 개발할 수 있다. 보통 패러다임의 불일치를 해결했다고 한다. java에서는 상속이라는 개념이 존재하는데 DB에서는 이런 객체의 상속관계를 지원하지 않는다.&lt;/li&gt;
&lt;li&gt;자바코드를 통하여 자유로운 객체그래프 탐색이 가능하다. 지연로딩전략을 통해 객체를 사용하는 시점에 Select쿼리를 날려서 객체를 가져오도록 할 수 있다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;정리&lt;/b&gt; : 개체지향적인 개발이 가능합니다. 자바의 개체인 클래스를 엔티티로 하여 테이블과 매핑을 하고 이를 이용하여 db를 조작하는것이 가능하기 때문입니다. 이를 통해 테이블상속관계를 엔티티로 표현하기도 하고 객체그래프 탐색을 통하여 데이터를 조회하는것도 가능합니다. 다만 객체그래프 탐색시에는 로딩전략을 잘 설정하는것이 중요하겠습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;성능최적화&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;JPA는 JDBC와 DB사이에 존재하기 때문에 버퍼링,캐싱기능을 지원한다.&lt;/li&gt;
&lt;li&gt;캐싱 : 같은 트랜잭션 안에서는 같은 엔티티를 반환하여. 조회시 같은 메소드를 두번 실행시키더라도 실제로 SQL은 한번만 실행된다.&lt;/li&gt;
&lt;li&gt;버퍼링 : 트랜잭션을 커밋할때 까지 INSERT SQL을 쌓아놨다가 한번에 전송한다. INSERT Query를 매번 실행시켜 불필요한 네트워크를 타지 않는다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;정리&lt;/b&gt; : 한 트랜잭션 안에서 이런 특징들을 모르고 기존 mybatis처럼 사용할 경우 개발자가 의도한대로 동작하지 않을 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;단점&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;설계가 잘못된 경우 속도가 떨어지거나 코드 일관성이 떨어질 수 있다.&lt;/li&gt;
&lt;li&gt;복잡하고 무거운 쿼리는 속도를 위한 별도의 튜닝이 필요하여 결국 SQL문을 사용할 수 있다.&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;캐싱, 버퍼링과 같은 특성들을 잘 모르고 기존에 사용하던 MyBatis처럼 사용할 경우 개발자가 의도한대로 동작하지 않을 수 있다. entity duplicate등...&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;부가정리 및 설명&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;ORM - Object Relational Mapping&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;스프링과 같은 어플리케이션의 Class와 DB의 테이블을 연결(매핑)한다는 뜻이다.&lt;/li&gt;
&lt;li&gt;ORM프레임워크는 DB와 어플리케이션 사이에 중간을 매핑해주는 역할을 한다.&lt;/li&gt;
&lt;li&gt;어플리케이션의 객체를 DB테이블에 자동으로 영속화 해주는것이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;영속성&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;하나의 객체가 자신을 생성한 작업이 종료되었음에도 불구하고 지속적으로 존재하는 상태를 말한다.&lt;/li&gt;
&lt;li&gt;소멸되지 않고 저장될 수 있는 데이터의 성질을 말한다.&lt;/li&gt;
&lt;li&gt;JPA에서는 엔티티를 영속화하여 DB에 저장한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Spring Data JPA&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;JPA를 쉽게 사용하기 위하여 스프링에서 제공하는 프레임워크&lt;/li&gt;
&lt;li&gt;Spring Data Redis, MongoDB등이 존재한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;참고 및 레퍼런스&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://velog.io/@adam2/JPA는-도데체-뭘까-orm-영속성-hibernate-spring-data-jpa&quot;&gt;https://velog.io/@adam2/JPA는-도데체-뭘까-orm-영속성-hibernate-spring-data-jpa&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://ultrakain.gitbooks.io/jpa/content/chapter3/chapter3.4.html&quot;&gt;https://ultrakain.gitbooks.io/jpa/content/chapter3/chapter3.4.html&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://suhwan.dev/2019/02/24/jpa-vs-hibernate-vs-spring-data-jpa/&quot;&gt;https://suhwan.dev/2019/02/24/jpa-vs-hibernate-vs-spring-data-jpa/&lt;/a&gt;&lt;/p&gt;</description>
      <author>기기디</author>
      <guid isPermaLink="true">https://kimdeveloper.tistory.com/60</guid>
      <comments>https://kimdeveloper.tistory.com/60#entry60comment</comments>
      <pubDate>Thu, 22 Feb 2024 16:35:38 +0900</pubDate>
    </item>
    <item>
      <title>Hash Collision 해시 충돌</title>
      <link>https://kimdeveloper.tistory.com/59</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;정의&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;해시값을 이용하여 데이터를 저장할때 해시주소가 겹쳐 충돌하는 경우 생기는 문제&lt;/li&gt;
&lt;li&gt;Open Addressing / Separate Chaining 두가지 방법으로 해결을 한다&lt;/li&gt;
&lt;li&gt;Open Addressing
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;저장하려는 데이터에 할당한 해시주소가 이미 존재한다면 다른 주소로 새롭게 할당하는 방식&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Separate Chaing
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;해시 테이블의 구조를 변경하여 하나 이상의 키값을 저장할 수 있도록 만드는 방법&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Java에서는 Separate Chaing를 사용하여 해쉬 충돌을 해결&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;해시 충돌의 해결 방법&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. Chaning&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해시 버킷내 링크드 리스트를 할당하여 버킷에 데이터를 삽입하다 해시 충돌이 발생하면 링크드 리스트로 데이터를 연결하는 방식&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;장점
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;링크드 리스트 하나로 해결 가능하기에 복잡한 계산식을 사용할 필요가 없다.&lt;/li&gt;
&lt;li&gt;개방주소법의 선형탐색에 비해서 성능저하가 적다&lt;/li&gt;
&lt;li&gt;성능저하 참고 이미지&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;709&quot; data-origin-height=&quot;422&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cMS2b6/btsHRKBU4Cm/4UKoQZ50mTeC506qzaHKok/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cMS2b6/btsHRKBU4Cm/4UKoQZ50mTeC506qzaHKok/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cMS2b6/btsHRKBU4Cm/4UKoQZ50mTeC506qzaHKok/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcMS2b6%2FbtsHRKBU4Cm%2F4UKoQZ50mTeC506qzaHKok%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;465&quot; height=&quot;422&quot; data-origin-width=&quot;709&quot; data-origin-height=&quot;422&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;h3 data-ke-size=&quot;size23&quot;&gt;2. Open Addressing개방 주소법&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1의 체이닝은 버킷이 꽉 차더라도 링크드리스트로 계속해서 늘려가기에 데이터의 주소값은 바뀌지 않는다.(Closed Addressing)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개방 주소법은 해시 충돌이 일어나는 경우 다른 버킷에 데이터를 삽입하는 방식을 말한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개방 주소법은 3가지 방식으로 나눌 수 있다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;선형 탐색
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;해시 충돌시 다음 버킷, 혹은 몇개를 건너뛰어 데이터를 삽입한다&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;제곱 탐색
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;해시 충돌시 제곱만큼 건너뛴 버킷에 데이터를 삽입한다(1, 4, 9 , 16)&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;이중 해시
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;해시 충돌시 다른 해시함수를 한번 더 적용한 결과를 이용한다&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;장점
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;체이닝의 링크드 리스트처럼 포인터가 필요없고 지정한 메모리 외에 추가적인 저장공간 필요 없다&lt;/li&gt;
&lt;li&gt;삽입, 삭제시 체이닝에 비해서 오버헤드가 적다.&lt;/li&gt;
&lt;li&gt;저장할 데이터가 적을때 더 유리하다&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;</description>
      <author>기기디</author>
      <guid isPermaLink="true">https://kimdeveloper.tistory.com/59</guid>
      <comments>https://kimdeveloper.tistory.com/59#entry59comment</comments>
      <pubDate>Thu, 15 Feb 2024 23:55:53 +0900</pubDate>
    </item>
    <item>
      <title>Spring과 Spring Boot의 차이점</title>
      <link>https://kimdeveloper.tistory.com/58</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;어렴풋이 대충 알고 있던 내용을 정리해본다&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;공통점&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Spring 생태계 기반 자바 프레임 워크&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Spring&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개발자가 직접 설정파일을 작성해야 하는 부분의 리소스가 크다. 모든 빈 객체 등록, 객체 간 의존성 설정, 컴포넌트 구성을 해야함&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;별도로 was를 설치하고 설정하는것이 필요&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;배포시 war파일을 생성해서 Tomcat에 배포해야함&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Spring Boot&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;간결한 설정 &amp;amp; 자동 구성&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;보일러 플레이트 코드 최소화 - 보편적으로 많이 사용되는 트랜잭션 매니저, JDBC Template등을 기본적으로 Bean으로 등록되어있음&lt;/li&gt;
&lt;li&gt;XML 설정 불필요&lt;/li&gt;
&lt;li&gt;어노테이션을 통해 컴포넌트들을 스캔하여 자동으로 Bean에 등록(@Component, @Controller, @Service&amp;hellip;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;의존성 &amp;amp; 버전 관리 간소화&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Starter를 통한 dependency 자동화&lt;/li&gt;
&lt;li&gt;버전를 권장버전으로 자동 설정&lt;/li&gt;
&lt;li&gt;예시 - 만약 test프레임워크가 필요하다면 pom.xml이나 build.gradle에 'spring-boot-starter-test'만 추가해주면 필요한 dependency를(junit, mockito&amp;hellip;) 자동으로 추가하고 관리해준다. ( JPA의 경우 JDBC, HikariCP&amp;hellip;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;배포 편의성&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;프레임워크 단에서 tomcat 내장 서버 제공을 통하여 jar파일만으로도 배포 가능&lt;/li&gt;
&lt;/ul&gt;</description>
      <author>기기디</author>
      <guid isPermaLink="true">https://kimdeveloper.tistory.com/58</guid>
      <comments>https://kimdeveloper.tistory.com/58#entry58comment</comments>
      <pubDate>Wed, 14 Feb 2024 13:00:41 +0900</pubDate>
    </item>
    <item>
      <title>Effective Java 정리 #1</title>
      <link>https://kimdeveloper.tistory.com/56</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;이펙티브 자바 3판 2장에 해당하는 아이템중 스스로 정리가 필요하다고 생각되는 내용들을 정리했다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;아이템 1 생성자 대신 정적 팩토리 메소드를 고려하라&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클래스의 인스턴스를 얻는 수단은 public 생성자가 있지만 그 외에 정적 팩토리 메소드를 제공하는 방법이 존재한다. 클래스의 인스턴스를 반환하는 단순한 정적 메소드를 이야기한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;장점&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;정적 팩토리 메소드를 사용하는 경우 이름을 지을 수 있다.
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;반환될 객체의 특성을 이름에서 나타내는것이 가능하여 가독성을 높인다&lt;/li&gt;
&lt;li&gt;자바에서 하나의 시그니쳐로는 생성자를 하나만 만들 수 있다. 임시방편으로 전달하는 파라미터의 순서를 변경하는 방법으로 이 제한을 회피할 수 있지만 좋은 방법은 아니다. 파라미터의 순서로는 각 생성자의 역할을 나타내기 충분하지 않다.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;호출될때 마다 인스턴스를 새롭게 생성하지 않아도 된다.
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;호출시 불필요한 인스턴스 생성을 만들지 않아 생성 비용이 큰 객체의 경우 성능을 끌어올리는데 도움이 된다.&lt;/li&gt;
&lt;li&gt;인스턴스 통제 클래스 - 정적 팩토리 방식의 클래스는 자기 자신의 인스턴스를 완전히 통제하는것이 가능하다. 인스턴스를 통제하면 클래스를 싱글톤으로 만들수도 인스턴스화 불가로 만들수도 있다. 인스턴스 통제는 플라이웨이트 패턴의 근간이 된다.&lt;/li&gt;
&lt;li&gt;열거 타입은 인스턴스가 하나만 만들어짐을 보장한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;반환 타입의 하위 타입 객체를 반환할 수 있는 능력이 있다.
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;반환할 객체의 클래스를 자유롭게 선택할 수 있게하는 유연성을 제공한다.&lt;/li&gt;
&lt;li&gt;구현 클래스를 공개하지 않고 해당 객체를 반환할 수 있어 API를 작게 유지할 수 있다.&lt;/li&gt;
&lt;li&gt;자바8을 기준으로 인터페이스도 정적메소드를 가질 수 있게 됐다.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;입력 매개변수에 따라 매번 다른 클래스의 객체를 반환할 수 있다
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;반환 타입의 하위 타입 범위 안에서는 어떤 클래스의 객체를 반환하든 상관 없다.&lt;/li&gt;
&lt;li&gt;예시로 EnumSet 클래스는 public 생성자 없이 정적 팩토리만 제공한다. 원소의 길이에 따라서 64개 이하라면 Long변수 하나로 관리하는 RegularEnumSet의 인스턴스 / 65개 이상이라면 long배열로 관리하는 JumboEnumSet의 인스턴스를 반환한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;정적 팩토리 메소드를 작성하는 시점에는 반환할 객체의 클래스가 존재하지 않아도 된다.
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;이 특징은 프레임워크를 만들때의 유연함을 얻는다.&lt;/li&gt;
&lt;li&gt;서비스 제공자 프레임워크 패턴&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;단점&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;상속을 하려면 public, protected 생성자가 필요하니 정적 팩토리 메소드만 제공하면 하위 클래스를 만들 수 없다.
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;해당 제약은 상속보다는 컴포지션을 사용하도록 유도하고 불변타입으로 만드려면 이 제약을 지켜야한다는 점에서 오히려 장점이 되기도 한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;정적 팩토리 메소드는 다른 개발자가 봤을때 찾기 어렵다.&lt;/li&gt;
&lt;/ol&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;정적 팩토리 메소드와 public 생성자는 각각 사용할 용도가 다르니 각자의 장단점을 이해하고 사용하는게 좋다. 하지만 대부분의 경우 정적 팩토리 메소드를 쓰는게 유리한 경우가 많기 때문에 무조건 public 생성자를 제공하던 습관이 있다면 고치는게 좋다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;아이템 5 자원을 직접 명시하지 말고 의존 객체 주입을 사용하라&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대부분의 클래스는 제대로 동작하기 위하여 하나 이상의 자원에 의존해야한다. 맞춤법 검사기라는 클래스가 있다면 사전에 의존해야하는게 예시다. 이런 클래스를 정적 유틸리티 클래스로 구현하는 경우 유연하지 않고 테스트 하기 어렵다는 단점을 가진다. 사전을 언어별로 사용할수도 있고 특수 어휘용 사전을 따로 쓸수도 있고 테스트용 사전을 쓸수도 있기 때문에 단 하나의 사전만을 가지는건 유연하지 못하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대신 클래스(맞춤법 검사기)가 여러 자원을 사용해야하고 클라이언트의 요구사항에 따라 사용해야하는 자원이 달라져야한다면, 인스턴스를 생성할때 생성자에 필요한 자원을 넘겨주는 방식으로 구현할 수 있다. 이 방식은 의존 객체 주입의 형태중 하나로 맞춤법 검사기를 생성할 때 의존객체인 사전을 주입해주면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 패턴의 변형으로 생성자에 자원 팩토리를 넘겨주는 방식을 사용할 수 있다. 여기서 말하는 팩토리란 호출할때마다 특정 타입의 인스턴스를 반복해서 만들어주는 객체를 말한다. 이 변형은 팩토리 메소드 패턴 이라고도 불린다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;정리&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;클래스가 하나 이상의 자원에 의존성을 가지고 그 자원에 따라서 클래스의 동작이 달라져야한다면 싱글턴과 정적 유틸리티 클래스를 사용하지 않는것이 좋다.&lt;/li&gt;
&lt;li&gt;자원으로 인해서 매번 새로운 클래스를 만들지 않게 하는것이 좋다. 필요한 자원을 생성자에 넘겨주자. 이 기법을 의존 객체 주입이라고도 부른다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;아이템 9 try-finally보다는 try-with-resources를 사용하라&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자바에서는 close메소드로 직접 닫아줘야하는 자원들이 존재한다. 놓치는 경우 성능 문제로 이어지기에 안전하게 사용하기 위하여 try-finally가 전통적으로 쓰였다. 하지만 try-finally는 자원이 둘 이상이라면 중첩구문을 유발하여 가독성이 떨어지고 특정 자원의 예외 발생시 스택 추적 내역에 다른 자원의 정보를 집어삼키는 경우도 발생한다. 이런 경우 디버깅을 어렵게 만든다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러한 문제들을 try-with-resorces를 통해 해결할 수 있다. 사용하기 위하여 AutoCloseable 인터페이스를 구현해야한다. tru-with-resources를 사용하며 가독성을 높일 수 있고 하나의 예외만 보여지고 숨겨지는 나머지 예외들은 콘솔창에서 suppressed를 달고 출력되어 다른 스택 내역을 덮어쓰지않고 디버깅하기 수월하다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;정리&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;꼭 close를 통해서 닫아줘야하는 자원을 다룰때는 try-finally말고 try-with-resources를 사용하자.&lt;/p&gt;</description>
      <category>Java</category>
      <author>기기디</author>
      <guid isPermaLink="true">https://kimdeveloper.tistory.com/56</guid>
      <comments>https://kimdeveloper.tistory.com/56#entry56comment</comments>
      <pubDate>Sun, 10 Dec 2023 07:29:47 +0900</pubDate>
    </item>
    <item>
      <title>이펙티브 파이썬 2nd 정리 #5</title>
      <link>https://kimdeveloper.tistory.com/55</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;38. 간단한 인터페이스의 경우 클래스 대신 함수를 받아라&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;요약&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;간단한 인터페이스가 필요할때는 클래스를 만들고 인스턴스로 생성해서 쓰는 대신 간단하게 함수를 활용할 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;상세&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;defaultdict는 없는 키로 접근하는 상황에서 호출할 함수를 넘겨 받습니다.&lt;/p&gt;
&lt;pre class=&quot;python&quot;&gt;&lt;code&gt;def log_missing():
    print('Key added')
    return 0

# 특정상황에서 넘겨 준 log_missing함수를 실행
# 인자로 받는 함수를 훅이라고 함
current = {'green': 12, 'blue': 3}
increments = [
    ('red', 5),
    ('blue', 17),
    ('orange', 9),
]
for key, amount in increments:
    result[key] += amount
print('After: ', dict(result))

# result
Before: {'green': 12, 'blue': 3}
Key added
Key added
After:  {'green': 12, 'blue': 20, 'red': 5, 'orange': 9}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와 같이 구현하는 경우 정해진 동작과 사이드 이펙트를 분리할 수 있기 때문에 API를 더 쉽게 만들 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;작은 클래스를 만들어 해결하는 방법도 있지만, 클래스만 보면 CountMissing 클래스의 목적이 무엇인지 확실하게 알기 어렵다. 누가 CountMissing의 인스턴스를 만들지, 누가 missing 메소드를 호출할지, 어떤 메소드가 더 추가될지 등등 DeafultDict와 함께 사용되는 예제를 보기 전에는 클래스를 정확하게 파악하기 어려울 수 있다.&lt;/p&gt;
&lt;pre class=&quot;ruby&quot;&gt;&lt;code&gt;class CountMissing:
		def __init__(self):
				self.added = 0

		def missing(self):
				self.added += 1
				return 0

counter = CountMissing()
for key. amount in increments:
		result[key] += amount
assert count.added == 2
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 경우에는 __call__메소드를 정의하여 사용할 수 있습니다. 객체를 함수처럼 호출할 수 있게 만들어줍니다. __call__이 정의된 클래스의 인스턴스에 대해 callable 내장 함수를 호출하면 다른 메소드와 같이 True가 반환됩니다. 이런 식으로 정의되어 호출할 수 있는 모든 가능 객체를 호출 가능(callable) 객체라고 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래는 존재하지 않는 키에 접근한 횟수를 세고 싶은 상황 가정했을때의 예시 코드입니다. 호출 가능(callable) 객체를 사용한 예제입니다.&lt;/p&gt;
&lt;pre class=&quot;ruby&quot;&gt;&lt;code&gt;class BetterCountMissing:
    def __init__(self):
        self.added = 0

    def __call__(self):# 호출 가능 객체
				self.added += 1
        return 0

current = {'green': 12, 'blue': 3}
increments = [
    ('red', 5),
    ('blue', 17),
    ('orange', 9),
]

# Example 9
counter = BetterCountMissing()
result = defaultdict(counter, current) # __call__에 의존
for key, amount in increments:
    result[key] += amount

print(counter.added)# 2
print(dict(result)) # {'green': 12, 'blue': 20, 'red': 5, 'orange': 9}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;__call__을 활용한 방식은 함수가 인자로 쓰일 수 있는 부분에 이 클래스의 인스턴를 사용할 수 있다는 사실을 보여줄 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결론&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;파이썬의 여러 컴포넌트 사이에 간단한 인터페이스가 필요할 때는 클래스를 정의하고 인스턴스화하는 대신 간단히 함수를 사용할 수 있다.&lt;/li&gt;
&lt;li&gt;파이썬 함수나 메서드는 일급 시민이다. 따라서 (다른 타입의 값과 마찬가지로) 함수나 함수 참조를 식에 사용할 수 있다.&lt;/li&gt;
&lt;li&gt;특별 메서드를 사용하면 클래스의 인스턴스 객체를 일반 파이썬 함수처럼 호출할 수 있다.&lt;/li&gt;
&lt;li&gt;상태를 유지하기 위한 함수가 필요한 경우에는 상태가 있는 클로저를 정의하는 대신&amp;nbsp;__call__&amp;nbsp;메서드가 있는 클래스를 정의할지 고려해보라.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;39. &lt;b&gt;&lt;b&gt;객체를 제너릭하게 구성하려면 @classmethod를 통한 다형성을 활용하라&lt;/b&gt;&lt;/b&gt;&lt;/h3&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;@classmethod&amp;nbsp;를 사용해서 하위 클래스를 같은 방식으로 사용할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;상세&lt;/h3&gt;
&lt;pre class=&quot;ruby&quot;&gt;&lt;code&gt;class GenericInputData:
    def read(self):
        raise NotImplementedError

    @classmethod # 클래스메서드로 표시
		def generate_inputs(cls, config):
        raise NotImplementedError

class PathInputData(GenericInputData):
    def __init__(self, i):
        super().__init__()
        self.path = f'temp_dir/{i}'

    def read(self):
        return self.path

    @classmethod
    def generate_inputs(cls, start):# 클래스를 인자로 받음
				for i in range(start, start + 5):
						yield cls(i) # 인자로 받은 클래스로 인스턴스 생성

# 부모 클래스(GenericInput)로 작성
def temp_generate_inputs(input_class, start):
    it = input_class.generate_inputs(start)
    return it

# 최초 사용 부분에서 자식 클래스 지정(PathInputData)
data = temp_generate_inputs(PathInputData, 3)
for x in data:# x는 PathInputData 객체
		print(x.read())

#print
temp_dir/3
temp_dir/4
temp_dir/5
temp_dir/6
temp_dir/7

&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정리&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;파이썬의 클래스에는 생성자가&amp;nbsp;&lt;b&gt;init&lt;/b&gt;&amp;nbsp;메서드 뿐이다.&lt;/li&gt;
&lt;li&gt;@classmethod를 사용하면 클래스에 다른 생성자를 정의할 수 있다.&lt;/li&gt;
&lt;li&gt;클래스 메서드 다형성을 활용하면 여러 구체적인 하위 클래스의 객체를 만들고 연결하는 제너릭한 방법을 제공할 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;41. 기능을 합성할때는 믹스인 클래스를 사용하라&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;파이썬은 다중 상속을 지원하지만 피하는 편이 좋습니다. 다이아몬드 문제, 코드의 복잡성이 증가하는게 그 이유가 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다중 상속이 제공하는 편의와 캡슐화가 필요하지만 다중 상속으로 인해 발생할 수 있는 골치아픈 경우는 피하고 싶다면 mix-in을 사용해보는걸 고려할 수 있습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;믹스인 클래스 : 자식 클래스가 사용할 메소드 몇개만 정의하는 클래스입니다. 믹스인 클래스에는 따로 attribute정의가 없고 믹스인 클래스의 __init__메소드를 호출할 필요 없이 기능만 정의 할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;공통으로 사용될 기능을 믹스인 안에 한번만 작성해두면 다른 여러 클래스에 적용할 수 있다는 뜻을 가집니다. 믹스인을 합성하거나 계층화해서 반복적인 코드를 최소화하고 재사용성을 극대화 할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래 코드는 공개메소드를 사용해 정의한 믹스인의 예제로 이 믹스인을 상속하는 모든 클래스에서 이 함수의 기능을 사용할 수 있습니다.&lt;/p&gt;
&lt;pre class=&quot;python&quot;&gt;&lt;code&gt;class ToDictMixin:
    def to_dict(self):# 믹스인을 상속하는 모든 클래스에서 이 함수의 기능을 사용할 수 있음
				return self._traverse_dict(self.__dict__)# __dict__ : 인스턴스가 갖는 애트리뷰트들의 dict

		def _traverse_dict(self, instance_dict):
        output = {}
        for key, value in instance_dict.items():
            output[key] = self._traverse(key, value)
        return output

    def _traverse(self, key, value):
        if isinstance(value, ToDictMixin):
            return value.to_dict()
        elif isinstance(value, dict):
            return self._traverse_dict(value)
        elif isinstance(value, list):
            return [self._traverse(key, i) for i in value]
        elif hasattr(value, '__dict__'):
            return self._traverse_dict(value.__dict__)
        else:
            return value

# Example 3
class BinaryTree(ToDictMixin):
    def __init__(self, value, left=None, right=None):
        self.value = value
        self.left = left
        self.right = right

# 이해를 돕기 위해
temp_node1 = BinaryTree(5, None, None)
print(temp_node1.__dict__)# {'value': 5, 'left': None, 'right': None}

# 이해를 돕기 위해
temp_node2 = BinaryTree(3, temp_node1, None)
print(temp_node2.__dict__)# {'value': 3, 'left': &amp;lt;__main__.BinaryTree object at 0x000002A5DA1D9730&amp;gt;, 'right': None}

# Example 4
tree = BinaryTree(10,
                  left=BinaryTree(7, right=BinaryTree(9)),
                  right=BinaryTree(13, left=BinaryTree(11)))
pprint.pprint(tree.to_dict())

# print
{'left': {'left': None,
          'right': {'left': None, 'right': None, 'value': 9},
          'value': 7},
 'right': {'left': {'left': None, 'right': None, 'value': 11},
           'right': None,
           'value': 13},
 'value': 10}

&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정리&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;믹스인을 사용해 구현할 수 있는 기능을 인스턴스 애트리뷰트와&amp;nbsp;__init__을 사용하는 다중 상속을 통해 구현하지 말라.&lt;/li&gt;
&lt;li&gt;믹스인 클래스가 클래스별로 특화된 기능을 필요로 한다면 인스턴스 수준에서 끼워 넣을 수 있는 기능(정해진 메서드를 통해 해당 기능을 인스턴스가 제공하게 만듦)을 활용하라.&lt;/li&gt;
&lt;li&gt;믹스인에는 필요에 따라 인스턴스 메서드는 물론 클래스 메서드도 포함될 수 있다.&lt;/li&gt;
&lt;li&gt;믹스인을 합성하면 단순한 동작으로부터 더 복잡한 기능을 만들어낼 수 있다.&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>python</category>
      <author>기기디</author>
      <guid isPermaLink="true">https://kimdeveloper.tistory.com/55</guid>
      <comments>https://kimdeveloper.tistory.com/55#entry55comment</comments>
      <pubDate>Fri, 8 Sep 2023 15:50:14 +0900</pubDate>
    </item>
  </channel>
</rss>