<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ko"><generator uri="https://jekyllrb.com/" version="3.9.0">Jekyll</generator><link href="https://hwangtoemat.github.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://hwangtoemat.github.io/" rel="alternate" type="text/html" hreflang="ko" /><updated>2021-07-20T16:09:27+00:00</updated><id>https://hwangtoemat.github.io/feed.xml</id><title type="html">황토매트 연구소</title><subtitle>재밋는거 하고싶은 개발자의 블로그
</subtitle><author><name>Taeho Kim</name><email>taeho.kim20@snowcorp.com</email></author><entry><title type="html">[이펙티브자바] 3장. 모든 객체의 공통 메서드</title><link href="https://hwangtoemat.github.io/computer-science/2021-07-20-javaitem02/" rel="alternate" type="text/html" title="[이펙티브자바] 3장. 모든 객체의 공통 메서드" /><published>2021-07-20T00:00:00+00:00</published><updated>2021-07-20T00:00:00+00:00</updated><id>https://hwangtoemat.github.io/computer-science/javaitem02</id><content type="html" xml:base="https://hwangtoemat.github.io/computer-science/2021-07-20-javaitem02/">&lt;h3 id=&quot;item-10-equals는-일반-규약을-지켜-재정의하라&quot;&gt;Item 10. equals는 일반 규약을 지켜 재정의하라&lt;/h3&gt;

&lt;p&gt;equals 메서드를 재정의 하기 위해서는 고려해야 할 점들이 많다.
아래의 경우에 해당한다면 재정의 하지 않는 것이 좋다&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;각 인스턴스가 본질적으로 고유하다&lt;/li&gt;
  &lt;li&gt;논리적 동시성을 검사할 일이 없다.&lt;/li&gt;
  &lt;li&gt;상위클래스에서 정의한 equals가 하위클래스에서도 잘 동작한다.&lt;/li&gt;
  &lt;li&gt;클래스가 private, package-private이고 equals메서드를 호출할 일이 없다.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;하지만 위의 경우에 해당하지 않고 재정의가 필요할 경우(논리적 동치성을 확인해야 하는 경우) 
&lt;strong&gt;null이 아닌 모든 참조값 x,y,z에 대해 반드시 아래의 일반규약을 따라야한다.&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;반사성 (x.equals(x) 는 true)&lt;/li&gt;
  &lt;li&gt;대칭성 (x.equals(y) 는 true -&amp;gt; y.equals(x) 는 true)&lt;/li&gt;
  &lt;li&gt;추이성 (x.equals(y) 는 true &amp;amp;&amp;amp; y.equals(z) 는 true -&amp;gt; x.equals(z) 는 true)&lt;/li&gt;
  &lt;li&gt;일관성 (x.equals(x) 는 true 일때 반복해서 호출해도 같은 값이 나온다.)&lt;/li&gt;
  &lt;li&gt;null-아님 (x.equals(null) 은 false)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;양질의 equals 메서드를 구현하는 방법은 아래와 같다.&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;== 연산자를 사용해 자기 자신의 참조인지 확인한다.
    &lt;ul&gt;
      &lt;li&gt;단순한 성능최적화용으로 작업이 복잡할때 주로 사용된다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;instanceof 연산자로 입력이 올바른 타입인지 확인한다.&lt;/li&gt;
  &lt;li&gt;입력을 올바른 타입으로 형변환한다.&lt;/li&gt;
  &lt;li&gt;입력 객체와 자기 자신의 대응되는 핵심 필드들이 모두 일치하는지 하나씩 검사한다.&lt;/li&gt;
  &lt;li&gt;equals를 재정의 할땐 반드시 hashcode도 재정의하자&lt;/li&gt;
  &lt;li&gt;Object 외의 타입을 매개변수로 받는 equals 는 선언하지 말자&lt;/li&gt;
  &lt;li&gt;AutoValue 프레임 워크를 사용하면 간편하게 테스트 할 수 있다.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;item-11-equals를-재정의-하려거든-hashcode도-재정의하라&quot;&gt;Item 11. equals를 재정의 하려거든 hashCode도 재정의하라&lt;/h3&gt;

&lt;p&gt;equals를 재정의한 클래스 모두에서 hashCode도 재정의해야 한다. 
그렇지 않으면 &lt;strong&gt;hashCode 일반 규약을 어기게 되어&lt;/strong&gt; 해당 클래스의 인스턴스를 컬렉션 원소로 사용할때 문제가 발생한다.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;equals 비교에 사용되는 정보가 변경되지 않았다면, 애플리케이션이 실행되는 동안 그 객체의 hashCode 는 몇번을 호출해도 일관되게 항상 같은 값을 반환해야 한다.&lt;/li&gt;
  &lt;li&gt;equals가 두 객체를 같다고 판단했다면 hashCode는 똑같은 값을 반환해야 한다.&lt;/li&gt;
  &lt;li&gt;equals가 두 객체를 다르다고 판단했더라도 두 객체의 hashCode는 서로 다를필요는 없다.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;일반적으로 hashCode의 재정의를 잘못했을때 문제되는 조항은 2번이다. &lt;strong&gt;논리적으로 같은 객체는 같은 해시코드를 반환해야한다.&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nc&quot;&gt;Map&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;PhoneNumber&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;HashMap&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;gt;();&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;put&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;PhoneNumber&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;707&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;867&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5309&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;제니&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;위와 같이 정의된 HashMap에서&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;PhoneNumber&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;707&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;867&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5309&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;을 하더라도 “제니” 라는 값은 나오지 않는다.(null이 나옴)&lt;/p&gt;

&lt;p&gt;논리적 동치성을 갖는 두 new PhoneNumber(707,867,5309) 를 사용하였지만, 
적절한 hashCode 재정의를 해주지 않았기때문에 각각의 hashCode가 달랐기 때문이다.&lt;/p&gt;

&lt;p&gt;좋은 해시 함수라면 서로 다른 인스턴스에 다른 해시코드를 반환한다. 이것을 완벽하게 실행하기는 어렵지만 비슷하게는 구현할 수 있다.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;int 변수 reuslt 를 선언한 후 값 c로 초기화한다. 이때 c는 해당 객체의 첫 번째 핵심필드를 2.a 방식으로 계산한 해시코드이다.(핵심 필드는 equals 비교에 사용되는 필드)&lt;/li&gt;
  &lt;li&gt;나머지 핵심 필드에도 다음의 작업을 진행한다.
 a. 해당 필드의 해시코드 c를 계산한다.
         a.1. 기본 타입 필드라면, Type.hashCode(f)를 수행한다.
         a.2. 참조 타입 필드면서 이 클래스의 equals 가 이 필드의 equals를 재귀적으로 호출한다면, 이 필드의 hashCode를 재귀적으로 호출한다.
         a.3. 필드가 배열이라면, 핵심 원소 각각을 별도 필드처럼 다룬다. 이상의 규칙을 재귀적으로 적용해 각 핵심 원소의 해시코드를 계산한 다음 2.b 방식으로 갱신한다.
 b. 2.a에서 계산한 해시코드 c로 result를 갱신한다. (result = 31 * result + c;)&lt;/li&gt;
  &lt;li&gt;result 반환&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;hashCode 재정의를 완료했다면 앞선 3가지 규칙에 부합한지 테스트해본다.
파생필드(다른필드로 부터 계산해 낼 수 있는)는 제외해도 된다.
또한, &lt;strong&gt;equals 비교에 사용되지 않는 필드는 반드시 제외해야 한다.&lt;/strong&gt;
반대로 &lt;strong&gt;핵심필드를 생략해서는 안된다.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;위의 방법을 적용하여 PhoneNumber 클래스에 적절한 hashCode를 아래와 같이 재정의 해줄 수 있다.&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nd&quot;&gt;@Override&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;hashCode&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Short&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;hashCode&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;areaCode&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;31&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Short&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;hashCode&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;prefix&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;31&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Short&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;hashCode&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lineNum&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;이외에도 com.google.common.hash.Hashing 를 쓰거나 Object.hash를 사용하여 쉽게 구현할 수 있지만 성능이 아쉬운 부분이 있다.&lt;/p&gt;

&lt;p&gt;그리고 클래스가 불변이고 해시코드를 계산하는 비용이 크다면, 매번 계산하기보다는 캐싱을 사용하는 방법도 있다.&lt;/p&gt;

&lt;h3 id=&quot;item-12-tostring을-항상-재정의하라&quot;&gt;Item 12. toString을 항상 재정의하라&lt;/h3&gt;

&lt;p&gt;Object의 기본 toString 메서드는 우리가 작성한 클래스에서 적절한 정보를 반환해주지 못한다.(클래스이름@16진수해시코드 정도의 형태를 반환한다.)&lt;/p&gt;

&lt;p&gt;따라서 toString의 규약에도 ‘모든 하위 클래스에서 이 메서드를 재정의하라’ 라고 나와있다.
toString의 재정의를 통해 사용하기에 편하고 디버깅이 쉬워지며, 의미있는 로그를 남길 수 있다.&lt;/p&gt;

&lt;p&gt;실제로 우리가 직접 toString을 사용하지 않더라도 다양한 경우에서 toString이 사용된다.
특히, 우리가 작성한 객체를 참조하는 컴포넌트가 toString을 통해 로그를 남길때 toString이 적절하게 재정의 되어있다면,
의미있는 로그를 남길 수 있을 것이다.&lt;/p&gt;

&lt;p&gt;이때 toString의 효과적인 재정의를 위해서는 다음과 같은 조건이 필요하다.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;toString은 그 객체가 가진 주요정보 모두를 반환하는게 좋다.(단, 객체가 거대하거나 문자열로 표현하기 어렵다면 요약정보를 담아야한다.&lt;/li&gt;
  &lt;li&gt;toString의 반한 포맷을 문서화 하면, 표준적이고, 명확하게 재정의 할 수 있다.&lt;/li&gt;
  &lt;li&gt;포맷을 명시하든 아니든 의도는 명확히 밝혀야 한다.&lt;/li&gt;
  &lt;li&gt;toString이 반환한 값에 포함된 정보를 얻어올 수 있는 api를 제공하자.(toString의 값을 매번 파싱해서 쓸 수는 없으니 각각 요소를 따로 가져올 수 있도록 api 제공)&lt;/li&gt;
  &lt;li&gt;AutoValue 프레임워크를 사용하면 자동으로 toString을 재정의해주지만, 완벽하게 의미와 개발자의 의도를 파악하지는 못하므로 필요시 수정해야한다.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;item-13-clone-재정의는-주의해서-진행해라&quot;&gt;Item 13. clone 재정의는 주의해서 진행해라&lt;/h3&gt;

&lt;p&gt;Cloneable 은 복제해도 되는 클래스 임을 명시하는 용도의 인터페이스이지만, clone 메서드가 선언된 곳이 Object이고, protected로 선언되어 있기때문에 항상 성공적으로 clone이 되는것은 아니다.
Cloneable 은 protected로 선언된 clone의 동작방식을 결정하는 역할을 한다. Cloneable 구현체 인스턴스에서 clone() 호출 시 그 객체의 필드들을 하나하나 복사한 객체를 반환하고, Cloneable 구현체가 아닌 경우 CloneNotSupportedException을 던진다.&lt;/p&gt;

&lt;p&gt;Cloneable 을 통해 clone이 이루어지기위해서는 복잡하고, 허술하게 기술된 아래와 같은 프로토콜을 지켜야 한다.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;x.clone() != x&lt;/li&gt;
  &lt;li&gt;x.clone().getClass() == x.getClass()&lt;/li&gt;
  &lt;li&gt;x.clone().equals(x)&lt;/li&gt;
  &lt;li&gt;관례상, 이 메서드가 반환하는 객체는 super.clone을 호출해 얻어야 한다&lt;/li&gt;
  &lt;li&gt;관례상, 반환된 객체와 원본 객체는 독립적이어야 한다.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;위와 같은 요구조건들은 반드시 만족되어야 하는것은 아니기 때문에 그 과정이 깨지기 쉽고, 위험하고, 모순적인 매커니즘이 생성되게 된다.&lt;/p&gt;

&lt;p&gt;예를들어,
클래스 B가 클래스 A를 상속할때 하위 클래스인 B의 clone은 B타입 객체를 반환해야 한다.
하지만 A의 clone이 자신의 생성자(new A())로 생성된 객체를 반환한다면, B의 clone 도 A타입 객체를 반환할 수 밖에 없다.
즉, super.clone을 연쇄적으로 호출하게 두면 상위에서 clone이 처음 호출된 상위클래스의 객체가 만들어지게 된다.&lt;/p&gt;

&lt;p&gt;Clonable을 구현한 모든 클래스는 clone을 재정의 해야 한다.
이때 접근 제한자는 public으로 반환타입은 클래스 자신으로 변경한다.&lt;/p&gt;

&lt;p&gt;그외의 방법으로는 복사 생성자와 복사 팩터리 라는 방식이 존재한다.&lt;/p&gt;
&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Yum&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Yum&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;yum&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{...};&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 복사 생성자&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Yum&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;newInstance&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Yum&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;yum&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{...};&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;복사&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;팩터리&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;두 가지 방법은 Clonable/clone 보다 나은면이 많다.
앞서 설명한 위험천만한 객체 생성 메커니즘을 사용하지 않고 엉성한 규양에 기대지 않으며, 불필요한 검사 예외(CloneNotSupportedException)를 던지지도 않고 형변환도 필요없다.
또한, 원본의 구현타입에 얽매이지 않고 복제본의 타입을 직접 선택할 수 있다.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;요약
  Clonable/clone 응 다양한 위험요소가 많기때문에 드물게 사용하는 것이 좋다. 그보다는 생성자와 팩터리를 이용하는것이 좋으며, clone 메서드는 배열에서만 사용하는 것이 좋다.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;item-14-comparable을-구현할지-고려하라&quot;&gt;Item 14. Comparable을 구현할지 고려하라&lt;/h3&gt;

&lt;p&gt;compareTo는 Object의 메서드가 아닌 Comparable 인터페이스의 유일무이한 메서드이다.
compareTo는  equals 처럼 두 객체를 비교하는데 쓰이는데 차이점은 다음과 같다.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;단순 동치성 비교에 더해 순서까지 비교할 수 있다.&lt;/li&gt;
  &lt;li&gt;제네릭하다.&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
  &lt;li&gt;Comparable 을 구현했다는 것은
    &lt;ul&gt;
      &lt;li&gt;그 클래스의 인스턴스에는 자연적인 순서가 있다는 것을 의미하며, 그렇기 때문에 손쉽게 정렬할 수 있다.(Arrays.sort(a))&lt;/li&gt;
      &lt;li&gt;그뿐 아니라 검색, 극단값 계산, 자동정렬되는 컬렉션 관리도 쉽게 할 수 있다. (즉, 제너릭 알고리즘과 컬렉션을 다루기 편리해진다.)&lt;/li&gt;
    &lt;/ul&gt;

    &lt;p&gt;이러한 이점들이 있기때문에 사실상 자바 플랫폼 라이브러리의 모든 값 클래스와 열거타입이 Comparable을 구현했다.
  따라서, 알파벳, 숫자, 연대 같이 순서가 명확한 값 클래스를 작성한다면 반드시 Comparable 인터페이스를 구현하자&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;compareTo 메서드의 일반 규약은 equals의 규약과 비슷하다.
차이점이 있다면 모든 객체에 대해 전역 동치관계를 부여하는 equals 메서드와 달리, compareTo는 타입이 다른 객체를 신경쓰지 않아도 된다.(타입이 다른 객체가 주어지면 간단히 ClassCastException을 던져도 된다.)
물론 비교가 불가능 한 것은 아니고, 객체들이 구현한 공통 인터페이스를 통해 비교가 이루어지기도 한다.
또한, compareTo의 일반 규약을 지키지 못하면 비교를 활용하는 클래스와 어울리지 못한다.(TreeSet, TreeMap, Collections, Arrays 와 같이 검색과 정렬 알고리즘을 활용하는 클래스)&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;compareTo의 일반 규약을 살펴보면&lt;/p&gt;

    &lt;ol&gt;
      &lt;li&gt;두 객체 참조의 순서를 바꿔비교해도 예상한 결과가 나와야한다.&lt;/li&gt;
      &lt;li&gt;첫번째가 두번째 보다 크고, 두번째가 세번째 보다 크면 첫번째는 세번째보다 커야한다.&lt;/li&gt;
      &lt;li&gt;크기가 같은 객체들끼리는 어떤 객체와 비교하더라도 항상 같아야한다.&lt;/li&gt;
    &lt;/ol&gt;

    &lt;p&gt;즉, 앞서 살펴본 equals의 규약과 같이 반사성, 대칭성, 추이성을 충족해야한다.&lt;/p&gt;

    &lt;p&gt;이때, Comparable을 구현한 클래스를 확장하여 새로운 값 컴포넌트를 추가하고 싶다면,(compartTo 규약을 지키면서)
  독립된 클래스를 만들어 원래 인스턴스를 가르키는 필드를 두고, 내부 인스턴스를 반환하는 ‘뷰’메서드를 제공하면 된다.&lt;/p&gt;

    &lt;p&gt;3번 규약은 필수는 아니지만 지켜지기를 권장한다. 3번 규약은 compareTo 메서드로 수행한 동치성 테스트의 결과가 equals와 같아야 한다는 것이다.
  이를 지키게 되면 &lt;strong&gt;compareTo로 줄지은 순서와 equals의 결과가 일관&lt;/strong&gt;되게 된다.&lt;/p&gt;

    &lt;p&gt;만약 두 메서드의 결과가 다르다면 해당 클래스의 객체를 정렬된 컬렉션에 넣었을때, 해당 컬렉션이 구현한 인터페이스의 동작에 좋지 않은 영향을 줄 수 있다.
  이 인터페이스들은 equals 메서드의 규약을 따르지만, &lt;strong&gt;정렬된 컬렉션들은 동치성을 비교할때 compareTo를 사용&lt;/strong&gt;하기 때문이다.&lt;/p&gt;

    &lt;p&gt;예를들어, HashSet에 new BigDecimal(“1.0”) 과 new BigDecimal(“1.00”)을 추가할 경우 equals를 통해 비교되기 때문에 2개의 원소가 생성되고.
  TreeSet(정렬된 컬렉션)을 사용하면 compareTo 메서드로 비교하기 때문에 1개의 원소를 갖게 된다.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;compareTo 메서드 작성 요령&lt;/p&gt;

    &lt;p&gt;타입을 인수로 받는 제네릭 인터페이스이므로 입력 인수의 타입을 확인하거나 형변환할 필요가 없다.( 잘못됐다면 컴파일이 되지 않는다.)
  관계 연산자 &amp;lt;, &amp;gt; 사용시 거추장스럽고 오류를 유발할 수 있으니 박싱된 기본 타입 클래스들의 compare 메서드 사용한다.
  핵심필드가 여러개라면 가장 중요한 필드부터 비교해 나간다.
  Comparable 하게 구현되지 않았다면 비교자를 대신 사용한다.
      - 자바 8에서부터는 연쇄방식으로 비교자를 생성할 수 있지만 성능저하가 뒤따른다…
      - 수많은 보조 생성 메서드들이 있다(comparingInt, thenComparingInt…)&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;</content><author><name>Taeho Kim</name><email>insu7942@naver.com</email></author><category term="Computer-Science" /><summary type="html">Item 10. equals는 일반 규약을 지켜 재정의하라</summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://github.com/HwangToeMat/HwangToeMat.github.io/blob/master/Computer-Science/image/effectiveJAVA/img.png?raw=true" /><media:content medium="image" url="https://github.com/HwangToeMat/HwangToeMat.github.io/blob/master/Computer-Science/image/effectiveJAVA/img.png?raw=true" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">[이펙티브자바] 2장. 객체 생성과 파괴</title><link href="https://hwangtoemat.github.io/computer-science/2021-07-10-javaitem01/" rel="alternate" type="text/html" title="[이펙티브자바] 2장. 객체 생성과 파괴" /><published>2021-07-10T00:00:00+00:00</published><updated>2021-07-10T00:00:00+00:00</updated><id>https://hwangtoemat.github.io/computer-science/javaitem01</id><content type="html" xml:base="https://hwangtoemat.github.io/computer-science/2021-07-10-javaitem01/">&lt;h3 id=&quot;item-1-생성자-대신-정적-팩터리-메서드를-고려하라&quot;&gt;Item 1. 생성자 대신 정적 팩터리 메서드를 고려하라&lt;/h3&gt;
&lt;p&gt;클래스의 인스턴스를 얻는 전통적인 수단인 public 생성자 이외에도 &lt;strong&gt;static factory method&lt;/strong&gt;를 통해 더 효율적으로 클래스를 제공할 수 도 있다.(장단점 존재)&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;장점
    &lt;ol&gt;
      &lt;li&gt;&lt;em&gt;이름을 가질 수 있다.&lt;/em&gt;
        &lt;ul&gt;
          &lt;li&gt;이름만 잘지으면 반환될 객체의 특성을 쉽게 묘사할 수 있다.&lt;/li&gt;
          &lt;li&gt;한 클래스에 시그니처가 같은 생성자가 여러개 필요할 것 같으면, 입력 매개변수의 순서를 바꾸기 보다는 정적 팩터리 메서드로 변경하고 차이가 드러나는 이름을 지어주자&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;호출될 때마다 인스턴스를 새로 생성하지는 않아도 된다.
        &lt;ul&gt;
          &lt;li&gt;같은 객체가 자주 요청되는 상황에서 성능을 끌어올려 준다.&lt;/li&gt;
          &lt;li&gt;&lt;em&gt;반복되는 요청에 같은 객체를 반환하는 식으로 정적 팩터리 방식의 클래스는 언제 어느 인스턴스를 살아있게 할지 통제할 수 있다.&lt;/em&gt;&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;반환 타입의 하위 타입 객체를 반환할 수 있는 능력이 있다.
        &lt;ul&gt;
          &lt;li&gt;반환할 객체의 클래스를 자유롭게 선택할 수 있게하는 유연성 제공(java.util.Collection 에서도 이를 통해 api를 작게 유지하고, 사용자가 편리하게 사용가능하다.)&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;입력 매개변수에 따라 매번 다른 클래스의 객체를 반환할 수 있다
        &lt;ul&gt;
          &lt;li&gt;반환 타입의 하위 타입이기만 하면 어떤 클래스의 객체를 반환하든 상관없다.(EnumSet 클래스의 경우 원소의 수에 따라 반환되는 인스턴스(하위 클래스의 인스턴스)가 다르다.)&lt;/li&gt;
          &lt;li&gt;사용자는 이를 알필요도 없고 그냥 사용하면 되고, 그렇기때문에 개발자는 상황에 맞게 하위클래스를 마음대로 변경 할 수 있다.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;정적 팩터리 메서드를 작성하는 시점에는 반환할 객체의 클래스가 존재하지 않아도 된다.
        &lt;ul&gt;
          &lt;li&gt;JDBC&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;단점
    &lt;ol&gt;
      &lt;li&gt;하위클래스를 만들 수 없다.
        &lt;ul&gt;
          &lt;li&gt;상속 불가&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;&lt;em&gt;프로그래머가 찾기 어렵다&lt;/em&gt;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;결론
    &lt;blockquote&gt;
      &lt;p&gt;정적팩터리 메서드와 public 생성자는 각자의 쓰임새가 있으니 장단점을 이해하고 각각 유리한 경우 선택적으로 사용해야한다.&lt;/p&gt;
    &lt;/blockquote&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;item-2-생성자에-매개변수가-많다면-빌더를-고려하라&quot;&gt;Item 2. 생성자에 매개변수가 많다면 빌더를 고려하라&lt;/h3&gt;
&lt;p&gt;선택적 매개변수가 많을 경우 생성자, 정적 팩터리를 사용하여 구현하면 어려움이 있을 수 있다.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;생성자 패턴의 경우 가독성이 떨어져, 잘못된 데이터 전달로 오류를 유발할 수 있다.&lt;/li&gt;
  &lt;li&gt;자바빈즈 패턴의 경우 불완전한 객체가 생성될 수 있어 에러를 유발할 수 있다&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;따라서 이럴경우 점층적 생성자 패턴의 안전성과 자바빈즈 패턴의 가독성을 겸비한 &lt;strong&gt;빌더패턴&lt;/strong&gt;을 사용하면 좋다.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;빌더패턴
    &lt;ul&gt;
      &lt;li&gt;클라이언트는 필요한 객체를 직접 만드는 대신, ‘필수 매개변수’만으로 생성자를 호출해 “빌더객체”를 얻는다.&lt;/li&gt;
      &lt;li&gt;“빌더객체”의 Setter 메서드를 사용하여 나머지 ‘선택 매개변수’를 입력하고 .build() 를 호출하여 필요한 객체를 얻는다.&lt;/li&gt;
      &lt;li&gt;이때 빌더객체의 Setter 메서드는 빌더 자신을 반환하기 때문에 연쇄적으로 호출(method chaining)할 수 있다.
        &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  User user1 = new User.Builder(SN10525, pw1234).email(taeho.kim20@snowcorp.com).gender(M).build(); 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;
      &lt;/li&gt;
      &lt;li&gt;계층적으로 설계된 클래스와 함께 쓰기에 좋다.(하위클래스의 메서드가 상위클래스에서 정의한 타입이 아닌 하위에서 정의한 타입을 반환(공변 반환 타이핑)할 수 있음)&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;단점
    &lt;ul&gt;
      &lt;li&gt;빌더가 생성되야하기 때문에 성능에 민감한 경우 문제가 될 수 있다.&lt;/li&gt;
      &lt;li&gt;코드 양이 늘기 때문에 매개변수가 많은 경우에만 사용하는것이 좋다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;결론
    &lt;blockquote&gt;
      &lt;p&gt;처리해야할 매개변수가 많다면 빌더패턴을 선택하는 것이 더 낫다.&lt;/p&gt;
    &lt;/blockquote&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;item-3-private-생성자나-열거-타입으로-싱글턴임을-보증하라&quot;&gt;Item 3. private 생성자나 열거 타입으로 싱글턴임을 보증하라&lt;/h3&gt;

&lt;p&gt;싱글턴이란 인스턴스를 오직 하나만 생성할 수 있는 클래스를 말한다. 설계상 유일해야 하는 시스템 컴포넌트와 같은 경우가 이에 해당한다.&lt;/p&gt;

&lt;p&gt;일반적으로 싱글턴을 구현하는 방법으로는&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;public static final 로 인스턴스를 바로 제공하는 방식&lt;/li&gt;
  &lt;li&gt;public static 메서드로 private static final 인스턴스를 제공하는 방식&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;이 일반적이다. 하지만 이 경우 리플랙션 공격에 취약하고, 직렬화과정에서 모든 인스턴스 필드를 transient라고 선언하고, readResolve 메서드를 제공하지 않으면 역직렬화시 제2의 인스턴스가 생길 위험이 있다.&lt;/p&gt;

&lt;p&gt;이러한 문제점이 발생하지 않는 방법으로는 원소가 하나인 열거타입을 선언하는 것이다.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;public enum Taeho {
    INSTANCE;
    
    public void leaveTheBuilding() {...}
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;이와 같은 방법으로 앞서 소개된 위험을 해결 할 수 있으며, 간결하게 작성할 수 있다.&lt;/p&gt;

&lt;p&gt;하지만 Enum 외의 클래스를 상속해야한다면 사용할 수 없다는 단점이 있다.&lt;/p&gt;

&lt;h3 id=&quot;item-4-인스턴스화를-막으려거든-private-생성자를-사용하라&quot;&gt;Item 4. 인스턴스화를 막으려거든 private 생성자를 사용하라&lt;/h3&gt;

&lt;p&gt;일반적으로 인스턴스 생성시 생성자를 명시하지 않으면 컴파일러가 자동으로 기본 생성자를 만들어준다.
따라서, 인스턴스화를 막고싶을 경우 private 생성자를 사용하면 클래스 바깥에서는 접근할 수 없게 된다.&lt;/p&gt;

&lt;h3 id=&quot;item-5-자원을-직접-명시하지-말고-의존-객체-주입을-사용하라&quot;&gt;Item 5. 자원을 직접 명시하지 말고 의존 객체 주입을 사용하라&lt;/h3&gt;

&lt;p&gt;클래스가 하나 이상의 자원에 의존하며 사용하는 자원에 따라 동작이 달라지는 경우 싱글톤(item3)이나 정적유틸리티(item4) 을 사용하는 것은 부적합하다.&lt;/p&gt;

&lt;p&gt;이런 경우 &lt;strong&gt;의존 객체 주입&lt;/strong&gt;을 사용해야한다. (인스턴스를 생성할 때 생성자에 필요한 자원을 넘겨주는 방식)&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;public class SpellChecker {
    private final Lexicon dictionary;
    
    public SpellChecker (Lexicon dictionary) {
        this.dictionary = Object.requireNonNull(dictionary)
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;item-6-불필요한-객체-생성을-피하라&quot;&gt;Item 6. 불필요한 객체 생성을 피하라&lt;/h3&gt;

&lt;p&gt;똑같은 기능의 객체를 매번 생성하기 보다는 객체 하나를 재사용하는 것이 좋을때가 많다.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;String s = new String(&quot;bikini&quot;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;위와 같이 “bikini” 자체가 String의 인스턴스인데 불필요하게 String 객체를 매번 재생성할 필요는 없다.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;private static long sum() {
    Long sum = 0L;
    for (long i = o; i&amp;lt;= Integer.MAX_VALUE; i++){ sum += i; }
    return sum;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;위의 경우 sum이 Long으로 i가 long선언되어 있기 때문에 둘을 더할때마다 오토박싱(자동 형변환)이 일어나 Long 객체가 불필요하게되고(불필요한 객체 생성) 이는 성능 저하를 야기한다.&lt;/p&gt;

&lt;p&gt;특히, ‘비싼 객체’의 반복적 생산은 지양하고 캐싱하여 재사용하는 편이 좋다.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;static boolean isRomanNumeral(String s) {
	return s.matches(&quot;^(?=.)M*(C[MD]|D?C{0,3})&quot;
		+ &quot;(X[CL]|L?X{0,3})(I[XV]|V?I{0,3})$&quot;);
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;위의 경우 정규식을 변환해주는 전 과정을 한번에 실행한다. 위의 코드가 반복적으로 실행될시 성능 저하가 일어날 수 있다.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;public class RomanNumerals {
	private static final Pattern ROMAN = Pattern.compile(
		&quot;^(?=.)M*(C[MD]|D?C{0,3})&quot;
		+ &quot;(X[CL]|L?X{0,3})(I[XV]|V?I{0,3})$&quot;);

	static boolean isRomanNumeral(String s) {
		return ROMAN.matcher(s).matches();
	}
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;하지만 위의 경우 String.matches 내부에서 사용되는 Pattern 인스턴스를 ROMAN으로 저장해 놓고, 재사용하여 Pattern 인스턴스의 재사용을 통해 성능을 개선할 수 있다.&lt;/p&gt;

&lt;h3 id=&quot;item-7-다-쓴-객체-참조를-해제하라&quot;&gt;Item 7. 다 쓴 객체 참조를 해제하라&lt;/h3&gt;

&lt;p&gt;자바는 가비지 컬렉터를 갖춘언어로 대부분의 경우 알아서 메모리를 관리해준다. 
하지만 그렇지 못한 예외의 경우에 발생할 수 있는 메모리 누수에 미리 대비할 필요가 있다.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;메모리를 직접 관리하는 경우
 프로그램상에서는 더 이상 쓰이지 않는 참조가 있다면 null을 주어 해제해야 한다.(null을 주면 잘못된 참조 사용시 NPE를 유발시켜 잘못된 로직을 미리 잡을 수 있다.)
 가비지 컬렉터는 객체 참조 하나를 상려두면 그 객체가 참조하는 모든 객체까지 회수 할 수 없기때문에 메모리 누수정도가 빠르게 늘어날 수 있다.&lt;/li&gt;
  &lt;li&gt;캐시를 사용하는 경우
 WeakHashMap을 사용하면 다 쓴 엔트리는 자동으로 삭제될 수 있다. 하지만 캐시 엔트리의 유효기간을 정의하기 어렵기 때문에 보통은 시간이 지날수록 가치를 떨어트리는 방식을 사용한다.&lt;/li&gt;
  &lt;li&gt;리스너와 콜백에서 명확히 해지하지 않는경우
 약한참조로 저장하면 명확히 해지하지 않아도 가비지컬렉터가 수거해 간다.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;item-8-finalizer-와-cleaner-사용을-피하라&quot;&gt;Item 8. finalizer 와 cleaner 사용을 피하라&lt;/h3&gt;

&lt;p&gt;자바에서 제공하는 객체소멸자인 finalizer와 cleaner의 사용을 피하는 것이 좋다.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;예측할 수 없고, 여전히 느리고, 상황에 따라 위험할 수 있다.&lt;/li&gt;
  &lt;li&gt;C++ 에서 사용되는 destructor와는 다른 개념이다.
    &lt;ul&gt;
      &lt;li&gt;자바에서는 가비지 컬렉터가 접근할 수 없게 된 객체를 회수&lt;/li&gt;
    &lt;/ul&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;finalizer 공격에 노출되어 심각한 보안 문제를 일으킬 수 있다.&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
  &lt;li&gt;대안
    &lt;blockquote&gt;
      &lt;p&gt;파일이나 스레드등 종료해야할 자원을 담고 있는 객체의 클래스에서 효과적으로 자원을 회수하기 위해서는 finalizer와 cleaner 대신 AutoCloseable을 구현하고, 클라이언트에서 인스턴스를 다 쓰고나면 close 메서드를 호출해야 한다.(close 메서드에서 이 객체가 더이상 유효하지 않다고 기록하여, 닫힌후 호출됬을경우 에러를 발생시켜야 한다)&lt;/p&gt;
    &lt;/blockquote&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;item-9-try-finally-보다는-try-with-resources를-사용하라&quot;&gt;Item 9. try-finally 보다는 try-with-resources를 사용하라&lt;/h3&gt;

&lt;p&gt;자바라이브러리에는 close 메소드를 호출해 직접 닫아야 하는 자원이 많고, 그럴경우 AutoCloseable 인터페이스를 구현해야한다. 
AutoCloseable 인터페이스는 try-with-resources를 사용하는 것이 바람직하다.
try-finally를 사용해서 close 메소드를 호출할 경우 만약 try, finally 모두에서 예외가 발생한다면 try에서의 에러는 감추어지고 finally에서의 에러만 나오기 때문에 추적이 쉽지 않기 때문이다. 
또한 catch 문도 같이 사용할 수 있어 예외처리에도 효과적이며 코드를 간결하게 구성할 수 있다.&lt;/p&gt;</content><author><name>Taeho Kim</name><email>insu7942@naver.com</email></author><category term="Computer-Science" /><summary type="html">Item 1. 생성자 대신 정적 팩터리 메서드를 고려하라 클래스의 인스턴스를 얻는 전통적인 수단인 public 생성자 이외에도 static factory method를 통해 더 효율적으로 클래스를 제공할 수 도 있다.(장단점 존재)</summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://github.com/HwangToeMat/HwangToeMat.github.io/blob/master/Computer-Science/image/effectiveJAVA/img.png?raw=true" /><media:content medium="image" url="https://github.com/HwangToeMat/HwangToeMat.github.io/blob/master/Computer-Science/image/effectiveJAVA/img.png?raw=true" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">[데이터베이스] 01. 데이터베이스 시스템의 기본 개념과 세부 요소를 파악해 보자</title><link href="https://hwangtoemat.github.io/computer-science/2020-12-14-database1/" rel="alternate" type="text/html" title="[데이터베이스] 01. 데이터베이스 시스템의 기본 개념과 세부 요소를 파악해 보자" /><published>2020-12-14T00:00:00+00:00</published><updated>2020-12-14T00:00:00+00:00</updated><id>https://hwangtoemat.github.io/computer-science/database1</id><content type="html" xml:base="https://hwangtoemat.github.io/computer-science/2020-12-14-database1/">&lt;h2 id=&quot;데이터베이스-시스템의-정의와-구성요소&quot;&gt;데이터베이스 시스템의 정의와 구성요소&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;https://github.com/HwangToeMat/HwangToeMat.github.io/blob/master/Computer-Science/image/DB/01/1.png?raw=true&quot; style=&quot;max-width:100%;margin-left: auto; margin-right: auto; display: block;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://blog.naver.com/kiseop91/221543594820&quot;&gt;이미지 출처&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;데이터베이스에 데이터를 저장하고, 이를 관리하여 조직에 필요한 정보를 생성해주는 시스템이다.&lt;/p&gt;

&lt;p&gt;전체적인 구조는 위와같이 사용자, 데이터언어(SQL), 데이터베이스 관리 시스템(DBMS), 데이터베이스로 이루어 진다.&lt;/p&gt;

&lt;h2 id=&quot;데이터베이스&quot;&gt;데이터베이스&lt;/h2&gt;

&lt;h3 id=&quot;정의&quot;&gt;정의&lt;/h3&gt;

&lt;p&gt;특정 조직의 여러 사용자가 공유해서 사용할 수 있도록 통합해서 저장한 운영 데이터의 집합이다.&lt;/p&gt;

&lt;p&gt;즉, 여러 사용자가 함께 소유하고 이용할수 있는 &lt;strong&gt;공용&lt;/strong&gt;데이터이고, 중복성을 최소화한 &lt;strong&gt;통합&lt;/strong&gt;데이터이며, &lt;strong&gt;저장&lt;/strong&gt;하여 보관하고, 지속적으로 유지하눈 &lt;strong&gt;운영&lt;/strong&gt; 데이터이다.&lt;/p&gt;

&lt;h3 id=&quot;구조&quot;&gt;구조&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;스키마 : 데이터베이스에 저장되는 데이터 구조와 제약조건을 정의한 것&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;인스턴스 : 정의된 스키마에 따라 데이터베이스에 실제로 저장된 값&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;3단계 구조&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;https://github.com/HwangToeMat/HwangToeMat.github.io/blob/master/Computer-Science/image/DB/01/2.jpg?raw=true&quot; style=&quot;max-width:100%;margin-left: auto; margin-right: auto; display: block;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://terms.naver.com/entry.nhn?docId=3431096&amp;amp;cid=58430&amp;amp;categoryId=58430&quot;&gt;이미지 출처&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;ul&gt;
    &lt;li&gt;외부 스키마(외부 단계)&lt;/li&gt;
  &lt;/ul&gt;

  &lt;p&gt;개별사용자가 사용자의 필요에의해 생각하여 정의한 데이터베이스를 표현한 논리적 구조이다.&lt;/p&gt;

  &lt;ul&gt;
    &lt;li&gt;개념 스키마(개념 단계)&lt;/li&gt;
  &lt;/ul&gt;

  &lt;p&gt;데이터베이스 관리자의 관점에서 모든 사용자에게 필요한 데이터를 통합하여 전체 데이터베이스를 표현한 논리적 구조이다.&lt;/p&gt;

  &lt;ul&gt;
    &lt;li&gt;내부 스키마(내부 단계)&lt;/li&gt;
  &lt;/ul&gt;

  &lt;p&gt;저장 장치의 관점에서 전체 데이터베이스가 실제로 저장되는 방법을 정의한 구조이다.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;데이터&quot;&gt;데이터&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;정형데이터&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;구조화된 데이터로서 미리 정해진 구조에 따라 저장된 데이터이다. (ex. 엑셀의 스프레드시트)&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;반정형데이터&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;데이터 내용안에 구조에대한 설명이 함께 존재하며 파싱과정이 필요하고 주로 웹에서 데이터를 교환할때나 로그, 센서데이터에 많이 쓰인다. (ex. JSON, XML)&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;비정형데이터&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;정해진 구조가 없는 데이터이다. 최근 SNS의 발달로인해 많이 발생한다. (ex. 영상, 이미지, 멀티미디어 데이터)&lt;/p&gt;

&lt;h2 id=&quot;데이터베이스-관리-시스템dbms&quot;&gt;데이터베이스 관리 시스템(DBMS)&lt;/h2&gt;

&lt;h3 id=&quot;정의-1&quot;&gt;정의&lt;/h3&gt;

&lt;p&gt;파일 시스템의 문제를 해결하기 위해 제시된 소프트웨어로, 필요한 데이터를 데이터베이스에 통합하여 저장하고 이를 관히하는 시스템이다.&lt;/p&gt;

&lt;p&gt;주요기능은 데이터베이스의 구조를 정의하는 &lt;strong&gt;정의 기능&lt;/strong&gt;, 데이터를 삽입,삭제,수정,검색하는 &lt;strong&gt;조작 기능&lt;/strong&gt;, 데이터를 정확하고 안전하게 유지하는 &lt;strong&gt;제어기능&lt;/strong&gt;이 있다.&lt;/p&gt;

&lt;p&gt;데이터의 중복을 최소한으로 유지하고, 독립성을 확보하여 무결성을 유지할 수 있게한다. 또한 접근권한을 제어하여 데이터의 보안을 강화할 수 있다는 장점이 있다.&lt;/p&gt;

&lt;h3 id=&quot;발전과정&quot;&gt;발전과정&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;네트워크 DBMS &amp;gt; &lt;strong&gt;관계 DBMS&lt;/strong&gt; &amp;gt; 객체지향 DBMS &amp;gt; &lt;strong&gt;NoSQL DBMS&lt;/strong&gt; &amp;gt; &lt;strong&gt;NewSQL DBMS&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
  &lt;li&gt;관계 DBMS(RDBMS)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;데이터베이스를 테이블 형태로 구성하는 관계 데이터 모델을 사용하여 테이블과 테이블 간의 연관관계(주로 외래키형태)를 이용해 필요한 정보를 구하는 방식을 사용한다. 또한 정규화를 통해 데이터 중복문제를 개선 할 수 있고, 독립성과 무결성 유지에 도움을 줄 수 있다. (ex. 오라클, MySQL, 엑세스)&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;NoSQL DBMS&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;데이터 구조를 미리 정해두지 않기 때문에 비정형 데이터를 저장하고 처리하는데 적합한 DBMS이다. 안정성과 일관성 유지를 위한 복잡한 기능을 포기하였지만 그로인해 뛰어난 확장성과 유연성을 가지고 있다. (ex. MongoDB, HBase, 레디스)&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;NewSQL DBMS&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;RDBMS의 안정성과 일관성을 유지하면서 NoSQL의 확장성과 유연성을 가지고 있어 다양하고 복잡한 데이터 처리를 편리하게 요청할 수 있다. 따라서 비정형, 정형 데이터를 빠르게 처리할 수 있다. (ex. 구글 스패너, 볼드DB, 누오DB)&lt;/p&gt;

&lt;h3 id=&quot;구성&quot;&gt;구성&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;https://github.com/HwangToeMat/HwangToeMat.github.io/blob/master/Computer-Science/image/DB/01/3.jpg?raw=true&quot; style=&quot;max-width:100%;margin-left: auto; margin-right: auto; display: block;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://m.blog.naver.com/PostView.nhn?blogId=dufvndrnjs&amp;amp;logNo=70136327091&amp;amp;proxyReferer=https:%2F%2Fwww.google.com%2F&quot;&gt;이미지 출처&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&quot;사용자&quot;&gt;사용자&lt;/h2&gt;

&lt;h3 id=&quot;데이터베이스-관리자&quot;&gt;데이터베이스 관리자&lt;/h3&gt;

&lt;p&gt;데이터베이스 시스템을 운영, 관리 하는역할이다. 주로 DDL, DCL을 사용하여 데이터베이스를 유지 보수한다. 또한 데이터 사전과 같은 시스템데이터베이스를 관리하며, 시스템 성능을 저해하는 여러현상(병목현상..)을 감시하고 해결한다.&lt;/p&gt;

&lt;h3 id=&quot;최종-사용자&quot;&gt;최종 사용자&lt;/h3&gt;

&lt;p&gt;데이터를 조작(삽입,삭제,수정,검색)하기 위해 데이터베이스에 접근한다. 주로 DML을 사용하여 필요한 데이터에대한 처리를 하며 직접 SQL을 사용하지 않더라도 GUI로 구현된 응용 프로그램을 사용하기도 한다.&lt;/p&gt;

&lt;h3 id=&quot;응용-프로그래머&quot;&gt;응용 프로그래머&lt;/h3&gt;

&lt;p&gt;프로그래밍 언어를 사용하여 데이터베이스에 접근할 수 있는 응용프로그램을 개발한다. 사용자의 요구에 맞게 데이터를 활용하는 여러 기능을 구현한다.&lt;/p&gt;

&lt;h2 id=&quot;데이터-언어sql&quot;&gt;데이터 언어(SQL)&lt;/h2&gt;

&lt;h3 id=&quot;데이터-정의어ddl&quot;&gt;데이터 정의어(DDL)&lt;/h3&gt;

&lt;p&gt;새로운 데이터베이스를 구축하기 위해 스키마를 정의하거나 기존 스키마의 정의를 삭제 또는 수정하기 위해 사용하는 데이터 언어이다.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;CREATE table : 테이블 생성&lt;/p&gt;

  &lt;p&gt;ALTER table : 수정&lt;/p&gt;

  &lt;p&gt;DROP table : 삭제&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;데이터-조작어dml&quot;&gt;데이터 조작어(DML)&lt;/h3&gt;

&lt;p&gt;사용자가 데이터의 삽입, 삭제, 수정, 검색 등의 처리를 데이터베이스에 요청하기 위한 데이터 언어이다.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;SELECT : 데이터 검색&lt;/p&gt;

  &lt;p&gt;INSERT : 데이터 삽입&lt;/p&gt;

  &lt;p&gt;UPDATE : 데이터 수정&lt;/p&gt;

  &lt;p&gt;DELETE : 데이터 삭제&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;데이터-제어어dcl&quot;&gt;데이터 제어어(DCL)&lt;/h3&gt;

&lt;p&gt;데이터베이스에 저장된 데이터를 여러 사용자가 무결성과 일관성을 유지하며 공유할 수 있도록 내부적으로 필요한 규칙이나 기법을 정의하는데 사용되는 데이터 언어이다.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;GRANT : 권한 부여&lt;/p&gt;

  &lt;p&gt;REVOKE : 권한 회수&lt;/p&gt;

  &lt;p&gt;COMMIT : 작업 저장&lt;/p&gt;

  &lt;p&gt;ROLLBACK : 이전 과정으로 복구&lt;/p&gt;
&lt;/blockquote&gt;</content><author><name>Taeho Kim</name><email>insu7942@naver.com</email></author><category term="Computer-Science" /><summary type="html">데이터베이스 시스템의 정의와 구성요소</summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://github.com/HwangToeMat/HwangToeMat.github.io/blob/master/Computer-Science/image/DB/0.jpg?raw=true" /><media:content medium="image" url="https://github.com/HwangToeMat/HwangToeMat.github.io/blob/master/Computer-Science/image/DB/0.jpg?raw=true" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">[웹개발] 06. WebServer와 WAS의 개념과 역할</title><link href="https://hwangtoemat.github.io/computer-science/2020-12-13-webserverWAS/" rel="alternate" type="text/html" title="[웹개발] 06. WebServer와 WAS의 개념과 역할" /><published>2020-12-13T00:00:00+00:00</published><updated>2020-12-13T00:00:00+00:00</updated><id>https://hwangtoemat.github.io/computer-science/webserverWAS</id><content type="html" xml:base="https://hwangtoemat.github.io/computer-science/2020-12-13-webserverWAS/">&lt;h2 id=&quot;개발한-웹을-배포할때-주로-사용하는-구조&quot;&gt;개발한 웹을 배포할때 주로 사용하는 구조&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;https://github.com/HwangToeMat/HwangToeMat.github.io/blob/master/Computer-Science/image/WEB/WAS/1.png?raw=true&quot; style=&quot;max-width:100%;margin-left: auto; margin-right: auto; display: block;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://hackernoon.com/a-guide-to-scaling-machine-learning-models-in-production-aa8831163846&quot;&gt;이미지 출처&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;최근에 Flask를 자주 사용하는데 개발한 웹을 배포할때 간단한 구조는 위와같다. 그림에서 nginx는 WebServer의 역할을 하고, uWSGI는 WAS의 역할을 한다.
이 두가지 역할을 통해 Client의 요청에 맞게 Flask로 구현된 서비스를 연결하여 DB에서 필요한 정보를 가공하여 제공할 수 있는 것이다.&lt;/p&gt;

&lt;p&gt;여기서 WebServer와 WAS가 각각 어떤역할을 하고 왜 존재하는지 알아보도록 하겠다.&lt;/p&gt;

&lt;h2 id=&quot;webserver의-개념-및-역할&quot;&gt;WebServer의 개념 및 역할?&lt;/h2&gt;

&lt;p&gt;웹서버는 클라이언트로부터 HTTP 요청을 받아 필요한 데이터를 제공하는 역할을 한다.
이때 웹서버는 주로 정적인 컨텐츠를 제공하고 동적인 컨텐츠에 대한 요청을 WAS로 전달하여 처리된 결과를 클라이언트에게 반환한다.&lt;/p&gt;

&lt;p&gt;웹서버는 주로 nginx와 aparch, iis가 많이 쓰이는데, 최근에는 쓰레드개념인 다른 웹서버에비해 Event-Driven구조를 사용하는 nginx를 많이 사용한다.&lt;/p&gt;

&lt;h2 id=&quot;was의-개념-및-역할&quot;&gt;WAS의 개념 및 역할?&lt;/h2&gt;

&lt;p&gt;WAS는 전달받은 동적컨텐츠에대한 요청을 처리하여 제공하는 역할을 하는 미들웨어이다.
이때 앞에서 요청받은 HTTP 요청을 앱에 맞게 변환하여 전달하고 처리된 값을 웹서버에 맞게 변환하여 전달해주는 역할을 한다.&lt;/p&gt;

&lt;p&gt;WAS는 주로 Tomcat, uWsgi, gUnicorn 등이 있다.&lt;/p&gt;</content><author><name>Taeho Kim</name><email>insu7942@naver.com</email></author><category term="Computer-Science" /><summary type="html">개발한 웹을 배포할때 주로 사용하는 구조</summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://github.com/HwangToeMat/HwangToeMat.github.io/blob/master/Computer-Science/image/WEB/WAS/0.png?raw=true" /><media:content medium="image" url="https://github.com/HwangToeMat/HwangToeMat.github.io/blob/master/Computer-Science/image/WEB/WAS/0.png?raw=true" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">[웹개발] 05. HTTP와 WebSocket는 무엇이고 언제쓰일까?</title><link href="https://hwangtoemat.github.io/computer-science/2020-12-11-httpwebsocket/" rel="alternate" type="text/html" title="[웹개발] 05. HTTP와 WebSocket는 무엇이고 언제쓰일까?" /><published>2020-12-11T00:00:00+00:00</published><updated>2020-12-11T00:00:00+00:00</updated><id>https://hwangtoemat.github.io/computer-science/httpwebsocket</id><content type="html" xml:base="https://hwangtoemat.github.io/computer-science/2020-12-11-httpwebsocket/">&lt;h2 id=&quot;http-란&quot;&gt;HTTP 란?&lt;/h2&gt;

&lt;p&gt;인터넷에서 웹서버와 사용자의 인터넷 브라우저 사이에 문서를 전송하기 위해 사용되는 통신 규약을 말한다.&lt;/p&gt;

&lt;p&gt;HTTP의 중요한 특징인 &lt;strong&gt;Client의 요청이 있을때만&lt;/strong&gt; 서버가 응답하여 해당 정보를 제공하면 &lt;strong&gt;연결을 종료&lt;/strong&gt;한다는 것이다.
다시 말해 Client가 요청을 보내는 경우에만 서버가 응답하는 단방향적 통신이다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://github.com/HwangToeMat/HwangToeMat.github.io/blob/master/Computer-Science/image/WEB/HTTP/1.jpeg?raw=true&quot; style=&quot;max-width:100%;margin-left: auto; margin-right: auto; display: block;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://hieroglyph.tistory.com/13&quot;&gt;이미지 출처&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&quot;websocket-이란&quot;&gt;WebSocket 이란?&lt;/h2&gt;

&lt;p&gt;브라우저와 웹서버 사이의 통신을 위한 양방향 통신 규격을 말한다.&lt;/p&gt;

&lt;p&gt;서버와 Client가 특정 포트를 통해 연결을 성립하고 있어 실시간으로 &lt;strong&gt;양방향 통신&lt;/strong&gt;을 하는 방식이다. 서버와 Client 모두 서로에게 요청을 보낼 수 있으며 지속적으로 연결을 유지하는 연결지향형 통신이다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://github.com/HwangToeMat/HwangToeMat.github.io/blob/master/Computer-Science/image/WEB/HTTP/2.png?raw=true&quot; style=&quot;max-width:100%;margin-left: auto; margin-right: auto; display: block;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://mangkyu.tistory.com/48&quot;&gt;이미지 출처&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&quot;http와-websocket의-특징과-쓰이는-곳&quot;&gt;HTTP와 WebSocket의 특징과 쓰이는 곳&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;HTTP&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;요청이 있을때만 연결이되고 요청을 해결하면 연결이 끊어지는 방식이기 때문에 정적페이지 요청에 사용하면 좋다.
만약, 모든 페이지 요청에 웹소켓을 사용할 경우 이미 데이터를 받은 후에도 계속해서 연결을 유지해야 하기 때문에 부하가 걸리게 된다.
따라서 이럴 경우에는 HTTP가 더 적절하다.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;WebSocket&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;양방향으로 연결을 유지하는 방식이기 때문에 동적페이지 요청에 사용하면 좋다.
또한 실시간으로 데이터를 주고 받는 주식, 동영상 스트리밍과 같은 상황에서 사용하면 좋다.&lt;/p&gt;</content><author><name>Taeho Kim</name><email>insu7942@naver.com</email></author><category term="Computer-Science" /><summary type="html">HTTP 란?</summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://github.com/HwangToeMat/HwangToeMat.github.io/blob/master/Computer-Science/image/WEB/HTTP/0.png?raw=true" /><media:content medium="image" url="https://github.com/HwangToeMat/HwangToeMat.github.io/blob/master/Computer-Science/image/WEB/HTTP/0.png?raw=true" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">[웹개발] 04. Flask 다시 배우기 - model, sqlalchemy</title><link href="https://hwangtoemat.github.io/computer-science/2020-12-09-flask4/" rel="alternate" type="text/html" title="[웹개발] 04. Flask 다시 배우기 - model, sqlalchemy" /><published>2020-12-09T00:00:00+00:00</published><updated>2020-12-09T00:00:00+00:00</updated><id>https://hwangtoemat.github.io/computer-science/flask4</id><content type="html" xml:base="https://hwangtoemat.github.io/computer-science/2020-12-09-flask4/">&lt;h2 id=&quot;flask에서-db-다루기&quot;&gt;Flask에서 DB 다루기&lt;/h2&gt;

&lt;h3 id=&quot;1-model-설계하기-및-연관관계-설정하기&quot;&gt;1. model 설계하기 및 연관관계 설정하기&lt;/h3&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;flask_sqlalchemy&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SQLAlchemy&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;db&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SQLAlchemy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;db&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;__tablename__&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'user'&lt;/span&gt;

    &lt;span class=&quot;nb&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;db&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Column&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;db&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Integer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;primary_key&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;userid&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;db&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Column&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;db&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;12&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
        
&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Model_detail&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;db&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;__tablename__&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'model_detail'&lt;/span&gt;

    &lt;span class=&quot;nb&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;db&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Column&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;db&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Integer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;primary_key&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;user_id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;db&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Column&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;db&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Integer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;db&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ForeignKey&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'user.id'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nullable&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# User 테이블에서 id값을 외래키로 사용
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;model_name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;db&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Column&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;db&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;12&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;user&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;db&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;relationship&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'User'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;backref&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'model_detail'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lazy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; 
    &lt;span class=&quot;c1&quot;&gt;# backref 를 사용하여 User에서 역참조를 허용(ex.user_1.model_detail)
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;2-데이터베이스-생성하기&quot;&gt;2. 데이터베이스 생성하기&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;config.py에 설정 추가&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;SQLALCHEMY_DATABASE_URI&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'sqlite:///XXXX'&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;SQLALCHEMY_COMMIT_ON_TEARDOWN&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;SQLALCHEMY_TRACK_MODIFICATIONS&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;False&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;ORM 적용하기&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# __init__.py
&lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;flask_sqlalchemy&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SQLAlchemy&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;flask_migrate&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Migrate&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;db&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SQLAlchemy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;migrate&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Migrate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;create_app&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;.....&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;db&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;init_app&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;migrate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;init_app&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;db&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;.....&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;app&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;db 초기화 및 모델 변경값 적용하기&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;
&lt;span class=&quot;c1&quot;&gt;# 데이터베이스 초기화
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;flask&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;db&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;init&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# 리비전파일 생성하기
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;flask&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;db&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;migrate&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# 데이터베이스 갱신
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;flask&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;db&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;upgrade&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;3-데이터-다루기&quot;&gt;3. 데이터 다루기&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;데이터 저장하기&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;db_1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;userid&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'hwangtoemat'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;db&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;session&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;db_1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;db&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;session&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;commit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;db_1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;데이터에 변경사항이 있을 경우 위와같은 과정을 거쳐야 변경사항의 저장이 완료된다.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;데이터 조회하기&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;query&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;all&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# 아래와 같이 모든 객체를 리스트에 담아서 리턴
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;User&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;User&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;query&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;first&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# 쿼리의 첫번째 값을 리턴
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;query&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# id가 1인 값을 조회(id 가 유일한 값이기 때문에 가능)
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;query&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;userid&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'hwangtoemat'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;all&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# 조건에 맞는 모든 값 조회
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;query&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;userid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;like&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'%toe%'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)).&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;all&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# 'toe'가 들어가는 아이디를 가진 모든 값 조회
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;데이터 삭제하기&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;db_2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;query&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;userid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;like&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'%toe%'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;first&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;db&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;session&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;delete&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;db_2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# 조건에 맞는 값 삭제
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;db&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;session&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;commit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;db_2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# 데이터에 반영
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;연관관계에 맞게 데이터 생성하기&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;temp&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;query&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;db_3&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Model_detail&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;temp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;model_name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'SVM_2'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# user_id는 temp에 의해 자동 입력
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;db&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;session&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;db_3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;db&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;session&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;commit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;db_3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;</content><author><name>Taeho Kim</name><email>insu7942@naver.com</email></author><category term="Computer-Science" /><summary type="html">Flask에서 DB 다루기</summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://github.com/HwangToeMat/HwangToeMat.github.io/blob/master/Computer-Science/image/WEB/FLASK/flask.png?raw=true" /><media:content medium="image" url="https://github.com/HwangToeMat/HwangToeMat.github.io/blob/master/Computer-Science/image/WEB/FLASK/flask.png?raw=true" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">[웹개발] 03. Flask 다시 배우기 - 기초</title><link href="https://hwangtoemat.github.io/computer-science/2020-12-08-flask3/" rel="alternate" type="text/html" title="[웹개발] 03. Flask 다시 배우기 - 기초" /><published>2020-12-08T00:00:00+00:00</published><updated>2020-12-08T00:00:00+00:00</updated><id>https://hwangtoemat.github.io/computer-science/flask3</id><content type="html" xml:base="https://hwangtoemat.github.io/computer-science/2020-12-08-flask3/">&lt;h2 id=&quot;더-효과적으로-코딩하는-방법&quot;&gt;더 효과적으로 코딩하는 방법&lt;/h2&gt;

&lt;h3 id=&quot;1-순환참조-오류를-예방하는-방법&quot;&gt;1. 순환참조 오류를 예방하는 방법&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;기존에 사용하던 방법&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# app.py 파일에서 직접 아래와 같이 사용
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;app&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Flask&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;__name__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;위와 같이 Flask 객체를 전역으로 사용하면 프로젝트 규모가 커질수록 순환참조 오류가 발생할 확률이 높아진다.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;해결 방법 (어플리케이션 팩토리를 사용)&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# __init__.py 에서 create_app 메서드를 사용
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;create_app&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;app&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Flask&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;__name__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;.....&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;app&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;위와 같은 구조(애플리케이션 팩토리)를 사용하면 순환참조 문제를 해결할 수 있다.(이는 Flask 공식홈페이지에도 나와있는 내용이다.)&lt;/p&gt;

&lt;h3 id=&quot;2-블루프린트-사용하기&quot;&gt;2. 블루프린트 사용하기&lt;/h3&gt;

&lt;p&gt;블루프린트를 사용하면 기능이나 용도별로 view나 package를 만들어 훨씬 구조적이고 효율적이게 설계할 수 있다.
또한, 기능별로 다른 파일에 분리할 수 있기때문에 유지, 보수가 간편하다.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# package_1/__init__.py
&lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;flask&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Blueprint&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;bp&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Blueprint&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'package_1'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__name__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# __init__.py
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;create_app&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;app&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Flask&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;__name__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;package_1&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bp&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;register_blueprint&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;url_prefix&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'/package_1'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; 
  &lt;span class=&quot;c1&quot;&gt;# url_prefix에 의해 package_1에서 정의한 페이지는 {서브도메인:포트}/package_1/ 이후에 나오게 된다.  
&lt;/span&gt;  &lt;span class=&quot;p&quot;&gt;.....&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;app&lt;/span&gt;
  
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;3-configpy-활용하여-설정하기&quot;&gt;3. config.py 활용하여 설정하기&lt;/h3&gt;

&lt;p&gt;루트 디렉토리에 config.py를 추가하여 기타 설정을 분리하여 관리할 수 있다.&lt;/p&gt;

&lt;p&gt;프로젝트의 규모가 작거나 설정할 요소들이 많지 않을때는
아래와같이 하나씩 직접 설정할 수 있다.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# __init__.py 
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;create_app&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;app&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Flask&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;__name__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'SQLALCHEMY_DATABASE_URI'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'sqlite:///XXXX'&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'SQLALCHEMY_COMMIT_ON_TEARDOWN'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'SQLALCHEMY_TRACK_MODIFICATIONS'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;False&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'SECRET_KEY'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'dkssudgktpdy'&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'JSON_AS_ASCII'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;False&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;.....&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;app&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;하지만 설정값이 많아질 경우 관리하기 쉽지않고, 크고작은 에러를 발생할 위험이 있다. 따라서 이를 분리하여 config.py 를 만들어 설정값을 한번에 관리할 수 있다.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# config.py
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;SQLALCHEMY_DATABASE_URI&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'sqlite:///XXXX'&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;SQLALCHEMY_COMMIT_ON_TEARDOWN&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;SQLALCHEMY_TRACK_MODIFICATIONS&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;False&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;SECRET_KEY&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'dkssudgktpdy'&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;JSON_AS_ASCII&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;False&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# __init__.py
&lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;config&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;create_app&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;app&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Flask&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;__name__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;from_object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;.....&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;app&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;</content><author><name>Taeho Kim</name><email>insu7942@naver.com</email></author><category term="Computer-Science" /><summary type="html">더 효과적으로 코딩하는 방법</summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://github.com/HwangToeMat/HwangToeMat.github.io/blob/master/Computer-Science/image/WEB/FLASK/flask.png?raw=true" /><media:content medium="image" url="https://github.com/HwangToeMat/HwangToeMat.github.io/blob/master/Computer-Science/image/WEB/FLASK/flask.png?raw=true" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">[Python] 02. 파이썬에서 가비지컬렉션(GC)을 수행하는 방법에대해 알아본다.</title><link href="https://hwangtoemat.github.io/computer-science/2020-11-24-pythongc/" rel="alternate" type="text/html" title="[Python] 02. 파이썬에서 가비지컬렉션(GC)을 수행하는 방법에대해 알아본다." /><published>2020-11-24T00:00:00+00:00</published><updated>2020-11-24T00:00:00+00:00</updated><id>https://hwangtoemat.github.io/computer-science/pythongc</id><content type="html" xml:base="https://hwangtoemat.github.io/computer-science/2020-11-24-pythongc/">&lt;h2 id=&quot;python에서-garbage-collection을-하는-방법&quot;&gt;Python에서 Garbage Collection을 하는 방법?&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;Reference Counting&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;모든 객체는 참조될때마다 카운팅을 하고 참조를 해제하면 카운팅된 숫자를 줄인다. 이런식으로 카운팅하다가 0이될때 메모리에서 삭제하는 방법을 reference counting 이라고 한다.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Reference Counting의 단점&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;객체가 참조될때 일반적인 경우와 다르게 &lt;strong&gt;순환 참조&lt;/strong&gt;가 일어나는 경우가 있다. 자기 자신을 참조하거나 서로 참조하는 경우 참조를 해제해도 카운팅된 숫자가 0이될 수 없다.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;예를 들어,&lt;/p&gt;

  &lt;p&gt;A 인스턴스 참조   +1&lt;/p&gt;

  &lt;p&gt;자기 자신 참조    +1&lt;/p&gt;

  &lt;p&gt;참조 해제    -1&lt;/p&gt;

  &lt;p&gt;이 경우 reference counting은 1이다.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
  &lt;li&gt;Generational Garbage Collection&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;세대와 각 세대의 임계값을 기준으로 Garbage Collection이 이루어진다. 세대는 0~2로 이루어 졌다.
 새로 참조된 객체는 0세대로 배정된다.&lt;/p&gt;

&lt;p&gt;이때 객체가 카운팅된 값(참조된 횟수 - 해제된 횟수)이 세대에 지정된 임계값보다 커질경우 가비지 컬렉션이 이루어지게된다.&lt;/p&gt;

&lt;p&gt;가비지 컬렉션은 오래된 세대부터 이루어 지게되는데 각 세대마다 정해진 임계값을 기준으로 이루어진다.
 그 후 객체들은 다음 세대로 넘어가게된다.&lt;/p&gt;</content><author><name>Taeho Kim</name><email>insu7942@naver.com</email></author><category term="Computer-Science" /><summary type="html">Python에서 Garbage Collection을 하는 방법?</summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://github.com/HwangToeMat/HwangToeMat.github.io/blob/master/Computer-Science/image/etc/python/2/0.jpeg?raw=true" /><media:content medium="image" url="https://github.com/HwangToeMat/HwangToeMat.github.io/blob/master/Computer-Science/image/etc/python/2/0.jpeg?raw=true" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">[자료구조] 08. Trie(트라이)를 사용하여 검색 자동완성 기능을 구현해 본다.</title><link href="https://hwangtoemat.github.io/computer-science/2020-11-17-trie/" rel="alternate" type="text/html" title="[자료구조] 08. Trie(트라이)를 사용하여 검색 자동완성 기능을 구현해 본다." /><published>2020-11-17T00:00:00+00:00</published><updated>2020-11-17T00:00:00+00:00</updated><id>https://hwangtoemat.github.io/computer-science/trie</id><content type="html" xml:base="https://hwangtoemat.github.io/computer-science/2020-11-17-trie/">&lt;p&gt;&lt;img src=&quot;https://github.com/HwangToeMat/HwangToeMat.github.io/blob/master/Computer-Science/image/08.trie/img1.png?raw=true&quot; style=&quot;max-width:100%;margin-left: auto; margin-right: auto; display: block;&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;trie-란&quot;&gt;Trie 란?&lt;/h2&gt;

&lt;p&gt;그림과 같이 트리구조를 가지며 문자열을 효율적으로 검색하고 저장하기위해 단어의 글자를 노드로 이어져있으며 단어의 끝에는 끝을 확인 할 수 있는 확인자가 있는 구조이다.&lt;/p&gt;

&lt;h2 id=&quot;자동완성에서-trie를-쓰는-이유&quot;&gt;자동완성에서 Trie를 쓰는 이유?&lt;/h2&gt;

&lt;p&gt;String 구조를 트리에 담아 검색한다고 가정해보자&lt;/p&gt;

&lt;p&gt;트리의 대표적인 구조인 이진탐색트리와 비교해보면
String의 길이를 M이라고 했을때, 시간복잡도는 O(M*log(N)) 이고&lt;/p&gt;

&lt;p&gt;Trie의 경우 시간복잡도는 O(M)이 된다.
즉, 시간복잡도면에서 우월한 성능을 보이기 때문에 자동완성에서 Trie를 사용한다고 볼 수 있다.&lt;/p&gt;

&lt;h2 id=&quot;구현-코드&quot;&gt;구현 코드&lt;/h2&gt;

&lt;h3 id=&quot;1-메인-코드&quot;&gt;1. 메인 코드&lt;/h3&gt;
&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# 노드 설정
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Node&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;__init__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fin&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;False&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# 단어가 끝났을 경우 해당 단어를 집어넣는다.
&lt;/span&gt;        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;next&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;dict&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# 트라이 설정
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Trie&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;__init__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;head&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Node&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
     
    &lt;span class=&quot;c1&quot;&gt;# 단어 삽입
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;insert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;curr_node&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;head&lt;/span&gt;
        
        &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;word&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;word&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;curr_node&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;curr_node&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;word&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Node&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;word&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;curr_node&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;curr_node&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;word&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
        
        &lt;span class=&quot;n&quot;&gt;curr_node&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fin&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;string&lt;/span&gt;
    
    &lt;span class=&quot;c1&quot;&gt;# 자동완성 
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;auto_complete&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;curr_node&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;head&lt;/span&gt;
        
        &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;
        
        &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;word&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;word&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;curr_node&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;추천 검색어가 없습니다.&quot;&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;curr_node&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;curr_node&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;word&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
        
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;curr_node&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;curr_node&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            
        &lt;span class=&quot;n&quot;&gt;stack&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;curr_node&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;values&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
        
        &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stack&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stack&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
            
            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;stack&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;extend&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;values&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()))&lt;/span&gt;
            
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    
    &lt;span class=&quot;c1&quot;&gt;# 검색기록 출력
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;show_list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;curr_node&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;head&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;stack&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;curr_node&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;values&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;
        
        &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stack&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stack&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
            
            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;stack&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;extend&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;values&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()))&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h3 id=&quot;2-결과&quot;&gt;2. 결과&lt;/h3&gt;
&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# 초기화
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Trie&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# 단어 삽입
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;insert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'string'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;insert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'str'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;insert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'stress'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;insert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'star'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;insert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'singer'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;insert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'sign'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;insert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'starcraft'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;insert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'southkorea'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;insert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'south korea'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# 자동완성 기능
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;auto_complete&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'soo'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;auto_complete&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'st'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;auto_complete&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'star'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;auto_complete&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'south'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# 검색기록 출력
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;show_list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# Result

# 자동완성
'추천 검색어가 없습니다.'
['star', 'starcraft', 'str', 'stress', 'string']
['star', 'starcraft']
['south korea', 'southkorea']

# 검색기록
['south korea', 'southkorea', 'sign', 'singer', 'star', 'starcraft', 'str', 'stress', 'string']
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;</content><author><name>Taeho Kim</name><email>insu7942@naver.com</email></author><category term="Computer-Science" /><summary type="html"></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://github.com/HwangToeMat/HwangToeMat.github.io/blob/master/Computer-Science/image/08.trie/img0.png?raw=true" /><media:content medium="image" url="https://github.com/HwangToeMat/HwangToeMat.github.io/blob/master/Computer-Science/image/08.trie/img0.png?raw=true" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">[Python] 01. Python에서 GIL이 존재하는 이유</title><link href="https://hwangtoemat.github.io/computer-science/2020-11-15-gil/" rel="alternate" type="text/html" title="[Python] 01. Python에서 GIL이 존재하는 이유" /><published>2020-11-15T00:00:00+00:00</published><updated>2020-11-15T00:00:00+00:00</updated><id>https://hwangtoemat.github.io/computer-science/gil</id><content type="html" xml:base="https://hwangtoemat.github.io/computer-science/2020-11-15-gil/">&lt;p&gt;GIL은 &lt;strong&gt;Global Interpreter Lock&lt;/strong&gt;의 줄임말이다.&lt;/p&gt;

&lt;p&gt;간단히 요약하면 &lt;strong&gt;Python 인터프리터에 하나의 스레드에서만 접근이 가능하도록 제한을 걸어둔 것을 의미한다.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;이러한 제한이 걸린 이유를 이해하기 위해서는 Python의 Garbage Collection 이 작동하는 원리에 대해 먼저 알아야 한다.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Python의 Garbage Collection&lt;/strong&gt;&lt;/p&gt;

    &lt;p&gt;Python에서는 각 객체가 참조될때 Reference Counts가 이루어진다. 즉, 객체가 참조될때 카운팅이 되고 삭제되면 카운팅된 값이 줄어들게 된다. 이때 카운팅된 값이 0이되면 메모리에서 할당된 부분이 삭제되게 되는 방법이다.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;멀티쓰레드를 사용하면 발생할 수 있는 문제점&lt;/strong&gt;&lt;/p&gt;

    &lt;p&gt;멀티쓰레드를 사용하고 있는 상태라면 하나의 객체를 여러개의 쓰레드에서 동시에 접근하는 경우가 생길 수 있다. 즉, race condition이 발생할 수 있는것이다.&lt;/p&gt;

    &lt;p&gt;이를 해결하기위해 객체에 lock을 걸어주어야 하는데, 만약 모든 객체에 lock을 걸어준다면 프로그램 전체적인 실행속도가 상당히 느려지고, 경우에 따라 deadlock이 걸릴 수 있다.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;해결방법&lt;/strong&gt;&lt;/p&gt;

    &lt;p&gt;따라서 이러한 상황에서 발생될 수 있는 문제를 해결하기위해 Python에서는 가장 간단하고 확실한 방법을 적용하였다.&lt;/p&gt;

    &lt;p&gt;Python 인터프리터에 하나의 스레드에서만 접근이 가능하도록 제한을 걸어 문제가 될만한 상황을 차단해 버린 것이다.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;즉, 이러한 문제가 발생되는 것을 막기위해 파이썬은 GIL이라는 개념을 도입하게 된 것이다.&lt;/p&gt;</content><author><name>Taeho Kim</name><email>insu7942@naver.com</email></author><category term="Computer-Science" /><summary type="html">GIL은 Global Interpreter Lock의 줄임말이다.</summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://github.com/HwangToeMat/HwangToeMat.github.io/blob/master/Computer-Science/image/etc/python/img0.png?raw=true" /><media:content medium="image" url="https://github.com/HwangToeMat/HwangToeMat.github.io/blob/master/Computer-Science/image/etc/python/img0.png?raw=true" xmlns:media="http://search.yahoo.com/mrss/" /></entry></feed>